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

signals_dialog.cpp

/*
***************************************************************************
*
* Author: Teunis van Beelen
*
* Copyright (C) 2007, 2008, 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 "signals_dialog.h"



UI_Signalswindow::UI_Signalswindow(QWidget *parent)
{
  int i;

  mainwindow = (UI_Mainwindow *)parent;

  SignalsDialog = new QDialog;

  SignalsDialog->setMinimumSize(QSize(800, 475));
  SignalsDialog->setMaximumSize(QSize(800, 475));
  SignalsDialog->setWindowTitle("Signals");
  SignalsDialog->setModal(TRUE);
  SignalsDialog->setAttribute(Qt::WA_DeleteOnClose, TRUE);

  filelist = new QListWidget(SignalsDialog);
  filelist->setGeometry(QRect(10, 10, 780, 75));
  for(i=0; i<mainwindow->files_open; i++)
  {
    new QListWidgetItem(mainwindow->edfheaderlist[i]->filename, filelist);
  }

  label1 = new QLabel(SignalsDialog);
  label1->setGeometry(QRect(10, 95, 760, 20));

  label2 = new QLabel(SignalsDialog);
  label2->setGeometry(QRect(10, 120, 760, 20));

  label3 = new QLabel(SignalsDialog);
  label3->setGeometry(QRect(10, 145, 250, 20));

  label4 = new QLabel(SignalsDialog);
  label4->setGeometry(QRect(270, 145, 250, 20));

  colorlabel = new QLabel(SignalsDialog);
  colorlabel->setGeometry(QRect(320, 355, 100, 20));
  colorlabel->setText("   Color");

  signallist = new QListWidget(SignalsDialog);
  signallist->setGeometry(QRect(10, 185, 300, 225));
  signallist->setFont(*mainwindow->monofont);
  signallist->setSelectionBehavior(QAbstractItemView::SelectRows);
  signallist->setSelectionMode(QAbstractItemView::ExtendedSelection);

  CloseButton = new QPushButton(SignalsDialog);
  CloseButton->setGeometry(QRect(690, 430, 100, 25));
  CloseButton->setText("Close");

  SelectAllButton = new QPushButton(SignalsDialog);
  SelectAllButton->setGeometry(QRect(10, 430, 100, 25));
  SelectAllButton->setText("Select All");

  HelpButton = new QPushButton(SignalsDialog);
  HelpButton->setGeometry(QRect(690, 120, 100, 25));
  HelpButton->setText("Help");

  DisplayButton = new QPushButton(SignalsDialog);
  DisplayButton->setGeometry(QRect(150, 430, 160, 25));
  DisplayButton->setText("Add signals");

  DisplayCompButton = new QPushButton(SignalsDialog);
  DisplayCompButton->setGeometry(QRect(430, 430, 160, 25));
  DisplayCompButton->setText("Display Combination");

  AddButton = new QPushButton(SignalsDialog);
  AddButton->setGeometry(QRect(320, 225, 100, 25));
  AddButton->setText("Add->");

  SubtractButton = new QPushButton(SignalsDialog);
  SubtractButton->setGeometry(QRect(320, 260, 100, 25));
  SubtractButton->setText("Subtract->");

  RemoveButton = new QPushButton(SignalsDialog);
  RemoveButton->setGeometry(QRect(320, 295, 100, 25));
  RemoveButton->setText("Remove<-");

  ColorButton = new SpecialButton(SignalsDialog);
  ColorButton->setGeometry(QRect(320, 380, 100, 25));
  ColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->signal_color);

  compositionlist = new QListWidget(SignalsDialog);
  compositionlist->setGeometry(QRect(430, 185, 360, 225));
  compositionlist->setFont(*mainwindow->monofont);
  compositionlist->setSelectionBehavior(QAbstractItemView::SelectRows);
  compositionlist->setSelectionMode(QAbstractItemView::ExtendedSelection);

  smp_per_record = 0;

  QObject::connect(CloseButton,       SIGNAL(clicked()),              SignalsDialog, SLOT(close()));
  QObject::connect(SelectAllButton,   SIGNAL(clicked()),              this, SLOT(SelectAllButtonClicked()));
  QObject::connect(HelpButton,        SIGNAL(clicked()),              this, SLOT(HelpButtonClicked()));
  QObject::connect(DisplayButton,     SIGNAL(clicked()),              this, SLOT(DisplayButtonClicked()));
  QObject::connect(DisplayCompButton, SIGNAL(clicked()),              this, SLOT(DisplayCompButtonClicked()));
  QObject::connect(AddButton,         SIGNAL(clicked()),              this, SLOT(AddButtonClicked()));
  QObject::connect(SubtractButton,    SIGNAL(clicked()),              this, SLOT(SubtractButtonClicked()));
  QObject::connect(RemoveButton,      SIGNAL(clicked()),              this, SLOT(RemoveButtonClicked()));
  QObject::connect(ColorButton,       SIGNAL(clicked()),              this, SLOT(ColorButtonClicked()));
  QObject::connect(filelist,          SIGNAL(currentRowChanged(int)), this, SLOT(show_signals(int)));

  curve_color = mainwindow->maincurve->signal_color;

  filelist->setCurrentRow(mainwindow->files_open - 1);

  SignalsDialog->exec();
}


void UI_Signalswindow::ColorButtonClicked()
{
  UI_ColorMenuDialog colormenudialog(mainwindow->maincurve, &curve_color, ColorButton);
}



void UI_Signalswindow::DisplayCompButtonClicked()
{
  int i, j, k, n, len;

  char str[512],
       str2[128];

  struct signalcompblock *newsignalcomp;

  QListWidgetItem *item;


  n = compositionlist->count();

  if(!n)
  {
    return;
  }

  newsignalcomp = (struct signalcompblock *)calloc(1, sizeof(struct signalcompblock));
  if(newsignalcomp==NULL)
  {
    UI_Messagewindow popuperrormessage("Error", "Internal error: Memory allocation error:\n\"new signal composition\"");
    SignalsDialog->close();
    return;
  }

  newsignalcomp->num_of_signals = n;
  newsignalcomp->filenum = filelist->currentRow();
  newsignalcomp->edfhdr = mainwindow->edfheaderlist[newsignalcomp->filenum];
  newsignalcomp->file_duration = newsignalcomp->edfhdr->long_data_record_duration * newsignalcomp->edfhdr->datarecords;
  newsignalcomp->voltpercm = 50.0;
  newsignalcomp->color = curve_color;
  newsignalcomp->hasruler = 0;

  for(i=0; i<n; i++)
  {
    strcpy(str, compositionlist->item(i)->text().toLatin1().data());

    for(j=0; j<newsignalcomp->edfhdr->edfsignals; j++)
    {
      if(!strncmp(newsignalcomp->edfhdr->edfparam[j].label, str + 5, 16))
      {
        newsignalcomp->edfsignal[i] = j;
        newsignalcomp->factor[i] = str[23] - 48;
        if(str[3]=='-')
        {
          newsignalcomp->factor[i] = -(newsignalcomp->factor[i]);
          strcat(newsignalcomp->signallabel, "- ");
        }
        else
        {
          if(i)
          {
            strcat(newsignalcomp->signallabel, "+ ");
          }
        }
        strcpy(str2, newsignalcomp->edfhdr->edfparam[j].label);
        strip_types_from_label(str2);
        strcat(newsignalcomp->signallabel, str2);
        strcat(newsignalcomp->signallabel, " ");
        len = strlen(newsignalcomp->signallabel);
        for(k=(len-1); k>0; k--)
        {
          if(newsignalcomp->signallabel[k]!=' ')  break;
        }
        newsignalcomp->signallabel[k+2] = 0;

        newsignalcomp->sensitivity[i] = newsignalcomp->edfhdr->edfparam[j].bitvalue / ((double)newsignalcomp->voltpercm * mainwindow->pixelsizefactor);
      }
    }
  }

  newsignalcomp->signallabellen = strlen(newsignalcomp->signallabel);

  strcpy(newsignalcomp->physdimension, newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].physdimension);
  len = strlen(newsignalcomp->physdimension);
  for(k=(len-1); k>0; k--)
  {
    if(newsignalcomp->physdimension[k]!=' ')  break;
  }
  newsignalcomp->physdimension[k+1] = 0;

  mainwindow->signalcomp[mainwindow->signalcomps] = newsignalcomp;
  mainwindow->signalcomps++;

  while(compositionlist->count())
  {
    item = compositionlist->takeItem(0);
    delete item;
  }

  mainwindow->setup_viewbuf();

  smp_per_record = 0;
}


void UI_Signalswindow::DisplayButtonClicked()
{
  int i, k, n, s, len;

  struct signalcompblock *newsignalcomp;

  QListWidgetItem *item;

  QList<QListWidgetItem *> selectedlist;

  selectedlist = signallist->selectedItems();

  n = selectedlist.size();

  if(!n)
  {
    SignalsDialog->close();
    return;
  }

  for(i=0; i<n; i++)
  {
    newsignalcomp = (struct signalcompblock *)calloc(1, sizeof(struct signalcompblock));
    if(newsignalcomp==NULL)
    {
      UI_Messagewindow popuperrormessage("Error", "Internal error: Memory allocation error:\n\"new signal composition\"");
      SignalsDialog->close();
      return;
    }

    newsignalcomp->num_of_signals = 1;
    newsignalcomp->filenum = filelist->currentRow();
    newsignalcomp->edfhdr = mainwindow->edfheaderlist[newsignalcomp->filenum];
    newsignalcomp->voltpercm = 50.0;
    newsignalcomp->color = curve_color;
    newsignalcomp->hasruler = 0;

    item = selectedlist.at(i);
    s = signallist->row(item);
    newsignalcomp->edfsignal[0] = s;
    newsignalcomp->factor[0] = 1;
    newsignalcomp->sensitivity[0] = newsignalcomp->edfhdr->edfparam[s].bitvalue / ((double)newsignalcomp->voltpercm * mainwindow->pixelsizefactor);
    strcpy(newsignalcomp->signallabel, newsignalcomp->edfhdr->edfparam[s].label);
    strip_types_from_label(newsignalcomp->signallabel);
    len = strlen(newsignalcomp->signallabel);
    for(k=(len-1); k>0; k--)
    {
      if(newsignalcomp->signallabel[k]!=' ')  break;
    }
    newsignalcomp->signallabel[k+1] = 0;

    newsignalcomp->file_duration = newsignalcomp->edfhdr->long_data_record_duration * newsignalcomp->edfhdr->datarecords;

    newsignalcomp->signallabellen = strlen(newsignalcomp->signallabel);

    strcpy(newsignalcomp->physdimension, newsignalcomp->edfhdr->edfparam[s].physdimension);
    len = strlen(newsignalcomp->physdimension);
    for(k=(len-1); k>0; k--)
    {
      if(newsignalcomp->physdimension[k]!=' ')  break;
    }
    newsignalcomp->physdimension[k+1] = 0;

    mainwindow->signalcomp[mainwindow->signalcomps] = newsignalcomp;
    mainwindow->signalcomps++;
  }

  SignalsDialog->close();

  mainwindow->setup_viewbuf();
}


void UI_Signalswindow::RemoveButtonClicked()
{
  int i, n, row;

  QListWidgetItem *item;

  QList<QListWidgetItem *> selectedlist;

  selectedlist = compositionlist->selectedItems();

  n = selectedlist.size();

  if(!n)  return;

  for(i=0; i<n; i++)
  {
    item = selectedlist.at(i);
    row = compositionlist->row(item);
    item = compositionlist->takeItem(row);
    delete item;
  }
}


void UI_Signalswindow::AddButtonClicked()
{
  int i, j, k, n, s, row, duplicate;

  char str[256];

  QListWidgetItem *item;

  QList<QListWidgetItem *> selectedlist;

  selectedlist = signallist->selectedItems();

  n = selectedlist.size();

  if(!n)  return;

  if(!compositionlist->count())
  {
    smp_per_record = 0;
    physdimension[0] = 0;
    bitvalue = 0.0;
  }

  for(i=0; i<n; i++)
  {
    item = selectedlist.at(i);
    s = signallist->row(item);
    row = filelist->currentRow();

    if(smp_per_record)
    {
      if(smp_per_record!=mainwindow->edfheaderlist[row]->edfparam[s].smp_per_record)
      {
        UI_Messagewindow popup_error("Error",
                                     "It is only possible to make combinations with signals who:\n"
                                     " - are from the same file\n"
                                     " - have the same samplerate\n"
                                     " - have the same physical dimension (e.g. uV)\n"
                                     " - have the same sensitivity (e.g. uV/bit)");

        continue;
      }
    }
    else
    {
      smp_per_record = mainwindow->edfheaderlist[row]->edfparam[s].smp_per_record;
    }

    if(physdimension[0])
    {
      if(strcmp(physdimension, mainwindow->edfheaderlist[row]->edfparam[s].physdimension))
      {
        UI_Messagewindow popup_error("Error",
                                     "It is only possible to make combinations with signals who:\n"
                                     " - are from the same file\n"
                                     " - have the same samplerate\n"
                                     " - have the same physical dimension (e.g. uV)\n"
                                     " - have the same sensitivity (e.g. uV/bit)");

        continue;
      }
    }
    else
    {
      strcpy(physdimension, mainwindow->edfheaderlist[row]->edfparam[s].physdimension);
    }

    if(bitvalue!=0.0)
    {
      if(bitvalue!=mainwindow->edfheaderlist[row]->edfparam[s].bitvalue)
      {
        UI_Messagewindow popup_error("Error",
                                     "It is only possible to make combinations with signals who:\n"
                                     " - are from the same file\n"
                                     " - have the same samplerate\n"
                                     " - have the same physical dimension (e.g. uV)\n"
                                     " - have the same sensitivity (e.g. uV/bit)");

        continue;
      }
    }
    else
    {
      bitvalue = mainwindow->edfheaderlist[row]->edfparam[s].bitvalue;
    }

    duplicate = 0;

    k = compositionlist->count();
    for(j=0; j<k; j++)
    {
      item = compositionlist->item(j);
      strcpy(str, item->text().toLatin1().data());
      if(!strncmp(mainwindow->edfheaderlist[row]->edfparam[s].label, str + 5, 16))
      {
        if(str[3]=='+')
        {
          duplicate = 1;
          break;
        }
      }
    }
    if(duplicate)
    {
       if(str[23]==57)  continue;

       str[23] += 1;
       item->setText(str);
    }
    else
    {
      snprintf(str, 200, "%-2i + ", row + 1);
      strcat(str, mainwindow->edfheaderlist[row]->edfparam[s].label);
      strcat(str, " x1");
      snprintf(str + strlen(str), 50, " %5.fHz", mainwindow->edfheaderlist[row]->edfparam[s].smp_per_record / mainwindow->edfheaderlist[row]->data_record_duration);
      item = new QListWidgetItem;
      item->setText(str);
      compositionlist->addItem(item);
    }
  }
}


void UI_Signalswindow::SubtractButtonClicked()
{
  int i, j, k, n, s, row, duplicate;

  char str[256];

  QListWidgetItem *item;

  QList<QListWidgetItem *> selectedlist;

  selectedlist = signallist->selectedItems();

  n = selectedlist.size();

  if(!n)  return;

  if(!compositionlist->count())
  {
    smp_per_record = 0;
    physdimension[0] = 0;
    bitvalue = 0.0;
  }

  for(i=0; i<n; i++)
  {
    item = selectedlist.at(i);
    s = signallist->row(item);
    row = filelist->currentRow();

    if(smp_per_record)
    {
      if(smp_per_record!=mainwindow->edfheaderlist[row]->edfparam[s].smp_per_record)
      {
        UI_Messagewindow popup_error("Error",
                                     "It is only possible to make combinations with signals who:\n"
                                     " - are from the same file\n"
                                     " - have the same samplerate\n"
                                     " - have the same physical dimension (e.g. uV)\n"
                                     " - have the same sensitivity (e.g. uV/bit)");

        continue;
      }
    }
    else
    {
      smp_per_record = mainwindow->edfheaderlist[row]->edfparam[s].smp_per_record;
    }

    if(physdimension[0])
    {
      if(strcmp(physdimension, mainwindow->edfheaderlist[row]->edfparam[s].physdimension))
      {
        UI_Messagewindow popup_error("Error",
                                     "It is only possible to make combinations with signals who:\n"
                                     " - are from the same file\n"
                                     " - have the same samplerate\n"
                                     " - have the same physical dimension (e.g. uV)\n"
                                     " - have the same sensitivity (e.g. uV/bit)");

        continue;
      }
    }
    else
    {
      strcpy(physdimension, mainwindow->edfheaderlist[row]->edfparam[s].physdimension);
    }

    if(bitvalue!=0.0)
    {
      if(bitvalue!=mainwindow->edfheaderlist[row]->edfparam[s].bitvalue)
      {
        UI_Messagewindow popup_error("Error",
                                     "It is only possible to make combinations with signals who:\n"
                                     " - are from the same file\n"
                                     " - have the same samplerate\n"
                                     " - have the same physical dimension (e.g. uV)\n"
                                     " - have the same sensitivity (e.g. uV/bit)");

        continue;
      }
    }
    else
    {
      bitvalue = mainwindow->edfheaderlist[row]->edfparam[s].bitvalue;
    }

    duplicate = 0;

    k = compositionlist->count();
    for(j=0; j<k; j++)
    {
      item = compositionlist->item(j);
      strcpy(str, item->text().toLatin1().data());
      if(!strncmp(mainwindow->edfheaderlist[row]->edfparam[s].label, str + 5, 16))
      {
        if(str[3]=='-')
        {
          duplicate = 1;
          break;
        }
      }
    }
    if(duplicate)
    {
       if(str[23]==57)  continue;

       str[23] += 1;
       item->setText(str);
    }
    else
    {
      snprintf(str, 200, "%-2i - ", row + 1);
      strcat(str, mainwindow->edfheaderlist[row]->edfparam[s].label);
      strcat(str, " x1");
      snprintf(str + strlen(str), 50, " %5.fHz", mainwindow->edfheaderlist[row]->edfparam[s].smp_per_record / mainwindow->edfheaderlist[row]->data_record_duration);
      item = new QListWidgetItem;
      item->setText(str);
      compositionlist->addItem(item);
    }
  }
}


void UI_Signalswindow::show_signals(int row)
{
  int i, j, len, skip, signal_cnt;

  char str[256];

  long long file_duration;

  QListWidgetItem *item;

  struct date_time_struct date_time;


  if(row<0)  return;

  while(signallist->count())
  {
    delete signallist->item(0);
  }

  if((mainwindow->edfheaderlist[row]->edfplus)||(mainwindow->edfheaderlist[row]->bdfplus))
  {
    strcpy(str, "Patient    ");
    strcat(str, mainwindow->edfheaderlist[row]->plus_patient_name);
    strcat(str, "  ");
    strcat(str, mainwindow->edfheaderlist[row]->plus_birthdate);
    strcat(str, "  ");
    strcat(str, mainwindow->edfheaderlist[row]->plus_patientcode);
    label1->setText(str);
    strcpy(str, "Recording  ");
    strcat(str, mainwindow->edfheaderlist[row]->plus_admincode);
    label2->setText(str);
  }
  else
  {
    strcpy(str, "Patient    ");
    strcat(str, mainwindow->edfheaderlist[row]->patient);
    len = strlen(str);
    for(j=0; j<len; j++)
    {
      if(str[j]=='_')
      {
        str[j] = ' ';
      }
    }
    label1->setText(str);
    strcpy(str, "Recording  ");
    strcat(str, mainwindow->edfheaderlist[row]->recording);
    len = strlen(str);
    for(j=0; j<len; j++)
    {
      if(str[j]=='_')
      {
        str[j] = ' ';
      }
    }
    label2->setText(str);
  }

  utc_to_date_time(mainwindow->edfheaderlist[row]->utc_starttime, &date_time);

  date_time.month_str[0] += 32;
  date_time.month_str[1] += 32;
  date_time.month_str[2] += 32;

  snprintf(str, 256, "Start      %i %s %i   %2i:%02i:%02i",
          date_time.day,
          date_time.month_str,
          date_time.year,
          date_time.hour,
          date_time.minute,
          date_time.second);

  label3->setText(str);

  strcpy(str, "Duration   ");
  file_duration = mainwindow->edfheaderlist[row]->long_data_record_duration * mainwindow->edfheaderlist[row]->datarecords;
  snprintf(str + 11, 240,
          "%2i:%02i:%02i",
          (int)((file_duration / TIME_DIMENSION)/ 3600LL),
          (int)(((file_duration / TIME_DIMENSION) % 3600LL) / 60LL),
          (int)((file_duration / TIME_DIMENSION) % 60LL));
  label4->setText(str);

  skip = 0;

  signal_cnt = mainwindow->edfheaderlist[row]->edfsignals;

  for(i=0; i<signal_cnt; i++)
  {
    if(mainwindow->edfheaderlist[row]->edfplus || mainwindow->edfheaderlist[row]->bdfplus)
    {
      for(j=0; j<mainwindow->edfheaderlist[row]->nr_annot_chns; j++)
      {
        if(i==mainwindow->edfheaderlist[row]->annot_ch[j])
        {
          skip = 1;
          break;
        }
      }
      if(skip)
      {
        skip = 0;
        continue;
      }
    }

    snprintf(str, 256, "%-3i ", i + 1);
    strcat(str, mainwindow->edfheaderlist[row]->edfparam[i].label);
    sprintf(str + strlen(str), "   %5.fHz", mainwindow->edfheaderlist[row]->edfparam[i].smp_per_record / mainwindow->edfheaderlist[row]->data_record_duration);
    item = new QListWidgetItem;
    item->setText(str);
    signallist->addItem(item);
  }

  SelectAllButtonClicked();
}


void UI_Signalswindow::SelectAllButtonClicked()
{
  int row, i;

  QListWidgetItem *item;

  row = signallist->count();

  for(i=0; i<row; i++)
  {
    item = signallist->item(i);
    item->setSelected(TRUE);
  }
}


void UI_Signalswindow::HelpButtonClicked()
{
  UI_Messagewindow popup_help("Help",

  "On top you will see a list of opened files.\n"
  "Select (highlight) the file from which you want to add signals. At the left part of the dialog you see a list of\n"
  "all the signals which are in the selected file. Select one or more signals and click on the \"Add signals\"\n"
  "button. Now you will see the selected signals on the screen.\n"

  "\nWhen you want to make a combination (subtraction) of two or more signals, do as follows.\n"
  "Select the file from which you want to add signals. For example, we choose an EEG file which contains\n"
  "the signals \"P3\" and \"C3\" and we want to subtract \"C3\" from \"P3\".\n"
  "- Select (highlight) the signal \"P3\".\n"
  "- Click on the \"Add\" button.\n"
  "- Select (highlight) the signal \"C3\".\n"
  "- Click on the \"Subtract\" button.\n"
  "- Click on the \"Display Combination\" button.\n"
  "- The result of \"P3\" minus \"C3\" will appear on the screen.");
}


void UI_Signalswindow::strip_types_from_label(char *label)
{
  int i,
      len;


  len = strlen(label);
  if(len<16)
  {
    return;
  }

  if((!(strncmp(label, "EEG ", 4)))
   ||(!(strncmp(label, "ECG ", 4)))
   ||(!(strncmp(label, "EOG ", 4)))
   ||(!(strncmp(label, "ERG ", 4)))
   ||(!(strncmp(label, "EMG ", 4)))
   ||(!(strncmp(label, "MEG ", 4)))
   ||(!(strncmp(label, "MCG ", 4))))
  {
    if(label[4]!=' ')
    {
      for(i=0; i<(len-4); i++)
      {
        label[i] = label[i+4];
      }

      for(; i<len; i++)
      {
        label[i] = ' ';
      }
    }
  }
}













Generated by  Doxygen 1.6.0   Back to index