Logo Search packages:      
Sourcecode: edfbrowser version File versions  Download package

bdf2edf.cpp

/*
***************************************************************************
*
* Author: Teunis van Beelen
*
* Copyright (C) 2009 Teunis van Beelen
*
* teuniz@gmail.com
*
***************************************************************************
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
***************************************************************************
*
* This version of GPL is at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
*
***************************************************************************
*/



#include "bdf2edf.h"






UI_BDF2EDFwindow::UI_BDF2EDFwindow(const char *recent_dir)
{
  myobjectDialog = new QDialog;

  myobjectDialog->setMinimumSize(QSize(600, 526));
  myobjectDialog->setMaximumSize(QSize(600, 526));
  myobjectDialog->setWindowTitle("BDF+ to EDF+ converter");
  myobjectDialog->setModal(TRUE);
  myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, TRUE);

  label1 = new QLabel(myobjectDialog);
  label1->setGeometry(20, 20, 560, 26);

  label2 = new QLabel(myobjectDialog);
  label2->setGeometry(440, 196, 100, 26);
  label2->setText("High-pass filter");

  label3 = new QLabel(myobjectDialog);
  label3->setGeometry(440, 300, 100, 26);
  label3->setText("Divider");

  SignalsTablewidget = new QTableWidget(myobjectDialog);
  SignalsTablewidget->setGeometry(20, 66, 400, 380);
  SignalsTablewidget->setSelectionMode(QAbstractItemView::NoSelection);
  SignalsTablewidget->setColumnCount(3);
  SignalsTablewidget->setColumnWidth(0, 140);
  SignalsTablewidget->setColumnWidth(1, 100);
  SignalsTablewidget->setColumnWidth(2, 100);

  QStringList horizontallabels;
  horizontallabels += "Label";
  horizontallabels += "HighPassFilter";
  horizontallabels += "Divider";
  SignalsTablewidget->setHorizontalHeaderLabels(horizontallabels);

  spinBox1 = new QDoubleSpinBox(myobjectDialog);
  spinBox1->setGeometry(440, 232, 100, 26);
  spinBox1->setDecimals(3);
  spinBox1->setSuffix(" Hz");
  spinBox1->setRange(0.001, 100.0);
  spinBox1->setValue(0.1);

  spinBox2 = new QDoubleSpinBox(myobjectDialog);
  spinBox2->setGeometry(440, 336, 100, 26);
  spinBox2->setDecimals(3);
  spinBox2->setRange(1.0, 256.0);
  spinBox2->setValue(1.0);

  pushButton1 = new QPushButton(myobjectDialog);
  pushButton1->setGeometry(QRect(20, 476, 100, 26));
  pushButton1->setText("Select File");

  pushButton2 = new QPushButton(myobjectDialog);
  pushButton2->setGeometry(QRect(480, 476, 100, 26));
  pushButton2->setText("Close");

  pushButton3 = new QPushButton(myobjectDialog);
  pushButton3->setGeometry(QRect(200, 476, 100, 26));
  pushButton3->setText("Convert");
  pushButton3->setEnabled(FALSE);

  pushButton4 = new QPushButton(myobjectDialog);
  pushButton4->setGeometry(QRect(440, 66, 140, 26));
  pushButton4->setText("Select all signals");

  pushButton5 = new QPushButton(myobjectDialog);
  pushButton5->setGeometry(QRect(440, 118, 140, 26));
  pushButton5->setText("Deselect all signals");

  fchooser = new QFileDialog(myobjectDialog);
  fchooser->setConfirmOverwrite(1);
  fchooser->setFileMode(QFileDialog::ExistingFile);
  fchooser->setAcceptMode(QFileDialog::AcceptOpen);
  fchooser->setWindowTitle("Select inputfile");
  fchooser->setLabelText(QFileDialog::FileName, "input file");
#ifdef Q_WS_X11
  fchooser->setDirectory(getenv("HOME"));
#endif
#ifdef Q_WS_MAC
  fchooser->setDirectory(getenv("HOME"));
#endif
  fchooser->setFilter("BDF files (*.bdf *.BDF)");

  if(recent_dir!=NULL)
  {
    if(recent_dir[0]!=0)
    {
      fchooser->setDirectory(recent_dir);
    }
  }

  QObject::connect(pushButton1, SIGNAL(clicked()),            this,           SLOT(SelectFileButton()));
  QObject::connect(pushButton2, SIGNAL(clicked()),            myobjectDialog, SLOT(close()));
  QObject::connect(pushButton3, SIGNAL(clicked()),            this,           SLOT(StartConversion()));
  QObject::connect(pushButton4, SIGNAL(clicked()),            this,           SLOT(Select_all_signals()));
  QObject::connect(pushButton5, SIGNAL(clicked()),            this,           SLOT(Deselect_all_signals()));
  QObject::connect(spinBox1,    SIGNAL(valueChanged(double)), this,           SLOT(spinbox1_changed(double)));
  QObject::connect(spinBox2,    SIGNAL(valueChanged(double)), this,           SLOT(spinbox2_changed(double)));

  inputfile = NULL;
  outputfile = NULL;

  path[0] = 0;

  edfhdr = NULL;

  myobjectDialog->exec();
}



void UI_BDF2EDFwindow::Select_all_signals()
{
  int i;

  for(i=0; i<edfhdr->edfsignals; i++)
  {
    if(!edfhdr->edfparam[i].annotation)
    {
      ((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->setCheckState(Qt::Checked);
    }
  }
}



void UI_BDF2EDFwindow::Deselect_all_signals()
{
  int i;

  for(i=0; i<edfhdr->edfsignals; i++)
  {
    if(!edfhdr->edfparam[i].annotation)
    {
      ((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->setCheckState(Qt::Unchecked);
    }
  }
}



void UI_BDF2EDFwindow::spinbox1_changed(double value)
{
  int i;

  if(edfhdr==NULL)
  {
    return;
  }

  for(i=0; i<edfhdr->edfsignals; i++)
  {
    if(!edfhdr->edfparam[i].annotation)
    {
      ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 1)))->setValue(value);
    }
  }
}



void UI_BDF2EDFwindow::spinbox2_changed(double value)
{
  int i;

  if(edfhdr==NULL)
  {
    return;
  }

  for(i=0; i<edfhdr->edfsignals; i++)
  {
    if(!edfhdr->edfparam[i].annotation)
    {
      ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 2)))->setValue(value);
    }
  }
}



void UI_BDF2EDFwindow::SelectFileButton()
{
  const char *fileName;

  int i;

  char txt_string[2048];

  QStringList  input_fileNames;

  QString input_fileName;

  if(edfhdr!=NULL)
  {
    label1->setText("");

    SignalsTablewidget->setRowCount(0);

    free(edfhdr);

    inputfile = NULL;
    outputfile = NULL;

    path[0] = 0;

    edfhdr = NULL;

    pushButton3->setEnabled(FALSE);
  }

  if(!(fchooser->exec() == QDialog::Accepted))
  {
    return;
  }
  input_fileNames = fchooser->selectedFiles();
  input_fileName = input_fileNames.at(0);
  strcpy(path, input_fileName.toLatin1().data());

  pathlen = strlen(path);

  if(pathlen<5)
  {
    UI_Messagewindow popuperror("Error", "Filename must contain at least five characters.");
    return;
  }

  fname_len = 0;
  for(i=pathlen; i>0; i--)
  {
       if((path[i-1]=='/')||(path[i-1]=='\\'))  break;
       fname_len++;
  }
  fileName = path + pathlen - fname_len;

  for(i=0; fileName[i]!=0; i++) ;
  if(i==0)
  {
    UI_Messagewindow popuperror("Error", "Filename must contain at least five characters.");
    return;
  }

  i -= 4;
  if(strcmp((const char *)fileName + i, ".bdf")&&strcmp((const char *)fileName + i, ".BDF"))
  {
    UI_Messagewindow popuperror("Error", "Filename extension must have the form \".bdf\" or \".BDF\"");
    return;
  }

  inputfile = fopen64(path, "rb");
  if(inputfile==NULL)
  {
    snprintf(txt_string, 2048, "Can not open file %s for reading.", path);
    UI_Messagewindow popuperror("Error", txt_string);
    return;
  }

/***************** check if the file is valid ******************************/

  EDFfileCheck EDFfilechecker;

  edfhdr = EDFfilechecker.check_edf_file(inputfile, txt_string);
  if(edfhdr==NULL)
  {
    fclose(inputfile);
    UI_Messagewindow popuperror("Error", txt_string);
    return;
  }

  if(!edfhdr->bdf)
  {
    fclose(inputfile);
    UI_Messagewindow popuperror("Error", "File is not a BDF file.");
    free(edfhdr);
    return;
  }

/***************** load signalproperties ******************************/

  label1->setText(path);

  SignalsTablewidget->setRowCount(edfhdr->edfsignals);

  for(i=0; i<edfhdr->edfsignals; i++)
  {
    SignalsTablewidget->setRowHeight(i, 20);

    SignalsTablewidget->setCellWidget(i, 0, new QCheckBox(edfhdr->edfparam[i].label));
    ((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->setTristate(FALSE);
    ((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->setCheckState(Qt::Checked);

    if(!edfhdr->edfparam[i].annotation)
    {
      SignalsTablewidget->setCellWidget(i, 1, new QDoubleSpinBox);
      ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 1)))->setDecimals(3);
      ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 1)))->setSuffix(" Hz");
      ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 1)))->setRange(0.001, 100.0);
      ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 1)))->setValue(spinBox1->value());

      SignalsTablewidget->setCellWidget(i, 2, new QDoubleSpinBox);
      ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 2)))->setDecimals(3);
      ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 2)))->setRange(1.0, 256.0);
      ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 2)))->setValue(spinBox2->value());
    }
    else
    {
      ((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->setEnabled(FALSE);
    }
  }

  pushButton3->setEnabled(TRUE);
}



void UI_BDF2EDFwindow::StartConversion()
{
  int i, j, k,
      new_edfsignals,
      datarecords;

  char *readbuf,
       scratchpad[256];

  union {
          unsigned int one;
          signed int one_signed;
          unsigned short two[2];
          signed short two_signed[2];
          unsigned char four[4];
        } var;

  union {
          signed short one_short;
          unsigned char two_bytes[2];
        } var2;



  pushButton3->setEnabled(FALSE);

  if(edfhdr==NULL)
  {
    return;
  }

  if(edfhdr->edfsignals>MAXSIGNALS)
  {
    return;
  }

  new_edfsignals = 0;

  for(i=0; i<edfhdr->edfsignals; i++)
  {
    if(!edfhdr->edfparam[i].annotation)
    {
      if(((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->checkState()==Qt::Checked)
      {
        signalslist[new_edfsignals] = i;

        annotlist[new_edfsignals] = 0;

        filterlist[new_edfsignals] = create_filter(0,
                                                  ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 1)))->value(),
                                                  1.0 / (edfhdr->data_record_duration / edfhdr->edfparam[i].smp_per_record));

        dividerlist[new_edfsignals] = ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 2)))->value();

        new_edfsignals++;
      }
    }
    else
    {
      signalslist[new_edfsignals] = i;

      annotlist[new_edfsignals] = 1;

      filterlist[new_edfsignals] = create_filter(0, 0.01,
                                                1.0 / (edfhdr->data_record_duration / edfhdr->edfparam[i].smp_per_record));
      dividerlist[new_edfsignals] = 1.0;

      new_edfsignals++;
    }
  }

  if(!new_edfsignals)
  {
    showpopupmessage("Error", "You must select at least one signal.");
    goto END_1;
  }

  datarecords = edfhdr->datarecords;

  readbuf = (char *)malloc(edfhdr->recordsize);
  if(readbuf==NULL)
  {
    showpopupmessage("Error", "Malloc error, (readbuf).");
    goto END_2;
  }

///////////////////////////////////////////////////////////////////

  strcpy(output_path, path);
  sprintf(output_path + pathlen - 4, ".edf");

  outputfile = fopen64(output_path, "wb");
  if(outputfile==NULL)
  {
    showpopupmessage("Error", "Can not open outputfile for writing.");
    goto END_2;
  }

  fprintf(outputfile, "0       ");
  fseek(inputfile, 8, SEEK_SET);
  if(fread(scratchpad, 176, 1, inputfile)!=1)
  {
    showpopupmessage("Error", "Read error (1).");
    goto END_3;
  }
  if(fwrite(scratchpad, 176, 1, outputfile)!=1)
  {
    showpopupmessage("Error", "Write error (1).");
    goto END_3;
  }
  fprintf(outputfile, "%-8i", new_edfsignals * 256 + 256);
  if(edfhdr->bdfplus)
  {
    if(edfhdr->discontinuous)
    {
      fprintf(outputfile, "EDF+D");
    }
    else
    {
      fprintf(outputfile, "EDF+C");
    }
    for(i=0; i<39; i++)
    {
      fputc(' ', outputfile);
    }
  }
  else
  {
    for(i=0; i<44; i++)
    {
      fputc(' ', outputfile);
    }
  }
  fprintf(outputfile, "%-8i", datarecords);
  snprintf(scratchpad, 256, "%f", edfhdr->data_record_duration);
  for(i=0; i<8; i++)
  {
    if(scratchpad[i]=='.')
    {
      for(j=7; j>=0; j--)
      {
        if((scratchpad[j]!='.')&&(scratchpad[j]!='0'))
        {
          break;
        }

        if(scratchpad[j]=='.')
        {
          scratchpad[j] = ' ';
          break;
        }

        scratchpad[j] = ' ';
      }
      break;
    }
  }
  scratchpad[8] = 0;
  fprintf(outputfile, "%s", scratchpad);
  fprintf(outputfile, "%-4i", new_edfsignals);

  for(i=0; i<new_edfsignals; i++)
  {
    if(annotlist[i])
    {
      fprintf(outputfile, "EDF Annotations ");
    }
    else
    {
      fprintf(outputfile, "%s", edfhdr->edfparam[signalslist[i]].label);
    }
  }
  for(i=0; i<new_edfsignals; i++)
  {
    fprintf(outputfile, "%s", edfhdr->edfparam[signalslist[i]].transducer);
  }
  for(i=0; i<new_edfsignals; i++)
  {
    fprintf(outputfile, "%s", edfhdr->edfparam[signalslist[i]].physdimension);
  }
  for(i=0; i<new_edfsignals; i++)
  {
    if(annotlist[i])
    {
      fprintf(outputfile, "-1      ");
    }
    else
    {
      snprintf(scratchpad, 256, "%f", edfhdr->edfparam[signalslist[i]].bitvalue * -32768.0 * dividerlist[i]);
      for(k=0; k<8; k++)
      {
        if(scratchpad[k]=='.')
        {
          for(j=7; j>=0; j--)
          {
            if((scratchpad[j]!='.')&&(scratchpad[j]!='0'))
            {
              break;
            }

            if(scratchpad[j]=='.')
            {
              scratchpad[j] = ' ';
              break;
            }

            scratchpad[j] = ' ';
          }
          break;
        }
      }
      scratchpad[8] = 0;
      fprintf(outputfile, "%s", scratchpad);
    }
  }
  for(i=0; i<new_edfsignals; i++)
  {
    if(annotlist[i])
    {
      fprintf(outputfile, "1       ");
    }
    else
    {
      snprintf(scratchpad, 256, "%f", edfhdr->edfparam[signalslist[i]].bitvalue * 32767.0 * dividerlist[i]);
      for(k=0; k<8; k++)
      {
        if(scratchpad[k]=='.')
        {
          for(j=7; j>=0; j--)
          {
            if((scratchpad[j]!='.')&&(scratchpad[j]!='0'))
            {
              break;
            }

            if(scratchpad[j]=='.')
            {
              scratchpad[j] = ' ';
              break;
            }

            scratchpad[j] = ' ';
          }
          break;
        }
      }
      scratchpad[8] = 0;
      fprintf(outputfile, "%s", scratchpad);
    }
  }
  for(i=0; i<new_edfsignals; i++)
  {
    fprintf(outputfile, "-32768  ");
  }
  for(i=0; i<new_edfsignals; i++)
  {
    fprintf(outputfile, "32767   ");
  }
  for(i=0; i<new_edfsignals; i++)
  {
    if(annotlist[i])
    {
      for(j=0; j<80; j++)
      {
        fputc(' ', outputfile);
      }
    }
    else
    {
      snprintf(scratchpad, 256, "HP:%f", ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(signalslist[i], 1)))->value());

      for(k=strlen(scratchpad)-1; k>=0; k--)
      {
        if(scratchpad[k]=='.')
        {
          for(j=strlen(scratchpad)-1; j>=0; j--)
          {
            if((scratchpad[j]!='.')&&(scratchpad[j]!='0'))
            {
              scratchpad[j + 1] = 0;
              break;
            }

            if(scratchpad[j]=='.')
            {
              scratchpad[j] = 0;
              break;
            }

            scratchpad[j] = 0;
          }
          break;
        }
      }

      strcat(scratchpad, "Hz ");

      for(j=0; j<72; j++)
      {
        if(!strncmp(&(edfhdr->edfparam[signalslist[i]].prefilter[j]), "HP: DC; ", 8))
        {
          break;
        }
      }

      if(j==72)
      {
        strcat(scratchpad, edfhdr->edfparam[signalslist[i]].prefilter);
      }
      else
      {
        strcat(scratchpad, &(edfhdr->edfparam[signalslist[i]].prefilter[j + 8]));
      }

      for(j=strlen(scratchpad); j<80; j++)
      {
        scratchpad[j] = ' ';
      }

      scratchpad[80] = 0;

      for(j=0; j<68; j++)
      {
        if(!strncmp(scratchpad + j, "No filtering", 12))
        {
          for(k=j; k<(j+12); k++)
          {
            scratchpad[k] = ' ';
          }
        }
      }

      fprintf(outputfile, "%s", scratchpad);
    }
  }
  for(i=0; i<new_edfsignals; i++)
  {
    if(annotlist[i])
    {
      if(edfhdr->edfparam[signalslist[i]].smp_per_record % 2)
      {
        fprintf(outputfile, "%-8i", ((edfhdr->edfparam[signalslist[i]].smp_per_record * 15) / 10) + 1);
      }
      else
      {
        fprintf(outputfile, "%-8i", (edfhdr->edfparam[signalslist[i]].smp_per_record * 15) / 10);
      }
    }
    else
    {
      fprintf(outputfile, "%-8i", edfhdr->edfparam[signalslist[i]].smp_per_record);
    }
  }
  for(i=0; i<(new_edfsignals * 32); i++)
  {
   fputc(' ', outputfile);
  }

///////////////////////////////////////////////////////////////////

  QApplication::setOverrideCursor(Qt::WaitCursor);

  fseeko64(inputfile, edfhdr->hdrsize, SEEK_SET);

  while(datarecords--)
  {
    qApp->processEvents();

    if(fread(readbuf, edfhdr->recordsize, 1, inputfile) != 1)
    {
      QApplication::restoreOverrideCursor();
      showpopupmessage("Error", "Read error (2).");
      goto END_3;
    }

    for(i=0; i<new_edfsignals; i++)
    {
      if(annotlist[i])
      {
        if(fwrite(readbuf + edfhdr->edfparam[signalslist[i]].buf_offset, edfhdr->edfparam[signalslist[i]].smp_per_record * 3, 1, outputfile)!=1)
        {
          QApplication::restoreOverrideCursor();
          showpopupmessage("Error", "Write error (2).");
          goto END_3;
        }

        if(edfhdr->edfparam[signalslist[i]].smp_per_record % 2)
        {
          if(fputc(0, outputfile)==EOF)
          {
            QApplication::restoreOverrideCursor();
            showpopupmessage("Error", "Write error (3).");
            goto END_3;
          }
        }
      }
      else
      {
        for(j=0; j<edfhdr->edfparam[signalslist[i]].smp_per_record; j++)
        {
          var.two[0] = *((unsigned short *)(readbuf + edfhdr->edfparam[signalslist[i]].buf_offset + (j * 3)));

          var.four[2] = *((unsigned char *)(readbuf + edfhdr->edfparam[signalslist[i]].buf_offset + (j * 3) + 2));

          if(var.four[2]&0x80)
          {
            var.four[3] = 0xff;
          }
          else
          {
            var.four[3] = 0x00;
          }

          var.one_signed += edfhdr->edfparam[signalslist[i]].offset;

          var.one_signed = first_order_filter(var.one_signed, filterlist[i]);

          var.one_signed /= dividerlist[i];

          if(var.one_signed>32767)  var.one_signed = 32767;

          if(var.one_signed<-32768)  var.one_signed = -32768;

          var2.one_short = var.one_signed;

          fputc(var2.two_bytes[0], outputfile);
          if(fputc(var2.two_bytes[1], outputfile)==EOF)
          {
            QApplication::restoreOverrideCursor();
            showpopupmessage("Error", "Write error (4).");
            goto END_3;
          }
        }
      }
    }
  }

  QApplication::restoreOverrideCursor();
  showpopupmessage("Ready", "Done.");

END_3:

  fclose(outputfile);
  outputfile = NULL;

END_2:

  free(readbuf);

END_1:

  for(i=0; i<new_edfsignals; i++)
  {
    free(filterlist[i]);
  }

  fclose(inputfile);
  inputfile = NULL;

  path[0] = 0;

  free(edfhdr);
  edfhdr = NULL;

  label1->setText("");

  SignalsTablewidget->setRowCount(0);
}


void UI_BDF2EDFwindow::showpopupmessage(const char *str1, const char *str2)
{
  UI_Messagewindow popupmessage(str1, str2);
}

















Generated by  Doxygen 1.6.0   Back to index