diff -Nru edfbrowser-1.30/about_dialog.cpp edfbrowser-1.38/about_dialog.cpp --- edfbrowser-1.30/about_dialog.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/about_dialog.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -61,10 +61,8 @@ textedit1->setLineWrapMode(QTextEdit::NoWrap); textedit1->setPlainText( "\n " PROGRAM_NAME " " PROGRAM_VERSION "\n" - "\n This program is made by Teunis van Beelen\n" - " in cooperation with the Clinical Neurophysiology department at\n" - " Leiden University Medical Centre, Netherland.\n" - "\n Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen.\n" + "\n This program is made by Teunis van Beelen.\n" + "\n Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen.\n" "\n Email: teuniz@gmail.com\n" "\n Disclaimer:\n" " Despite this software is intend to be usefull, there is no warranty, use this software at your own risk!\n" diff -Nru edfbrowser-1.30/about_dialog.h edfbrowser-1.38/about_dialog.h --- edfbrowser-1.30/about_dialog.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/about_dialog.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/active_file_chooser.cpp edfbrowser-1.38/active_file_chooser.cpp --- edfbrowser-1.30/active_file_chooser.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/active_file_chooser.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/active_file_chooser.h edfbrowser-1.38/active_file_chooser.h --- edfbrowser-1.30/active_file_chooser.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/active_file_chooser.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/adjustfiltersettings.cpp edfbrowser-1.38/adjustfiltersettings.cpp --- edfbrowser-1.30/adjustfiltersettings.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/adjustfiltersettings.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -35,8 +35,8 @@ type: -0 : lowpass -1 : highpass +0 : highpass +1 : lowpass 2 : notch 3 : bandpass 4 : bandstop @@ -46,6 +46,7 @@ 0 : Butterworth 1 : Chebyshev 2 : Bessel +3 : moving average 0 : resonator @@ -134,6 +135,8 @@ CloseButton->setGeometry(270, 220, 80, 25); CloseButton->setText("Close"); + filter_cnt = 0; + for(i=0; ifidfilter_cnt; i++) { txtbuf[0] = 0; @@ -224,6 +227,27 @@ } filterbox->addItem(txtbuf); + + brand[filter_cnt++] = 0; + } + + for(i=0; iravg_filter_cnt; i++) + { + type = signalcomp->ravg_filter_type[i]; + + size = signalcomp->ravg_filter_size[i]; + + if(type == 0) + { + filterbox->addItem("Highpass Moving Average"); + } + + if(type == 1) + { + filterbox->addItem("Lowpass Moving Average"); + } + + brand[filter_cnt++] = 1; } filterboxchanged(filterbox->currentIndex()); @@ -241,12 +265,18 @@ void AdjustFilterSettings::orderboxvaluechanged(int) { + int j; + + for(j=0; j<10; j++) qApp->processEvents(); + update_filter(); } void AdjustFilterSettings::freqbox1valuechanged(double value) { + int j; + if((type == 3) || (type == 4)) { if(freq2box->value() < (value * 1.12)) @@ -259,12 +289,16 @@ } } + for(j=0; j<10; j++) qApp->processEvents(); + update_filter(); } void AdjustFilterSettings::freqbox2valuechanged(double value) { + int j; + if(freq1box->value() > (value * 0.9)) { QObject::disconnect(freq1box, SIGNAL(valueChanged(double)), this, SLOT(freqbox1valuechanged(double))); @@ -274,32 +308,55 @@ QObject::connect(freq1box, SIGNAL(valueChanged(double)), this, SLOT(freqbox1valuechanged(double))); } + for(j=0; j<10; j++) qApp->processEvents(); + update_filter(); } void AdjustFilterSettings::filterboxchanged(int i) { - if(i >= 0) + int n; + + + if(i < 0) { - frequency1 = signalcomp->fidfilter_freq[i]; + return; + } - frequency2 = signalcomp->fidfilter_freq2[i]; + QObject::disconnect(freq1box, SIGNAL(valueChanged(double)), this, SLOT(freqbox1valuechanged(double))); + QObject::disconnect(freq2box, SIGNAL(valueChanged(double)), this, SLOT(freqbox2valuechanged(double))); + QObject::disconnect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); - type = signalcomp->fidfilter_type[i]; + if(brand[i] == 0) // fidfilter + { + n = i; - model = signalcomp->fidfilter_model[i]; + frequency1 = signalcomp->fidfilter_freq[n]; - order = signalcomp->fidfilter_order[i]; + frequency2 = signalcomp->fidfilter_freq2[n]; - ripple = signalcomp->fidfilter_ripple[i]; + type = signalcomp->fidfilter_type[n]; - QObject::disconnect(freq1box, SIGNAL(valueChanged(double)), this, SLOT(freqbox1valuechanged(double))); - QObject::disconnect(freq2box, SIGNAL(valueChanged(double)), this, SLOT(freqbox2valuechanged(double))); - QObject::disconnect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); + model = signalcomp->fidfilter_model[n]; + + order = signalcomp->fidfilter_order[n]; + + ripple = signalcomp->fidfilter_ripple[n]; freq1box->setValue(frequency1); + label[1]->setText("Order"); + label[2]->setText("Frequency"); + freq1box->setVisible(TRUE); + stepsizebox->clear(); + stepsizebox->addItem("0.01Hz"); + stepsizebox->addItem("0.1Hz"); + stepsizebox->addItem("1Hz"); + stepsizebox->addItem("10Hz"); + stepsizebox->addItem("100Hz"); + stepsizebox->setCurrentIndex(2); + if((type == 3) || (type == 4)) { freq2box->setValue(frequency2); @@ -333,11 +390,39 @@ } orderbox->setValue(order); - - QObject::connect(freq1box, SIGNAL(valueChanged(double)), this, SLOT(freqbox1valuechanged(double))); - QObject::connect(freq2box, SIGNAL(valueChanged(double)), this, SLOT(freqbox2valuechanged(double))); - QObject::connect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); } + + if(brand[i] == 1) // moving average filter + { + n = i - signalcomp->fidfilter_cnt; + + type = signalcomp->ravg_filter_type[n]; + + size = signalcomp->ravg_filter_size[n]; + + stepsizebox->clear(); + stepsizebox->addItem("1"); + stepsizebox->addItem("10"); + stepsizebox->addItem("100"); + stepsizebox->addItem("1000"); + stepsizebox->setCurrentIndex(0); + + label[1]->setText("Size"); + label[2]->setText(""); + freq1box->setVisible(FALSE); + label[3]->setVisible(FALSE); + freq2box->setVisible(FALSE); + orderbox->setMinimum(2); + orderbox->setSingleStep(1); + orderbox->setMaximum(10000); + orderbox->setPrefix(""); + orderbox->setSuffix(" samples"); + orderbox->setValue(size); + } + + QObject::connect(freq1box, SIGNAL(valueChanged(double)), this, SLOT(freqbox1valuechanged(double))); + QObject::connect(freq2box, SIGNAL(valueChanged(double)), this, SLOT(freqbox2valuechanged(double))); + QObject::connect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); } @@ -357,176 +442,197 @@ return; } - frequency1 = freq1box->value(); - frequency2 = freq2box->value(); - order = orderbox->value(); - - if(type < 3) + if(brand[filter_nr] == 0) // fidfilter { - if(frequency1 >= ((signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record - / signalcomp->edfhdr->data_record_duration) - / 2.0)) + frequency1 = freq1box->value(); + frequency2 = freq2box->value(); + order = orderbox->value(); + + if(type < 3) { - frequency1 = (signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record - / signalcomp->edfhdr->data_record_duration) - / 2.0; + if(frequency1 >= ((signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record + / signalcomp->edfhdr->data_record_duration) + / 2.0)) + { + frequency1 = (signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record + / signalcomp->edfhdr->data_record_duration) + / 2.0; - frequency1 -= freq1box->singleStep(); + frequency1 -= freq1box->singleStep(); - freq1box->setValue(frequency1); + freq1box->setValue(frequency1); + } } - } - else - { - if(frequency2 >= ((signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record - / signalcomp->edfhdr->data_record_duration) - / 2.0)) + else { - frequency2 = (signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record - / signalcomp->edfhdr->data_record_duration) - / 2.0; + if(frequency2 >= ((signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record + / signalcomp->edfhdr->data_record_duration) + / 2.0)) + { + frequency2 = (signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record + / signalcomp->edfhdr->data_record_duration) + / 2.0; - frequency2 -= freq2box->singleStep(); + frequency2 -= freq2box->singleStep(); - freq2box->setValue(frequency2); - } + freq2box->setValue(frequency2); + } - if(frequency1 >= frequency2 * 0.9) - { - frequency1 = frequency2 * 0.9; + if(frequency1 >= frequency2 * 0.9) + { + frequency1 = frequency2 * 0.9; - freq1box->setValue(frequency1); + freq1box->setValue(frequency1); + } } - } - if(type < 3) - { - if(frequency1 >= ((signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record - / signalcomp->edfhdr->data_record_duration) - / 2.0)) + if(type < 3) { - UI_Messagewindow errormessage("Error", "The frequency must be less than: samplerate / 2"); - return; + if(frequency1 >= ((signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record + / signalcomp->edfhdr->data_record_duration) + / 2.0)) + { + UI_Messagewindow errormessage("Error", "The frequency must be less than: samplerate / 2"); + return; + } } - } - else - { - if(frequency2 >= ((signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record - / signalcomp->edfhdr->data_record_duration) - / 2.0)) + else { - UI_Messagewindow errormessage("Error", "The frequency must be less than: samplerate / 2"); - return; + if(frequency2 >= ((signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record + / signalcomp->edfhdr->data_record_duration) + / 2.0)) + { + UI_Messagewindow errormessage("Error", "The frequency must be less than: samplerate / 2"); + return; + } } - } - spec_str_1[0] = 0; + spec_str_1[0] = 0; - if(type == 0) - { - if(model == 0) + if(type == 0) { - sprintf(spec_str_1, "HpBu%i/%f", order, frequency1); - } + if(model == 0) + { + sprintf(spec_str_1, "HpBu%i/%f", order, frequency1); + } - if(model == 1) - { - sprintf(spec_str_1, "HpCh%i/%f/%f", order, ripple, frequency1); - } + if(model == 1) + { + sprintf(spec_str_1, "HpCh%i/%f/%f", order, ripple, frequency1); + } - if(model == 2) - { - sprintf(spec_str_1, "HpBe%i/%f", order, frequency1); + if(model == 2) + { + sprintf(spec_str_1, "HpBe%i/%f", order, frequency1); + } } - } - if(type == 1) - { - if(model == 0) + if(type == 1) { - sprintf(spec_str_1, "LpBu%i/%f", order, frequency1); + if(model == 0) + { + sprintf(spec_str_1, "LpBu%i/%f", order, frequency1); + } + + if(model == 1) + { + sprintf(spec_str_1, "LpCh%i/%f/%f", order, ripple, frequency1); + } + + if(model == 2) + { + sprintf(spec_str_1, "LpBe%i/%f", order, frequency1); + } } - if(model == 1) + if(type == 2) { - sprintf(spec_str_1, "LpCh%i/%f/%f", order, ripple, frequency1); + sprintf(spec_str_1, "BsRe/%i/%f", order, frequency1); } - if(model == 2) + if(type == 3) { - sprintf(spec_str_1, "LpBe%i/%f", order, frequency1); - } - } + if(model == 0) + { + sprintf(spec_str_1, "BpBu%i/%f-%f", order, frequency1, frequency2); + } - if(type == 2) - { - sprintf(spec_str_1, "BsRe/%i/%f", order, frequency1); - } + if(model == 1) + { + sprintf(spec_str_1, "BpCh%i/%f/%f-%f", order, ripple, frequency1, frequency2); + } - if(type == 3) - { - if(model == 0) - { - sprintf(spec_str_1, "BpBu%i/%f-%f", order, frequency1, frequency2); + if(model == 2) + { + sprintf(spec_str_1, "BpBe%i/%f-%f", order, frequency1, frequency2); + } } - if(model == 1) + if(type == 4) { - sprintf(spec_str_1, "BpCh%i/%f/%f-%f", order, ripple, frequency1, frequency2); - } + if(model == 0) + { + sprintf(spec_str_1, "BsBu%i/%f-%f", order, frequency1, frequency2); + } - if(model == 2) - { - sprintf(spec_str_1, "BpBe%i/%f-%f", order, frequency1, frequency2); - } - } + if(model == 1) + { + sprintf(spec_str_1, "BsCh%i/%f/%f-%f", order, ripple, frequency1, frequency2); + } - if(type == 4) - { - if(model == 0) - { - sprintf(spec_str_1, "BsBu%i/%f-%f", order, frequency1, frequency2); + if(model == 2) + { + sprintf(spec_str_1, "BsBe%i/%f-%f", order, frequency1, frequency2); + } } - if(model == 1) - { - sprintf(spec_str_1, "BsCh%i/%f/%f-%f", order, ripple, frequency1, frequency2); - } + strcpy(spec_str_2, spec_str_1); + + filter_spec = spec_str_2; - if(model == 2) + free(signalcomp->fidfilter[filter_nr]); + fid_run_free(signalcomp->fid_run[filter_nr]); + fid_run_freebuf(signalcomp->fidbuf[filter_nr]); + fid_run_freebuf(signalcomp->fidbuf2[filter_nr]); + + err = fid_parse(((double)(signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record)) / signalcomp->edfhdr->data_record_duration, + &filter_spec, + &signalcomp->fidfilter[filter_nr]); + + if(err != NULL) { - sprintf(spec_str_1, "BsBe%i/%f-%f", order, frequency1, frequency2); + UI_Messagewindow errormessage("Error", err); + free(err); + return; } - } - - strcpy(spec_str_2, spec_str_1); - filter_spec = spec_str_2; + signalcomp->fid_run[filter_nr] = fid_run_new(signalcomp->fidfilter[filter_nr], &signalcomp->fidfuncp[filter_nr]); - free(signalcomp->fidfilter[filter_nr]); - fid_run_free(signalcomp->fid_run[filter_nr]); - fid_run_freebuf(signalcomp->fidbuf[filter_nr]); - fid_run_freebuf(signalcomp->fidbuf2[filter_nr]); + signalcomp->fidbuf[filter_nr] = fid_run_newbuf(signalcomp->fid_run[filter_nr]); + signalcomp->fidbuf2[filter_nr] = fid_run_newbuf(signalcomp->fid_run[filter_nr]); - err = fid_parse(((double)(signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record)) / signalcomp->edfhdr->data_record_duration, - &filter_spec, - &signalcomp->fidfilter[filter_nr]); + signalcomp->fidfilter_freq[filter_nr] = frequency1; + signalcomp->fidfilter_freq2[filter_nr] = frequency2; + signalcomp->fidfilter_order[filter_nr] = order; + } - if(err != NULL) + if(brand[filter_nr] == 1) // moving average filter { - UI_Messagewindow errormessage("Error", err); - free(err); - return; - } + filter_nr -= signalcomp->fidfilter_cnt; - signalcomp->fid_run[filter_nr] = fid_run_new(signalcomp->fidfilter[filter_nr], &signalcomp->fidfuncp[filter_nr]); + size = orderbox->value(); - signalcomp->fidbuf[filter_nr] = fid_run_newbuf(signalcomp->fid_run[filter_nr]); - signalcomp->fidbuf2[filter_nr] = fid_run_newbuf(signalcomp->fid_run[filter_nr]); + free_ravg_filter(signalcomp->ravg_filter[filter_nr]); + + signalcomp->ravg_filter[filter_nr] = create_ravg_filter(type, size); + if(signalcomp->ravg_filter[filter_nr] == NULL) + { + UI_Messagewindow errormessage("Error", "An error occurred while creating a moving average filter."); + return; + } - signalcomp->fidfilter_freq[filter_nr] = frequency1; - signalcomp->fidfilter_freq2[filter_nr] = frequency2; - signalcomp->fidfilter_order[filter_nr] = order; + signalcomp->ravg_filter_size[filter_nr] = size; + } mainwindow->setup_viewbuf(); } @@ -534,23 +640,50 @@ void AdjustFilterSettings::stepsizeboxchanged(int index) { - switch(index) + int n; + + n = filterbox->currentIndex(); + + if(n < 0) { - case 0: freq1box->setSingleStep(0.01); - freq2box->setSingleStep(0.01); - break; - case 1: freq1box->setSingleStep(0.1); - freq2box->setSingleStep(0.1); - break; - case 2: freq1box->setSingleStep(1.0); - freq2box->setSingleStep(1.0); - break; - case 3: freq1box->setSingleStep(10.0); - freq2box->setSingleStep(10.0); - break; - case 4: freq1box->setSingleStep(100.0); - freq2box->setSingleStep(100.0); - break; + return; + } + + if(brand[n] == 0) // fidfilter + { + switch(index) + { + case 0: freq1box->setSingleStep(0.01); + freq2box->setSingleStep(0.01); + break; + case 1: freq1box->setSingleStep(0.1); + freq2box->setSingleStep(0.1); + break; + case 2: freq1box->setSingleStep(1.0); + freq2box->setSingleStep(1.0); + break; + case 3: freq1box->setSingleStep(10.0); + freq2box->setSingleStep(10.0); + break; + case 4: freq1box->setSingleStep(100.0); + freq2box->setSingleStep(100.0); + break; + } + } + + if(brand[n] == 1) // moving average filter + { + switch(index) + { + case 0: orderbox->setSingleStep(1); + break; + case 1: orderbox->setSingleStep(10); + break; + case 2: orderbox->setSingleStep(100); + break; + case 3: orderbox->setSingleStep(1000); + break; + } } } diff -Nru edfbrowser-1.30/adjustfiltersettings.h edfbrowser-1.38/adjustfiltersettings.h --- edfbrowser-1.30/adjustfiltersettings.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/adjustfiltersettings.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -50,6 +50,7 @@ #include "mainwindow.h" #include "viewcurve.h" #include "popup_messagewindow.h" +#include "ravg_filter.h" #include "fidlib/fidlib.h" @@ -71,9 +72,12 @@ private: int filter_nr, + filter_cnt, type, model, - order; + order, + size, + brand[MAXFILTERS]; double frequency1, frequency2, diff -Nru edfbrowser-1.30/annotations_dock.cpp edfbrowser-1.38/annotations_dock.cpp --- edfbrowser-1.30/annotations_dock.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/annotations_dock.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -67,6 +67,11 @@ list->setAutoFillBackground(TRUE); list->setPalette(palette); + average_annot_act = new QAction("Average", list); + + list->setContextMenuPolicy(Qt::ActionsContextMenu); + list->insertAction(NULL, average_annot_act); + v_layout = new QVBoxLayout(dialog1); v_layout->addWidget(checkbox1); v_layout->addWidget(list); @@ -76,12 +81,44 @@ updateList(file_num); - QObject::connect(list, SIGNAL(itemPressed(QListWidgetItem *)), this, SLOT(annotation_selected(QListWidgetItem *))); - QObject::connect(docklist, SIGNAL(visibilityChanged(bool)), this, SLOT(hide_editdock(bool))); - QObject::connect(checkbox1, SIGNAL(stateChanged(int)), this, SLOT(checkbox1_clicked(int))); + QObject::connect(list, SIGNAL(itemPressed(QListWidgetItem *)), this, SLOT(annotation_selected(QListWidgetItem *))); + QObject::connect(docklist, SIGNAL(visibilityChanged(bool)), this, SLOT(hide_editdock(bool))); + QObject::connect(checkbox1, SIGNAL(stateChanged(int)), this, SLOT(checkbox1_clicked(int))); + QObject::connect(average_annot_act, SIGNAL(triggered(bool)), this, SLOT(average_annot(bool))); } +void UI_Annotationswindow::average_annot(bool) +{ + if(mainwindow->files_open != 1) + { + return; + } + + if(!mainwindow->signalcomps) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "First add a signal to the screen."); + messagewindow.exec(); + + return; + } + + if(mainwindow->annot_editor_active) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Close the annotation editor and try again."); + messagewindow.exec(); + + return; + } + + if(list->count() < 1) + { + return; + } + + UI_AveragerWindow average_wndw(mainwindow, list->currentRow()); +} + void UI_Annotationswindow::checkbox1_clicked(int state) { @@ -99,7 +136,6 @@ } - void UI_Annotationswindow::hide_editdock(bool visible) { if(visible==FALSE) @@ -112,21 +148,21 @@ void UI_Annotationswindow::updateList(int file_num) { - char str[MAX_ANNOTATION_LEN + 16], + char str[MAX_ANNOTATION_LEN + 32], *str_tmp; - QListWidgetItem *listitem; - - QString string; - - QByteArray ba; - int i, len, sequence_nr=0, jump=0, modified=0; + QListWidgetItem *listitem; + + QString string; + + QByteArray ba; + selected = -1; @@ -177,16 +213,16 @@ { if(annotation->onset<0) { - snprintf(str, (MAX_ANNOTATION_LEN + 16) / 2, " -%i:%02i:%02i.%04i", - (int)(((-annotation->onset / TIME_DIMENSION)/ 3600) % 24), + snprintf(str, (MAX_ANNOTATION_LEN + 32) / 2, " -%2i:%02i:%02i.%04i", + (int)((-annotation->onset / TIME_DIMENSION)/ 3600), (int)(((-annotation->onset / TIME_DIMENSION) % 3600) / 60), (int)((-annotation->onset / TIME_DIMENSION) % 60), (int)((-annotation->onset % TIME_DIMENSION) / 1000LL)); } else { - snprintf(str, (MAX_ANNOTATION_LEN + 16) / 2, " %2i:%02i:%02i.%04i", - (int)(((annotation->onset / TIME_DIMENSION)/ 3600) % 24), + snprintf(str, (MAX_ANNOTATION_LEN + 32) / 2, " %3i:%02i:%02i.%04i", + (int)((annotation->onset / TIME_DIMENSION)/ 3600), (int)(((annotation->onset / TIME_DIMENSION) % 3600) / 60), (int)((annotation->onset / TIME_DIMENSION) % 60), (int)((annotation->onset % TIME_DIMENSION) / 1000LL)); @@ -194,13 +230,15 @@ } else { - snprintf(str, MAX_ANNOTATION_LEN + 16, " %2i:%02i:%02i.%04i", - (int)(((annotation->onset + mainwindow->edfheaderlist[file_num]->l_starttime) / TIME_DIMENSION)/ 3600), - (int)((((annotation->onset + mainwindow->edfheaderlist[file_num]->l_starttime) / TIME_DIMENSION) % 3600) / 60), - (int)(((annotation->onset + mainwindow->edfheaderlist[file_num]->l_starttime) / TIME_DIMENSION) % 60), - (int)(((annotation->onset + mainwindow->edfheaderlist[file_num]->l_starttime) % TIME_DIMENSION) / 1000LL)); + snprintf(str, MAX_ANNOTATION_LEN + 32, " %3i:%02i:%02i.%04i", + (int)((((annotation->onset + mainwindow->edfheaderlist[file_num]->l_starttime + mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION)/ 3600) % 24), + (int)((((annotation->onset + mainwindow->edfheaderlist[file_num]->l_starttime + mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION) % 3600) / 60), + (int)(((annotation->onset + mainwindow->edfheaderlist[file_num]->l_starttime + mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION) % 60), + (int)(((annotation->onset + mainwindow->edfheaderlist[file_num]->l_starttime + mainwindow->edfheaderlist[file_num]->starttime_offset) % TIME_DIMENSION) / 1000LL)); } + str[MAX_ANNOTATION_LEN + 31] = 0; + remove_trailing_zeros(str); if(string.size() < 20) @@ -223,16 +261,16 @@ if(annotation->onset<0) { - snprintf(str, (MAX_ANNOTATION_LEN + 16) / 2, "onset: -%i:%02i:%02i.%04i", - (int)(((-annotation->onset / TIME_DIMENSION)/ 3600) % 24), + snprintf(str, (MAX_ANNOTATION_LEN + 32) / 2, "onset: -%i:%02i:%02i.%04i", + (int)((-annotation->onset / TIME_DIMENSION)/ 3600), (int)(((-annotation->onset / TIME_DIMENSION) % 3600) / 60), (int)((-annotation->onset / TIME_DIMENSION) % 60), (int)((-annotation->onset % TIME_DIMENSION) / 1000LL)); } else { - snprintf(str, (MAX_ANNOTATION_LEN + 16) / 2, "onset: %2i:%02i:%02i.%04i", - (int)(((annotation->onset / TIME_DIMENSION)/ 3600) % 24), + snprintf(str, (MAX_ANNOTATION_LEN + 32) / 2, "onset: %2i:%02i:%02i.%04i", + (int)((annotation->onset / TIME_DIMENSION)/ 3600), (int)(((annotation->onset / TIME_DIMENSION) % 3600) / 60), (int)((annotation->onset / TIME_DIMENSION) % 60), (int)((annotation->onset % TIME_DIMENSION) / 1000LL)); @@ -240,9 +278,11 @@ if(annotation->duration[0]!=0) { - snprintf(str + strlen(str), (MAX_ANNOTATION_LEN + 16) / 2, "\nduration: %s",annotation->duration); + snprintf(str + strlen(str), (MAX_ANNOTATION_LEN + 32) / 2, "\nduration: %s",annotation->duration); } + str[MAX_ANNOTATION_LEN + 31] = 0; + remove_trailing_zeros(str); strcat(str, "\n\n"); @@ -328,7 +368,7 @@ { for(i=0; ifiles_open; i++) { - mainwindow->edfheaderlist[i]->viewtime = annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset; + mainwindow->edfheaderlist[i]->viewtime = annotation->onset; mainwindow->edfheaderlist[i]->viewtime -= (mainwindow->pagetime / 2); } @@ -336,14 +376,14 @@ if(mainwindow->viewtime_sync==VIEWTIME_UNSYNCED) { - mainwindow->edfheaderlist[file_num]->viewtime = annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset; + mainwindow->edfheaderlist[file_num]->viewtime = annotation->onset; mainwindow->edfheaderlist[i]->viewtime -= (mainwindow->pagetime / 2); } if((mainwindow->viewtime_sync==VIEWTIME_SYNCED_ABSOLUT)||(mainwindow->viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { - temp = annotation->onset - mainwindow->edfheaderlist[file_num]->viewtime - mainwindow->edfheaderlist[file_num]->starttime_offset; + temp = annotation->onset - mainwindow->edfheaderlist[file_num]->viewtime; for(i=0; ifiles_open; i++) { diff -Nru edfbrowser-1.30/annotations_dock.h edfbrowser-1.38/annotations_dock.h --- edfbrowser-1.30/annotations_dock.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/annotations_dock.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -50,6 +50,8 @@ #include #include #include +#include +#include #include #include @@ -60,6 +62,7 @@ #include "edit_annotation_dock.h" #include "viewcurve.h" #include "utils.h" +#include "averager_dialog.h" class UI_Mainwindow; @@ -96,11 +99,14 @@ QCheckBox *checkbox1; + QAction *average_annot_act; + private slots: void annotation_selected(QListWidgetItem *); void hide_editdock(bool); void checkbox1_clicked(int); + void average_annot(bool); }; diff -Nru edfbrowser-1.30/ascii2edf.cpp edfbrowser-1.38/ascii2edf.cpp --- edfbrowser-1.30/ascii2edf.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/ascii2edf.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -37,8 +37,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -357,14 +355,16 @@ if(!(strlen(PatientnameLineEdit->text().toLatin1().data()))) { - UI_Messagewindow popuperror("Invalid input", "Please enter a subjectname."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a subjectname."); + messagewindow.exec(); ascii2edfDialog->setEnabled(TRUE); return; } if(!(strlen(RecordingLineEdit->text().toLatin1().data()))) { - UI_Messagewindow popuperror("Invalid input", "Please enter a recordingdescription."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a recording description."); + messagewindow.exec(); ascii2edfDialog->setEnabled(TRUE); return; } @@ -382,7 +382,8 @@ inputfile = fopeno(path, "rb"); if(inputfile==NULL) { - UI_Messagewindow popuperror("Error", "Can not open file for reading."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); + messagewindow.exec(); ascii2edfDialog->setEnabled(TRUE); return; } @@ -399,7 +400,8 @@ if(temp==EOF) { - UI_Messagewindow popuperror("Error", "File does not contain enough lines."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "File does not contain enough lines."); + messagewindow.exec(); fclose(inputfile); ascii2edfDialog->setEnabled(TRUE); return; @@ -425,7 +427,8 @@ if(temp==EOF) { - UI_Messagewindow popuperror("Error", "File does not contain enough lines."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "File does not contain enough lines."); + messagewindow.exec(); fclose(inputfile); ascii2edfDialog->setEnabled(TRUE); return; @@ -456,7 +459,8 @@ if(column!=columns) { - UI_Messagewindow popuperror("Error", "Number of columns does not match."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Number of columns does not match."); + messagewindow.exec(); fclose(inputfile); ascii2edfDialog->setEnabled(TRUE); return; @@ -471,7 +475,8 @@ if(i>2045) { - UI_Messagewindow popuperror("Error", "Too many characters in a line."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Too many characters in a line."); + messagewindow.exec(); fclose(inputfile); ascii2edfDialog->setEnabled(TRUE); return; @@ -487,7 +492,7 @@ for(i=0; isetEnabled(TRUE); return; @@ -632,7 +638,8 @@ { QApplication::restoreOverrideCursor(); snprintf(txt_string, 2048, "Error, line %i is too long.\n", line_nr); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); fclose(inputfile); ascii2edfDialog->setEnabled(TRUE); return; @@ -707,7 +714,8 @@ if(outputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for writing.", outputfilename); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); fclose(inputfile); ascii2edfDialog->setEnabled(TRUE); return; @@ -758,7 +766,8 @@ snprintf(str, 256, "%.8f", datrecduration); if(fwrite(str, 8, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Error", "A write error occurred."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A write error occurred."); + messagewindow.exec(); fclose(inputfile); fclose(outputfile); ascii2edfDialog->setEnabled(TRUE); @@ -950,7 +959,8 @@ if(buf==NULL) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Error", "Malloc error (buf)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error (buf)"); + messagewindow.exec(); fclose(inputfile); fclose(outputfile); ascii2edfDialog->setEnabled(TRUE); @@ -1061,7 +1071,8 @@ QApplication::restoreOverrideCursor(); snprintf(txt_string, 2048, "Error, number of columns in line %i is wrong.\n", line_nr); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); fclose(inputfile); fclose(outputfile); free(buf); @@ -1104,7 +1115,8 @@ if(fwrite(buf, bufsize, 1, outputfile)!=1) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Error", "Write error during conversion."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Write error during conversion."); + messagewindow.exec(); fclose(inputfile); fclose(outputfile); free(buf); @@ -1138,7 +1150,8 @@ { QApplication::restoreOverrideCursor(); snprintf(txt_string, 2048, "Error, line %i is too long.\n", line_nr); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); fclose(inputfile); fclose(outputfile); free(buf); @@ -1157,7 +1170,8 @@ if(fclose(outputfile)) { - UI_Messagewindow popuperror("Error", "An error occurred when closing outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when closing outputfile."); + messagewindow.exec(); fclose(inputfile); ascii2edfDialog->setEnabled(TRUE); return; @@ -1165,13 +1179,15 @@ if(fclose(inputfile)) { - UI_Messagewindow popuperror("Error", "An error occurred when closing inputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when closing inputfile."); + messagewindow.exec(); ascii2edfDialog->setEnabled(TRUE); return; } snprintf(txt_string, 2048, "Done. EDF file is located at %s\n", outputfilename); - UI_Messagewindow popupmessage("Ready", txt_string); + QMessageBox messagewindow(QMessageBox::Information, "Ready", txt_string); + messagewindow.exec(); ascii2edfDialog->setEnabled(TRUE); } @@ -1217,7 +1233,8 @@ outputfile = fopeno(path, "wb"); if(outputfile==NULL) { - UI_Messagewindow popuperror("Error", "Can not open file for writing."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for writing."); + messagewindow.exec(); ascii2edfDialog->setEnabled(TRUE); return; } @@ -1326,20 +1343,23 @@ xml_hdl = xml_get_handle(path); if(xml_hdl==NULL) { - UI_Messagewindow popuperror("Error", "Can not open file for reading."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); + messagewindow.exec(); return; } if(strcmp(xml_hdl->elementname, PROGRAM_NAME "_ascii2edf_template")) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this template."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); + messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_goto_nth_element_inside(xml_hdl, "separator", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this template."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -1353,7 +1373,8 @@ { if(strlen(content)!=1) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this template."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); + messagewindow.exec(); free(content); xml_close(xml_hdl); return; @@ -1362,7 +1383,8 @@ { if((content[0]<32)||(content[0]>126)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this template."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); + messagewindow.exec(); free(content); xml_close(xml_hdl); return; @@ -1376,7 +1398,8 @@ if(xml_goto_nth_element_inside(xml_hdl, "columns", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this template."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -1385,7 +1408,8 @@ free(content); if((temp<1)||(temp>256)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this template."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -1397,7 +1421,8 @@ if(xml_goto_nth_element_inside(xml_hdl, "startline", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this template."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -1406,7 +1431,8 @@ free(content); if((temp<1)||(temp>100)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this template."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -1416,7 +1442,8 @@ if(xml_goto_nth_element_inside(xml_hdl, "samplefrequency", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this template."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -1425,7 +1452,8 @@ free(content); if((f_temp<0.0000001)||(f_temp>1000000.0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this template."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -1477,14 +1505,16 @@ { if(xml_goto_nth_element_inside(xml_hdl, "signalparams", i)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this template."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); + messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_goto_nth_element_inside(xml_hdl, "checked", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this template."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -1499,7 +1529,8 @@ if(xml_goto_nth_element_inside(xml_hdl, "label", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this template."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -1511,7 +1542,8 @@ if(xml_goto_nth_element_inside(xml_hdl, "physical_maximum", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this template."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -1523,7 +1555,8 @@ if(xml_goto_nth_element_inside(xml_hdl, "physical_dimension", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this template."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -1535,7 +1568,8 @@ if(xml_goto_nth_element_inside(xml_hdl, "multiplier", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this template."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -1555,7 +1589,6 @@ { int i, j, k, len, - space, dot; char str[128], @@ -1574,28 +1607,32 @@ { if(strlen(str)!=1) { - UI_Messagewindow popuperror("Invalid input", "Separator must be one character or tab."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Separator must be one character or tab."); + messagewindow.exec(); return(1); } if((str[0]<32)||(str[0]>126)) { - UI_Messagewindow popuperror("Invalid input", "Separator character is not a valid ASCII character."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Separator character is not a valid ASCII character."); + messagewindow.exec(); return(1); } if(str[0]=='.') { - UI_Messagewindow popuperror("Invalid input", "Separator character can not be a dot."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Separator character can not be a dot."); + messagewindow.exec(); return(1); } if((str[0]>47)&&(str[0]<58)) { - UI_Messagewindow popuperror("Invalid input", "Separator character can not be a number."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Separator character can not be a number."); + messagewindow.exec(); return(1); } @@ -1611,7 +1648,8 @@ { if(samplefrequency>((double)((int)samplefrequency))) { - UI_Messagewindow popuperror("Invalid input", "Only samplefrequencies below 1 Hz can have a decimal fraction."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Only samplefrequencies below 1 Hz can have a decimal fraction."); + messagewindow.exec(); return(1); } @@ -1630,8 +1668,6 @@ continue; } - space = 0; - dot = 0; strcpy(str, ((QLineEdit *)SignalsTablewidget->cellWidget(i, j))->text().toLatin1().data()); @@ -1642,7 +1678,8 @@ { snprintf(big_str, 2048, "%s field of row %i is empty.", columnname[j], i + 1); - UI_Messagewindow popuperror("Invalid input", big_str); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", big_str); + messagewindow.exec(); return(1); } @@ -1655,7 +1692,8 @@ "Character %i in %s field of row %i is not a valid ASCII character.", k + 1, columnname[j], i + 1); - UI_Messagewindow popuperror("Invalid input", big_str); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", big_str); + messagewindow.exec(); return(1); } @@ -1668,7 +1706,8 @@ "Text in %s field of row %i is not valid.\nField must not be empty and left-aligned (no spaces in front of the text).", columnname[j], i + 1); - UI_Messagewindow popuperror("Invalid input", big_str); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", big_str); + messagewindow.exec(); return(1); } @@ -1683,7 +1722,8 @@ "Last character can not be a dot.", columnname[j], i + 1); - UI_Messagewindow popuperror("Invalid input", big_str); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", big_str); + messagewindow.exec(); return(1); } @@ -1699,7 +1739,8 @@ "Only one dot is allowed as a decimal separator.", columnname[j], i + 1); - UI_Messagewindow popuperror("Invalid input", big_str); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", big_str); + messagewindow.exec(); return(1); } @@ -1712,7 +1753,8 @@ "First character can not be a dot.", columnname[j], i + 1); - UI_Messagewindow popuperror("Invalid input", big_str); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", big_str); + messagewindow.exec(); return(1); } @@ -1727,7 +1769,8 @@ "Field must contain a number and no spaces.", columnname[j], i + 1); - UI_Messagewindow popuperror("Invalid input", big_str); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", big_str); + messagewindow.exec(); return(1); } @@ -1744,7 +1787,8 @@ "Value must be 1 or more.", columnname[j], i + 1); - UI_Messagewindow popuperror("Invalid input", big_str); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", big_str); + messagewindow.exec(); return(1); } @@ -1763,7 +1807,8 @@ if(edfsignals<1) { - UI_Messagewindow popuperror("Invalid input", "At least one row needs to be checked."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "At least one row needs to be checked."); + messagewindow.exec(); return(1); } diff -Nru edfbrowser-1.30/ascii2edf.h edfbrowser-1.38/ascii2edf.h --- edfbrowser-1.30/ascii2edf.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/ascii2edf.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -52,6 +52,7 @@ #include #include #include +#include #include #include diff -Nru edfbrowser-1.30/ascii_export.cpp edfbrowser-1.38/ascii_export.cpp --- edfbrowser-1.30/ascii_export.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/ascii_export.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -37,8 +37,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -195,7 +193,8 @@ if(mainwindow->file_is_opened(path)) { - UI_Messagewindow popuperror("Save file", "Error, selected file is in use."); + QMessageBox messagewindow(QMessageBox::Critical, "Save file", "Error, selected file is in use."); + messagewindow.exec(); AsciiExportDialog->close(); return; } @@ -208,21 +207,24 @@ scratchpad = (char *)calloc(1, 128); if(scratchpad==NULL) { - UI_Messagewindow popuperror("Error", "Malloc error! (scratchpad)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error! (scratchpad)."); + messagewindow.exec(); AsciiExportDialog->close(); return; } if(fseeko(inputfile, 0xfcLL, SEEK_SET)) { - UI_Messagewindow popuperror("Error", "Error, reading file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "File read error."); + messagewindow.exec(); AsciiExportDialog->close(); return; } if(fread(scratchpad, 4, 1, inputfile)!=1) { - UI_Messagewindow popuperror("Error", "Error, reading file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "File read error."); + messagewindow.exec(); AsciiExportDialog->close(); return; } @@ -233,7 +235,8 @@ edf_hdr = (char *)calloc(1, (edfsignals + 1) * 256); if(edf_hdr==NULL) { - UI_Messagewindow popuperror("Error", "Malloc error! (edf_hdr)\n"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error! (edf_hdr)"); + messagewindow.exec(); AsciiExportDialog->close(); return; } @@ -241,7 +244,8 @@ rewind(inputfile); if(fread(edf_hdr, (edfsignals + 1) * 256, 1, inputfile)!=1) { - UI_Messagewindow popuperror("Error", "Error, reading file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "File read error."); + messagewindow.exec(); free(edf_hdr); AsciiExportDialog->close(); return; @@ -312,7 +316,8 @@ edfparamascii = (struct asciiedfparamblock *)calloc(1, sizeof(struct asciiedfparamblock[edfsignals])); if(edfparamascii==NULL) { - UI_Messagewindow popuperror("Error", "Malloc error! (edfparam)\n"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error! (edfparam)"); + messagewindow.exec(); free(edf_hdr); AsciiExportDialog->close(); return; @@ -347,7 +352,8 @@ cnv_buf = (char *)calloc(1, recordsize * samplesize); if(cnv_buf==NULL) { - UI_Messagewindow popuperror("Error", "Malloc error! (cnv_buf)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error! (cnv_buf)"); + messagewindow.exec(); free(edf_hdr); free(edfparamascii); AsciiExportDialog->close(); @@ -368,7 +374,8 @@ scratchpad = (char *)calloc(1, max_tal_ln + 3); if(scratchpad==NULL) { - UI_Messagewindow popuperror("Error", "Malloc error! (scratchpad)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error! (scratchpad)"); + messagewindow.exec(); free(cnv_buf); free(edf_hdr); free(edfparamascii); @@ -379,7 +386,8 @@ duration_in_txt = (char *)calloc(1, max_tal_ln + 3); if(duration_in_txt==NULL) { - UI_Messagewindow popuperror("Error", "Malloc error! (duration_in_txt)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error! (duration_in_txt)"); + messagewindow.exec(); free(scratchpad); free(cnv_buf); free(edf_hdr); @@ -391,7 +399,8 @@ time_in_txt = (char *)calloc(1, max_tal_ln + 3); if(time_in_txt==NULL) { - UI_Messagewindow popuperror("Error", "Malloc error! (time_in_txt)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error! (time_in_txt)"); + messagewindow.exec(); free(duration_in_txt); free(scratchpad); free(cnv_buf); @@ -409,7 +418,8 @@ outputfile = fopeno(ascii_path, "wb"); if(outputfile==NULL) { - UI_Messagewindow popuperror("Error", "Error, can not open headerfile for writing."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, can not open headerfile for writing."); + messagewindow.exec(); free(edf_hdr); free(edfparamascii); free(cnv_buf); @@ -451,7 +461,8 @@ outputfile = fopeno(ascii_path, "wb"); if(outputfile==NULL) { - UI_Messagewindow popuperror("Error", "Error, can not open signalfile for writing."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, can not open signalfile for writing."); + messagewindow.exec(); free(edf_hdr); free(edfparamascii); free(cnv_buf); @@ -501,7 +512,8 @@ annotationfile = fopeno(ascii_path, "wb"); if(annotationfile==NULL) { - UI_Messagewindow popuperror("Error", "Error, can not open annotationfile for writing."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, can not open annotationfile for writing."); + messagewindow.exec(); free(edf_hdr); free(edfparamascii); free(cnv_buf); @@ -522,7 +534,8 @@ outputfile = fopeno(ascii_path, "wb"); if(outputfile==NULL) { - UI_Messagewindow popuperror("Error", "Error, can not open datafile for writing."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, can not open datafile for writing."); + messagewindow.exec(); fclose(annotationfile); free(edf_hdr); free(edfparamascii); @@ -543,7 +556,8 @@ if(fputc('\n', outputfile)==EOF) { - UI_Messagewindow popuperror("Error", "Error when writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when writing to outputfile."); + messagewindow.exec(); fclose(annotationfile); fclose(outputfile); free(edf_hdr); @@ -558,7 +572,8 @@ if(fseeko(inputfile, (long long)((edfsignals + 1) * 256), SEEK_SET)) { - UI_Messagewindow popuperror("Error", "Error when reading inputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when reading from inputfile."); + messagewindow.exec(); fclose(annotationfile); fclose(outputfile); free(edf_hdr); @@ -593,7 +608,8 @@ if(fread(cnv_buf, recordsize * samplesize, 1, inputfile)!=1) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Error", "Error when reading inputfile during export."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when reading inputfile during export."); + messagewindow.exec(); fclose(annotationfile); fclose(outputfile); free(edf_hdr); @@ -619,7 +635,8 @@ { QApplication::restoreOverrideCursor(); snprintf(str, 256, "Error, TAL in record %i exceeds my buffer.", datarecordswritten + 1); - UI_Messagewindow popuperror("Error", str); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); fclose(annotationfile); fclose(outputfile); free(edf_hdr); @@ -657,7 +674,8 @@ { QApplication::restoreOverrideCursor(); snprintf(str, 256, "Error, TAL in record %i exceeds my buffer.", datarecordswritten + 1); - UI_Messagewindow popuperror("Error", str); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); fclose(annotationfile); fclose(outputfile); free(edf_hdr); @@ -756,7 +774,8 @@ { QApplication::restoreOverrideCursor(); snprintf(str, 256, "Error, TAL in record %i exceeds my buffer.", datarecordswritten + 1); - UI_Messagewindow popuperror("Error", str); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); fclose(annotationfile); fclose(outputfile); free(edf_hdr); @@ -852,7 +871,8 @@ if(fputc('\n', outputfile)==EOF) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Error", "Error when writing to outputfile during conversion."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when writing to outputfile during conversion."); + messagewindow.exec(); fclose(annotationfile); fclose(outputfile); free(edf_hdr); @@ -916,3 +936,4 @@ + diff -Nru edfbrowser-1.30/ascii_export.h edfbrowser-1.38/ascii_export.h --- edfbrowser-1.30/ascii_export.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/ascii_export.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -46,6 +46,7 @@ #include #include #include +#include #include #include diff -Nru edfbrowser-1.30/averager_curve_wnd.cpp edfbrowser-1.38/averager_curve_wnd.cpp --- edfbrowser-1.30/averager_curve_wnd.cpp 1970-01-01 00:00:00.000000000 +0000 +++ edfbrowser-1.38/averager_curve_wnd.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -0,0 +1,577 @@ +/* +*************************************************************************** +* +* Author: Teunis van Beelen +* +* Copyright (C) 2011 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 "averager_curve_wnd.h" + + + + +UI_AverageCurveWindow::UI_AverageCurveWindow(struct signalcompblock *signal_comp, QWidget *parent, int number, + double *abuf, + double maxvalue, + long long apagetime, + long long samples_on_screen, + int acnt, + int trigger_position, + char *annotation, + double avg__period) +{ + char str[1024]; + + + averager_curve_dialog_is_destroyed = 0; + + mainwindow = (UI_Mainwindow *)parent; + + signalcomp = signal_comp; + + averagecurvedialognumber = number; + + pagetime = apagetime; + + pagetime /= TIME_DIMENSION; + + avgbuf = abuf; + + avg_max_value = maxvalue; + + avg_samples_on_screen = samples_on_screen; + + avg_cnt = acnt; + + avg_trigger_position_ratio = trigger_position; + + avg_period = avg__period; + + strcpy(avg_annotation, annotation); + + averager_curve_dialog = new QDialog(); + averager_curve_dialog->setAttribute(Qt::WA_DeleteOnClose, TRUE); + averager_curve_dialog->setMinimumSize(QSize(650, 480)); + averager_curve_dialog->setSizeGripEnabled(TRUE); + averager_curve_dialog->setModal(FALSE); + averager_curve_dialog->setWindowFlags(Qt::Window | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); + averager_curve_dialog->setWindowIcon(QIcon(":/images/edf.png")); + + strcpy(str, "Averaging "); + strcat(str, signalcomp->signallabel); + averager_curve_dialog->setWindowTitle(str); + + curve1 = new SignalCurve; + curve1->setSignalColor(Qt::green); + curve1->setBackgroundColor(Qt::black); + curve1->setRasterColor(Qt::gray); + curve1->setTraceWidth(0); + curve1->setH_label("sec"); + curve1->setLowerLabel("Time"); + curve1->setV_label(signalcomp->physdimension); + curve1->setDashBoardEnabled(FALSE); + curve1->setMarker1Color(Qt::yellow); + curve1->create_button("to EDF/BDF"); + + sprintf(str, "Averaging %i triggers \"%s\"", avg_cnt, avg_annotation); + curve1->setUpperLabel1(str); + + amplitudeSlider = new QSlider; + amplitudeSlider->setOrientation(Qt::Vertical); + amplitudeSlider->setMinimum(1); + amplitudeSlider->setMaximum(2000); + amplitudeSlider->setValue(1000); + amplitudeSlider->setInvertedAppearance(TRUE); + amplitudeSlider->setMinimumSize(15, 280); + + amplitudeLabel = new QLabel; + amplitudeLabel->setText("Amplitude"); + amplitudeLabel->setMinimumSize(110, 15); + amplitudeLabel->setAlignment(Qt::AlignHCenter); + + inversionCheckBox = new QCheckBox("Invert"); + inversionCheckBox->setMinimumSize(40, 25); + + vlayout2 = new QVBoxLayout; + vlayout2->setSpacing(20); + vlayout2->addStretch(100); + vlayout2->addWidget(inversionCheckBox, 0, Qt::AlignHCenter); + vlayout2->addWidget(amplitudeLabel, 0, Qt::AlignHCenter); + vlayout2->addWidget(amplitudeSlider, 0, Qt::AlignHCenter); + + spanSlider = new QSlider; + spanSlider->setOrientation(Qt::Horizontal); + spanSlider->setMinimum(10); + spanSlider->setMaximum(1000); + spanSlider->setValue(1000); + spanSlider->setMinimumSize(500, 15); + + spanLabel = new QLabel; + spanLabel->setText("Span"); + spanLabel->setMinimumSize(110, 15); + spanLabel->setAlignment(Qt::AlignHCenter); + + centerSlider = new QSlider; + centerSlider->setOrientation(Qt::Horizontal); + centerSlider->setMinimum(0); + centerSlider->setMaximum(1000); + centerSlider->setValue(250); + centerSlider->setMinimumSize(500, 15); + + centerLabel = new QLabel; + centerLabel->setText("Center"); + centerLabel->setMinimumSize(110, 15); + centerLabel->setAlignment(Qt::AlignHCenter); + + hlayout1 = new QHBoxLayout; + hlayout1->setSpacing(20); + hlayout1->addLayout(vlayout2); + hlayout1->addWidget(curve1, 100); + + hlayout2 = new QHBoxLayout; + hlayout2->setSpacing(20); + hlayout2->addWidget(spanLabel); + hlayout2->addWidget(spanSlider); + hlayout2->addStretch(100); + + hlayout3 = new QHBoxLayout; + hlayout3->setSpacing(20); + hlayout3->addWidget(centerLabel); + hlayout3->addWidget(centerSlider); + hlayout3->addStretch(100); + + vlayout1 = new QVBoxLayout; + vlayout1->setSpacing(20); + vlayout1->addLayout(hlayout1); + vlayout1->addLayout(hlayout2); + vlayout1->addLayout(hlayout3); + + averager_curve_dialog->setLayout(vlayout1); + + QObject::connect(amplitudeSlider, SIGNAL(valueChanged(int)), this, SLOT(sliderMoved(int))); + QObject::connect(inversionCheckBox, SIGNAL(stateChanged(int)), this, SLOT(sliderMoved(int))); + QObject::connect(spanSlider, SIGNAL(valueChanged(int)), this, SLOT(sliderMoved(int))); + QObject::connect(centerSlider, SIGNAL(valueChanged(int)), this, SLOT(sliderMoved(int))); + QObject::connect(averager_curve_dialog, SIGNAL(destroyed(QObject *)), this, SLOT(averager_curve_dialogDestroyed(QObject *))); + QObject::connect(curve1, SIGNAL(extra_button_clicked()), this, SLOT(export_edf())); + + sliderMoved(0); + + averager_curve_dialog->show(); +} + + +void UI_AverageCurveWindow::export_edf(void) +{ + int i, j, k, p, + type, + edf_hdl, + smp_per_record, + datarecords, + smpls_left; + + char path[1024], + str[512]; + + double *buf, + frequency, + frequency2; + + + smp_per_record = signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record; + + datarecords = avg_samples_on_screen / smp_per_record; + + smpls_left = avg_samples_on_screen % smp_per_record; + + path[0] = 0; + if(mainwindow->recent_savedir[0]!=0) + { + strcpy(path, mainwindow->recent_savedir); + strcat(path, "/"); + } + get_filename_from_path(path + strlen(path), signalcomp->edfhdr->filename, 512); + remove_extension_from_filename(path); + sprintf(path + strlen(path), " averaging %s %i triggers [%s]", + signalcomp->signallabel, + avg_cnt, + avg_annotation); + + if(signalcomp->edfhdr->edf) + { + strcat(path, ".edf"); + + strcpy(path, QFileDialog::getSaveFileName(0, "Save as EDF", path, "EDF files (*.edf *.EDF)").toLatin1().data()); + } + else + { + strcat(path, ".bdf"); + + strcpy(path, QFileDialog::getSaveFileName(0, "Save as BDF", path, "BDF files (*.bdf *.BDF)").toLatin1().data()); + } + + if(!strcmp(path, "")) + { + return; + } + + get_directory_from_path(mainwindow->recent_savedir, path, 1024); + + if(signalcomp->edfhdr->edf) + { + edf_hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_EDFPLUS, 1); + } + else + { + edf_hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_BDFPLUS, 1); + } + + if(edf_hdl < 0) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open output file for writing."); + messagewindow.exec(); + return; + } + + edf_set_samplefrequency(edf_hdl, 0, smp_per_record); + + if(edf_set_datarecord_duration(edf_hdl, signalcomp->edfhdr->long_data_record_duration / 100LL)) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Datarecordduration out of range."); + messagewindow.exec(); + return; + } + + if(signalcomp->edfhdr->edf) + { + edf_set_digital_maximum(edf_hdl, 0, 32767); + edf_set_digital_minimum(edf_hdl, 0, -32768); + } + else + { + edf_set_digital_maximum(edf_hdl, 0, 8388607); + edf_set_digital_minimum(edf_hdl, 0, -8388608); + } + + edf_set_physical_maximum(edf_hdl, 0, avg_max_value * 1.05); + edf_set_physical_minimum(edf_hdl, 0, avg_max_value * -1.05); + edf_set_label(edf_hdl, 0, signalcomp->signallabel); + edf_set_physical_dimension(edf_hdl, 0, signalcomp->physdimension); + + p = 0; + + for(j=0; jfidfilter_cnt; j++) + { + type = signalcomp->fidfilter_type[j]; + + frequency = signalcomp->fidfilter_freq[j]; + + frequency2 = signalcomp->fidfilter_freq2[j]; + + if(type == 0) + { + p += sprintf(str + p, "HP:%f", frequency); + } + + if(type == 1) + { + p += sprintf(str + p, "LP:%f", frequency); + } + + if(type == 2) + { + p += sprintf(str + p, "N:%f", frequency); + } + + if(type == 3) + { + p += sprintf(str + p, "BP:%f", frequency); + } + + if(type == 4) + { + p += sprintf(str + p, "BS:%f", frequency); + } + + for(k=(p-1); k>0; k--) + { + if(str[k]!='0') break; + } + + if(str[k]=='.') str[k] = 0; + else str[k+1] = 0; + + p = strlen(str); + + if((type == 3) || (type == 4)) + { + p += sprintf(str + p, "-%f", frequency2); + + for(k=(p-1); k>0; k--) + { + if(str[k]!='0') break; + } + + if(str[k]=='.') str[k] = 0; + else str[k+1] = 0; + } + + strcat(str, "Hz "); + + p = strlen(str); + + if(p>80) break; + } + + for(j=0; jravg_filter_cnt; j++) + { + if(signalcomp->ravg_filter_type[j] == 0) + { + p += sprintf(str + p, "HP:%iSmpls ", signalcomp->ravg_filter[j]->size); + } + + if(signalcomp->ravg_filter_type[j] == 1) + { + p += sprintf(str + p, "LP:%iSmpls ", signalcomp->ravg_filter[j]->size); + } + + p = strlen(str); + + if(p>80) break; + } + + strcat(str, signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].prefilter); + edf_set_prefilter(edf_hdl, 0, str); + edf_set_transducer(edf_hdl, 0, signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].transducer); + + if((signalcomp->edfhdr->edfplus) || (signalcomp->edfhdr->bdfplus)) + { + edf_set_patientname(edf_hdl, signalcomp->edfhdr->plus_patient_name); + sprintf(str, "%i triggers \"%s\" averaged. %s", avg_cnt, avg_annotation, signalcomp->edfhdr->plus_recording_additional); + edf_set_recording_additional(edf_hdl, str); + edf_set_patientcode(edf_hdl, signalcomp->edfhdr->plus_patientcode); + if(signalcomp->edfhdr->plus_gender[0] == 'M') + { + edf_set_gender(edf_hdl, 1); + } + if(signalcomp->edfhdr->plus_gender[0] == 'F') + { + edf_set_gender(edf_hdl, 0); + } + edf_set_patient_additional(edf_hdl, signalcomp->edfhdr->plus_patient_additional); + edf_set_admincode(edf_hdl, signalcomp->edfhdr->plus_admincode); + edf_set_technician(edf_hdl, signalcomp->edfhdr->plus_technician); + edf_set_equipment(edf_hdl, signalcomp->edfhdr->plus_equipment); + } + else + { + edf_set_patientname(edf_hdl, signalcomp->edfhdr->patient); + sprintf(str, "%i triggers \"%s\" averaged. %s", avg_cnt, avg_annotation, signalcomp->edfhdr->recording); + edf_set_recording_additional(edf_hdl, str); + } + + for(i=0; ivalue() * steps / 1000; + + startstep = centerSlider->value() * (steps - spanstep) / 1000; + + stopstep = startstep + spanstep; + + dtmp = avg_max_value * (double)amplitudeSlider->value() / 1000.0; + + if(inversionCheckBox->isChecked() == TRUE) + { + curve1->drawCurve(avgbuf + startstep, stopstep - startstep, -dtmp, dtmp); + } + else + { + curve1->drawCurve(avgbuf + startstep, stopstep - startstep, dtmp, -dtmp); + } + + max_sec = pagetime * stopstep / steps - (pagetime * (1.0 / avg_trigger_position_ratio)); + + precision = 0; + if(max_sec < 100.0) + { + precision = 1; + } + if(max_sec < 10.0) + { + precision = 2; + } + if(max_sec < 1.0) + { + precision = 3; + } + if(max_sec < 0.1) + { + precision = 4; + } + + start_sec = pagetime * startstep / steps - (pagetime * (1.0 / avg_trigger_position_ratio)); + + curve1->setH_RulerValues(start_sec, max_sec); + + centerLabel->setText(QString::number(start_sec + ((max_sec - start_sec) / 2.0), 'f', precision).append(" sec").prepend("Center ")); + + spanLabel->setText(QString::number(max_sec - start_sec, 'f', precision).append(" sec").prepend("Span ")); + + if(avg_trigger_position_ratio > 0) + { + markerstep = steps / avg_trigger_position_ratio; + + if((markerstep > startstep) && (markerstep < stopstep)) + { + curve1->setMarker1Enabled(TRUE); + + curve1->setMarker1Position((((double)steps / (double)avg_trigger_position_ratio) - (double)startstep) / (double)spanstep); + } + else + { + curve1->setMarker1Enabled(FALSE); + } + } + else + { + curve1->setMarker1Enabled(FALSE); + } +} + + +void UI_AverageCurveWindow::averager_curve_dialogDestroyed(QObject *) +{ + averager_curve_dialog_is_destroyed = 1; + + mainwindow->averagecurvedialog[averagecurvedialognumber] = NULL; + + delete this; +} + + +UI_AverageCurveWindow::~UI_AverageCurveWindow() +{ + int i; + + if(!averager_curve_dialog_is_destroyed) + { + averager_curve_dialog->close(); + } + + if(avgbuf != NULL) + { + free(avgbuf); + } + + mainwindow->averagecurvedialog[averagecurvedialognumber] = NULL; + + for(i=0; iavg_dialog[i] == (averagecurvedialognumber + 1)) + { + signalcomp->avg_dialog[i] = 0; + } + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru edfbrowser-1.30/averager_curve_wnd.h edfbrowser-1.38/averager_curve_wnd.h --- edfbrowser-1.30/averager_curve_wnd.h 1970-01-01 00:00:00.000000000 +0000 +++ edfbrowser-1.38/averager_curve_wnd.h 2011-08-23 20:01:14.000000000 +0000 @@ -0,0 +1,156 @@ +/* +*************************************************************************** +* +* Author: Teunis van Beelen +* +* Copyright (C) 2011 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 +* +*************************************************************************** +*/ + + + +#ifndef AVERAGERCURVEWND_H +#define AVERAGERCURVEWND_H + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "global.h" +#include "mainwindow.h" +#include "signalcurve.h" +#include "edflib.h" +#include "utils.h" + + + + +class UI_Mainwindow; + + + + +class UI_AverageCurveWindow : public QWidget +{ + Q_OBJECT + +public: + UI_AverageCurveWindow(struct signalcompblock *, QWidget *, int, + double *, + double, + long long, + long long, + int, + int, + char *, + double); + + ~UI_AverageCurveWindow(); + + UI_Mainwindow *mainwindow; + + QDialog *averager_curve_dialog; + + struct signalcompblock *signalcomp; + +private: + + int averager_curve_dialog_is_destroyed, + averagecurvedialognumber, + avg_cnt, + avg_trigger_position_ratio; + + double pagetime, + *avgbuf, + avg_max_value, + avg_period; + + long long avg_samples_on_screen; + + char avg_annotation[MAX_ANNOTATION_LEN + 1]; + + QHBoxLayout *hlayout1, + *hlayout2, + *hlayout3; + + QVBoxLayout *vlayout1, + *vlayout2; + + SignalCurve *curve1; + + QSlider *amplitudeSlider, + *spanSlider, + *centerSlider; + + QLabel *spanLabel, + *centerLabel, + *amplitudeLabel; + + QCheckBox *inversionCheckBox; + + +private slots: + +void sliderMoved(int); +void averager_curve_dialogDestroyed(QObject *); +void export_edf(void); + +}; + + +#endif + + + + + + + + + + + + + + + + + + + diff -Nru edfbrowser-1.30/averager_dialog.cpp edfbrowser-1.38/averager_dialog.cpp --- edfbrowser-1.30/averager_dialog.cpp 1970-01-01 00:00:00.000000000 +0000 +++ edfbrowser-1.38/averager_dialog.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -0,0 +1,603 @@ +/* +*************************************************************************** +* +* Author: Teunis van Beelen +* +* Copyright (C) 2011 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 "averager_dialog.h" + + + +UI_AveragerWindow::UI_AveragerWindow(QWidget *parent, int annot_nr) +{ + int i, n; + + long long recording_duration; + + struct annotationblock *annot; + + mainwindow = (UI_Mainwindow *)parent; + + averager_dialog = new QDialog(parent); + + averager_dialog->setMinimumSize(QSize(600, 400)); + averager_dialog->setMaximumSize(QSize(600, 400)); + averager_dialog->setWindowTitle("Average waveforms"); + averager_dialog->setModal(TRUE); + averager_dialog->setAttribute(Qt::WA_DeleteOnClose, TRUE); + + annotLabel = new QLabel(averager_dialog); + annotLabel->setGeometry(20, 20, 100, 25); + annotLabel->setText("Use annotation:"); + + annotNameLabel = new QLabel(averager_dialog); + annotNameLabel->setGeometry(130, 20, 200, 25); + + signalLabel = new QLabel(averager_dialog); + signalLabel->setGeometry(340, 20, 100, 25); + signalLabel->setText("Select signal(s):"); + + list = new QListWidget(averager_dialog); + list->setGeometry(450, 20, 130, 360); + list->setSelectionBehavior(QAbstractItemView::SelectRows); + list->setSelectionMode(QAbstractItemView::ExtendedSelection); + + time1.setHMS(0, 0, 0, 0); + + recording_duration = (mainwindow->edfheaderlist[0]->datarecords * mainwindow->edfheaderlist[0]->long_data_record_duration) / TIME_DIMENSION; + + time2.setHMS((recording_duration / 3600) % 24, (recording_duration % 3600) / 60, recording_duration % 60, 0); + + time1Label = new QLabel(averager_dialog); + time1Label->setGeometry(20, 65, 100, 25); + time1Label->setText("From (hh:mm:ss)"); + + timeEdit1 = new QTimeEdit(averager_dialog); + timeEdit1->setGeometry(130, 65, 110, 25); + timeEdit1->setDisplayFormat("hh:mm:ss.zzz"); + timeEdit1->setMinimumTime(QTime(0, 0, 0, 0)); + timeEdit1->setMaximumTime(time2); + + time2Label = new QLabel(averager_dialog); + time2Label->setGeometry(20, 110, 100, 25); + time2Label->setText("To (hh:mm:ss)"); + + timeEdit2 = new QTimeEdit(averager_dialog); + timeEdit2->setGeometry(130, 110, 110, 25); + timeEdit2->setDisplayFormat("hh:mm:ss.zzz"); + timeEdit2->setMinimumTime(QTime(0, 0, 0, 0)); + timeEdit2->setMaximumTime(time2); + timeEdit2->setTime(time2); + + ratioLabel = new QLabel(averager_dialog); + ratioLabel->setGeometry(20, 155, 100, 75); + ratioLabel->setText("Ratio of time\n" + "before and after\n" + "trigger:"); + + ratioBox = new QComboBox(averager_dialog); + ratioBox->setGeometry(130, 180, 100, 25); + ratioBox->addItem("10 / 90"); + ratioBox->addItem("25 / 75"); + ratioBox->addItem("50 / 50"); + + bufsizeLabel = new QLabel(averager_dialog); + bufsizeLabel->setGeometry(20, 250, 100, 25); + bufsizeLabel->setText("Average period:"); + + avg_periodspinbox = new QDoubleSpinBox(averager_dialog); + avg_periodspinbox->setGeometry(130, 250, 100, 25); + avg_periodspinbox->setDecimals(3); + avg_periodspinbox->setRange(0.01, 300.0); + avg_periodspinbox->setSuffix(" sec"); + avg_periodspinbox->setValue(mainwindow->average_period); + + CloseButton = new QPushButton(averager_dialog); + CloseButton->setGeometry(20, 355, 100, 25); + CloseButton->setText("Cancel"); + + StartButton = new QPushButton(averager_dialog); + StartButton->setGeometry(310, 355, 100, 25); + StartButton->setText("Start"); + + for(i=0; isignalcomps; i++) + { + new QListWidgetItem(mainwindow->signalcomp[i]->signallabel, list); + } + + list->setCurrentRow(0, QItemSelectionModel::Select); + + annot = mainwindow->annotationlist[0]; + + n = annot_nr; + + while(n) + { + annot = annot->next_annotation; + + n--; + } + + strcpy(annot_str, annot->annotation); + remove_trailing_spaces(annot_str); + + annotNameLabel->setText(annot_str); + + QObject::connect(CloseButton, SIGNAL(clicked()), averager_dialog, SLOT(close())); + QObject::connect(StartButton, SIGNAL(clicked()), this, SLOT(startButtonClicked())); + + averager_dialog->exec(); +} + + + +void UI_AveragerWindow::startButtonClicked() +{ + int i, j, n, + avg_cnt=0, + samples_on_screen, + trigger_position_ratio=4, + dialoglistnumber, + itemCnt; + + char str[MAX_ANNOTATION_LEN + 1], + scratchpad[1024]; + + double avg_max_value; + + long long backup_viewtime, + backup_timescale, + l_time1, + l_time2; + + struct annotationblock *annot; + + QList itemList; + + + mainwindow->average_period = avg_periodspinbox->value(); + + itemList = list->selectedItems(); + + itemCnt = itemList.size(); + + if(itemCnt < 1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "You have to select at least one signal."); + messagewindow.exec(); + return; + } + + if(itemCnt > MAXAVERAGECURVEDIALOGS) + { + sprintf(scratchpad,"You can not select more than %i signals.", MAXAVERAGECURVEDIALOGS); + QMessageBox messagewindow(QMessageBox::Critical, "Error", scratchpad); + messagewindow.exec(); + return; + } + + time1 = timeEdit1->time(); + time2 = timeEdit2->time(); + + if(time2.operator<=(time1) == TRUE) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Starttime is higher or equal to stoptime."); + messagewindow.exec(); + return; + } + + l_time1 = (((time1.hour() * 3600) + (time1.minute() * 60) + (time1.second())) * TIME_DIMENSION) + (time1.msec() * TIME_DIMENSION / 1000LL); + l_time2 = (((time2.hour() * 3600) + (time2.minute() * 60) + (time2.second())) * TIME_DIMENSION) + (time2.msec() * TIME_DIMENSION / 1000LL); + + n = ratioBox->currentIndex(); + + switch(n) + { + case 0 : trigger_position_ratio = 10; + break; + case 1 : trigger_position_ratio = 4; + break; + case 2 : trigger_position_ratio = 2; + break; + } + + backup_viewtime = mainwindow->edfheaderlist[0]->viewtime; + + backup_timescale = mainwindow->pagetime; + + mainwindow->pagetime = avg_periodspinbox->value() * TIME_DIMENSION; + + mainwindow->setup_viewbuf(); + + mainwindow->signal_averaging_active = 1; + + for(j=0; javeragecurvedialog[i] == NULL) + { + dialoglistnumber = i; + + break; + } + } + + if(i >= MAXAVERAGECURVEDIALOGS) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Too many \"Average\" windows are open.\nClose some first."); + messagewindow.exec(); + + mainwindow->edfheaderlist[0]->viewtime = backup_viewtime; + mainwindow->pagetime = backup_timescale; + mainwindow->signal_averaging_active = 0; + mainwindow->setup_viewbuf(); + + return; + } + + signal_nr = list->row(itemList.at(j)); + + if(mainwindow->signalcomp[signal_nr]->samples_on_screen > 2147483646LL) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Too many samples in buf."); + messagewindow.exec(); + + mainwindow->edfheaderlist[0]->viewtime = backup_viewtime; + mainwindow->pagetime = backup_timescale; + mainwindow->signal_averaging_active = 0; + mainwindow->setup_viewbuf(); + + return; + } + + samples_on_screen = mainwindow->signalcomp[signal_nr]->samples_on_screen; + + avgbuf = (double *)calloc(1, sizeof(double) * samples_on_screen); + if(avgbuf == NULL) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); + messagewindow.exec(); + + mainwindow->edfheaderlist[0]->viewtime = backup_viewtime; + mainwindow->pagetime = backup_timescale; + mainwindow->signal_averaging_active = 0; + mainwindow->setup_viewbuf(); + + return; + } + + n = edfplus_annotation_count(&mainwindow->annotationlist[0]); + + for(i=0; iannotationlist[0], i); + + strcpy(str, annot->annotation); + + remove_trailing_spaces(str); + + if(!strcmp(str, annot_str)) + { + avg_cnt++; + } + } + + QProgressDialog progress("Averaging ...", "Abort", 0, avg_cnt, averager_dialog); + progress.setWindowModality(Qt::WindowModal); + progress.setMinimumDuration(200); + progress.setValue(0); + + for(i=0; i<10; i++) qApp->processEvents(); + + avg_cnt = 0; + + for(i=0; iannotationlist[0], i); + + if((annot->onset >= l_time1) && (annot->onset <= l_time2)) + { + strcpy(str, annot->annotation); + + remove_trailing_spaces(str); + + if(!strcmp(str, annot_str)) + { + mainwindow->edfheaderlist[0]->viewtime = annot->onset; + + mainwindow->edfheaderlist[0]->viewtime -= (mainwindow->pagetime / trigger_position_ratio); + + mainwindow->setup_viewbuf(); + + process_avg(mainwindow->signalcomp[signal_nr]); + + progress.setValue(++avg_cnt); + } + } + + qApp->processEvents(); + + if(progress.wasCanceled() == TRUE) + { + free(avgbuf); + + mainwindow->edfheaderlist[0]->viewtime = backup_viewtime; + + mainwindow->pagetime = backup_timescale; + + mainwindow->signal_averaging_active = 0; + + mainwindow->setup_viewbuf(); + + return; + } + } + + if(!avg_cnt) + { + progress.reset(); + + sprintf(scratchpad, "The selected annotation/trigger \"%s\" is not in the selected timewindow\n" + "%i:%02i:%02i - %i:%02i:%02i", + annot_str, + timeEdit1->time().hour(), timeEdit1->time().minute(), timeEdit1->time().second(), + timeEdit2->time().hour(), timeEdit2->time().minute(), timeEdit2->time().second()); + + QMessageBox messagewindow(QMessageBox::Critical, "Error", scratchpad); + messagewindow.exec(); + + free(avgbuf); + + mainwindow->edfheaderlist[0]->viewtime = backup_viewtime; + + mainwindow->pagetime = backup_timescale; + + mainwindow->signal_averaging_active = 0; + + mainwindow->setup_viewbuf(); + + return; + } + + avg_max_value = 0.01; + + for(i=0; i avg_max_value) + { + avg_max_value = avgbuf[i]; + } + + if((avgbuf[i] * -1.0) > avg_max_value) + { + avg_max_value = avgbuf[i] * -1.0; + } + } + + avg_max_value *= 1.05; + + mainwindow->averagecurvedialog[dialoglistnumber] = new UI_AverageCurveWindow(mainwindow->signalcomp[signal_nr], mainwindow, dialoglistnumber, + avgbuf, + avg_max_value, + mainwindow->pagetime, + mainwindow->signalcomp[signal_nr]->samples_on_screen, + avg_cnt, + trigger_position_ratio, + annot_str, + avg_periodspinbox->value()); + + for(i=0; isignalcomp[signal_nr]->avg_dialog[i] == 0) + { + mainwindow->signalcomp[signal_nr]->avg_dialog[i] = dialoglistnumber + 1; + + break; + } + } + } + + mainwindow->edfheaderlist[0]->viewtime = backup_viewtime; + + mainwindow->pagetime = backup_timescale; + + mainwindow->signal_averaging_active = 0; + + mainwindow->setup_viewbuf(); + + averager_dialog->close(); +} + + +UI_AveragerWindow::~UI_AveragerWindow() +{ + int i; + + for(i=0; iaveragecurvedialog[i] != NULL) + { + mainwindow->averagecurvedialog[i]->averager_curve_dialog->move(((i % 15) * 30) + 200, ((i % 15) * 30) + 200); + mainwindow->averagecurvedialog[i]->averager_curve_dialog->raise(); + mainwindow->averagecurvedialog[i]->averager_curve_dialog->activateWindow(); + } + } +} + + +void UI_AveragerWindow::process_avg(struct signalcompblock *signalcomp) +{ + int j, k, + temp=0; + + char *viewbuf; + + long long s, s2; + + double dig_value=0.0; + + union { + unsigned int one; + signed int one_signed; + unsigned short two[2]; + signed short two_signed[2]; + unsigned char four[4]; + } var; + + viewbuf = mainwindow->viewbuf; + + if(viewbuf == NULL) + { + return; + } + + if(avgbuf == NULL) + { + return; + } + + for(s=signalcomp->sample_start; ssamples_on_screen; s++) + { + if(s>signalcomp->sample_stop) break; + + dig_value = 0.0; + s2 = s + signalcomp->sample_timeoffset - signalcomp->sample_start; + + for(j=0; jnum_of_signals; j++) + { + if(signalcomp->edfhdr->bdf) + { + var.two[0] = *((unsigned short *)( + viewbuf + + signalcomp->viewbufoffset + + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)) + + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset + + ((s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record) * 3))); + + var.four[2] = *((unsigned char *)( + viewbuf + + signalcomp->viewbufoffset + + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)) + + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset + + ((s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record) * 3) + + 2)); + + if(var.four[2]&0x80) + { + var.four[3] = 0xff; + } + else + { + var.four[3] = 0x00; + } + + temp = var.one_signed; + } + + if(signalcomp->edfhdr->edf) + { + temp = *(((short *)( + viewbuf + + signalcomp->viewbufoffset + + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)) + + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset)) + + (s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)); + } + + temp += signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].offset; + temp *= signalcomp->factor[j]; + + dig_value += temp; + } + + for(k=0; kfilter_cnt; k++) + { + dig_value = first_order_filter(dig_value, signalcomp->filter[k]); + } + + for(k=0; kravg_filter_cnt; k++) + { + if(s==signalcomp->sample_start) + { + ravg_filter_restore_buf(signalcomp->ravg_filter[k]); + } + + dig_value = run_ravg_filter(dig_value, signalcomp->ravg_filter[k]); + } + + for(k=0; kfidfilter_cnt; k++) + { + if(s==signalcomp->sample_start) + { + memcpy(signalcomp->fidbuf[k], signalcomp->fidbuf2[k], fid_run_bufsize(signalcomp->fid_run[k])); + } + + dig_value = signalcomp->fidfuncp[k](signalcomp->fidbuf[k], dig_value); + } + + if(signalcomp->ecg_filter != NULL) + { + if(s==signalcomp->sample_start) + { + ecg_filter_restore_buf(signalcomp->ecg_filter); + } + + dig_value = run_ecg_filter(dig_value, signalcomp->ecg_filter); + } + + avgbuf[s] += (dig_value * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue); + } +} + + + + + + + + + + + + + + + + + + + + + + diff -Nru edfbrowser-1.30/averager_dialog.h edfbrowser-1.38/averager_dialog.h --- edfbrowser-1.30/averager_dialog.h 1970-01-01 00:00:00.000000000 +0000 +++ edfbrowser-1.38/averager_dialog.h 2011-08-23 20:01:14.000000000 +0000 @@ -0,0 +1,128 @@ +/* +*************************************************************************** +* +* Author: Teunis van Beelen +* +* Copyright (C) 2011 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 +* +*************************************************************************** +*/ + + + + +#ifndef AVERAGER_FORM1_H +#define AVERAGER_FORM1_H + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "global.h" +#include "mainwindow.h" +#include "edf_annot_list.h" +#include "averager_curve_wnd.h" +#include "utils.h" + + + +class UI_Mainwindow; + + + +class UI_AveragerWindow : public QObject +{ + Q_OBJECT + +public: + UI_AveragerWindow(QWidget *, int); + + ~UI_AveragerWindow(); + + UI_Mainwindow *mainwindow; + + +private: + +QDialog *averager_dialog; + +QLabel *annotLabel, + *annotNameLabel, + *signalLabel, + *ratioLabel, + *bufsizeLabel, + *time1Label, + *time2Label; + +QPushButton *CloseButton, + *StartButton; + +QListWidget *list; + +QComboBox *ratioBox; + +QTimeEdit *timeEdit1, + *timeEdit2; + +QTime time1, + time2; + +QDoubleSpinBox *avg_periodspinbox; + +char annot_str[MAX_ANNOTATION_LEN + 1]; + +int signal_nr; + +double *avgbuf; + + +void process_avg(struct signalcompblock *); + +private slots: + +void startButtonClicked(); + +}; + + + +#endif // AVERAGER_FORM1_H + + diff -Nru edfbrowser-1.30/bdf2edf.cpp edfbrowser-1.38/bdf2edf.cpp --- edfbrowser-1.30/bdf2edf.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/bdf2edf.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2009, 2010 Teunis van Beelen +* Copyright (C) 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -37,8 +37,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -275,7 +273,8 @@ if(inputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for reading.", inputpath); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); return; } @@ -287,14 +286,16 @@ if(edfhdr==NULL) { fclose(inputfile); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); return; } if(!edfhdr->bdf) { fclose(inputfile); - UI_Messagewindow popuperror("Error", "File is not a BDF file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "File is not a BDF file."); + messagewindow.exec(); free_edfheader(); return; } @@ -342,6 +343,7 @@ void UI_BDF2EDFwindow::StartConversion() { int i, j, k, + datrecs, new_edfsignals, datarecords, len; @@ -413,18 +415,24 @@ } } + datarecords = edfhdr->datarecords; + + QProgressDialog progress("Converting...", "Abort", 0, datarecords, myobjectDialog); + progress.setWindowModality(Qt::WindowModal); + progress.setMinimumDuration(200); + if(!new_edfsignals) { - showpopupmessage("Error", "You must select at least one signal."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "You must select at least one signal."); + messagewindow.exec(); goto END_1; } - datarecords = edfhdr->datarecords; - readbuf = (char *)malloc(edfhdr->recordsize); if(readbuf==NULL) { - showpopupmessage("Error", "Malloc error, (readbuf)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error, (readbuf)."); + messagewindow.exec(); goto END_2; } @@ -454,14 +462,16 @@ if(mainwindow->file_is_opened(outputpath)) { - UI_Messagewindow popuperror("Save file", "Error, selected file is in use."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, selected file is in use."); + messagewindow.exec(); goto END_2; } outputfile = fopeno(outputpath, "wb"); if(outputfile==NULL) { - showpopupmessage("Error", "Can not open outputfile for writing."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open outputfile for writing."); + messagewindow.exec(); goto END_2; } @@ -470,11 +480,14 @@ if(fread(scratchpad, 176, 1, inputfile)!=1) { showpopupmessage("Error", "Read error (1)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Read error (1)."); + messagewindow.exec(); goto END_3; } if(fwrite(scratchpad, 176, 1, outputfile)!=1) { - showpopupmessage("Error", "Write error (1)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Write error (1)."); + messagewindow.exec(); goto END_3; } fprintf(outputfile, "%-8i", new_edfsignals * 256 + 256); @@ -662,17 +675,25 @@ ///////////////////////////// start conversion ////////////////////////////////////// - QApplication::setOverrideCursor(Qt::WaitCursor); - fseeko(inputfile, (long long)(edfhdr->hdrsize), SEEK_SET); - while(datarecords--) + for(datrecs=0; datrecsprocessEvents(); + if(!(datrecs%100)) + { + progress.setValue(datrecs); + + qApp->processEvents(); + + if(progress.wasCanceled() == TRUE) + { + goto END_3; + } + } if(fread(readbuf, edfhdr->recordsize, 1, inputfile) != 1) { - QApplication::restoreOverrideCursor(); + progress.reset(); showpopupmessage("Error", "Read error (2)."); goto END_3; } @@ -683,7 +704,7 @@ { if(fwrite(readbuf + edfhdr->edfparam[signalslist[i]].buf_offset, edfhdr->edfparam[signalslist[i]].smp_per_record * 3, 1, outputfile)!=1) { - QApplication::restoreOverrideCursor(); + progress.reset(); showpopupmessage("Error", "Write error (2)."); goto END_3; } @@ -692,7 +713,7 @@ { if(fputc(0, outputfile)==EOF) { - QApplication::restoreOverrideCursor(); + progress.reset(); showpopupmessage("Error", "Write error (3)."); goto END_3; } @@ -730,7 +751,7 @@ fputc(var2.two_bytes[0], outputfile); if(fputc(var2.two_bytes[1], outputfile)==EOF) { - QApplication::restoreOverrideCursor(); + progress.reset(); showpopupmessage("Error", "Write error (4)."); goto END_3; } @@ -739,7 +760,7 @@ } } - QApplication::restoreOverrideCursor(); + progress.reset(); showpopupmessage("Ready", "Done."); END_3: diff -Nru edfbrowser-1.30/bdf2edf.h edfbrowser-1.38/bdf2edf.h --- edfbrowser-1.30/bdf2edf.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/bdf2edf.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2009, 2010 Teunis van Beelen +* Copyright (C) 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -50,6 +50,8 @@ #include #include #include +#include +#include #include #include diff -Nru edfbrowser-1.30/bdf_triggers.cpp edfbrowser-1.38/bdf_triggers.cpp --- edfbrowser-1.30/bdf_triggers.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/bdf_triggers.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -37,8 +37,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -87,6 +85,11 @@ datarecords = hdr->datarecords; long_data_record_duration = hdr->long_data_record_duration; + if(edfsignals < 1) + { + return(0); + } + if(long_data_record_duration != TIME_DIMENSION) { return(0); @@ -153,14 +156,15 @@ buf = (char *)calloc(1, bufsize); if(buf==NULL) { - UI_Messagewindow popuperror("Error", "Memory allocation error occurred when trying to read triggers.\n" - "(buf)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Memory allocation error occurred when trying to read triggers.\n(buf)"); + messagewindow.exec(); return(1); } if(fseeko(inputfile, ((long long)edfsignals + 1LL) * 256LL, SEEK_SET)) { - UI_Messagewindow popuperror("Error", "An error occurred when reading inputfile triggers."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when reading inputfile triggers."); + messagewindow.exec(); free(buf); return(2); } @@ -189,7 +193,9 @@ if(fseeko(inputfile, (long long)jump_file, SEEK_CUR)) { - UI_Messagewindow popuperror("Error", "An error occurred when reading inputfile triggers."); + QApplication::restoreOverrideCursor(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when reading inputfile triggers."); + messagewindow.exec(); free(buf); return(2); } @@ -197,7 +203,8 @@ if(fread(buf, bufsize, 1, inputfile)!=1) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Error", "An error occurred when reading inputfile triggers."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when reading inputfile triggers."); + messagewindow.exec(); free(buf); return(2); } @@ -211,7 +218,9 @@ annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); if(annotation == NULL) { - UI_Messagewindow popuperror("Error", "Malloc error (annotation)."); + QApplication::restoreOverrideCursor(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error (annotation)."); + messagewindow.exec(); *list = annotlist; free(buf); return(1); @@ -242,7 +251,9 @@ annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); if(annotation == NULL) { - UI_Messagewindow popuperror("Error", "Malloc error (annotation)."); + QApplication::restoreOverrideCursor(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error (annotation)."); + messagewindow.exec(); *list = annotlist; free(buf); return(1); diff -Nru edfbrowser-1.30/bdf_triggers.h edfbrowser-1.38/bdf_triggers.h --- edfbrowser-1.30/bdf_triggers.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/bdf_triggers.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -46,6 +46,7 @@ #include "global.h" #include "popup_messagewindow.h" #include "edf_annot_list.h" +#include diff -Nru edfbrowser-1.30/bi9800.cpp edfbrowser-1.38/bi9800.cpp --- edfbrowser-1.30/bi9800.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/bi9800.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -37,8 +37,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -134,7 +132,8 @@ if(dcmfile==NULL) { snprintf(str, 2048, "Can not open file %s for reading.", path); - UI_Messagewindow popuperror("Error", str); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); return; } @@ -149,7 +148,8 @@ if(evtfile==NULL) { snprintf(str, 2048, "Can not open file %s for reading.", path); - UI_Messagewindow popuperror("Error", str); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); fclose(dcmfile); return; } @@ -190,7 +190,8 @@ case 512 : break; case 1024 : break; - default : UI_Messagewindow popuperror("Error", "Unknown samplerate."); + default : QMessageBox messagewindow(QMessageBox::Critical, "Error", "Unknown samplerate."); + messagewindow.exec(); fclose(dcmfile); fclose(evtfile); return; @@ -207,7 +208,8 @@ if(strcmp(modelnumber_str, "TM SD01G") && strcmp(modelnumber_str, "SD SD02G")) { - UI_Messagewindow popuperror("Error", "Wrong modelnumber."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Wrong modelnumber."); + messagewindow.exec(); fclose(dcmfile); fclose(evtfile); return; @@ -229,7 +231,8 @@ (startdate_month < 1) || (startdate_month > 12) || (startdate_day < 1) || (startdate_day > 31)) { - UI_Messagewindow popuperror("Error", "Wrong recorddate."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Wrong recorddate."); + messagewindow.exec(); fclose(dcmfile); fclose(evtfile); return; @@ -251,7 +254,8 @@ (starttime_minute < 0) || (starttime_minute > 59) || (starttime_second < 0) || (starttime_second > 59)) { - UI_Messagewindow popuperror("Error", "Wrong recordtime."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Wrong recordtime."); + messagewindow.exec(); fclose(dcmfile); fclose(evtfile); return; @@ -267,7 +271,8 @@ if(atoi(str2) != 24) { - UI_Messagewindow popuperror("Error", "Wrong record hours."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Wrong record hours."); + messagewindow.exec(); fclose(dcmfile); fclose(evtfile); return; @@ -283,7 +288,8 @@ !checked_recorddate || !checked_recordtime) { - UI_Messagewindow popuperror("Error", "Missing line."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Missing line."); + messagewindow.exec(); fclose(dcmfile); fclose(evtfile); return; @@ -296,6 +302,8 @@ buf1 = (char *)malloc(bufsize); if(buf1 == NULL) { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error."); + messagewindow.exec(); UI_Messagewindow popuperror("Error", "Malloc error."); fclose(dcmfile); fclose(evtfile); @@ -305,7 +313,8 @@ buf2 = (int *)malloc(bufsize * sizeof(int)); if(buf2 == NULL) { - UI_Messagewindow popuperror("Error", "Malloc error."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error."); + messagewindow.exec(); fclose(dcmfile); fclose(evtfile); free(buf1); @@ -341,7 +350,8 @@ if(hdl<0) { snprintf(str, 2048, "Can not open file %s for writing.", path); - UI_Messagewindow popuperror("Error", str); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); fclose(dcmfile); fclose(evtfile); free(buf1); diff -Nru edfbrowser-1.30/bi9800.h edfbrowser-1.38/bi9800.h --- edfbrowser-1.30/bi9800.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/bi9800.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -44,6 +44,7 @@ #include #include #include +#include #include #include diff -Nru edfbrowser-1.30/biosemi2bdfplus.cpp edfbrowser-1.38/biosemi2bdfplus.cpp --- edfbrowser-1.30/biosemi2bdfplus.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/biosemi2bdfplus.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -125,7 +125,6 @@ hdl_out, edfsignals, status_signal=0, - status_signal_offset=0, status_samples_in_datarecord=0, rising_edge, set_duration, @@ -157,7 +156,8 @@ if(!lineEdit1[i]->text().length()) { sprintf(str, "Trigger Input label %i is empty!", i + 1); - UI_Messagewindow popuperror("Error", str); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); return; } } @@ -171,7 +171,8 @@ if(!strcmp(lineEdit1[i]->text().toLatin1().data(), lineEdit1[j]->text().toLatin1().data())) { sprintf(str, "Trigger Input labels %i and %i are the same!", i + 1, j + 1); - UI_Messagewindow popuperror("Error", str); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); return; } } @@ -222,7 +223,8 @@ default : strcpy(str, "EDFlib: unknown error."); } - UI_Messagewindow popuperror("Error", str); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); return; } @@ -233,21 +235,24 @@ if(hdr.filetype == EDFLIB_FILETYPE_BDFPLUS) { - UI_Messagewindow popuperror("Error", "Selected file is already a BDF-plus file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Selected file is already a BDF-plus file."); + messagewindow.exec(); edfclose_file(hdl_in); return; } if(hdr.filetype != EDFLIB_FILETYPE_BDF) { - UI_Messagewindow popuperror("Error", "Selected file is not a BDF file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Selected file is not a BDF file."); + messagewindow.exec(); edfclose_file(hdl_in); return; } if(hdr.datarecord_duration != EDFLIB_TIME_DIMENSION) { - UI_Messagewindow popuperror("Error", "Datarecord duration of inputfile must be 1 second."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Datarecord duration of inputfile must be 1 second."); + messagewindow.exec(); edfclose_file(hdl_in); return; } @@ -256,7 +261,8 @@ if(edfsignals < 1) { - UI_Messagewindow popuperror("Error", "There are no signals in the selected file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There are no signals in the selected file."); + messagewindow.exec(); edfclose_file(hdl_in); return; } @@ -267,7 +273,8 @@ { if(hdr.signalparam[i].smp_in_datarecord != sf) { - UI_Messagewindow popuperror("Error", "All signals must have the same samplefrequency."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "All signals must have the same samplefrequency."); + messagewindow.exec(); edfclose_file(hdl_in); return; } @@ -301,7 +308,8 @@ if(error) { - UI_Messagewindow popuperror("Error", "Samplefrequency must be 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64 or 32 Hz."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Samplefrequency must be 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64 or 32 Hz."); + messagewindow.exec(); edfclose_file(hdl_in); return; } @@ -318,7 +326,8 @@ if(i == edfsignals) { - UI_Messagewindow popuperror("Error", "There is no Status signal in the selected file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There is no Status signal in the selected file."); + messagewindow.exec(); edfclose_file(hdl_in); return; } @@ -331,8 +340,6 @@ if(i == status_signal) { - status_signal_offset = buf_offset[i]; - status_samples_in_datarecord = hdr.signalparam[i].smp_in_datarecord; } @@ -406,15 +413,16 @@ if(mainwindow->file_is_opened(outputpath)) { - UI_Messagewindow popuperror("Error", "Outputfile is already opened in EDFbrowser.\n" - "Close the file and try again."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Outputfile is already opened in EDFbrowser.\nClose the file and try again."); + messagewindow.exec(); edfclose_file(hdl_in); return; } if(!(strcmp(inputpath, outputpath))) { - UI_Messagewindow popuperror("Error", "Inputfile and outputfile are the same."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Inputfile and outputfile are the same."); + messagewindow.exec(); edfclose_file(hdl_in); return; } @@ -444,7 +452,8 @@ default : strcpy(str, "EDFlib: unknown error."); } - UI_Messagewindow popuperror("Error", str); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); edfclose_file(hdl_in); return; @@ -474,7 +483,8 @@ buf = (int *)malloc(sizeof(int) * status_samples_in_datarecord); if(buf == NULL) { - UI_Messagewindow popuperror("Error", "Malloc error (buf)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error (buf)."); + messagewindow.exec(); edfclose_file(hdl_in); edfclose_file(hdl_out); return; @@ -518,8 +528,9 @@ if(edfread_digital_samples(hdl_in, status_signal, status_samples_in_datarecord, buf) < 0) { - progress.setValue((int)(hdr.datarecords_in_file / 10LL)); - UI_Messagewindow popuperror("Error", "A read error occurred during the collection of triggers."); + progress.reset(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read error occurred during the collection of triggers."); + messagewindow.exec(); edfclose_file(hdl_in); edfclose_file(hdl_out); free(buf); @@ -539,8 +550,9 @@ annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); if(annotation == NULL) { - progress.setValue((int)(hdr.datarecords_in_file / 10LL)); - UI_Messagewindow popuperror("Error", "Malloc error (annotation)."); + progress.reset(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error (annotation)."); + messagewindow.exec(); edfclose_file(hdl_in); edfclose_file(hdl_out); free(buf); @@ -585,8 +597,9 @@ annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); if(annotation == NULL) { - progress.setValue((int)(hdr.datarecords_in_file / 10LL)); - UI_Messagewindow popuperror("Error", "Malloc error (annotation)."); + progress.reset(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error (annotation)."); + messagewindow.exec(); edfclose_file(hdl_in); edfclose_file(hdl_out); free(buf); @@ -629,7 +642,7 @@ } } - progress.setValue((int)(hdr.datarecords_in_file / 10LL)); + progress.reset(); edfwrite_annotation_latin1(hdl_out, 0LL, -1LL, "Recording starts"); @@ -691,7 +704,8 @@ if(edf_set_datarecord_duration(hdl_out, 100000 / samplerate_divider) == -1) { - UI_Messagewindow popuperror("Error", "edf_set_datarecord_duration() returned an error."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "edf_set_datarecord_duration() returned an error."); + messagewindow.exec(); edfclose_file(hdl_in); edfclose_file(hdl_out); return; @@ -705,7 +719,8 @@ buf = (int *)malloc(sizeof(int) * totalSamplesInDatarecord); if(buf == NULL) { - UI_Messagewindow popuperror("Error", "Malloc error (buf)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error (buf)."); + messagewindow.exec(); edfclose_file(hdl_in); edfclose_file(hdl_out); return; @@ -739,8 +754,9 @@ { if(edfread_digital_samples(hdl_in, i, hdr.signalparam[i].smp_in_datarecord, buf + buf_offset[i]) < 0) { - progress.setValue((int)(hdr.datarecords_in_file / 10LL)); - UI_Messagewindow popuperror("Error", "A read error occurred during the conversion."); + progress.reset(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read error occurred during the conversion."); + messagewindow.exec(); edfclose_file(hdl_in); edfclose_file(hdl_out); free(buf); @@ -754,8 +770,9 @@ { if(edfwrite_digital_samples(hdl_out, buf + buf_offset[i] + (j * new_sf)) < 0) { - progress.setValue((int)(hdr.datarecords_in_file / 10LL)); - UI_Messagewindow popuperror("Error", "A write error occurred during the conversion."); + progress.reset(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A write error occurred during the conversion."); + messagewindow.exec(); edfclose_file(hdl_in); edfclose_file(hdl_out); free(buf); @@ -765,7 +782,7 @@ } } - progress.setValue((int)(hdr.datarecords_in_file / 10LL)); + progress.reset(); edfclose_file(hdl_in); edfclose_file(hdl_out); @@ -779,7 +796,8 @@ "\nBDF+ file is located at %s", trigger_cnt, outputpath); #endif - UI_Messagewindow popuperror("Ready", str); + QMessageBox messagewindow(QMessageBox::Information, "Ready", str); + messagewindow.exec(); } diff -Nru edfbrowser-1.30/biosemi2bdfplus.h edfbrowser-1.38/biosemi2bdfplus.h --- edfbrowser-1.30/biosemi2bdfplus.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/biosemi2bdfplus.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -45,6 +45,7 @@ #include #include #include +#include #include #include diff -Nru edfbrowser-1.30/check_edf_file.cpp edfbrowser-1.38/check_edf_file.cpp --- edfbrowser-1.30/check_edf_file.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/check_edf_file.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -37,8 +37,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -52,7 +50,7 @@ -struct edfhdrblock * EDFfileCheck::check_edf_file(FILE *inputfile, char *txt_string) +struct edfhdrblock * EDFfileCheck::check_edf_file(FILE *inputfile, char *txt_string, int live_stream) { int i, j, p, r=0, n, dotposition, @@ -162,7 +160,8 @@ { if((((unsigned char *)scratchpad)[i]<32)||(((unsigned char *)scratchpad)[i]>126)) { - sprintf(txt_string, "Error, %ith character of local patient identification field is not a valid 7-bit ASCII character.", + sprintf(txt_string, "Error, %ith character of local patient identification field is not a valid 7-bit ASCII character.\n" + "Use the header editor to fix your file. Look at the manual for the details.", i + 1); free(edf_hdr); free(edfhdr); @@ -181,7 +180,8 @@ { if((((unsigned char *)scratchpad)[i]<32)||(((unsigned char *)scratchpad)[i]>126)) { - sprintf(txt_string, "Error, %ith character of local recording identification field is not a valid 7-bit ASCII character.", + sprintf(txt_string, "Error, %ith character of local recording identification field is not a valid 7-bit ASCII character.\n" + "Use the header editor to fix your file. Look at the manual for the details.", i + 1); free(edf_hdr); free(edfhdr); @@ -210,7 +210,15 @@ error = 0; - if((edf_hdr[170]!='.')||(edf_hdr[173]!='.')) error = 1; + if((edf_hdr[170]!='.')||(edf_hdr[173]!='.')) + { + sprintf(txt_string, "Error, separator character of startdate is not a dot.\n" + "You can fix this problem with the header editor, check the manual for details."); + free(edf_hdr); + free(edfhdr); + return(NULL); + } + if((edf_hdr[168]<48)||(edf_hdr[168]>57)) error = 1; if((edf_hdr[169]<48)||(edf_hdr[169]>57)) error = 1; if((edf_hdr[171]<48)||(edf_hdr[171]>57)) error = 1; @@ -286,7 +294,15 @@ error = 0; - if((edf_hdr[178]!='.')||(edf_hdr[181]!='.')) error = 1; + if((edf_hdr[178]!='.')||(edf_hdr[181]!='.')) + { + sprintf(txt_string, "Error, separator character of starttime is not a dot.\n" + "You can fix this problem with the header editor, check the manual for details."); + free(edf_hdr); + free(edfhdr); + return(NULL); + } + if((edf_hdr[176]<48)||(edf_hdr[176]>57)) error = 1; if((edf_hdr[177]<48)||(edf_hdr[177]>57)) error = 1; if((edf_hdr[179]<48)||(edf_hdr[179]>57)) error = 1; @@ -413,7 +429,7 @@ { if((scratchpad[i]<32)||(scratchpad[i]>126)) { - sprintf(txt_string, "Error, %ith character of number of bytes in header field is not a valid 7-bit ASCII\ncharacter.", + sprintf(txt_string, "Error, %ith character of number of bytes in header field is not a valid 7-bit ASCII character.", i + 1); free(edf_hdr); free(edfhdr); @@ -500,7 +516,7 @@ { if((scratchpad[i]<32)||(scratchpad[i]>126)) { - sprintf(txt_string, "Error, %ith character of number of datarecords field is not a valid ASCII\ncharacter.", + sprintf(txt_string, "Error, %ith character of number of datarecords field is not a valid ASCII character.", i + 1); free(edf_hdr); free(edfhdr); @@ -518,18 +534,21 @@ } edfhdr->datarecords = atoi(scratchpad); - if(edfhdr->datarecords<1) + if(live_stream == 0) { + if(edfhdr->datarecords<1) + { #ifdef Q_WS_WIN - sprintf(txt_string, "Error, number of datarecords is %I64d, expected >0.", - edfhdr->datarecords); + sprintf(txt_string, "Error, number of datarecords is %I64d, expected >0.", + edfhdr->datarecords); #else - sprintf(txt_string, "Error, number of datarecords is %lli, expected >0.", - edfhdr->datarecords); + sprintf(txt_string, "Error, number of datarecords is %lli, expected >0.", + edfhdr->datarecords); #endif - free(edf_hdr); - free(edfhdr); - return(NULL); + free(edf_hdr); + free(edfhdr); + return(NULL); + } } /********************* DATARECORD DURATION *************************************/ @@ -610,7 +629,8 @@ { if((scratchpad[j]<32)||(scratchpad[j]>126)) { - sprintf(txt_string, "Error, %ith character of label field of signal %i is not a valid 7-bit ASCII character.", + sprintf(txt_string, "Error, %ith character of label field of signal %i is not a valid 7-bit ASCII character.\n" + "Use the header editor to fix your file. Look at the manual for the details.", j + 1, i + 1); free(edf_hdr); @@ -677,7 +697,8 @@ { if((scratchpad[j]<32)||(scratchpad[j]>126)) { - sprintf(txt_string, "Error, %ith character of transducer type field of signal %i is not a valid 7-bit ASCII\ncharacter.", + sprintf(txt_string, "Error, %ith character of transducer type field of signal %i is not a valid 7-bit ASCII character.\n" + "Use the header editor to fix your file. Look at the manual for the details.", j + 1, i + 1); free(edf_hdr); @@ -697,7 +718,8 @@ { if(edfhdr->edfparam[i].transducer[j]!=' ') { - sprintf(txt_string, "Error, transducer type field of EDF annotationchannel must be empty."); + sprintf(txt_string, "Error, transducer type field of EDF annotationchannel must be empty.\n" + "Use the header editor to fix your file. Look at the manual for the details."); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); @@ -714,7 +736,8 @@ { if(edfhdr->edfparam[i].transducer[j]!=' ') { - sprintf(txt_string, "Error, transducer type field of BDF annotationchannel must be empty."); + sprintf(txt_string, "Error, transducer type field of BDF annotationchannel must be empty." + "Use the header editor to fix your file. Look at the manual for the details."); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); @@ -734,7 +757,8 @@ { if((scratchpad[j]<32)||(scratchpad[j]>126)) { - sprintf(txt_string, "Error, %ith character of physical dimension field of signal %i is not a valid\n7-bit ASCII character.", + sprintf(txt_string, "Error, %ith character of physical dimension field of signal %i is not a valid 7-bit ASCII character.\n" + "Use the header editor to fix your file. Look at the manual for the details.", j + 1, i + 1); free(edf_hdr); @@ -758,7 +782,7 @@ { if((scratchpad[j]<32)||(scratchpad[j]>126)) { - sprintf(txt_string, "Error, %ith character of physical minimum field of signal %i is not a valid\n7-bit ASCII character.", + sprintf(txt_string, "Error, %ith character of physical minimum field of signal %i is not a valid 7-bit ASCII character.", j + 1, i + 1); free(edf_hdr); @@ -793,7 +817,7 @@ { if((scratchpad[j]<32)||(scratchpad[j]>126)) { - sprintf(txt_string, "Error, %ith character of physical maximum field of signal %i is not a valid\n7-bit ASCII character.", + sprintf(txt_string, "Error, %ith character of physical maximum field of signal %i is not a valid 7-bit ASCII character.", j + 1, i + 1); free(edf_hdr); @@ -837,7 +861,7 @@ { if((scratchpad[j]<32)||(scratchpad[j]>126)) { - sprintf(txt_string, "Error, %ith character of digital minimum field of signal %i is not a valid 7-bit ASCII\ncharacter.", + sprintf(txt_string, "Error, %ith character of digital minimum field of signal %i is not a valid 7-bit ASCII character.", j + 1, i + 1); free(edf_hdr); @@ -933,7 +957,7 @@ { if((scratchpad[j]<32)||(scratchpad[j]>126)) { - sprintf(txt_string, "Error, %ith character of digital maximum field of signal %i is not a valid\n7-bit ASCII character.", + sprintf(txt_string, "Error, %ith character of digital maximum field of signal %i is not a valid 7-bit ASCII character.", j + 1, i + 1); free(edf_hdr); @@ -1036,7 +1060,8 @@ { if((scratchpad[j]<32)||(scratchpad[j]>126)) { - sprintf(txt_string, "Error, %ith character of prefilter field of signal %i is not a valid\n7-bit ASCII character.", + sprintf(txt_string, "Error, %ith character of prefilter field of signal %i is not a valid 7-bit ASCII character.\n" + "Use the header editor to fix your file. Look at the manual for the details.", j + 1, i + 1); free(edf_hdr); @@ -1054,9 +1079,10 @@ { for(j=0; j<80; j++) { - if(edfhdr->edfparam[i].transducer[j]!=' ') + if(edfhdr->edfparam[i].prefilter[j]!=' ') { - sprintf(txt_string, "Error, prefilter field of EDF annotationchannel must be empty."); + sprintf(txt_string, "Error, prefilter field of EDF annotationchannel must be empty.\n" + "Use the header editor to fix your file. Look at the manual for the details."); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); @@ -1071,9 +1097,10 @@ { for(j=0; j<80; j++) { - if(edfhdr->edfparam[i].transducer[j]!=' ') + if(edfhdr->edfparam[i].prefilter[j]!=' ') { - sprintf(txt_string, "Error, prefilter field of BDF annotationchannel must be empty."); + sprintf(txt_string, "Error, prefilter field of BDF annotationchannel must be empty.\n" + "Use the header editor to fix your file. Look at the manual for the details."); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); @@ -1097,7 +1124,7 @@ { if((scratchpad[j]<32)||(scratchpad[j]>126)) { - sprintf(txt_string, "Error, %ith character of number of samples field of signal %i is not a valid\n7-bit ASCII character.", + sprintf(txt_string, "Error, %ith character of number of samples field of signal %i is not a valid 7-bit ASCII character.", j + 1, i + 1); free(edf_hdr); @@ -1136,21 +1163,31 @@ if(edfhdr->bdf) { edfhdr->recordsize *= 3; + + if(edfhdr->recordsize > 15728640) + { + sprintf(txt_string, "Error, the datarecordsize is %i bytes. The datarecordsize should not exceed 15 MB.", + edfhdr->recordsize); + free(edf_hdr); + free(edfhdr->edfparam); + free(edfhdr); + return(NULL); + } } else { edfhdr->recordsize *= 2; - } -// if((edfhdr->edfplus)&&(edfhdr->recordsize>61440)) -// { -// sprintf(txt_string, "Error, Datarecordsize is %i bytes. The maximum datarecordsize in EDFplus is 61440 bytes.", -// edfhdr->recordsize); -// free(edf_hdr); -// free(edfhdr->edfparam); -// free(edfhdr); -// return(NULL); -// } + if(edfhdr->recordsize > 10485760) + { + sprintf(txt_string, "Error, the datarecordsize is %i bytes. The datarecordsize should not exceed 10 MB.", + edfhdr->recordsize); + free(edf_hdr); + free(edfhdr->edfparam); + free(edfhdr); + return(NULL); + } + } /**************************** RESERVED FIELDS *************************************/ @@ -1161,7 +1198,7 @@ { if((scratchpad[j]<32)||(scratchpad[j]>126)) { - sprintf(txt_string, "Error, %ith character of reserved field of signal %i is not a valid\n7-bit ASCII character.", + sprintf(txt_string, "Error, %ith character of reserved field of signal %i is not a valid 7-bit ASCII character.", j + 1, i + 1); free(edf_hdr); @@ -1565,28 +1602,41 @@ edfhdr->hdrsize = edfhdr->edfsignals * 256 + 256; - l_tmp = edfhdr->recordsize; - l_tmp *= edfhdr->datarecords; - l_tmp += (edfhdr->edfsignals * 256 + 256); + if(live_stream) + { + fseeko(inputfile, 0LL, SEEK_END); + + edfhdr->datarecords = ftello(inputfile); - fseeko(inputfile, 0LL, SEEK_END); - l_tmp2 = ftello(inputfile); + edfhdr->datarecords -= (long long)edfhdr->hdrsize; - if(l_tmp != l_tmp2) + edfhdr->datarecords /= (long long)edfhdr->recordsize; + } + else { + l_tmp = edfhdr->recordsize; + l_tmp *= edfhdr->datarecords; + l_tmp += (edfhdr->edfsignals * 256 + 256); + + fseeko(inputfile, 0LL, SEEK_END); + l_tmp2 = ftello(inputfile); + + if(l_tmp != l_tmp2) + { #ifdef Q_WS_WIN - sprintf(txt_string, "Error, filesize does not match with the calculated filesize based on the parameters\n" - "in the header. Filesize is %I64i and filesize according to header is %I64i.", - l_tmp2, l_tmp); + sprintf(txt_string, "Error, filesize does not match with the calculated filesize based on the parameters\n" + "in the header. Filesize is %I64i and filesize according to header is %I64i.", + l_tmp2, l_tmp); #else - sprintf(txt_string, "Error, filesize does not match with the calculated filesize based on the parameters\n" - "in the header. Filesize is %lli and filesize according to header is %lli.", - l_tmp2, l_tmp); + sprintf(txt_string, "Error, filesize does not match with the calculated filesize based on the parameters\n" + "in the header. Filesize is %lli and filesize according to header is %lli.", + l_tmp2, l_tmp); #endif - free(edf_hdr); - free(edfhdr->edfparam); - free(edfhdr); - return(NULL); + free(edf_hdr); + free(edfhdr->edfparam); + free(edfhdr); + return(NULL); + } } n = 0; diff -Nru edfbrowser-1.30/check_edf_file.h edfbrowser-1.38/check_edf_file.h --- edfbrowser-1.30/check_edf_file.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/check_edf_file.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -53,8 +53,7 @@ public: - struct edfhdrblock * check_edf_file(FILE *, char *); - + struct edfhdrblock * check_edf_file(FILE *, char *, int live_stream=0); private: diff -Nru edfbrowser-1.30/colordialog.cpp edfbrowser-1.38/colordialog.cpp --- edfbrowser-1.30/colordialog.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/colordialog.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/colordialog.h edfbrowser-1.38/colordialog.h --- edfbrowser-1.30/colordialog.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/colordialog.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/debian/changelog edfbrowser-1.38/debian/changelog --- edfbrowser-1.30/debian/changelog 2010-12-07 10:53:34.000000000 +0000 +++ edfbrowser-1.38/debian/changelog 2011-08-29 20:36:36.000000000 +0000 @@ -1,3 +1,19 @@ +edfbrowser (1.38-1) unstable; urgency=low + + * New upstearm version + * Team maintenance in Debian Med team with permission of + original maintainer given in + http://lists.debian.org/debian-med/2011/05/msg00141.html + * Update Standards-Version to 3.9.2 (No changes needed) + * Added Vcs fields + * DM-Upload-Allowed: yes + * omit initial article in short description + * debian/rules: short dh notation to get simply rid of any + lintian warning + * Debhelper 8 (control+compat) + + -- Andreas Tille Mon, 29 Aug 2011 19:27:10 +0200 + edfbrowser (1.30-1) unstable; urgency=low * Update Standards-Version to 3.9.1 (No changes needed) diff -Nru edfbrowser-1.30/debian/compat edfbrowser-1.38/debian/compat --- edfbrowser-1.30/debian/compat 2010-12-07 10:53:34.000000000 +0000 +++ edfbrowser-1.38/debian/compat 2011-08-29 20:36:22.000000000 +0000 @@ -1 +1 @@ -7 +8 diff -Nru edfbrowser-1.30/debian/control edfbrowser-1.38/debian/control --- edfbrowser-1.30/debian/control 2010-12-07 10:53:34.000000000 +0000 +++ edfbrowser-1.38/debian/control 2011-08-29 20:36:18.000000000 +0000 @@ -1,15 +1,20 @@ Source: edfbrowser Section: science Priority: extra -Maintainer: Bas Zoetekouw -Build-Depends: debhelper (>= 7), libqt4-dev, qt4-qmake -Standards-Version: 3.9.1 +Maintainer: Debian Med Packaging Team +Uploaders: Bas Zoetekouw , + Andreas Tille +DM-Upload-Allowed: yes +Build-Depends: debhelper (>= 8), libqt4-dev, qt4-qmake +Standards-Version: 3.9.2 Homepage: http://www.teuniz.net/edfbrowser/ +Vcs-Browser: http://svn.debian.org/wsvn/debian-med/trunk/packages/edfbrowser/trunk/ +Vcs-Svn: svn://svn.debian.org/debian-med/trunk/packages/edfbrowser/trunk/ Package: edfbrowser Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} -Description: a viewer for biosignal storage files such as bdf and edf +Description: viewer for biosignal storage files such as bdf and edf EDFbrowser is a viewer for medical timeseries storage files containing data such as EEG, EMG, and ECG signals. It supports EDF(+) and BDF(+) file formats. diff -Nru edfbrowser-1.30/debian/install edfbrowser-1.38/debian/install --- edfbrowser-1.30/debian/install 1970-01-01 00:00:00.000000000 +0000 +++ edfbrowser-1.38/debian/install 2011-08-29 20:29:15.000000000 +0000 @@ -0,0 +1 @@ +edfbrowser usr/bin diff -Nru edfbrowser-1.30/debian/manpages edfbrowser-1.38/debian/manpages --- edfbrowser-1.30/debian/manpages 1970-01-01 00:00:00.000000000 +0000 +++ edfbrowser-1.38/debian/manpages 2011-08-29 20:36:09.000000000 +0000 @@ -0,0 +1 @@ +debian/*.1 diff -Nru edfbrowser-1.30/debian/rules edfbrowser-1.38/debian/rules --- edfbrowser-1.30/debian/rules 2010-12-07 10:53:34.000000000 +0000 +++ edfbrowser-1.38/debian/rules 2011-08-29 20:23:23.000000000 +0000 @@ -21,9 +21,10 @@ FULLVERSION :=$(word 2,$(shell dpkg-parsechangelog | grep ^Version ) ) UPSTREAMVER :=$(shell echo $(FULLVERSION) | sed 's/-[0-9.]\+$$//' | sed 's/^0~//' ) -build: build-stamp -build-stamp: - dh_testdir +%: + dh $@ + +override_dh_auto_build: qmake-qt4 -makefile -after \ QMAKE_CXXFLAGS="$(QMAKE_CXXFLAGS)" \ QMAKE_CXXFLAGS_RELEASE="$(QMAKE_CXXFLAGS_RELEASE)" @@ -32,44 +33,14 @@ sed -i -e 's/-lpthread//' Makefile $(MAKE) - touch build-stamp -clean: - dh_testdir +override_dh_clean: test ! -f Makefile || $(MAKE) distclean dh_clean -install: build - dh_testdir - dh_testroot - dh_prep - dh_installdirs - install -m 0755 -d debian/edfbrowser/usr/bin/ - install -m 0755 -d debian/edfbrowser/usr/share/doc/edfbrowser/ - install -m 0755 edfbrowser debian/edfbrowser/usr/bin/edfbrowser - install -m 0755 "doc/EDFbrowser manual.html" \ - debian/edfbrowser/usr/share/doc/edfbrowser/manual.html - -# Build architecture-independent files here. -binary-indep: build install -# We have nothing to do - -# Build architecture-dependent files here. -binary-arch: build install - dh_testdir - dh_testroot - dh_installchangelogs +override_dh_installdocs: dh_installdocs - dh_installman debian/edfbrowser.1 - dh_strip - dh_compress - dh_fixperms - dh_link - dh_installdeb - dh_shlibdeps - dh_gencontrol - dh_md5sums - dh_builddeb - -binary: binary-indep binary-arch -.PHONY: build clean binary-indep binary-arch binary install unpack + # rename badly named documentation + install -m 0755 -d debian/$(PKGNAME)/usr/share/doc/$(PKGNAME)/ + install -m 0755 "doc/EDFbrowser manual.html" \ + debian/$(PKGNAME)/usr/share/doc/$(PKGNAME)/manual.html diff -Nru edfbrowser-1.30/doc/EDFbrowser manual.html edfbrowser-1.38/doc/EDFbrowser manual.html --- edfbrowser-1.30/doc/EDFbrowser manual.html 2010-11-24 09:50:00.000000000 +0000 +++ edfbrowser-1.38/doc/EDFbrowser manual.html 2011-08-23 20:01:14.000000000 +0000 @@ -7,14 +7,15 @@ -

EDFbrowser 1.30 manual

+

EDFbrowser 1.38 manual


-Table of Contents
+Table of Contents:
  • Filemenu
  • +
  • Streaming mode
  • Signalsmenu
  • Timescalemenu
  • Amplitudemenu
  • @@ -22,11 +23,15 @@
  • Signaldialog
  • Signalproperties
  • Adjusting the position and size of the signals
  • +
  • Organize signals
  • Navigation
  • Annotations
  • Filters
  • Adjust filters
  • Powerspectrum
  • +
  • Averaging (evoked potentials or other triggers)
  • +
  • ECG heartrate detection
  • +
  • Heart Rate statistics
  • Zoomfunction
  • Floating ruler
  • Crosshairs
  • @@ -37,20 +42,23 @@
  • Calibration
  • Timelock / File synchronisation
  • File info / header / properties
  • +
  • Edit EDF/BDF header
  • EDF(+)/BDF(+) to ASCII format converter
  • Reduce signals and/or duration
  • -
  • Edit EDF/BDF header
  • Export annotations/events
  • Import annotations/events
  • ASCII to EDF/BDF format converter
  • Nihon Kohden to EDF(+) format converter
  • Biosemi to BDF+ format converter
  • Finometer to EDF format converter
  • +
  • Wave to EDF format converter
  • Nexfin to EDF format converter
  • Emsa to EDF+ format converter
  • EDF+D to EDF+C converter
  • BDF(+) to EDF(+) converter
  • EDF(+) and BDF(+) compatibility checker
  • +
  • Print to PDF
  • +
  • Print to image
  • Print to EDF(+)
  • Print to BDF(+)
  • Annotation editor
  • @@ -74,6 +82,23 @@



    +

    Streaming mode

    + +

    + Use the Filemenu to open a stream. The stream must be a "growing" file.
    + This mode is used when you have an aquisitionprogram running that writes EDF or BDF.
    + While the aquisitionprogram writes the data to the file, you can use EDFbrowser to watch
    + (follow) the actual data. EDFbrowser will regularly check the actual filesize and show the
    + last part of the file i.e. the most actual/recent data.
    + The default intervaltime between the updates is 500 milliSeconds and can be changed in the settingsmenu. +

    + +


    + +

    Table of Contents

    + +



    +

    Signalsmenu

    @@ -93,7 +118,9 @@

    Use the Timescalemenu to choose the pagetime (the amount of seconds that must be shown on the screen).
    Be aware that a pagetime of more than five minutes slowsdown the program. Specially when there are
    - many signals on the screen and/or high samplefrequencies. + many signals on the screen and/or high samplefrequencies.
    + "3cm/Sec" will adjust the pagetime so that one second equals 3 cm horizontally. In case you get a different
    + result, calibrate your screen in Menu -> Settings -> Calibration.


    @@ -105,8 +132,11 @@

    Amplitudemenu

    - Use the Amplitudemenu to adjust the amplitude (size/gain) of all signals on the screen.
    - If you want to adjust the amplitude of one particular signal, use Signalproperties. + Use the Amplitudemenu to adjust the amplitude (size/gain/sensitivity) of all signals on the screen.
    + If you want to adjust the amplitude of one particular signal, use Signalproperties.
    + "Fit to pane" will adjust the height and size of all signals so that they will fit on the screen.
    + "Adjust offset" will adjust the height only (of all signals so that they will fit on the screen).
    + "Offset -> 0" will set the offset on the screen of all signals to zero.


    @@ -135,18 +165,18 @@ Use the signaldialog to add one or more signals to the screen. Go to Signals -> Add.
    On top you will see a list of opened files.
    Select (highlight) the file from which you want to add signals. At the left part of the dialog you see a list of
    - all the signals which are in the selected file. Select one or more signals and click on the "Add signals"
    + all the signals which are in the selected file. Select one or more signals and click on the "Add signal(s)"
    button. Now you will see the selected signals on the screen. You can add more signals afterwards,
    just go to Signals -> Add.

    - When you want to make a combination (subtraction) of two or more signals, do as follows. Open the signalsdialog.
    + When you want to make a combination (derivation) of two or more signals, do as follows. Open the signalsdialog.
    Select the file from which you want to add signals. In this example we choose an EEG file which contains
    the signals "P3" and "C3" and we want to subtract "C3" from "P3".
    - Select (highlight) the signal "P3".
    - Click on the "Add" button.
    - Select (highlight) the signal "C3".
    - Click on the "Subtract" button.
    - - Click on the "Display Combination" button.
    + - Click on the "Make derivation" button.
    - The result of "P3" minus "C3" will appear on the screen.

    Now you can add more combinations or simply close the dialog.
    @@ -158,7 +188,8 @@ - have the same sensitivity (e.g. uV/bit)

    note 2: If you want to invert the signals (which is common in EEG) do as follows:
    - instead of P3 - C3, use -P3 + C3 (or C3 - P3). + instead of P3 - C3, use -P3 + C3 (or C3 - P3).
    + You can also invert a signal afterwards, go to Signals -> Organize.


    @@ -204,11 +235,26 @@



    +

    Organize signals

    + +

    + You can organize the signals via Signals -> Organize.
    + Here you can change the order of the signals on the screen, remove or invert signals. +

    + +


    + +

    Table of Contents

    + +



    +

    Navigation

    Navigation throug a file can be done by using the PageUp/PageDown buttons on your keyboard.
    - Use the Arrowkeys to shift the screen one tenth of the pagetime. + Use the Arrowkeys to shift the screen one tenth of the pagetime. The mousewheel can be used to
    + scroll horizontally. The stepsize of the mousewheel can be set in the settings menu.
    + A value of zero disables mousewheel scrolling.


    @@ -237,15 +283,19 @@

    Use the filtermenu to add or remove filters. First select the type of filter: highpass, lowpass, notch, bandpass or bandstop.
    - Now select the model: Butterworth, Chebyshev or Bessel (a notchfilter has resonator model only).
    - Then set the frequency(s) of the filter.
    + Now select the model: Butterworth, Chebyshev, Bessel or "moving average" (a notchfilter has resonator model only).
    + Then set the frequency(s) of the filter (or number of samples in case of a "moving average" filter).
    Depending on the type and model of the filter, you can adjust the order, Q-factor and passbandripple.

    - The curve will show the frequency and phase response of the filter.

    + The curve will show the frequency and phase response of the filter (except for "moving average" filters).

    Now select one or more signals to apply to and click the "Apply" button.

    - Reviewing the filters can be done in the "Montage" -> "View this montage" menu. + Reviewing the filters can be done in the Montage -> View this montage menu.

    + + Algorithm for the moving average filters:
    + LPF: the mean of the last n data samples.
    + HPF: last-n/2 sample minus the mean of the last n data samples.


    @@ -301,13 +351,96 @@



    +

    Averaging (evoked potentials or other triggers)

    + +

    + Averaging waveforms (multiple parts of a signal) can be done by rightclicking on an annotation (trigger) in
    + the annotationlist. A contextmenu will be opened, now click on "Average".
    + The timescale (datablocksize) of the averaging window will be equal to the timescale of the mainwindow.
    + So, if you want to average 20 seconds, set the timescale to 20 first.
    + A dialog will be opened where you can choose to which signal you want to apply the averaging.
    + If necessary, change the "From"- and "To"-times in order to select a particular group of triggers.
    + Only the triggers with an onsettime that lies between the two timevalues will be used for the averaging.
    + Select the ratio of the time before and after the triggerpoint. For example, if the timescale of the mainwindow
    + is set to 20 seconds and you select a 10/90 ratio, averaging will start 2 seconds before the triggerpoint and
    + stops at 18 seconds after the triggerpoint.
    + Now click on "Start" and a new window will be opened which will show the result of averaging
    + all signalparts of all annotations (triggerpoints) with that specific name.
    + The yellow colored, dashed, vertical line is the triggerpoint, i.e. the onsettime of the annotations (triggers).
    + Use the sliders to zoom into the signal. The timescale is relative to the trigger (onset) point.
    +
    + The result can be printed or exported as a new EDF/BDF file.
    +
    + You can also use external triggers in ASCII(*.csv or *.txt) or XML format.
    + See Import annotations/events how to import triggers/events/annotations.
    +
    + Note: It is also possible to change the selection of annotations/triggers for averaging, by editing the annotationlist first. +

    + +


    + +

    Table of Contents

    + +



    + +

    ECG heart rate detection

    + +

    + Toggling the "Heart Rate" button toggles on or off the detection and calculation of the heartrate
    + expressed in beats per minute (bpm).
    + The "Heart Rate" button can be found in the Signalproperties dialog. +
    + The algorithm used for the heartrate detection is derived from "Real time electrocardiogram QRS detection using combined adaptive threshold"
    + by Ivaylo I Christov. http://www.biomedical-engineering-online.com/content/3/1/28
    +
    + The R-onset times and/or RR-interval times (beat to beat) can be exported to an ascii-file for analysis in other programs (Kubios).
    + After you switched on the Heart Rate detection, go to "Tools -> Export ECG RR-interval to ASCII".
    + Only the part of the signal that is visible on the screen will be exported. So, first make the part of the file
    + that you want to export visible by navigating through the file and adjusting the Timescale.
    +
    + Some statistics about the Heart Rate (variability) are available here.
    +
    + Important: before using the Heart Rate detection, go to the settings menu (Settings -> Other) and adjust the "Powerline Frequency" to the frequency used in the country
    + where the recording of the ECG took place (50 or 60 Hz). Otherwise the powerline noise suppression filter in the Heart Rate detection algorithm will not work correctly. +

    + +


    + +

    Table of Contents

    + +



    + +

    Heart Rate statistics

    + +

    + When the ECG heart rate detection is enabled, you can view some statistics about the
    + Heart Rate (variability) in the Signalproperties. Once you see the Signalproperties dialog,
    + click on the "Statistics" button. A brief description of the statistics:
    +
    + - Mean, the average of the RR-intervals.
    + - SDNN, the standard deviation of RR-intervals.
    + - RMSSD, the square root of the mean squared difference of successive RR's.
    + - NN50, the number of pairs of successive RR's that differ by more than 50 ms.
    + - pNN50, the proportion of NN50 divided by total number of RR's as a percentage.
    +
    + The data used for the statistics is derived from the timewindow that is visible on the screen. +

    + +


    + +

    Table of Contents

    + +



    +

    Zoomfunction

    There are two ways to zoom-in:

    - - By pressing (several times) Ctrl++ or Ctrl+-.

    - + - By pressing (several times) Ctrl++ or Ctrl+-.
    +
    + or
    +
    - You can zoom into a signal/curve on the screen by drawing a rectangle with the mouse.
    Keep the left mousebutton pressed and move the mousepointer in the direction of the
    right lower corner. When you release the left mousebutton, the content of the rectangle
    @@ -329,7 +462,7 @@

    You can use a floating ruler for measurements. Leftclick on the signallabel of the signal
    of interest. A small dialog will appear. Click on Ruler. A floating ruler will appear.
    - Drag and drop the ruler with the left mousebutton. Rightclick to remove the ruler.
    + Drag and drop the ruler with the left mousebutton. Rightclick to remove the ruler or press the "Esc" key.
    Note: the ruler will appear only when the Timescaletime (pagetime) is set between 2 and 60 seconds
    AND when the amplitude (size/gain) is set between 1 and 2000.

    @@ -347,7 +480,7 @@ of the signal of interest. A small dialog will appear. Click on Crosshair. A crosshair will
    appear. Drag and drop the crosshair with the left mousebutton. Now you can add another crosshair.
    The second crosshair will show you the differences (delta) in time and value of the signal(s).
    - Rightclick to remove the crosshair(s). + Rightclick to remove the crosshair(s) or press the "Esc" key.


    @@ -374,10 +507,11 @@

    Montages can be used to store information about which signals should be shown on
    - the screen, what combinations (subtractions) should be made and other properties
    - like filters, amplitude and color. Once you have loaded a file for review and
    - you have added all the signals you want (and/or all the combinations/subtractions) and
    - you have adjusted amplitude and colors and/or filters, you can save them as a montage.
    + the screen, what combinations (derivations) should be made and other properties
    + like filters, amplitude (sensitivity), offset, color and pagetime (timescale).
    + Once you have loaded a file for review and you have added all the signals you want
    + (and/or all the combinations/derivations) and you have adjusted amplitude and colors
    + and/or filters, you can save them as a montage.
    Go to Montage -> Save. A dialog will be opened where you can choose a directory
    and filename to store your montage.
    Next time when you load a file, you can load a montage via Montage -> Load.
    @@ -391,7 +525,7 @@
    You can bind the F1 to F8 keys to eight different montages. This way you can quickly switch
    between different montages by pressing key F1, F2, etc.
    - Go to Montage -> Edit key-bindings for montages. + Go to Montage -> Edit key-bindings for montages.


    @@ -464,6 +598,8 @@
    - Userdefined synchronizing

    + When this setting is selected, only the signals from the file that has the
    + "time reference" will move when you navigate.
    Use this option when you want to align two or more files manually.


    @@ -497,6 +633,29 @@



    +

    Edit EDF/BDF header

    + +

    + This tool can be used to edit (or anonymize) the header (file info) like subject, birthdate, etc.
    + You can also edit labels (signalnames), physical dimension, pre-filter and transducer names.
    + Warning, always make a backupcopy of the file before using this tool!
    + If the file you want to edit has been opened in EDFbrowser already, close it first before starting
    + this tool.
    + This tool can also be used to repair a file that can not be opened with EDFbrowser because of
    + invalid characters in the header (the EDF format allows 7-bit ascii characters only) or other errors.
    + Do as follows: In EDFbrowser go to Tools -> Edit EDF/BDF header. Select the file. Now click on the
    + "save" button (do not edit the content!). Close the header editor. Now open the file in EDFbrowser.
    +
    + Note: some older programs that export EDF contain a bug that causes to write an invalid time-stamp
    + into the EDF-header (a colon instead of a dot between the numbers). This can be fixed with this tool as well. +

    + +


    + +

    Table of Contents

    + +



    +

    EDF(+)/BDF(+) to ASCII format converter

    @@ -555,26 +714,6 @@



    -

    Edit EDF/BDF header

    - -

    - This tool can be used to edit (or anonymize) the header (file info) like subject, birthdate, etc.
    - You can also edit labels (signalnames), physical dimension, pre-filter and transducer names.
    - Warning, always make a backupcopy of the file before using this tool!
    - If the file you want to edit has been opened in EDFbrowser already, close it first before starting
    - this tool.
    - This tool can also be used to repair a file that can not be opened with EDFbrowser because of
    - invalid characters in the header (the EDF format allows 7-bit ascii characters only).
    - Do as follows: In EDFbrowser go to "Edit EDF/BDF header". Select the file. Now click on the
    - "save" button (do not edit the content!). Close the header editor. Now open the file in EDFbrowser. -

    - -


    - -

    Table of Contents

    - -



    -

    Export annotations/events

    @@ -595,7 +734,23 @@

    Import annotations/events

    - This tool imports annotations/events. The inputfile can be ASCII (CSV) or XML.
    + This tool imports annotations/events. The inputfile can be ASCII (CSV), XML, EDF+ or BDF+.
    + It's also possible to use a triggersignal in a dc-coupled channel/signal.
    +

    +

    ASCII

    +

    + An ASCII-file must be organised in rows and columns.
    + In the import dialog, set the separatorcharacter (the character that separates the columns),
    + for example: "tab" (tabulator) or "," (comma).
    + Also, set the columnnumber of the onsettime and the description/label.
    + If the file starts with a header, adjust the "Data starts at line" spinbox
    + in order to skip these lines.
    + If there's only one column in the ascii/txt file (with onset time values), check the
    + "Manual description" button and enter a description. This description will be used for all
    + annotations that will be imported from that ascii/txt file. +

    +

    XML

    +

    XML-files need to be encoded either in ISO-8859-1 or UTF-8 character encoding.
    The root element name must be "annotationlist", child elements must be named "annotation".
    Inside the element "annotation" are the elements "onset", "duration" and "description".
    @@ -622,8 +777,54 @@ </annotation> </annotationlist> -
    - Note: You have to open an EDF/BDF file first in order to be able to import annotations/events. +

    + Note: You have to open an EDF/BDF file first in order to be able to import annotations/events.
    +

    +

    DC-events / DC-triggers

    +

    + A "DC-event" consist of a positive impulse (startbit) followed by eight databits and a stopbit (lowlevel).
    + This signal is recorded onto a dc-coupled inputchannel of the hardware during aquisition.
    + The eight databits are used to identify a maximum of 256 different types of events/triggers.
    + The startbit has always a high level and the stopbit has always a lowlevel.
    + At idle the signal should stay at low level.
    + The following example shows a dc-event with decimal code 170:
    +

    +                  onsettime of the event
    +                  |                               bittime
    +                  |                               |<->|
    +                  v                               |   |
    + 1 Volt           +---+   +---+   +---+   +---+   +---+
    +                  |   |   |   |   |   |   |   |   |   |
    +                  |   |   |   |   |   |   |   |   |   |<--triggerlevel = 0.5 Volt
    +                  |   |   |   |   |   |   |   |   |   |
    + 0 Volt ----------+   +---+   +---+   +---+   +---+   +---+--------------
    +            ^       ^   ^   ^   ^   ^   ^   ^   ^   ^   ^
    +            |       |   |   |   |   |   |   |   |   |   |
    +            idle    |   |   |   |   |   |   |   |   |   stopbit, always low
    +                    |   |   |   |   |   |   |   |   db7
    +                    |   |   |   |   |   |   |   db6
    +                    |   |   |   |   |   |   db5
    +                    |   |   |   |   |   db4
    +                    |   |   |   |   db3
    +                    |   |   |   db2
    +                    |   |   db1
    +                    |   db0
    +                    startbit, always high
    +
    +

    + The binary code in the example is 01010101 which is 170 decimal.
    + The rising edge of the startbit represents the time of the event (for example, an evoked potential).
    + The voltage levels can be freely chosen. In the importdialog adjust the triggerlevel to a level that is equal
    + to: (lowlevel + highlevel) / 2.
    + Also, set the bittime used for the DC-event.
    + Note that the intervaltime between two consegutive events must be more than ten times the bittime.
    +
    + It is possible not to use the code but just only the startbit. In that case all triggers will have the code "0".
    + In that case you can use a simple on/off pulse as a trigger.
    +
    + Note: The signal which contains the DC-event must be put on the screen in order to be available in the selectionscreen.
    + Also, the signal must be unipolar, i.e. not a derivation. Next, the detectionalgorithm of the triggers in this signal will bypass
    + any filters.


    @@ -697,7 +898,7 @@ If you expect higher values in your ascii-file, use the multiplier. For example,
    set the multiplier to 0.1, 0.01 or 0.001, etc.

    - Note 3: If you think that, later, you want to make subtractions (for example P4 - C4 in EEG applications),
    + Note 3: If you think that, later, you want to make derivations (for example P4 - C4 in EEG applications),
    make sure that the signals have the same value in the physical maximum field.

    @@ -721,6 +922,9 @@
    In case you have only the nihonkohdenfile.eeg you can not convert to EDF+.
    It is still possible to convert to EDF. In that case there will be no annotations/events and patientinfo.
    +
    + Note: In case you changed the default electrodenames in the Nihon Kohden aquisition software,
    + you need also the *.21e file which contains the electrode names (labels).


    @@ -734,10 +938,10 @@

    This tool converts a Biosemi data file to BDF+ and makes it possible to visualize the
    trigger interrupts and the "new epoch" in EDFbrowser.
    - The Status signal of the Biosemi datafile which contains the trigger inputs will be
    + The Status signal of the Biosemi datafile which contains the input triggers will be
    converted to annotations in the BDF+ format. The original file will not be altered.
    Instead, a copy of the file will be made in the BDF+ format which will contain annotations
    - extracted from the Status signal (which contains the trigger interrupts).
    + extracted from the Status signal (which contains the input triggers).
    The original Status signal will be preserved in the new file.
    You'll find the Biosemi to BDF+ converter in the Tools-menu.

    @@ -747,11 +951,11 @@ Limitations:

    - - The maximum number of annotations (trigger input events) in the new file
    + - The maximum number of annotations (input triggers) in the new file
      is: duration of file in seconds multiplied by 32. If the original file contains more
      trigger input events, they will be ignored.
    -   If, for example, the duration of a file is 5 minutes, the first 9600 trigger input
    -   events will be converted to BDF+ annotations.

    +   If, for example, the duration of a file is 5 minutes, the first 9600 input triggers
    +   will be converted to BDF+ annotations.

    - The precision of the annotations is limited to 100 microSeconds (0.0001 sec.).

    @@ -800,6 +1004,22 @@



    +

    Wave to EDF converter

    + +

    + This tool converts a Waveform Audio File (*.wav) to EDF.
    + The converter accepts 8, 16 and 24 bit wave files.
    + It accepts 1 to 256 channels and samplerates from 1 Hz to 500000 Hz.
    + 8 and 16 bit wave files will be converted to EDF. 24 bit wave files will be
    + converted to BDF. Compressed files are not supported. +

    + +


    + +

    Table of Contents

    + +



    +

    Nexfin to EDF converter

    @@ -919,6 +1139,30 @@



    +

    Print to PDF

    + +

    + You can print/export to PDF in File -> Print -> to PDF +

    + +


    + +

    Table of Contents

    + +



    + +

    Print to image

    + +

    + You can print/export to an image in File -> Print -> to Image +

    + +


    + +

    Table of Contents

    + +



    +

    Print to EDF

    @@ -930,16 +1174,16 @@ signals.
    It is also possible to extract one or more signals from one (or more) files into a new file.

    - This function is located in File->Print menu.
    + This function is located in File -> Print menu.

    The following rules apply:

    - - the length (duration) of the new file will be equal to the selected displaytime (pagetime)
    + - the length (duration) of the new file will be equal to the selected displaytime (timescale)

    - - combined signals (subtractions) will become one signal like they are on your screen
    + - combined signals (derivations) will become one signal like they are on your screen

    - in case of multple files, the new file will get the subject, recording, date and time
    - of the file that has the reference at the moment of printing.
    + of the file that has the reference at the moment of printing.
    You can select the reference in the Time-menu

    - if (one of) the file(s) is of type EDF+, the outputfile will be an EDF+ file as well,
    @@ -961,7 +1205,7 @@

    The option "Print to BDF" creates a new BDF-file which will contain the signals
    - (and annotations) as they are on your screen, in the same way like the "Print to EDF" function,
    + (and annotations) as they are on your screen, in the same way like the Print to EDF function,
    except that it is also possible to print EDF(+) files to BDF. You can even mix
    EDF and BDF files onto your screen and print them to a new BDF file.

    @@ -976,7 +1220,7 @@

    The annotation editor can be used to add, remove or edit annotations.
    - Start the editor via menu -> Window -> Annotation editor.
    + Start the editor via menu -> Window -> Annotation editor.
    To create a new annotation, write the text of the annotation in the description window and set
    the onset time. You can set the duration time as well. If the duration time is unknown or not
    applicable, set it to the value -1. Now click on the create button.

    @@ -991,7 +1235,7 @@ To delete an annotation, click on the annotation in the annotation window and click
    on the delete button.

    - When you are finished editing annotations, save the file in menu -> File -> Save.
    + When you are finished editing annotations, save the file in menu -> File -> Save.
    Your file will not be altered, instead a copy of your file with the edited annotations
    will be made.

    @@ -1039,28 +1283,38 @@


    + + Q. When I try to open a file, I get the error message "Can not open file for reading".
    +
    + A. Check the path to your file. Are there any non-ascii characters in the file- or directorynames?
    + (non-ascii characters are characters like ã ü ö é ç ä etc.)
    + If so, remove those non-ascii characters and try to open the file again.
    +
    +
    Q. How do I add signals to the screen?

    @@ -1103,9 +1357,17 @@ A. Try to find out what program created that file. Write the maker/developer of that
    program and tell him/her that the program does not produce valid EDF(+)/BDF(+) files.
    Ask him/her to fix that program.
    + If you get the message that a character in the header is not a valid ASCII-character,
    + use the header editor to repair your file.

    + Q. How can I combine multiple EDF/BDF files?
    +
    + A. Use the Print to EDF function.
    +
    +
    + Q. What is the difference between EDF and BDF?

    A. The difference is the resolution. In EDF the maximum resolution is 16 bits, so the ratio
    @@ -1117,7 +1379,7 @@ you will lose information.


    - + Q. When I print a file, the borders are cut away (the first characters of the signallabels are missing).

    A. In the printerdialog, choose "landscape" and the right papersize (A4) and
    @@ -1125,55 +1387,55 @@ For example, set top and bottom margins to 0.85 cm and the left and right margins to 1.27 cm.


    - + Q. When I print to a PDF file, the traces look grey instead of black when I open the file
    in Adobe Reader 8.x.

    A. In Adobe Reader, go to Edit->Preferences->Page Display and uncheck "Smooth line art".


    - + Q. Why are the annotationmarkers not visible?

    A. Go to the Settings menu. Check "Annotation marker" and make sure that it
    has a different color than the background color.


    - + Q. The amplitude settings are not correct. For example, 100 uV/cm is 100 uV/1.5 cm.

    A. This can happen when the DPI-settings of the operatingsystem are wrong. For example,
    - when it can not read your monitorsettings or when the monitorsettings are wrong.
    + when EDFbrowser can not read your monitorsettings or when the monitorsettings are wrong.
    You can solve this as follows. Go to the settingsmenu and open the Calibration tab and
    check the "Manually override automatic DPI settings" checkbox. Now measure the two black
    rectangles, enter the values and click on the apply button.


    - + Q. What are the system requirements?

    A. There are no special requirements. However, the faster your CPU and the more memory,
    the faster you can navigate. For example, a large pagetime (five minutes or more) will make
    the responsetime of the program longer, specially when you add a lot of signals and/or
    - when the samplerate is high.
    + when the signals have a high samplerate.
    When you open a file with a size of hundred megabytes and you choose to make the whole
    recording visible on the screen, the program will load the whole file (hundred megabytes)
    - into memory.
    + into memory (RAM).


    - + Q. Which operatingsystems are supported?

    - A. Linux and Windows 2000/XP. The source can be compiled on the Mac.
    + A. Linux and Windows 2000/XP/Vista/7. The source can be compiled on the Mac.


    - + Q. Which license is used for the program?

    A. The GNU General Public License version 2. For more info go to Help -> About EDFbrowser.


    - + Q. I think I found a bug. Where do I report it?

    A. First check if you are using the latest version of EDFbrowser.
    diff -Nru edfbrowser-1.30/ecg_export.cpp edfbrowser-1.38/ecg_export.cpp --- edfbrowser-1.30/ecg_export.cpp 1970-01-01 00:00:00.000000000 +0000 +++ edfbrowser-1.38/ecg_export.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -0,0 +1,301 @@ +/* +*************************************************************************** +* +* Author: Teunis van Beelen +* +* Copyright (C) 2011 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 "ecg_export.h" + + + +#if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) + +#define fopeno fopen + +#else + +#define fseeko fseeko64 +#define ftello ftello64 +#define fopeno fopen64 + +#endif + + + + +UI_ECGExport::UI_ECGExport(QWidget *parent) +{ + mainwindow = (UI_Mainwindow *)parent; + + myobjectDialog = new QDialog(parent); + + myobjectDialog->setMinimumSize(QSize(400, 445)); + myobjectDialog->setMaximumSize(QSize(400, 445)); + myobjectDialog->setWindowTitle("Export RR-intervals"); + myobjectDialog->setModal(TRUE); + myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, TRUE); + + list = new QListWidget(myobjectDialog); + list->setGeometry(20, 20, 130, 350); + list->setSelectionBehavior(QAbstractItemView::SelectRows); + list->setSelectionMode(QAbstractItemView::SingleSelection); + + groupBox1 = new QGroupBox(myobjectDialog); + groupBox1->setGeometry(170, 20, 210, 120); + groupBox1->setTitle("Output format"); + + radioButton1 = new QRadioButton("RR interval"); + radioButton2 = new QRadioButton("R Onset + RR interval"); + radioButton3 = new QRadioButton("R Onset"); + radioButton2->setChecked(TRUE); + + vbox1 = new QVBoxLayout; + vbox1->addWidget(radioButton1); + vbox1->addWidget(radioButton2); + vbox1->addWidget(radioButton3); + + groupBox1->setLayout(vbox1); + + startButton = new QPushButton(myobjectDialog); + startButton->setGeometry(20, 400, 100, 25); + startButton->setText("Export"); + + cancelButton = new QPushButton(myobjectDialog); + cancelButton->setGeometry(280, 400, 100, 25); + cancelButton->setText("Cancel"); + + load_signalcomps(); + + QObject::connect(cancelButton, SIGNAL(clicked()), myobjectDialog, SLOT(close())); + QObject::connect(startButton, SIGNAL(clicked()), this, SLOT(Export_RR_intervals())); + + myobjectDialog->exec(); +} + + + +void UI_ECGExport::Export_RR_intervals() +{ + int i, + len, + signal_nr, + type=-1, + beat_cnt; + + char path[1024], + str[2048]; + + double *beat_interval_list; + + long long *beat_onset_list, + datrecs, + smpls_left, + l_time; + + struct signalcompblock *signalcomp; + + + FILE *outputfile; + + QList selectedlist; + + + selectedlist = list->selectedItems(); + + if(selectedlist.size() < 1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Select a signal first."); + messagewindow.exec(); + return; + } + + signal_nr = selectedlist.at(0)->data(Qt::UserRole).toInt(); + + if((signal_nr < 0) || (signal_nr >= mainwindow->signalcomps)) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Invalid signalcomp number"); + messagewindow.exec(); + return; + } + + signalcomp = mainwindow->signalcomp[signal_nr]; + + if(signalcomp->ecg_filter == NULL) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Heart Rate detection is not activated for the selected signal."); + messagewindow.exec(); + return; + } + + beat_cnt = ecg_filter_get_beat_cnt(signalcomp->ecg_filter); + + beat_onset_list = ecg_filter_get_onset_beatlist(signalcomp->ecg_filter); + + beat_interval_list = ecg_filter_get_interval_beatlist(signalcomp->ecg_filter); + + if(beat_cnt < 4) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, not enough beats."); + messagewindow.exec(); + return; + } + + path[0] = 0; + if(mainwindow->recent_savedir[0]!=0) + { + strcpy(path, mainwindow->recent_savedir); + strcat(path, "/"); + } + len = strlen(path); + get_filename_from_path(path + len, signalcomp->edfhdr->filename, 1024 - len); + remove_extension_from_filename(path); + strcat(path, "_RR_interval.txt"); + + strcpy(path, QFileDialog::getSaveFileName(0, "Export RR-interval to ASCII", path, "Text files (*.txt *.TXT)").toLatin1().data()); + + if(!strcmp(path, "")) + { + return; + } + + get_directory_from_path(mainwindow->recent_savedir, path, 1024); + + outputfile = fopeno(path, "wb"); + if(outputfile==NULL) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, can not open outputfile for writing."); + messagewindow.exec(); + return; + } + + if(radioButton1->isChecked() == TRUE) + { + type = 1; + } + + if(radioButton2->isChecked() == TRUE) + { + type = 2; + } + + if(radioButton3->isChecked() == TRUE) + { + type = 3; + } + + if(type == 1) + { + for(i=0; iedfhdr->viewtime; + + if(l_time < 0LL) + { + l_time = 0LL; + } + + datrecs = beat_onset_list[i] / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record; + + smpls_left = beat_onset_list[i] % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record; + + l_time += (datrecs * signalcomp->edfhdr->long_data_record_duration); + + l_time += ((smpls_left * signalcomp->edfhdr->long_data_record_duration) / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record); + + l_time += (mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime - signalcomp->edfhdr->viewtime); + + if(type == 2) + { + fprintf(outputfile, "%.4f\t%.4f\n", ((double)l_time) / TIME_DIMENSION, beat_interval_list[i]); + } + + if(type == 3) + { + fprintf(outputfile, "%.4f\n", ((double)l_time) / TIME_DIMENSION); + } + } + } + + fclose(outputfile); + + myobjectDialog->close(); + + sprintf(str, "Done. The R-onsets and/or RR-intervals are exported to:\n\n%s", path); + QMessageBox messagewindow(QMessageBox::Information, "Ready", str); + messagewindow.exec(); +} + + +void UI_ECGExport::load_signalcomps(void) +{ + int i; + + QListWidgetItem *item; + + list->clear(); + + for(i=0; isignalcomps; i++) + { + item = new QListWidgetItem; + item->setText(mainwindow->signalcomp[i]->signallabel); + item->setData(Qt::UserRole, QVariant(i)); + list->addItem(item); + } +} + + + + + + + + + + + + + + + + + + + + + + diff -Nru edfbrowser-1.30/ecg_export.h edfbrowser-1.38/ecg_export.h --- edfbrowser-1.30/ecg_export.h 1970-01-01 00:00:00.000000000 +0000 +++ edfbrowser-1.38/ecg_export.h 2011-08-23 20:01:14.000000000 +0000 @@ -0,0 +1,114 @@ +/* +*************************************************************************** +* +* Author: Teunis van Beelen +* +* Copyright (C) 2011 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 +* +*************************************************************************** +*/ + + + + +#ifndef ECGEXPORTCLASS_H +#define ECGEXPORTCLASS_H + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "global.h" +#include "mainwindow.h" +#include "viewcurve.h" +#include "utils.h" + + + + +class UI_Mainwindow; +class ViewCurve; + + + +class UI_ECGExport : public QObject +{ + Q_OBJECT + +public: + UI_ECGExport(QWidget *parent); + + UI_Mainwindow *mainwindow; + + +private: + +QDialog *myobjectDialog; + +QListWidget *list; + +QPushButton *startButton, + *cancelButton; + +QGroupBox *groupBox1; + +QVBoxLayout *vbox1; + +QRadioButton *radioButton1, + *radioButton2, + *radioButton3; + +void load_signalcomps(void); + +private slots: + +void Export_RR_intervals(); + +}; + + + +#endif + + + + diff -Nru edfbrowser-1.30/ecg_filter.cpp edfbrowser-1.38/ecg_filter.cpp --- edfbrowser-1.30/ecg_filter.cpp 1970-01-01 00:00:00.000000000 +0000 +++ edfbrowser-1.38/ecg_filter.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -0,0 +1,687 @@ +/* +*************************************************************************** +* +* Author: Teunis van Beelen +* +* Copyright (C) 2011 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. +* +*************************************************************************** +* +* The current version of GPL is at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt +* +*************************************************************************** +*/ + + + + +#include "ecg_filter.h" + + + +#define ECG_FILTER_STAT_BUFSIZE 262144 + + + + +struct ecg_filter_settings * create_ecg_filter(double sf, double bitval, int powerlinefreq) +{ + int i; + + double d_tmp; + + struct ecg_filter_settings *settings; + + if(sf < 99.9) return(NULL); + + if((powerlinefreq != 50) && (powerlinefreq != 60)) return(NULL); + + settings = (struct ecg_filter_settings *) calloc(1, sizeof(struct ecg_filter_settings)); + if(settings==NULL) return(NULL); + + d_tmp = sf / (double)powerlinefreq; + settings->avgfilter_50_size = d_tmp; + if((d_tmp - settings->avgfilter_50_size) > 0.5) settings->avgfilter_50_size++; + + d_tmp = sf / 35.0; + settings->avgfilter_35_size = d_tmp; + if((d_tmp - settings->avgfilter_35_size) > 0.5) settings->avgfilter_35_size++; + + d_tmp = sf / 25.0; + settings->avgfilter_25_size = d_tmp; + if((d_tmp - settings->avgfilter_25_size) > 0.5) settings->avgfilter_25_size++; + + settings->avgfilter_50_idx = 0; + settings->avgfilter_35_idx = 0; + settings->avgfilter_25_idx = 0; + + settings->avgfilter_50_buf = (double *)calloc(1, settings->avgfilter_50_size * sizeof(double)); + if(settings->avgfilter_50_buf == NULL) + { + free(settings); + + return(NULL); + } + settings->avgfilter_50_buf_bu = (double *)calloc(1, settings->avgfilter_50_size * sizeof(double)); + if(settings->avgfilter_50_buf_bu == NULL) + { + free(settings->avgfilter_50_buf); + free(settings); + + return(NULL); + } + settings->avgfilter_35_buf = (double *)calloc(1, settings->avgfilter_35_size * sizeof(double)); + if(settings->avgfilter_35_buf == NULL) + { + free(settings->avgfilter_50_buf); + free(settings->avgfilter_50_buf_bu); + free(settings); + + return(NULL); + } + settings->avgfilter_35_buf_bu = (double *)calloc(1, settings->avgfilter_35_size * sizeof(double)); + if(settings->avgfilter_35_buf_bu == NULL) + { + free(settings->avgfilter_50_buf); + free(settings->avgfilter_50_buf_bu); + free(settings->avgfilter_35_buf); + free(settings); + + return(NULL); + } + settings->avgfilter_25_buf = (double *)calloc(1, settings->avgfilter_25_size * sizeof(double)); + if(settings->avgfilter_25_buf == NULL) + { + free(settings->avgfilter_50_buf); + free(settings->avgfilter_50_buf_bu); + free(settings->avgfilter_35_buf); + free(settings->avgfilter_35_buf_bu); + free(settings); + + return(NULL); + } + settings->avgfilter_25_buf_bu = (double *)calloc(1, settings->avgfilter_25_size * sizeof(double)); + if(settings->avgfilter_25_buf_bu == NULL) + { + free(settings->avgfilter_50_buf); + free(settings->avgfilter_50_buf_bu); + free(settings->avgfilter_35_buf); + free(settings->avgfilter_35_buf_bu); + free(settings->avgfilter_25_buf); + free(settings); + + return(NULL); + } + + settings->SV_idx = 0; + for(i=0; i<3; i++) + { + settings->SV[i] = 0.0; + } + settings->M_startslope = sf * 0.2; + settings->M_endslope = sf * 1.2; + settings->smpl_n = 0; + for(i=0; i<5; i++) + { + settings->M[i] = 0.0; + } + settings->M_avg = 0.0; + settings->M_idx = 0; + settings->drain = 0.0; + settings->top = 0.0; + settings->runin = 3 * sf; + settings->sf = sf; + + settings->F_size = 0.35 * sf; + settings->F_wd = 0.05 * sf; + settings->F_value = 0.0; + settings->F_idx = 0; + settings->F = (double *)calloc(1, settings->F_size * sizeof(double)); + if(settings->F == NULL) + { + free(settings->avgfilter_50_buf); + free(settings->avgfilter_50_buf_bu); + free(settings->avgfilter_35_buf); + free(settings->avgfilter_35_buf_bu); + free(settings->avgfilter_25_buf); + free(settings); + + return(NULL); + } + settings->F_bu = (double *)calloc(1, settings->F_size * sizeof(double)); + if(settings->F_bu == NULL) + { + free(settings->avgfilter_50_buf); + free(settings->avgfilter_50_buf_bu); + free(settings->avgfilter_35_buf); + free(settings->avgfilter_35_buf_bu); + free(settings->avgfilter_25_buf); + free(settings->F); + free(settings); + + return(NULL); + } + + for(i=0; i<5; i++) + { + settings->R[i] = sf; + } + settings->R_idx = 0; + settings->R_avg = sf; + settings->R_value = 0.0; + + settings->bu_filled = 0; + + settings->bpm = 60.0; + + settings->bitvalue = bitval; + + settings->stat_buf_idx = 0; + + settings->sample_cntr = 0; + + settings->stat_buf = (double *)malloc(sizeof(double) * ECG_FILTER_STAT_BUFSIZE); + if(settings->stat_buf == NULL) + { + free(settings->avgfilter_50_buf); + free(settings->avgfilter_50_buf_bu); + free(settings->avgfilter_35_buf); + free(settings->avgfilter_35_buf_bu); + free(settings->avgfilter_25_buf); + free(settings->F); + free(settings->F_bu); + free(settings); + + return(NULL); + } + + settings->stat_smpl_buf = (long long *)malloc(sizeof(long long) * ECG_FILTER_STAT_BUFSIZE); + if(settings->stat_smpl_buf == NULL) + { + free(settings->avgfilter_50_buf); + free(settings->avgfilter_50_buf_bu); + free(settings->avgfilter_35_buf); + free(settings->avgfilter_35_buf_bu); + free(settings->avgfilter_25_buf); + free(settings->F); + free(settings->F_bu); + free(settings->stat_buf); + free(settings); + + return(NULL); + } + + return(settings); +} + + +double run_ecg_filter(double new_sample, struct ecg_filter_settings *settings) +{ + int i, j; + + double new_input, + max_value, + result; + + +/* running average filter 1 */ + + settings->avgfilter_50_buf[settings->avgfilter_50_idx] = new_sample; + + settings->avgfilter_50_idx++; + + if(settings->avgfilter_50_idx >= settings->avgfilter_50_size) + { + settings->avgfilter_50_idx = 0; + } + + settings->avgfilter_50_mean = 0.0; + + for(i=0; iavgfilter_50_size; i++) + { + settings->avgfilter_50_mean += settings->avgfilter_50_buf[i]; + } + + settings->avgfilter_50_mean /= settings->avgfilter_50_size; + +/* running average filter 2 */ + + settings->avgfilter_35_buf[settings->avgfilter_35_idx] = settings->avgfilter_50_mean; + + settings->avgfilter_35_idx++; + + if(settings->avgfilter_35_idx >= settings->avgfilter_35_size) + { + settings->avgfilter_35_idx = 0; + } + + settings->avgfilter_35_mean = 0.0; + + for(i=0; iavgfilter_35_size; i++) + { + settings->avgfilter_35_mean += settings->avgfilter_35_buf[i]; + } + + settings->avgfilter_35_mean /= settings->avgfilter_35_size; + +/* running average filter 3 */ + + settings->avgfilter_25_buf[settings->avgfilter_25_idx] = settings->avgfilter_35_mean; + + settings->avgfilter_25_idx++; + + if(settings->avgfilter_25_idx >= settings->avgfilter_25_size) + { + settings->avgfilter_25_idx = 0; + } + + settings->avgfilter_25_mean = 0.0; + + for(i=0; iavgfilter_25_size; i++) + { + settings->avgfilter_25_mean += settings->avgfilter_25_buf[i]; + } + + settings->avgfilter_25_mean /= settings->avgfilter_25_size; + +/* spatial velocity filter */ + + settings->SV[settings->SV_idx] = settings->avgfilter_25_mean; + + new_input = settings->SV[settings->SV_idx] - settings->SV[(settings->SV_idx + 1) % 3]; + + if(++settings->SV_idx >= 3) settings->SV_idx = 0; + + if(new_input < 0.0) new_input *= -1.0; + + settings->F[settings->F_idx++] = new_input; + settings->F_idx %= settings->F_size; + + max_value = 0.0; + for(i=0; iF_wd; i++) + { + j = (settings->F_idx + settings->F_size - i - 1) % settings->F_size; + + if(settings->F[j] > max_value) + { + max_value = settings->F[j]; + } + } + result = max_value; + + max_value = 0.0; + for(i=0; iF_wd; i++) + { + j = (settings->F_idx + i) % settings->F_size; + + if(settings->F[j] > max_value) + { + max_value = settings->F[j]; + } + } + result -= max_value; + + settings->F_value += (result / 150.0); + +//////////////////////////////////////////////// + + if(settings->runin) + { + if(new_input > settings->top) + { + settings->top = new_input; + } + + if(settings->runin == 1) + { + for(i=0; i<5; i++) + { + settings->M[i] = settings->top * 0.5; + } + + settings->M_avg = settings->top * 0.5; + + settings->drain = settings->top * 0.2 / settings->sf; + + settings->smpl_n = settings->M_startslope; + +/* printf("-> settings->drain is %f\n", settings->drain); + + printf("-> settings->M_avg is %f\n", settings->M_avg);*/ + } + + settings->runin--; + + settings->sample_cntr++; + + return(settings->bpm / settings->bitvalue); + } + + if((settings->smpl_n > settings->R_startslope) && (settings->smpl_n < settings->R_endslope)) + { + settings->R_value -= (settings->drain * 0.7); + } + + if(settings->smpl_n < settings->M_startslope) + { + if(new_input > settings->top) + { + settings->top = new_input; + +/* printf("new_input is %f\n", new_input);*/ + } + + settings->sample_cntr++; + + settings->smpl_n++; + } + else + { + if(settings->smpl_n == settings->M_startslope) + { + settings->top *= 0.6; + +// printf("settings->top is %f\n", settings->top); + + if(settings->top > (1.5 * settings->M[settings->M_idx])) + { + settings->top = 1.1 * settings->M[settings->M_idx]; + } + + settings->M[settings->M_idx++] = settings->top; + + settings->M_idx %= 5; + + settings->M_avg = (settings->M[0] + settings->M[1] + settings->M[2] + settings->M[3] + settings->M[4]) / 5.0; + + settings->drain = settings->M_avg * 0.4 / settings->sf; + +/* printf("settings->top is %f\n", settings->top); + + printf("settings->M_avg is %f\n", settings->M_avg); + + printf("settings->drain is %f\n", settings->drain);*/ + } + + if(new_input > (settings->M_avg + settings->F_value + settings->R_value)) // beat detected? + { + settings->top = new_input; + + settings->R[settings->R_idx++] = settings->smpl_n; + +// printf("beat detected: settings->top is %f\n", settings->top); +// +// printf("beat detected: settings->smpl_n is %i\n", settings->smpl_n); + + settings->R_idx %= 5; + + settings->R_avg = (settings->R[0] + settings->R[1] + settings->R[2] + settings->R[3] + settings->R[4]) / 5; + + settings->R_value = 0.0; + + settings->R_startslope = 0.667 * settings->R_avg; + + settings->R_endslope = settings->R_avg; + + settings->bpm = (settings->sf * 60.0) / settings->smpl_n; + + if(settings->stat_buf_idx < (ECG_FILTER_STAT_BUFSIZE - 1)) + { + settings->stat_buf[settings->stat_buf_idx] = ((double)settings->smpl_n) / settings->sf; + + if(settings->stat_buf_idx > 0) + { + settings->stat_smpl_buf[settings->stat_buf_idx] = settings->stat_smpl_buf[settings->stat_buf_idx - 1] + settings->sample_cntr; + } + else + { + settings->stat_smpl_buf[settings->stat_buf_idx] = settings->sample_cntr; + } + + settings->stat_buf_idx++; + } + + settings->sample_cntr = 1; + + settings->smpl_n = 1; + } + else + { + if(settings->smpl_n < settings->M_endslope) + { + settings->M_avg -= settings->drain; + } + + settings->sample_cntr++; + + settings->smpl_n++; + } + } + +// return(settings->M_avg + settings->F_value + settings->R_value); // debug: check ecg detection treshold +// return(settings->M_avg); // debug: check ecg detection treshold +// return(settings->F_value); // debug: check ecg detection treshold +// return(settings->R_value); // debug: check ecg detection treshold + + return(settings->bpm / settings->bitvalue); +} + + +void ecg_filter_save_buf(struct ecg_filter_settings *settings) +{ + int i; + + + settings->avgfilter_50_idx_bu = settings->avgfilter_50_idx; + memcpy(settings->avgfilter_50_buf_bu, settings->avgfilter_50_buf, sizeof(double) * settings->avgfilter_50_size); + settings->avgfilter_50_mean_bu = settings->avgfilter_50_mean; + + settings->avgfilter_35_idx_bu = settings->avgfilter_35_idx; + memcpy(settings->avgfilter_35_buf_bu, settings->avgfilter_35_buf, sizeof(double) * settings->avgfilter_35_size); + settings->avgfilter_35_mean_bu = settings->avgfilter_35_mean; + + settings->avgfilter_25_idx_bu = settings->avgfilter_25_idx; + memcpy(settings->avgfilter_25_buf_bu, settings->avgfilter_25_buf, sizeof(double) * settings->avgfilter_25_size); + settings->avgfilter_25_mean_bu = settings->avgfilter_25_mean; + + settings->runin_bu = settings->runin; + + for(i=0; i<3; i++) + { + settings->SV_bu[i] = settings->SV[i]; + } + settings->SV_idx_bu = settings->SV_idx; + + settings->smpl_n_bu = settings->smpl_n; + for(i=0; i<5; i++) + { + settings->M_bu[i] = settings->M[i]; + settings->R_bu[i] = settings->R[i]; + } + settings->M_idx_bu = settings->M_idx; + settings->M_avg_bu = settings->M_avg; + settings->drain_bu = settings->drain; + settings->top_bu = settings->top; + for(i=0; iF_size; i++) + { + settings->F_bu[i] = settings->F[i]; + } + settings->F_idx_bu = settings->F_idx; + settings->F_value_bu = settings->F_value; + settings->R_idx_bu = settings->R_idx; + settings->R_avg_bu = settings->R_avg; + settings->R_value_bu = settings->R_value; + settings->R_startslope_bu = settings->R_startslope; + settings->R_endslope_bu = settings->R_endslope; + settings->bpm_bu = settings->bpm; + + settings->bu_filled = 1; +} + + +void ecg_filter_restore_buf(struct ecg_filter_settings *settings) +{ + int i; + + + settings->stat_buf_idx = 0; + + settings->sample_cntr = 0; + + if(settings->bu_filled == 0) return; + + settings->avgfilter_50_idx = settings->avgfilter_50_idx_bu; + memcpy(settings->avgfilter_50_buf, settings->avgfilter_50_buf_bu, sizeof(double) * settings->avgfilter_50_size); + settings->avgfilter_50_mean = settings->avgfilter_50_mean_bu; + + settings->avgfilter_35_idx = settings->avgfilter_35_idx_bu; + memcpy(settings->avgfilter_35_buf, settings->avgfilter_35_buf_bu, sizeof(double) * settings->avgfilter_35_size); + settings->avgfilter_35_mean = settings->avgfilter_35_mean_bu; + + settings->avgfilter_25_idx = settings->avgfilter_25_idx_bu; + memcpy(settings->avgfilter_25_buf, settings->avgfilter_25_buf_bu, sizeof(double) * settings->avgfilter_25_size); + settings->avgfilter_25_mean = settings->avgfilter_25_mean_bu; + + settings->runin = settings->runin_bu; + + for(i=0; i<3; i++) + { + settings->SV[i] = settings->SV_bu[i]; + } + settings->SV_idx = settings->SV_idx_bu; + + settings->smpl_n = settings->smpl_n_bu; + for(i=0; i<5; i++) + { + settings->M[i] = settings->M_bu[i]; + settings->R[i] = settings->R_bu[i]; + } + settings->M_idx = settings->M_idx_bu; + settings->M_avg = settings->M_avg_bu; + settings->drain = settings->drain_bu; + settings->top = settings->top_bu; + for(i=0; iF_size; i++) + { + settings->F[i] = settings->F_bu[i]; + } + settings->F_idx = settings->F_idx_bu; + settings->F_value = settings->F_value_bu; + settings->R_idx = settings->R_idx_bu; + settings->R_avg = settings->R_avg_bu; + settings->R_value = settings->R_value_bu; + settings->R_startslope = settings->R_startslope_bu; + settings->R_endslope = settings->R_endslope_bu; + settings->bpm = settings->bpm_bu; +} + + +void reset_ecg_filter(struct ecg_filter_settings *settings) +{ + int i; + + + settings->avgfilter_50_idx = 0; + settings->avgfilter_35_idx = 0; + settings->avgfilter_25_idx = 0; + + memset(settings->avgfilter_50_buf, 0, settings->avgfilter_50_size * sizeof(double)); + memset(settings->avgfilter_35_buf, 0, settings->avgfilter_35_size * sizeof(double)); + memset(settings->avgfilter_25_buf, 0, settings->avgfilter_25_size * sizeof(double)); + + settings->SV_idx = 0; + for(i=0; i<3; i++) + { + settings->SV[i] = 0.0; + } + settings->smpl_n = 0; + for(i=0; i<5; i++) + { + settings->M[i] = 0.0; + } + settings->M_avg = 0.0; + settings->M_idx = 0; + settings->drain = 0.0; + settings->top = 0.0; + settings->runin = 3 * settings->sf; + + settings->F_value = 0.0; + settings->F_idx = 0; + memset(settings->F, 0, settings->F_size * sizeof(double)); + + for(i=0; i<5; i++) + { + settings->R[i] = settings->sf; + } + settings->R_idx = 0; + settings->R_avg = settings->sf; + settings->R_value = 0.0; + + settings->bu_filled = 0; + + settings->bpm = 60.0; + + settings->stat_buf_idx = 0; + + settings->sample_cntr = 0; +} + + +void free_ecg_filter(struct ecg_filter_settings *settings) +{ + free(settings->avgfilter_50_buf); + free(settings->avgfilter_50_buf_bu); + free(settings->avgfilter_35_buf); + free(settings->avgfilter_35_buf_bu); + free(settings->avgfilter_25_buf); + free(settings->F); + free(settings->F_bu); + free(settings->stat_buf); + free(settings->stat_smpl_buf); + free(settings); +} + + +int ecg_filter_get_beat_cnt(struct ecg_filter_settings *settings) +{ + return(settings->stat_buf_idx); +} + + +long long * ecg_filter_get_onset_beatlist(struct ecg_filter_settings *settings) +{ + return(settings->stat_smpl_buf); +} + + +double * ecg_filter_get_interval_beatlist(struct ecg_filter_settings *settings) +{ + return(settings->stat_buf); +} + + + + + + + + + + + diff -Nru edfbrowser-1.30/ecg_filter.h edfbrowser-1.38/ecg_filter.h --- edfbrowser-1.30/ecg_filter.h 1970-01-01 00:00:00.000000000 +0000 +++ edfbrowser-1.38/ecg_filter.h 2011-08-23 20:01:14.000000000 +0000 @@ -0,0 +1,148 @@ +/* +*************************************************************************** +* +* Author: Teunis van Beelen +* +* Copyright (C) 2011 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 +* +*************************************************************************** +*/ + + + + + + + +#ifndef ecg_filter_INCLUDED +#define ecg_filter_INCLUDED + + + +#include +#include +#include + + + + + +struct ecg_filter_settings{ + int avgfilter_50_size; + double *avgfilter_50_buf; + int avgfilter_50_idx; + double avgfilter_50_mean; + double *avgfilter_50_buf_bu; + int avgfilter_50_idx_bu; + double avgfilter_50_mean_bu; + + int avgfilter_35_size; + double *avgfilter_35_buf; + int avgfilter_35_idx; + double avgfilter_35_mean; + double *avgfilter_35_buf_bu; + int avgfilter_35_idx_bu; + double avgfilter_35_mean_bu; + + int avgfilter_25_size; + double *avgfilter_25_buf; + int avgfilter_25_idx; + double avgfilter_25_mean; + double *avgfilter_25_buf_bu; + int avgfilter_25_idx_bu; + double avgfilter_25_mean_bu; + + double SV[3]; + int SV_idx; + double SV_bu[3]; + int SV_idx_bu; + + int runin; + int runin_bu; + int M_startslope; + int M_endslope; + int smpl_n; + double M[5]; + int M_idx; + double M_avg; + double drain; + double top; + double sf; + double *F; + int F_size; + int F_idx; + int F_wd; + double F_value; + int R[5]; + int R_idx; + int R_avg; + double R_value; + int R_startslope; + int R_endslope; + double bpm; + double bitvalue; + + int M_startslope_bu; + int M_endslope_bu; + int smpl_n_bu; + double M_bu[5]; + int M_idx_bu; + double M_avg_bu; + double drain_bu; + double top_bu; + double *F_bu; + int F_idx_bu; + double F_value_bu; + int R_bu[5]; + int R_idx_bu; + int R_avg_bu; + double R_value_bu; + int R_startslope_bu; + int R_endslope_bu; + double bpm_bu; + int bu_filled; + + double *stat_buf; + long long *stat_smpl_buf; + int stat_buf_idx; + int sample_cntr; +}; + + + +struct ecg_filter_settings * create_ecg_filter(double, double, int); +double run_ecg_filter(double, struct ecg_filter_settings *); +void free_ecg_filter(struct ecg_filter_settings *); +void ecg_filter_save_buf(struct ecg_filter_settings *); +void ecg_filter_restore_buf(struct ecg_filter_settings *); +void reset_ecg_filter(struct ecg_filter_settings *); +int ecg_filter_get_beat_cnt(struct ecg_filter_settings *); +long long * ecg_filter_get_onset_beatlist(struct ecg_filter_settings *); +double * ecg_filter_get_interval_beatlist(struct ecg_filter_settings *); +#endif + + + + + diff -Nru edfbrowser-1.30/edf_annotations.cpp edfbrowser-1.38/edf_annotations.cpp --- edfbrowser-1.30/edf_annotations.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/edf_annotations.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -37,8 +37,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -230,8 +228,8 @@ cnv_buf = (char *)calloc(1, recordsize); if(cnv_buf==NULL) { - UI_Messagewindow popuperror("Error", "Memory allocation error occurred when trying to read annotations.\n" - "(cnv_buf)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Memory allocation error occurred when trying to read annotations.\n(cnv_buf)"); + messagewindow.exec(); return(1); } @@ -247,8 +245,8 @@ scratchpad = (char *)calloc(1, max_tal_ln + 3); if(scratchpad==NULL) { - UI_Messagewindow popuperror("Error", "Memory allocation error occurred when trying to read annotations.\n" - "(scratchpad)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Memory allocation error occurred when trying to read annotations.\n(scratchpad)"); + messagewindow.exec(); free(cnv_buf); return(1); } @@ -256,8 +254,8 @@ time_in_txt = (char *)calloc(1, max_tal_ln + 3); if(time_in_txt==NULL) { - UI_Messagewindow popuperror("Error", "Memory allocation error occurred when trying to read annotations.\n" - "(time_in_txt)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Memory allocation error occurred when trying to read annotations.\n(time_in_txt)"); + messagewindow.exec(); free(cnv_buf); free(scratchpad); return(1); @@ -266,8 +264,8 @@ duration_in_txt = (char *)calloc(1, max_tal_ln + 3); if(duration_in_txt==NULL) { - UI_Messagewindow popuperror("Error", "Memory allocation error occurred when trying to read annotations.\n" - "(duration_in_txt)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Memory allocation error occurred when trying to read annotations.\n(duration_in_txt)"); + messagewindow.exec(); free(cnv_buf); free(scratchpad); free(time_in_txt); @@ -276,7 +274,8 @@ if(fseeko(inputfile, (long long)((edfsignals + 1) * 256), SEEK_SET)) { - UI_Messagewindow popuperror("Error", "An error occurred when reading inputfile annotations."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when reading inputfile annotations."); + messagewindow.exec(); free(cnv_buf); free(scratchpad); free(time_in_txt); @@ -295,7 +294,8 @@ if(fread(cnv_buf, recordsize, 1, inputfile)!=1) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Error", "An error occurred when reading inputfile annotations."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading inputfile annotations."); + messagewindow.exec(); free(cnv_buf); free(scratchpad); free(time_in_txt); @@ -442,12 +442,14 @@ { if(r||annots_in_record) { - if(n) + if(n >= 0) { new_annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); if(new_annotation==NULL) { - UI_Messagewindow popuperror("Error", "Memory allocation error occurred while reading annotations."); + QApplication::restoreOverrideCursor(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred while reading annotations."); + messagewindow.exec(); free(cnv_buf); free(scratchpad); free(time_in_txt); @@ -545,8 +547,9 @@ if(error) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Error", "Can not read annotations because there is an EDF or BDF incompatibility in this file.\n" - "For more information, run the EDF/BDF compatibility checker in the Tools menu."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not read annotations because there is an EDF or BDF incompatibility in this file.\n" + "For more information, run the EDF/BDF compatibility checker in the Tools menu."); + messagewindow.exec(); free(cnv_buf); free(scratchpad); free(time_in_txt); diff -Nru edfbrowser-1.30/edf_annotations.h edfbrowser-1.38/edf_annotations.h --- edfbrowser-1.30/edf_annotations.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/edf_annotations.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -38,6 +38,7 @@ #include +#include #include #include diff -Nru edfbrowser-1.30/edf_annot_list.c edfbrowser-1.38/edf_annot_list.c --- edfbrowser-1.30/edf_annot_list.c 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/edf_annot_list.c 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -332,5 +332,170 @@ } +int get_tal_timestamp_digit_cnt(struct edfhdrblock *hdr) +{ + int timestamp_digits; + + char scratchpad[256]; + + long long time; + + + if(hdr==NULL) + { + return(-1); + } + + if((hdr->edfplus==0)&&(hdr->bdfplus==0)) + { + return(-1); + } + + time = (hdr->datarecords * hdr->long_data_record_duration) / TIME_DIMENSION; + +#ifdef _WIN32 + timestamp_digits = snprintf(scratchpad, 256, "%I64d", time); +#else + timestamp_digits = snprintf(scratchpad, 256, "%lli", time); +#endif + + return(timestamp_digits); +} + + +int get_tal_timestamp_decimal_cnt(struct edfhdrblock *hdr) +{ + int i, j, + timestamp_decimals; + + + if(hdr==NULL) + { + return(-1); + } + + if((hdr->edfplus==0)&&(hdr->bdfplus==0)) + { + return(-1); + } + + j = 10; + + for(timestamp_decimals=7; timestamp_decimals>0; timestamp_decimals--) + { + if(hdr->long_data_record_duration % j) + { + break; + } + + j *= 10; + } + + j = 10; + + for(i=7; i>0; i--) + { + if(hdr->starttime_offset % j) + { + break; + } + + j *= 10; + } + + if(i > timestamp_decimals) + { + timestamp_decimals = i; + } + + return(timestamp_decimals); +} + + +int get_max_annotation_strlen(struct annotationblock **list) +{ + int j, + len, + annot_descr_len=0, + annot_duration_len=0, + timestamp_digits=0, + timestamp_decimals=0; + + char scratchpad[256]; + + struct annotationblock *annot; + + + annot = list[0]; + + if(annot==NULL) + { + return(0); + } + + while(annot!=NULL) + { +#ifdef _WIN32 + len = snprintf(scratchpad, 256, "%I64d", annot->onset / TIME_DIMENSION); +#else + len = snprintf(scratchpad, 256, "%lli", annot->onset / TIME_DIMENSION); +#endif + + if(len > timestamp_digits) + { + timestamp_digits = len; + } + + j = 10; + + for(len=7; len>0; len--) + { + if(annot->onset % j) + { + break; + } + + j *= 10; + } + + if(len > timestamp_decimals) + { + timestamp_decimals = len; + } + + len = strlen(annot->annotation); + + if(len>annot_descr_len) + { + annot_descr_len = len; + } + + len = strlen(annot->duration); + + if(len>annot_duration_len) + { + annot_duration_len = len; + } + + annot = annot->next_annotation; + } + + if(annot_duration_len) + { + annot_duration_len++; + } + + if(timestamp_decimals) + { + timestamp_decimals++; + } + + return(annot_descr_len + annot_duration_len + timestamp_digits + timestamp_decimals + 4); +} + + + + + diff -Nru edfbrowser-1.30/edf_annot_list.h edfbrowser-1.38/edf_annot_list.h --- edfbrowser-1.30/edf_annot_list.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/edf_annot_list.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -45,14 +45,18 @@ #endif -void edfplus_annotation_add_item(struct annotationblock **list, struct annotationblock *annotation); -void edfplus_annotation_add_copy(struct annotationblock **list, struct annotationblock *annotation); -int edfplus_annotation_count(struct annotationblock **list); -void edfplus_annotation_delete(struct annotationblock **list, int); -void edfplus_annotation_delete_list(struct annotationblock **list); -struct annotationblock * edfplus_annotation_item(struct annotationblock **list, int); -void edfplus_annotation_sort(struct annotationblock **list); -struct annotationblock * edfplus_annotation_copy_list(struct annotationblock **list); +void edfplus_annotation_add_item(struct annotationblock **, struct annotationblock *); +void edfplus_annotation_add_copy(struct annotationblock **, struct annotationblock *); +int edfplus_annotation_count(struct annotationblock **); +void edfplus_annotation_delete(struct annotationblock **, int); +void edfplus_annotation_delete_list(struct annotationblock **); +struct annotationblock * edfplus_annotation_item(struct annotationblock **, int); +void edfplus_annotation_sort(struct annotationblock **); +struct annotationblock * edfplus_annotation_copy_list(struct annotationblock **); + +int get_tal_timestamp_digit_cnt(struct edfhdrblock *); +int get_tal_timestamp_decimal_cnt(struct edfhdrblock *); +int get_max_annotation_strlen(struct annotationblock **); #ifdef __cplusplus diff -Nru edfbrowser-1.30/edfbrowser.pro edfbrowser-1.38/edfbrowser.pro --- edfbrowser-1.30/edfbrowser.pro 2010-11-24 08:17:06.000000000 +0000 +++ edfbrowser-1.38/edfbrowser.pro 2011-08-23 20:01:14.000000000 +0000 @@ -3,11 +3,11 @@ error("you are using an old version of Qt") } -LIST = 0 1 2 3 4 5 +LIST = 0 1 2 3 4 5 6 for(a, LIST):contains(QT_MINOR_VERSION, $$a):error("you are using an old version of Qt") -contains(QT_MINOR_VERSION, 6) { - LIST = 0 1 +contains(QT_MINOR_VERSION, 7) { + LIST = 0 for(a, LIST):contains(QT_PATCH_VERSION, $$a):error("you are using an old version of Qt") } @@ -80,6 +80,13 @@ HEADERS += bdf_triggers.h HEADERS += adjustfiltersettings.h HEADERS += import_annotations.h +HEADERS += ravg_filter.h +HEADERS += wav2edf.h +HEADERS += averager_dialog.h +HEADERS += averager_curve_wnd.h +HEADERS += ecg_filter.h +HEADERS += ecg_export.h +HEADERS += statistics_dialog.h HEADERS += fidlib/fidlib.h HEADERS += fidlib/fidmkf.h @@ -146,6 +153,13 @@ SOURCES += bdf_triggers.cpp SOURCES += adjustfiltersettings.cpp SOURCES += import_annotations.cpp +SOURCES += ravg_filter.cpp +SOURCES += wav2edf.cpp +SOURCES += averager_dialog.cpp +SOURCES += averager_curve_wnd.cpp +SOURCES += ecg_filter.cpp +SOURCES += ecg_export.cpp +SOURCES += statistics_dialog.cpp SOURCES += fidlib/fidlib.c diff -Nru edfbrowser-1.30/edf_compat.cpp edfbrowser-1.38/edf_compat.cpp --- edfbrowser-1.30/edf_compat.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/edf_compat.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -37,8 +37,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -61,7 +59,7 @@ EDFCompatDialog->setMinimumSize(QSize(800, 180)); EDFCompatDialog->setMaximumSize(QSize(800, 180)); - EDFCompatDialog->setWindowTitle("Check EDF(+) / BDF compatibility"); + EDFCompatDialog->setWindowTitle("Check EDF(+) / BDF(+) compatibility"); EDFCompatDialog->setModal(TRUE); EDFCompatDialog->setAttribute(Qt::WA_DeleteOnClose, TRUE); @@ -77,9 +75,6 @@ } } - progressbar = new QProgressBar(EDFCompatDialog); - progressbar->setGeometry(QRect(10, 100, 780, 25)); - CheckButton = new QPushButton(EDFCompatDialog); CheckButton->setGeometry(QRect(10, 140, 100, 25)); CheckButton->setText("Check"); @@ -102,7 +97,7 @@ void UI_EDFCompatwindow::CheckButtonClicked() { - int i, j, k, l, p, r=0, n, + int i, j, k, p, r=0, n, len, edfsignals, datarecords, @@ -187,7 +182,8 @@ cnv_buf = (char *)calloc(1, recordsize); if(cnv_buf==NULL) { - UI_Messagewindow popuperror("Error", "Malloc error. (cnv_buf)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error. (cnv_buf)."); + messagewindow.exec(); EDFCompatDialog->close(); return; } @@ -204,7 +200,8 @@ scratchpad = (char *)calloc(1, max_tal_ln + 3); if(scratchpad==NULL) { - UI_Messagewindow popuperror("Error", "malloc error. (scratchpad)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "malloc error. (scratchpad)."); + messagewindow.exec(); free(cnv_buf); EDFCompatDialog->close(); return; @@ -212,7 +209,8 @@ if(fseeko(inputfile, (long long)((edfsignals + 1) * 256), SEEK_SET)) { - UI_Messagewindow popuperror("Error", "error when reading inputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading inputfile."); + messagewindow.exec(); free(cnv_buf); free(scratchpad); EDFCompatDialog->close(); @@ -221,7 +219,12 @@ /***************** check the maximum and minimum of samples of all signals ******************************/ - QApplication::setOverrideCursor(Qt::WaitCursor); + QProgressDialog progress("Checking...", "Abort", 0, datarecords, EDFCompatDialog); + progress.setWindowModality(Qt::WindowModal); + progress.setMinimumDuration(200); + progress.setValue(0); + + for(i=0; i<10; i++) qApp->processEvents(); elapsedtime = 0.0; @@ -229,17 +232,24 @@ { if(!(i%100)) { - progressbar->setValue(i); + progress.setValue(i); + + qApp->processEvents(); - for(l=0; l<10; l++) qApp->processEvents(); + if(progress.wasCanceled() == TRUE) + { + free(cnv_buf); + free(scratchpad); + EDFCompatDialog->close(); + return; + } } if(fread(cnv_buf, recordsize, 1, inputfile)!=1) { - QApplication::restoreOverrideCursor(); - snprintf(txt_string, 2048, "Error when reading inputfile at datarecord %i.", - i + 1); - UI_Messagewindow popuperror("Error", txt_string); + snprintf(txt_string, 2048, "An error occurred while reading inputfile at datarecord %i.", i + 1); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); free(cnv_buf); free(scratchpad); EDFCompatDialog->close(); @@ -273,7 +283,6 @@ if(temp > edfparam[j].dig_max) { - QApplication::restoreOverrideCursor(); snprintf(txt_string, 2048, "Error.\n\nIn datarecord %i -> signal %i -> sample %i is more than digital maximum.\n" "Digital maximum for this signal as written in header is %i but sample is %i.\n" "Offset from start of file: 0x%X\n", @@ -283,7 +292,9 @@ edfparam[j].dig_max, temp, (i * recordsize) + edfparam[j].buf_offset + (k * samplesize) + (edfsignals * 256) + 256); - UI_Messagewindow popuperror("Error", txt_string); + progress.reset(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); free(scratchpad); free(cnv_buf); EDFCompatDialog->close(); @@ -292,7 +303,6 @@ if(temp < edfparam[j].dig_min) { - QApplication::restoreOverrideCursor(); snprintf(txt_string, 2048, "Error.\n\nIn datarecord %i -> signal %i -> sample %i is less than digital minimum.\n" "Digital minimum for this signal as written in header is %i but sample is %i.\n" "Offset from start of file: 0x%X\n", @@ -302,7 +312,9 @@ edfparam[j].dig_min, temp, (i * recordsize) + edfparam[j].buf_offset + (k * samplesize) + (edfsignals * 256) + 256); - UI_Messagewindow popuperror("Error", txt_string); + progress.reset(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); free(cnv_buf); free(scratchpad); EDFCompatDialog->close(); @@ -495,14 +507,14 @@ } if(error==2) { - snprintf(txt_string, 1700, "Error.\n\nFile is marked as EDF+ and time keeping annotation in the first datarecord is %f\n" + snprintf(txt_string, 1700, "Error.\n\nFile is marked as EDF+ and time keeping annotation in the first datarecord is %.12f\n" "expected <1.0\n", time_tmp); } if(error==3) { - snprintf(txt_string, 1700, "Error.\n\nFile is marked as continuous EDF+ and datarecord duration is %f\n" - "but timestep between datarecord %i and preceding datarecord is %f.\n", + snprintf(txt_string, 1700, "Error.\n\nFile is marked as continuous EDF+ and datarecord duration is %.12f\n" + "but timestep between datarecord %i and preceding datarecord is %.12f.\n", data_record_duration, i + 1, time_tmp - elapsedtime); @@ -510,7 +522,7 @@ if(error==4) { snprintf(txt_string, 1700, "Error.\n\nFile is marked as discontinuous EDF+ but datarecords are not in chronological order,\n" - "datarecord %i has timestamp %f and datarecord %i has timestamp %f.\n", + "datarecord %i has timestamp %.12f and datarecord %i has timestamp %.12f.\n", i, elapsedtime, i + 1, @@ -562,13 +574,14 @@ "duration has an invalid number.\n", i + 1); } - QApplication::restoreOverrideCursor(); len = strlen(txt_string); p = (i * recordsize) + (edfsignals * 256) + 256 + (edfparam[annot_ch[r]].buf_offset); snprintf(txt_string + len, 348, "Offset from start of file: 0x%X\n\n" "Stopped at the first error, additional errors may be present.", p); - UI_Messagewindow popuperror("Error", txt_string); + progress.reset(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); free(cnv_buf); free(scratchpad); EDFCompatDialog->close(); @@ -577,28 +590,32 @@ } } - QApplication::restoreOverrideCursor(); + progress.reset(); if(bdf) { if(bdfplus) { - UI_Messagewindow popuperror("Success", "No errors found, file is BDF+ compliant."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "No errors found, file is BDF+ compliant."); + messagewindow.exec(); } else { - UI_Messagewindow popuperror("Success", "No errors found, file is BDF compliant."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "No errors found, file is BDF compliant."); + messagewindow.exec(); } } else { if(edfplus) { - UI_Messagewindow popuperror("Success", "No errors found, file is EDF+ compliant."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "No errors found, file is EDF+ compliant."); + messagewindow.exec(); } else { - UI_Messagewindow popuperror("Success", "No errors found, file is EDF compliant."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "No errors found, file is EDF compliant."); + messagewindow.exec(); } } diff -Nru edfbrowser-1.30/edf_compat.h edfbrowser-1.38/edf_compat.h --- edfbrowser-1.30/edf_compat.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/edf_compat.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -44,7 +44,8 @@ #include #include #include -#include +#include +#include #include #include @@ -79,8 +80,6 @@ QPushButton *CloseButton, *CheckButton; - QProgressBar *progressbar; - int is_duration_number(char *); int is_onset_number(char *); int is_integer_number(char *); diff -Nru edfbrowser-1.30/edflib.c edfbrowser-1.38/edflib.c --- edfbrowser-1.30/edflib.c 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/edflib.c 2011-08-23 20:01:14.000000000 +0000 @@ -1,7 +1,7 @@ /* ***************************************************************************** * -* Copyright (c) 2009, 2010 Teunis van Beelen +* Copyright (c) 2009, 2010, 2011 Teunis van Beelen * All rights reserved. * * email: teuniz@gmail.com @@ -39,14 +39,12 @@ #include "edflib.h" -#define EDFLIB_VERSION 108 +#define EDFLIB_VERSION 109 #define EDFLIB_MAXFILES 64 #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -593,6 +591,11 @@ nmemb = fwrite(str, EDFLIB_ANNOTATION_BYTES, 1, hdr->file_hdl); + if(nmemb != 1) + { + break; + } + offset += datrecsize; datarecords++; @@ -829,7 +832,6 @@ long long smp_in_file, offset, - samples_end, sample_pntr, smp_per_record, jump; @@ -929,8 +931,6 @@ sample_pntr = hdr->edfparam[channel].sample_pntr; - samples_end = sample_pntr + n; - smp_per_record = hdr->edfparam[channel].smp_per_record; jump = hdr->recordsize - (smp_per_record * bytes_per_smpl); @@ -1020,7 +1020,6 @@ long long smp_in_file, offset, - samples_end, sample_pntr, smp_per_record, jump; @@ -1120,8 +1119,6 @@ sample_pntr = hdr->edfparam[channel].sample_pntr; - samples_end = sample_pntr + n; - smp_per_record = hdr->edfparam[channel].smp_per_record; jump = hdr->recordsize - (smp_per_record * bytes_per_smpl); @@ -1720,7 +1717,7 @@ } edfhdr->data_record_duration = edflib_atof_nonlocalized(scratchpad); - if(edfhdr->data_record_duration<-0.000001) + if(edfhdr->data_record_duration < -0.000001) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); @@ -1816,7 +1813,7 @@ } if((edfhdr->edfsignals!=edfhdr->nr_annot_chns)||((!edfhdr->edfplus)&&(!edfhdr->bdfplus))) { - if(edfhdr->data_record_duration<0.000001) + if(edfhdr->data_record_duration<0.0000001) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); @@ -1845,24 +1842,7 @@ strncpy(edfhdr->edfparam[i].transducer, edf_hdr + 256 + (edfhdr->edfsignals * 16) + (i * 80), 80); edfhdr->edfparam[i].transducer[80] = 0; - if(edfhdr->edfplus) - { - if(edfhdr->edfparam[i].annotation) - { - for(j=0; j<80; j++) - { - if(edfhdr->edfparam[i].transducer[j]!=' ') - { - *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; - free(edf_hdr); - free(edfhdr->edfparam); - free(edfhdr); - return(NULL); - } - } - } - } - if(edfhdr->bdfplus) + if((edfhdr->edfplus) || (edfhdr->bdfplus)) { if(edfhdr->edfparam[i].annotation) { @@ -2162,30 +2142,13 @@ strncpy(edfhdr->edfparam[i].prefilter, edf_hdr + 256 + (edfhdr->edfsignals * 136) + (i * 80), 80); edfhdr->edfparam[i].prefilter[80] = 0; - if(edfhdr->edfplus) - { - if(edfhdr->edfparam[i].annotation) - { - for(j=0; j<80; j++) - { - if(edfhdr->edfparam[i].transducer[j]!=' ') - { - *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; - free(edf_hdr); - free(edfhdr->edfparam); - free(edfhdr); - return(NULL); - } - } - } - } - if(edfhdr->bdfplus) + if((edfhdr->edfplus) || (edfhdr->bdfplus)) { if(edfhdr->edfparam[i].annotation) { for(j=0; j<80; j++) { - if(edfhdr->edfparam[i].transducer[j]!=' ') + if(edfhdr->edfparam[i].prefilter[j]!=' ') { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); @@ -2244,10 +2207,28 @@ if(edfhdr->bdf) { edfhdr->recordsize *= 3; + + if(edfhdr->recordsize > 15728640) + { + *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; + free(edf_hdr); + free(edfhdr->edfparam); + free(edfhdr); + return(NULL); + } } else { edfhdr->recordsize *= 2; + + if(edfhdr->recordsize > 10485760) + { + *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; + free(edf_hdr); + free(edfhdr->edfparam); + free(edfhdr); + return(NULL); + } } /**************************** RESERVED FIELDS *************************************/ @@ -3133,7 +3114,7 @@ { if(r||annots_in_record) { - if(n) + if(n >= 0) { new_annotation = (struct edf_annotationblock *)calloc(1, sizeof(struct edf_annotationblock)); if(new_annotation==NULL) @@ -3969,6 +3950,8 @@ } hdr->datarecords++; + + fflush(file); } return(0); @@ -4094,6 +4077,8 @@ hdr->datarecords++; + fflush(file); + return(0); } @@ -4223,6 +4208,8 @@ } hdr->datarecords++; + + fflush(file); } return(0); @@ -4359,6 +4346,8 @@ hdr->datarecords++; + fflush(file); + return(0); } @@ -6165,11 +6154,14 @@ var = nr - q; - if(q < 0) + if(nr < 0.0) { str[j++] = '-'; - q = -q; + if(q < 0) + { + q = -q; + } } for(i=10; i; i--) @@ -6236,6 +6228,8 @@ } else { + j++; + break; } } @@ -6246,30 +6240,33 @@ double edflib_atof_nonlocalized(const char *str) { - int i, dot_pos=-1, decimals=0, expon=0; + int i=0, dot_pos=-1, decimals=0, sign=1; double value, value2=0.0; value = edflib_atoi_nonlocalized(str); - for(i=0; ; i++) + while(str[i] == ' ') { - if(str[i] == 0) - { - break; - } + i++; + } - if((str[i] == 'E') || (str[i] == 'e')) + if((str[i] == '+') || (str[i] == '-')) + { + if(str[i] == '-') { - expon++; - - break;; + sign = -1; } - if((str[i] == ' ') && (dot_pos < 0)) + i++; + } + + for(; ; i++) + { + if(str[i] == 0) { - continue; + break; } if(((str[i] < '0') || (str[i] > '9')) && (str[i] != '.')) @@ -6300,7 +6297,7 @@ if(decimals) { - value2 = edflib_atoi_nonlocalized(str + dot_pos + 1); + value2 = edflib_atoi_nonlocalized(str + dot_pos + 1) * sign; i = 1; diff -Nru edfbrowser-1.30/edflib.h edfbrowser-1.38/edflib.h --- edfbrowser-1.30/edflib.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/edflib.h 2011-08-23 20:01:14.000000000 +0000 @@ -1,7 +1,7 @@ /* ***************************************************************************** * -* Copyright (c) 2009, 2010 Teunis van Beelen +* Copyright (c) 2009, 2010, 2011 Teunis van Beelen * All rights reserved. * * email: teuniz@gmail.com diff -Nru edfbrowser-1.30/edfplusd_cnv.cpp edfbrowser-1.38/edfplusd_cnv.cpp --- edfbrowser-1.30/edfplusd_cnv.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/edfplusd_cnv.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2009, 2010 Teunis van Beelen +* Copyright (C) 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -37,8 +37,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else diff -Nru edfbrowser-1.30/edfplusd_cnv.h edfbrowser-1.38/edfplusd_cnv.h --- edfbrowser-1.30/edfplusd_cnv.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/edfplusd_cnv.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2009, 2010 Teunis van Beelen +* Copyright (C) 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/edit_annotation_dock.cpp edfbrowser-1.38/edit_annotation_dock.cpp --- edfbrowser-1.30/edit_annotation_dock.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/edit_annotation_dock.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2009, 2010 Teunis van Beelen +* Copyright (C) 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -69,17 +69,23 @@ posNegTimebox->addItem("+"); posNegTimebox->addItem("-"); + onset_daySpinbox = new QSpinBox(annot_edit_dialog); + onset_daySpinbox->setGeometry(335, 10, 45, 25); + onset_daySpinbox->setRange(0, 99); + onset_daySpinbox->setSingleStep(1); + onset_daySpinbox->setValue(0); + onset_timeEdit = new QTimeEdit(annot_edit_dialog); - onset_timeEdit->setGeometry(335, 10, 100, 25); + onset_timeEdit->setGeometry(380, 10, 100, 25); onset_timeEdit->setDisplayFormat("hh:mm:ss.zzz"); onset_timeEdit->setMinimumTime(QTime(-1, 0, 0, 0)); durationLabel = new QLabel(annot_edit_dialog); - durationLabel->setGeometry(445, 10, 58, 25); + durationLabel->setGeometry(490, 10, 58, 25); durationLabel->setText("Duration"); duration_spinbox = new QDoubleSpinBox(annot_edit_dialog); - duration_spinbox->setGeometry(505, 10, 120, 25); + duration_spinbox->setGeometry(550, 10, 120, 25); duration_spinbox->setRange(-1.0, 10000.0); duration_spinbox->setSingleStep(1.0); duration_spinbox->setDecimals(3); @@ -87,17 +93,17 @@ duration_spinbox->setValue(-1.0); modifybutton = new QPushButton(annot_edit_dialog); - modifybutton->setGeometry(675, 10, 100, 25); + modifybutton->setGeometry(720, 10, 100, 25); modifybutton->setText("Modify"); modifybutton->setEnabled(FALSE); deletebutton = new QPushButton(annot_edit_dialog); - deletebutton->setGeometry(795, 10, 100, 25); + deletebutton->setGeometry(840, 10, 100, 25); deletebutton->setText("Delete"); deletebutton->setEnabled(FALSE); createbutton = new QPushButton(annot_edit_dialog); - createbutton->setGeometry(915, 10, 100, 25); + createbutton->setGeometry(960, 10, 100, 25); createbutton->setText("Create"); QObject::connect(modifybutton, SIGNAL(clicked()), this, SLOT(modifyButtonClicked())); @@ -137,7 +143,8 @@ { annotation = edfplus_annotation_item(&mainwindow->annotationlist[file_num], annot_num); - annotation->onset = onset_timeEdit->time().hour() * 3600 * TIME_DIMENSION; + annotation->onset = onset_daySpinbox->value() * 86400 * TIME_DIMENSION; + annotation->onset += onset_timeEdit->time().hour() * 3600 * TIME_DIMENSION; annotation->onset += onset_timeEdit->time().minute() * 60 * TIME_DIMENSION; annotation->onset += onset_timeEdit->time().second() * TIME_DIMENSION; annotation->onset += onset_timeEdit->time().msec() * (TIME_DIMENSION / 1000); @@ -204,7 +211,8 @@ { annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); - annotation->onset = onset_timeEdit->time().hour() * 3600 * TIME_DIMENSION; + annotation->onset = onset_daySpinbox->value() * 86400 * TIME_DIMENSION; + annotation->onset += onset_timeEdit->time().hour() * 3600 * TIME_DIMENSION; annotation->onset += onset_timeEdit->time().minute() * 60 * TIME_DIMENSION; annotation->onset += onset_timeEdit->time().second() * TIME_DIMENSION; annotation->onset += onset_timeEdit->time().msec() * (TIME_DIMENSION / 1000); @@ -245,6 +253,8 @@ if(onset < 0LL) { + onset_daySpinbox->setValue((-(onset)) / TIME_DIMENSION / 86400); + ta.setHMS(((-(onset)) / TIME_DIMENSION / 3600) % 24, (((-(onset)) / TIME_DIMENSION) % 3600) / 60, ((-(onset)) / TIME_DIMENSION) % 60, @@ -254,6 +264,8 @@ } else { + onset_daySpinbox->setValue(onset / TIME_DIMENSION / 86400); + ta.setHMS((onset / TIME_DIMENSION / 3600) % 24, ((onset / TIME_DIMENSION) % 3600) / 60, (onset / TIME_DIMENSION) % 60, @@ -294,6 +306,8 @@ if(annotation->onset < 0LL) { + onset_daySpinbox->setValue((-(annotation->onset)) / TIME_DIMENSION / 86400); + ta.setHMS(((-(annotation->onset)) / TIME_DIMENSION / 3600) % 24, (((-(annotation->onset)) / TIME_DIMENSION) % 3600) / 60, ((-(annotation->onset)) / TIME_DIMENSION) % 60, @@ -303,6 +317,8 @@ } else { + onset_daySpinbox->setValue(annotation->onset / TIME_DIMENSION / 86400); + ta.setHMS((annotation->onset / TIME_DIMENSION / 3600) % 24, ((annotation->onset / TIME_DIMENSION) % 3600) / 60, (annotation->onset / TIME_DIMENSION) % 60, @@ -342,6 +358,8 @@ if(annotation->onset < 0LL) { + onset_daySpinbox->setValue((-(annotation->onset)) / TIME_DIMENSION / 86400); + ta.setHMS(((-(annotation->onset)) / TIME_DIMENSION / 3600) % 24, (((-(annotation->onset)) / TIME_DIMENSION) % 3600) / 60, ((-(annotation->onset)) / TIME_DIMENSION) % 60, @@ -351,6 +369,8 @@ } else { + onset_daySpinbox->setValue(annotation->onset / TIME_DIMENSION / 86400); + ta.setHMS((annotation->onset / TIME_DIMENSION / 3600) % 24, ((annotation->onset / TIME_DIMENSION) % 3600) / 60, (annotation->onset / TIME_DIMENSION) % 60, diff -Nru edfbrowser-1.30/edit_annotation_dock.h edfbrowser-1.38/edit_annotation_dock.h --- edfbrowser-1.30/edit_annotation_dock.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/edit_annotation_dock.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2009, 2010 Teunis van Beelen +* Copyright (C) 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -104,6 +105,8 @@ QTimeEdit *onset_timeEdit; + QSpinBox *onset_daySpinbox; + QDoubleSpinBox *duration_spinbox; QPushButton *modifybutton, diff -Nru edfbrowser-1.30/edit_predefined_mtg.cpp edfbrowser-1.38/edit_predefined_mtg.cpp --- edfbrowser-1.30/edit_predefined_mtg.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/edit_predefined_mtg.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/edit_predefined_mtg.h edfbrowser-1.38/edit_predefined_mtg.h --- edfbrowser-1.30/edit_predefined_mtg.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/edit_predefined_mtg.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -45,6 +45,7 @@ #include #include #include +#include #include #include diff -Nru edfbrowser-1.30/emsa2edf.cpp edfbrowser-1.38/emsa2edf.cpp --- edfbrowser-1.30/emsa2edf.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/emsa2edf.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2009, 2010 Teunis van Beelen +* Copyright (C) 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -37,8 +37,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else diff -Nru edfbrowser-1.30/emsa2edf.h edfbrowser-1.38/emsa2edf.h --- edfbrowser-1.30/emsa2edf.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/emsa2edf.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2009, 2010 Teunis van Beelen +* Copyright (C) 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/export_annotations.cpp edfbrowser-1.38/export_annotations.cpp --- edfbrowser-1.30/export_annotations.cpp 2010-11-22 11:08:58.000000000 +0000 +++ edfbrowser-1.38/export_annotations.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -36,8 +36,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -383,7 +381,8 @@ if(mainwindow->file_is_opened(path)) { - UI_Messagewindow popuperror("Export annotations", "Error, selected file is in use."); + QMessageBox messagewindow(QMessageBox::Critical, "Export annotations", "Error, selected file is in use."); + messagewindow.exec(); return; } @@ -420,7 +419,8 @@ annotationfile = fopeno(path, "wb"); if(annotationfile==NULL) { - UI_Messagewindow popuperror("Error", "Error, can not open annotationfile for writing."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open annotationfile for writing."); + messagewindow.exec(); ExportAnnotsDialog->close(); edfplus_annotation_delete_list(&annot_list); return; @@ -540,7 +540,8 @@ edfplus_annotation_delete_list(&annot_list); - UI_Messagewindow popuperror("Ready", "Done."); + QMessageBox messagewindow(QMessageBox::Information, "Ready", "Done."); + messagewindow.exec(); ExportAnnotsDialog->close(); @@ -554,7 +555,8 @@ annotationfile = fopeno(path, "wb"); if(annotationfile==NULL) { - UI_Messagewindow popuperror("Error", "Error, can not open annotationfile for writing."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open annotationfile for writing."); + messagewindow.exec(); ExportAnnotsDialog->close(); edfplus_annotation_delete_list(&annot_list); return; @@ -605,7 +607,8 @@ edfplus_annotation_delete_list(&annot_list); - UI_Messagewindow popuperror("Ready", "Done."); + QMessageBox messagewindow(QMessageBox::Information, "Ready", "Done."); + messagewindow.exec(); ExportAnnotsDialog->close(); @@ -635,7 +638,8 @@ break; } - UI_Messagewindow popuperror("Error", str); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); edfplus_annotation_delete_list(&annot_list); ExportAnnotsDialog->close(); return; @@ -749,12 +753,14 @@ if(edfclose_file(hdl) != 0) { - UI_Messagewindow popuperror("Error", "An error occurred: edfclose_file()"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred: edfclose_file()"); + messagewindow.exec(); } edfplus_annotation_delete_list(&annot_list); - UI_Messagewindow popuperror("Ready", "Done."); + QMessageBox messagewindow(QMessageBox::Information, "Ready", "Done."); + messagewindow.exec(); ExportAnnotsDialog->close(); } diff -Nru edfbrowser-1.30/export_annotations.h edfbrowser-1.38/export_annotations.h --- edfbrowser-1.30/export_annotations.h 2010-11-22 10:44:59.000000000 +0000 +++ edfbrowser-1.38/export_annotations.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -53,6 +53,7 @@ #include #include #include +#include #include #include diff -Nru edfbrowser-1.30/filter.cpp edfbrowser-1.38/filter.cpp --- edfbrowser-1.30/filter.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/filter.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/filtercurve.cpp edfbrowser-1.38/filtercurve.cpp --- edfbrowser-1.30/filtercurve.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/filtercurve.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -246,6 +246,10 @@ buf2 = NULL; + marker_1 = 0; + + marker_2 = 0; + update(); } diff -Nru edfbrowser-1.30/filtercurve.h edfbrowser-1.38/filtercurve.h --- edfbrowser-1.30/filtercurve.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/filtercurve.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/filter_dialog.cpp edfbrowser-1.38/filter_dialog.cpp --- edfbrowser-1.30/filter_dialog.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/filter_dialog.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -34,8 +34,8 @@ type: -0 : lowpass -1 : highpass +0 : highpass +1 : lowpass 2 : notch 3 : bandpass 4 : bandstop @@ -45,11 +45,13 @@ 0 : Butterworth 1 : Chebyshev 2 : Bessel +3 : moving average 0 : resonator */ + #include "filter_dialog.h" @@ -58,10 +60,15 @@ { int i; + QListWidgetItem *item; + + arraysize = 400; last_order = 1; + last_samples = 16; + last_qfactor = 20; last_model = 0; @@ -144,6 +151,7 @@ modelbox->addItem("Butterworth"); modelbox->addItem("Chebyshev"); modelbox->addItem("Bessel"); + modelbox->addItem("Moving Average"); ripplebox = new QDoubleSpinBox(filterdialog); ripplebox->setGeometry(QRect(300, 105, 120, 20)); @@ -178,7 +186,10 @@ for(i=0; isignalcomps; i++) { - list->addItem(mainwindow->signalcomp[i]->signallabel); + item = new QListWidgetItem; + item->setText(mainwindow->signalcomp[i]->signallabel); + item->setData(Qt::UserRole, QVariant(i)); + list->addItem(item); } list->setCurrentRow(0); @@ -222,6 +233,18 @@ model = modelbox->currentIndex(); + if(model == 3) + { + for(i=0; idrawCurve(array, arraysize, 1.4, 0.0); + + return; + } + ripple = -(ripplebox->value()); if((type == 3) || (type == 4)) @@ -316,7 +339,8 @@ if(err != NULL) { - UI_Messagewindow errormessage("Error", err); + QMessageBox messagewindow(QMessageBox::Critical, "Error", err); + messagewindow.exec(); free(err); return; } @@ -354,40 +378,77 @@ int type; + QObject::disconnect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); + QObject::disconnect(modelbox, SIGNAL(currentIndexChanged(int)), this, SLOT(filtermodelboxvaluechanged(int))); + type = typebox->currentIndex(); - if(model < 3) + last_model = model; + + freqboxlabel->setText("Frequency"); + freqbox->setVisible(TRUE); + + if(type != 2) { - last_model = model; + orderboxlabel->setText("Order"); + if((type == 3) || (type == 4)) + { + orderbox->setMaximum(16); + } + else + { + orderbox->setMaximum(8); + } + orderbox->setSingleStep(1); + orderbox->setMinimum(1); + orderbox->setValue(last_order); - if(type != 2) + if(model == 0) { - if(model == 0) - { - ripplebox->setVisible(FALSE); - ordervaluelabel->setVisible(TRUE); - orderlabel->setText("Slope roll-off:"); - ordervaluelabel->setText(QString::number(6 * orderbox->value(), 'f', 0).append(" dB / octave")); - } + ripplebox->setVisible(FALSE); + ordervaluelabel->setVisible(TRUE); + orderlabel->setText("Slope roll-off:"); + ordervaluelabel->setText(QString::number(6 * orderbox->value(), 'f', 0).append(" dB / octave")); + } - if(model == 1) - { - orderlabel->setText("passband ripple"); - ordervaluelabel->setVisible(FALSE); - ripplebox->setVisible(TRUE); - } + if(model == 1) + { + orderlabel->setText("passband ripple"); + ordervaluelabel->setVisible(FALSE); + ripplebox->setVisible(TRUE); + } - if(model == 2) - { - ripplebox->setVisible(FALSE); - ordervaluelabel->setVisible(TRUE); - orderlabel->setText(""); - ordervaluelabel->setText(""); - } + if(model == 2) + { + ripplebox->setVisible(FALSE); + ordervaluelabel->setVisible(TRUE); + orderlabel->setText(""); + ordervaluelabel->setText(""); + } + + if(model == 3) + { + orderlabel->setText(""); + ordervaluelabel->setText(""); + freqboxlabel->setText(""); + freqbox2label->setText(""); + freqbox->setVisible(FALSE); + ripplebox->setVisible(FALSE); + ordervaluelabel->setVisible(FALSE); + orderlabel->setText(""); + ordervaluelabel->setText(""); + orderboxlabel->setText("Samples"); + orderbox->setMaximum(10000); + orderbox->setSingleStep(1); + orderbox->setMinimum(2); + orderbox->setValue(last_samples); } } updatecurve(); + + QObject::connect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); + QObject::connect(modelbox, SIGNAL(currentIndexChanged(int)), this, SLOT(filtermodelboxvaluechanged(int))); } @@ -420,7 +481,14 @@ } else { - last_order = order; + if(model == 3) + { + last_samples = order; + } + else + { + last_order = order; + } } if(model == 0) @@ -440,6 +508,12 @@ orderlabel->setText(""); ordervaluelabel->setText(""); } + + if(model == 3) + { + orderlabel->setText(""); + ordervaluelabel->setText(""); + } } updatecurve(); @@ -488,6 +562,26 @@ orderbox->setValue(last_order); } + if(last_model == 3) + { + if(type < 2) + { + ripplebox->setVisible(FALSE); + ordervaluelabel->setVisible(FALSE); + orderlabel->setText(""); + ordervaluelabel->setText(""); + orderboxlabel->setText("Samples"); + orderbox->setMaximum(10000); + orderbox->setSingleStep(1); + orderbox->setMinimum(2); + orderbox->setValue(last_samples); + } + else + { + last_model = 0; + } + } + if(last_model == 0) { ripplebox->setVisible(FALSE); @@ -516,6 +610,10 @@ modelbox->addItem("Butterworth"); modelbox->addItem("Chebyshev"); modelbox->addItem("Bessel"); + if(type < 2) + { + modelbox->addItem("Moving Average"); + } modelbox->setCurrentIndex(last_model); } @@ -530,8 +628,19 @@ { freqbox2label->setVisible(FALSE); freq2box->setVisible(FALSE); - freqboxlabel->setText("Frequency"); - freqbox2label->setText("Time Constant"); + + if(last_model == 3) + { + orderlabel->setText(""); + ordervaluelabel->setText(""); + freqboxlabel->setText(""); + freqbox2label->setText(""); + } + else + { + freqboxlabel->setText("Frequency"); + freqbox2label->setText(""); + } } QObject::connect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); @@ -621,164 +730,196 @@ for(i=0; irow(item); + s = item->data(Qt::UserRole).toInt(); if((mainwindow->signalcomp[s]->filter_cnt + mainwindow->signalcomp[s]->fidfilter_cnt) > MAXFILTERS - 1) { - UI_Messagewindow errormessage("Error", "The maximum amount of filters per signal has been reached.\n" - "Remove some filters first."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The maximum amount of filters per signal has been reached.\n" + "Remove some filters first."); + messagewindow.exec(); return; } } - for(i=0; irow(item); - - if(type < 3) + for(i=0; i= ((mainwindow->signalcomp[s]->edfhdr->edfparam[mainwindow->signalcomp[s]->edfsignal[0]].smp_per_record - / mainwindow->signalcomp[s]->edfhdr->data_record_duration) - / 2.0)) + item = selectedlist.at(i); + s = list->row(item); + + if(type < 3) { - UI_Messagewindow errormessage("Error", "The frequency of the filter(s) must be less than: samplerate / 2"); - return; + if(frequency >= ((mainwindow->signalcomp[s]->edfhdr->edfparam[mainwindow->signalcomp[s]->edfsignal[0]].smp_per_record + / mainwindow->signalcomp[s]->edfhdr->data_record_duration) + / 2.0)) + { + UI_Messagewindow errormessage("Error", "The frequency of the filter(s) must be less than: samplerate / 2"); + return; + } } - } - else - { - if(frequency2 >= ((mainwindow->signalcomp[s]->edfhdr->edfparam[mainwindow->signalcomp[s]->edfsignal[0]].smp_per_record - / mainwindow->signalcomp[s]->edfhdr->data_record_duration) - / 2.0)) + else { - UI_Messagewindow errormessage("Error", "The frequency of the filter(s) must be less than: samplerate / 2"); - return; + if(frequency2 >= ((mainwindow->signalcomp[s]->edfhdr->edfparam[mainwindow->signalcomp[s]->edfsignal[0]].smp_per_record + / mainwindow->signalcomp[s]->edfhdr->data_record_duration) + / 2.0)) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The frequency of the filter(s) must be less than: samplerate / 2"); + messagewindow.exec(); + return; + } } } - } - spec_str_1[0] = 0; + spec_str_1[0] = 0; - if(type == 0) - { - if(model == 0) + if(type == 0) { - sprintf(spec_str_1, "HpBu%i/%f", order, frequency); - } + if(model == 0) + { + sprintf(spec_str_1, "HpBu%i/%f", order, frequency); + } - if(model == 1) - { - sprintf(spec_str_1, "HpCh%i/%f/%f", order, ripple, frequency); - } + if(model == 1) + { + sprintf(spec_str_1, "HpCh%i/%f/%f", order, ripple, frequency); + } - if(model == 2) - { - sprintf(spec_str_1, "HpBe%i/%f", order, frequency); + if(model == 2) + { + sprintf(spec_str_1, "HpBe%i/%f", order, frequency); + } } - } - if(type == 1) - { - if(model == 0) + if(type == 1) { - sprintf(spec_str_1, "LpBu%i/%f", order, frequency); + if(model == 0) + { + sprintf(spec_str_1, "LpBu%i/%f", order, frequency); + } + + if(model == 1) + { + sprintf(spec_str_1, "LpCh%i/%f/%f", order, ripple, frequency); + } + + if(model == 2) + { + sprintf(spec_str_1, "LpBe%i/%f", order, frequency); + } } - if(model == 1) + if(type == 2) { - sprintf(spec_str_1, "LpCh%i/%f/%f", order, ripple, frequency); + sprintf(spec_str_1, "BsRe/%i/%f", order, frequency); } - if(model == 2) + if(type == 3) { - sprintf(spec_str_1, "LpBe%i/%f", order, frequency); - } - } + if(model == 0) + { + sprintf(spec_str_1, "BpBu%i/%f-%f", order, frequency, frequency2); + } - if(type == 2) - { - sprintf(spec_str_1, "BsRe/%i/%f", order, frequency); - } + if(model == 1) + { + sprintf(spec_str_1, "BpCh%i/%f/%f-%f", order, ripple, frequency, frequency2); + } - if(type == 3) - { - if(model == 0) - { - sprintf(spec_str_1, "BpBu%i/%f-%f", order, frequency, frequency2); + if(model == 2) + { + sprintf(spec_str_1, "BpBe%i/%f-%f", order, frequency, frequency2); + } } - if(model == 1) + if(type == 4) { - sprintf(spec_str_1, "BpCh%i/%f/%f-%f", order, ripple, frequency, frequency2); - } + if(model == 0) + { + sprintf(spec_str_1, "BsBu%i/%f-%f", order, frequency, frequency2); + } - if(model == 2) - { - sprintf(spec_str_1, "BpBe%i/%f-%f", order, frequency, frequency2); - } - } + if(model == 1) + { + sprintf(spec_str_1, "BsCh%i/%f/%f-%f", order, ripple, frequency, frequency2); + } - if(type == 4) - { - if(model == 0) - { - sprintf(spec_str_1, "BsBu%i/%f-%f", order, frequency, frequency2); + if(model == 2) + { + sprintf(spec_str_1, "BsBe%i/%f-%f", order, frequency, frequency2); + } } - if(model == 1) + for(i=0; irow(item); - if(model == 2) - { - sprintf(spec_str_1, "BsBe%i/%f-%f", order, frequency, frequency2); - } - } + strcpy(spec_str_2, spec_str_1); - for(i=0; irow(item); + filter_spec = spec_str_2; - strcpy(spec_str_2, spec_str_1); + err = fid_parse(((double)(mainwindow->signalcomp[s]->edfhdr->edfparam[mainwindow->signalcomp[s]->edfsignal[0]].smp_per_record)) / mainwindow->signalcomp[s]->edfhdr->data_record_duration, + &filter_spec, + &mainwindow->signalcomp[s]->fidfilter[mainwindow->signalcomp[s]->fidfilter_cnt]); - filter_spec = spec_str_2; + if(err != NULL) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", err); + messagewindow.exec(); + free(err); + filterdialog->close(); + return; + } - err = fid_parse(((double)(mainwindow->signalcomp[s]->edfhdr->edfparam[mainwindow->signalcomp[s]->edfsignal[0]].smp_per_record)) / mainwindow->signalcomp[s]->edfhdr->data_record_duration, - &filter_spec, - &mainwindow->signalcomp[s]->fidfilter[mainwindow->signalcomp[s]->fidfilter_cnt]); + mainwindow->signalcomp[s]->fid_run[mainwindow->signalcomp[s]->fidfilter_cnt] = fid_run_new(mainwindow->signalcomp[s]->fidfilter[mainwindow->signalcomp[s]->fidfilter_cnt], + &mainwindow->signalcomp[s]->fidfuncp[mainwindow->signalcomp[s]->fidfilter_cnt]); - if(err != NULL) - { - UI_Messagewindow errormessage("Error", err); - free(err); - filterdialog->close(); - return; - } + mainwindow->signalcomp[s]->fidbuf[mainwindow->signalcomp[s]->fidfilter_cnt] = fid_run_newbuf(mainwindow->signalcomp[s]->fid_run[mainwindow->signalcomp[s]->fidfilter_cnt]); + mainwindow->signalcomp[s]->fidbuf2[mainwindow->signalcomp[s]->fidfilter_cnt] = fid_run_newbuf(mainwindow->signalcomp[s]->fid_run[mainwindow->signalcomp[s]->fidfilter_cnt]); + + mainwindow->signalcomp[s]->fidfilter_freq[mainwindow->signalcomp[s]->fidfilter_cnt] = frequency; + + mainwindow->signalcomp[s]->fidfilter_freq2[mainwindow->signalcomp[s]->fidfilter_cnt] = frequency2; - mainwindow->signalcomp[s]->fid_run[mainwindow->signalcomp[s]->fidfilter_cnt] = fid_run_new(mainwindow->signalcomp[s]->fidfilter[mainwindow->signalcomp[s]->fidfilter_cnt], - &mainwindow->signalcomp[s]->fidfuncp[mainwindow->signalcomp[s]->fidfilter_cnt]); + mainwindow->signalcomp[s]->fidfilter_ripple[mainwindow->signalcomp[s]->fidfilter_cnt] = ripple; - mainwindow->signalcomp[s]->fidbuf[mainwindow->signalcomp[s]->fidfilter_cnt] = fid_run_newbuf(mainwindow->signalcomp[s]->fid_run[mainwindow->signalcomp[s]->fidfilter_cnt]); - mainwindow->signalcomp[s]->fidbuf2[mainwindow->signalcomp[s]->fidfilter_cnt] = fid_run_newbuf(mainwindow->signalcomp[s]->fid_run[mainwindow->signalcomp[s]->fidfilter_cnt]); + mainwindow->signalcomp[s]->fidfilter_order[mainwindow->signalcomp[s]->fidfilter_cnt] = order; - mainwindow->signalcomp[s]->fidfilter_freq[mainwindow->signalcomp[s]->fidfilter_cnt] = frequency; + mainwindow->signalcomp[s]->fidfilter_model[mainwindow->signalcomp[s]->fidfilter_cnt] = model; - mainwindow->signalcomp[s]->fidfilter_freq2[mainwindow->signalcomp[s]->fidfilter_cnt] = frequency2; + mainwindow->signalcomp[s]->fidfilter_type[mainwindow->signalcomp[s]->fidfilter_cnt] = type; + + mainwindow->signalcomp[s]->fidfilter_setup[mainwindow->signalcomp[s]->fidfilter_cnt] = 1; + + mainwindow->signalcomp[s]->fidfilter_cnt++; + } + } - mainwindow->signalcomp[s]->fidfilter_ripple[mainwindow->signalcomp[s]->fidfilter_cnt] = ripple; + if(model == 3) + { + for(i=0; irow(item); - mainwindow->signalcomp[s]->fidfilter_order[mainwindow->signalcomp[s]->fidfilter_cnt] = order; + mainwindow->signalcomp[s]->ravg_filter[mainwindow->signalcomp[s]->ravg_filter_cnt] = create_ravg_filter(type, order); + if(mainwindow->signalcomp[s]->ravg_filter[mainwindow->signalcomp[s]->ravg_filter_cnt] == NULL) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while creating a moving average filter."); + messagewindow.exec(); + filterdialog->close(); + return; + } - mainwindow->signalcomp[s]->fidfilter_model[mainwindow->signalcomp[s]->fidfilter_cnt] = model; + mainwindow->signalcomp[s]->ravg_filter_type[mainwindow->signalcomp[s]->ravg_filter_cnt] = type; - mainwindow->signalcomp[s]->fidfilter_type[mainwindow->signalcomp[s]->fidfilter_cnt] = type; + mainwindow->signalcomp[s]->ravg_filter_size[mainwindow->signalcomp[s]->ravg_filter_cnt] = order; - mainwindow->signalcomp[s]->fidfilter_setup[mainwindow->signalcomp[s]->fidfilter_cnt] = 1; + mainwindow->signalcomp[s]->ravg_filter_setup[mainwindow->signalcomp[s]->ravg_filter_cnt] = 1; - mainwindow->signalcomp[s]->fidfilter_cnt++; + mainwindow->signalcomp[s]->ravg_filter_cnt++; + } } filterdialog->close(); diff -Nru edfbrowser-1.30/filter_dialog.h edfbrowser-1.38/filter_dialog.h --- edfbrowser-1.30/filter_dialog.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/filter_dialog.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,8 @@ #include #include #include +#include +#include #include #include @@ -58,6 +61,7 @@ #include "popup_messagewindow.h" #include "filtercurve.h" #include "utils.h" +#include "ravg_filter.h" #include "fidlib/fidlib.h" @@ -113,7 +117,8 @@ int arraysize, last_order, last_qfactor, - last_model; + last_model, + last_samples; void updatecurve(void); diff -Nru edfbrowser-1.30/filter.h edfbrowser-1.38/filter.h --- edfbrowser-1.30/filter.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/filter.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/fino2edf.cpp edfbrowser-1.38/fino2edf.cpp --- edfbrowser-1.30/fino2edf.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/fino2edf.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -37,8 +37,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -67,7 +65,7 @@ PatientnameLabel = new QLabel(myobjectDialog); PatientnameLabel->setGeometry(QRect(20, 20, 140, 16)); - PatientnameLabel->setText("Patient name"); + PatientnameLabel->setText("Subject name"); RecordingLabel = new QLabel(myobjectDialog); RecordingLabel->setGeometry(QRect(20, 50, 140, 16)); @@ -118,7 +116,6 @@ edfsignals=0, ok, timestep, - old_smpl_time, new_smpl_time=0, datarecords, str_start, @@ -150,8 +147,6 @@ - old_smpl_time = 0; - for(j=0; jtext().toLatin1().data()))) { - UI_Messagewindow popuperror("Invalid input", "Please enter a patientname."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a subjectname."); + messagewindow.exec(); enable_widgets(TRUE); return; } if(!(strlen(RecordingLineEdit->text().toLatin1().data()))) { - UI_Messagewindow popuperror("Invalid input", "Please enter a recordingdescription."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a recordingdescription."); + messagewindow.exec(); enable_widgets(TRUE); return; } @@ -187,7 +184,8 @@ if(inputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for reading.", path); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); enable_widgets(TRUE); return; } @@ -198,7 +196,8 @@ if(fread(scratchpad, 5, 1, inputfile)!=1) { - UI_Messagewindow popuperror("Error", "Error reading file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading the inputfile."); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -206,7 +205,8 @@ if(strncmp(scratchpad, "\"T\";", 4)) { - UI_Messagewindow popuperror("Error", "Unknown data in file (1)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Unknown data in file (1)."); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -218,7 +218,8 @@ if(temp==EOF) { - UI_Messagewindow popuperror("Error", "Reached end of file unexpectedly (2)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Reached end of file unexpectedly (2)."); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -229,7 +230,8 @@ if(fread(scratchpad, 2, 1, inputfile)!=1) { - UI_Messagewindow popuperror("Error", "Error reading file (3)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading inputfile (3)."); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -237,7 +239,8 @@ if(strncmp(scratchpad, "\"s\";", 4)) { - UI_Messagewindow popuperror("Error", "Unknown data in file (4)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Unknown data in file (4)."); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -253,7 +256,8 @@ if(temp==EOF) { - UI_Messagewindow popuperror("Error", "Reached end of file unexpectedly (5)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Reached end of file unexpectedly (5)."); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -273,7 +277,8 @@ if(temp==EOF) { - UI_Messagewindow popuperror("Error", "Reached end of file unexpectedly (6)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Reached end of file unexpectedly (6)."); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -288,7 +293,8 @@ { if(edfsignals>=MAX_SIGNALS) { - UI_Messagewindow popuperror("Error", "Too many labels/signals (7)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Too many labels/signals (7)."); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -461,7 +467,8 @@ if(!ok) { snprintf(txt_string, 2048, "Found unknown label/signal: %s", line); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -482,7 +489,8 @@ if(!edfsignals) { - UI_Messagewindow popuperror("Error", "There are no labels/signals."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There are no labels/signals."); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -544,7 +552,8 @@ if(outputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for writing.", path); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); enable_widgets(TRUE); fclose(inputfile); return; @@ -620,7 +629,8 @@ if(temp==EOF) { - UI_Messagewindow popuperror("Error", "Reached end of file unexpectedly (8)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Reached end of file unexpectedly (8)."); + messagewindow.exec(); fclose(inputfile); fclose(outputfile); enable_widgets(TRUE); @@ -701,7 +711,8 @@ { QApplication::restoreOverrideCursor(); snprintf(txt_string, 2048, "Number of separators in line %i is wrong.", line_nr); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); fclose(inputfile); fclose(outputfile); enable_widgets(TRUE); @@ -714,7 +725,8 @@ { QApplication::restoreOverrideCursor(); snprintf(txt_string, 2048, "Timestep <= 0 in line %i.", line_nr); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); fclose(inputfile); fclose(outputfile); enable_widgets(TRUE); @@ -740,8 +752,6 @@ datarecords++; } - old_smpl_time = new_smpl_time; - for(j=0; j #include #include +#include #include #include diff -Nru edfbrowser-1.30/fourier.c edfbrowser-1.38/fourier.c --- edfbrowser-1.30/fourier.c 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/fourier.c 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/fourier.h edfbrowser-1.38/fourier.h --- edfbrowser-1.30/fourier.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/fourier.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/global.h edfbrowser-1.38/global.h --- edfbrowser-1.30/global.h 2010-11-24 08:54:06.000000000 +0000 +++ edfbrowser-1.38/global.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -35,8 +35,8 @@ #define PROGRAM_NAME "EDFbrowser" -#define PROGRAM_VERSION "1.30" -#define MINIMUM_QT_VERSION 0x040602 +#define PROGRAM_VERSION "1.38" +#define MINIMUM_QT_VERSION 0x040701 #define MAXFILES 32 #define MAXSIGNALS 256 #define MAXFILTERS 8 @@ -50,6 +50,7 @@ #define MAX_ACTIVE_ANNOT_MARKERS 64 #define MAXSPECTRUMDIALOGS 32 #define MAXPREDEFINEDMONTAGES 8 +#define MAXAVERAGECURVEDIALOGS 32 // #define BK_MRS_project // This define activates temporary code for private use in a certain project. @@ -60,8 +61,9 @@ #include #include "filter.h" - #include "fidlib/fidlib.h" +#include "ravg_filter.h" +#include "ecg_filter.h" @@ -144,6 +146,8 @@ long long file_duration; char signallabel[512]; int signallabellen; + char signallabel_bu[512]; + int signallabellen_bu; int hascursor1; int hascursor2; int hasoffsettracking; @@ -152,6 +156,7 @@ double screen_offset; double voltpercm; char physdimension[9]; + char physdimension_bu[9]; int color; int filter_cnt; int samples_in_prefilterbuf; @@ -177,6 +182,14 @@ double stat_sum; double stat_sum_sqr; double stat_sum_rectified; + int ravg_filter_cnt; + int ravg_filter_type[MAXFILTERS]; + int ravg_filter_size[MAXFILTERS]; + int ravg_filter_setup[MAXFILTERS]; + struct ravg_filter_settings *ravg_filter[MAXFILTERS]; + struct ecg_filter_settings *ecg_filter; + int spectr_dialog[MAXSPECTRUMDIALOGS]; + int avg_dialog[MAXAVERAGECURVEDIALOGS]; }; struct zoomhistoryblock{ diff -Nru edfbrowser-1.30/header_editor.cpp edfbrowser-1.38/header_editor.cpp --- edfbrowser-1.30/header_editor.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/header_editor.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -37,8 +37,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -243,7 +241,8 @@ hdr = (char *)malloc(66048); - UI_Messagewindow popuperror("Warning", "Always make a backup copy of your file before using this tool!", "OK"); + QMessageBox messagewindow(QMessageBox::Warning, "Warning", "Always make a backup copy of your file before using this tool!"); + messagewindow.exec(); exec(); } @@ -311,7 +310,8 @@ if(hdr==NULL) { - UI_Messagewindow popuperror("Error", "Malloc error"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (hdr)"); + messagewindow.exec(); return; } @@ -326,14 +326,16 @@ if(mainwindow->file_is_opened(path)) { - UI_Messagewindow popuperror("Failure", "Selected file is in use."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Selected file is in use."); + messagewindow.exec(); return; } file = fopeno(path, "r+b"); if(file==NULL) { - UI_Messagewindow popuperror("Error", "Can not open file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file."); + messagewindow.exec(); return; } @@ -341,7 +343,8 @@ if(fread(hdr, 256, 1, file) != 1) { - UI_Messagewindow popuperror("Error", "Can not read from file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not read from file."); + messagewindow.exec(); fclose(file); file = NULL; return; @@ -356,7 +359,8 @@ if((!edf) && (!bdf)) { - UI_Messagewindow popuperror("Error", "File is not a valid EDF or BDF file"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "File is not a valid EDF or BDF file"); + messagewindow.exec(); fclose(file); file = NULL; return; @@ -366,7 +370,8 @@ if((edfsignals < 0) || (edfsignals > 256)) { - UI_Messagewindow popuperror("Error", "Invalid number of signals in header"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Invalid number of signals in header"); + messagewindow.exec(); fclose(file); file = NULL; return; @@ -400,7 +405,8 @@ if(fread(hdr, (256 * edfsignals) + 256, 1, file) != 1) { - UI_Messagewindow popuperror("Error", "Can not read from file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not read from file."); + messagewindow.exec(); fclose(file); file = NULL; return; @@ -1010,52 +1016,80 @@ fprintf(file, "%s", scratchpad); } + fseeko(file, 170LL, SEEK_SET); + fputc('.', file); + fseeko(file, 173LL, SEEK_SET); + fputc('.', file); + fseeko(file, 178LL, SEEK_SET); + fputc('.', file); + fseeko(file, 181LL, SEEK_SET); + fputc('.', file); + for(i=0; icellWidget(i, 0)))->isEnabled() == FALSE) { - continue; - } + fseeko(file, (long long)(256 + (edfsignals * 96) + (i * 8)), SEEK_SET); + fprintf(file, " "); - strcpy(scratchpad, ((QLineEdit *)(signallist->cellWidget(i, 0)))->text().toLatin1().data()); - for(j=strlen(scratchpad); j<16; j++) - { - scratchpad[j] = ' '; - } - latin1_to_ascii(scratchpad, 16); - scratchpad[16] = 0; - fseeko(file, (long long)(256 + (i * 16)), SEEK_SET); - fprintf(file, "%s", scratchpad); + for(j=0; j<80; j++) + { + scratchpad[j] = ' '; + } + scratchpad[80] = 0; + fseeko(file, (long long)(256 + (edfsignals * 136) + (i * 80)), SEEK_SET); + fprintf(file, "%s", scratchpad); - strcpy(scratchpad, ((QLineEdit *)(signallist->cellWidget(i, 1)))->text().toLatin1().data()); - for(j=strlen(scratchpad); j<8; j++) - { - scratchpad[j] = ' '; + for(j=0; j<80; j++) + { + scratchpad[j] = ' '; + } + scratchpad[80] = 0; + fseeko(file, (long long)(256 + (edfsignals * 16) + (i * 80)), SEEK_SET); + fprintf(file, "%s", scratchpad); } - latin1_to_ascii(scratchpad, 8); - scratchpad[8] = 0; - fseeko(file, (long long)(256 + (edfsignals * 96) + (i * 8)), SEEK_SET); - fprintf(file, "%s", scratchpad); - - strcpy(scratchpad, ((QLineEdit *)(signallist->cellWidget(i, 2)))->text().toLatin1().data()); - for(j=strlen(scratchpad); j<80; j++) + else { - scratchpad[j] = ' '; - } - latin1_to_ascii(scratchpad, 80); - scratchpad[80] = 0; - fseeko(file, (long long)(256 + (edfsignals * 136) + (i * 80)), SEEK_SET); - fprintf(file, "%s", scratchpad); + strcpy(scratchpad, ((QLineEdit *)(signallist->cellWidget(i, 0)))->text().toLatin1().data()); + for(j=strlen(scratchpad); j<16; j++) + { + scratchpad[j] = ' '; + } + latin1_to_ascii(scratchpad, 16); + scratchpad[16] = 0; + fseeko(file, (long long)(256 + (i * 16)), SEEK_SET); + fprintf(file, "%s", scratchpad); - strcpy(scratchpad, ((QLineEdit *)(signallist->cellWidget(i, 3)))->text().toLatin1().data()); - for(j=strlen(scratchpad); j<80; j++) - { - scratchpad[j] = ' '; + strcpy(scratchpad, ((QLineEdit *)(signallist->cellWidget(i, 1)))->text().toLatin1().data()); + for(j=strlen(scratchpad); j<8; j++) + { + scratchpad[j] = ' '; + } + latin1_to_ascii(scratchpad, 8); + scratchpad[8] = 0; + fseeko(file, (long long)(256 + (edfsignals * 96) + (i * 8)), SEEK_SET); + fprintf(file, "%s", scratchpad); + + strcpy(scratchpad, ((QLineEdit *)(signallist->cellWidget(i, 2)))->text().toLatin1().data()); + for(j=strlen(scratchpad); j<80; j++) + { + scratchpad[j] = ' '; + } + latin1_to_ascii(scratchpad, 80); + scratchpad[80] = 0; + fseeko(file, (long long)(256 + (edfsignals * 136) + (i * 80)), SEEK_SET); + fprintf(file, "%s", scratchpad); + + strcpy(scratchpad, ((QLineEdit *)(signallist->cellWidget(i, 3)))->text().toLatin1().data()); + for(j=strlen(scratchpad); j<80; j++) + { + scratchpad[j] = ' '; + } + latin1_to_ascii(scratchpad, 80); + scratchpad[80] = 0; + fseeko(file, (long long)(256 + (edfsignals * 16) + (i * 80)), SEEK_SET); + fprintf(file, "%s", scratchpad); } - latin1_to_ascii(scratchpad, 80); - scratchpad[80] = 0; - fseeko(file, (long long)(256 + (edfsignals * 16) + (i * 80)), SEEK_SET); - fprintf(file, "%s", scratchpad); } fflush(file); diff -Nru edfbrowser-1.30/header_editor.h edfbrowser-1.38/header_editor.h --- edfbrowser-1.30/header_editor.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/header_editor.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -51,6 +51,7 @@ #include #include #include +#include #include #include Binary files /tmp/ILNBLxY8LE/edfbrowser-1.30/images/doc.png and /tmp/AX82HgjKrt/edfbrowser-1.38/images/doc.png differ Binary files /tmp/ILNBLxY8LE/edfbrowser-1.30/images/splash.png and /tmp/AX82HgjKrt/edfbrowser-1.38/images/splash.png differ diff -Nru edfbrowser-1.30/import_annotations.cpp edfbrowser-1.38/import_annotations.cpp --- edfbrowser-1.30/import_annotations.cpp 2010-11-22 11:39:56.000000000 +0000 +++ edfbrowser-1.38/import_annotations.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -36,8 +36,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -52,18 +50,22 @@ UI_ImportAnnotationswindow::UI_ImportAnnotationswindow(QWidget *parent) { + int i; + + mainwindow = (UI_Mainwindow *)parent; if(mainwindow->files_open < 1) { - UI_Messagewindow popuperror("Failure", "Can not import annotations without opening an EDF/BDF-file first."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not import annotations without opening an EDF/BDF-file first."); + messagewindow.exec(); return; } ImportAnnotsDialog = new QDialog; - ImportAnnotsDialog->setMinimumSize(490, 485); - ImportAnnotsDialog->setMaximumSize(490, 485); + ImportAnnotsDialog->setMinimumSize(490, 730); + ImportAnnotsDialog->setMaximumSize(490, 730); ImportAnnotsDialog->setWindowTitle("Import annotations/events"); ImportAnnotsDialog->setModal(TRUE); ImportAnnotsDialog->setAttribute(Qt::WA_DeleteOnClose, TRUE); @@ -74,9 +76,6 @@ OnsetColumnLabel = new QLabel(ImportAnnotsDialog); OnsetColumnLabel->setText("Onset column"); - DescriptionColumnLabel = new QLabel(ImportAnnotsDialog); - DescriptionColumnLabel->setText("Description column"); - DatastartLabel = new QLabel(ImportAnnotsDialog); DatastartLabel->setText("Data starts at line"); @@ -87,6 +86,10 @@ SeparatorLineEdit->setMaxLength(3); SeparatorLineEdit->setText("tab"); + DescriptionLineEdit = new QLineEdit(ImportAnnotsDialog); + DescriptionLineEdit->setMaxLength(20); + DescriptionLineEdit->setEnabled(FALSE); + OnsetColumnSpinBox = new QSpinBox(ImportAnnotsDialog); OnsetColumnSpinBox->setRange(1,256); OnsetColumnSpinBox->setValue(1); @@ -106,21 +109,41 @@ RelativeTimeComboBox->addItem("yyyy-mm-ddThh:mm:ss"); RelativeTimeComboBox->addItem("yyyy-mm-ddThh:mm:ss.xxx"); - CSVRadioButton = new QRadioButton("ASCII/CSV"); + BitTimeSpinbox = new QSpinBox(ImportAnnotsDialog); + BitTimeSpinbox->setRange(1,1000); + BitTimeSpinbox->setSuffix(" mS"); + BitTimeSpinbox->setValue(10); + + DCEventTriggerLevelSpinBox = new QDoubleSpinBox(ImportAnnotsDialog); + DCEventTriggerLevelSpinBox->setDecimals(3); + DCEventTriggerLevelSpinBox->setRange(-10000.0, 10000.0); + DCEventTriggerLevelSpinBox->setValue(500.0); + + CSVRadioButton = new QRadioButton("ASCII / CSV"); CSVRadioButton->setChecked(TRUE); XMLRadioButton = new QRadioButton("XML"); + EDFplusRadioButton = new QRadioButton("EDF+ / BDF+"); + + DescriptionColumnRadioButton = new QRadioButton("Description column"); + DescriptionColumnRadioButton->setChecked(TRUE); + UseManualDescriptionRadioButton = new QRadioButton("Manual description"); + + DCEventRadioButton = new QRadioButton("DC-event (8-bit serial code)"); + formatGroupBox = new QGroupBox("input format", ImportAnnotsDialog); - formatGroupBox->setGeometry(20, 20, 450, 90); + formatGroupBox->setGeometry(20, 20, 450, 145); formatVBoxLayout = new QVBoxLayout; formatVBoxLayout->addWidget(CSVRadioButton); formatVBoxLayout->addWidget(XMLRadioButton); + formatVBoxLayout->addWidget(EDFplusRadioButton); + formatVBoxLayout->addWidget(DCEventRadioButton); formatGroupBox->setLayout(formatVBoxLayout); asciiSettingsGroupBox = new QGroupBox("ASCII settings", ImportAnnotsDialog); - asciiSettingsGroupBox->setGeometry(20, 130, 450, 230); + asciiSettingsGroupBox->setGeometry(20, 185, 450, 260); asciiSettingsHBoxLayout1 = new QHBoxLayout; asciiSettingsHBoxLayout1->addWidget(SeparatorLabel, 2); @@ -133,18 +156,23 @@ asciiSettingsHBoxLayout2->addStretch(2); asciiSettingsHBoxLayout3 = new QHBoxLayout; - asciiSettingsHBoxLayout3->addWidget(DescriptionColumnLabel, 2); + asciiSettingsHBoxLayout3->addWidget(DescriptionColumnRadioButton, 2); asciiSettingsHBoxLayout3->addWidget(DescriptionColumnSpinBox, 1); asciiSettingsHBoxLayout3->addStretch(2); asciiSettingsHBoxLayout4 = new QHBoxLayout; - asciiSettingsHBoxLayout4->addWidget(DatastartLabel, 2); - asciiSettingsHBoxLayout4->addWidget(DatastartSpinbox, 1); - asciiSettingsHBoxLayout4->addStretch(2); + asciiSettingsHBoxLayout4->addWidget(UseManualDescriptionRadioButton, 2); + asciiSettingsHBoxLayout4->addWidget(DescriptionLineEdit, 2); + asciiSettingsHBoxLayout4->addStretch(1); asciiSettingsHBoxLayout5 = new QHBoxLayout; - asciiSettingsHBoxLayout5->addWidget(OnsetTimeLabel, 2); - asciiSettingsHBoxLayout5->addWidget(RelativeTimeComboBox, 3); + asciiSettingsHBoxLayout5->addWidget(DatastartLabel, 2); + asciiSettingsHBoxLayout5->addWidget(DatastartSpinbox, 1); + asciiSettingsHBoxLayout5->addStretch(2); + + asciiSettingsHBoxLayout6 = new QHBoxLayout; + asciiSettingsHBoxLayout6->addWidget(OnsetTimeLabel, 2); + asciiSettingsHBoxLayout6->addWidget(RelativeTimeComboBox, 3); asciiSettingsVBoxLayout = new QVBoxLayout; asciiSettingsVBoxLayout->addLayout(asciiSettingsHBoxLayout1); @@ -152,55 +180,201 @@ asciiSettingsVBoxLayout->addLayout(asciiSettingsHBoxLayout3); asciiSettingsVBoxLayout->addLayout(asciiSettingsHBoxLayout4); asciiSettingsVBoxLayout->addLayout(asciiSettingsHBoxLayout5); + asciiSettingsVBoxLayout->addLayout(asciiSettingsHBoxLayout6); asciiSettingsGroupBox->setLayout(asciiSettingsVBoxLayout); + DCEventSignalLabel = new QLabel(ImportAnnotsDialog); + DCEventSignalLabel->setText("Signal"); + + DCEventBitTimeLabel = new QLabel(ImportAnnotsDialog); + DCEventBitTimeLabel->setText("Bit Time"); + + DCEventTriggerLevelLabel = new QLabel(ImportAnnotsDialog); + DCEventTriggerLevelLabel->setText("Trigger Level"); + + DCEventSignalComboBox = new QComboBox(ImportAnnotsDialog); + for(i=0; isignalcomps; i++) + { + DCEventSignalComboBox->addItem(mainwindow->signalcomp[i]->signallabel); + } + + if(mainwindow->signalcomps) + { + DCEventSignalChanged(0); + } + + DCEventGroupBox = new QGroupBox("DC-event settings", ImportAnnotsDialog); + DCEventGroupBox->setGeometry(20, 465, 450, 140); + + DCEventVBoxLayout1 = new QVBoxLayout; + DCEventVBoxLayout1->addWidget(DCEventSignalLabel); + DCEventVBoxLayout1->addWidget(DCEventBitTimeLabel); + DCEventVBoxLayout1->addWidget(DCEventTriggerLevelLabel); + + DCEventVBoxLayout2 = new QVBoxLayout; + DCEventVBoxLayout2->addWidget(DCEventSignalComboBox); + DCEventVBoxLayout2->addWidget(BitTimeSpinbox); + DCEventVBoxLayout2->addWidget(DCEventTriggerLevelSpinBox); + + DCEventHBoxLayout = new QHBoxLayout; + DCEventHBoxLayout->addLayout(DCEventVBoxLayout1, 1); + DCEventHBoxLayout->addLayout(DCEventVBoxLayout2, 1); + DCEventHBoxLayout->addStretch(2); + + DCEventGroupBox->setLayout(DCEventHBoxLayout); + IgnoreConsecutiveCheckBox = new QCheckBox(" Ignore consecutive events with the\n same description", ImportAnnotsDialog); - IgnoreConsecutiveCheckBox->setGeometry(25, 380, 300, 40); + IgnoreConsecutiveCheckBox->setGeometry(25, 625, 300, 40); IgnoreConsecutiveCheckBox->setTristate(FALSE); IgnoreConsecutiveCheckBox->setCheckState(Qt::Unchecked); ImportButton = new QPushButton(ImportAnnotsDialog); - ImportButton->setGeometry(20, 440, 80, 25); + ImportButton->setGeometry(20, 685, 80, 25); ImportButton->setText("Import"); CloseButton = new QPushButton(ImportAnnotsDialog); - CloseButton->setGeometry(390, 440, 80, 25); - CloseButton->setText("Close"); + CloseButton->setGeometry(390, 685, 80, 25); + CloseButton->setText("Cancel"); SeparatorLineEdit->setText(mainwindow->import_annotations_var->separator); OnsetColumnSpinBox->setValue(mainwindow->import_annotations_var->onsetcolumn); DescriptionColumnSpinBox->setValue(mainwindow->import_annotations_var->descriptioncolumn); + DescriptionLineEdit->setText(mainwindow->import_annotations_var->description); DatastartSpinbox->setValue(mainwindow->import_annotations_var->datastartline); RelativeTimeComboBox->setCurrentIndex(mainwindow->import_annotations_var->onsettimeformat); + BitTimeSpinbox->setValue(mainwindow->import_annotations_var->dceventbittime); + DCEventTriggerLevelSpinBox->setValue(mainwindow->import_annotations_var->triggerlevel); + if(mainwindow->import_annotations_var->format == 1) { CSVRadioButton->setChecked(TRUE); asciiSettingsGroupBox->setEnabled(TRUE); + DCEventGroupBox->setEnabled(FALSE); } - else + + if(mainwindow->import_annotations_var->format == 0) { XMLRadioButton->setChecked(TRUE); asciiSettingsGroupBox->setEnabled(FALSE); + DCEventGroupBox->setEnabled(FALSE); + } + + if(mainwindow->import_annotations_var->format == 2) + { + DCEventRadioButton->setChecked(TRUE); + asciiSettingsGroupBox->setEnabled(FALSE); + DCEventGroupBox->setEnabled(TRUE); + } + + if(mainwindow->import_annotations_var->format == 3) + { + EDFplusRadioButton->setChecked(TRUE); + asciiSettingsGroupBox->setEnabled(FALSE); + DCEventGroupBox->setEnabled(FALSE); + } + + IgnoreConsecutiveCheckBox->setEnabled(TRUE); + + if(mainwindow->import_annotations_var->manualdescription == 0) + { + DescriptionColumnRadioButton->setChecked(TRUE); + DescriptionColumnSpinBox->setEnabled(TRUE); + DescriptionLineEdit->setEnabled(FALSE); + } + else + { + UseManualDescriptionRadioButton->setChecked(TRUE); + DescriptionColumnSpinBox->setEnabled(FALSE); + DescriptionLineEdit->setEnabled(TRUE); + if(mainwindow->import_annotations_var->format == 1) + { + IgnoreConsecutiveCheckBox->setEnabled(FALSE); + } } - QObject::connect(CloseButton, SIGNAL(clicked()), ImportAnnotsDialog, SLOT(close())); - QObject::connect(ImportButton, SIGNAL(clicked()), this, SLOT(ImportButtonClicked())); - QObject::connect(CSVRadioButton, SIGNAL(toggled(bool)), this, SLOT(outputformatRadioButtonClicked(bool))); + QObject::connect(CloseButton, SIGNAL(clicked()), ImportAnnotsDialog, SLOT(close())); + QObject::connect(ImportButton, SIGNAL(clicked()), this, SLOT(ImportButtonClicked())); + QObject::connect(CSVRadioButton, SIGNAL(toggled(bool)), this, SLOT(outputformatRadioButtonClicked(bool))); + QObject::connect(XMLRadioButton, SIGNAL(toggled(bool)), this, SLOT(outputformatRadioButtonClicked(bool))); + QObject::connect(DCEventRadioButton, SIGNAL(toggled(bool)), this, SLOT(outputformatRadioButtonClicked(bool))); + QObject::connect(DCEventSignalComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(DCEventSignalChanged(int))); + QObject::connect(DescriptionColumnRadioButton, SIGNAL(toggled(bool)), this, SLOT(descriptionRadioButtonClicked(bool))); + QObject::connect(UseManualDescriptionRadioButton, SIGNAL(toggled(bool)), this, SLOT(descriptionRadioButtonClicked(bool))); ImportAnnotsDialog->exec(); } -void UI_ImportAnnotationswindow::outputformatRadioButtonClicked(bool checked) +void UI_ImportAnnotationswindow::descriptionRadioButtonClicked(bool) { - if(checked == TRUE) + if(DescriptionColumnRadioButton->isChecked() == TRUE) + { + DescriptionColumnSpinBox->setEnabled(TRUE); + DescriptionLineEdit->setEnabled(FALSE); + IgnoreConsecutiveCheckBox->setEnabled(TRUE); + } + + if(UseManualDescriptionRadioButton->isChecked() == TRUE) + { + DescriptionColumnSpinBox->setEnabled(FALSE); + DescriptionLineEdit->setEnabled(TRUE); + IgnoreConsecutiveCheckBox->setEnabled(FALSE); + } +} + + + +void UI_ImportAnnotationswindow::DCEventSignalChanged(int index) +{ + char scratchpad[64]; + + + if((index < 0) || (!mainwindow->signalcomps)) + { + DCEventTriggerLevelSpinBox->setSuffix(""); + + return; + } + + strcpy(scratchpad, " "); + strcat(scratchpad, mainwindow->signalcomp[index]->physdimension); + + DCEventTriggerLevelSpinBox->setSuffix(scratchpad); +} + + + +void UI_ImportAnnotationswindow::outputformatRadioButtonClicked(bool) +{ + IgnoreConsecutiveCheckBox->setEnabled(TRUE); + + if(CSVRadioButton->isChecked() == TRUE) { asciiSettingsGroupBox->setEnabled(TRUE); + DCEventGroupBox->setEnabled(FALSE); + if(UseManualDescriptionRadioButton->isChecked() == TRUE) + { + IgnoreConsecutiveCheckBox->setEnabled(FALSE); + } } - else + + if(XMLRadioButton->isChecked() == TRUE) { asciiSettingsGroupBox->setEnabled(FALSE); + DCEventGroupBox->setEnabled(FALSE); + } + + if(EDFplusRadioButton->isChecked() == TRUE) + { + asciiSettingsGroupBox->setEnabled(FALSE); + DCEventGroupBox->setEnabled(FALSE); + } + + if(DCEventRadioButton->isChecked() == TRUE) + { + asciiSettingsGroupBox->setEnabled(FALSE); + DCEventGroupBox->setEnabled(TRUE); } } @@ -224,30 +398,65 @@ digits, days=0, ignore_consecutive=0, - csv_format=0; + csv_format=0, + signal_nr, + smpls_per_datrec, + bytes_per_datrec, + recsize, + jumpbytes, + bufoffset, + triggervalue, + bitwidth, + bitposition, + trigger_sample, + next_sample, + eventcode, + tmp_value=0, + edfformat, + annotlist_size, + manualdescription; char path[1024], line[2048], scratchpad[256], - str[256], + str[2048], separator=',', description[256], last_description[256], - *result; + *result, + *buf; long long onset=0LL, l_temp, last_onset=0LL, - utc_time=0LL; + utc_time=0LL, + datrecs, + trigger_datrec, + time_per_sample, + starttime_diff; + + union { + unsigned int one; + signed int one_signed; + unsigned short two[2]; + signed short two_signed[2]; + unsigned char four[4]; + } var; FILE *inputfile=NULL; + struct edfhdrblock *edfhdr=NULL; + + struct annotationblock *annotlist[1]; + struct annotationblock *annotation; struct date_time_struct date_time; struct xml_handle *xml_hdl; + struct signalcompblock *signalcomp; + max_descr_length = 20; @@ -260,7 +469,38 @@ if(CSVRadioButton->isChecked() == TRUE) { csv_format = 1; + } + + if(XMLRadioButton->isChecked() == TRUE) + { + csv_format = 0; + } + + if(DCEventRadioButton->isChecked() == TRUE) + { + csv_format = 2; + } + + if(EDFplusRadioButton->isChecked() == TRUE) + { + csv_format = 3; + } + + if(UseManualDescriptionRadioButton->isChecked() == TRUE) + { + manualdescription = 1; + + strcpy(description, DescriptionLineEdit->text().toLatin1().data()); + } + else + { + manualdescription = 0; + } +//////////////////////////////////////////// CSV format ////////////////////////////////////////// + + if(csv_format == 1) + { strcpy(str, SeparatorLineEdit->text().toLatin1().data()); if(!strcmp(str, "tab")) @@ -271,28 +511,32 @@ { if(strlen(str)!=1) { - UI_Messagewindow popuperror("Invalid input", "Separator must be one character or \"tab\"."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Separator must be one character or \"tab\"."); + messagewindow.exec(); ImportAnnotsDialog->setEnabled(TRUE); return; } if((str[0]<32)||(str[0]>126)) { - UI_Messagewindow popuperror("Invalid input", "Separator character is not a valid ASCII character."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Separator character is not a valid ASCII character."); + messagewindow.exec(); ImportAnnotsDialog->setEnabled(TRUE); return; } if(str[0]=='.') { - UI_Messagewindow popuperror("Invalid input", "Separator character can not be a dot."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Separator character can not be a dot."); + messagewindow.exec(); ImportAnnotsDialog->setEnabled(TRUE); return; } if((str[0]>47)&&(str[0]<58)) { - UI_Messagewindow popuperror("Invalid input", "Separator character can not be a number."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Separator character can not be a number."); + messagewindow.exec(); ImportAnnotsDialog->setEnabled(TRUE); return; } @@ -312,7 +556,8 @@ if(descr_column == onset_column) { - UI_Messagewindow popuperror("Invalid input", "Onset and Description can not be in the same column."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Onset and Description can not be in the same column."); + messagewindow.exec(); ImportAnnotsDialog->setEnabled(TRUE); return; } @@ -321,10 +566,15 @@ mainwindow->import_annotations_var->onsetcolumn = onset_column + 1; mainwindow->import_annotations_var->descriptioncolumn = descr_column + 1; mainwindow->import_annotations_var->datastartline = startline; - } - else - { - csv_format = 0; + if(UseManualDescriptionRadioButton->isChecked() == TRUE) + { + mainwindow->import_annotations_var->manualdescription = 1; + } + else + { + mainwindow->import_annotations_var->manualdescription = 0; + } + strcpy(mainwindow->import_annotations_var->description, DescriptionLineEdit->text().toLatin1().data()); } if(IgnoreConsecutiveCheckBox->checkState() == Qt::Checked) @@ -338,38 +588,389 @@ mainwindow->import_annotations_var->format = csv_format; - if(csv_format) + if((csv_format == 0) || (csv_format == 1) || (csv_format == 3)) { - strcpy(path, QFileDialog::getOpenFileName(0, "Open ASCII file", mainwindow->recent_opendir, "ASCII files (*.txt *.TXT *.csv *.CSV)").toLatin1().data()); + if(csv_format == 1) + { + strcpy(path, QFileDialog::getOpenFileName(0, "Open ASCII file", mainwindow->recent_opendir, "ASCII files (*.txt *.TXT *.csv *.CSV)").toLatin1().data()); + } + + if(csv_format == 0) + { + strcpy(path, QFileDialog::getOpenFileName(0, "Open XML file", mainwindow->recent_opendir, "XML files (*.xml *.XML)").toLatin1().data()); + } + + if(csv_format == 3) + { + strcpy(path, QFileDialog::getOpenFileName(0, "Open EDF+/BDF+ file", mainwindow->recent_opendir, "EDF/BDF files (*.edf *.EDF *.bdf *.BDF )").toLatin1().data()); + } + + if(!strcmp(path, "")) + { + ImportAnnotsDialog->setEnabled(TRUE); + return; + } + + get_directory_from_path(mainwindow->recent_opendir, path, 1024); } - else + + if(mainwindow->annotationlist_backup==NULL) { - strcpy(path, QFileDialog::getOpenFileName(0, "Open XML file", mainwindow->recent_opendir, "XML files (*.xml *.XML)").toLatin1().data()); + mainwindow->annotationlist_backup = edfplus_annotation_copy_list(&mainwindow->annotationlist[0]); } - if(!strcmp(path, "")) +//////////////////////////////////////////// DC-event format ////////////////////////////////////////// + + if(csv_format == 2) { - ImportAnnotsDialog->setEnabled(TRUE); - return; + signal_nr = DCEventSignalComboBox->currentIndex(); + + if(signal_nr < 0) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "You need to put at least one signal on the screen."); + messagewindow.exec(); + ImportAnnotsDialog->setEnabled(TRUE); + return; + } + + if(mainwindow->signalcomp[signal_nr]->num_of_signals > 1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The signal can not be a derivation of multiple signals."); + messagewindow.exec(); + ImportAnnotsDialog->setEnabled(TRUE); + return; + } + + mainwindow->import_annotations_var->dceventbittime = BitTimeSpinbox->value(); + + mainwindow->import_annotations_var->triggerlevel = DCEventTriggerLevelSpinBox->value(); + + signalcomp = mainwindow->signalcomp[signal_nr]; + + smpls_per_datrec = signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record; + + recsize = signalcomp->edfhdr->recordsize; + + bufoffset = signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].buf_offset; + + time_per_sample = signalcomp->edfhdr->long_data_record_duration / smpls_per_datrec; + + if(signalcomp->edfhdr->edf) + { + edfformat = 1; + + bytes_per_datrec = smpls_per_datrec * 2; + } + else + { + bytes_per_datrec = smpls_per_datrec * 3; + + edfformat = 0; + } + + jumpbytes = recsize - bytes_per_datrec; + + inputfile = signalcomp->edfhdr->file_hdl; + + bitwidth = ((long long)mainwindow->import_annotations_var->dceventbittime * 10000LL) / time_per_sample; + + if(bitwidth < 5) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Bit Time is set too low compared to the samplerate of the selected signal."); + messagewindow.exec(); + ImportAnnotsDialog->setEnabled(TRUE); + return; + } + + triggervalue = mainwindow->import_annotations_var->triggerlevel / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue; + + triggervalue -= signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].offset; + + if(triggervalue >= signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].dig_max) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Trigger Level is equal or higher than physical maximum."); + messagewindow.exec(); + ImportAnnotsDialog->setEnabled(TRUE); + return; + } + + if(triggervalue <= signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].dig_min) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Trigger Level is equal or lower than physical minimum."); + messagewindow.exec(); + ImportAnnotsDialog->setEnabled(TRUE); + return; + } + + if(fseeko(inputfile, signalcomp->edfhdr->hdrsize + bufoffset, SEEK_SET)) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading inputfile. (fseek)"); + messagewindow.exec(); + ImportAnnotsDialog->setEnabled(TRUE); + return; + } + + buf = (char *)malloc(bytes_per_datrec); + if(buf == NULL) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (buf)"); + messagewindow.exec(); + ImportAnnotsDialog->setEnabled(TRUE); + return; + } + +/* BITPOSITION: + 0 nothing (idle) + 1 rising edge of startbit found + 2 middle of startbit found + 3 middle of bit 0 found + ........................ + 10 middle of bit 7 found + 11 middle of stopbit found +*/ + + QApplication::setOverrideCursor(Qt::WaitCursor); + + for(j=0; j<10; j++) qApp->processEvents(); + + bitposition = 0; + + eventcode = 0; + + next_sample = 0; + + trigger_sample = 0; + + trigger_datrec = 0LL; + + for(datrecs=0LL; datrecs < signalcomp->edfhdr->datarecords; datrecs++) + { + if(datrecs) + { + fseek(inputfile, jumpbytes, SEEK_CUR); + } + + if(fread(buf, bytes_per_datrec, 1, inputfile) != 1) + { + QApplication::restoreOverrideCursor(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading inputfile. (fread)"); + messagewindow.exec(); + ImportAnnotsDialog->setEnabled(TRUE); + free(buf); + return; + } + + for(i=0; i triggervalue) + { + eventcode += (1 << (bitposition - 2)); + } + } + + if(bitposition == 10) + { + if(tmp_value < triggervalue) + { + sprintf(scratchpad, "Trigger ID=%i", eventcode); + + if(strcmp(scratchpad, last_description) || (!ignore_consecutive)) + { + annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); + if(annotation == NULL) + { + QApplication::restoreOverrideCursor(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred (annotation)."); + messagewindow.exec(); + free(buf); + ImportAnnotsDialog->setEnabled(TRUE); + return; + } + annotation->onset = ((trigger_datrec * signalcomp->edfhdr->long_data_record_duration) + (trigger_sample * time_per_sample)); + strncpy(annotation->annotation, scratchpad, MAX_ANNOTATION_LEN); + annotation->annotation[MAX_ANNOTATION_LEN] = 0; + edfplus_annotation_add_item(&mainwindow->annotationlist[0], annotation); + + strcpy(last_description, scratchpad); + } + } + + bitposition = 0; + + continue; + } + } + + next_sample = (i + bitwidth) % smpls_per_datrec; + + bitposition++; + } + } + else + { + if(tmp_value > triggervalue) + { + trigger_sample = i; + + trigger_datrec = datrecs; + + bitposition = 1; + + next_sample = (i + (bitwidth / 2)) % smpls_per_datrec; + + eventcode = 0; + } + } + } + } + + free(buf); + + inputfile = NULL; } - get_directory_from_path(mainwindow->recent_opendir, path, 1024); +//////////////////////////////////////////// EDFplus format ////////////////////////////////////////// + + if(csv_format == 3) + { + inputfile = fopeno(path, "rb"); + if(inputfile==NULL) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); + messagewindow.exec(); + ImportAnnotsDialog->setEnabled(TRUE); + return; + } + + rewind(inputfile); + + QApplication::setOverrideCursor(Qt::WaitCursor); + + EDFfileCheck EDFfilechecker; + + str[0] = 0; + + annotlist[0] = NULL; + + edfhdr = EDFfilechecker.check_edf_file(inputfile, str, 0); + if(edfhdr==NULL) + { + QApplication::restoreOverrideCursor(); + strcat(str, "\n File is not a valid EDF or BDF file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); + fclose(inputfile); + ImportAnnotsDialog->setEnabled(TRUE); + return; + } + + if(!(edfhdr->edfplus || edfhdr->bdfplus)) + { + QApplication::restoreOverrideCursor(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "File is not an EDF+ or BDF+ file."); + messagewindow.exec(); + free(edfhdr->edfparam); + free(edfhdr); + fclose(inputfile); + ImportAnnotsDialog->setEnabled(TRUE); + return; + } + + strcpy(edfhdr->filename, path); + + edfhdr->file_hdl = inputfile; + + EDF_annotations annotations; + + annotations.get_annotations(0, edfhdr, &annotlist[0]); + + annotlist_size = edfplus_annotation_count(&annotlist[0]); + if(annotlist_size == 0) + { + QApplication::restoreOverrideCursor(); + QMessageBox messagewindow(QMessageBox::Information, "Import annotations", "No annotations found."); + messagewindow.exec(); + free(edfhdr->edfparam); + free(edfhdr); + fclose(inputfile); + ImportAnnotsDialog->setEnabled(TRUE); + return; + } + + starttime_diff = edfhdr->utc_starttime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime; + + starttime_diff *= TIME_DIMENSION; + + for(i=0; ionset += starttime_diff; + edfplus_annotation_add_copy(&mainwindow->annotationlist[0], annotation); + } + + edfplus_annotation_sort(&mainwindow->annotationlist[0]); + + edfplus_annotation_delete_list(&annotlist[0]); + free(edfhdr->edfparam); + free(edfhdr); + fclose(inputfile); + } //////////////////////////////////////////// XML format ////////////////////////////////////////// - if(!csv_format) + if(csv_format == 0) { xml_hdl = xml_get_handle(path); if(xml_hdl==NULL) { - UI_Messagewindow popuperror("Error", "Can not open file for reading."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); + messagewindow.exec(); ImportAnnotsDialog->setEnabled(TRUE); return; } if((xml_hdl->encoding != 1) && (xml_hdl->encoding != 2)) { - UI_Messagewindow popuperror("Error", "Encoding of XML-file must be UTF-8 or ISO-8859-1."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Encoding of XML-file must be UTF-8 or ISO-8859-1."); + messagewindow.exec(); xml_close(xml_hdl); ImportAnnotsDialog->setEnabled(TRUE); return; @@ -377,7 +978,8 @@ if(strcmp(xml_hdl->elementname, "annotationlist")) { - UI_Messagewindow popuperror("Error", "Can not find root element \"annotationlist\"."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find root element \"annotationlist\"."); + messagewindow.exec(); xml_close(xml_hdl); ImportAnnotsDialog->setEnabled(TRUE); return; @@ -394,7 +996,8 @@ if(i == 0) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Error", "Can not find child element \"annotation\"."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find child element \"annotation\"."); + messagewindow.exec(); xml_close(xml_hdl); ImportAnnotsDialog->setEnabled(TRUE); return; @@ -477,7 +1080,8 @@ if(annotation == NULL) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Error", "Malloc error (annotation)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred (annotation)."); + messagewindow.exec(); free(result); xml_close(xml_hdl); ImportAnnotsDialog->setEnabled(TRUE); @@ -507,12 +1111,13 @@ //////////////////////////////////////////// CSV format ////////////////////////////////////////// - if(csv_format) + if(csv_format == 1) { inputfile = fopeno(path, "rb"); if(inputfile==NULL) { - UI_Messagewindow popuperror("Error", "Can not open file for reading."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); + messagewindow.exec(); ImportAnnotsDialog->setEnabled(TRUE); return; } @@ -530,7 +1135,8 @@ if(temp==EOF) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Error", "File does not contain enough lines."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "File does not contain enough lines."); + messagewindow.exec(); fclose(inputfile); ImportAnnotsDialog->setEnabled(TRUE); return; @@ -595,6 +1201,8 @@ if(onsettime_coding == 0) { onset = atoll_x(scratchpad, TIME_DIMENSION); + + onset_is_set = 1; } if(onsettime_coding == 1) @@ -774,7 +1382,7 @@ } } - if(column == descr_column) + if((!manualdescription) && (column == descr_column)) { strncpy(description, line + str_start, max_descr_length); description[max_descr_length] = 0; @@ -808,7 +1416,7 @@ { if(column == onset_column) { - if(descr_is_set) + if((descr_is_set) || (manualdescription)) { onset = 0LL; strncpy(scratchpad, line + str_start, 30); @@ -817,6 +1425,8 @@ if(onsettime_coding == 0) { onset = atoll_x(scratchpad, TIME_DIMENSION); + + onset_is_set = 1; } if(onsettime_coding == 1) @@ -997,7 +1607,7 @@ } } - if(column == descr_column) + if((!manualdescription) && (column == descr_column)) { if(onset_is_set) { @@ -1009,7 +1619,7 @@ } } - if(onset_is_set && descr_is_set) + if(onset_is_set && descr_is_set && (!manualdescription)) { if(strcmp(description, last_description) || (!ignore_consecutive)) { @@ -1017,7 +1627,8 @@ if(annotation == NULL) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Error", "Malloc error (annotation)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred (annotation)."); + messagewindow.exec(); fclose(inputfile); ImportAnnotsDialog->setEnabled(TRUE); return; @@ -1031,6 +1642,24 @@ } } + if(onset_is_set && manualdescription) + { + annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); + if(annotation == NULL) + { + QApplication::restoreOverrideCursor(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred (annotation)."); + messagewindow.exec(); + fclose(inputfile); + ImportAnnotsDialog->setEnabled(TRUE); + return; + } + annotation->onset = onset + (86400LL * TIME_DIMENSION * days); + strncpy(annotation->annotation, description, MAX_ANNOTATION_LEN); + annotation->annotation[MAX_ANNOTATION_LEN] = 0; + edfplus_annotation_add_item(&mainwindow->annotationlist[0], annotation); + } + line_nr++; str_start = 0; @@ -1056,7 +1685,8 @@ { QApplication::restoreOverrideCursor(); snprintf(scratchpad, 256, "Error, line %i is too long.\n", line_nr); - UI_Messagewindow popuperror("Error", scratchpad); + QMessageBox messagewindow(QMessageBox::Critical, "Error", scratchpad); + messagewindow.exec(); fclose(inputfile); ImportAnnotsDialog->setEnabled(TRUE); return; @@ -1064,6 +1694,8 @@ } } +//////////////////////////////////////////// finish ////////////////////////////////////////// + QApplication::restoreOverrideCursor(); if(mainwindow->annotations_dock[0] == NULL) @@ -1078,23 +1710,32 @@ } } - mainwindow->annotations_edited = 1; + if(mainwindow->annotationlist[0]) + { + mainwindow->annotations_dock[0]->docklist->show(); + + mainwindow->annotations_edited = 1; - mainwindow->annotations_dock[0]->updateList(0); + mainwindow->annotations_dock[0]->updateList(0); - mainwindow->save_act->setEnabled(TRUE); + mainwindow->save_act->setEnabled(TRUE); + } - if(csv_format) + if(csv_format == 1) { if(fclose(inputfile)) { - UI_Messagewindow popuperror("Error", "An error occurred when closing inputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while closing inputfile."); + messagewindow.exec(); ImportAnnotsDialog->setEnabled(TRUE); return; } } - UI_Messagewindow popupmessage("Ready", "Done"); + mainwindow->maincurve->update(); + + QMessageBox messagewindow(QMessageBox::Information, "Ready", "Done."); + messagewindow.exec(); ImportAnnotsDialog->setEnabled(TRUE); diff -Nru edfbrowser-1.30/import_annotations.h edfbrowser-1.38/import_annotations.h --- edfbrowser-1.30/import_annotations.h 2010-11-22 10:18:09.000000000 +0000 +++ edfbrowser-1.38/import_annotations.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -51,7 +51,7 @@ #include #include #include - +#include #include #include @@ -65,6 +65,9 @@ #include "utils.h" #include "annotations_dock.h" #include "xml.h" +#include "edflib.h" +#include "check_edf_file.h" +#include "edf_annotations.h" @@ -79,7 +82,11 @@ int onsettimeformat; int onsetcolumn; int descriptioncolumn; + int manualdescription; + char description[21]; int datastartline; + int dceventbittime; + double triggerlevel; }; @@ -100,32 +107,48 @@ QLabel *SeparatorLabel, *OnsetColumnLabel, - *DescriptionColumnLabel, *DatastartLabel, - *OnsetTimeLabel; + *OnsetTimeLabel, + *DCEventSignalLabel, + *DCEventBitTimeLabel, + *DCEventTriggerLevelLabel; -QLineEdit *SeparatorLineEdit; +QLineEdit *SeparatorLineEdit, + *DescriptionLineEdit; QSpinBox *OnsetColumnSpinBox, *DescriptionColumnSpinBox, - *DatastartSpinbox; + *DatastartSpinbox, + *BitTimeSpinbox; + +QDoubleSpinBox *DCEventTriggerLevelSpinBox; -QComboBox *RelativeTimeComboBox; +QComboBox *RelativeTimeComboBox, + *DCEventSignalComboBox; QGroupBox *formatGroupBox, - *asciiSettingsGroupBox; + *asciiSettingsGroupBox, + *DCEventGroupBox; QVBoxLayout *formatVBoxLayout, - *asciiSettingsVBoxLayout; + *asciiSettingsVBoxLayout, + *DCEventVBoxLayout1, + *DCEventVBoxLayout2; QHBoxLayout *asciiSettingsHBoxLayout1, *asciiSettingsHBoxLayout2, *asciiSettingsHBoxLayout3, *asciiSettingsHBoxLayout4, - *asciiSettingsHBoxLayout5; + *asciiSettingsHBoxLayout5, + *asciiSettingsHBoxLayout6, + *DCEventHBoxLayout; QRadioButton *CSVRadioButton, - *XMLRadioButton; + *XMLRadioButton, + *EDFplusRadioButton, + *DCEventRadioButton, + *DescriptionColumnRadioButton, + *UseManualDescriptionRadioButton; QCheckBox *IgnoreConsecutiveCheckBox; @@ -137,6 +160,8 @@ void ImportButtonClicked(); void outputformatRadioButtonClicked(bool); +void descriptionRadioButtonClicked(bool); +void DCEventSignalChanged(int); }; diff -Nru edfbrowser-1.30/jump_dialog.cpp edfbrowser-1.38/jump_dialog.cpp --- edfbrowser-1.30/jump_dialog.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/jump_dialog.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/jump_dialog.h edfbrowser-1.38/jump_dialog.h --- edfbrowser-1.30/jump_dialog.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/jump_dialog.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -46,6 +46,7 @@ #include #include #include +#include #include diff -Nru edfbrowser-1.30/load_montage_dialog.cpp edfbrowser-1.38/load_montage_dialog.cpp --- edfbrowser-1.30/load_montage_dialog.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/load_montage_dialog.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -97,7 +97,7 @@ void UI_LoadMontagewindow::LoadButtonClicked() { - int i, j, k, n, + int i, j, k, n, p, skip, found, signalcomps_read=0, @@ -105,11 +105,13 @@ signal_cnt, filters_read, filter_cnt=0, + ravg_filter_cnt=0, fidfilter_cnt=0, len, order=1, type=0, - model=0; + model=0, + size=0; char *result, scratchpad[2048], @@ -149,14 +151,16 @@ if(xml_hdl==NULL) { sprintf(scratchpad, "Can not open montage file:\n%s", mtg_path); - UI_Messagewindow popuperror("Error", scratchpad); + QMessageBox messagewindow(QMessageBox::Critical, "Error", scratchpad); + messagewindow.exec(); mainwindow->remove_recent_file_mtg_path(mtg_path); return; } if(strcmp(xml_hdl->elementname, PROGRAM_NAME "_montage")) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -175,14 +179,25 @@ for(i=0; ispectrumdialog[i] != NULL) + p = mainwindow->signalcomp[k]->spectr_dialog[i]; + + if(p != 0) { - if(mainwindow->spectrumdialog[i]->signalcomp == mainwindow->signalcomp[k]) - { - delete mainwindow->spectrumdialog[i]; + delete mainwindow->spectrumdialog[p - 1]; - mainwindow->spectrumdialog[i] = NULL; - } + mainwindow->spectrumdialog[p - 1] = NULL; + } + } + + for(i=0; isignalcomp[k]->avg_dialog[i]; + + if(p != 0) + { + delete mainwindow->averagecurvedialog[p - 1]; + + mainwindow->averagecurvedialog[p - 1] = NULL; } } @@ -212,6 +227,13 @@ mainwindow->signalcomp[k]->filter_cnt = 0; + for(i=0; isignalcomp[k]->ravg_filter_cnt; i++) + { + free_ravg_filter(mainwindow->signalcomp[k]->ravg_filter[i]); + } + + mainwindow->signalcomp[k]->ravg_filter_cnt = 0; + for(i=0; isignalcomp[k]->fidfilter_cnt; i++) { free(mainwindow->signalcomp[k]->fidfilter[i]); @@ -222,6 +244,17 @@ mainwindow->signalcomp[k]->fidfilter_cnt = 0; + + if(mainwindow->signalcomp[k]->ecg_filter != NULL) + { + free_ecg_filter(mainwindow->signalcomp[k]->ecg_filter); + + mainwindow->signalcomp[k]->ecg_filter = NULL; + + strcpy(mainwindow->signalcomp[k]->signallabel, mainwindow->signalcomp[k]->signallabel_bu); + mainwindow->signalcomp[k]->signallabellen = mainwindow->signalcomp[k]->signallabellen_bu; + } + free(mainwindow->signalcomp[k]); for(i=k; isignalcomps - 1; i++) @@ -257,14 +290,16 @@ newsignalcomp = (struct signalcompblock *)calloc(1, sizeof(struct signalcompblock)); if(newsignalcomp==NULL) { - UI_Messagewindow popuperrormessage("Error", "Internal error: Memory allocation error:\n\"new signal composition\""); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Internal error: Memory allocation error:\n\"new signal composition\""); + messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_goto_nth_element_inside(xml_hdl, "num_of_signals", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; @@ -274,7 +309,8 @@ free(result); if((signal_cnt<1)||(signal_cnt>256)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; @@ -288,12 +324,16 @@ newsignalcomp->hasgaintracking = 0; newsignalcomp->screen_offset = 0; newsignalcomp->filter_cnt = 0; + newsignalcomp->ravg_filter_cnt = 0; + newsignalcomp->ecg_filter = NULL; + newsignalcomp->fidfilter_cnt = 0; newsignalcomp->hasruler = 0; xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "voltpercm", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; @@ -306,7 +346,8 @@ xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "screen_offset", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; @@ -318,7 +359,8 @@ xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "color", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; @@ -340,6 +382,17 @@ xml_go_up(xml_hdl); } + if(!(xml_goto_nth_element_inside(xml_hdl, "ravg_filter_cnt", 0))) + { + result = xml_get_content_of_element(xml_hdl); + ravg_filter_cnt = atoi(result); + if(filter_cnt < 0) filter_cnt = 0; + if(filter_cnt > MAXFILTERS) filter_cnt = MAXFILTERS; + free(result); + + xml_go_up(xml_hdl); + } + if(filter_cnt) { fidfilter_cnt = 0; @@ -362,7 +415,8 @@ { if(xml_goto_nth_element_inside(xml_hdl, "signal", signals_read)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; @@ -370,7 +424,8 @@ if(xml_goto_nth_element_inside(xml_hdl, "factor", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; @@ -385,18 +440,25 @@ { if(xml_goto_nth_element_inside(xml_hdl, "label", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } result = xml_get_content_of_element(xml_hdl); + remove_trailing_spaces(result); + found = 0; for(i=0; iedfhdr->edfsignals; i++) { - if(!strcmp(newsignalcomp->edfhdr->edfparam[i].label, result)) + strcpy(scratchpad, newsignalcomp->edfhdr->edfparam[i].label); + + remove_trailing_spaces(scratchpad); + + if(!strcmp(scratchpad, result)) { newsignalcomp->edfsignal[signals_read] = i; found = 1; @@ -500,7 +562,8 @@ { if(xml_goto_nth_element_inside(xml_hdl, "filter", filters_read)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; @@ -508,7 +571,8 @@ if(xml_goto_nth_element_inside(xml_hdl, "LPF", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; @@ -520,7 +584,8 @@ xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "frequency", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; @@ -531,7 +596,8 @@ if((type < 0) || (type > 1) || (frequency < 0.0001)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file. (filter values)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file. (filter values)"); + messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; @@ -541,7 +607,8 @@ / newsignalcomp->edfhdr->data_record_duration) / 2.0)) { - UI_Messagewindow errormessage("Error", "The frequency of the filter(s) must be less than: samplerate / 2"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The frequency of the filter(s) must be less than: samplerate / 2"); + messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; @@ -565,7 +632,8 @@ if(err != NULL) { - UI_Messagewindow errormessage("Error", err); + QMessageBox messagewindow(QMessageBox::Critical, "Error", err); + messagewindow.exec(); free(err); free(newsignalcomp); xml_close(xml_hdl); @@ -598,11 +666,77 @@ xml_go_up(xml_hdl); } + for(filters_read=0; filters_read 1) || (size < 2) || (size > 10000)) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file. (ravg_filter values)"); + messagewindow.exec(); + free(newsignalcomp); + xml_close(xml_hdl); + return; + } + + newsignalcomp->ravg_filter[filters_read] = create_ravg_filter(type, size); + if(newsignalcomp->ravg_filter[filters_read] == NULL) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred when creating an ravg filter."); + messagewindow.exec(); + free(newsignalcomp); + xml_close(xml_hdl); + return; + } + + newsignalcomp->ravg_filter_size[filters_read] = size; + + newsignalcomp->ravg_filter_type[filters_read] = type; + + newsignalcomp->ravg_filter_cnt = filters_read + 1; + + xml_go_up(xml_hdl); + xml_go_up(xml_hdl); + } + for(filters_read=0; filters_read (-0.1)) || (frequency < 0.0001) || (frequency2 < 0.0001)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file. (fidfilter values)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file. (fidfilter values)"); + messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; @@ -695,7 +836,8 @@ / newsignalcomp->edfhdr->data_record_duration) / 2.0)) { - UI_Messagewindow errormessage("Error", "The frequency of the filter(s) must be less than: samplerate / 2"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The frequency of the filter(s) must be less than: samplerate / 2"); + messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; @@ -707,7 +849,8 @@ / newsignalcomp->edfhdr->data_record_duration) / 2.0)) { - UI_Messagewindow errormessage("Error", "The frequency of the filter(s) must be less than: samplerate / 2"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The frequency of the filter(s) must be less than: samplerate / 2"); + messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; @@ -838,7 +981,8 @@ if(err != NULL) { - UI_Messagewindow errormessage("Error", err); + QMessageBox messagewindow(QMessageBox::Critical, "Error", err); + messagewindow.exec(); free(err); free(newsignalcomp); xml_close(xml_hdl); @@ -871,6 +1015,47 @@ xml_go_up(xml_hdl); } + if(!xml_goto_nth_element_inside(xml_hdl, "ecg_filter", 0)) + { + if(xml_goto_nth_element_inside(xml_hdl, "type", 0)) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); + free(newsignalcomp); + xml_close(xml_hdl); + return; + } + result = xml_get_content_of_element(xml_hdl); + type = atoi(result); + free(result); + + if(type == 1) + { + newsignalcomp->ecg_filter = create_ecg_filter(newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].smp_per_record / + newsignalcomp->edfhdr->data_record_duration, + newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].bitvalue, + mainwindow->powerlinefreq); + if(newsignalcomp->ecg_filter == NULL) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred when creating an ECG filter."); + messagewindow.exec(); + free(newsignalcomp); + xml_close(xml_hdl); + return; + } + + strcpy(newsignalcomp->signallabel_bu, newsignalcomp->signallabel); + newsignalcomp->signallabellen_bu = newsignalcomp->signallabellen; + strcpy(newsignalcomp->signallabel, "HR"); + newsignalcomp->signallabellen = strlen(newsignalcomp->signallabel); + strcpy(newsignalcomp->physdimension_bu, newsignalcomp->physdimension); + strcpy(newsignalcomp->physdimension, "bpm"); + } + + xml_go_up(xml_hdl); + xml_go_up(xml_hdl); + } + mainwindow->signalcomp[mainwindow->signalcomps] = newsignalcomp; mainwindow->signalcomps++; diff -Nru edfbrowser-1.30/load_montage_dialog.h edfbrowser-1.38/load_montage_dialog.h --- edfbrowser-1.30/load_montage_dialog.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/load_montage_dialog.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -56,6 +57,7 @@ #include "filter.h" #include "popup_messagewindow.h" #include "utc_date_time.h" +#include "utils.h" #include "fidlib/fidlib.h" diff -Nru edfbrowser-1.30/mainwindow.cpp edfbrowser-1.38/mainwindow.cpp --- edfbrowser-1.30/mainwindow.cpp 2010-11-24 08:15:18.000000000 +0000 +++ edfbrowser-1.38/mainwindow.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -36,8 +36,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -55,14 +53,10 @@ { int i, j, k; - pixmap = new QPixmap(":/images/splash.png"); - splash = new QSplashScreen(this, *pixmap, Qt::WindowStaysOnTopHint); - splash->show(); - t1 = new QTimer; - t1->setSingleShot(TRUE); - t1->start(3000); - QObject::connect(t1, SIGNAL(timeout()), splash, SLOT(close())); + live_stream_timer = new QTimer; + live_stream_timer->setSingleShot(TRUE); + QObject::connect(live_stream_timer, SIGNAL(timeout()), this, SLOT(live_stream_timer_func())); setMinimumSize(QSize(640, 480)); setWindowTitle(PROGRAM_NAME); @@ -122,6 +116,16 @@ exit_in_progress = 0; + live_stream_active = 0; + + signal_averaging_active = 0; + + live_stream_update_interval = 500; + + powerlinefreq = 50; + + mousewheelsens = 10; + recent_montagedir[0] = 0; recent_savedir[0] = 0; recent_opendir[0] = 0; @@ -131,6 +135,11 @@ spectrumdialog[i] = NULL; } + for(i=0; ionsetcolumn = 1; import_annotations_var->descriptioncolumn = 2; import_annotations_var->datastartline = 1; + import_annotations_var->dceventbittime = 10; + import_annotations_var->triggerlevel = 500.0; + import_annotations_var->manualdescription = 0; + import_annotations_var->description[0] = 0; export_annotations_var = (export_annotations_var_block *)calloc(1, sizeof(struct export_annotations_var_block)); export_annotations_var->separator = 0; export_annotations_var->format = 1; export_annotations_var->duration = 0; + average_period = 0.3; + read_general_settings(); maincurve = new ViewCurve(this); @@ -228,6 +243,9 @@ filemenu = new QMenu(this); filemenu->setTitle("&File"); filemenu->addAction("Open", this, SLOT(open_new_file()), QKeySequence::Open); + filemenu->addSeparator(); + filemenu->addAction("Open stream", this, SLOT(open_stream())); + filemenu->addSeparator(); filemenu->addAction(save_act); filemenu->addMenu(recent_filesmenu); filemenu->addMenu(printmenu); @@ -240,6 +258,7 @@ signalmenu->setTitle("&Signals"); signalmenu->addAction("Properties", this, SLOT(signalproperties_dialog())); signalmenu->addAction("Add", this, SLOT(add_signals_dialog())); + signalmenu->addAction("Organize", this, SLOT(organize_signals())); signalmenu->addAction("Remove all", this, SLOT(remove_all_signals())); menubar->addMenu(signalmenu); @@ -355,9 +374,11 @@ connect(fit_to_pane, SIGNAL(triggered()), this, SLOT(fit_signals_to_pane())); amplitudemenu->addAction(fit_to_pane); - amplitudemenu->addSeparator(); + fit_to_dc = new QAction("Adjust offset", this); + connect(fit_to_dc, SIGNAL(triggered()), this, SLOT(fit_signals_dc_offset())); + amplitudemenu->addAction(fit_to_dc); - amplitudemenu->addAction("offset -> 0", this, SLOT(set_dc_offset_to_zero())); + amplitudemenu->addAction("Offset -> 0", this, SLOT(set_dc_offset_to_zero())); amplitudemenu->addSeparator(); @@ -521,8 +542,16 @@ toolsmenu = new QMenu(this); toolsmenu->setTitle("T&ools"); - toolsmenu->addAction("Export EDF/BDF to ASCII", this, SLOT(export_to_ascii())); toolsmenu->addAction("Check EDF/BDF compatibility", this, SLOT(check_edf_compatibility())); + toolsmenu->addSeparator(); + toolsmenu->addAction("Edit EDF/BDF header", this, SLOT(edit_header())); + toolsmenu->addAction("Reduce signals and/or duration", this, SLOT(reduce_signals())); + toolsmenu->addSeparator(); + toolsmenu->addAction("Import annotations/events", this, SLOT(import_annotations())); + toolsmenu->addAction("Export annotations/events", this, SLOT(export_annotations())); + toolsmenu->addAction("Export EDF/BDF to ASCII", this, SLOT(export_to_ascii())); + toolsmenu->addAction("Export ECG RR-interval to ASCII", this, SLOT(export_ecg_rr_interval_to_ascii())); + toolsmenu->addSeparator(); toolsmenu->addAction("Convert Nihon Kohden to EDF+", this, SLOT(nk2edf_converter())); toolsmenu->addAction("Convert ASCII to EDF/BDF", this, SLOT(convert_ascii_to_edf())); toolsmenu->addAction("Convert Finometer to EDF", this, SLOT(convert_fino_to_edf())); @@ -531,11 +560,9 @@ toolsmenu->addAction("Convert EDF+D to EDF+C", this, SLOT(edfd_converter())); toolsmenu->addAction("Convert Biosemi to BDF+", this, SLOT(biosemi2bdfplus_converter())); toolsmenu->addAction("Convert BDF to EDF", this, SLOT(bdf2edf_converter())); - toolsmenu->addAction("Reduce signals and/or duration", this, SLOT(reduce_signals())); - toolsmenu->addAction("Edit EDF/BDF header", this, SLOT(edit_header())); toolsmenu->addAction("Convert BI9800TL+3 to EDF", this, SLOT(BI98002edf_converter())); - toolsmenu->addAction("Export annotations/events", this, SLOT(export_annotations())); - toolsmenu->addAction("Import annotations/events", this, SLOT(import_annotations())); + toolsmenu->addAction("Convert Wave to EDF", this, SLOT(convert_wave_to_edf())); + toolsmenu->addSeparator(); toolsmenu->addAction("Options", this, SLOT(show_options_dialog())); menubar->addMenu(toolsmenu); @@ -628,15 +655,22 @@ helpmenu = new QMenu(this); helpmenu->setTitle("&Help"); +#ifdef Q_WS_X11 + helpmenu->addAction("Manual", this, SLOT(show_help())); +#endif #ifdef Q_WS_WIN helpmenu->addAction("Manual", this, SLOT(show_help())); #endif helpmenu->addAction("Keyboard shortcuts", this, SLOT(show_kb_shortcuts())); helpmenu->addAction("About EDFbrowser", this, SLOT(show_about_dialog())); - helpmenu->addAction("About Qt", qApp, SLOT(aboutQt())); helpmenu->addAction("Show splashscreen", this, SLOT(show_splashscreen())); menubar->addMenu(helpmenu); + Escape_act = new QAction(this); + Escape_act->setShortcut(Qt::Key_Escape); + connect(Escape_act, SIGNAL(triggered()), this, SLOT(Escape_fun())); + maincurve->addAction(Escape_act); + positionslider = new QSlider(Qt::Horizontal); positionslider->setRange(0, 1000000); positionslider->setSingleStep(10000); @@ -766,7 +800,8 @@ if(QT_VERSION < MINIMUM_QT_VERSION) { - UI_Messagewindow popupmessage("Warning", "Qt version is too old!"); + QMessageBox messagewindow(QMessageBox::Warning, "Warning", "Qt version is too old"); + messagewindow.exec(); } else { @@ -781,11 +816,23 @@ v_nr += 0x100 * atoi(v_str + 2); v_nr += atoi(v_str + 4); - if(v_nr < QT_VERSION) + if(v_nr < MINIMUM_QT_VERSION) { - UI_Messagewindow popupmessage("Warning", "Qt version is too old!"); + QMessageBox messagewindow(QMessageBox::Warning, "Warning", "Qt version is too old"); + messagewindow.exec(); } } + + pixmap = new QPixmap(":/images/splash.png"); + splash = new QSplashScreen(this, *pixmap, Qt::WindowStaysOnTopHint); + + t1 = new QTimer; + t1->setSingleShot(TRUE); + QObject::connect(t1, SIGNAL(timeout()), splash, SLOT(close())); + + splash->show(); + + t1->start(3000); } @@ -800,6 +847,7 @@ delete maincurve; delete annotationEditDock; delete spectrumdock; + delete live_stream_timer; } @@ -819,14 +867,15 @@ if(annotations_edited) { - UI_CancelSavewindow ask_to_save_window("Annotations", - "There are unsaved annotations,\n are you sure you want to quit?", - "Quit", - "Cancel", - &button_nr); + QMessageBox messagewindow; + messagewindow.setText("There are unsaved annotations,\n are you sure you want to quit?"); + messagewindow.setIcon(QMessageBox::Question); + messagewindow.setStandardButtons(QMessageBox::Cancel | QMessageBox::Close); + messagewindow.setDefaultButton(QMessageBox::Cancel); + button_nr = messagewindow.exec(); } - if(button_nr==1) + if(button_nr == QMessageBox::Cancel) { event->ignore(); } @@ -839,6 +888,18 @@ if(spectrumdialog[i] != NULL) { delete spectrumdialog[i]; + + spectrumdialog[i] = NULL; + } + } + + for(i=0; ihascursor1 = 0; + signalcomp[i]->hascursor2 = 0; + signalcomp[i]->hasoffsettracking = 0; + } + maincurve->crosshair_1_active = 0; + maincurve->crosshair_2_active = 0; + maincurve->crosshair_1_moving = 0; + maincurve->crosshair_2_moving = 0; + maincurve->use_move_events = 0; + maincurve->setMouseTracking(FALSE); + + for(i=0; ihasruler = 0; + } + maincurve->ruler_active = 0; + maincurve->ruler_moving = 0; + + maincurve->update(); +} + + +void UI_Mainwindow::open_stream() +{ + if(files_open) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Close all files before opening a stream."); + messagewindow.exec(); + return; + } + + live_stream_active = 1; + + open_new_file(); + + if(files_open == 1) + { + toolsmenu->setEnabled(FALSE); + timemenu->setEnabled(FALSE); + windowmenu->setEnabled(FALSE); + former_page_Act->setEnabled(FALSE); + shift_page_left_Act->setEnabled(FALSE); + shift_page_right_Act->setEnabled(FALSE); + next_page_Act->setEnabled(FALSE); + shift_page_up_Act->setEnabled(FALSE); + shift_page_down_Act->setEnabled(FALSE); + printmenu->setEnabled(FALSE); + recent_filesmenu->setEnabled(FALSE); + + live_stream_timer->start(live_stream_update_interval); + } + else + { + live_stream_active = 0; + } +} + + +void UI_Mainwindow::live_stream_timer_func() +{ + long long datarecords_old, + datarecords_new; + + + if((!live_stream_active) || (files_open != 1)) + { + return; + } + + if(!signalcomps) + { + live_stream_timer->start(live_stream_update_interval); + + return; + } + + datarecords_old = edfheaderlist[0]->datarecords; + + datarecords_new = check_edf_file_datarecords(edfheaderlist[0]); + + if(datarecords_new == 0LL) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Stream has no datarecords."); + messagewindow.exec(); + + close_all_files(); + + return; + } + + if((datarecords_new > datarecords_old) && (datarecords_new > 0)) + { + jump_to_end(); + } + + live_stream_timer->start(live_stream_update_interval); +} + + +long long UI_Mainwindow::check_edf_file_datarecords(struct edfhdrblock *hdr) +{ + long long datarecords; + + + if(fseeko(hdr->file_hdl, 0LL, SEEK_END) == -1LL) + { + hdr->datarecords = 0LL; + + return(0LL); + } + + datarecords = ftello(hdr->file_hdl); + + if(datarecords < 1LL) + { + hdr->datarecords = 0LL; + + return(0LL); + } + + datarecords -= (long long)hdr->hdrsize; + + datarecords /= (long long)hdr->recordsize; + + if(datarecords < 1LL) + { + hdr->datarecords = 0LL; + + return(0LL); + } + + hdr->datarecords = datarecords; + + return(datarecords); +} + + #ifdef BK_MRS_project // temporary code for private use in a certain project // do not use this code, it will be removed in future @@ -930,7 +1134,8 @@ if(bk_mrs_project_file == NULL) { - UI_Messagewindow popuperror("Error", "Error, can not open outputfile for writing."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open outputfile for writing."); + messagewindow.exec(); return; } @@ -963,7 +1168,7 @@ result_rms = 0.0; } - strcpy(str_dimension, signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].physdimension); + strcpy(str_dimension, signalcomp[i]->physdimension); len = strlen(str_dimension); for(j=0; j 0) && (live_stream_active)) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "You can not open multiple files while a streaming file is open.\n" + "Close the streaming file first."); + messagewindow.exec(); + + return; + } + if(files_open>=MAXFILES) { - UI_Messagewindow popuperror("Error", "Error, there are too many files opened."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There are too many files opened."); + messagewindow.exec(); cmdlineargument = 0; return; } @@ -1938,7 +2171,8 @@ { snprintf(str, 2048, "File has an unknown extension: \"%s\"", path + (len - 4)); - UI_Messagewindow popuperror("Error", str); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); cmdlineargument = 0; @@ -1948,7 +2182,12 @@ newfile = fopeno(path, "rb"); if(newfile==NULL) { - UI_Messagewindow popuperror("Error", "Can not open file for reading"); + snprintf(str, 2048, "Can not open file for reading:\n\"%s\"\n" + "Check if you have the right permissions.\n" + "Check the path to your file if there are non-ascii characters\n" + "in the file- or directorynames", path); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); cmdlineargument = 0; return; } @@ -1970,14 +2209,15 @@ EDFfileCheck EDFfilechecker; - edfhdr = EDFfilechecker.check_edf_file(newfile, str); + edfhdr = EDFfilechecker.check_edf_file(newfile, str, live_stream_active); if(edfhdr==NULL) { fclose(newfile); strcat(str, "\n File is not a valid EDF or BDF file."); - UI_Messagewindow popuperror("Error", str); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); cmdlineargument = 0; @@ -1988,16 +2228,18 @@ { if(edfhdr->edf) { - UI_Messagewindow popuperror("Error", "EDFbrowser can not show EDF+D (discontinuous) files.\n" - "Convert this file to EDF+C first. You can find this converter\n" - "in the Tools menu (EDF+D to EDF+C converter)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "EDFbrowser can not show EDF+D (discontiguous) files.\n" + "Convert this file to EDF+C first. You can find this converter\n" + "in the Tools menu (EDF+D to EDF+C converter)."); + messagewindow.exec(); } if(edfhdr->bdf) { - UI_Messagewindow popuperror("Error", "EDFbrowser can not show BDF+D (discontinuous) files.\n" - "Convert this file to BDF+C first. You can find this converter\n" - "in the Tools menu (EDF+D to EDF+C converter)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "EDFbrowser can not show BDF+D (discontiguous) files.\n" + "Convert this file to BDF+C first. You can find this converter\n" + "in the Tools menu (EDF+D to EDF+C converter)."); + messagewindow.exec(); } free(edfhdr->edfparam); @@ -2018,7 +2260,7 @@ annotations_dock[files_open] = NULL; - if(edfhdr->edfplus || edfhdr->bdfplus) + if((edfhdr->edfplus || edfhdr->bdfplus) && (!live_stream_active)) { QLabel waitlabel("Looking for annotations...", this); waitlabel.setGeometry(width() / 2, height() / 2, 325, 25); @@ -2040,7 +2282,7 @@ } } - if(edfhdr->bdf && (!edfhdr->bdfplus) && read_biosemi_status_signal) + if((edfhdr->bdf && (!edfhdr->bdfplus) && read_biosemi_status_signal) && (!live_stream_active)) { QLabel waitlabel("Looking for trigger inputs...", this); waitlabel.setGeometry(width() / 2, height() / 2, 325, 25); @@ -2087,7 +2329,7 @@ if(viewtime_sync==VIEWTIME_USER_DEF_SYNCED) { - edfheaderlist[files_open]->viewtime = 0; + edfheaderlist[files_open]->viewtime = 0; } } @@ -2112,11 +2354,15 @@ { if((recent_file_mtg_path[0][0] != 0) && (files_open == 1) && auto_reload_mtg) { - sprintf(str, "Load last used montage?\n\n(%s)", &recent_file_mtg_path[0][0]); + QMessageBox messagewindow; + messagewindow.setText("Load last used montage?"); + messagewindow.setInformativeText(&recent_file_mtg_path[0][0]); + messagewindow.setIcon(QMessageBox::Question); + messagewindow.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + messagewindow.setDefaultButton(QMessageBox::Yes); + button_nr = messagewindow.exec(); - UI_CancelSavewindow popupmsg("Load Montage", str, "Yes", "No", &button_nr); - - if(button_nr == 1) + if(button_nr == QMessageBox::No) { recent_file_mtg_path[0][0] = 0; @@ -2177,7 +2423,7 @@ if(edfhdr->edfplus || edfhdr->bdfplus) { - snprintf(str, 256, PROGRAM_NAME " patient %s birthdate %s startdate %s", + snprintf(str, 256, PROGRAM_NAME " subject %s birthdate %s startdate %s", edfhdr->plus_patient_name, edfhdr->plus_birthdate, edfhdr->plus_startdate); @@ -2274,11 +2520,31 @@ } signalcomp[i]->fidfilter_cnt = 0; + + for(j=0; jravg_filter_cnt; j++) + { + free_ravg_filter(signalcomp[i]->ravg_filter[j]); + + update = 1; + } + + signalcomp[i]->ravg_filter_cnt = 0; + + if(signalcomp[i]->ecg_filter != NULL) + { + free_ecg_filter(signalcomp[i]->ecg_filter); + + signalcomp[i]->ecg_filter = NULL; + + strcpy(signalcomp[i]->signallabel, signalcomp[i]->signallabel_bu); + signalcomp[i]->signallabellen = signalcomp[i]->signallabellen_bu; + strcpy(signalcomp[i]->physdimension, signalcomp[i]->physdimension_bu); + } } if(update) { - maincurve->drawCurve_stage_1(); + setup_viewbuf(); } } @@ -2301,6 +2567,16 @@ } } + for(i=0; icrosshair_1_active = 0; maincurve->crosshair_2_active = 0; maincurve->crosshair_1_moving = 0; @@ -2322,6 +2598,8 @@ } slidertoolbar->hide(); + + setup_viewbuf(); } @@ -2331,16 +2609,31 @@ button_nr=0; + live_stream_active = 0; + live_stream_timer->stop(); + toolsmenu->setEnabled(TRUE); + timemenu->setEnabled(TRUE); + windowmenu->setEnabled(TRUE); + former_page_Act->setEnabled(TRUE); + shift_page_left_Act->setEnabled(TRUE); + shift_page_right_Act->setEnabled(TRUE); + next_page_Act->setEnabled(TRUE); + shift_page_up_Act->setEnabled(TRUE); + shift_page_down_Act->setEnabled(TRUE); + printmenu->setEnabled(TRUE); + recent_filesmenu->setEnabled(TRUE); + if(annotations_edited) { - UI_CancelSavewindow ask_to_save_window("Annotations", - "There are unsaved annotations,\n are you sure you want to close this file?", - "Close file", - "Cancel", - &button_nr); + QMessageBox messagewindow; + messagewindow.setText("There are unsaved annotations,\n are you sure you want to close this file?"); + messagewindow.setIcon(QMessageBox::Question); + messagewindow.setStandardButtons(QMessageBox::Cancel | QMessageBox::Close); + messagewindow.setDefaultButton(QMessageBox::Cancel); + button_nr = messagewindow.exec(); } - if(button_nr==1) + if(button_nr == QMessageBox::Cancel) { return; } @@ -2364,7 +2657,10 @@ while(files_open) { files_open--; - fclose(edfheaderlist[files_open]->file_hdl); + if(edfheaderlist[files_open]->file_hdl != NULL) + { + fclose(edfheaderlist[files_open]->file_hdl); + } free(edfheaderlist[files_open]->edfparam); free(edfheaderlist[files_open]); edfplus_annotation_delete_list(&annotationlist[files_open]); @@ -2605,6 +2901,21 @@ } +void UI_Mainwindow::fit_signals_dc_offset() +{ + int i; + + if(!signalcomps) return; + + for(i=0; iscreen_offset = ((signalcomp[i]->max_dig_value + signalcomp[i]->min_dig_value) / 2.0) * signalcomp[i]->sensitivity[0]; + } + + maincurve->drawCurve_stage_1(); +} + + void UI_Mainwindow::set_amplitude(QAction *action) { int i, j; @@ -2692,11 +3003,11 @@ totalsize, hasprefilter=0, readsize=0, - dif, - dig_value; + dif; double time=0.0, - d_temp; + d_temp, + dig_value; long long l_temp, datarecords; @@ -2728,6 +3039,29 @@ } } + if(signalcomp[i]->ravg_filter_cnt) + { + hasprefilter = 1; + + for(k=0; kravg_filter_cnt; k++) + { + if(time < ((double)(signalcomp[i]->ravg_filter[k]->size + 3) / ((double)signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record / signalcomp[i]->edfhdr->data_record_duration))) + { + time = (double)(signalcomp[i]->ravg_filter[k]->size + 3) / ((double)signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record / signalcomp[i]->edfhdr->data_record_duration); + } + } + } + + if(signalcomp[i]->ecg_filter != NULL) + { + hasprefilter = 1; + + if(time < 9.0) + { + time = 9.0; + } + } + if(signalcomp[i]->fidfilter_cnt) { hasprefilter = 1; @@ -2746,13 +3080,13 @@ { for(i=0; ifilter_cnt) || (signalcomp[i]->fidfilter_cnt)) + if((signalcomp[i]->filter_cnt) || (signalcomp[i]->ravg_filter_cnt) || (signalcomp[i]->fidfilter_cnt) || (signalcomp[i]->ecg_filter != NULL)) { - edfheaderlist[signalcomp[i]->filenum]->prefiltertime = (long long)(time * ((double)TIME_DIMENSION)); - if(edfheaderlist[signalcomp[i]->filenum]->prefiltertime>edfheaderlist[signalcomp[i]->filenum]->viewtime) + signalcomp[i]->edfhdr->prefiltertime = (long long)(time * ((double)TIME_DIMENSION)); + if(signalcomp[i]->edfhdr->prefiltertime>signalcomp[i]->edfhdr->viewtime) { - edfheaderlist[signalcomp[i]->filenum]->prefiltertime = edfheaderlist[signalcomp[i]->filenum]->viewtime; - if(edfheaderlist[signalcomp[i]->filenum]->prefiltertime<0) edfheaderlist[signalcomp[i]->filenum]->prefiltertime = 0; + signalcomp[i]->edfhdr->prefiltertime = signalcomp[i]->edfhdr->viewtime; + if(signalcomp[i]->edfhdr->prefiltertime<0) signalcomp[i]->edfhdr->prefiltertime = 0; } } } @@ -2761,26 +3095,23 @@ for(i=0; ifilenum]->prefiltertime) signalcomp[i]->records_in_viewbuf = (edfheaderlist[signalcomp[i]->filenum]->viewtime / signalcomp[i]->edfhdr->long_data_record_duration) - ((edfheaderlist[signalcomp[i]->filenum]->viewtime - edfheaderlist[signalcomp[i]->filenum]->prefiltertime) / signalcomp[i]->edfhdr->long_data_record_duration) + 1; + if(signalcomp[i]->edfhdr->prefiltertime) signalcomp[i]->records_in_viewbuf = (signalcomp[i]->edfhdr->viewtime / signalcomp[i]->edfhdr->long_data_record_duration) - ((signalcomp[i]->edfhdr->viewtime - signalcomp[i]->edfhdr->prefiltertime) / signalcomp[i]->edfhdr->long_data_record_duration) + 1; else signalcomp[i]->records_in_viewbuf = 0; signalcomp[i]->viewbufsize = signalcomp[i]->records_in_viewbuf * signalcomp[i]->edfhdr->recordsize; - for(j=0; jnum_of_signals; j++) + if(signalcomp[i]->edfhdr->prefiltertime) { - if(edfheaderlist[signalcomp[i]->filenum]->prefiltertime) - { - signalcomp[i]->samples_in_prefilterbuf = (signalcomp[i]->records_in_viewbuf - 1) * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record; + signalcomp[i]->samples_in_prefilterbuf = (signalcomp[i]->records_in_viewbuf - 1) * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record; - signalcomp[i]->samples_in_prefilterbuf - += (int)(((double)(edfheaderlist[signalcomp[i]->filenum]->viewtime % signalcomp[i]->edfhdr->long_data_record_duration) - / (double)signalcomp[i]->edfhdr->long_data_record_duration) - * (double)signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record); - } - else - { - signalcomp[i]->samples_in_prefilterbuf = 0; - } + signalcomp[i]->samples_in_prefilterbuf + += (int)(((double)(signalcomp[i]->edfhdr->viewtime % signalcomp[i]->edfhdr->long_data_record_duration) + / (double)signalcomp[i]->edfhdr->long_data_record_duration) + * (double)signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record); + } + else + { + signalcomp[i]->samples_in_prefilterbuf = 0; } if(!i) @@ -2821,7 +3152,9 @@ viewbuf = (char *)malloc(totalsize); if(viewbuf==NULL) { - UI_Messagewindow popuperror("Error", "Internal error: Memory allocation error:\n\"prefilterbuf\""); + live_stream_active = 0; + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Internal error: Memory allocation error:\n\"prefilterbuf\""); + messagewindow.exec(); remove_all_signals(); return; } @@ -2830,7 +3163,7 @@ { if(!i) { - datarecords = (edfheaderlist[signalcomp[i]->filenum]->viewtime - edfheaderlist[signalcomp[i]->filenum]->prefiltertime) / signalcomp[i]->edfhdr->long_data_record_duration; + datarecords = (signalcomp[i]->edfhdr->viewtime - signalcomp[i]->edfhdr->prefiltertime) / signalcomp[i]->edfhdr->long_data_record_duration; if((signalcomp[i]->viewbufsize>0)&&(datarecordsedfhdr->datarecords)) { @@ -2843,7 +3176,9 @@ if(fread(viewbuf + signalcomp[i]->viewbufoffset, signalcomp[i]->viewbufsize, 1, signalcomp[i]->edfhdr->file_hdl)!=1) { - UI_Messagewindow popuperror("Error", "A read error occurred. 2"); + live_stream_active = 0; + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read error occurred. 2"); + messagewindow.exec(); remove_all_signals(); return; } @@ -2864,7 +3199,7 @@ if(!skip) { - datarecords = (edfheaderlist[signalcomp[i]->filenum]->viewtime - edfheaderlist[signalcomp[i]->filenum]->prefiltertime) / signalcomp[i]->edfhdr->long_data_record_duration; + datarecords = (signalcomp[i]->edfhdr->viewtime - signalcomp[i]->edfhdr->prefiltertime) / signalcomp[i]->edfhdr->long_data_record_duration; if((signalcomp[i]->viewbufsize>0)&&(datarecordsedfhdr->datarecords)) { @@ -2877,7 +3212,9 @@ if(fread(viewbuf + signalcomp[i]->viewbufoffset, signalcomp[i]->viewbufsize, 1, signalcomp[i]->edfhdr->file_hdl)!=1) { - UI_Messagewindow popuperror("Error", "A read error occurred. 3"); + live_stream_active = 0; + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read error occurred. 3"); + messagewindow.exec(); remove_all_signals(); return; } @@ -2888,11 +3225,11 @@ for(i=0; ifilter_cnt) && (!signalcomp[i]->fidfilter_cnt)) continue; + if((!signalcomp[i]->filter_cnt) && (!signalcomp[i]->ravg_filter_cnt) && (!signalcomp[i]->fidfilter_cnt) && (signalcomp[i]->ecg_filter == NULL)) continue; for(s=0; ssamples_in_prefilterbuf; s++) { - dig_value = 0; + dig_value = 0.0; for(k=0; knum_of_signals; k++) { @@ -2946,16 +3283,31 @@ dig_value = first_order_filter(dig_value, signalcomp[i]->filter[j]); } + for(j=0; jravg_filter_cnt; j++) + { + dig_value = run_ravg_filter(dig_value, signalcomp[i]->ravg_filter[j]); + } + for(j=0; jfidfilter_cnt; j++) { dig_value = signalcomp[i]->fidfuncp[j](signalcomp[i]->fidbuf[j], dig_value); } + + if(signalcomp[i]->ecg_filter != NULL) + { + if(s == 0) + { + reset_ecg_filter(signalcomp[i]->ecg_filter); + } + + dig_value = run_ecg_filter(dig_value, signalcomp[i]->ecg_filter); + } } } for(i=0; inum_of_signals; k++) + if(signalcomp[i]->samples_in_prefilterbuf > 0) { for(j=0; jfilter_cnt; j++) { @@ -2963,10 +3315,20 @@ signalcomp[i]->filterpreset_b[j] = signalcomp[i]->filter[j]->old_output; } + for(j=0; jravg_filter_cnt; j++) + { + ravg_filter_save_buf(signalcomp[i]->ravg_filter[j]); + } + for(j=0; jfidfilter_cnt; j++) { memcpy(signalcomp[i]->fidbuf2[j], signalcomp[i]->fidbuf[j], fid_run_bufsize(signalcomp[i]->fid_run[j])); } + + if(signalcomp[i]->ecg_filter != NULL) + { + ecg_filter_save_buf(signalcomp[i]->ecg_filter); + } } } } @@ -2975,17 +3337,17 @@ for(i=0; ifilenum]->viewtime>=0) signalcomp[i]->records_in_viewbuf = ((pagetime + (edfheaderlist[signalcomp[i]->filenum]->viewtime % signalcomp[i]->edfhdr->long_data_record_duration)) / signalcomp[i]->edfhdr->long_data_record_duration) + 1; - else signalcomp[i]->records_in_viewbuf = ((pagetime + ((-(edfheaderlist[signalcomp[i]->filenum]->viewtime)) % signalcomp[i]->edfhdr->long_data_record_duration)) / signalcomp[i]->edfhdr->long_data_record_duration) + 1; + if(signalcomp[i]->edfhdr->viewtime>=0) signalcomp[i]->records_in_viewbuf = ((pagetime + (signalcomp[i]->edfhdr->viewtime % signalcomp[i]->edfhdr->long_data_record_duration)) / signalcomp[i]->edfhdr->long_data_record_duration) + 1; + else signalcomp[i]->records_in_viewbuf = ((pagetime + ((-(signalcomp[i]->edfhdr->viewtime)) % signalcomp[i]->edfhdr->long_data_record_duration)) / signalcomp[i]->edfhdr->long_data_record_duration) + 1; signalcomp[i]->viewbufsize = signalcomp[i]->records_in_viewbuf * signalcomp[i]->edfhdr->recordsize; signalcomp[i]->samples_on_screen = (int)(((double)pagetime / (double)signalcomp[i]->edfhdr->long_data_record_duration) * (double)signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record); - if(edfheaderlist[signalcomp[i]->filenum]->viewtime<0) + if(signalcomp[i]->edfhdr->viewtime<0) { d_temp = - (((double)(-(edfheaderlist[signalcomp[i]->filenum]->viewtime))) + (((double)(-(signalcomp[i]->edfhdr->viewtime))) / (double)signalcomp[i]->edfhdr->long_data_record_duration) * (double)signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record; @@ -3003,9 +3365,9 @@ signalcomp[i]->sample_start = 0; } - if(edfheaderlist[signalcomp[i]->filenum]->viewtime>=0) + if(signalcomp[i]->edfhdr->viewtime>=0) { - signalcomp[i]->sample_timeoffset_part = ((double)(edfheaderlist[signalcomp[i]->filenum]->viewtime % signalcomp[i]->edfhdr->long_data_record_duration) / (double)signalcomp[i]->edfhdr->long_data_record_duration) * (double)signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record; + signalcomp[i]->sample_timeoffset_part = ((double)(signalcomp[i]->edfhdr->viewtime % signalcomp[i]->edfhdr->long_data_record_duration) / (double)signalcomp[i]->edfhdr->long_data_record_duration) * (double)signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record; signalcomp[i]->sample_timeoffset = (int)(signalcomp[i]->sample_timeoffset_part); signalcomp[i]->sample_timeoffset_part -= signalcomp[i]->sample_timeoffset; } @@ -3055,8 +3417,10 @@ viewbuf = (char *)malloc(totalsize); if(viewbuf==NULL) { - UI_Messagewindow popuperror("Error", "The system was not able to provide enough resources (memory) to perform the requested action.\n" - "Decrease the displaytime and/or the amount of signals on the screen and retry."); + live_stream_active = 0; + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.\n" + "Decrease the timescale and/or the number of signals on the screen and retry."); + messagewindow.exec(); remove_all_signals(); return; @@ -3067,9 +3431,9 @@ { if(!i) { - if(edfheaderlist[signalcomp[i]->filenum]->viewtime>=0) + if(signalcomp[i]->edfhdr->viewtime>=0) { - datarecords = edfheaderlist[signalcomp[i]->filenum]->viewtime / signalcomp[i]->edfhdr->long_data_record_duration; + datarecords = signalcomp[i]->edfhdr->viewtime / signalcomp[i]->edfhdr->long_data_record_duration; } else { @@ -3108,7 +3472,9 @@ if(fread(viewbuf + signalcomp[i]->viewbufoffset, readsize, 1, signalcomp[i]->edfhdr->file_hdl)!=1) { - UI_Messagewindow popuperror("Error", "A read error occurred. 5"); + live_stream_active = 0; + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read error occurred. 5"); + messagewindow.exec(); remove_all_signals(); return; } @@ -3127,9 +3493,9 @@ } } - if(edfheaderlist[signalcomp[i]->filenum]->viewtime>=0) + if(signalcomp[i]->edfhdr->viewtime>=0) { - datarecords = edfheaderlist[signalcomp[i]->filenum]->viewtime / signalcomp[i]->edfhdr->long_data_record_duration; + datarecords = signalcomp[i]->edfhdr->viewtime / signalcomp[i]->edfhdr->long_data_record_duration; } else { @@ -3179,7 +3545,9 @@ if(fread(viewbuf + signalcomp[i]->viewbufoffset, readsize, 1, signalcomp[i]->edfhdr->file_hdl)!=1) { - UI_Messagewindow popuperror("Error", "A read error occurred. 6"); + live_stream_active = 0; + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read error occurred. 6"); + messagewindow.exec(); remove_all_signals(); return; } @@ -3190,7 +3558,7 @@ signalcomp[i]->sample_stop += signalcomp[i]->sample_start; } - if(signalcomps) + if(signalcomps && (!signal_averaging_active)) { if((edfheaderlist[sel_viewtime]->viewtime + edfheaderlist[sel_viewtime]->starttime_offset)>=0LL) { @@ -3236,73 +3604,93 @@ remove_trailing_zeros(pagetime_string); } - if(print_to_edf_active) + if(!signal_averaging_active) { - print_to_edf_active = 0; - } - else - { - if(signalcomps && slidertoolbar->isHidden()) + if(print_to_edf_active) { - slidertoolbar->show(); + print_to_edf_active = 0; } - - maincurve->drawCurve_stage_1(); - - if(signalcomps) + else { - QObject::disconnect(positionslider, SIGNAL(valueChanged(int)), this, SLOT(slider_moved(int))); + if(signalcomps && (!live_stream_active)) + { + QObject::disconnect(positionslider, SIGNAL(valueChanged(int)), this, SLOT(slider_moved(int))); - long long record_duration = edfheaderlist[sel_viewtime]->long_data_record_duration * edfheaderlist[sel_viewtime]->datarecords; + long long record_duration = edfheaderlist[sel_viewtime]->long_data_record_duration * edfheaderlist[sel_viewtime]->datarecords; - record_duration -= pagetime; + record_duration -= pagetime; - if(edfheaderlist[sel_viewtime]->viewtime<=0) - { - positionslider->setValue(0); - } - else - { - if(edfheaderlist[sel_viewtime]->viewtime>=record_duration) + if(edfheaderlist[sel_viewtime]->viewtime<=0) { - positionslider->setValue(1000000); + positionslider->setValue(0); } else { - if(record_durationviewtime>=record_duration) { positionslider->setValue(1000000); } else { - positionslider->setValue(edfheaderlist[sel_viewtime]->viewtime * 1000000LL / record_duration); + if(record_durationsetValue(1000000); + } + else + { + positionslider->setValue(edfheaderlist[sel_viewtime]->viewtime * 1000000LL / record_duration); + } } } + + QObject::connect(positionslider, SIGNAL(valueChanged(int)), this, SLOT(slider_moved(int))); + + slidertoolbar->show(); + } + else + { + slidertoolbar->hide(); } - QObject::connect(positionslider, SIGNAL(valueChanged(int)), this, SLOT(slider_moved(int))); + maincurve->drawCurve_stage_1(); } - else + + if(spectrumdock->dock->isVisible()) { - slidertoolbar->hide(); + spectrumdock->rescan(); } } +} - if(spectrumdock->dock->isVisible()) + +void UI_Mainwindow::export_to_ascii() +{ + if(!files_open) { - spectrumdock->rescan(); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "You have to open a file first."); + messagewindow.exec(); + return; } + + UI_AsciiExportwindow exportdialog(this); } -void UI_Mainwindow::export_to_ascii() +void UI_Mainwindow::export_ecg_rr_interval_to_ascii() { - UI_AsciiExportwindow exportdialog(this); + UI_ECGExport ECG_export(this); } void UI_Mainwindow::export_annotations() { + if(!files_open) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "You have to open a file first."); + messagewindow.exec(); + return; + } + UI_ExportAnnotationswindow exportAnnotsDialog(this); } @@ -3315,6 +3703,13 @@ void UI_Mainwindow::check_edf_compatibility() { + if(!files_open) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "You have to open the file first."); + messagewindow.exec(); + return; + } + UI_EDFCompatwindow edfcompatdialog(this); } @@ -4243,6 +4638,11 @@ import_annotations_var->format = atoi(result); + if((import_annotations_var->format < 0) || (import_annotations_var->format > 3)) + { + import_annotations_var->format = 1; + } + free(result); xml_go_up(xml_hdl); @@ -4330,6 +4730,77 @@ xml_go_up(xml_hdl); } + if(!(xml_goto_nth_element_inside(xml_hdl, "dceventbittime", 0))) + { + result = xml_get_content_of_element(xml_hdl); + if(result==NULL) + { + xml_close(xml_hdl); + return; + } + + import_annotations_var->dceventbittime = atoi(result); + + free(result); + + xml_go_up(xml_hdl); + } + + if(!(xml_goto_nth_element_inside(xml_hdl, "triggerlevel", 0))) + { + result = xml_get_content_of_element(xml_hdl); + if(result==NULL) + { + xml_close(xml_hdl); + return; + } + + import_annotations_var->triggerlevel = atof(result); + + free(result); + + xml_go_up(xml_hdl); + } + + if(!(xml_goto_nth_element_inside(xml_hdl, "manualdescription", 0))) + { + result = xml_get_content_of_element(xml_hdl); + if(result==NULL) + { + xml_close(xml_hdl); + return; + } + + import_annotations_var->manualdescription = atoi(result); + + if((import_annotations_var->manualdescription < 0) || (import_annotations_var->manualdescription > 1)) + { + import_annotations_var->manualdescription = 0; + } + + free(result); + + xml_go_up(xml_hdl); + } + + if(!(xml_goto_nth_element_inside(xml_hdl, "description", 0))) + { + result = xml_get_content_of_element(xml_hdl); + if(result==NULL) + { + xml_close(xml_hdl); + return; + } + + strncpy(import_annotations_var->description, result, 20); + + import_annotations_var->description[20] = 0; + + free(result); + + xml_go_up(xml_hdl); + } + xml_go_up(xml_hdl); } @@ -4386,6 +4857,86 @@ xml_go_up(xml_hdl); } + if(!(xml_goto_nth_element_inside(xml_hdl, "live_stream_update_interval", 0))) + { + result = xml_get_content_of_element(xml_hdl); + if(result==NULL) + { + xml_close(xml_hdl); + return; + } + + live_stream_update_interval = atoi(result); + if((live_stream_update_interval < 100) || (live_stream_update_interval > 3000)) + { + live_stream_update_interval = 500; + } + + free(result); + + xml_go_up(xml_hdl); + } + + if(!(xml_goto_nth_element_inside(xml_hdl, "powerlinefreq", 0))) + { + result = xml_get_content_of_element(xml_hdl); + if(result==NULL) + { + xml_close(xml_hdl); + return; + } + + powerlinefreq = atoi(result); + if((powerlinefreq != 50) && (powerlinefreq != 60)) + { + powerlinefreq = 50; + } + + free(result); + + xml_go_up(xml_hdl); + } + + if(!(xml_goto_nth_element_inside(xml_hdl, "mousewheelsens", 0))) + { + result = xml_get_content_of_element(xml_hdl); + if(result==NULL) + { + xml_close(xml_hdl); + return; + } + + mousewheelsens = atoi(result); + if((mousewheelsens < 0) || (mousewheelsens > 100)) + { + mousewheelsens = 10; + } + + free(result); + + xml_go_up(xml_hdl); + } + + if(!(xml_goto_nth_element_inside(xml_hdl, "average_period", 0))) + { + result = xml_get_content_of_element(xml_hdl); + if(result==NULL) + { + xml_close(xml_hdl); + return; + } + + average_period = atof(result); + if((mousewheelsens < 0.01) || (mousewheelsens > 300.0)) + { + mousewheelsens = 0.3; + } + + free(result); + + xml_go_up(xml_hdl); + } + xml_close(xml_hdl); } @@ -4637,6 +5188,14 @@ fprintf(cfgfile, " %s\n", import_annotations_var->separator); + fprintf(cfgfile, " %i\n", import_annotations_var->dceventbittime); + + fprintf(cfgfile, " %.12f\n", import_annotations_var->triggerlevel); + + fprintf(cfgfile, " %i\n", import_annotations_var->manualdescription); + + fprintf(cfgfile, " %s\n", import_annotations_var->description); + fprintf(cfgfile, " \n"); fprintf(cfgfile, " \n"); @@ -4649,6 +5208,14 @@ fprintf(cfgfile, " \n"); + fprintf(cfgfile, " %i\n", live_stream_update_interval); + + fprintf(cfgfile, " %i\n", powerlinefreq); + + fprintf(cfgfile, " %i\n", mousewheelsens); + + fprintf(cfgfile, " %f\n", average_period); + fprintf(cfgfile, " \n\n"); fclose(cfgfile); @@ -4724,6 +5291,10 @@ void UI_Mainwindow::show_help() { +#ifdef Q_WS_X11 + QDesktopServices::openUrl(QUrl("file:///usr/share/doc/edfbrowser/EDFbrowser%20manual.html")); +#endif + #ifdef Q_WS_WIN char path[1024]; @@ -4754,9 +5325,22 @@ "Ctrl++\tzoom in\n" "Ctrl+-\tzoom out\n" "F1 - F8\tload predefined montage\n" + "Esc\tremove crosshairs or floating ruler\n" + "\nafter zooming in by dragging a rectangle:\n" "Backspace\tzoom back\n" - "Insert\tzoom in\n"); + "Insert\tzoom in\n" + +#ifdef Q_WS_WIN +"\nCtrl+O\tOpen a file\n" +"Ctrl+F4\tClose all files\n" +"Alt+F4\tExit program"); +#else +"\nCtrl+O\tOpen a file\n" +"Ctrl+W\tClose all files\n" +"Ctrl+Q\tExit program"); +#endif + } @@ -4816,6 +5400,10 @@ } +void UI_Mainwindow::organize_signals() +{ + UI_SignalChooser signalchooser(this, 3); +} diff -Nru edfbrowser-1.30/mainwindow.h edfbrowser-1.38/mainwindow.h --- edfbrowser-1.30/mainwindow.h 2010-11-22 10:12:30.000000000 +0000 +++ edfbrowser-1.38/mainwindow.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -83,6 +83,7 @@ #include #include #include +#include #include #include @@ -136,6 +137,12 @@ #include "biosemi2bdfplus.h" #include "bdf_triggers.h" #include "import_annotations.h" +#include "ravg_filter.h" +#include "wav2edf.h" +#include "averager_curve_wnd.h" +#include "ecg_filter.h" +#include "ecg_export.h" + #include "fidlib/fidlib.h" @@ -148,7 +155,7 @@ class UI_AnnotationEditwindow; class UI_SpectrumDockWindow; class UI_FreqSpectrumWindow; - +class UI_AverageCurveWindow; class UI_Mainwindow : public QMainWindow { @@ -175,7 +182,12 @@ auto_dpi, clip_to_pane, auto_reload_mtg, - read_biosemi_status_signal; + read_biosemi_status_signal, + live_stream_active, + live_stream_update_interval, + signal_averaging_active, + powerlinefreq, + mousewheelsens; long long pagetime; @@ -189,7 +201,8 @@ recent_file_mtg_path[MAX_RECENTFILES][1024]; double pixelsizefactor, - x_pixelsizefactor; + x_pixelsizefactor, + average_period; struct edfhdrblock *edfheaderlist[MAXFILES]; @@ -213,6 +226,8 @@ UI_FreqSpectrumWindow *spectrumdialog[MAXSPECTRUMDIALOGS]; + UI_AverageCurveWindow *averagecurvedialog[MAXAVERAGECURVEDIALOGS]; + void setup_viewbuf(); void setMainwindowTitle(struct edfhdrblock *); @@ -227,7 +242,8 @@ *monofont; QAction *save_act, - *load_predefined_mtg_act[MAXPREDEFINEDMONTAGES]; + *load_predefined_mtg_act[MAXPREDEFINEDMONTAGES], + *Escape_act; QActionGroup *timelock_act_group, *sel_viewtime_act_group; @@ -295,6 +311,7 @@ *page_user_defined, *page_whole_rec, *fit_to_pane, + *fit_to_dc, *amp_00001, *amp_00002, *amp_00005, @@ -335,7 +352,8 @@ *DisplayGroup, *load_predefined_mtg_group; - QTimer *t1; + QTimer *t1, + *live_stream_timer; QSplashScreen *splash; @@ -356,6 +374,7 @@ #ifdef Q_WS_WIN QString specialFolder(int); #endif + long long check_edf_file_datarecords(struct edfhdrblock *); public slots: void remove_all_signals(); @@ -375,6 +394,7 @@ void set_display_time_whole_rec(); void set_amplitude(QAction *); void fit_signals_to_pane(); + void fit_signals_dc_offset(); void former_page(); void shift_page_left(); void shift_page_right(); @@ -415,6 +435,7 @@ void print_to_img_1600x1200(); void convert_ascii_to_edf(); void convert_fino_to_edf(); + void convert_wave_to_edf(); void convert_nexfin_to_edf(); void edfd_converter(); void slider_moved(int); @@ -433,6 +454,11 @@ void edit_header(); void biosemi2bdfplus_converter(); void import_annotations(); + void open_stream(); + void live_stream_timer_func(); + void organize_signals(); + void Escape_fun(); + void export_ecg_rr_interval_to_ascii(); #ifdef BK_MRS_project // temporary code for private use in a certain project diff -Nru edfbrowser-1.30/nexfin2edf.cpp edfbrowser-1.38/nexfin2edf.cpp --- edfbrowser-1.30/nexfin2edf.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/nexfin2edf.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -37,8 +37,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -66,7 +64,7 @@ PatientnameLabel = new QLabel(myobjectDialog); PatientnameLabel->setGeometry(QRect(20, 20, 140, 16)); - PatientnameLabel->setText("Patient name"); + PatientnameLabel->setText("Subject name"); RecordingLabel = new QLabel(myobjectDialog); RecordingLabel->setGeometry(QRect(20, 50, 140, 16)); @@ -138,7 +136,6 @@ edfsignals=0, ok, timestep, - old_smpl_time, new_smpl_time=0, str_start, column, @@ -186,8 +183,6 @@ file_type = 32; } - old_smpl_time = 0; - for(j=0; jtext().toLatin1().data()))) { - UI_Messagewindow popuperror("Invalid input", "Please enter a patientname."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a subject name."); + messagewindow.exec(); enable_widgets(TRUE); return; } if(!(strlen(RecordingLineEdit->text().toLatin1().data()))) { - UI_Messagewindow popuperror("Invalid input", "Please enter a recordingdescription."); + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a recordingdescription."); + messagewindow.exec(); enable_widgets(TRUE); return; } @@ -236,7 +233,8 @@ if(inputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for reading.", path); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); enable_widgets(TRUE); return; } @@ -249,7 +247,8 @@ if(fread(scratchpad, 32, 1, inputfile)!=1) { - UI_Messagewindow popuperror("Error", "Error reading file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not read from file."); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -257,7 +256,8 @@ if(strncmp(scratchpad, "Time;IBI;HR;LVET;HRS;Sys;Dia;MAP", 32)) { - UI_Messagewindow popuperror("Error", "Unknown data in file (1)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Unknown data in file (1)."); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -273,7 +273,8 @@ if(temp==EOF) { - UI_Messagewindow popuperror("Error", "Reached end of file unexpectedly (5)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Reached end of file unexpectedly (5)."); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -293,7 +294,8 @@ if(temp==EOF) { - UI_Messagewindow popuperror("Error", "Reached end of file unexpectedly (6)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Reached end of file unexpectedly (6)."); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -308,7 +310,8 @@ { if(edfsignals>=MAX_SIGNALS) { - UI_Messagewindow popuperror("Error", "Too many labels/signals (7)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Too many labels/signals (7)."); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -391,7 +394,8 @@ if(!ok) { snprintf(txt_string, 2048, "Found unknown label/signal: %s", line); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -412,7 +416,8 @@ if(!edfsignals) { - UI_Messagewindow popuperror("Error", "There are no labels/signals."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There are no labels/signals."); + messagewindow.exec(); fclose(inputfile); enable_widgets(TRUE); return; @@ -493,7 +498,8 @@ if(outputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for writing.", path); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); enable_widgets(TRUE); fclose(inputfile); return; @@ -679,7 +685,8 @@ if(temp==EOF) { - UI_Messagewindow popuperror("Error", "Reached end of file unexpectedly (8)."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Reached end of file unexpectedly (8)."); + messagewindow.exec(); fclose(inputfile); fclose(outputfile); enable_widgets(TRUE); @@ -760,7 +767,8 @@ { QApplication::restoreOverrideCursor(); snprintf(txt_string, 2048, "Number of separators in line %i is wrong.", line_nr); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); fclose(inputfile); fclose(outputfile); enable_widgets(TRUE); @@ -773,7 +781,8 @@ { QApplication::restoreOverrideCursor(); snprintf(txt_string, 2048, "Timestep <= 0 in line %i.", line_nr); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); fclose(inputfile); fclose(outputfile); enable_widgets(TRUE); @@ -799,8 +808,6 @@ datarecords++; } - old_smpl_time = new_smpl_time; - for(j=0; j #include #include +#include #include #include diff -Nru edfbrowser-1.30/nk2edf.cpp edfbrowser-1.38/nk2edf.cpp --- edfbrowser-1.30/nk2edf.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/nk2edf.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -37,8 +37,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -50,6 +48,11 @@ #endif +#define ELECTRODE_TAG "[ELECTRODE]" +#define ELECTRODE_UNTAG "[" +#define ELECTRODE_NAME_MAXLEN 256 + + @@ -118,6 +121,7 @@ char txt_string[2048], path[1024], + outputpath[1024], logfilepath[1024], pntfilepath[1024], *log_buf=NULL, @@ -341,6 +345,72 @@ } } +/***************** initialize labels **************************************/ + + for(i=0; i<256; i++) + { + strcpy(labels[i], "- "); + } + + strcpy(labels[0], "EEG FP1 "); + strcpy(labels[1], "EEG FP2 "); + strcpy(labels[2], "EEG F3 "); + strcpy(labels[3], "EEG F4 "); + strcpy(labels[4], "EEG C3 "); + strcpy(labels[5], "EEG C4 "); + strcpy(labels[6], "EEG P3 "); + strcpy(labels[7], "EEG P4 "); + strcpy(labels[8], "EEG O1 "); + strcpy(labels[9], "EEG O2 "); + strcpy(labels[10], "EEG F7 "); + strcpy(labels[11], "EEG F8 "); + strcpy(labels[12], "EEG T3 "); + strcpy(labels[13], "EEG T4 "); + strcpy(labels[14], "EEG T5 "); + strcpy(labels[15], "EEG T6 "); + strcpy(labels[16], "EEG FZ "); + strcpy(labels[17], "EEG CZ "); + strcpy(labels[18], "EEG PZ "); + strcpy(labels[19], "EEG E "); + strcpy(labels[20], "EEG PG1 "); + strcpy(labels[21], "EEG PG2 "); + strcpy(labels[22], "EEG A1 "); + strcpy(labels[23], "EEG A2 "); + strcpy(labels[24], "EEG T1 "); + strcpy(labels[25], "EEG T2 "); + for(i=26; i<35; i++) + { + sprintf(labels[i], "EEG X%i ", i - 25); + } + strcpy(labels[35], "EEG X10 "); + strcpy(labels[36], "EEG X11 "); + for(i=42; i<74; i++) + { + sprintf(labels[i], "DC%02i ", i - 41); + } + strcpy(labels[74], "EEG BN1 "); + strcpy(labels[75], "EEG BN2 "); + strcpy(labels[76], "EEG Mark1 "); + strcpy(labels[77], "EEG Mark2 "); + strcpy(labels[100], "EEG X12/BP1 "); + strcpy(labels[101], "EEG X13/BP2 "); + strcpy(labels[102], "EEG X14/BP3 "); + strcpy(labels[103], "EEG X15/BP4 "); + for(i=104; i<188; i++) + { + sprintf(labels[i], "EEG X%i ", i - 88); + } + for(i=188; i<254; i++) + { + sprintf(labels[i], "EEG X%i ", i - 88); + } + strcpy(labels[255], "Z "); + + if(read_21e_file(path)) + { + textEdit1->append("Can not open *.21e file, converter will use default electrode names."); + } + /***************** start conversion **************************************/ total_blocks = 0; @@ -416,13 +486,14 @@ /********************************************************************/ - if(edfplus) sprintf(path + strlen(path) - 4, "_%u-%u+.edf", i + 1, j + 1); - else sprintf(path + strlen(path) - 4, "_%u-%u.edf", i + 1, j + 1); + strcpy(outputpath, path); + if(edfplus) sprintf(outputpath + strlen(path) - 4, "_%u-%u+.edf", i + 1, j + 1); + else sprintf(outputpath + strlen(path) - 4, "_%u-%u.edf", i + 1, j + 1); - outputfile = fopeno(path, "wb"); + outputfile = fopeno(outputpath, "wb"); if(outputfile==NULL) { - snprintf(txt_string, 2048, "can not open file %s for writing.\n", path); + snprintf(txt_string, 2048, "can not open file %s for writing.\n", outputpath); textEdit1->append(txt_string); pushButton1->setEnabled(TRUE); fclose(inputfile); @@ -436,14 +507,14 @@ return; } - textEdit1->append("converting a waveform datablock..."); + textEdit1->append("Converting a waveform datablock..."); for(k=0; k<10; k++) qApp->processEvents(); error = convert_nk2edf(inputfile, outputfile, pntfile, wfmblock_address, edfplus, total_logs, log_buf); if(error==0) { - snprintf(txt_string, 2048, "to %s", path); + snprintf(txt_string, 2048, "to %s", outputpath); textEdit1->append(txt_string); } if(error==1) textEdit1->append("malloc error.\n"); @@ -1092,92 +1163,14 @@ { fseeko(inputfile, (long long)(0x0027 + (i * 10) + offset), SEEK_SET); temp = fgetc(inputfile); - switch(temp) + if((temp < 0) || (temp > 255)) { - case 0 : fprintf(outputfile, "EEG FP1 "); - break; - case 1 : fprintf(outputfile, "EEG FP2 "); - break; - case 2 : fprintf(outputfile, "EEG F3 "); - break; - case 3 : fprintf(outputfile, "EEG F4 "); - break; - case 4 : fprintf(outputfile, "EEG C3 "); - break; - case 5 : fprintf(outputfile, "EEG C4 "); - break; - case 6 : fprintf(outputfile, "EEG P3 "); - break; - case 7 : fprintf(outputfile, "EEG P4 "); - break; - case 8 : fprintf(outputfile, "EEG O1 "); - break; - case 9 : fprintf(outputfile, "EEG O2 "); - break; - case 10 : fprintf(outputfile, "EEG F7 "); - break; - case 11 : fprintf(outputfile, "EEG F8 "); - break; - case 12 : fprintf(outputfile, "EEG T3 "); - break; - case 13 : fprintf(outputfile, "EEG T4 "); - break; - case 14 : fprintf(outputfile, "EEG T5 "); - break; - case 15 : fprintf(outputfile, "EEG T6 "); - break; - case 16 : fprintf(outputfile, "EEG FZ "); - break; - case 17 : fprintf(outputfile, "EEG CZ "); - break; - case 18 : fprintf(outputfile, "EEG PZ "); - break; - case 19 : fprintf(outputfile, "EEG E "); - break; - case 20 : fprintf(outputfile, "EEG PG1 "); - break; - case 21 : fprintf(outputfile, "EEG PG2 "); - break; - case 22 : fprintf(outputfile, "EEG A1 "); - break; - case 23 : fprintf(outputfile, "EEG A2 "); - break; - case 24 : fprintf(outputfile, "EEG T1 "); - break; - case 25 : fprintf(outputfile, "EEG T2 "); - break; - case 35 : fprintf(outputfile, "EEG X10 "); - break; - case 36 : fprintf(outputfile, "EEG X11 "); - break; - case 74 : fprintf(outputfile, "BN1 "); - break; - case 75 : fprintf(outputfile, "BN2 "); - break; - case 76 : fprintf(outputfile, "Mark1 "); - break; - case 77 : fprintf(outputfile, "Mark2 "); - break; - case 100 : fprintf(outputfile, "EEG X12/BP1 "); - break; - case 101 : fprintf(outputfile, "EEG X13/BP2 "); - break; - case 102 : fprintf(outputfile, "EEG X14/BP3 "); - break; - case 103 : fprintf(outputfile, "EEG X15/BP4 "); - break; - case 254 : fprintf(outputfile, "- "); - break; - case 255 : fprintf(outputfile, "Z "); - break; - } - - if((2573)) fprintf(outputfile, "uV "); + if(((temp<42)||(temp>73)) && (temp!=76) && (temp!=77)) fprintf(outputfile, "uV "); else fprintf(outputfile, "mV "); } if(edfplus) fprintf(outputfile, " "); @@ -1198,7 +1191,7 @@ { fseeko(inputfile, (long long)(0x0027 + (i * 10) + offset), SEEK_SET); temp = fgetc(inputfile); - if((temp<42)||(temp>73)) fprintf(outputfile, "-3200 "); + if(((temp<42)||(temp>73)) && (temp!=76) && (temp!=77)) fprintf(outputfile, "-3200 "); else fprintf(outputfile, "-12002.9"); } if(edfplus) fprintf(outputfile, "-1 "); @@ -1207,7 +1200,7 @@ { fseeko(inputfile, (long long)(0x0027 + (i * 10) + offset), SEEK_SET); temp = fgetc(inputfile); - if((temp<42)||(temp>73)) fprintf(outputfile, "3199.902"); + if(((temp<42)||(temp>73)) && (temp!=76) && (temp!=77)) fprintf(outputfile, "3199.902"); else fprintf(outputfile, "12002.56"); } if(edfplus) fprintf(outputfile, "1 "); @@ -1353,6 +1346,120 @@ } +int UI_NK2EDFwindow::read_21e_file(char *e21filepath) +{ + int n, + flag_eleclines=0, + idx; + + char *electrode_name, + electrode_name_buffer[ELECTRODE_NAME_MAXLEN], + scratchpad[64], + *charpntr; + + FILE *inputfile; + + + remove_extension_from_filename(e21filepath); + strcat(e21filepath, ".21E"); + inputfile = fopeno(e21filepath, "rb"); + if(inputfile==NULL) + { + remove_extension_from_filename(e21filepath); + strcat(e21filepath, ".21e"); + inputfile = fopeno(e21filepath, "rb"); + if(inputfile==NULL) + { + return(1); + } + } + + while (!feof(inputfile)) + { + charpntr = fgets(electrode_name_buffer, ELECTRODE_NAME_MAXLEN-1, inputfile); + + if(charpntr == NULL) + { + break; + } + + if(strncmp(electrode_name_buffer, ELECTRODE_TAG, strlen(ELECTRODE_TAG)) == 0) + { + flag_eleclines = 1; + } + else + { + if(strncmp(electrode_name_buffer, ELECTRODE_UNTAG, strlen(ELECTRODE_UNTAG)) == 0) + { + flag_eleclines = 0; + } + } + + if(flag_eleclines) + { + if(strtok(electrode_name_buffer, "=") != NULL) + { + idx = atoi(electrode_name_buffer); + + electrode_name = strtok(NULL, "="); + + if(electrode_name != NULL) + { + n = strlen(electrode_name); + + if((n > 0)&&(electrode_name[n-1] == 10)) + { + electrode_name[n-1] = 0; + } + + if((n > 1)&&(electrode_name[n-2] == 13)) + { + electrode_name[n-2] = 0; + } + + n = strlen(electrode_name); + + if((idx >= 0) && (idx < 256)) + { + if(n > 0) + { + strncpy(scratchpad, electrode_name, 16); + + strcat(scratchpad, " "); + + latin1_to_ascii(scratchpad, 16); + + scratchpad[16] = 0; + + strcpy(labels[idx], scratchpad); + } + else + { + strcpy(labels[idx], "- "); + } + } + } + } + } + } + + fclose(inputfile); + + return(0); +} + + + + + + + + + + + + + diff -Nru edfbrowser-1.30/nk2edf.h edfbrowser-1.38/nk2edf.h --- edfbrowser-1.30/nk2edf.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/nk2edf.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -78,10 +78,13 @@ int total_elapsed_time; -char *recent_opendir; +char *recent_opendir, + labels[256][17]; int check_device(char *); +int read_21e_file(char *); + private slots: void SelectFileButton(); diff -Nru edfbrowser-1.30/options_dialog.cpp edfbrowser-1.38/options_dialog.cpp --- edfbrowser-1.30/options_dialog.cpp 2010-11-23 14:07:47.000000000 +0000 +++ edfbrowser-1.38/options_dialog.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -204,7 +204,7 @@ } DefaultButton = new QPushButton(tab1); - DefaultButton->setGeometry(QRect(20, 650, 100, 25)); + DefaultButton->setGeometry(QRect(140, 620, 140, 25)); DefaultButton->setText("Restore default"); QObject::connect(BgColorButton, SIGNAL(clicked(SpecialButton *)), this, SLOT(BgColorButtonClicked(SpecialButton *))); @@ -443,6 +443,54 @@ QObject::connect(checkbox4_2, SIGNAL(stateChanged(int)), this, SLOT(checkbox4_2Clicked(int))); + label4_3 = new QLabel(tab4); + label4_3->setGeometry(QRect(20, 100, 200, 25)); + label4_3->setText("livestream update interval"); + + spinbox4_1 = new QSpinBox(tab4); + spinbox4_1->setGeometry(QRect(200, 100, 140, 20)); + spinbox4_1->setSuffix(" mSec"); + spinbox4_1->setMinimum(100); + spinbox4_1->setMaximum(3000); + spinbox4_1->setSingleStep(1); + spinbox4_1->setValue(mainwindow->live_stream_update_interval); + + QObject::connect(spinbox4_1, SIGNAL(valueChanged(int)), this, SLOT(spinBox4_1ValueChanged(int))); + + label4_4 = new QLabel(tab4); + label4_4->setGeometry(QRect(20, 140, 200, 25)); + label4_4->setText("Powerline Frequency"); + + combobox4_1 = new QComboBox(tab4); + combobox4_1->setGeometry(QRect(200, 140, 140, 20)); + combobox4_1->addItem("50 Hz"); + combobox4_1->addItem("60 Hz"); + if(mainwindow->powerlinefreq == 50) + { + combobox4_1->setCurrentIndex(0); + } + if(mainwindow->powerlinefreq == 60) + { + combobox4_1->setCurrentIndex(1); + } + + QObject::connect(combobox4_1, SIGNAL(currentIndexChanged(int)), this, SLOT(combobox4_1IndexChanged(int))); + + label4_4 = new QLabel(tab4); + label4_4->setGeometry(QRect(20, 180, 200, 40)); + label4_4->setText("Mousewheel stepsize\n" + "(0 means no scroll)"); + + spinbox4_2 = new QSpinBox(tab4); + spinbox4_2->setGeometry(QRect(200, 180, 140, 20)); + spinbox4_2->setPrefix("Timescale / "); + spinbox4_2->setMinimum(0); + spinbox4_2->setMaximum(100); + spinbox4_2->setSingleStep(1); + spinbox4_2->setValue(mainwindow->mousewheelsens); + + QObject::connect(spinbox4_2, SIGNAL(valueChanged(int)), this, SLOT(spinBox4_2ValueChanged(int))); + tabholder->addTab(tab4, "Other"); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -463,6 +511,32 @@ } +void UI_OptionsDialog::spinBox4_2ValueChanged(int stepsize) +{ + mainwindow->mousewheelsens = stepsize; +} + + +void UI_OptionsDialog::combobox4_1IndexChanged(int index) +{ + if(index == 0) + { + mainwindow->powerlinefreq = 50; + } + + if(index == 1) + { + mainwindow->powerlinefreq = 60; + } +} + + +void UI_OptionsDialog::spinBox4_1ValueChanged(int interval) +{ + mainwindow->live_stream_update_interval = interval; +} + + void UI_OptionsDialog::calibrate_checkbox_stateChanged(int state) { if(state == Qt::Checked) @@ -548,7 +622,8 @@ { sprintf(str, "Row %i must have a higher frequency than row %i", row + 1, row); - UI_Messagewindow popup("Error", str); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); return; } diff -Nru edfbrowser-1.30/options_dialog.h edfbrowser-1.38/options_dialog.h --- edfbrowser-1.30/options_dialog.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/options_dialog.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -56,6 +56,8 @@ #include #include #include +#include +#include #include "global.h" #include "mainwindow.h" @@ -129,6 +131,9 @@ *label13, *label4_1, *label4_2, + *label4_3, + *label4_4, + *label4_5, *label2_2, *label2_4, *label1_3, @@ -138,7 +143,11 @@ QSpinBox *spinbox2_1, *spinbox2_2, - *spinbox3_1; + *spinbox3_1, + *spinbox4_1, + *spinbox4_2; + +QComboBox *combobox4_1; QCheckBox *checkbox1, *checkbox2, @@ -186,6 +195,9 @@ void spinBox3_3ValueChanged(int); void labelEdited(const QString &); void calibrate_checkbox_stateChanged(int); +void spinBox4_1ValueChanged(int); +void combobox4_1IndexChanged(int); +void spinBox4_2ValueChanged(int); }; diff -Nru edfbrowser-1.30/pagetime_dialog.cpp edfbrowser-1.38/pagetime_dialog.cpp --- edfbrowser-1.30/pagetime_dialog.cpp 2010-11-23 09:01:59.000000000 +0000 +++ edfbrowser-1.38/pagetime_dialog.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/pagetime_dialog.h edfbrowser-1.38/pagetime_dialog.h --- edfbrowser-1.30/pagetime_dialog.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/pagetime_dialog.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -46,6 +46,7 @@ #include #include #include +#include #include diff -Nru edfbrowser-1.30/popup_messagewindow.cpp edfbrowser-1.38/popup_messagewindow.cpp --- edfbrowser-1.30/popup_messagewindow.cpp 2010-11-23 10:43:18.000000000 +0000 +++ edfbrowser-1.38/popup_messagewindow.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/popup_messagewindow.h edfbrowser-1.38/popup_messagewindow.h --- edfbrowser-1.30/popup_messagewindow.h 2010-11-23 10:50:18.000000000 +0000 +++ edfbrowser-1.38/popup_messagewindow.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/popup_save_cancelwindow.cpp edfbrowser-1.38/popup_save_cancelwindow.cpp --- edfbrowser-1.30/popup_save_cancelwindow.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/popup_save_cancelwindow.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/popup_save_cancelwindow.h edfbrowser-1.38/popup_save_cancelwindow.h --- edfbrowser-1.30/popup_save_cancelwindow.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/popup_save_cancelwindow.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/print_to_bdf.cpp edfbrowser-1.38/print_to_bdf.cpp --- edfbrowser-1.30/print_to_bdf.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/print_to_bdf.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -36,8 +36,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -61,13 +59,11 @@ signalcomps, duration_factor[MAXFILES], temp=0, - dig_value, bdfplus=0, tallen, annotationlist_nr=0, annotations_left=1, add_one_sec=0, - add_one_sec_advanced=0, annot_smp_per_record=16, type, len; @@ -87,7 +83,8 @@ *viewbuf; double frequency, - frequency2; + frequency2, + dig_value; FILE *outputfile; @@ -128,7 +125,8 @@ if((!mainwindow->files_open)||(!signalcomps)) { - UI_Messagewindow popuperror("Print to BDF", "Put a signal on the screen and try again."); + QMessageBox messagewindow(QMessageBox::Critical, "Print to BDF", "Put a signal on the screen and try again."); + messagewindow.exec(); return; } @@ -136,7 +134,8 @@ { if(mainwindow->edfheaderlist[i]->discontinuous) { - UI_Messagewindow popuperror("Print to BDF", "Sorry, discontinues BDF/EDF files can not be printed to BDF.\n"); + QMessageBox messagewindow(QMessageBox::Critical, "Print to BDF", "Sorry, discontinues BDF/EDF files can not be printed to BDF.\n"); + messagewindow.exec(); return; } @@ -172,7 +171,8 @@ fseeko(signalcomp[n]->edfhdr->file_hdl, 244LL, SEEK_SET); if(fread(datrecduration, 8, 1, signalcomp[n]->edfhdr->file_hdl)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while reading from inputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); return; } @@ -182,8 +182,9 @@ { if(duration % signalcomp[i]->edfhdr->long_data_record_duration) { - UI_Messagewindow popuperror("Print to BDF", "This combination of files can not be printed to EDF\n" - "because the quotient of the datarecordblock durations is not an integer."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "This combination of files can not be printed to EDF\n" + "because the quotient of the datarecordblock durations is not an integer."); + messagewindow.exec(); return; } @@ -214,14 +215,16 @@ if(mainwindow->file_is_opened(path)) { - UI_Messagewindow popuperror("Print to BDF", "Error, selected file is in use."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, selected file is in use."); + messagewindow.exec(); return; } outputfile = fopeno(path, "wb"); if(outputfile==NULL) { - UI_Messagewindow popuperror("Print to BDF", "Error, can not create a file for writing."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not create a file for writing."); + messagewindow.exec(); return; } @@ -236,8 +239,6 @@ referencetime--; add_one_sec = 1; - - add_one_sec_advanced = 1; } } else @@ -265,14 +266,16 @@ { if(fread(scratchpad, 80, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while reading from inputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad, 80, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -282,14 +285,16 @@ fprintf(outputfile, "X X X X "); if(fread(scratchpad, 80, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while reading from inputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad, 72, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -333,7 +338,8 @@ { if(fread(scratchpad, 80, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while reading from inputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -342,7 +348,8 @@ { if(fwrite(scratchpad + 12, 58, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -351,7 +358,8 @@ { if(fwrite(scratchpad + 22, 58, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -363,14 +371,16 @@ if(fread(scratchpad, 80, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while reading from inputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad + 28, 52, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -380,7 +390,8 @@ { if(fread(scratchpad, 160, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while reading from inputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -391,7 +402,8 @@ if(fwrite(scratchpad, 160, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -430,7 +442,8 @@ if(fwrite(datrecduration, 8, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -439,19 +452,12 @@ for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].label, "EEG ", 4)) - { - strcpy(scratchpad, signalcomp[i]->signallabel); - } - else - { - strcpy(scratchpad, "EEG "); - strcat(scratchpad, signalcomp[i]->signallabel); - } + strcpy(scratchpad, signalcomp[i]->signallabel); strcat(scratchpad, " "); if(fwrite(scratchpad, 16, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -461,7 +467,8 @@ { if(fwrite("BDF Annotations ", 16, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -471,7 +478,8 @@ { if(fwrite(signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].transducer, 80, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -484,9 +492,12 @@ for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].physdimension, 8, 1, outputfile)!=1) + strcpy(scratchpad, signalcomp[i]->physdimension); + strcat(scratchpad, " "); + if(fwrite(scratchpad, 8, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -499,18 +510,33 @@ for(i=0; iedfhdr->file_hdl, (long long)((signalcomp[i]->edfsignal[0] * 8) + (104 * signalcomp[i]->edfhdr->edfsignals) + 256), SEEK_SET); - if(fread(scratchpad, 8, 1, signalcomp[i]->edfhdr->file_hdl)!=1) + if(signalcomp[i]->ecg_filter == NULL) { - UI_Messagewindow popuperror("Print to BDF", "Error while reading from inputfile."); - fclose(outputfile); - return; + fseeko(signalcomp[i]->edfhdr->file_hdl, (long long)((signalcomp[i]->edfsignal[0] * 8) + (104 * signalcomp[i]->edfhdr->edfsignals) + 256), SEEK_SET); + if(fread(scratchpad, 8, 1, signalcomp[i]->edfhdr->file_hdl)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); + fclose(outputfile); + return; + } + if(fwrite(scratchpad, 8, 1, outputfile)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); + fclose(outputfile); + return; + } } - if(fwrite(scratchpad, 8, 1, outputfile)!=1) + else { - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); - fclose(outputfile); - return; + if(fwrite("0 ", 8, 1, outputfile)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); + fclose(outputfile); + return; + } } } @@ -518,7 +544,8 @@ { if(fwrite("-1 ", 8, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -526,18 +553,33 @@ for(i=0; iedfhdr->file_hdl, (long long)((signalcomp[i]->edfsignal[0] * 8) + (112 * signalcomp[i]->edfhdr->edfsignals) + 256), SEEK_SET); - if(fread(scratchpad, 8, 1, signalcomp[i]->edfhdr->file_hdl)!=1) + if(signalcomp[i]->ecg_filter == NULL) { - UI_Messagewindow popuperror("Print to BDF", "Error while reading from inputfile."); - fclose(outputfile); - return; + fseeko(signalcomp[i]->edfhdr->file_hdl, (long long)((signalcomp[i]->edfsignal[0] * 8) + (112 * signalcomp[i]->edfhdr->edfsignals) + 256), SEEK_SET); + if(fread(scratchpad, 8, 1, signalcomp[i]->edfhdr->file_hdl)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); + fclose(outputfile); + return; + } + if(fwrite(scratchpad, 8, 1, outputfile)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); + fclose(outputfile); + return; + } } - if(fwrite(scratchpad, 8, 1, outputfile)!=1) + else { - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); - fclose(outputfile); - return; + if(fwrite("1000 ", 8, 1, outputfile)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); + fclose(outputfile); + return; + } } } @@ -545,7 +587,8 @@ { if(fwrite("1 ", 8, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -553,15 +596,30 @@ for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min); - - if(signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min<0) + if(signalcomp[i]->ecg_filter == NULL) { - null_bytes[i].one_signed = 0; + fprintf(outputfile, "%-8i", signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min); + + if(signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min<0) + { + null_bytes[i].one_signed = 0; + } + else + { + null_bytes[i].one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min; + } } else { - null_bytes[i].one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min; + if(fwrite("-8388608", 8, 1, outputfile)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); + fclose(outputfile); + return; + } + + null_bytes[i].one_signed = -8388608; } } @@ -569,7 +627,8 @@ { if(fwrite("-8388608", 8, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -577,14 +636,28 @@ for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max); + if(signalcomp[i]->ecg_filter == NULL) + { + fprintf(outputfile, "%-8i", signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max); + } + else + { + if(fwrite("8388607 ", 8, 1, outputfile)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); + fclose(outputfile); + return; + } + } } if(bdfplus) { if(fwrite("8388607 ", 8, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -691,6 +764,28 @@ if(p>80) break; } + for(j=0; jravg_filter_cnt; j++) + { + if(signalcomp[i]->ravg_filter_type[j] == 0) + { + p += sprintf(scratchpad + p, "HP:%iSmpls ", signalcomp[i]->ravg_filter[j]->size); + } + + if(signalcomp[i]->ravg_filter_type[j] == 1) + { + p += sprintf(scratchpad + p, "LP:%iSmpls ", signalcomp[i]->ravg_filter[j]->size); + } + + p = strlen(scratchpad); + + if(p>80) break; + } + + if(signalcomp[i]->ecg_filter != NULL) + { + p += sprintf(scratchpad + p, "ECG:HR "); + } + for(;p<81; p++) { scratchpad[p] = ' '; @@ -698,7 +793,8 @@ if(fwrite(scratchpad, 80, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -770,7 +866,8 @@ if(fputc(null_bytes[i].four[2], outputfile)==EOF) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -855,6 +952,19 @@ dig_value = first_order_filter(dig_value, signalcomp[i]->filter[p]); } + for(p=0; pravg_filter_cnt; p++) + { + if(smpls_written[i]==signalcomp[i]->sample_start) + { + if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime!=0) + { + ravg_filter_restore_buf(signalcomp[i]->ravg_filter[p]); + } + } + + dig_value = run_ravg_filter(dig_value, signalcomp[i]->ravg_filter[p]); + } + for(p=0; pfidfilter_cnt; p++) { if(smpls_written[i]==signalcomp[i]->sample_start) @@ -868,24 +978,55 @@ dig_value = signalcomp[i]->fidfuncp[p](signalcomp[i]->fidbuf[p], dig_value); } + if(signalcomp[i]->ecg_filter != NULL) + { + if(smpls_written[i]==signalcomp[i]->sample_start) + { + if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime != 0) + { + ecg_filter_restore_buf(signalcomp[i]->ecg_filter); + } + } + + dig_value = run_ecg_filter(dig_value, signalcomp[i]->ecg_filter); + + dig_value = (dig_value * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue * 16777.216) - 8388608.0; + } + if((smpls_written[i]>=signalcomp[i]->sample_start)&&(smpls_written[i]sample_stop)) { - if(dig_value>signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max) + wr_var.one_signed = dig_value; + + if(signalcomp[i]->ecg_filter == NULL) { - dig_value = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max; + if(wr_var.one_signed>signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max) + { + wr_var.one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max; + } + if(wr_var.one_signededfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min) + { + wr_var.one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min; + } } - if(dig_valueedfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min) + else { - dig_value = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min; + if(wr_var.one_signed > 8388607) + { + wr_var.one_signed = 8388607; + } + if(wr_var.one_signed < -8388608) + { + wr_var.one_signed = -8388608; + } } - wr_var.one_signed = dig_value; fputc(wr_var.four[0], outputfile); fputc(wr_var.four[1], outputfile); if(fputc(wr_var.four[2], outputfile)==EOF) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -897,7 +1038,8 @@ if(fputc(null_bytes[i].four[2], outputfile)==EOF) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Print to BDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } diff -Nru edfbrowser-1.30/print_to_bdf.h edfbrowser-1.38/print_to_bdf.h --- edfbrowser-1.30/print_to_bdf.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/print_to_bdf.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -39,6 +39,7 @@ #include #include +#include #include #include diff -Nru edfbrowser-1.30/print_to_edf.cpp edfbrowser-1.38/print_to_edf.cpp --- edfbrowser-1.30/print_to_edf.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/print_to_edf.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -36,8 +36,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -61,13 +59,11 @@ signalcomps, duration_factor[MAXFILES], temp=0, - dig_value, edfplus=0, tallen, annotationlist_nr=0, annotations_left=1, add_one_sec=0, - add_one_sec_advanced=0, annot_smp_per_record=16, type, len; @@ -87,7 +83,8 @@ *viewbuf; double frequency, - frequency2; + frequency2, + dig_value; FILE *outputfile; @@ -95,8 +92,9 @@ struct signalcompblock **signalcomp; union { - signed short one_signed; - unsigned char two[2]; + signed int one_signed; + signed short two_signed[2]; + unsigned char four[4]; } wr_var; union { @@ -118,7 +116,8 @@ if((!mainwindow->files_open)||(!signalcomps)) { - UI_Messagewindow popuperror("Print to EDF", "Put a signal on the screen and try again."); + QMessageBox messagewindow(QMessageBox::Critical, "Print to EDF", "Put a signal on the screen and try again."); + messagewindow.exec(); return; } @@ -126,13 +125,15 @@ { if(mainwindow->edfheaderlist[i]->bdf) { - UI_Messagewindow popuperror("Print to EDF", "BDF files can not be printed to EDF.\n"); + QMessageBox messagewindow(QMessageBox::Critical, "Print to EDF", "BDF files can not be printed to EDF."); + messagewindow.exec(); return; } if(mainwindow->edfheaderlist[i]->discontinuous) { - UI_Messagewindow popuperror("Print to EDF", "Sorry, discontinues EDF files can not be printed to EDF.\n"); + QMessageBox messagewindow(QMessageBox::Critical, "Print to EDF", "Sorry, discontinues EDF files can not be printed to EDF."); + messagewindow.exec(); return; } @@ -168,7 +169,8 @@ fseeko(signalcomp[n]->edfhdr->file_hdl, 244LL, SEEK_SET); if(fread(datrecduration, 8, 1, signalcomp[n]->edfhdr->file_hdl)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while reading from inputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); return; } @@ -178,9 +180,9 @@ { if(duration % signalcomp[i]->edfhdr->long_data_record_duration) { - UI_Messagewindow popuperror("Print to EDF", "This combination of files can not be printed to EDF\n" - "because the quotient of the datarecordblock durations of these files\n" - "is not an integer."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "This combination of files can not be printed to EDF\n" + "because the quotient of the datarecordblock durations is not an integer."); + messagewindow.exec(); return; } @@ -211,14 +213,16 @@ if(mainwindow->file_is_opened(path)) { - UI_Messagewindow popuperror("Print to EDF", "Error, selected file is in use."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, selected file is in use."); + messagewindow.exec(); return; } outputfile = fopeno(path, "wb"); if(outputfile==NULL) { - UI_Messagewindow popuperror("Print to EDF", "Error, can not create a file for writing."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not create a file for writing."); + messagewindow.exec(); return; } @@ -233,8 +237,6 @@ referencetime--; add_one_sec = 1; - - add_one_sec_advanced = 1; } } else @@ -265,14 +267,16 @@ { if(fread(scratchpad, 88, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while reading from inputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad, 88, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -283,14 +287,16 @@ if(fread(scratchpad, 88, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while reading from inputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad + 8, 72, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -334,7 +340,8 @@ { if(fread(scratchpad, 80, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while reading from inputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -343,7 +350,8 @@ { if(fwrite(scratchpad + 12, 58, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -352,7 +360,8 @@ { if(fwrite(scratchpad + 22, 58, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -364,14 +373,16 @@ if(fread(scratchpad, 80, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while reading from inputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad + 28, 52, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -381,14 +392,16 @@ { if(fread(scratchpad, 168, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while reading from inputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad, 168, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -424,7 +437,8 @@ if(fwrite(datrecduration, 8, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -433,19 +447,12 @@ for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].label, "EEG ", 4)) - { - strcpy(scratchpad, signalcomp[i]->signallabel); - } - else - { - strcpy(scratchpad, "EEG "); - strcat(scratchpad, signalcomp[i]->signallabel); - } + strcpy(scratchpad, signalcomp[i]->signallabel); strcat(scratchpad, " "); if(fwrite(scratchpad, 16, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -455,7 +462,8 @@ { if(fwrite("EDF Annotations ", 16, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -465,7 +473,8 @@ { if(fwrite(signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].transducer, 80, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -478,9 +487,12 @@ for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].physdimension, 8, 1, outputfile)!=1) + strcpy(scratchpad, signalcomp[i]->physdimension); + strcat(scratchpad, " "); + if(fwrite(scratchpad, 8, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -493,18 +505,33 @@ for(i=0; iedfhdr->file_hdl, (long long)((signalcomp[i]->edfsignal[0] * 8) + (104 * signalcomp[i]->edfhdr->edfsignals) + 256), SEEK_SET); - if(fread(scratchpad, 8, 1, signalcomp[i]->edfhdr->file_hdl)!=1) + if(signalcomp[i]->ecg_filter == NULL) { - UI_Messagewindow popuperror("Print to EDF", "Error while reading from inputfile."); - fclose(outputfile); - return; + fseeko(signalcomp[i]->edfhdr->file_hdl, (long long)((signalcomp[i]->edfsignal[0] * 8) + (104 * signalcomp[i]->edfhdr->edfsignals) + 256), SEEK_SET); + if(fread(scratchpad, 8, 1, signalcomp[i]->edfhdr->file_hdl)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); + fclose(outputfile); + return; + } + if(fwrite(scratchpad, 8, 1, outputfile)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); + fclose(outputfile); + return; + } } - if(fwrite(scratchpad, 8, 1, outputfile)!=1) + else { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); - fclose(outputfile); - return; + if(fwrite("0 ", 8, 1, outputfile)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); + fclose(outputfile); + return; + } } } @@ -512,7 +539,8 @@ { if(fwrite("-1 ", 8, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -520,18 +548,33 @@ for(i=0; iedfhdr->file_hdl, (long long)((signalcomp[i]->edfsignal[0] * 8) + (112 * signalcomp[i]->edfhdr->edfsignals) + 256), SEEK_SET); - if(fread(scratchpad, 8, 1, signalcomp[i]->edfhdr->file_hdl)!=1) + if(signalcomp[i]->ecg_filter == NULL) { - UI_Messagewindow popuperror("Print to EDF", "Error while reading from inputfile."); - fclose(outputfile); - return; + fseeko(signalcomp[i]->edfhdr->file_hdl, (long long)((signalcomp[i]->edfsignal[0] * 8) + (112 * signalcomp[i]->edfhdr->edfsignals) + 256), SEEK_SET); + if(fread(scratchpad, 8, 1, signalcomp[i]->edfhdr->file_hdl)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); + fclose(outputfile); + return; + } + if(fwrite(scratchpad, 8, 1, outputfile)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); + fclose(outputfile); + return; + } } - if(fwrite(scratchpad, 8, 1, outputfile)!=1) + else { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); - fclose(outputfile); - return; + if(fwrite("1000 ", 8, 1, outputfile)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); + fclose(outputfile); + return; + } } } @@ -539,7 +582,8 @@ { if(fwrite("1 ", 8, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -547,15 +591,30 @@ for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min); - - if(signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min<0) + if(signalcomp[i]->ecg_filter == NULL) { - null_bytes[i].one_signed = 0; + fprintf(outputfile, "%-8i", signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min); + + if(signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min<0) + { + null_bytes[i].one_signed = 0; + } + else + { + null_bytes[i].one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min; + } } else { - null_bytes[i].one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min; + if(fwrite("-32768 ", 8, 1, outputfile)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); + fclose(outputfile); + return; + } + + null_bytes[i].one_signed = -32768; } } @@ -563,7 +622,8 @@ { if(fwrite("-32768 ", 8, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -571,14 +631,28 @@ for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max); + if(signalcomp[i]->ecg_filter == NULL) + { + fprintf(outputfile, "%-8i", signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max); + } + else + { + if(fwrite("32767 ", 8, 1, outputfile)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); + fclose(outputfile); + return; + } + } } if(edfplus) { if(fwrite("32767 ", 8, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -685,6 +759,28 @@ if(p>80) break; } + for(j=0; jravg_filter_cnt; j++) + { + if(signalcomp[i]->ravg_filter_type[j] == 0) + { + p += sprintf(scratchpad + p, "HP:%iSmpls ", signalcomp[i]->ravg_filter[j]->size); + } + + if(signalcomp[i]->ravg_filter_type[j] == 1) + { + p += sprintf(scratchpad + p, "LP:%iSmpls ", signalcomp[i]->ravg_filter[j]->size); + } + + p = strlen(scratchpad); + + if(p>80) break; + } + + if(signalcomp[i]->ecg_filter != NULL) + { + p += sprintf(scratchpad + p, "ECG:HR "); + } + for(;p<81; p++) { scratchpad[p] = ' '; @@ -692,7 +788,8 @@ if(fwrite(scratchpad, 80, 1, outputfile)!=1) { - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -758,7 +855,8 @@ if(fputc(null_bytes[i].two[1], outputfile)==EOF) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -814,6 +912,19 @@ dig_value = first_order_filter(dig_value, signalcomp[i]->filter[p]); } + for(p=0; pravg_filter_cnt; p++) + { + if(smpls_written[i]==signalcomp[i]->sample_start) + { + if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime!=0) + { + ravg_filter_restore_buf(signalcomp[i]->ravg_filter[p]); + } + } + + dig_value = run_ravg_filter(dig_value, signalcomp[i]->ravg_filter[p]); + } + for(p=0; pfidfilter_cnt; p++) { if(smpls_written[i]==signalcomp[i]->sample_start) @@ -827,23 +938,54 @@ dig_value = signalcomp[i]->fidfuncp[p](signalcomp[i]->fidbuf[p], dig_value); } + if(signalcomp[i]->ecg_filter != NULL) + { + if(smpls_written[i]==signalcomp[i]->sample_start) + { + if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime != 0) + { + ecg_filter_restore_buf(signalcomp[i]->ecg_filter); + } + } + + dig_value = run_ecg_filter(dig_value, signalcomp[i]->ecg_filter); + + dig_value = (dig_value * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue * 65.536) - 32768.0; + } + if((smpls_written[i]>=signalcomp[i]->sample_start)&&(smpls_written[i]sample_stop)) { - if(dig_value>signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max) + wr_var.one_signed = dig_value; + + if(signalcomp[i]->ecg_filter == NULL) { - dig_value = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max; + if(wr_var.one_signed>signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max) + { + wr_var.one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max; + } + if(wr_var.one_signededfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min) + { + wr_var.one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min; + } } - if(dig_valueedfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min) + else { - dig_value = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min; + if(wr_var.one_signed > 32767) + { + wr_var.one_signed = 32767; + } + if(wr_var.one_signed < -32768) + { + wr_var.one_signed = -32768; + } } - wr_var.one_signed = dig_value; - fputc(wr_var.two[0], outputfile); - if(fputc(wr_var.two[1], outputfile)==EOF) + fputc(wr_var.four[0], outputfile); + if(fputc(wr_var.four[1], outputfile)==EOF) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } @@ -854,7 +996,8 @@ if(fputc(null_bytes[i].two[1], outputfile)==EOF) { QApplication::restoreOverrideCursor(); - UI_Messagewindow popuperror("Print to EDF", "Error while writing to outputfile."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); + messagewindow.exec(); fclose(outputfile); return; } diff -Nru edfbrowser-1.30/print_to_edf.h edfbrowser-1.38/print_to_edf.h --- edfbrowser-1.30/print_to_edf.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/print_to_edf.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -39,6 +39,7 @@ #include #include +#include #include #include diff -Nru edfbrowser-1.30/ravg_filter.cpp edfbrowser-1.38/ravg_filter.cpp --- edfbrowser-1.30/ravg_filter.cpp 1970-01-01 00:00:00.000000000 +0000 +++ edfbrowser-1.38/ravg_filter.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -0,0 +1,202 @@ +/* +*************************************************************************** +* +* Author: Teunis van Beelen +* +* Copyright (C) 2010, 2011 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. +* +*************************************************************************** +* +* The current version of GPL is at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt +* +*************************************************************************** +*/ + + + + +#include "ravg_filter.h" + + + + +struct ravg_filter_settings * create_ravg_filter(int type, int size) +{ + struct ravg_filter_settings *settings; + + if((size < 2) || (size > 10000)) return(NULL); + + if((type < 0) || (type > 1)) return(NULL); + + settings = (struct ravg_filter_settings *) calloc(1, sizeof(struct ravg_filter_settings)); + if(settings==NULL) return(NULL); + + settings->size = size; + settings->type = type; + settings->first_sample = 1; + settings->buf_pntr = 0; + settings->buf_pntr2 = 0; + settings->mean = 0.0; + settings->mean2 = 0.0; + settings->buf = (double *)calloc(1, sizeof(double) * size); + if(settings->buf == NULL) + { + free(settings); + return(NULL); + } + settings->buf2 = (double *)calloc(1, sizeof(double) * size); + if(settings->buf2 == NULL) + { + free(settings->buf); + free(settings); + return(NULL); + } + + return(settings); +} + + +void reset_ravg_filter(double offset, struct ravg_filter_settings *settings) +{ + int i; + + for(i=0; isize; i++) + { + settings->buf[i] = offset; + } + + memcpy(settings->buf2, settings->buf, settings->size * sizeof(double)); + + settings->mean = offset; + + settings->mean2 = offset; + + settings->buf_pntr = 0; + + settings->buf_pntr2 = 0; +} + + +void ravg_filter_restore_buf(struct ravg_filter_settings *settings) +{ + memcpy(settings->buf, settings->buf2, settings->size * sizeof(double)); + + settings->mean = settings->mean2; + + settings->buf_pntr = settings->buf_pntr2; +} + + +void ravg_filter_save_buf(struct ravg_filter_settings *settings) +{ + memcpy(settings->buf2, settings->buf, settings->size * sizeof(double)); + + settings->mean2 = settings->mean; + + settings->buf_pntr2 = settings->buf_pntr; +} + + +double run_ravg_filter(double new_input, struct ravg_filter_settings *settings) +{ + int i; + + + if(settings->first_sample) + { + settings->first_sample = 0; + + for(i=0; isize; i++) + { + settings->buf[i] = new_input; + } + + settings->mean = new_input; + + return(new_input); + } + + settings->mean -= (settings->buf[settings->buf_pntr] / settings->size); + + settings->buf[settings->buf_pntr] = new_input; + + settings->buf_pntr++; + + if(settings->buf_pntr >= settings->size) + { + settings->buf_pntr = 0; + } + + settings->mean += (new_input / settings->size); + + if(settings->type == 0) /* highpass */ + { + return(settings->buf[(settings->buf_pntr + (settings->size / 2)) % settings->size] - settings->mean); + } + + if(settings->type == 1) /* lowpass */ + { + return(settings->mean); + } + + return(0.0); +} + + +void free_ravg_filter(struct ravg_filter_settings *settings) +{ + free(settings->buf); + free(settings->buf2); + free(settings); +} + + +double ravg_filter_response(int type, int size, double freq) +{ + if((type < 0) || (type > 1) || (size < 2) || (freq > 0.5)) + { + return(1.0); + } + + if(type) + { + if(freq < 0.000001) + { + return(1.0); + } + + return(fabs((sin(M_PI * freq * (double)size)) / ((double)size * sin(M_PI * freq)))); + } + + if(freq < 0.000001) + { + return(0.0); + } + + return(1.0 - fabs((sin(M_PI * freq * (double)size)) / ((double)size * sin(M_PI * freq)))); +} + + + + + + + + diff -Nru edfbrowser-1.30/ravg_filter.h edfbrowser-1.38/ravg_filter.h --- edfbrowser-1.30/ravg_filter.h 1970-01-01 00:00:00.000000000 +0000 +++ edfbrowser-1.38/ravg_filter.h 2011-08-23 20:01:14.000000000 +0000 @@ -0,0 +1,75 @@ +/* +*************************************************************************** +* +* Author: Teunis van Beelen +* +* Copyright (C) 2010, 2011 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 +* +*************************************************************************** +*/ + + + + + + + +#ifndef ravg_filter_INCLUDED +#define ravg_filter_INCLUDED + + + +#include +#include +#include + + + + +struct ravg_filter_settings{ + int size; + int type; + int first_sample; + double *buf; + double *buf2; + int buf_pntr; + int buf_pntr2; + double mean; + double mean2; + }; + + + +struct ravg_filter_settings * create_ravg_filter(int, int); +void reset_ravg_filter(double, struct ravg_filter_settings *); +double run_ravg_filter(double, struct ravg_filter_settings *); +void free_ravg_filter(struct ravg_filter_settings *); +void ravg_filter_restore_buf(struct ravg_filter_settings *); +void ravg_filter_save_buf(struct ravg_filter_settings *); +double ravg_filter_response(int, int, double); + + +#endif + + diff -Nru edfbrowser-1.30/README.txt edfbrowser-1.38/README.txt --- edfbrowser-1.30/README.txt 2010-11-24 08:59:32.000000000 +0000 +++ edfbrowser-1.38/README.txt 2011-08-23 20:01:14.000000000 +0000 @@ -1,5 +1,5 @@ -You need to have Qt 4.7.1 and GCC (MinGW on Windows) installed. +You need to have Qt 4.7.2 and GCC (MinGW on Windows) installed. Extract the sourcefile and enter the following commands: diff -Nru edfbrowser-1.30/reduce_signals.cpp edfbrowser-1.38/reduce_signals.cpp --- edfbrowser-1.30/reduce_signals.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/reduce_signals.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2009, 2010 Teunis van Beelen +* Copyright (C) 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -37,8 +37,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -164,7 +162,10 @@ void UI_ReduceSignalsWindow::spinBox1changed(int value) { - long long seconds; + long long seconds, + milliSec; + + int days; char scratchpad[256]; @@ -176,19 +177,32 @@ { return; } + days = (int)((((value - 1) * edfhdr->long_data_record_duration) / TIME_DIMENSION) / 86400LL); seconds = ((value - 1) * edfhdr->long_data_record_duration) / TIME_DIMENSION; if(seconds < 0) { seconds = 0; } - sprintf(scratchpad, "%02i:%02i:%02i", (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60)); + milliSec = ((value - 1) * edfhdr->long_data_record_duration) % TIME_DIMENSION; + milliSec /= 10000LL; + if(days) + { + sprintf(scratchpad, "%id %i:%02i:%02i.%03i", days, (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60), (int)milliSec); + } + else + { + sprintf(scratchpad, "%i:%02i:%02i.%03i", (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60), (int)milliSec); + } label4->setText(scratchpad); } void UI_ReduceSignalsWindow::spinBox2changed(int value) { - long long seconds; + long long seconds, + milliSec; + + int days; char scratchpad[256]; @@ -200,15 +214,28 @@ { return; } + days = (int)(((value * edfhdr->long_data_record_duration) / TIME_DIMENSION) / 86400LL); seconds = (value * edfhdr->long_data_record_duration) / TIME_DIMENSION; - sprintf(scratchpad, "%02i:%02i:%02i", (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60)); + milliSec = (value * edfhdr->long_data_record_duration) % TIME_DIMENSION; + milliSec /= 10000LL; + if(days) + { + sprintf(scratchpad, "%id %i:%02i:%02i.%03i", days, (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60), (int)milliSec); + } + else + { + sprintf(scratchpad, "%i:%02i:%02i.%03i", (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60), (int)milliSec); + } label5->setText(scratchpad); } void UI_ReduceSignalsWindow::radioButton1Toggled(bool checked) { - long long seconds; + long long seconds, + milliSec; + + int days; char scratchpad[256]; @@ -230,9 +257,24 @@ spinBox2->setValue(edfhdr->datarecords); spinBox1->setMaximum(edfhdr->datarecords); - label4->setText("00:00:00"); + days = (int)(((edfhdr->datarecords * edfhdr->long_data_record_duration) / TIME_DIMENSION) / 86400LL); seconds = (edfhdr->datarecords * edfhdr->long_data_record_duration) / TIME_DIMENSION; - sprintf(scratchpad, "%02i:%02i:%02i", (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60)); + milliSec = (edfhdr->datarecords * edfhdr->long_data_record_duration) % TIME_DIMENSION; + milliSec /= 10000LL; + + if(days > 0) + { + label4->setText("0d 0:00:00.000"); + + sprintf(scratchpad, "%id %i:%02i:%02i.%03i", days, (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60), (int)milliSec); + } + else + { + label4->setText("0:00:00.000"); + + sprintf(scratchpad, "%i:%02i:%02i.%03i", (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60), (int)milliSec); + } + label5->setText(scratchpad); } } @@ -296,7 +338,8 @@ { int i; - long long seconds; + long long seconds, + milliSec; char txt_string[2048]; @@ -343,7 +386,8 @@ if(inputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for reading.", inputpath); - UI_Messagewindow popuperror("Error", txt_string); + QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); + messagewindow.exec(); inputpath[0] = 0; @@ -356,8 +400,10 @@ if(edfhdr->datarecords > 2147483647LL) { - UI_Messagewindow popuperror("Failure", "This file contains more than 2147483647 datarecords.\n" - "This tool can not handle more than 2147483647 datarecords."); + QMessageBox messagewindow(QMessageBox::Critical, "Failure", "This file contains more than 2147483647 datarecords.\n" + "This tool can not handle more than 2147483647 datarecords."); + messagewindow.exec(); + inputfile = NULL; inputpath[0] = 0; @@ -401,9 +447,11 @@ radioButton1->setEnabled(TRUE); radioButton2->setEnabled(TRUE); - label4->setText("00:00:00"); + label4->setText("0:00:00.000"); seconds = (edfhdr->datarecords * edfhdr->long_data_record_duration) / TIME_DIMENSION; - sprintf(txt_string, "%02i:%02i:%02i", (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60)); + milliSec = (edfhdr->datarecords * edfhdr->long_data_record_duration) % TIME_DIMENSION; + milliSec /= 10000LL; + sprintf(txt_string, "%i:%02i:%02i.%03i", (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60), (int)milliSec); label5->setText(txt_string); } @@ -416,12 +464,16 @@ datarecords, annot_smp_per_record, annot_recordsize, - tallen, - len; + timestamp_digits=0, + timestamp_decimals=0, + annot_len, + tallen=0, + len, + annot_cnt, + annots_per_datrec=0; char *readbuf, - scratchpad[256], - *talbuf=NULL; + scratchpad[256]; long long new_starttime, time_diff, @@ -431,7 +483,9 @@ struct date_time_struct dts; - struct annotationblock *annotations_pntr=NULL; + struct annotationblock *new_annot_list=NULL, + *root_new_annot_list=NULL, + *annot_list=NULL; pushButton3->setEnabled(FALSE); @@ -458,13 +512,17 @@ annot_smp_per_record = 0; + annot_cnt = 0; + + time_diff = (long long)(spinBox1->value() - 1) * edfhdr->long_data_record_duration; + + taltime = (time_diff + edfhdr->starttime_offset) % TIME_DIMENSION; + + endtime = (long long)(spinBox2->value() - (spinBox1->value() - 1)) * edfhdr->long_data_record_duration + taltime; + for(i=0; iedfsignals; i++) { - if(edfhdr->edfparam[i].annotation) - { - annot_smp_per_record += edfhdr->edfparam[i].smp_per_record; - } - else + if(!edfhdr->edfparam[i].annotation) { if(((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->checkState()==Qt::Checked) { @@ -475,29 +533,85 @@ } } + datarecords = spinBox2->value() - spinBox1->value() + 1; + if(edfhdr->edfplus || edfhdr->bdfplus) { - annot_smp_per_record += 8; + timestamp_decimals = get_tal_timestamp_decimal_cnt(edfhdr); + + timestamp_digits = get_tal_timestamp_digit_cnt(edfhdr); + + annot_list = mainwindow->annotationlist[file_num]; - if(annot_smp_per_record < 16) + while(annot_list != NULL) { - annot_smp_per_record = 16; + l_temp = annot_list->onset - time_diff; + + if((l_temp >= 0) && (l_temp <= endtime)) + { + annot_cnt++; + + edfplus_annotation_add_copy(&new_annot_list, annot_list); + } + + annot_list = annot_list->next_annotation; } - if(edfhdr->edf) + annot_list = new_annot_list; + + root_new_annot_list = new_annot_list; + + while(annot_list != NULL) { - annot_recordsize = annot_smp_per_record * 2; + annot_list->onset -= time_diff; + + annot_list = annot_list->next_annotation; } - else + + edfplus_annotation_sort(&new_annot_list); + + annots_per_datrec = annot_cnt / datarecords; + + if(annot_cnt % datarecords) { - annot_recordsize = annot_smp_per_record * 3; + annots_per_datrec++; } - talbuf = (char *)malloc(annot_recordsize); - if(talbuf==NULL) + annot_len = get_max_annotation_strlen(&new_annot_list); + + if(!annot_cnt) + { + annots_per_datrec = 0; + } + + annot_recordsize = (annot_len * annots_per_datrec) + timestamp_digits + timestamp_decimals + 4; + + if(timestamp_decimals) + { + annot_recordsize++; + } + + if(edfhdr->edf) + { + annot_smp_per_record = annot_recordsize / 2; + + if(annot_recordsize % annot_smp_per_record) + { + annot_smp_per_record++; + + annot_recordsize = annot_smp_per_record * 2; + } + } + else { - showpopupmessage("Error", "Malloc error, (talbuf)."); - goto END_1; + annot_smp_per_record = annot_recordsize / 3; + + if(annot_recordsize % annot_smp_per_record) + { + annot_smp_per_record++; + + annot_recordsize = annot_smp_per_record * 3; + } } } else @@ -507,8 +621,6 @@ annot_recordsize = 0; } - annotations_pntr = mainwindow->annotationlist[file_num]; - readbuf = (char *)malloc(edfhdr->recordsize); if(readbuf==NULL) { @@ -516,8 +628,6 @@ goto END_2; } - datarecords = spinBox2->value() - spinBox1->value() + 1; - /////////////////////////////////////////////////////////////////// outputpath[0] = 0; @@ -562,8 +672,6 @@ goto END_2; } - time_diff = (long long)(spinBox1->value() - 1) * edfhdr->long_data_record_duration; - new_starttime = edfhdr->utc_starttime + ((time_diff + edfhdr->starttime_offset) / TIME_DIMENSION); utc_to_date_time(new_starttime, &dts); @@ -769,10 +877,6 @@ } /////////////////////////////////////////////////////////////////// - taltime = (time_diff + edfhdr->starttime_offset) % TIME_DIMENSION; - - endtime = (long long)(spinBox2->value() - (spinBox1->value() - 1)) * edfhdr->long_data_record_duration + taltime; - QApplication::setOverrideCursor(Qt::WaitCursor); fseeko(inputfile, (long long)edfhdr->hdrsize + ((long long)(spinBox1->value() - 1) * (long long)edfhdr->recordsize), SEEK_SET); @@ -824,9 +928,25 @@ if(edfhdr->edfplus || edfhdr->bdfplus) { - tallen = fprintf(outputfile, "+%i.%07i", - (int)(taltime / TIME_DIMENSION), - (int)(taltime % TIME_DIMENSION)); + switch(timestamp_decimals) + { + case 0 : tallen = fprintf(outputfile, "+%i", (int)(taltime / TIME_DIMENSION)); + break; + case 1 : tallen = fprintf(outputfile, "+%i.%01i", (int)(taltime / TIME_DIMENSION), (int)((taltime % TIME_DIMENSION) / 1000000LL)); + break; + case 2 : tallen = fprintf(outputfile, "+%i.%02i", (int)(taltime / TIME_DIMENSION), (int)((taltime % TIME_DIMENSION) / 100000LL)); + break; + case 3 : tallen = fprintf(outputfile, "+%i.%03i", (int)(taltime / TIME_DIMENSION), (int)((taltime % TIME_DIMENSION) / 10000LL)); + break; + case 4 : tallen = fprintf(outputfile, "+%i.%04i", (int)(taltime / TIME_DIMENSION), (int)((taltime % TIME_DIMENSION) / 1000LL)); + break; + case 5 : tallen = fprintf(outputfile, "+%i.%05i", (int)(taltime / TIME_DIMENSION), (int)((taltime % TIME_DIMENSION) / 100LL)); + break; + case 6 : tallen = fprintf(outputfile, "+%i.%06i", (int)(taltime / TIME_DIMENSION), (int)((taltime % TIME_DIMENSION) / 10LL)); + break; + case 7 : tallen = fprintf(outputfile, "+%i.%07i", (int)(taltime / TIME_DIMENSION), (int)(taltime % TIME_DIMENSION)); + break; + } fputc(20, outputfile); fputc(20, outputfile); @@ -834,46 +954,62 @@ tallen += 3; - if(annotations_pntr != NULL) + if(new_annot_list != NULL) { - l_temp = annotations_pntr->onset - time_diff; - - while((l_temp < 0) || (l_temp > endtime)) + for(i=0; inext_annotation; - - if(annotations_pntr == NULL) + if(new_annot_list != NULL) { - break; - } - - l_temp = annotations_pntr->onset - time_diff; - } + len = snprintf(scratchpad, 256, "%+i.%07i", + (int)(new_annot_list->onset / TIME_DIMENSION), + (int)(new_annot_list->onset % TIME_DIMENSION)); + + for(j=0; j<7; j++) + { + if(scratchpad[len - j - 1] != '0') + { + break; + } + } + + if(j) + { + len -= j; + + if(j == 7) + { + len--; + } + } + + if(fwrite(scratchpad, len, 1, outputfile) != 1) + { + QApplication::restoreOverrideCursor(); + showpopupmessage("Error", "Write error (5)."); + goto END_3; + } + + tallen += len; + + if(new_annot_list->duration[0]!=0) + { + fputc(21, outputfile); + tallen++; - if(annotations_pntr != NULL) - { - tallen += fprintf(outputfile, "%+i.%07i", - (int)(l_temp / TIME_DIMENSION), - (int)(l_temp % TIME_DIMENSION)); + tallen += fprintf(outputfile, "%s", new_annot_list->duration); + } - if(annotations_pntr->duration[0]!=0) - { - fputc(21, outputfile); + fputc(20, outputfile); tallen++; - tallen += fprintf(outputfile, "%s", annotations_pntr->duration); - } - - fputc(20, outputfile); - tallen++; - - tallen += fprintf(outputfile, "%s", annotations_pntr->annotation); + tallen += fprintf(outputfile, "%s", new_annot_list->annotation); - fputc(20, outputfile); - fputc(0, outputfile); - tallen += 2; + fputc(20, outputfile); + fputc(0, outputfile); + tallen += 2; - annotations_pntr = annotations_pntr->next_annotation; + new_annot_list = new_annot_list->next_annotation; + } } } @@ -898,13 +1034,6 @@ free(readbuf); -END_1: - - if(edfhdr->edfplus || edfhdr->bdfplus) - { - free(talbuf); - } - inputfile = NULL; inputpath[0] = 0; @@ -917,7 +1046,9 @@ edfhdr = NULL; - annotations_pntr = NULL; + edfplus_annotation_delete_list(&root_new_annot_list); + + root_new_annot_list = NULL; SignalsTablewidget->setRowCount(0); } @@ -944,3 +1075,5 @@ + + diff -Nru edfbrowser-1.30/reduce_signals.h edfbrowser-1.38/reduce_signals.h --- edfbrowser-1.30/reduce_signals.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/reduce_signals.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2009, 2010 Teunis van Beelen +* Copyright (C) 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -58,6 +59,7 @@ #include "utils.h" #include "utc_date_time.h" #include "active_file_chooser.h" +#include "edf_annot_list.h" diff -Nru edfbrowser-1.30/save_annots.cpp edfbrowser-1.38/save_annots.cpp --- edfbrowser-1.30/save_annots.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/save_annots.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2009, 2010 Teunis van Beelen +* Copyright (C) 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -37,8 +37,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -52,20 +50,19 @@ -int save_annotations(UI_Mainwindow *mainwindow, FILE *outputfile, struct edfhdrblock *hdr, struct annotationblock *annotation) +int save_annotations(UI_Mainwindow *mainwindow, FILE *outputfile, struct edfhdrblock *hdr, struct annotationblock *annotlist) { int i, j, k, p=0, - len, new_edfsignals=0, signalslist[MAXSIGNALS], datarecords, - bytes_per_sample, - annot_len=0, - annot_descr_len=0, - annot_duration_len=0, + annot_len, + annot_smp_per_record, + annot_recordsize, timestamp_decimals, timestamp_digits, - bytes_written; + bytes_written, + annots_per_datrec; char *readbuf, scratchpad[256], @@ -91,66 +88,54 @@ datarecords = hdr->datarecords; - if(hdr->edf) - { - bytes_per_sample = 2; - } - else - { - bytes_per_sample = 3; - } - time = (hdr->datarecords * hdr->long_data_record_duration) / TIME_DIMENSION; -#ifdef Q_WS_WIN - timestamp_digits = sprintf(scratchpad, "%I64d", time); -#else - timestamp_digits = sprintf(scratchpad, "%lli", time); -#endif + timestamp_decimals = get_tal_timestamp_decimal_cnt(hdr); - j = 10; + timestamp_digits = get_tal_timestamp_digit_cnt(hdr); - for(timestamp_decimals=7; timestamp_decimals>0; timestamp_decimals--) - { - if(hdr->long_data_record_duration % j) - { - break; - } + annot = annotlist; - j *= 10; - } + annot_len = get_max_annotation_strlen(&annot); - annot = annotation; + i = edfplus_annotation_count(&annot); - while(annot) + annots_per_datrec = i / datarecords; + + if(i % datarecords) { - len = strlen(annot->annotation); + annots_per_datrec++; + } - if(len>annot_descr_len) - { - annot_descr_len = len; - } + annot_recordsize = (annot_len * annots_per_datrec) + timestamp_digits + timestamp_decimals + 4; - len = strlen(annot->duration); + if(timestamp_decimals) + { + annot_recordsize++; + } - if(len>annot_duration_len) + if(hdr->edf) + { + annot_smp_per_record = annot_recordsize / 2; + + if(annot_recordsize % annot_smp_per_record) { - annot_duration_len = len; - } + annot_smp_per_record++; - annot = annot->next_annotation; + annot_recordsize = annot_smp_per_record * 2; + } } - - if(annot_duration_len) + else { - annot_duration_len += 1; - } - - annot_len = 27 + timestamp_digits + timestamp_decimals + annot_descr_len + annot_duration_len; + annot_smp_per_record = annot_recordsize / 3; - j = annot_len % bytes_per_sample; + if(annot_recordsize % annot_smp_per_record) + { + annot_smp_per_record++; - annot_len -= j; + annot_recordsize = annot_smp_per_record * 3; + } + } readbuf = (char *)malloc(hdr->recordsize); if(readbuf==NULL) @@ -158,7 +143,7 @@ return(1); } - annot_buf = (char *)malloc(annot_len + 6); + annot_buf = (char *)malloc(annot_recordsize + 10); if(annot_buf==NULL) { free(readbuf); @@ -237,7 +222,7 @@ return(3); } } - fprintf(outputfile, "%-8i", new_edfsignals * 256 + 512); + fprintf(outputfile, "%-8i", (new_edfsignals * 256) + 512); if(hdr->edf) { fprintf(outputfile, "EDF+C"); @@ -251,31 +236,19 @@ fputc(' ', outputfile); } fprintf(outputfile, "%-8i", datarecords); - snprintf(scratchpad, 256, "%f", hdr->data_record_duration); - for(i=0; i<8; i++) + snprintf(scratchpad, 256, "%.12f", hdr->data_record_duration); + remove_trailing_zeros(scratchpad); + strcat(scratchpad, " "); + if((!strncmp(scratchpad, "0.", 2)) && (scratchpad[8] != ' ')) { - 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[9] = 0; + fprintf(outputfile, "%s", scratchpad + 1); + } + else + { + scratchpad[8] = 0; + fprintf(outputfile, "%s", scratchpad); } - scratchpad[8] = 0; - fprintf(outputfile, "%s", scratchpad); fprintf(outputfile, "%-4i", new_edfsignals + 1); for(i=0; iedfparam[signalslist[i]].smp_per_record); } - fprintf(outputfile, "%-8i", annot_len / bytes_per_sample); - for(i=0; i<(new_edfsignals * 32 + 32); i++) + fprintf(outputfile, "%-8i", annot_smp_per_record); + for(i=0; i<((new_edfsignals * 32) + 32); i++) { fputc(' ', outputfile); } @@ -409,16 +382,15 @@ /////////////////////////////////////////////////////////////////// QProgressDialog progress("Saving file...", "Abort", 0, datarecords, mainwindow); - progress.setWindowModality(Qt::WindowModal); + progress.setMinimumDuration(1000); + progress.setValue(0); bytes_written = 0; - QApplication::setOverrideCursor(Qt::WaitCursor); - fseeko(inputfile, (long long)(hdr->hdrsize), SEEK_SET); - annot = annotation; + annot = annotlist; time = hdr->starttime_offset; @@ -428,7 +400,6 @@ { if(fread(readbuf, hdr->recordsize, 1, inputfile) != 1) { - QApplication::restoreOverrideCursor(); free(readbuf); free(annot_buf); return(2); @@ -459,94 +430,117 @@ } #ifdef Q_WS_WIN - switch(timestamp_decimals) - { - case 0 : p = snprintf(annot_buf, 16, "+%I64d", time / TIME_DIMENSION); - break; - case 1 : p = snprintf(annot_buf, 16, "+%I64d.%01I64d", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 1000000LL); - break; - case 2 : p = snprintf(annot_buf, 16, "+%I64d.%02I64d", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 100000LL); - break; - case 3 : p = snprintf(annot_buf, 16, "+%I64d.%03I64d", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 10000LL); - break; - case 4 : p = snprintf(annot_buf, 16, "+%I64d.%04I64d", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 1000LL); - break; - case 5 : p = snprintf(annot_buf, 16, "+%I64d.%05I64d", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 100LL); - break; - case 6 : p = snprintf(annot_buf, 16, "+%I64d.%06I64d", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 10LL); - break; - case 7 : p = snprintf(annot_buf, 16, "+%I64d.%07I64d", time / TIME_DIMENSION, time % TIME_DIMENSION); - break; - } + switch(timestamp_decimals) + { + case 0 : p = snprintf(annot_buf, 16, "+%I64d", time / TIME_DIMENSION); + break; + case 1 : p = snprintf(annot_buf, 16, "+%I64d.%01I64d", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 1000000LL); + break; + case 2 : p = snprintf(annot_buf, 16, "+%I64d.%02I64d", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 100000LL); + break; + case 3 : p = snprintf(annot_buf, 16, "+%I64d.%03I64d", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 10000LL); + break; + case 4 : p = snprintf(annot_buf, 16, "+%I64d.%04I64d", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 1000LL); + break; + case 5 : p = snprintf(annot_buf, 16, "+%I64d.%05I64d", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 100LL); + break; + case 6 : p = snprintf(annot_buf, 16, "+%I64d.%06I64d", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 10LL); + break; + case 7 : p = snprintf(annot_buf, 16, "+%I64d.%07I64d", time / TIME_DIMENSION, time % TIME_DIMENSION); + break; + } #else - switch(timestamp_decimals) - { - case 0 : p = snprintf(annot_buf, 16, "+%lli", time / TIME_DIMENSION); - break; - case 1 : p = snprintf(annot_buf, 16, "+%lli.%01lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 1000000LL); - break; - case 2 : p = snprintf(annot_buf, 16, "+%lli.%02lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 100000LL); - break; - case 3 : p = snprintf(annot_buf, 16, "+%lli.%03lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 10000LL); - break; - case 4 : p = snprintf(annot_buf, 16, "+%lli.%04lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 1000LL); - break; - case 5 : p = snprintf(annot_buf, 16, "+%lli.%05lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 100LL); - break; - case 6 : p = snprintf(annot_buf, 16, "+%lli.%06lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 10LL); - break; - case 7 : p = snprintf(annot_buf, 16, "+%lli.%07lli", time / TIME_DIMENSION, time % TIME_DIMENSION); - break; - } + switch(timestamp_decimals) + { + case 0 : p = snprintf(annot_buf, 16, "+%lli", time / TIME_DIMENSION); + break; + case 1 : p = snprintf(annot_buf, 16, "+%lli.%01lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 1000000LL); + break; + case 2 : p = snprintf(annot_buf, 16, "+%lli.%02lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 100000LL); + break; + case 3 : p = snprintf(annot_buf, 16, "+%lli.%03lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 10000LL); + break; + case 4 : p = snprintf(annot_buf, 16, "+%lli.%04lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 1000LL); + break; + case 5 : p = snprintf(annot_buf, 16, "+%lli.%05lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 100LL); + break; + case 6 : p = snprintf(annot_buf, 16, "+%lli.%06lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 10LL); + break; + case 7 : p = snprintf(annot_buf, 16, "+%lli.%07lli", time / TIME_DIMENSION, time % TIME_DIMENSION); + break; + } #endif - annot_buf[p++] = 20; annot_buf[p++] = 20; annot_buf[p++] = 0; if(annot!=NULL) { - if(annot->onset<0) + for(i=0; ionset<0) + { #ifdef Q_WS_WIN - p += snprintf(annot_buf + p, 16, "-%I64d.%07I64d", -(annot->onset / TIME_DIMENSION), -(annot->onset % TIME_DIMENSION)); + p += snprintf(annot_buf + p, 20, "-%I64d.%07I64d", -(annot->onset / TIME_DIMENSION), -(annot->onset % TIME_DIMENSION)); #else - p += snprintf(annot_buf + p, 16, "-%lli.%07lli", -(annot->onset / TIME_DIMENSION), -(annot->onset % TIME_DIMENSION)); + p += snprintf(annot_buf + p, 20, "-%lli.%07lli", -(annot->onset / TIME_DIMENSION), -(annot->onset % TIME_DIMENSION)); #endif - } - else - { + } + else + { #ifdef Q_WS_WIN - p += snprintf(annot_buf + p, 16, "+%I64d.%07I64d", annot->onset / TIME_DIMENSION, annot->onset % TIME_DIMENSION); + p += snprintf(annot_buf + p, 20, "+%I64d.%07I64d", annot->onset / TIME_DIMENSION, annot->onset % TIME_DIMENSION); #else - p += snprintf(annot_buf + p, 16, "+%lli.%07lli", annot->onset / TIME_DIMENSION, annot->onset % TIME_DIMENSION); + p += snprintf(annot_buf + p, 20, "+%lli.%07lli", annot->onset / TIME_DIMENSION, annot->onset % TIME_DIMENSION); #endif - } + } - if(annot->duration[0]) - { - annot_buf[p++] = 21; + for(j=0; j<7; j++) + { + if(annot_buf[p - j - 1] != '0') + { + break; + } + } - p += sprintf(annot_buf + p, "%s", annot->duration); - } + if(j) + { + p -= j; + + if(j == 7) + { + p--; + } + } + + if(annot->duration[0]) + { + annot_buf[p++] = 21; - annot_buf[p++] = 20; + p += sprintf(annot_buf + p, "%s", annot->duration); + } + + annot_buf[p++] = 20; - p += sprintf(annot_buf + p, "%s", annot->annotation); + p += sprintf(annot_buf + p, "%s", annot->annotation); - annot_buf[p++] = 20; + annot_buf[p++] = 20; + annot_buf[p++] = 0; - annot = annot->next_annotation; + annot = annot->next_annotation; + } + } } - for(; plong_data_record_duration; - bytes_written += hdr->recordsize + annot_len; + bytes_written += hdr->recordsize; if(bytes_written>1000000) { @@ -564,7 +558,6 @@ if(progress.wasCanceled()) { - QApplication::restoreOverrideCursor(); free(readbuf); free(annot_buf); return(4); @@ -576,8 +569,6 @@ progress.setValue(datarecords); - QApplication::restoreOverrideCursor(); - free(readbuf); free(annot_buf); diff -Nru edfbrowser-1.30/save_annots.h edfbrowser-1.38/save_annots.h --- edfbrowser-1.30/save_annots.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/save_annots.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2009, 2010 Teunis van Beelen +* Copyright (C) 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -47,6 +47,8 @@ #include "global.h" #include "mainwindow.h" +#include "utils.h" +#include "edf_annot_list.h" diff -Nru edfbrowser-1.30/save_montage_dialog.cpp edfbrowser-1.38/save_montage_dialog.cpp --- edfbrowser-1.30/save_montage_dialog.cpp 2010-11-22 07:52:40.000000000 +0000 +++ edfbrowser-1.38/save_montage_dialog.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -36,8 +36,6 @@ #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) -#define fseeko fseek -#define ftello ftell #define fopeno fopen #else @@ -136,7 +134,8 @@ mtgfile = fopeno(mtg_path, "wb"); if(mtgfile==NULL) { - UI_Messagewindow popuperror("Error", "Error, can not open file for writing."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for writing."); + messagewindow.exec(); return; } @@ -161,6 +160,8 @@ fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->fidfilter_cnt); + fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->ravg_filter_cnt); + for(j=0; jsignalcomp[i]->num_of_signals; j++) { fprintf(mtgfile, " \n"); @@ -187,6 +188,17 @@ fprintf(mtgfile, " \n"); } + for(j=0; jsignalcomp[i]->ravg_filter_cnt; j++) + { + fprintf(mtgfile, " \n"); + + fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->ravg_filter[j]->type); + + fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->ravg_filter[j]->size); + + fprintf(mtgfile, " \n"); + } + for(j=0; jsignalcomp[i]->fidfilter_cnt; j++) { fprintf(mtgfile, " \n"); @@ -206,6 +218,15 @@ fprintf(mtgfile, " \n"); } + if(mainwindow->signalcomp[i]->ecg_filter != NULL) + { + fprintf(mtgfile, " \n"); + + fprintf(mtgfile, " 1\n"); + + fprintf(mtgfile, " \n"); + } + fprintf(mtgfile, " \n"); } } diff -Nru edfbrowser-1.30/save_montage_dialog.h edfbrowser-1.38/save_montage_dialog.h --- edfbrowser-1.30/save_montage_dialog.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/save_montage_dialog.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -45,6 +45,7 @@ #include #include #include +#include #include #include diff -Nru edfbrowser-1.30/show_actual_montage_dialog.cpp edfbrowser-1.38/show_actual_montage_dialog.cpp --- edfbrowser-1.30/show_actual_montage_dialog.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/show_actual_montage_dialog.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -49,36 +49,46 @@ frequency2, ripple; + QStandardItem *parentItem, + *signalItem, + *filterItem; + mainwindow = (UI_Mainwindow *)parent; ShowMontageDialog = new QDialog; - ShowMontageDialog->setMinimumSize(QSize(800, 300)); - ShowMontageDialog->resize(600, 440); + ShowMontageDialog->setMinimumSize(QSize(500, 300)); + ShowMontageDialog->resize(500, 440); ShowMontageDialog->setWindowTitle("Show montage"); ShowMontageDialog->setModal(TRUE); ShowMontageDialog->setAttribute(Qt::WA_DeleteOnClose, TRUE); - textedit1 = new QTextEdit; - textedit1->setFrameStyle(QFrame::Panel | QFrame::Sunken); - textedit1->setReadOnly(TRUE); - textedit1->setLineWrapMode(QTextEdit::NoWrap); - textedit1->setFont(*mainwindow->monofont); + tree = new QTreeView; + tree->setHeaderHidden(TRUE); + tree->setIndentation(30); + tree->setSelectionMode(QAbstractItemView::NoSelection); + tree->setEditTriggers(QAbstractItemView::NoEditTriggers); + tree->setSortingEnabled(FALSE); + tree->setDragDropMode(QAbstractItemView::NoDragDrop); CloseButton = new QPushButton; CloseButton->setFixedSize(100, 25); CloseButton->setText("Close"); box = new QBoxLayout(QBoxLayout::TopToBottom, ShowMontageDialog); - box->addWidget(textedit1); + box->addWidget(tree); box->addWidget(CloseButton, 0, Qt::AlignRight); QObject::connect(CloseButton, SIGNAL(clicked()), ShowMontageDialog, SLOT(close())); + t_model = new QStandardItemModel(this); + + parentItem = t_model->invisibleRootItem(); + for(i=0; isignalcomps; i++) { - sprintf(txtbuf, "%3i: ", i + 1); + txtbuf[0] = 0; for(j=0; jsignalcomp[i]->num_of_signals; j++) { @@ -88,20 +98,103 @@ remove_trailing_spaces(txtbuf); - strcat(txtbuf, " "); + strcat(txtbuf, " "); + } + + signalItem = new QStandardItem(txtbuf); + + parentItem->appendRow(signalItem); + + sprintf(txtbuf, "amplitude: %f", mainwindow->signalcomp[i]->voltpercm); + + strcat(txtbuf, mainwindow->signalcomp[i]->physdimension); + + remove_trailing_spaces(txtbuf); + + sprintf(txtbuf + strlen(txtbuf), "/cm offset: %f%s", + mainwindow->signalcomp[i]->screen_offset * mainwindow->pixelsizefactor * mainwindow->signalcomp[i]->voltpercm, + mainwindow->signalcomp[i]->physdimension); + + remove_trailing_zeros(txtbuf); + + remove_trailing_spaces(txtbuf); + + strcat(txtbuf, " color: "); + + switch(mainwindow->signalcomp[i]->color) + { + case Qt::white : strcat(txtbuf, "white"); + break; + case Qt::black : strcat(txtbuf, "black"); + break; + case Qt::red : strcat(txtbuf, "red"); + break; + case Qt::darkRed : strcat(txtbuf, "dark red"); + break; + case Qt::green : strcat(txtbuf, "green"); + break; + case Qt::darkGreen : strcat(txtbuf, "dark green"); + break; + case Qt::blue : strcat(txtbuf, "blue"); + break; + case Qt::darkBlue : strcat(txtbuf, "dark blue"); + break; + case Qt::cyan : strcat(txtbuf, "cyan"); + break; + case Qt::darkCyan : strcat(txtbuf, "dark cyan"); + break; + case Qt::magenta : strcat(txtbuf, "magenta"); + break; + case Qt::darkMagenta : strcat(txtbuf, "dark magenta"); + break; + case Qt::yellow : strcat(txtbuf, "yellow"); + break; + case Qt::darkYellow : strcat(txtbuf, "dark yellow"); + break; + case Qt::gray : strcat(txtbuf, "gray"); + break; + case Qt::darkGray : strcat(txtbuf, "dark gray"); + break; + case Qt::lightGray : strcat(txtbuf, "light gray"); + break; } + signalItem->appendRow(new QStandardItem(txtbuf)); + + filterItem = new QStandardItem("Filters"); + + signalItem->appendRow(filterItem); + for(j=0; jsignalcomp[i]->filter_cnt; j++) { if(mainwindow->signalcomp[i]->filter[j]->is_LPF == 1) { - sprintf(txtbuf + strlen(txtbuf), "LPF: %fHz ", mainwindow->signalcomp[i]->filter[j]->cutoff_frequency); + sprintf(txtbuf, "LPF: %fHz", mainwindow->signalcomp[i]->filter[j]->cutoff_frequency); } if(mainwindow->signalcomp[i]->filter[j]->is_LPF == 0) { - sprintf(txtbuf + strlen(txtbuf), "HPF: %fHz ", mainwindow->signalcomp[i]->filter[j]->cutoff_frequency); + sprintf(txtbuf, "HPF: %fHz", mainwindow->signalcomp[i]->filter[j]->cutoff_frequency); } + + remove_trailing_zeros(txtbuf); + + filterItem->appendRow(new QStandardItem(txtbuf)); + } + + for(j=0; jsignalcomp[i]->ravg_filter_cnt; j++) + { + if(mainwindow->signalcomp[i]->ravg_filter_type[j] == 0) + { + sprintf(txtbuf, "highpass moving average %i smpls", mainwindow->signalcomp[i]->ravg_filter[j]->size); + } + + if(mainwindow->signalcomp[i]->ravg_filter_type[j] == 1) + { + sprintf(txtbuf, "lowpass moving average %i smpls", mainwindow->signalcomp[i]->ravg_filter[j]->size); + } + + filterItem->appendRow(new QStandardItem(txtbuf)); } for(j=0; jsignalcomp[i]->fidfilter_cnt; j++) @@ -122,17 +215,17 @@ { if(model == 0) { - sprintf(txtbuf + strlen(txtbuf), "highpass Butterworth %fHz %ith order ", frequency, order); + sprintf(txtbuf, "highpass Butterworth %fHz %ith order", frequency, order); } if(model == 1) { - sprintf(txtbuf + strlen(txtbuf), "highpass Chebyshev %fHz %ith order %fdB ripple ", frequency, order, ripple); + sprintf(txtbuf, "highpass Chebyshev %fHz %ith order %fdB ripple", frequency, order, ripple); } if(model == 2) { - sprintf(txtbuf + strlen(txtbuf), "highpass Bessel %fHz %ith order ", frequency, order); + sprintf(txtbuf, "highpass Bessel %fHz %ith order", frequency, order); } } @@ -140,40 +233,40 @@ { if(model == 0) { - sprintf(txtbuf + strlen(txtbuf), "lowpass Butterworth %fHz %ith order ", frequency, order); + sprintf(txtbuf, "lowpass Butterworth %fHz %ith order", frequency, order); } if(model == 1) { - sprintf(txtbuf + strlen(txtbuf), "lowpass Chebyshev %fHz %ith order %fdB ripple ", frequency, order, ripple); + sprintf(txtbuf, "lowpass Chebyshev %fHz %ith order %fdB ripple", frequency, order, ripple); } if(model == 2) { - sprintf(txtbuf + strlen(txtbuf), "lowpass Bessel %fHz %ith order ", frequency, order); + sprintf(txtbuf, "lowpass Bessel %fHz %ith order", frequency, order); } } if(type == 2) { - sprintf(txtbuf + strlen(txtbuf), "notch %fHz Q-factor %i ", frequency, order); + sprintf(txtbuf, "notch %fHz Q-factor %i", frequency, order); } if(type == 3) { if(model == 0) { - sprintf(txtbuf + strlen(txtbuf), "bandpass Butterworth %f-%fHz %ith order ", frequency, frequency2, order); + sprintf(txtbuf, "bandpass Butterworth %f-%fHz %ith order", frequency, frequency2, order); } if(model == 1) { - sprintf(txtbuf + strlen(txtbuf), "bandpass Chebyshev %f-%fHz %ith order %fdB ripple ", frequency, frequency2, order, ripple); + sprintf(txtbuf, "bandpass Chebyshev %f-%fHz %ith order %fdB ripple", frequency, frequency2, order, ripple); } if(model == 2) { - sprintf(txtbuf + strlen(txtbuf), "bandpass Bessel %f-%fHz %ith order ", frequency, frequency2, order); + sprintf(txtbuf, "bandpass Bessel %f-%fHz %ith order", frequency, frequency2, order); } } @@ -181,37 +274,38 @@ { if(model == 0) { - sprintf(txtbuf + strlen(txtbuf), "bandstop Butterworth %f-%fHz %ith order ", frequency, frequency2, order); + sprintf(txtbuf, "bandstop Butterworth %f-%fHz %ith order", frequency, frequency2, order); } if(model == 1) { - sprintf(txtbuf + strlen(txtbuf), "bandstop Chebyshev %f-%fHz %ith order %fdB ripple ", frequency, frequency2, order, ripple); + sprintf(txtbuf, "bandstop Chebyshev %f-%fHz %ith order %fdB ripple", frequency, frequency2, order, ripple); } if(model == 2) { - sprintf(txtbuf + strlen(txtbuf), "bandstop Bessel %f-%fHz %ith order ", frequency, frequency2, order); + sprintf(txtbuf, "bandstop Bessel %f-%fHz %ith order", frequency, frequency2, order); } } - } - sprintf(txtbuf + strlen(txtbuf), " %f", mainwindow->signalcomp[i]->voltpercm); + remove_trailing_zeros(txtbuf); - strcat(txtbuf, mainwindow->signalcomp[i]->edfhdr->edfparam[mainwindow->signalcomp[i]->edfsignal[0]].physdimension); - - remove_trailing_spaces(txtbuf); - - sprintf(txtbuf + strlen(txtbuf), "/cm offset: %f", mainwindow->signalcomp[i]->screen_offset * mainwindow->pixelsizefactor * mainwindow->signalcomp[i]->voltpercm); + filterItem->appendRow(new QStandardItem(txtbuf)); + } - strcat(txtbuf, mainwindow->signalcomp[i]->edfhdr->edfparam[mainwindow->signalcomp[i]->edfsignal[0]].physdimension); + if(mainwindow->signalcomp[i]->ecg_filter != NULL) + { + sprintf(txtbuf, "ECG heartrate detection"); - remove_trailing_spaces(txtbuf); + filterItem->appendRow(new QStandardItem(txtbuf)); + } + } - remove_trailing_zeros(txtbuf); + sprintf(txtbuf, "timescale: %f seconds", (double)mainwindow->pagetime / (double)TIME_DIMENSION); + remove_trailing_zeros(txtbuf); + parentItem->appendRow(new QStandardItem(txtbuf)); - textedit1->append(txtbuf); - } + tree->setModel(t_model); ShowMontageDialog->exec(); } diff -Nru edfbrowser-1.30/show_actual_montage_dialog.h edfbrowser-1.38/show_actual_montage_dialog.h --- edfbrowser-1.30/show_actual_montage_dialog.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/show_actual_montage_dialog.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -41,8 +41,10 @@ #include #include #include -#include #include +#include +#include +#include #include #include @@ -72,11 +74,14 @@ QDialog *ShowMontageDialog; - QTextEdit *textedit1; - QPushButton *CloseButton; QBoxLayout *box; + + QTreeView *tree; + + QStandardItemModel *t_model; + }; diff -Nru edfbrowser-1.30/show_edf_hdr.cpp edfbrowser-1.38/show_edf_hdr.cpp --- edfbrowser-1.30/show_edf_hdr.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/show_edf_hdr.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -215,7 +215,7 @@ void UI_EDFhdrwindow::show_params(int row) { - int i, p, + int i, signal_cnt; char str[512]; @@ -283,8 +283,6 @@ label8a->setVisible(TRUE); label8a->setText(mainwindow->edfheaderlist[row]->plus_patient_additional); - p = 10; - label9->setVisible(TRUE); label9a->setVisible(TRUE); label9a->setText(mainwindow->edfheaderlist[row]->plus_startdate); @@ -377,7 +375,7 @@ label5a->setText(mainwindow->edfheaderlist[row]->reserved); - snprintf(str, 512, "%f", mainwindow->edfheaderlist[row]->data_record_duration); + snprintf(str, 512, "%.12f", mainwindow->edfheaderlist[row]->data_record_duration); remove_trailing_zeros(str); diff -Nru edfbrowser-1.30/show_edf_hdr.h edfbrowser-1.38/show_edf_hdr.h --- edfbrowser-1.30/show_edf_hdr.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/show_edf_hdr.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/signal_chooser.cpp edfbrowser-1.38/signal_chooser.cpp --- edfbrowser-1.30/signal_chooser.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/signal_chooser.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -36,47 +36,115 @@ -UI_SignalChooser::UI_SignalChooser(QWidget *parent, int job) +UI_SignalChooser::UI_SignalChooser(QWidget *parent, int job, int *sgnl_nr) { - int i; - task = job; + signal_nr = sgnl_nr; + mainwindow = (UI_Mainwindow *)parent; signalchooser_dialog = new QDialog(parent); - signalchooser_dialog->setMinimumSize(QSize(200, 400)); - signalchooser_dialog->setMaximumSize(QSize(200, 400)); - signalchooser_dialog->setWindowTitle("Signals"); + if(task == 3) + { + signalchooser_dialog->setMinimumSize(QSize(265, 400)); + signalchooser_dialog->setMaximumSize(QSize(265, 400)); + signalchooser_dialog->setWindowTitle("Organize signals"); + } + else + { + signalchooser_dialog->setMinimumSize(QSize(200, 400)); + signalchooser_dialog->setMaximumSize(QSize(200, 400)); + signalchooser_dialog->setWindowTitle("Signals"); + } signalchooser_dialog->setModal(TRUE); signalchooser_dialog->setAttribute(Qt::WA_DeleteOnClose, TRUE); list = new QListWidget(signalchooser_dialog); - list->setGeometry(QRect(5, 5, 130, 365)); + list->setGeometry(5, 5, 130, 365); list->setSelectionBehavior(QAbstractItemView::SelectRows); - list->setSelectionMode(QAbstractItemView::SingleSelection); - + if(task == 3) + { + list->setSelectionMode(QAbstractItemView::ExtendedSelection); + } + else + { + list->setSelectionMode(QAbstractItemView::SingleSelection); + } CloseButton = new QPushButton(signalchooser_dialog); - CloseButton->setGeometry(QRect(5, 375, 130, 20)); + CloseButton->setGeometry(5, 375, 130, 20); CloseButton->setText("Close"); - for(i=0; isignalcomps; i++) + if(task == 3) { - new QListWidgetItem(mainwindow->signalcomp[i]->signallabel, list); + UpButton = new QPushButton(signalchooser_dialog); + UpButton->setGeometry(150, 180, 100, 20); + UpButton->setText("Up"); + + DownButton = new QPushButton(signalchooser_dialog); + DownButton->setGeometry(150, 220, 100, 20); + DownButton->setText("Down"); + + InvertButton = new QPushButton(signalchooser_dialog); + InvertButton->setGeometry(150, 260, 100, 20); + InvertButton->setText("Invert"); + + DeleteButton = new QPushButton(signalchooser_dialog); + DeleteButton->setGeometry(150, 300, 100, 20); + DeleteButton->setText("Remove"); } + load_signalcomps(); + QObject::connect(CloseButton, SIGNAL(clicked()), signalchooser_dialog, SLOT(close())); - QObject::connect(list, SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(call_sidemenu(QListWidgetItem *))); + + if(task == 3) + { + if(list->count() > 0) + { + list->setCurrentRow(0); + + QObject::connect(UpButton, SIGNAL(clicked()), this, SLOT(signalUp())); + QObject::connect(DownButton, SIGNAL(clicked()), this, SLOT(signalDown())); + QObject::connect(InvertButton, SIGNAL(clicked()), this, SLOT(signalInvert())); + QObject::connect(DeleteButton, SIGNAL(clicked()), this, SLOT(signalDelete())); + } + } + else + { + QObject::connect(list, SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(call_sidemenu(QListWidgetItem *))); + } signalchooser_dialog->exec(); } +void UI_SignalChooser::load_signalcomps(void) +{ + int i; + + QListWidgetItem *item; + + list->clear(); + + for(i=0; isignalcomps; i++) + { + item = new QListWidgetItem; + item->setText(mainwindow->signalcomp[i]->signallabel); + item->setData(Qt::UserRole, QVariant(i)); + list->addItem(item); + } +} + + + void UI_SignalChooser::call_sidemenu(QListWidgetItem *) { + if(task == 3) return; + signalchooser_dialog->hide(); if(task == 0) @@ -94,10 +162,397 @@ AdjustFilterSettings filtersettings(mainwindow->signalcomp[list->currentRow()], mainwindow->maincurve); } + if(task == 4) + { + if(signal_nr != NULL) + { + *signal_nr = list->currentRow(); + } + } + signalchooser_dialog->close(); } +void UI_SignalChooser::signalUp() +{ + int i, n, + size, + sigcomp_nr, + selected_signals[MAXSIGNALS]; + + QList selectedlist; + + struct signalcompblock *signalcomp; + + + selectedlist = list->selectedItems(); + + n = selectedlist.size(); + + if(n < 1) + { + return; + } + + size = list->count(); + + if(size < (n + 1)) + { + return; + } + + if(selectedlist.at(0)->data(Qt::UserRole).toInt() < 1) + { + return; + } + + for(i=0; idata(Qt::UserRole).toInt(); + + signalcomp = mainwindow->signalcomp[sigcomp_nr]; + + mainwindow->signalcomp[sigcomp_nr] = mainwindow->signalcomp[sigcomp_nr - 1]; + + mainwindow->signalcomp[sigcomp_nr - 1] = signalcomp; + + selected_signals[i] = sigcomp_nr; + } + + load_signalcomps(); + + for(i=0; iitem(selected_signals[i] - 1)->setSelected(TRUE); + } + + mainwindow->setup_viewbuf(); +} + + +void UI_SignalChooser::signalDown() +{ + int i, n, + size, + sigcomp_nr, + selected_signals[MAXSIGNALS]; + + QList selectedlist; + + struct signalcompblock *signalcomp; + + + selectedlist = list->selectedItems(); + + n = selectedlist.size(); + + if(n < 1) + { + return; + } + + size = list->count(); + + if(size < (n + 1)) + { + return; + } + + if(selectedlist.at(n - 1)->data(Qt::UserRole).toInt() > (size - 2)) + { + return; + } + + for(i=(n-1); i>=0; i--) + { + sigcomp_nr = selectedlist.at(i)->data(Qt::UserRole).toInt(); + + signalcomp = mainwindow->signalcomp[sigcomp_nr]; + + mainwindow->signalcomp[sigcomp_nr] = mainwindow->signalcomp[sigcomp_nr + 1]; + + mainwindow->signalcomp[sigcomp_nr + 1] = signalcomp; + + selected_signals[i] = sigcomp_nr; + } + + load_signalcomps(); + + for(i=0; iitem(selected_signals[i] + 1)->setSelected(TRUE); + } + + mainwindow->setup_viewbuf(); +} + + +void UI_SignalChooser::signalDelete() +{ + int i, j, k, n, p, + sigcomp_nr; + + QListWidgetItem *item; + + QList selectedlist; + + + selectedlist = list->selectedItems(); + + n = selectedlist.size(); + + if(n < 1) + { + return; + } + + for(k=0; kdata(Qt::UserRole).toInt(); + + sigcomp_nr -= k; + + if(mainwindow->spectrumdock->signalcomp == mainwindow->signalcomp[sigcomp_nr]) + { + mainwindow->spectrumdock->clear(); + mainwindow->spectrumdock->dock->hide(); + } + + for(i=0; isignalcomp[sigcomp_nr]->spectr_dialog[i]; + + if(p != 0) + { + delete mainwindow->spectrumdialog[p - 1]; + + mainwindow->spectrumdialog[p - 1] = NULL; + } + } + + for(i=0; isignalcomp[sigcomp_nr]->avg_dialog[i]; + + if(p != 0) + { + delete mainwindow->averagecurvedialog[p - 1]; + + mainwindow->averagecurvedialog[p - 1] = NULL; + } + } + + if(mainwindow->signalcomp[sigcomp_nr]->hascursor2) + { + mainwindow->maincurve->crosshair_2_active = 0; + mainwindow->maincurve->crosshair_2_moving = 0; + } + + if(mainwindow->signalcomp[sigcomp_nr]->hascursor1) + { + mainwindow->maincurve->crosshair_1_active = 0; + mainwindow->maincurve->crosshair_2_active = 0; + mainwindow->maincurve->crosshair_1_moving = 0; + mainwindow->maincurve->crosshair_2_moving = 0; + + for(i=0; isignalcomps; i++) + { + mainwindow->signalcomp[i]->hascursor2 = 0; + } + } + + if(mainwindow->signalcomp[sigcomp_nr]->hasruler) + { + mainwindow->maincurve->ruler_active = 0; + mainwindow->maincurve->ruler_moving = 0; + } + + for(j=0; jsignalcomp[sigcomp_nr]->filter_cnt; j++) + { + free(mainwindow->signalcomp[sigcomp_nr]->filter[j]); + } + + mainwindow->signalcomp[sigcomp_nr]->filter_cnt = 0; + + for(j=0; jsignalcomp[sigcomp_nr]->ravg_filter_cnt; j++) + { + free_ravg_filter(mainwindow->signalcomp[sigcomp_nr]->ravg_filter[j]); + } + + mainwindow->signalcomp[sigcomp_nr]->ravg_filter_cnt = 0; + + if(mainwindow->signalcomp[sigcomp_nr]->ecg_filter != NULL) + { + free_ecg_filter(mainwindow->signalcomp[sigcomp_nr]->ecg_filter); + + mainwindow->signalcomp[sigcomp_nr]->ecg_filter = NULL; + + strcpy(mainwindow->signalcomp[sigcomp_nr]->signallabel, mainwindow->signalcomp[sigcomp_nr]->signallabel_bu); + mainwindow->signalcomp[sigcomp_nr]->signallabellen = mainwindow->signalcomp[sigcomp_nr]->signallabellen_bu; + strcpy(mainwindow->signalcomp[sigcomp_nr]->physdimension, mainwindow->signalcomp[sigcomp_nr]->physdimension_bu); + } + + for(j=0; jsignalcomp[sigcomp_nr]->fidfilter_cnt; j++) + { + free(mainwindow->signalcomp[sigcomp_nr]->fidfilter[j]); + fid_run_free(mainwindow->signalcomp[sigcomp_nr]->fid_run[j]); + fid_run_freebuf(mainwindow->signalcomp[sigcomp_nr]->fidbuf[j]); + fid_run_freebuf(mainwindow->signalcomp[sigcomp_nr]->fidbuf2[j]); + } + + mainwindow->signalcomp[sigcomp_nr]->fidfilter_cnt = 0; + + free(mainwindow->signalcomp[sigcomp_nr]); + + for(i=sigcomp_nr; isignalcomps - 1; i++) + { + mainwindow->signalcomp[i] = mainwindow->signalcomp[i + 1]; + } + + mainwindow->signalcomps--; + } + + load_signalcomps(); + + mainwindow->setup_viewbuf(); +} + + +void UI_SignalChooser::signalInvert() +{ + int i, j, k, n, + selected_signals[MAXSIGNALS]; + + char str[512]; + + QList selectedlist; + + + selectedlist = list->selectedItems(); + + n = selectedlist.size(); + + if(n < 1) + { + return; + } + + for(k=0; kdata(Qt::UserRole).toInt(); + + selected_signals[k] = j; + + for(i=0; isignalcomp[j]->num_of_signals; i++) + { + mainwindow->signalcomp[j]->factor[i] *= -1; + + strcpy(str, mainwindow->signalcomp[j]->edfhdr->edfparam[mainwindow->signalcomp[j]->edfsignal[i]].label); + + strip_types_from_label(str); + + if(i == 0) + { + if(mainwindow->signalcomp[j]->factor[i] < 0) + { + sprintf(mainwindow->signalcomp[j]->signallabel, + "- %s", + str); + } + else + { + sprintf(mainwindow->signalcomp[j]->signallabel, + "%s", + str); + } + } + else + { + if(mainwindow->signalcomp[j]->factor[i] < 0) + { + sprintf(mainwindow->signalcomp[j]->signallabel + strlen(mainwindow->signalcomp[j]->signallabel), + " - %s", + str); + } + else + { + sprintf(mainwindow->signalcomp[j]->signallabel + strlen(mainwindow->signalcomp[j]->signallabel), + " + %s", + str); + } + } + + remove_trailing_spaces(mainwindow->signalcomp[j]->signallabel); + + mainwindow->signalcomp[j]->signallabellen = strlen(mainwindow->signalcomp[j]->signallabel); + + if(mainwindow->signalcomp[j]->signallabellen > 480) break; + } + + if(mainwindow->signalcomp[j]->ecg_filter != NULL) + { + reset_ecg_filter(mainwindow->signalcomp[j]->ecg_filter); + + strcpy(mainwindow->signalcomp[j]->signallabel_bu, mainwindow->signalcomp[j]->signallabel); + + strcpy(mainwindow->signalcomp[j]->signallabel, "HR"); + + mainwindow->signalcomp[j]->signallabellen_bu = mainwindow->signalcomp[j]->signallabellen; + + mainwindow->signalcomp[j]->signallabellen = strlen(mainwindow->signalcomp[j]->signallabel); + } + } + + load_signalcomps(); + + for(i=0; iitem(selected_signals[i])->setSelected(TRUE); + } + + mainwindow->setup_viewbuf(); +} + + +void UI_SignalChooser::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 #include #include +#include #include #include +#include #include "global.h" #include "mainwindow.h" #include "viewcurve.h" #include "adjustfiltersettings.h" +#include "ecg_filter.h" +#include "utils.h" + class UI_Mainwindow; +class ViewCurve; @@ -60,7 +66,7 @@ Q_OBJECT public: - UI_SignalChooser(QWidget *, int); + UI_SignalChooser(QWidget *, int, int *sgnl_nr = NULL); UI_Mainwindow *mainwindow; @@ -69,16 +75,28 @@ QDialog *signalchooser_dialog; -QPushButton *CloseButton; +QPushButton *CloseButton, + *UpButton, + *DownButton, + *DeleteButton, + *InvertButton; QListWidget *list; -int task; +int task, + *signal_nr; + +void strip_types_from_label(char *); +void load_signalcomps(void); private slots: void call_sidemenu(QListWidgetItem *); +void signalUp(); +void signalDown(); +void signalDelete(); +void signalInvert(); }; diff -Nru edfbrowser-1.30/signalcurve.cpp edfbrowser-1.38/signalcurve.cpp --- edfbrowser-1.30/signalcurve.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/signalcurve.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -45,11 +45,14 @@ BorderColor = Qt::lightGray; RulerColor = Qt::black; TextColor = Qt::black; + crosshair_1_color = Qt::red; + + Marker1Pen.setStyle(Qt::DashLine); + Marker1Pen.setColor(Qt::yellow); dbuf = NULL; fbuf = NULL; - h_rastersize = 10; - v_rastersize = 10; + ibuf = NULL; bordersize = 60; drawHruler = 1; drawVruler = 1; @@ -72,13 +75,14 @@ crosshair_1_value = 0.0; crosshair_1_value_2 = 0.0; crosshair_1_x_position = 0; - - crosshair_1_color = Qt::red; + marker_1_position = 0.5; + fillsurface = 0; cursorEnabled = TRUE; printEnabled = TRUE; dashBoardEnabled = TRUE; updates_enabled = TRUE; + Marker1Enabled = FALSE; spectrum_color = NULL; @@ -334,13 +338,15 @@ backup_color_1 = SignalColor; SignalColor = Qt::black; backup_color_2 = RasterColor; - RasterColor = Qt::darkGray; + RasterColor = Qt::black; backup_color_3 = BorderColor; - BorderColor = Qt::lightGray; + BorderColor = Qt::black; backup_color_4 = RulerColor; RulerColor = Qt::black; backup_color_5 = TextColor; TextColor = Qt::black; + backup_color_6 = Marker1Pen.color(); + Marker1Pen.setColor(Qt::black); } @@ -351,6 +357,7 @@ BorderColor = backup_color_3; RulerColor = backup_color_4; TextColor = backup_color_5; + Marker1Pen.setColor(backup_color_6); } @@ -481,20 +488,33 @@ void SignalCurve::drawWidget_to_printer(QPainter *painter, int w, int h) { - int i, - ruler_divisor, - value_skip, + int i, j, precision, - bordersize_backup=0; + bordersize_backup=0, + p_w, + p_divisor, + p_range, + p_multiplier, + p_ruler_startvalue, + p_ruler_endvalue, + p_tmp, + p_h, + p2_divisor, + p2_range, + p2_multiplier, + p2_ruler_startvalue, + p2_ruler_endvalue, + p2_tmp; char str[128]; double v_sens, offset, h_step, - rasterstep, value, - p_factor; + p_factor, + p_pixels_per_unit, + p2_pixels_per_unit; QString q_str; @@ -519,134 +539,186 @@ /////////////////////////////////// draw the rulers /////////////////////////////////////////// - if((drawHruler) && (h_rastersize > 1) && (bordersize > (19 * p_factor))) + p_w = w - bordersize - bordersize; + + p_multiplier = 1; + + while((h_ruler_endvalue * p_multiplier) < 10000.0) { - painter->setPen(RulerColor); + p_multiplier *= 10; - painter->drawLine(bordersize, h - bordersize + (5 * p_factor), w - bordersize, h - bordersize + (5 * p_factor)); + if(p_multiplier > 10000000) + { + break; + } + } - ruler_divisor = 10; + p_ruler_startvalue = h_ruler_startvalue * p_multiplier; - rasterstep = (double)(w - (bordersize * 2)) / (h_rastersize * ruler_divisor); + p_ruler_endvalue = h_ruler_endvalue * p_multiplier; - if(rasterstep < (7.0 * p_factor)) - { - ruler_divisor = 5; + p_range = p_ruler_endvalue - p_ruler_startvalue; - rasterstep = (double)(w - (bordersize * 2)) / (h_rastersize * ruler_divisor); - } + p_pixels_per_unit = (double)p_w / (double)p_range; - if(rasterstep < (4.0 * p_factor)) - { - ruler_divisor = 2; + p_divisor = 1; + + while((p_range / p_divisor) > 10) + { + p_divisor *= 2; - rasterstep = (double)(w - (bordersize * 2)) / (h_rastersize * ruler_divisor); + if((p_range / p_divisor) <= 10) + { + break; } - for(i = 0; i < ((h_rastersize * ruler_divisor) + 1); i++) + p_divisor /= 2; + + p_divisor *= 5; + + if((p_range / p_divisor) <= 10) { - if(i % ruler_divisor) painter->drawLine((i * rasterstep) + bordersize , h - bordersize + (5 * p_factor), (i * rasterstep) + bordersize, h - bordersize + ((5 + 4) * p_factor)); + break; } - rasterstep = (double)(w - (bordersize * 2)) / h_rastersize; + p_divisor *= 2; + } - value_skip = 1; + if(drawHruler && (bordersize > (19 * p_factor))) + { + painter->setPen(RulerColor); - if(rasterstep < (60 * p_factor)) value_skip = 2; - if(rasterstep < (30 * p_factor)) value_skip = 4; - if(rasterstep < (15 * p_factor)) value_skip = 8; - if((w - (bordersize * 2)) < (120 * p_factor)) value_skip = h_rastersize; + painter->drawLine(bordersize, h - bordersize + (5 * p_factor), w - bordersize, h - bordersize + (5 * p_factor)); - for(i = 0; i < (h_rastersize + 1); i++) + h_ruler_precision = 0; + + if((h_ruler_endvalue < 10.0) && (h_ruler_endvalue > -10.0) && (h_ruler_startvalue < 10.0) && (h_ruler_startvalue > -10.0)) { - painter->drawLine((i * rasterstep) + bordersize , h - bordersize + (5 * p_factor), (i * rasterstep) + bordersize, h - bordersize + ((5 + 10) * p_factor)); + h_ruler_precision = 1; - if(!(i % value_skip)) + if((h_ruler_endvalue < 1.0) && (h_ruler_endvalue > -1.0) && (h_ruler_startvalue < 1.0) && (h_ruler_startvalue > -1.0)) { - value = h_ruler_startvalue - (((h_ruler_startvalue - h_ruler_endvalue) / h_rastersize) * i); - - q_str.setNum(value, 'f', h_ruler_precision); + h_ruler_precision = 2; - if(i == h_rastersize) + if((h_ruler_endvalue < 0.1) && (h_ruler_endvalue > -0.1) && (h_ruler_startvalue < 0.1) && (h_ruler_startvalue > -0.1)) { - if(h_label[0] != 0) + h_ruler_precision = 3; + + if((h_ruler_endvalue < 0.01) && (h_ruler_endvalue > -0.01) && (h_ruler_startvalue < 0.01) && (h_ruler_startvalue > -0.01)) { - q_str.append(" "); - q_str.append(h_label); + h_ruler_precision = 4; } } + } + } - painter->drawText(bordersize + (i * rasterstep) - (30 * p_factor), h - bordersize + (18 * p_factor), 60 * p_factor, 16 * p_factor, Qt::AlignCenter | Qt::TextSingleLine, q_str); + for(i = (p_ruler_startvalue / p_divisor) * p_divisor; i <= p_ruler_endvalue; i += p_divisor) + { + if(i < p_ruler_startvalue) + { + continue; } + + q_str.setNum((double)i / (double)p_multiplier, 'f', h_ruler_precision); + + p_tmp = (double)(i - p_ruler_startvalue) * p_pixels_per_unit; + + painter->drawText(bordersize + p_tmp - (30 * p_factor), h - bordersize + (18 * p_factor), 60 * p_factor, 16 * p_factor, Qt::AlignCenter | Qt::TextSingleLine, q_str); + + painter->drawLine(bordersize + p_tmp, h - bordersize + (5 * p_factor), bordersize + p_tmp, h - bordersize + ((5 + 10) * p_factor)); } + + painter->drawText(w - bordersize + (20 * p_factor), h - bordersize + (18 * p_factor), 40 * p_factor, 16 * p_factor, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, h_label); } - if((drawVruler) && (v_rastersize > 1) && (bordersize > (29 * p_factor))) + p_h = h - bordersize - bordersize; + + p2_multiplier = 1; + + while((max_value * p2_multiplier) < 10000.0) { - painter->setPen(RulerColor); + p2_multiplier *= 10; - painter->drawLine(bordersize - (5 * p_factor), bordersize, bordersize - (5 * p_factor), h - bordersize); + if(p2_multiplier > 10000000) + { + break; + } + } - ruler_divisor = 10; + p2_ruler_startvalue = min_value * p2_multiplier; - rasterstep = (double)(h - (bordersize * 2)) / (v_rastersize * ruler_divisor); + p2_ruler_endvalue = max_value * p2_multiplier; - if(rasterstep < (7.0 * p_factor)) - { - ruler_divisor = 5; + p2_range = p2_ruler_endvalue - p2_ruler_startvalue; - rasterstep = (double)(h - (bordersize * 2)) / (v_rastersize * ruler_divisor); - } + p2_pixels_per_unit = (double)p_h / (double)p2_range; - if(rasterstep < (4.0 * p_factor)) - { - ruler_divisor = 2; + p2_divisor = 1; + + while((p2_range / p2_divisor) > 10) + { + p2_divisor *= 2; - rasterstep = (double)(h - (bordersize * 2)) / (v_rastersize * ruler_divisor); + if((p2_range / p2_divisor) <= 10) + { + break; } - for(i = 0; i < ((v_rastersize * ruler_divisor) + 1); i++) + p2_divisor /= 2; + + p2_divisor *= 5; + + if((p2_range / p2_divisor) <= 10) { - if(i % ruler_divisor) painter->drawLine(bordersize - (5 * p_factor), bordersize + (i * rasterstep), bordersize - ((5 + 4) * p_factor), bordersize + (i * rasterstep)); + break; } - rasterstep = (double)(h - (bordersize * 2)) / v_rastersize; + p2_divisor *= 2; + } + + if(drawVruler && (bordersize > (29 * p_factor))) + { + painter->setPen(RulerColor); - value_skip = 1; + painter->drawLine(bordersize - (5 * p_factor), bordersize, bordersize - (5 * p_factor), h - bordersize); - if(rasterstep < (40 * p_factor)) value_skip = 2; - if(rasterstep < (20 * p_factor)) value_skip = 4; - if(rasterstep < (10 * p_factor)) value_skip = 8; - if((h - (bordersize * 2)) < (80 * p_factor)) value_skip = v_rastersize; + precision = 0; - for(i = 0; i < (v_rastersize + 1); i++) + if((max_value < 10.0) && (max_value > -10.0) && (min_value < 10.0) && (min_value > -10.0)) { - painter->drawLine(bordersize - (5 * p_factor), bordersize + (i * rasterstep), bordersize - ((5 + 10) * p_factor), bordersize + (i * rasterstep)); + precision = 1; - if(!(i % value_skip)) + if((max_value < 1.0) && (max_value > -1.0) && (min_value < 1.0) && (min_value > -1.0)) { - value = max_value - (((max_value - min_value) / v_rastersize) * i); - precision = 0; - if(max_value < 1000.0) - { - precision = 1; - } - if(max_value < 100.0) - { - precision = 2; - } - if(max_value < 10.0) + precision = 2; + + if((max_value < 0.1) && (max_value > -0.1) && (min_value < 0.1) && (min_value > -0.1)) { precision = 3; + + if((max_value < 0.01) && (max_value > -0.01) && (min_value < 0.01) && (min_value > -0.01)) + { + precision = 4; + } } - if(max_value < 1.0) - { - precision = 4; - } - q_str.setNum(value, 'f', precision); - painter->drawText(3 * p_factor, bordersize + (i * rasterstep) - (8 * p_factor), 40 * p_factor, 16 * p_factor, Qt::AlignRight | Qt::AlignVCenter | Qt::TextSingleLine, q_str); } } + + for(i = (p2_ruler_startvalue / p2_divisor) * p2_divisor; i <= p2_ruler_endvalue; i += p2_divisor) + { + if(i < p2_ruler_startvalue) + { + continue; + } + + q_str.setNum((double)i / (double)p2_multiplier, 'f', precision); + + p2_tmp = (double)(i - p2_ruler_startvalue) * p2_pixels_per_unit; + + painter->drawText((3 * p_factor), h - bordersize - p2_tmp - (8 * p_factor), (40 * p_factor), (16 * p_factor), Qt::AlignRight | Qt::AlignVCenter | Qt::TextSingleLine, q_str); + + painter->drawLine(bordersize - (5 * p_factor), h - bordersize - p2_tmp, bordersize - (15 * p_factor), h - bordersize - p2_tmp); + } } /////////////////////////////////// draw the labels /////////////////////////////////////////// @@ -691,29 +763,33 @@ painter->drawRect (0, 0, w - 1, h - 1); - if(h_rastersize > 1) + for(i = (p_ruler_startvalue / p_divisor) * p_divisor; i <= p_ruler_endvalue; i += p_divisor) { - rasterstep = (double)w / h_rastersize; - - for(i = 1; i < h_rastersize; i++) + if(i < p_ruler_startvalue) { - painter->drawLine(i * rasterstep, 0, i * rasterstep, h); + continue; } + + p_tmp = (double)(i - p_ruler_startvalue) * p_pixels_per_unit; + + painter->drawLine(p_tmp, 0, p_tmp, h); } - if(v_rastersize > 1) + for(i = (p2_ruler_startvalue / p2_divisor) * p2_divisor; i <= p2_ruler_endvalue; i += p2_divisor) { - rasterstep = (double)h / v_rastersize; - - for(i = 1; i < v_rastersize; i++) + if(i < p2_ruler_startvalue) { - painter->drawLine(0, i * rasterstep, w, i * rasterstep); + continue; } + + p2_tmp = (double)(i - p2_ruler_startvalue) * p2_pixels_per_unit; + + painter->drawLine(0, h - p2_tmp, w, h - p2_tmp); } /////////////////////////////////// draw the curve /////////////////////////////////////////// - if((dbuf == NULL) && (fbuf == NULL)) return; + if((dbuf == NULL) && (ibuf == NULL) && (fbuf == NULL)) return; if(max_value == min_value) return; @@ -731,20 +807,37 @@ { for(i = 0; i < bufsize; i++) { - if(bufsize < (w / 2)) + if(fillsurface) { - painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i] + offset) * v_sens); - if(i) + if(bufsize < w) { - painter->drawLine(i * h_step, (dbuf[i - 1] + offset) * v_sens, i * h_step, (dbuf[i] + offset) * v_sens); + for(j = 0; j < h_step; j++) + { + painter->drawLine((i * h_step) + j, (dbuf[i] + offset) * v_sens, (i * h_step) + j, h); + } + } + else + { + painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, i * h_step, h); } } else { - if(i < (bufsize - 1)) + if(bufsize < (w / 2)) { + painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i] + offset) * v_sens); + if(i) { - painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i + 1] + offset) * v_sens); + painter->drawLine(i * h_step, (dbuf[i - 1] + offset) * v_sens, i * h_step, (dbuf[i] + offset) * v_sens); + } + } + else + { + if(i < (bufsize - 1)) + { + { + painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i + 1] + offset) * v_sens); + } } } } @@ -762,24 +855,93 @@ } } + if(ibuf) + { + for(i = 0; i < bufsize; i++) + { + if(fillsurface) + { + if(bufsize < w) + { + for(j = 0; j < h_step; j++) + { + painter->drawLine((i * h_step) + j, ((double)(ibuf[i]) + offset) * v_sens, (i * h_step) + j, h); + } + } + else + { + painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, i * h_step, h); + } + } + else + { + if(bufsize < (w / 2)) + { + painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, (i + 1) * h_step, ((double)(ibuf[i]) + offset) * v_sens); + if(i) + { + painter->drawLine(i * h_step, ((double)(ibuf[i - 1]) + offset) * v_sens, i * h_step, ((double)(ibuf[i]) + offset) * v_sens); + } + } + else + { + if(i < (bufsize - 1)) + { + { + painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, (i + 1) * h_step, ((double)(ibuf[i + 1]) + offset) * v_sens); + } + } + } + } + + if(crosshair_1_active) + { + if(i==((int)(((double)crosshair_1_x_position * p_factor) / h_step))) + { + crosshair_1_y_value = ((double)(ibuf[i]) + offset) * v_sens; + crosshair_1_value = (double)(ibuf[i]); + value = (h_ruler_endvalue - h_ruler_startvalue) / bufsize; + crosshair_1_value_2 = (i * value) + (0.5 * value) + h_ruler_startvalue; + } + } + } + } + if(fbuf) { for(i = 0; i < bufsize; i++) { - if(bufsize < (w / 2)) + if(fillsurface) { - painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i] + offset) * v_sens); - if(i) + if(bufsize < w) + { + for(j = 0; j < h_step; j++) + { + painter->drawLine((i * h_step) + j, (fbuf[i] + offset) * v_sens, (i * h_step) + j, h); + } + } + else { - painter->drawLine(i * h_step, (fbuf[i - 1] + offset) * v_sens, i * h_step, (fbuf[i] + offset) * v_sens); + painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, i * h_step, h); } } else { - if(i < (bufsize - 1)) + if(bufsize < (w / 2)) { + painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i] + offset) * v_sens); + if(i) { - painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i + 1] + offset) * v_sens); + painter->drawLine(i * h_step, (fbuf[i - 1] + offset) * v_sens, i * h_step, (fbuf[i] + offset) * v_sens); + } + } + else + { + if(i < (bufsize - 1)) + { + { + painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i + 1] + offset) * v_sens); + } } } } @@ -797,8 +959,19 @@ } } +/////////////////////////////////// draw the marker /////////////////////////////////////////// + + if(Marker1Enabled == TRUE) + { + painter->setPen(Marker1Pen); + + painter->drawLine(w * marker_1_position, 0, w * marker_1_position, h); + } + /////////////////////////////////// draw the cursor /////////////////////////////////////////// + painter->setPen(TextColor); + if(crosshair_1_active) { QPainterPath path; @@ -839,18 +1012,31 @@ void SignalCurve::drawWidget(QPainter *painter, int w, int h) { - int i, - ruler_divisor, - value_skip, - precision; + int i, j, + precision, + p_w, + p_divisor, + p_range, + p_multiplier, + p_ruler_startvalue, + p_ruler_endvalue, + p_tmp, + p_h, + p2_divisor, + p2_range, + p2_multiplier, + p2_ruler_startvalue, + p2_ruler_endvalue, + p2_tmp; double v_sens, offset, h_step, - rasterstep, value, - pixelsPerHz, - max_colorbar_value; + pixelsPerUnit, + max_colorbar_value, + p_pixels_per_unit, + p2_pixels_per_unit; char str[128]; @@ -868,134 +1054,216 @@ /////////////////////////////////// draw the rulers /////////////////////////////////////////// - if((drawHruler) && (h_rastersize > 1) && (bordersize > 19)) + p_w = w - bordersize - bordersize; + + p_multiplier = 1; + + while((h_ruler_endvalue * p_multiplier) < 10000.0) { - painter->setPen(RulerColor); + p_multiplier *= 10; - painter->drawLine(bordersize, h - bordersize + 5, w - bordersize, h - bordersize + 5); + if(p_multiplier > 10000000) + { + break; + } + } - ruler_divisor = 10; + p_ruler_startvalue = h_ruler_startvalue * p_multiplier; - rasterstep = (double)(w - (bordersize * 2)) / (h_rastersize * ruler_divisor); + p_ruler_endvalue = h_ruler_endvalue * p_multiplier; - if(rasterstep < 7.0) - { - ruler_divisor = 5; + p_range = p_ruler_endvalue - p_ruler_startvalue; - rasterstep = (double)(w - (bordersize * 2)) / (h_rastersize * ruler_divisor); - } + p_pixels_per_unit = (double)p_w / (double)p_range; - if(rasterstep < 4.0) - { - ruler_divisor = 2; + p_divisor = 1; + + while((p_range / p_divisor) > 10) + { + p_divisor *= 2; - rasterstep = (double)(w - (bordersize * 2)) / (h_rastersize * ruler_divisor); + if((p_range / p_divisor) <= 10) + { + break; } - for(i = 0; i < ((h_rastersize * ruler_divisor) + 1); i++) + p_divisor /= 2; + + p_divisor *= 5; + + if((p_range / p_divisor) <= 10) { - if(i % ruler_divisor) painter->drawLine((i * rasterstep) + bordersize , h - bordersize + 5, (i * rasterstep) + bordersize, h - bordersize + 5 + 4); + break; } - rasterstep = (double)(w - (bordersize * 2)) / h_rastersize; + p_divisor *= 2; + } - value_skip = 1; +// printf("p_multiplier is %i\n" +// "p_ruler_startvalue is %i\n" +// "p_ruler_endvalue is %i\n" +// "p_range is %i\n" +// "p_divisor is %i\n" +// "p_pixels_per_unit is %f\n\n", +// p_multiplier, +// p_ruler_startvalue, +// p_ruler_endvalue, +// p_range, +// p_divisor, +// p_pixels_per_unit); - if(rasterstep < 60) value_skip = 2; - if(rasterstep < 30) value_skip = 4; - if(rasterstep < 15) value_skip = 8; - if((w - (bordersize * 2)) < 120) value_skip = h_rastersize; + if(drawHruler && (bordersize > 19)) + { + painter->setPen(RulerColor); - for(i = 0; i < (h_rastersize + 1); i++) + painter->drawLine(bordersize, h - bordersize + 5, w - bordersize, h - bordersize + 5); + + h_ruler_precision = 0; + + if((h_ruler_endvalue < 10.0) && (h_ruler_endvalue > -10.0) && (h_ruler_startvalue < 10.0) && (h_ruler_startvalue > -10.0)) { - painter->drawLine((i * rasterstep) + bordersize , h - bordersize + 5, (i * rasterstep) + bordersize, h - bordersize + 5 + 10); + h_ruler_precision = 1; - if(!(i % value_skip)) + if((h_ruler_endvalue < 1.0) && (h_ruler_endvalue > -1.0) && (h_ruler_startvalue < 1.0) && (h_ruler_startvalue > -1.0)) { - value = h_ruler_startvalue - (((h_ruler_startvalue - h_ruler_endvalue) / h_rastersize) * i); - - q_str.setNum(value, 'f', h_ruler_precision); + h_ruler_precision = 2; - if(i == h_rastersize) + if((h_ruler_endvalue < 0.1) && (h_ruler_endvalue > -0.1) && (h_ruler_startvalue < 0.1) && (h_ruler_startvalue > -0.1)) { - if(h_label[0] != 0) + h_ruler_precision = 3; + + if((h_ruler_endvalue < 0.01) && (h_ruler_endvalue > -0.01) && (h_ruler_startvalue < 0.01) && (h_ruler_startvalue > -0.01)) { - q_str.append(" "); - q_str.append(h_label); + h_ruler_precision = 4; } } + } + } - painter->drawText(bordersize + (i * rasterstep) - 30, h - bordersize + 18, 60, 16, Qt::AlignCenter | Qt::TextSingleLine, q_str); + for(i = (p_ruler_startvalue / p_divisor) * p_divisor; i <= p_ruler_endvalue; i += p_divisor) + { + if(i < p_ruler_startvalue) + { + continue; } + + q_str.setNum((double)i / (double)p_multiplier, 'f', h_ruler_precision); + + p_tmp = (double)(i - p_ruler_startvalue) * p_pixels_per_unit; + + painter->drawText(bordersize + p_tmp - 30, h - bordersize + 18, 60, 16, Qt::AlignCenter | Qt::TextSingleLine, q_str); + + painter->drawLine(bordersize + p_tmp, h - bordersize + 5, bordersize + p_tmp, h - bordersize + 5 + 10); } + + painter->drawText(w - bordersize + 20, h - bordersize + 18, 40, 16, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, h_label); } - if((drawVruler) && (v_rastersize > 1) && (bordersize > 29)) + p_h = h - bordersize - bordersize; + + p2_multiplier = 1; + + while((max_value * p2_multiplier) < 10000.0) { - painter->setPen(RulerColor); + p2_multiplier *= 10; - painter->drawLine(bordersize - 5, bordersize, bordersize - 5, h - bordersize); + if(p2_multiplier > 10000000) + { + break; + } + } - ruler_divisor = 10; + p2_ruler_startvalue = min_value * p2_multiplier; - rasterstep = (double)(h - (bordersize * 2)) / (v_rastersize * ruler_divisor); + p2_ruler_endvalue = max_value * p2_multiplier; - if(rasterstep < 7.0) - { - ruler_divisor = 5; + p2_range = p2_ruler_endvalue - p2_ruler_startvalue; - rasterstep = (double)(h - (bordersize * 2)) / (v_rastersize * ruler_divisor); - } + p2_pixels_per_unit = (double)p_h / (double)p2_range; - if(rasterstep < 4.0) - { - ruler_divisor = 2; + p2_divisor = 1; - rasterstep = (double)(h - (bordersize * 2)) / (v_rastersize * ruler_divisor); + while((p2_range / p2_divisor) > 10) + { + p2_divisor *= 2; + + if((p2_range / p2_divisor) <= 10) + { + break; } - for(i = 0; i < ((v_rastersize * ruler_divisor) + 1); i++) + p2_divisor /= 2; + + p2_divisor *= 5; + + if((p2_range / p2_divisor) <= 10) { - if(i % ruler_divisor) painter->drawLine(bordersize - 5, bordersize + (i * rasterstep), bordersize - 5 - 4, bordersize + (i * rasterstep)); + break; } - rasterstep = (double)(h - (bordersize * 2)) / v_rastersize; + p2_divisor *= 2; + } + +// printf("p2_multiplier is %i\n" +// "p2_ruler_startvalue is %i\n" +// "p2_ruler_endvalue is %i\n" +// "p2_range is %i\n" +// "p2_divisor is %i\n" +// "p2_pixels_per_unit is %f\n" +// "max_value is %f\n" +// "min_value is %f\n\n", +// p2_multiplier, +// p2_ruler_startvalue, +// p2_ruler_endvalue, +// p2_range, +// p2_divisor, +// p2_pixels_per_unit, +// max_value, +// min_value); - value_skip = 1; + if(drawVruler && (bordersize > 29)) + { + painter->setPen(RulerColor); - if(rasterstep < 40) value_skip = 2; - if(rasterstep < 20) value_skip = 4; - if(rasterstep < 10) value_skip = 8; - if((h - (bordersize * 2)) < 80) value_skip = v_rastersize; + painter->drawLine(bordersize - 5, bordersize, bordersize - 5, h - bordersize); - for(i = 0; i < (v_rastersize + 1); i++) + precision = 0; + + if((max_value < 10.0) && (max_value > -10.0) && (min_value < 10.0) && (min_value > -10.0)) { - painter->drawLine(bordersize - 5, bordersize + (i * rasterstep), bordersize - 5 - 10, bordersize + (i * rasterstep)); + precision = 1; - if(!(i % value_skip)) + if((max_value < 1.0) && (max_value > -1.0) && (min_value < 1.0) && (min_value > -1.0)) { - value = max_value - (((max_value - min_value) / v_rastersize) * i); - precision = 0; - if(max_value < 1000.0) - { - precision = 1; - } - if(max_value < 100.0) - { - precision = 2; - } - if(max_value < 10.0) + precision = 2; + + if((max_value < 0.1) && (max_value > -0.1) && (min_value < 0.1) && (min_value > -0.1)) { precision = 3; + + if((max_value < 0.01) && (max_value > -0.01) && (min_value < 0.01) && (min_value > -0.01)) + { + precision = 4; + } } - if(max_value < 1.0) - { - precision = 4; - } - q_str.setNum(value, 'f', precision); - painter->drawText(3, bordersize + (i * rasterstep) - 8, 40, 16, Qt::AlignRight | Qt::AlignVCenter | Qt::TextSingleLine, q_str); } } + + for(i = (p2_ruler_startvalue / p2_divisor) * p2_divisor; i <= p2_ruler_endvalue; i += p2_divisor) + { + if(i < p2_ruler_startvalue) + { + continue; + } + + q_str.setNum((double)i / (double)p2_multiplier, 'f', precision); + + p2_tmp = (double)(i - p2_ruler_startvalue) * p2_pixels_per_unit; + + painter->drawText(3, h - bordersize - p2_tmp - 8, 40, 16, Qt::AlignRight | Qt::AlignVCenter | Qt::TextSingleLine, q_str); + + painter->drawLine(bordersize - 5, h - bordersize - p2_tmp, bordersize - 5 - 10, h - bordersize - p2_tmp); + } } /////////////////////////////////// draw the labels /////////////////////////////////////////// @@ -1047,13 +1315,13 @@ max_colorbar_value *= 1.05; - pixelsPerHz = (double)w / (h_ruler_endvalue - h_ruler_startvalue); + pixelsPerUnit = (double)w / (h_ruler_endvalue - h_ruler_startvalue); if((spectrum_color->freq[0] > h_ruler_startvalue) && (spectrum_color->items > 1)) { painter->fillRect(0, (max_colorbar_value - spectrum_color->value[0]) * ((double)h / max_colorbar_value), - (spectrum_color->freq[0] - h_ruler_startvalue) * pixelsPerHz, + (spectrum_color->freq[0] - h_ruler_startvalue) * pixelsPerUnit, h, (Qt::GlobalColor)spectrum_color->color[0]); @@ -1065,14 +1333,14 @@ { if(spectrum_color->freq[i] > h_ruler_startvalue) { - painter->fillRect((spectrum_color->freq[i-1] - h_ruler_startvalue) * pixelsPerHz, + painter->fillRect((spectrum_color->freq[i-1] - h_ruler_startvalue) * pixelsPerUnit, (max_colorbar_value - spectrum_color->value[i]) * ((double)h / max_colorbar_value), - (spectrum_color->freq[i] - spectrum_color->freq[i-1]) * pixelsPerHz, + (spectrum_color->freq[i] - spectrum_color->freq[i-1]) * pixelsPerUnit, h, (Qt::GlobalColor)spectrum_color->color[i]); painter->setPen(Qt::lightGray); - painter->drawText((spectrum_color->freq[i-1] - h_ruler_startvalue) * pixelsPerHz + 10, 20, spectrum_color->label[i]); + painter->drawText((spectrum_color->freq[i-1] - h_ruler_startvalue) * pixelsPerUnit + 10, 20, spectrum_color->label[i]); } } } @@ -1081,7 +1349,7 @@ if(drawcurve_before_raster) { - if((dbuf == NULL) && (fbuf == NULL)) return; + if((dbuf == NULL) && (ibuf == NULL) && (fbuf == NULL)) return; if(max_value == min_value) return; @@ -1099,20 +1367,37 @@ { for(i = 0; i < bufsize; i++) { - if(bufsize < (w / 2)) + if(fillsurface) { - painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i] + offset) * v_sens); - if(i) + if(bufsize < w) { - painter->drawLine(i * h_step, (dbuf[i - 1] + offset) * v_sens, i * h_step, (dbuf[i] + offset) * v_sens); + for(j = 0; j < h_step; j++) + { + painter->drawLine((i * h_step) + j, (dbuf[i] + offset) * v_sens, (i * h_step) + j, h); + } + } + else + { + painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, i * h_step, h); } } else { - if(i < (bufsize - 1)) + if(bufsize < (w / 2)) { + painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i] + offset) * v_sens); + if(i) { - painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i + 1] + offset) * v_sens); + painter->drawLine(i * h_step, (dbuf[i - 1] + offset) * v_sens, i * h_step, (dbuf[i] + offset) * v_sens); + } + } + else + { + if(i < (bufsize - 1)) + { + { + painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i + 1] + offset) * v_sens); + } } } } @@ -1130,24 +1415,93 @@ } } + if(ibuf) + { + for(i = 0; i < bufsize; i++) + { + if(fillsurface) + { + if(bufsize < w) + { + for(j = 0; j < h_step; j++) + { + painter->drawLine((i * h_step) + j, ((double)(ibuf[i]) + offset) * v_sens, (i * h_step) + j, h); + } + } + else + { + painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, i * h_step, h); + } + } + else + { + if(bufsize < (w / 2)) + { + painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, (i + 1) * h_step, ((double)(ibuf[i]) + offset) * v_sens); + if(i) + { + painter->drawLine(i * h_step, ((double)(ibuf[i - 1]) + offset) * v_sens, i * h_step, ((double)(ibuf[i]) + offset) * v_sens); + } + } + else + { + if(i < (bufsize - 1)) + { + { + painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, (i + 1) * h_step, ((double)(ibuf[i + 1]) + offset) * v_sens); + } + } + } + } + + if(crosshair_1_active) + { + if(i==((int)(((double)crosshair_1_x_position) / h_step))) + { + crosshair_1_y_value = ((double)(ibuf[i]) + offset) * v_sens; + crosshair_1_value = (double)(ibuf[i]); + value = (h_ruler_endvalue - h_ruler_startvalue) / bufsize; + crosshair_1_value_2 = (i * value) + h_ruler_startvalue; + } + } + } + } + if(fbuf) { for(i = 0; i < bufsize; i++) { - if(bufsize < (w / 2)) + if(fillsurface) { - painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i] + offset) * v_sens); - if(i) + if(bufsize < w) { - painter->drawLine(i * h_step, (fbuf[i - 1] + offset) * v_sens, i * h_step, (fbuf[i] + offset) * v_sens); + for(j = 0; j < h_step; j++) + { + painter->drawLine((i * h_step) + j, (fbuf[i] + offset) * v_sens, (i * h_step) + j, h); + } + } + else + { + painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, i * h_step, h); } } else { - if(i < (bufsize - 1)) + if(bufsize < (w / 2)) { + painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i] + offset) * v_sens); + if(i) { - painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i + 1] + offset) * v_sens); + painter->drawLine(i * h_step, (fbuf[i - 1] + offset) * v_sens, i * h_step, (fbuf[i] + offset) * v_sens); + } + } + else + { + if(i < (bufsize - 1)) + { + { + painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i + 1] + offset) * v_sens); + } } } } @@ -1172,31 +1526,35 @@ painter->drawRect (0, 0, w - 1, h - 1); - if(h_rastersize > 1) + for(i = (p_ruler_startvalue / p_divisor) * p_divisor; i <= p_ruler_endvalue; i += p_divisor) { - rasterstep = (double)w / h_rastersize; - - for(i = 1; i < h_rastersize; i++) + if(i < p_ruler_startvalue) { - painter->drawLine(i * rasterstep, 0, i * rasterstep, h); + continue; } + + p_tmp = (double)(i - p_ruler_startvalue) * p_pixels_per_unit; + + painter->drawLine(p_tmp, 0, p_tmp, h); } - if(v_rastersize > 1) + for(i = (p2_ruler_startvalue / p2_divisor) * p2_divisor; i <= p2_ruler_endvalue; i += p2_divisor) { - rasterstep = (double)h / v_rastersize; - - for(i = 1; i < v_rastersize; i++) + if(i < p2_ruler_startvalue) { - painter->drawLine(0, i * rasterstep, w, i * rasterstep); + continue; } + + p2_tmp = (double)(i - p2_ruler_startvalue) * p2_pixels_per_unit; + + painter->drawLine(0, h - p2_tmp, w, h - p2_tmp); } /////////////////////////////////// draw the curve /////////////////////////////////////////// if(!drawcurve_before_raster) { - if((dbuf == NULL) && (fbuf == NULL)) return; + if((dbuf == NULL) && (ibuf == NULL) && (fbuf == NULL)) return; if(max_value == min_value) return; @@ -1214,18 +1572,33 @@ { for(i = 0; i < bufsize; i++) { - if(bufsize < (w / 2)) + if(fillsurface) { - painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i] + offset) * v_sens); - if(i) + if(bufsize < w) { - painter->drawLine(i * h_step, (dbuf[i - 1] + offset) * v_sens, i * h_step, (dbuf[i] + offset) * v_sens); + for(j = 0; j < h_step; j++) + { + painter->drawLine((i * h_step) + j, (dbuf[i] + offset) * v_sens, (i * h_step) + j, h); + } + } + else + { + painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, i * h_step, h); } } else { - if(i < (bufsize - 1)) + if(bufsize < (w / 2)) { + painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i] + offset) * v_sens); + if(i) + { + painter->drawLine(i * h_step, (dbuf[i - 1] + offset) * v_sens, i * h_step, (dbuf[i] + offset) * v_sens); + } + } + else + { + if(i < (bufsize - 1)) { painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i + 1] + offset) * v_sens); } @@ -1245,24 +1618,93 @@ } } + if(ibuf) + { + for(i = 0; i < bufsize; i++) + { + if(fillsurface) + { + if(bufsize < w) + { + for(j = 0; j < h_step; j++) + { + painter->drawLine((i * h_step) + j, ((double)(ibuf[i]) + offset) * v_sens, (i * h_step) + j, h); + } + } + else + { + painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, i * h_step, h); + } + } + else + { + if(bufsize < (w / 2)) + { + painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, (i + 1) * h_step, ((double)(ibuf[i]) + offset) * v_sens); + if(i) + { + painter->drawLine(i * h_step, ((double)(ibuf[i - 1]) + offset) * v_sens, i * h_step, ((double)(ibuf[i]) + offset) * v_sens); + } + } + else + { + if(i < (bufsize - 1)) + { + { + painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, (i + 1) * h_step, ((double)(ibuf[i + 1]) + offset) * v_sens); + } + } + } + } + + if(crosshair_1_active) + { + if(i==((int)(((double)crosshair_1_x_position) / h_step))) + { + crosshair_1_y_value = ((double)(ibuf[i]) + offset) * v_sens; + crosshair_1_value = (double)(ibuf[i]); + value = (h_ruler_endvalue - h_ruler_startvalue) / bufsize; + crosshair_1_value_2 = (i * value) + h_ruler_startvalue; + } + } + } + } + if(fbuf) { for(i = 0; i < bufsize; i++) { - if(bufsize < (w / 2)) + if(fillsurface) { - painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i] + offset) * v_sens); - if(i) + if(bufsize < w) { - painter->drawLine(i * h_step, (fbuf[i - 1] + offset) * v_sens, i * h_step, (fbuf[i] + offset) * v_sens); + for(j = 0; j < h_step; j++) + { + painter->drawLine((i * h_step) + j, (fbuf[i] + offset) * v_sens, (i * h_step) + j, h); + } + } + else + { + painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, i * h_step, h); } } else { - if(i < (bufsize - 1)) + if(bufsize < (w / 2)) { + painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i] + offset) * v_sens); + if(i) { - painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i + 1] + offset) * v_sens); + painter->drawLine(i * h_step, (fbuf[i - 1] + offset) * v_sens, i * h_step, (fbuf[i] + offset) * v_sens); + } + } + else + { + if(i < (bufsize - 1)) + { + { + painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i + 1] + offset) * v_sens); + } } } } @@ -1281,6 +1723,15 @@ } } +/////////////////////////////////// draw the marker /////////////////////////////////////////// + + if(Marker1Enabled == TRUE) + { + painter->setPen(Marker1Pen); + + painter->drawLine(w * marker_1_position, 0, w * marker_1_position, h); + } + /////////////////////////////////// draw the cursor /////////////////////////////////////////// if(crosshair_1_active) @@ -1329,6 +1780,26 @@ { dbuf = samplebuf; + ibuf = NULL; + + fbuf = NULL; + + bufsize = size; + + max_value = max_val; + + min_value = min_val; + + update(); +} + + +void SignalCurve::drawCurve(int *samplebuf, int size, double max_val, double min_val) +{ + ibuf = samplebuf; + + dbuf = NULL; + fbuf = NULL; bufsize = size; @@ -1347,6 +1818,8 @@ dbuf = NULL; + ibuf = NULL; + bufsize = size; max_value = max_val; @@ -1357,11 +1830,51 @@ } -void SignalCurve::setH_RulerValues(double start, double end, int precision) +void SignalCurve::setFillSurfaceEnabled(bool enabled) +{ + if(enabled == TRUE) + { + fillsurface = 1; + } + else + { + fillsurface = 0; + } + + update(); +} + + +void SignalCurve::setMarker1Position(double pos) +{ + marker_1_position = pos; + + if(marker_1_position > 1.01) marker_1_position = 1.01; + + if(marker_1_position < 0.0001) marker_1_position = 0.0001; + + update(); +} + + +void SignalCurve::setMarker1Enabled(bool on) +{ + Marker1Enabled = on; + update(); +} + + +void SignalCurve::setMarker1Color(QColor color) +{ + Marker1Pen.setColor(color); + update(); +} + + +void SignalCurve::setH_RulerValues(double start, double end) { h_ruler_startvalue = start; h_ruler_endvalue = end; - h_ruler_precision = precision; update(); } @@ -1410,20 +1923,6 @@ } -void SignalCurve::setH_RasterSize(int newsize) -{ - h_rastersize = newsize; - update(); -} - - -void SignalCurve::setV_RasterSize(int newsize) -{ - v_rastersize = newsize; - update(); -} - - void SignalCurve::setBorderSize(int newsize) { bordersize = newsize; @@ -1504,6 +2003,17 @@ } +void SignalCurve::setV_rulerEnabled(bool value) +{ + if(value == TRUE) + { + drawVruler = 1; + } + else + { + drawVruler = 0; + } +} diff -Nru edfbrowser-1.30/signalcurve.h edfbrowser-1.38/signalcurve.h --- edfbrowser-1.30/signalcurve.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/signalcurve.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -85,24 +85,28 @@ void setBorderColor(QColor); void setTextColor(QColor); void setBorderSize(int); - void setH_RasterSize(int); - void setV_RasterSize(int); - void setH_RulerValues(double, double, int); + void setH_RulerValues(double, double); void setH_label(const char *); void setV_label(const char *); void setUpperLabel1(const char *); void setUpperLabel2(const char *); void setLowerLabel(const char *); void drawCurve(double *, int , double , double ); + void drawCurve(int *, int , double , double ); void drawCurve( float *, int , double , double ); void create_button(const char *); void setCursorEnabled(bool); void setPrintEnabled(bool); void setDashBoardEnabled(bool); + void setMarker1Enabled(bool); + void setMarker1Position(double); + void setMarker1Color(QColor); void clear(); void setUpdatesEnabled(bool); void enableSpectrumColors(struct spectrum_markersblock *); void disableSpectrumColors(); + void setFillSurfaceEnabled(bool); + void setV_rulerEnabled(bool); signals: void extra_button_clicked(); @@ -135,10 +139,13 @@ backup_color_2, backup_color_3, backup_color_4, - backup_color_5; + backup_color_5, + backup_color_6; QPrinter *printer; + QPen Marker1Pen; + double max_value, min_value, *dbuf, @@ -148,13 +155,12 @@ printsize_y_factor, crosshair_1_value, crosshair_1_value_2, - crosshair_1_x_position; + crosshair_1_x_position, + marker_1_position; float *fbuf; int bufsize, - h_rastersize, - v_rastersize, bordersize, h_ruler_precision, drawHruler, @@ -175,7 +181,9 @@ w, h, old_w, - updates_enabled; + updates_enabled, + fillsurface, + *ibuf; char h_label[32], v_label[16], @@ -186,7 +194,8 @@ bool printEnabled, cursorEnabled, - dashBoardEnabled; + dashBoardEnabled, + Marker1Enabled; struct spectrum_markersblock *spectrum_color; diff -Nru edfbrowser-1.30/signals_dialog.cpp edfbrowser-1.38/signals_dialog.cpp --- edfbrowser-1.30/signals_dialog.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/signals_dialog.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -92,11 +92,11 @@ DisplayButton = new QPushButton(SignalsDialog); DisplayButton->setGeometry(QRect(150, 430, 160, 25)); - DisplayButton->setText("&Add signals"); + DisplayButton->setText("&Add signal(s)"); DisplayCompButton = new QPushButton(SignalsDialog); DisplayCompButton->setGeometry(QRect(430, 430, 160, 25)); - DisplayCompButton->setText("&Display Combination"); + DisplayCompButton->setText("&Make derivation"); AddButton = new QPushButton(SignalsDialog); AddButton->setGeometry(QRect(320, 225, 100, 25)); @@ -178,7 +178,8 @@ newsignalcomp = (struct signalcompblock *)calloc(1, sizeof(struct signalcompblock)); if(newsignalcomp==NULL) { - UI_Messagewindow popuperrormessage("Error", "Internal error: Memory allocation error:\n\"new signal composition\""); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Internal error: Memory allocation error:\n\"new signal composition\""); + messagewindow.exec(); SignalsDialog->close(); return; } @@ -199,6 +200,8 @@ { if(!strncmp(newsignalcomp->edfhdr->edfparam[j].label, str + 5, 16)) { + if(j != compositionlist->item(i)->data(Qt::UserRole).toInt()) continue; + newsignalcomp->edfsignal[i] = j; newsignalcomp->factor[i] = str[23] - 48; if(str[3]=='-') @@ -279,7 +282,8 @@ newsignalcomp = (struct signalcompblock *)calloc(1, sizeof(struct signalcompblock)); if(newsignalcomp==NULL) { - UI_Messagewindow popuperrormessage("Error", "Internal error: Memory allocation error:\n\"new signal composition\""); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Internal error: Memory allocation error:\n\"new signal composition\""); + messagewindow.exec(); SignalsDialog->close(); return; } @@ -292,7 +296,7 @@ newsignalcomp->hasruler = 0; item = selectedlist.at(i); - s = signallist->row(item); + s = item->data(Qt::UserRole).toInt(); newsignalcomp->edfsignal[0] = s; newsignalcomp->factor[0] = 1; newsignalcomp->sensitivity[0] = newsignalcomp->edfhdr->edfparam[s].bitvalue / ((double)newsignalcomp->voltpercm * mainwindow->pixelsizefactor); @@ -377,19 +381,20 @@ for(i=0; irow(item); + s = item->data(Qt::UserRole).toInt(); 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" + QMessageBox messagewindow(QMessageBox::Warning, "Warning", + "It is only possible to make combinations/derivations with signals which:\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)"); + messagewindow.exec(); continue; } @@ -403,12 +408,13 @@ { 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" + QMessageBox messagewindow(QMessageBox::Warning, "Warning", + "It is only possible to make combinations/derivations with signals which:\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)"); + messagewindow.exec(); continue; } @@ -422,12 +428,13 @@ { if(bitvalue!=mainwindow->edfheaderlist[row]->edfparam[s].bitvalue) { - UI_Messagewindow popup_error("Error", - "It is only possible to make combinations with signals who:\n" + QMessageBox messagewindow(QMessageBox::Warning, "Warning", + "It is only possible to make combinations/derivations with signals which:\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)"); + messagewindow.exec(); continue; } @@ -448,8 +455,11 @@ { if(str[3]=='+') { - duplicate = 1; - break; + if(s == item->data(Qt::UserRole).toInt()) + { + duplicate = 1; + break; + } } } } @@ -467,6 +477,7 @@ 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->setData(Qt::UserRole, QVariant(s)); item->setText(str); compositionlist->addItem(item); } @@ -500,19 +511,20 @@ for(i=0; irow(item); + s = item->data(Qt::UserRole).toInt(); 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" + QMessageBox messagewindow(QMessageBox::Warning, "Warning", + "It is only possible to make combinations/derivations with signals which:\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)"); + messagewindow.exec(); continue; } @@ -526,12 +538,13 @@ { 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" + QMessageBox messagewindow(QMessageBox::Warning, "Warning", + "It is only possible to make combinations/derivations with signals which:\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)"); + messagewindow.exec(); continue; } @@ -545,12 +558,13 @@ { if(bitvalue!=mainwindow->edfheaderlist[row]->edfparam[s].bitvalue) { - UI_Messagewindow popup_error("Error", - "It is only possible to make combinations with signals who:\n" + QMessageBox messagewindow(QMessageBox::Warning, "Warning", + "It is only possible to make combinations/derivations with signals which:\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)"); + messagewindow.exec(); continue; } @@ -590,6 +604,7 @@ 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->setData(Qt::UserRole, QVariant(s)); item->setText(str); compositionlist->addItem(item); } @@ -711,6 +726,7 @@ strcat(str, " Hz"); item = new QListWidgetItem; item->setText(str); + item->setData(Qt::UserRole, QVariant(i)); signallist->addItem(item); } @@ -743,14 +759,14 @@ "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" + "\nWhen you want to make a combination (derivation) 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" + "- Click on the \"Make derivation\" button.\n" "- The result of \"P3\" minus \"C3\" will appear on the screen."); } diff -Nru edfbrowser-1.30/signals_dialog.h edfbrowser-1.38/signals_dialog.h --- edfbrowser-1.30/signals_dialog.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/signals_dialog.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -46,6 +46,8 @@ #include #include #include +#include +#include #include #include diff -Nru edfbrowser-1.30/special_button.cpp edfbrowser-1.38/special_button.cpp --- edfbrowser-1.30/special_button.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/special_button.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2009, 2010 Teunis van Beelen +* Copyright (C) 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/special_button.h edfbrowser-1.38/special_button.h --- edfbrowser-1.30/special_button.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/special_button.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2009, 2010 Teunis van Beelen +* Copyright (C) 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/spectrumanalyzer.cpp edfbrowser-1.38/spectrumanalyzer.cpp --- edfbrowser-1.30/spectrumanalyzer.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/spectrumanalyzer.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -121,8 +121,6 @@ curve1->setBackgroundColor(Qt::black); curve1->setRasterColor(Qt::gray); curve1->setTraceWidth(0); - curve1->setH_RasterSize(10); - curve1->setV_RasterSize(10); curve1->setH_label("Hz"); curve1->setLowerLabel("Frequency"); if(sqrt_powerspectrum) @@ -258,7 +256,8 @@ if(outputfile == NULL) { snprintf(str, 1024, "Can not open file %s for writing.", path); - UI_Messagewindow popuperror("Error", str); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); return; } @@ -347,26 +346,26 @@ max_freq = ((double)samplefreq / 2.0) * stopstep / steps; precision = 0; - if(max_freq < 1000.0) + if(max_freq < 10.0) { precision = 1; } - if(max_freq < 100.0) + if(max_freq < 1.0) { precision = 2; } - if(max_freq < 10.0) + if(max_freq < 0.1) { precision = 3; } - if(max_freq < 1.0) + if(max_freq < 0.01) { precision = 4; } start_freq = ((double)samplefreq / 2.0) * startstep / steps; - curve1->setH_RulerValues(start_freq, max_freq, precision); + curve1->setH_RulerValues(start_freq, max_freq); centerLabel->setText(QString::number(start_freq + ((max_freq - start_freq) / 2.0), 'f', precision).append(" Hz").prepend("Center ")); @@ -377,7 +376,6 @@ void UI_FreqSpectrumWindow::update_curve() { int i, j, k, - dig_value=0, temp=0, dftblocksize, dftblocks, @@ -388,6 +386,8 @@ char str[512]; + double dig_value=0.0; + union { unsigned int one; signed int one_signed; @@ -444,8 +444,9 @@ buf1 = (double *)malloc(sizeof(double) * signalcomp->samples_on_screen); if(buf1 == NULL) { - UI_Messagewindow popupmessage("Error", "The system was not able to provide enough resources (memory) to perform the requested action.\n" - "Decrease the displaytime and try again."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.\n" + "Decrease the timescale and try again."); + messagewindow.exec(); return; } @@ -455,7 +456,7 @@ { if(s>signalcomp->sample_stop) break; - dig_value = 0; + dig_value = 0.0; s2 = s + signalcomp->sample_timeoffset - signalcomp->sample_start; for(j=0; jnum_of_signals; j++) @@ -510,6 +511,16 @@ dig_value = first_order_filter(dig_value, signalcomp->filter[k]); } + for(k=0; kravg_filter_cnt; k++) + { + if(s==signalcomp->sample_start) + { + ravg_filter_restore_buf(signalcomp->ravg_filter[k]); + } + + dig_value = run_ravg_filter(dig_value, signalcomp->ravg_filter[k]); + } + for(k=0; kfidfilter_cnt; k++) { if(s==signalcomp->sample_start) @@ -520,6 +531,16 @@ dig_value = signalcomp->fidfuncp[k](signalcomp->fidbuf[k], dig_value); } + if(signalcomp->ecg_filter != NULL) + { + if(s==signalcomp->sample_start) + { + ecg_filter_restore_buf(signalcomp->ecg_filter); + } + + dig_value = run_ecg_filter(dig_value, signalcomp->ecg_filter); + } + if(s>=signalcomp->sample_start) { buf1[samples++] = dig_value * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue; @@ -571,8 +592,8 @@ buf2 = (double *)calloc(1, sizeof(double) * fft_outputbufsize); if(buf2 == NULL) { - UI_Messagewindow popupmessage("Error", "The system was not able to provide enough resources (memory) to perform the requested action.\n" - "Decrease the displaytime and try again."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); + messagewindow.exec(); free(buf1); buf1 = NULL; return; @@ -585,8 +606,8 @@ buf3 = (double *)malloc(sizeof(double) * fft_outputbufsize); if(buf3 == NULL) { - UI_Messagewindow popupmessage("Error", "The system was not able to provide enough resources (memory) to perform the requested action.\n" - "Decrease the displaytime and try again."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); + messagewindow.exec(); free(buf1); free(buf2); buf1 = NULL; @@ -615,8 +636,8 @@ kiss_fftbuf = (kiss_fft_cpx *)malloc((fft_outputbufsize + 1) * sizeof(kiss_fft_cpx)); if(kiss_fftbuf == NULL) { - UI_Messagewindow popupmessage("Error", "The system was not able to provide enough resources (memory) to perform the requested action.\n" - "Decrease the displaytime and try again."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); + messagewindow.exec(); free(buf1); free(buf2); free(buf3); @@ -657,7 +678,14 @@ } } - buf2[0] /= 2.0; // DC! + if(signalcomp->ecg_filter == NULL) + { + buf2[0] /= 2.0; // DC! + } + else + { + buf2[0] = 0.0; // Remove DC because heart rate is always a positive value + } free(cfg); diff -Nru edfbrowser-1.30/spectrumanalyzer.h edfbrowser-1.38/spectrumanalyzer.h --- edfbrowser-1.30/spectrumanalyzer.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/spectrumanalyzer.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -58,6 +59,10 @@ #include "fourier.h" #include "popup_messagewindow.h" #include "utils.h" +#include "filter.h" +#include "ravg_filter.h" + +#include "fidlib/fidlib.h" #include "kiss_fft/kiss_fftr.h" diff -Nru edfbrowser-1.30/spectrum_dock.cpp edfbrowser-1.38/spectrum_dock.cpp --- edfbrowser-1.30/spectrum_dock.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/spectrum_dock.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -71,8 +71,6 @@ curve1->setBackgroundColor(Qt::black); curve1->setRasterColor(Qt::gray); curve1->setTraceWidth(0); - curve1->setH_RasterSize(10); - curve1->setV_RasterSize(5); curve1->setH_label("Hz"); curve1->setLowerLabel("Frequency"); if(sqrt_powerspectrum) @@ -235,7 +233,8 @@ if(outputfile == NULL) { snprintf(str, 1024, "Can not open file %s for writing.", path); - UI_Messagewindow popuperror("Error", str); + QMessageBox messagewindow(QMessageBox::Critical, "Error", str); + messagewindow.exec(); return; } @@ -337,26 +336,26 @@ max_freq = ((double)samplefreq / 2.0) * stopstep / steps; precision = 0; - if(max_freq < 1000.0) + if(max_freq < 10.0) { precision = 1; } - if(max_freq < 100.0) + if(max_freq < 1.0) { precision = 2; } - if(max_freq < 10.0) + if(max_freq < 0.1) { precision = 3; } - if(max_freq < 1.0) + if(max_freq < 0.01) { precision = 4; } start_freq = ((double)samplefreq / 2.0) * startstep / steps; - curve1->setH_RulerValues(start_freq, max_freq, precision); + curve1->setH_RulerValues(start_freq, max_freq); centerLabel->setText(QString::number(start_freq + ((max_freq - start_freq) / 2.0), 'f', precision).append(" Hz").prepend("Center ")); @@ -449,7 +448,6 @@ void UI_SpectrumDockWindow::update_curve() { int i, j, k, n, - dig_value=0, temp=0, dftblocksize, dftblocks, @@ -460,6 +458,7 @@ char str[512]; + double dig_value=0.0; union { unsigned int one; @@ -525,8 +524,9 @@ buf1 = (double *)malloc(sizeof(double) * signalcomp->samples_on_screen); if(buf1 == NULL) { - UI_Messagewindow popupmessage("Error", "The system was not able to provide enough resources (memory) to perform the requested action.\n" - "Decrease the displaytime and try again."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.\n" + "Decrease the timescale and try again."); + messagewindow.exec(); return; } @@ -536,7 +536,7 @@ { if(s>signalcomp->sample_stop) break; - dig_value = 0; + dig_value = 0.0; s2 = s + signalcomp->sample_timeoffset - signalcomp->sample_start; for(j=0; jnum_of_signals; j++) @@ -591,6 +591,16 @@ dig_value = first_order_filter(dig_value, signalcomp->filter[k]); } + for(k=0; kravg_filter_cnt; k++) + { + if(s==signalcomp->sample_start) + { + ravg_filter_restore_buf(signalcomp->ravg_filter[k]); + } + + dig_value = run_ravg_filter(dig_value, signalcomp->ravg_filter[k]); + } + for(k=0; kfidfilter_cnt; k++) { if(s==signalcomp->sample_start) @@ -601,6 +611,16 @@ dig_value = signalcomp->fidfuncp[k](signalcomp->fidbuf[k], dig_value); } + if(signalcomp->ecg_filter != NULL) + { + if(s==signalcomp->sample_start) + { + ecg_filter_restore_buf(signalcomp->ecg_filter); + } + + dig_value = run_ecg_filter(dig_value, signalcomp->ecg_filter); + } + if(s>=signalcomp->sample_start) { buf1[samples++] = dig_value * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue; @@ -652,8 +672,8 @@ buf2 = (double *)calloc(1, sizeof(double) * fft_outputbufsize); if(buf2 == NULL) { - UI_Messagewindow popupmessage("Error", "The system was not able to provide enough resources (memory) to perform the requested action.\n" - "Decrease the displaytime and try again."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); + messagewindow.exec(); free(buf1); buf1 = NULL; return; @@ -666,8 +686,8 @@ buf3 = (double *)malloc(sizeof(double) * fft_outputbufsize); if(buf3 == NULL) { - UI_Messagewindow popupmessage("Error", "The system was not able to provide enough resources (memory) to perform the requested action.\n" - "Decrease the displaytime and try again."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); + messagewindow.exec(); free(buf1); free(buf2); buf1 = NULL; @@ -685,8 +705,8 @@ kiss_fftbuf = (kiss_fft_cpx *)malloc((fft_outputbufsize + 1) * sizeof(kiss_fft_cpx)); if(kiss_fftbuf == NULL) { - UI_Messagewindow popupmessage("Error", "The system was not able to provide enough resources (memory) to perform the requested action.\n" - "Decrease the displaytime and try again."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); + messagewindow.exec(); free(buf1); free(buf2); free(buf3); @@ -727,7 +747,15 @@ } } - buf2[0] /= 2.0; // DC! + if(signalcomp->ecg_filter == NULL) + { + buf2[0] /= 2.0; // DC! + } + else + { + buf2[0] = 0.0; // Remove DC because heart rate is always a positive value + } + free(cfg); diff -Nru edfbrowser-1.30/spectrum_dock.h edfbrowser-1.38/spectrum_dock.h --- edfbrowser-1.30/spectrum_dock.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/spectrum_dock.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2010 Teunis van Beelen +* Copyright (C) 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -59,6 +60,10 @@ #include "fourier.h" #include "popup_messagewindow.h" #include "utils.h" +#include "filter.h" +#include "ravg_filter.h" + +#include "fidlib/fidlib.h" #include "kiss_fft/kiss_fftr.h" diff -Nru edfbrowser-1.30/statistics_dialog.cpp edfbrowser-1.38/statistics_dialog.cpp --- edfbrowser-1.30/statistics_dialog.cpp 1970-01-01 00:00:00.000000000 +0000 +++ edfbrowser-1.38/statistics_dialog.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -0,0 +1,363 @@ +/* +*************************************************************************** +* +* Author: Teunis van Beelen +* +* Copyright (C) 2011 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 "statistics_dialog.h" + + + +UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp) +{ + int i, + tmp, + NN50, + pNN50; + + char stat_str[2048]; + + double d_tmp, + average_bpm, + average_rr, + sdnn_bpm, + sdnn_rr, + *buf_bpm, + rmssd_rr, + *beat_interval_list; + + StatDialog = new QDialog; + StatDialog->setWindowTitle("Statistics"); + StatDialog->setModal(TRUE); + StatDialog->setAttribute(Qt::WA_DeleteOnClose, TRUE); + + if(signalcomp->ecg_filter != NULL) + { + StatDialog->setMinimumSize(600, 400); + + startSlider = new QSlider; + startSlider->setOrientation(Qt::Horizontal); + startSlider->setMinimum(0); + startSlider->setMaximum(295); + startSlider->setValue(0); + + stopSlider = new QSlider; + stopSlider->setOrientation(Qt::Horizontal); + stopSlider->setMinimum(5); + stopSlider->setMaximum(300); + stopSlider->setValue(300); + + curve1 = new SignalCurve(StatDialog); + curve1->setSignalColor(Qt::darkGreen); + curve1->setBackgroundColor(Qt::black); + curve1->setRasterColor(Qt::gray); + curve1->setTraceWidth(0); + curve1->setH_label(signalcomp->physdimension); + curve1->setLowerLabel("HR (beats/min)"); + curve1->setDashBoardEnabled(FALSE); + curve1->setUpperLabel1("Distribution"); + curve1->setFillSurfaceEnabled(TRUE); + + vlayout2_1 = new QVBoxLayout; + vlayout2_1->setSpacing(20); + vlayout2_1->addWidget(curve1); + vlayout2_1->addWidget(startSlider); + vlayout2_1->addWidget(stopSlider); + } + else + { + StatDialog->setMinimumSize(300, 400); + StatDialog->setMaximumSize(300, 400); + } + + Label1 = new QLabel(StatDialog); + Label1->setAlignment(Qt::AlignLeft | Qt::AlignTop); + + pushButton1 = new QPushButton(StatDialog); + pushButton1->setMinimumSize(100, 25); + pushButton1->setText("&Close"); + + hlayout1_1_1 = new QHBoxLayout; + hlayout1_1_1->addWidget(pushButton1); + hlayout1_1_1->addStretch(100); + + vlayout1_1 = new QVBoxLayout; + vlayout1_1->setSpacing(20); + vlayout1_1->addWidget(Label1); + vlayout1_1->addStretch(100); + vlayout1_1->addLayout(hlayout1_1_1); + + hlayout1 = new QHBoxLayout; + hlayout1->addLayout(vlayout1_1, 1); + if(signalcomp->ecg_filter != NULL) + { + hlayout1->addLayout(vlayout2_1, 100); + } + + StatDialog->setLayout(hlayout1); + + QObject::connect(pushButton1, SIGNAL(clicked()), StatDialog, SLOT(close())); + + for(i=0; i<300; i++) + { + bpm_distribution[i] = 0; + } + + if(signalcomp->ecg_filter == NULL) + { + if(signalcomp->stat_cnt < 1) + { + sprintf(stat_str, "%s\n\nSamples: 0\n\nSum: 0 %s\n\nMean: 0 %s\n\nRMS: 0 %s\n\nMRS: 0 %s", + signalcomp->signallabel, + signalcomp->physdimension, + signalcomp->physdimension, + signalcomp->physdimension, + signalcomp->physdimension); + } + else + { + sprintf(stat_str, "%s\n\nSamples: %i\n\nSum: %f %s\n\nMean: %f %s\n\nRMS: %f %s\n\nMRS: %f %s", + signalcomp->signallabel, + signalcomp->stat_cnt, + signalcomp->stat_sum * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue, + signalcomp->physdimension, + (signalcomp->stat_sum * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue) / signalcomp->stat_cnt, + signalcomp->physdimension, + sqrt(signalcomp->stat_sum_sqr / signalcomp->stat_cnt) * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue, + signalcomp->physdimension, + (signalcomp->stat_sum_rectified / signalcomp->stat_cnt) * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue, + signalcomp->physdimension); + } + } + else + { + beat_cnt = ecg_filter_get_beat_cnt(signalcomp->ecg_filter); + + beat_interval_list = ecg_filter_get_interval_beatlist(signalcomp->ecg_filter); + + if(beat_cnt < 3) + { + sprintf(stat_str, "Not enough beats."); + } + else + { + average_bpm = 0.0; + average_rr = 0.0; + sdnn_bpm = 0.0; + sdnn_rr = 0.0; + rmssd_rr = 0.0; + NN50 = 0; + + buf_bpm = (double *)malloc(sizeof(double) * beat_cnt); + if(buf_bpm == NULL) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); + messagewindow.exec(); + return; + } + + for(i=0; i 0.05 ) || ((beat_interval_list[i + 1] - beat_interval_list[i]) > 0.05 )) + { + NN50++; + } + } + } + + average_bpm /= beat_cnt; + average_rr /= beat_cnt; + rmssd_rr /= beat_cnt; + rmssd_rr = sqrt(rmssd_rr); + + pNN50 = (NN50 * 100) / (beat_cnt - 1); + + for(i=0; i 0) && (tmp < 301)) + { + bpm_distribution[tmp-1]++; + } + } + + max_val = 1; + + for(i=0; i<300; i++) + { + if(bpm_distribution[i] > max_val) + { + max_val = bpm_distribution[i]; + } + } + + for(i=0; i<300; i++) + { + if(bpm_distribution[i] > (max_val / 70)) + { + start_ruler = i; + + break; + } + } + + for(i=299; i>=0; i--) + { + if(bpm_distribution[i] > (max_val / 70)) + { + end_ruler = i + 1; + + if(end_ruler > 300) + { + end_ruler = 300; + } + + break; + } + } + + if(start_ruler >= end_ruler) + { + start_ruler = 0; + + end_ruler = 300; + } + + startSlider->setValue(start_ruler); + stopSlider->setValue(end_ruler); + + curve1->setH_RulerValues(start_ruler + 1, end_ruler + 1); + + curve1->drawCurve(bpm_distribution + start_ruler, end_ruler - start_ruler, (int)(max_val * 1.1) + 1, 0.0); + + QObject::connect(startSlider, SIGNAL(valueChanged(int)), this, SLOT(startSliderMoved(int))); + QObject::connect(stopSlider, SIGNAL(valueChanged(int)), this, SLOT(stopSliderMoved(int))); + } + } + + Label1->setText(stat_str); + + StatDialog->exec(); +} + + +void UI_StatisticWindow::startSliderMoved(int) +{ + startSlider->blockSignals(TRUE); + stopSlider->blockSignals(TRUE); + + start_ruler = startSlider->value(); + end_ruler = stopSlider->value(); + + if(end_ruler < (start_ruler + 5)) + { + end_ruler = start_ruler + 5; + + stopSlider->setValue(end_ruler); + } + + curve1->setH_RulerValues(start_ruler + 1, end_ruler + 1); + + curve1->drawCurve(bpm_distribution + start_ruler, end_ruler - start_ruler, (int)(max_val * 1.1) + 1, 0.0); + + startSlider->blockSignals(FALSE); + stopSlider->blockSignals(FALSE); +} + + +void UI_StatisticWindow::stopSliderMoved(int) +{ + startSlider->blockSignals(TRUE); + stopSlider->blockSignals(TRUE); + + start_ruler = startSlider->value(); + end_ruler = stopSlider->value(); + + if(start_ruler > (end_ruler - 5)) + { + start_ruler = end_ruler - 5; + + startSlider->setValue(start_ruler); + } + + curve1->setH_RulerValues(start_ruler + 1, end_ruler + 1); + + curve1->drawCurve(bpm_distribution + start_ruler, end_ruler - start_ruler, (int)(max_val * 1.1) + 1, 0.0); + + startSlider->blockSignals(FALSE); + stopSlider->blockSignals(FALSE); +} + + + + diff -Nru edfbrowser-1.30/statistics_dialog.h edfbrowser-1.38/statistics_dialog.h --- edfbrowser-1.30/statistics_dialog.h 1970-01-01 00:00:00.000000000 +0000 +++ edfbrowser-1.38/statistics_dialog.h 2011-08-23 20:01:14.000000000 +0000 @@ -0,0 +1,108 @@ +/* +*************************************************************************** +* +* Author: Teunis van Beelen +* +* Copyright (C) 2011 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 +* +*************************************************************************** +*/ + + + + +#ifndef STATISTICS_DIALOGFORM1_H +#define STATISTICS_DIALOGFORM1_H + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "global.h" +#include "ecg_filter.h" +#include "signalcurve.h" + + + + +class UI_StatisticWindow : public QObject +{ + Q_OBJECT + +public: + +UI_StatisticWindow(struct signalcompblock *); + +private: + +QDialog *StatDialog; + +QHBoxLayout *hlayout1, + *hlayout1_1_1; + +QVBoxLayout *vlayout1_1, + *vlayout2_1; + +QSlider *startSlider, + *stopSlider; + +QLabel *Label1, + *startLabel, + *stopLabel; + +QPushButton *pushButton1; + +SignalCurve *curve1; + +int beat_cnt, + bpm_distribution[300], + max_val, + start_ruler, + end_ruler; + + +private slots: + +void startSliderMoved(int); +void stopSliderMoved(int); + +}; + + + +#endif // STATISTICS_DIALOGFORM1_H + + diff -Nru edfbrowser-1.30/utc_date_time.c edfbrowser-1.38/utc_date_time.c --- edfbrowser-1.30/utc_date_time.c 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/utc_date_time.c 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/utc_date_time.h edfbrowser-1.38/utc_date_time.h --- edfbrowser-1.30/utc_date_time.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/utc_date_time.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/utils.c edfbrowser-1.38/utils.c --- edfbrowser-1.30/utils.c 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/utils.c 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2009, 2010 Teunis van Beelen +* Copyright (C) 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -114,7 +114,7 @@ /* last character of destination is not a slash! */ int get_directory_from_path(char *dest, const char *src, int size) { - int i, flag, len; + int i, len; if(size<1) { @@ -137,14 +137,10 @@ return(0); } - flag = 0; - for(i=len-1; i>=0; i--) { if((src[i]=='/') || (src[i]=='\\')) { - flag = 1; - break; } } @@ -656,7 +652,7 @@ str[len] = 0; - return(atoi(str)); + return(atoi_nonlocalized(str)); } @@ -942,11 +938,14 @@ var = nr - q; - if(q < 0) + if(nr < 0.0) { str[j++] = '-'; - q = -q; + if(q < 0) + { + q = -q; + } } for(i=10; i; i--) @@ -1013,6 +1012,8 @@ } else { + j++; + break; } } @@ -1023,23 +1024,33 @@ double atof_nonlocalized(const char *str) { - int i, dot_pos=-1, decimals=0; + int i=0, dot_pos=-1, decimals=0, sign=1; double value, value2=0.0; - value = atoi(str); + value = atoi_nonlocalized(str); - for(i=0; ; i++) + while(str[i] == ' ') { - if(str[i] == 0) + i++; + } + + if((str[i] == '+') || (str[i] == '-')) + { + if(str[i] == '-') { - break; + sign = -1; } - if((str[i] == ' ') &&(dot_pos < 0)) + i++; + } + + for(; ; i++) + { + if(str[i] == 0) { - continue; + break; } if(((str[i] < '0') || (str[i] > '9')) && (str[i] != '.')) @@ -1070,7 +1081,7 @@ if(decimals) { - value2 = atoi(str + dot_pos + 1); + value2 = atoi_nonlocalized(str + dot_pos + 1) * sign; i = 1; @@ -1086,6 +1097,46 @@ } +int atoi_nonlocalized(const char *str) +{ + int i=0, value=0, sign=1; + + while(str[i] == ' ') + { + i++; + } + + if((str[i] == '+') || (str[i] == '-')) + { + if(str[i] == '-') + { + sign = -1; + } + + i++; + } + + for( ; ; i++) + { + if(str[i] == 0) + { + break; + } + + if((str[i] < '0') || (str[i] > '9')) + { + break; + } + + value *= 10; + + value += (str[i] - '0'); + } + + return(value * sign); +} + + long long atoll_x(const char *str, int dimension) { int i, @@ -1186,4 +1237,3 @@ - diff -Nru edfbrowser-1.30/utils.h edfbrowser-1.38/utils.h --- edfbrowser-1.30/utils.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/utils.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2009, 2010 Teunis van Beelen +* Copyright (C) 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -59,6 +59,7 @@ void latin1_to_utf8(char *, int); void utf8_to_latin1(char *); int antoi(const char *, int); +int atoi_nonlocalized(const char *); double atof_nonlocalized(const char *); int sprint_number_nonlocalized(char *, double); long long atoll_x(const char *, int); diff -Nru edfbrowser-1.30/version.txt edfbrowser-1.38/version.txt --- edfbrowser-1.30/version.txt 2010-11-24 08:57:45.000000000 +0000 +++ edfbrowser-1.38/version.txt 2011-08-23 20:01:14.000000000 +0000 @@ -1,4 +1,126 @@ + + version 1.38 August 24, 2011 + ------------ + + - Fixed lots of regression bugs introduced with version 1.37. + + - Fixed a bug related to annotationmarkers and EDFplus feature to use subsecondprecision in the starttime + of the file. + + - Fixed a bug in the ascii to edf converter that caused to produce an invalid edf file when + all samples in have value "0.0". + + + version 1.37 August 17, 2011 + ------------ + + - Removed the limitation that no more annotations can be saved than the amount of datarecords. + EDFbrowser could only write one annotation per datarecord. From now on, if there are more + annotations than datarecords, the size (smpls/record) of the annotationchannel will increase + automatically in order to fit multiple annotations as needed. + + + version 1.36 June 16, 2011 + ------------ + + - Solved a bug when importing events/annotations from an ascii-file. + + + version 1.35 June 16, 2011 + ------------ + + - Changed the selectionbehaviour of the signallist in Signals -> Organize. + Now you can select multiple signals when organizing the signals on the screen. + + - Solved a bug that caused showing the wrong signal when there are duplicate signalnames in a file. + + - Solved a bug that caused a cryptic error message "avg_cnt is ..." when averaging a signal using + a trigger/annotation which was not inside the selected timewindow. + + - Now it is possible to start/open multiple averagingwindows applied on the same signal. + + - Added the possibility to invert te waveform of the averagingwindow. + + - Solved a bug that caused an errormessage when trying to open a large file (>2.1GB) on a Mac. + + - Removed some bugs in the heartrate detection code. + + - Now you can choose between different kinds of data (R onset or RR-interval or both) when exporting + the heartrate data. + + + version 1.34 May 9, 2011 + ------------ + + - Added ECG heartrate detection (it calculates beats per minute from the ECG-waveform). + + - Added the possibility to import annotations, also from discontinues EDF+D or BDF+D files. + + - Added mousewheel scrolling. + + - Added the possibility to save the data from averaging as EDF/BDF. + + - Added the possibility to (re-)organize (re-order and/or invert) the signals on the screen in an easy way + via Menu -> Signals -> Organize. + + - Modified the annotation editor, from now on annotations with an onsettime more than + 24 hours can be edited as well. + + - Solved a bug that prevented a messagebox to appear when trying to open + a BDF+D file. + + - Changed the way the onsettime of the annotations are presented. + + + version 1.33 March 22, 2011 + ------------ + + - Added the possibility to import/extract triggers/events from/recorded on a dc-coupled channel. + + - Added the possibility to perform "averaging" (evoked potentials or other triggers) + using (imported) annotations, events or other kind of triggers. + + - Added a WAV to EDF converter. + + - Modified the Nihon Kohden to EDF converter so that it will use the electrodenames defined + by the user in the aquisition software. + + - Fixed a bug that caused writing a wrong value in the datarecorddurationfield of the header + when saving annotations and when the number in the datarecorddurationfield of the sourcefile + has more than six digits after the dot. + + - Fixed a bug related to a rarely used EDFplus feature to use subsecondprecision in the starttime + of the file. Some tools ignored this feature, this has been fixed. + + - Updated Qt to 4.7.2 + + + version 1.32 December 16, 2010 + ------------ + + - Fixed a bug that prevented from updating the screen when in streaming mode + and after all signals were removed. + + - Fixed a bug in EDFlib. + + + + version 1.31 December 8, 2010 + ------------ + + - Added a streaming mode. The stream must be a "growing" file. + This mode can be used when you have an aquisitionprogram running that writes EDF or BDF. + While the aquisitionprogram writes the data to the file, you can use EDFbrowser to watch + (follow) the actual data. EDFbrowser will regularly check the actual filesize and show the + last part of the file i.e. the most actual/recent data. + + - Added a "moving average" filtermodel (high- and lowpass). + + - The "View montage" dialogs got a facelift. + + + version 1.30 November 24, 2010 ------------ @@ -14,6 +136,7 @@ - Updated Qt to version 4.7.1. + version 1.29 November 9, 2010 ------------ diff -Nru edfbrowser-1.30/viewcurve.cpp edfbrowser-1.38/viewcurve.cpp --- edfbrowser-1.30/viewcurve.cpp 2010-11-24 08:32:59.000000000 +0000 +++ edfbrowser-1.38/viewcurve.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -52,6 +52,7 @@ sidemenu_active = 0; draw_zoom_rectangle = 0; printing = 0; + pressed_on_label = 0; original_sensitivity = (double *)calloc(1, sizeof(double[MAXSIGNALS])); @@ -122,6 +123,44 @@ } +void ViewCurve::wheelEvent(QWheelEvent *event) +{ + int i; + + if(mainwindow->mousewheelsens < 1) return; + + if(mainwindow->files_open == 0) return; + + if((mainwindow->viewtime_sync==VIEWTIME_SYNCED_OFFSET)||(mainwindow->viewtime_sync==VIEWTIME_SYNCED_ABSOLUT)||(mainwindow->viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) + { + for(i=0; ifiles_open; i++) + { + if(event->delta() > 0) + { + mainwindow->edfheaderlist[i]->viewtime -= (mainwindow->pagetime / mainwindow->mousewheelsens); + } + else + { + mainwindow->edfheaderlist[i]->viewtime += (mainwindow->pagetime / mainwindow->mousewheelsens); + } + } + } + + if(mainwindow->viewtime_sync==VIEWTIME_UNSYNCED) + { + if(event->delta() > 0) + { + mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime -= (mainwindow->pagetime / mainwindow->mousewheelsens); + } + else + { + mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime += (mainwindow->pagetime / mainwindow->mousewheelsens); + } + } + + mainwindow->setup_viewbuf(); +} + void ViewCurve::mousePressEvent(QMouseEvent *event) { @@ -130,7 +169,6 @@ signalcomps, m_x, m_y, - pressed_on_label=0, h_size; struct signalcompblock **signalcomp; @@ -148,6 +186,8 @@ mouse_press_coordinate_x = m_x; mouse_press_coordinate_y = m_y; + pressed_on_label = 0; + h_size = (int)(4.0 / mainwindow->pixelsizefactor); setFocus(Qt::MouseFocusReason); @@ -251,7 +291,8 @@ original_screen_offset = signalcomp[i]->screen_offset; signalcomp[i]->hasoffsettracking = 1; signal_nr = i; - pressed_on_label = 1; + pressed_on_label = i + 1; + label_press_y_position = m_y; break; } @@ -450,14 +491,17 @@ if((m_y<(baseline-5))&&(m_y>(baseline-24))&&(m_x>3)&&(m_x<110)) { - use_move_events = 0; - setMouseTracking(FALSE); - update(); + if(pressed_on_label == (i + 1)) + { + use_move_events = 0; + setMouseTracking(FALSE); + update(); - signal_nr = i; - exec_sidemenu(i); + signal_nr = i; + exec_sidemenu(i); - break; + break; + } } } } @@ -475,6 +519,8 @@ } } } + + pressed_on_label = 0; } @@ -496,6 +542,14 @@ mouse_x = event->x(); mouse_y = event->y(); + if(pressed_on_label) + { + if((mouse_y > (label_press_y_position + 10)) || (mouse_y < (label_press_y_position - 10))) + { + pressed_on_label = 0; + } + } + if(crosshair_1_moving) { if(mouse_x<(w-100)) @@ -1421,7 +1475,7 @@ { if(annot->onset > mainwindow->edfheaderlist[i]->viewtime) { - if(annot->onset > (mainwindow->edfheaderlist[i]->viewtime + mainwindow->pagetime)) + if(annot->onset > mainwindow->edfheaderlist[i]->viewtime + mainwindow->pagetime) { break; } @@ -1432,11 +1486,22 @@ painter->drawLine(marker_x, 0, marker_x, h); - snprintf(string, 32, "%2i:%02i:%02i.%04i", - (int)((annot->onset / TIME_DIMENSION)/ 3600LL), - (int)(((annot->onset / TIME_DIMENSION) % 3600LL) / 60LL), - (int)((annot->onset / TIME_DIMENSION) % 60LL), - (int)(((annot->onset % TIME_DIMENSION) / 1000LL))); + if(annot->onset < 0LL) + { + snprintf(string, 32, "-%i:%02i:%02i.%04i", + (int)(((-(annot->onset)) / TIME_DIMENSION)/ 3600LL), + (int)((((-(annot->onset)) / TIME_DIMENSION) % 3600LL) / 60LL), + (int)(((-(annot->onset)) / TIME_DIMENSION) % 60LL), + (int)((((-(annot->onset)) % TIME_DIMENSION) / 1000LL))); + } + else + { + snprintf(string, 32, "%i:%02i:%02i.%04i", + (int)((annot->onset / TIME_DIMENSION)/ 3600LL), + (int)(((annot->onset / TIME_DIMENSION) % 3600LL) / 60LL), + (int)((annot->onset / TIME_DIMENSION) % 60LL), + (int)(((annot->onset % TIME_DIMENSION) / 1000LL))); + } remove_trailing_zeros(string); @@ -1525,7 +1590,7 @@ painter->drawLine((int)((double)crosshair_1_x_position * printsize_x_factor), 0, (int)((double)crosshair_1_x_position * printsize_x_factor), h); snprintf(string, 128, "%+f %s", crosshair_1_value, - signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].physdimension); + signalcomp[i]->physdimension); painter->drawText((int)(((double)crosshair_1_x_position + 5.0) * printsize_x_factor), (int)(((double)crosshair_1_y_position - 40.0) * printsize_y_factor), string); snprintf(string, 128, "%2i:%02i:%02i.%04i", (int)(((crosshair_1_time / TIME_DIMENSION)/ 3600LL) % 24LL), @@ -1543,7 +1608,7 @@ painter->drawLine(crosshair_1_x_position, 0, crosshair_1_x_position, h); snprintf(string, 128, "%+f %s", crosshair_1_value, - signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].physdimension); + signalcomp[i]->physdimension); painter->drawText(crosshair_1_x_position + 5, crosshair_1_y_position - 40, string); snprintf(string, 128, "%2i:%02i:%02i.%04i", (int)(((crosshair_1_time / TIME_DIMENSION)/ 3600LL) % 24LL), @@ -1573,7 +1638,7 @@ painter->drawLine((int)((double)crosshair_2_x_position * printsize_x_factor), 0, (int)((double)crosshair_2_x_position * printsize_x_factor), h); snprintf(string, 128, "%+f %s", crosshair_2_value, - signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].physdimension); + signalcomp[i]->physdimension); painter->drawText((int)(((double)crosshair_2_x_position + 5.0) * printsize_x_factor), (int)(((double)crosshair_2_y_position - 70.0) * printsize_y_factor), string); snprintf(string, 128, "%2i:%02i:%02i.%04i", (int)(((crosshair_2_time / TIME_DIMENSION)/ 3600LL) % 24LL), @@ -1583,7 +1648,7 @@ painter->drawText((int)(((double)crosshair_2_x_position + 5.0) * printsize_x_factor), (int)(((double)crosshair_2_y_position - 55.0) * printsize_y_factor), string); snprintf(string, 128, "delta %+f %s", crosshair_2_value - crosshair_1_value, - signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].physdimension); + signalcomp[i]->physdimension); painter->drawText((int)(((double)crosshair_2_x_position + 5.0) * printsize_x_factor), (int)(((double)crosshair_2_y_position - 40.0) * printsize_y_factor), string); l_time = crosshair_2_time - crosshair_1_time; if(l_time<0) l_time = -l_time; @@ -1603,7 +1668,7 @@ painter->drawLine(crosshair_2_x_position, 0, crosshair_2_x_position, h); snprintf(string, 128, "%+f %s", crosshair_2_value, - signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].physdimension); + signalcomp[i]->physdimension); painter->drawText(crosshair_2_x_position + 5, crosshair_2_y_position - 70, string); snprintf(string, 128, "%2i:%02i:%02i.%04i", (int)(((crosshair_2_time / TIME_DIMENSION)/ 3600LL) % 24LL), @@ -1619,7 +1684,7 @@ painter->drawText(crosshair_2_x_position + 5, crosshair_2_y_position - 55, string); snprintf(string, 128, "delta %+f %s", crosshair_2_value - crosshair_1_value, - signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].physdimension); + signalcomp[i]->physdimension); painter->drawText(crosshair_2_x_position + 5, crosshair_2_y_position - 40, string); l_time = crosshair_2_time - crosshair_1_time; if(l_time<0) l_time = -l_time; @@ -1712,9 +1777,7 @@ char *viewbuf; - long long elapsed_time, - s, - s2; + long long s, s2; double dig_value=0.0; @@ -1787,15 +1850,6 @@ } } - if(mainwindow->files_open&&mainwindow->signalcomps) - { - elapsed_time = mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime; - } - else - { - elapsed_time = 0; - } - if((viewbuf==NULL)||(screensamples==NULL)) { if(graphicBuf!=NULL) @@ -1805,6 +1859,8 @@ graphicBuf = NULL; } + update(); + return; } @@ -1822,7 +1878,8 @@ if(graphicBuf==NULL) { - UI_Messagewindow popuperror("Error", "The system was not able to provide enough resources (memory) to perform the requested action."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); + messagewindow.exec(); return; } @@ -1913,6 +1970,25 @@ dig_value = first_order_filter(dig_value, signalcomp[i]->filter[k]); } + for(k=0; kravg_filter_cnt; k++) + { + if(s==signalcomp[i]->sample_start) + { + if((mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime <= 0) && signalcomp[i]->ravg_filter_setup[k]) + { + reset_ravg_filter(dig_value, signalcomp[i]->ravg_filter[k]); + } + else + { + ravg_filter_restore_buf(signalcomp[i]->ravg_filter[k]); + } + + signalcomp[i]->ravg_filter_setup[k] = 0; + } + + dig_value = run_ravg_filter(dig_value, signalcomp[i]->ravg_filter[k]); + } + for(k=0; kfidfilter_cnt; k++) { if(s==signalcomp[i]->sample_start) @@ -1946,6 +2022,23 @@ dig_value = signalcomp[i]->fidfuncp[k](signalcomp[i]->fidbuf[k], dig_value); } + if(signalcomp[i]->ecg_filter != NULL) + { + if(s==signalcomp[i]->sample_start) + { + if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime <= 0LL) + { + reset_ecg_filter(signalcomp[i]->ecg_filter); + } + else + { + ecg_filter_restore_buf(signalcomp[i]->ecg_filter); + } + } + + dig_value = run_ecg_filter(dig_value, signalcomp[i]->ecg_filter); + } + if(printing) { value += (int)(dig_value * signalcomp[i]->sensitivity[0] * printsize_y_factor); @@ -2058,7 +2151,7 @@ crosshair_1_y_value = value; crosshair_1_value = dig_value * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue; crosshair_1_time = mainwindow->edfheaderlist[signalcomp[i]->filenum]->l_starttime + mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + signalcomp[i]->edfhdr->starttime_offset + (long long)(((double)mainwindow->pagetime / ((double)w / printsize_x_factor)) * (double)crosshair_1_x_position); - crosshair_1_time_relative = mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + signalcomp[i]->edfhdr->starttime_offset + (long long)(((double)mainwindow->pagetime / ((double)w / printsize_x_factor)) * (double)crosshair_1_x_position); + crosshair_1_time_relative = mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + (long long)(((double)mainwindow->pagetime / ((double)w / printsize_x_factor)) * (double)crosshair_1_x_position); } } else @@ -2068,7 +2161,7 @@ crosshair_1_y_value = value; crosshair_1_value = dig_value * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue; crosshair_1_time = mainwindow->edfheaderlist[signalcomp[i]->filenum]->l_starttime + mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + signalcomp[i]->edfhdr->starttime_offset + (long long)(((double)mainwindow->pagetime / (double)w) * (double)crosshair_1_x_position); - crosshair_1_time_relative = mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + signalcomp[i]->edfhdr->starttime_offset + (long long)(((double)mainwindow->pagetime / (double)w) * (double)crosshair_1_x_position); + crosshair_1_time_relative = mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + (long long)(((double)mainwindow->pagetime / (double)w) * (double)crosshair_1_x_position); } } } @@ -2082,7 +2175,7 @@ crosshair_2_y_value = value; crosshair_2_value = dig_value * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue; crosshair_2_time = mainwindow->edfheaderlist[signalcomp[i]->filenum]->l_starttime + mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + signalcomp[i]->edfhdr->starttime_offset + (long long)(((double)mainwindow->pagetime / ((double)w / printsize_x_factor)) * (double)crosshair_2_x_position); - crosshair_2_time_relative = mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + signalcomp[i]->edfhdr->starttime_offset + (long long)(((double)mainwindow->pagetime / ((double)w / printsize_x_factor)) * (double)crosshair_2_x_position); + crosshair_2_time_relative = mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + (long long)(((double)mainwindow->pagetime / ((double)w / printsize_x_factor)) * (double)crosshair_2_x_position); } } else @@ -2092,7 +2185,7 @@ crosshair_2_y_value = value; crosshair_2_value = dig_value * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue; crosshair_2_time = mainwindow->edfheaderlist[signalcomp[i]->filenum]->l_starttime + mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + signalcomp[i]->edfhdr->starttime_offset + (long long)(((double)mainwindow->pagetime / (double)w) * (double)crosshair_2_x_position); - crosshair_2_time_relative = mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + signalcomp[i]->edfhdr->starttime_offset + (long long)(((double)mainwindow->pagetime / (double)w) * (double)crosshair_2_x_position); + crosshair_2_time_relative = mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + (long long)(((double)mainwindow->pagetime / (double)w) * (double)crosshair_2_x_position); } } } @@ -2120,8 +2213,8 @@ sidemenu = new QDialog(this); - sidemenu->setMinimumSize(QSize(190, 360)); - sidemenu->setMaximumSize(QSize(190, 360)); + sidemenu->setMinimumSize(QSize(190, 410)); + sidemenu->setMaximumSize(QSize(190, 410)); sidemenu->setWindowTitle("Signal"); sidemenu->setModal(TRUE); sidemenu->setAttribute(Qt::WA_DeleteOnClose, TRUE); @@ -2144,7 +2237,7 @@ ScaleBox->setMaximum(1000000.0); ScaleBox->setMinimum(0.0000001); ScaleBox->setValue(mainwindow->signalcomp[signal_nr]->voltpercm); - strcpy(str, mainwindow->signalcomp[signal_nr]->edfhdr->edfparam[mainwindow->signalcomp[signal_nr]->edfsignal[0]].physdimension); + strcpy(str, mainwindow->signalcomp[signal_nr]->physdimension); for(i=1; i<4; i++) { if(str[i]==' ') break; @@ -2158,7 +2251,7 @@ ScaleBox2->setMaximum(1000000.0); ScaleBox2->setMinimum(-1000000.0); ScaleBox2->setValue(-mainwindow->signalcomp[signal_nr]->screen_offset * mainwindow->pixelsizefactor * mainwindow->signalcomp[signal_nr]->voltpercm); - ScaleBox2->setSuffix(mainwindow->signalcomp[signal_nr]->edfhdr->edfparam[mainwindow->signalcomp[signal_nr]->edfsignal[0]].physdimension); + ScaleBox2->setSuffix(mainwindow->signalcomp[signal_nr]->physdimension); sidemenuButton1 = new QPushButton(sidemenu); sidemenuButton1->setGeometry(QRect(45, 80, 100, 20)); @@ -2178,27 +2271,35 @@ sidemenuButton5 = new QPushButton(sidemenu); sidemenuButton5->setGeometry(QRect(45, 180, 100, 20)); - sidemenuButton5->setText("Spectrum"); + sidemenuButton5->setText("Invert"); sidemenuButton6 = new QPushButton(sidemenu); sidemenuButton6->setGeometry(QRect(45, 205, 100, 20)); - sidemenuButton6->setText("Remove filter"); + sidemenuButton6->setText("Spectrum"); sidemenuButton7 = new QPushButton(sidemenu); sidemenuButton7->setGeometry(QRect(45, 230, 100, 20)); - sidemenuButton7->setText("Remove signal"); + sidemenuButton7->setText("Remove filter"); sidemenuButton8 = new QPushButton(sidemenu); sidemenuButton8->setGeometry(QRect(45, 255, 100, 20)); - sidemenuButton8->setText("Adjust filter"); + sidemenuButton8->setText("Remove signal"); sidemenuButton9 = new QPushButton(sidemenu); sidemenuButton9->setGeometry(QRect(45, 280, 100, 20)); - sidemenuButton9->setText("Statistics"); + sidemenuButton9->setText("Adjust filter"); sidemenuButton10 = new QPushButton(sidemenu); sidemenuButton10->setGeometry(QRect(45, 305, 100, 20)); - sidemenuButton10->setText("Close"); + sidemenuButton10->setText("Statistics"); + + sidemenuButton11 = new QPushButton(sidemenu); + sidemenuButton11->setGeometry(QRect(45, 330, 100, 20)); + sidemenuButton11->setText("Heart Rate"); + + sidemenuButton12 = new QPushButton(sidemenu); + sidemenuButton12->setGeometry(QRect(45, 355, 100, 20)); + sidemenuButton12->setText("Close"); QObject::connect(ScaleBox, SIGNAL(valueChanged(double)), this, SLOT(ScaleBoxChanged(double))); QObject::connect(ScaleBox2, SIGNAL(valueChanged(double)), this, SLOT(ScaleBox2Changed(double))); @@ -2206,19 +2307,26 @@ QObject::connect(sidemenuButton2, SIGNAL(clicked()), this, SLOT(CrosshairButton())); QObject::connect(sidemenuButton3, SIGNAL(clicked()), this, SLOT(FittopaneButton())); QObject::connect(sidemenuButton4, SIGNAL(clicked()), this, SLOT(ColorButton())); - QObject::connect(sidemenuButton5, SIGNAL(clicked()), this, SLOT(FreqSpecButton())); - QObject::connect(sidemenuButton6, SIGNAL(clicked()), this, SLOT(RemovefilterButton())); - QObject::connect(sidemenuButton7, SIGNAL(clicked()), this, SLOT(RemovesignalButton())); - QObject::connect(sidemenuButton8, SIGNAL(clicked()), this, SLOT(AdjustFilterButton())); - QObject::connect(sidemenuButton9, SIGNAL(clicked()), this, SLOT(StatisticsButton())); - QObject::connect(sidemenuButton10, SIGNAL(clicked()), sidemenu, SLOT(close())); + QObject::connect(sidemenuButton5, SIGNAL(clicked()), this, SLOT(signalInvert())); + QObject::connect(sidemenuButton6, SIGNAL(clicked()), this, SLOT(FreqSpecButton())); + QObject::connect(sidemenuButton7, SIGNAL(clicked()), this, SLOT(RemovefilterButton())); + QObject::connect(sidemenuButton8, SIGNAL(clicked()), this, SLOT(RemovesignalButton())); + QObject::connect(sidemenuButton9, SIGNAL(clicked()), this, SLOT(AdjustFilterButton())); + QObject::connect(sidemenuButton10, SIGNAL(clicked()), this, SLOT(StatisticsButton())); + QObject::connect(sidemenuButton11, SIGNAL(clicked()), this, SLOT(ECGdetectButton())); + QObject::connect(sidemenuButton12, SIGNAL(clicked()), sidemenu, SLOT(close())); sidemenu->exec(); } -void ViewCurve::AdjustFilterButton() +void ViewCurve::signalInvert() { + int i; + + char str[512]; + + sidemenu->close(); if(!mainwindow->signalcomps) @@ -2231,60 +2339,163 @@ return; } - AdjustFilterSettings filtersettings(mainwindow->signalcomp[signal_nr], this); + for(i=0; isignalcomp[signal_nr]->num_of_signals; i++) + { + mainwindow->signalcomp[signal_nr]->factor[i] *= -1; + + strcpy(str, mainwindow->signalcomp[signal_nr]->edfhdr->edfparam[mainwindow->signalcomp[signal_nr]->edfsignal[i]].label); + + strip_types_from_label(str); + + if(i == 0) + { + if(mainwindow->signalcomp[signal_nr]->factor[i] < 0) + { + sprintf(mainwindow->signalcomp[signal_nr]->signallabel, + "- %s", + str); + } + else + { + sprintf(mainwindow->signalcomp[signal_nr]->signallabel, + "%s", + str); + } + } + else + { + if(mainwindow->signalcomp[signal_nr]->factor[i] < 0) + { + sprintf(mainwindow->signalcomp[signal_nr]->signallabel + strlen(mainwindow->signalcomp[signal_nr]->signallabel), + " - %s", + str); + } + else + { + sprintf(mainwindow->signalcomp[signal_nr]->signallabel + strlen(mainwindow->signalcomp[signal_nr]->signallabel), + " + %s", + str); + } + } + + remove_trailing_spaces(mainwindow->signalcomp[signal_nr]->signallabel); + + mainwindow->signalcomp[signal_nr]->signallabellen = strlen(mainwindow->signalcomp[signal_nr]->signallabel); + + if(mainwindow->signalcomp[signal_nr]->signallabellen > 480) break; + } + + if(mainwindow->signalcomp[signal_nr]->ecg_filter != NULL) + { + reset_ecg_filter(mainwindow->signalcomp[signal_nr]->ecg_filter); + + strcpy(mainwindow->signalcomp[signal_nr]->signallabel_bu, mainwindow->signalcomp[signal_nr]->signallabel); + + strcpy(mainwindow->signalcomp[signal_nr]->signallabel, "HR"); + + mainwindow->signalcomp[signal_nr]->signallabellen_bu = mainwindow->signalcomp[signal_nr]->signallabellen; + + mainwindow->signalcomp[signal_nr]->signallabellen = strlen(mainwindow->signalcomp[signal_nr]->signallabel); + } + + mainwindow->setup_viewbuf(); } -void ViewCurve::StatisticsButton() +void ViewCurve::ECGdetectButton() { - char stat_str[2048]; - - struct signalcompblock *signalcomp; + int i; + sidemenu->close(); if(!mainwindow->signalcomps) { - sidemenu->close(); - return; } if(signal_nr>(mainwindow->signalcomps - 1)) { - sidemenu->close(); - return; } + if(mainwindow->signalcomp[signal_nr]->ecg_filter != NULL) + { + free_ecg_filter(mainwindow->signalcomp[signal_nr]->ecg_filter); + + mainwindow->signalcomp[signal_nr]->ecg_filter = NULL; + + strcpy(mainwindow->signalcomp[signal_nr]->signallabel, mainwindow->signalcomp[signal_nr]->signallabel_bu); + mainwindow->signalcomp[signal_nr]->signallabellen = mainwindow->signalcomp[signal_nr]->signallabellen_bu; + strcpy(mainwindow->signalcomp[signal_nr]->physdimension, mainwindow->signalcomp[signal_nr]->physdimension_bu); + + drawCurve_stage_1(); + } + else + { + mainwindow->signalcomp[signal_nr]->ecg_filter = + create_ecg_filter(mainwindow->signalcomp[signal_nr]->edfhdr->edfparam[mainwindow->signalcomp[signal_nr]->edfsignal[0]].smp_per_record / + mainwindow->signalcomp[signal_nr]->edfhdr->data_record_duration, + mainwindow->signalcomp[signal_nr]->edfhdr->edfparam[mainwindow->signalcomp[signal_nr]->edfsignal[0]].bitvalue, + mainwindow->powerlinefreq); + + strcpy(mainwindow->signalcomp[signal_nr]->signallabel_bu, mainwindow->signalcomp[signal_nr]->signallabel); + mainwindow->signalcomp[signal_nr]->signallabellen_bu = mainwindow->signalcomp[signal_nr]->signallabellen; + strcpy(mainwindow->signalcomp[signal_nr]->signallabel, "HR"); + mainwindow->signalcomp[signal_nr]->signallabellen = strlen(mainwindow->signalcomp[signal_nr]->signallabel); + strcpy(mainwindow->signalcomp[signal_nr]->physdimension_bu, mainwindow->signalcomp[signal_nr]->physdimension); + strcpy(mainwindow->signalcomp[signal_nr]->physdimension, "bpm"); + + for(i=0; isignalcomp[signal_nr]->num_of_signals; i++) + { + mainwindow->signalcomp[signal_nr]->sensitivity[i] = mainwindow->signalcomp[signal_nr]->edfhdr->edfparam[mainwindow->signalcomp[signal_nr]->edfsignal[i]].bitvalue / 5.0 / mainwindow->pixelsizefactor; + } + + mainwindow->signalcomp[signal_nr]->voltpercm = 5.0; + + mainwindow->signalcomp[signal_nr]->screen_offset = -(-55.0 / (mainwindow->pixelsizefactor * mainwindow->signalcomp[signal_nr]->voltpercm)); + + mainwindow->setup_viewbuf(); + } +} + + +void ViewCurve::AdjustFilterButton() +{ sidemenu->close(); - signalcomp = mainwindow->signalcomp[signal_nr]; + if(!mainwindow->signalcomps) + { + return; + } - if(signalcomp->stat_cnt < 1) + if(signal_nr>(mainwindow->signalcomps - 1)) { - sprintf(stat_str, "%s\n\nSamples: 0\n\nSum: 0 %s\n\nMean: 0 %s\n\nRMS: 0 %s\n\nMRS: 0 %s", - signalcomp->signallabel, - signalcomp->physdimension, - signalcomp->physdimension, - signalcomp->physdimension, - signalcomp->physdimension); + return; } - else + + AdjustFilterSettings filtersettings(mainwindow->signalcomp[signal_nr], this); +} + + +void ViewCurve::StatisticsButton() +{ + if(!mainwindow->signalcomps) + { + sidemenu->close(); + + return; + } + + if(signal_nr>(mainwindow->signalcomps - 1)) { - sprintf(stat_str, "%s\n\nSamples: %i\n\nSum: %f %s\n\nMean: %f %s\n\nRMS: %f %s\n\nMRS: %f %s", - signalcomp->signallabel, - signalcomp->stat_cnt, - signalcomp->stat_sum * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue, - signalcomp->physdimension, - (signalcomp->stat_sum * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue) / signalcomp->stat_cnt, - signalcomp->physdimension, - sqrt(signalcomp->stat_sum_sqr / signalcomp->stat_cnt) * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue, - signalcomp->physdimension, - (signalcomp->stat_sum_rectified / signalcomp->stat_cnt) * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue, - signalcomp->physdimension); + sidemenu->close(); + + return; } - UI_Messagewindow show_stats_window("Statistics", stat_str, "Close"); + sidemenu->close(); + + UI_StatisticWindow show_stats_window(mainwindow->signalcomp[signal_nr]); } @@ -2306,7 +2517,18 @@ if(isignalcomp[signal_nr]->spectr_dialog[j] == 0) + { + mainwindow->signalcomp[signal_nr]->spectr_dialog[j] = i + 1; + + break; + } + } + mainwindow->spectrumdialog[i]->SpectrumDialog->move(((i % 15) * 30) + 200, ((i % 15) * 30) + 200); + for(j=0; jspectrumdialog[j] != NULL) @@ -2453,6 +2675,24 @@ mainwindow->signalcomp[signal_nr]->filter_cnt = 0; + for(j=0; jsignalcomp[signal_nr]->ravg_filter_cnt; j++) + { + free_ravg_filter(mainwindow->signalcomp[signal_nr]->ravg_filter[j]); + } + + mainwindow->signalcomp[signal_nr]->ravg_filter_cnt = 0; + + if(mainwindow->signalcomp[signal_nr]->ecg_filter != NULL) + { + free_ecg_filter(mainwindow->signalcomp[signal_nr]->ecg_filter); + + mainwindow->signalcomp[signal_nr]->ecg_filter = NULL; + + strcpy(mainwindow->signalcomp[signal_nr]->signallabel, mainwindow->signalcomp[signal_nr]->signallabel_bu); + mainwindow->signalcomp[signal_nr]->signallabellen = mainwindow->signalcomp[signal_nr]->signallabellen_bu; + strcpy(mainwindow->signalcomp[signal_nr]->physdimension, mainwindow->signalcomp[signal_nr]->physdimension_bu); + } + for(j=0; jsignalcomp[signal_nr]->fidfilter_cnt; j++) { free(mainwindow->signalcomp[signal_nr]->fidfilter[j]); @@ -2474,7 +2714,7 @@ void ViewCurve::RemovesignalButton() { - int i, j; + int i, j, p; if(!mainwindow->signalcomps) { @@ -2498,14 +2738,25 @@ for(i=0; ispectrumdialog[i] != NULL) + p = mainwindow->signalcomp[signal_nr]->spectr_dialog[i]; + + if(p != 0) { - if(mainwindow->spectrumdialog[i]->signalcomp == mainwindow->signalcomp[signal_nr]) - { - delete mainwindow->spectrumdialog[i]; + delete mainwindow->spectrumdialog[p - 1]; - mainwindow->spectrumdialog[i] = NULL; - } + mainwindow->spectrumdialog[p - 1] = NULL; + } + } + + for(i=0; isignalcomp[signal_nr]->avg_dialog[i]; + + if(p != 0) + { + delete mainwindow->averagecurvedialog[p - 1]; + + mainwindow->averagecurvedialog[p - 1] = NULL; } } @@ -2541,6 +2792,34 @@ mainwindow->signalcomp[signal_nr]->filter_cnt = 0; + for(j=0; jsignalcomp[signal_nr]->ravg_filter_cnt; j++) + { + free_ravg_filter(mainwindow->signalcomp[signal_nr]->ravg_filter[j]); + } + + mainwindow->signalcomp[signal_nr]->ravg_filter_cnt = 0; + + if(mainwindow->signalcomp[signal_nr]->ecg_filter != NULL) + { + free_ecg_filter(mainwindow->signalcomp[signal_nr]->ecg_filter); + + mainwindow->signalcomp[signal_nr]->ecg_filter = NULL; + + strcpy(mainwindow->signalcomp[signal_nr]->signallabel, mainwindow->signalcomp[signal_nr]->signallabel_bu); + mainwindow->signalcomp[signal_nr]->signallabellen = mainwindow->signalcomp[signal_nr]->signallabellen_bu; + strcpy(mainwindow->signalcomp[signal_nr]->physdimension, mainwindow->signalcomp[signal_nr]->physdimension_bu); + } + + for(j=0; jsignalcomp[signal_nr]->fidfilter_cnt; j++) + { + free(mainwindow->signalcomp[signal_nr]->fidfilter[j]); + fid_run_free(mainwindow->signalcomp[signal_nr]->fid_run[j]); + fid_run_freebuf(mainwindow->signalcomp[signal_nr]->fidbuf[j]); + fid_run_freebuf(mainwindow->signalcomp[signal_nr]->fidbuf2[j]); + } + + mainwindow->signalcomp[signal_nr]->fidfilter_cnt = 0; + free(mainwindow->signalcomp[signal_nr]); for(i=signal_nr; isignalcomps - 1; i++) @@ -2585,28 +2864,32 @@ if((mainwindow->pagetime / TIME_DIMENSION) < 2LL) { - UI_Messagewindow msg_window("Ruler", "The ruler can not be used when the Timescale\n is set to a value less than 2 seconds.", "Close"); + QMessageBox messagewindow(QMessageBox::Warning, "Ruler", "The ruler can not be used when the Timescale\n is set to a value less than 2 seconds."); + messagewindow.exec(); goto END_OF_FUNC; } if((mainwindow->pagetime / TIME_DIMENSION) > 120LL) { - UI_Messagewindow msg_window("Ruler", "The ruler can not be used when the Timescale\n is set to a value more than 120 seconds.", "Close"); + QMessageBox messagewindow(QMessageBox::Warning, "Ruler", "The ruler can not be used when the Timescale\n is set to a value more than 120 seconds."); + messagewindow.exec(); goto END_OF_FUNC; } if(mainwindow->signalcomp[signal_nr]->voltpercm < 1.0) { - UI_Messagewindow msg_window("Ruler", "The ruler can not be used when the Amplitude\n is set to a value less than 1.", "Close"); + QMessageBox messagewindow(QMessageBox::Warning, "Ruler", "The ruler can not be used when the Amplitude\n is set to a value less than 1."); + messagewindow.exec(); goto END_OF_FUNC; } if(mainwindow->signalcomp[signal_nr]->voltpercm > 2000.0) { - UI_Messagewindow msg_window("Ruler", "The ruler can not be used when the Amplitude\n is set to a value more than 2000.", "Close"); + QMessageBox messagewindow(QMessageBox::Warning, "Ruler", "The ruler can not be used when the Amplitude\n is set to a value more than 2000."); + messagewindow.exec(); goto END_OF_FUNC; } @@ -2947,6 +3230,40 @@ +void ViewCurve::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 #include #include +#include #include #include @@ -61,6 +62,9 @@ #include "spectrumanalyzer.h" #include "utils.h" #include "adjustfiltersettings.h" +#include "ravg_filter.h" +#include "ecg_filter.h" +#include "statistics_dialog.h" #include "fidlib/fidlib.h" @@ -118,7 +122,9 @@ backup_color_11, backup_color_12, backup_color_14, - annot_marker_moving; + annot_marker_moving, + pressed_on_label, + label_press_y_position; double crosshair_1_value, @@ -189,7 +195,9 @@ *sidemenuButton7, *sidemenuButton8, *sidemenuButton9, - *sidemenuButton10; + *sidemenuButton10, + *sidemenuButton11, + *sidemenuButton12; QDoubleSpinBox *ScaleBox, *ScaleBox2; @@ -232,6 +240,9 @@ void FreqSpecButton(); void AdjustFilterButton(); void StatisticsButton(); + void ECGdetectButton(); + void signalInvert(); + void strip_types_from_label(char *); protected: void paintEvent(QPaintEvent *); @@ -240,6 +251,7 @@ void mousePressEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *); + void wheelEvent(QWheelEvent *); }; diff -Nru edfbrowser-1.30/view_montage_dialog.cpp edfbrowser-1.38/view_montage_dialog.cpp --- edfbrowser-1.30/view_montage_dialog.cpp 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/view_montage_dialog.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -51,17 +51,22 @@ ViewMontageDialog = new QDialog; - ViewMontageDialog->setMinimumSize(QSize(400, 300)); - ViewMontageDialog->resize(700, 440); + ViewMontageDialog->setMinimumSize(QSize(500, 300)); + ViewMontageDialog->resize(500, 440); ViewMontageDialog->setWindowTitle("View montage"); ViewMontageDialog->setModal(TRUE); ViewMontageDialog->setAttribute(Qt::WA_DeleteOnClose, TRUE); - textedit1 = new QTextEdit; - textedit1->setFrameStyle(QFrame::Panel | QFrame::Sunken); - textedit1->setReadOnly(TRUE); - textedit1->setLineWrapMode(QTextEdit::NoWrap); - textedit1->setFont(*mainwindow->monofont); + t_model = new QStandardItemModel(this); + + tree = new QTreeView; + tree->setHeaderHidden(TRUE); + tree->setIndentation(30); + tree->setSelectionMode(QAbstractItemView::NoSelection); + tree->setEditTriggers(QAbstractItemView::NoEditTriggers); + tree->setSortingEnabled(FALSE); + tree->setDragDropMode(QAbstractItemView::NoDragDrop); + tree->setModel(t_model); SelectButton = new QPushButton; SelectButton->setFixedSize(100, 25); @@ -76,7 +81,7 @@ hbox->addWidget(CloseButton, 0, Qt::AlignRight); box = new QBoxLayout(QBoxLayout::TopToBottom, ViewMontageDialog); - box->addWidget(textedit1); + box->addWidget(tree); box->addLayout(hbox); QObject::connect(CloseButton, SIGNAL(clicked()), ViewMontageDialog, SLOT(close())); @@ -95,7 +100,8 @@ signal_cnt, filters_read, color, - filter_cnt, + filter_cnt=0, + ravg_filter_cnt=0, fidfilter_cnt=0, islpf, factor[MAXSIGNALS], @@ -103,7 +109,8 @@ screen_offset, order, model, - type; + type, + size; char *result, composition_txt[2048], @@ -115,6 +122,10 @@ ripple, timescale; + QStandardItem *parentItem, + *signalItem, + *filterItem; + struct xml_handle *xml_hdl; @@ -127,25 +138,27 @@ get_directory_from_path(mtg_dir, mtg_path, 1024); - textedit1->clear(); - xml_hdl = xml_get_handle(mtg_path); if(xml_hdl==NULL) { - UI_Messagewindow popuperror("Error", "Error, can not open file for reading."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); + messagewindow.exec(); return; } if(strcmp(xml_hdl->elementname, PROGRAM_NAME "_montage")) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); xml_close(xml_hdl); return; } ViewMontageDialog->setWindowTitle(mtg_path); - textedit1->clear(); + t_model->clear(); + + parentItem = t_model->invisibleRootItem(); for(signalcomps=0; ; signalcomps++) { @@ -153,6 +166,10 @@ signals_read = 0; + filter_cnt = 0; + ravg_filter_cnt = 0; + fidfilter_cnt = 0; + if(xml_goto_nth_element_inside(xml_hdl, "signalcomposition", signalcomps_read)) { break; @@ -160,7 +177,8 @@ if(xml_goto_nth_element_inside(xml_hdl, "num_of_signals", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -169,7 +187,8 @@ free(result); if((signal_cnt<1)||(signal_cnt>256)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -177,7 +196,8 @@ xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "voltpercm", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -188,59 +208,68 @@ xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "screen_offset", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); xml_close(xml_hdl); return; } result = xml_get_content_of_element(xml_hdl); screen_offset = atoi(result); free(result); - xml_go_up(xml_hdl); + if(xml_goto_nth_element_inside(xml_hdl, "color", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); xml_close(xml_hdl); return; } result = xml_get_content_of_element(xml_hdl); color = atoi(result); free(result); - xml_go_up(xml_hdl); - if(xml_goto_nth_element_inside(xml_hdl, "filter_cnt", 0)) + + if(!(xml_goto_nth_element_inside(xml_hdl, "filter_cnt", 0))) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file."); - xml_close(xml_hdl); - return; + result = xml_get_content_of_element(xml_hdl); + filter_cnt = atoi(result); + free(result); + xml_go_up(xml_hdl); + } + + if(!(xml_goto_nth_element_inside(xml_hdl, "ravg_filter_cnt", 0))) + { + result = xml_get_content_of_element(xml_hdl); + ravg_filter_cnt = atoi(result); + free(result); + xml_go_up(xml_hdl); } - result = xml_get_content_of_element(xml_hdl); - filter_cnt = atoi(result); - free(result); - xml_go_up(xml_hdl); if(!(xml_goto_nth_element_inside(xml_hdl, "fidfilter_cnt", 0))) { result = xml_get_content_of_element(xml_hdl); fidfilter_cnt = atoi(result); free(result); + xml_go_up(xml_hdl); } - sprintf(composition_txt, "%3i: ", signalcomps + 1); - - xml_go_up(xml_hdl); for(signals_read=0; signals_readappendRow(signalItem); + + sprintf(composition_txt, "amplitude: %f", voltpercm); + + remove_trailing_zeros(composition_txt); + + sprintf(composition_txt + strlen(composition_txt), "/cm offset: %f", (double)screen_offset * mainwindow->pixelsizefactor * voltpercm); + + remove_trailing_zeros(composition_txt); + + strcat(composition_txt, " color: "); + + switch(color) + { + case Qt::white : strcat(composition_txt, "white"); + break; + case Qt::black : strcat(composition_txt, "black"); + break; + case Qt::red : strcat(composition_txt, "red"); + break; + case Qt::darkRed : strcat(composition_txt, "dark red"); + break; + case Qt::green : strcat(composition_txt, "green"); + break; + case Qt::darkGreen : strcat(composition_txt, "dark green"); + break; + case Qt::blue : strcat(composition_txt, "blue"); + break; + case Qt::darkBlue : strcat(composition_txt, "dark blue"); + break; + case Qt::cyan : strcat(composition_txt, "cyan"); + break; + case Qt::darkCyan : strcat(composition_txt, "dark cyan"); + break; + case Qt::magenta : strcat(composition_txt, "magenta"); + break; + case Qt::darkMagenta : strcat(composition_txt, "dark magenta"); + break; + case Qt::yellow : strcat(composition_txt, "yellow"); + break; + case Qt::darkYellow : strcat(composition_txt, "dark yellow"); + break; + case Qt::gray : strcat(composition_txt, "gray"); + break; + case Qt::darkGray : strcat(composition_txt, "dark gray"); + break; + case Qt::lightGray : strcat(composition_txt, "light gray"); + break; + } + + signalItem->appendRow(new QStandardItem(composition_txt)); + + filterItem = new QStandardItem("Filters"); + + signalItem->appendRow(filterItem); + for(filters_read=0; filters_readappendRow(new QStandardItem(composition_txt)); + + xml_go_up(xml_hdl); + xml_go_up(xml_hdl); + } + + for(filters_read=0; filters_readappendRow(new QStandardItem(composition_txt)); + xml_go_up(xml_hdl); xml_go_up(xml_hdl); } @@ -316,14 +460,16 @@ { if(xml_goto_nth_element_inside(xml_hdl, "fidfilter", filters_read)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file. (fidfilter)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file. (fidfilter)"); + messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_goto_nth_element_inside(xml_hdl, "type", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file. (type)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file. (type)"); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -334,7 +480,8 @@ xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "frequency", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file. (frequency)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file. (frequency)"); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -345,7 +492,8 @@ xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "frequency2", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file. (frequency2)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file. (frequency2)"); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -356,7 +504,8 @@ xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "ripple", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file. (ripple)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file. (ripple)"); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -367,7 +516,8 @@ xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "order", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file. (order)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file. (order)"); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -378,7 +528,8 @@ xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "model", 0)) { - UI_Messagewindow popuperror("Error", "There seems to be an error in this montage file. (model)"); + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file. (model)"); + messagewindow.exec(); xml_close(xml_hdl); return; } @@ -390,17 +541,17 @@ { if(model == 0) { - sprintf(composition_txt + strlen(composition_txt), "highpass Butterworth %fHz %ith order ", frequency, order); + sprintf(composition_txt, "highpass Butterworth %fHz %ith order ", frequency, order); } if(model == 1) { - sprintf(composition_txt + strlen(composition_txt), "highpass Chebyshev %fHz %ith order %fdB ripple ", frequency, order, ripple); + sprintf(composition_txt, "highpass Chebyshev %fHz %ith order %fdB ripple ", frequency, order, ripple); } if(model == 2) { - sprintf(composition_txt + strlen(composition_txt), "highpass Bessel %fHz %ith order ", frequency, order); + sprintf(composition_txt, "highpass Bessel %fHz %ith order ", frequency, order); } } @@ -408,40 +559,40 @@ { if(model == 0) { - sprintf(composition_txt + strlen(composition_txt), "lowpass Butterworth %fHz %ith order ", frequency, order); + sprintf(composition_txt, "lowpass Butterworth %fHz %ith order ", frequency, order); } if(model == 1) { - sprintf(composition_txt + strlen(composition_txt), "lowpass Chebyshev %fHz %ith order %fdB ripple ", frequency, order, ripple); + sprintf(composition_txt, "lowpass Chebyshev %fHz %ith order %fdB ripple ", frequency, order, ripple); } if(model == 2) { - sprintf(composition_txt + strlen(composition_txt), "lowpass Bessel %fHz %ith order ", frequency, order); + sprintf(composition_txt, "lowpass Bessel %fHz %ith order ", frequency, order); } } if(type == 2) { - sprintf(composition_txt + strlen(composition_txt), "notch %fHz Q-factor %i ", frequency, order); + sprintf(composition_txt, "notch %fHz Q-factor %i ", frequency, order); } if(type == 3) { if(model == 0) { - sprintf(composition_txt + strlen(composition_txt), "bandpass Butterworth %f-%fHz %ith order ", frequency, frequency2, order); + sprintf(composition_txt, "bandpass Butterworth %f-%fHz %ith order ", frequency, frequency2, order); } if(model == 1) { - sprintf(composition_txt + strlen(composition_txt), "bandpass Chebyshev %f-%fHz %ith order %fdB ripple ", frequency, frequency2, order, ripple); + sprintf(composition_txt, "bandpass Chebyshev %f-%fHz %ith order %fdB ripple ", frequency, frequency2, order, ripple); } if(model == 2) { - sprintf(composition_txt + strlen(composition_txt), "bandpass Bessel %f-%fHz %ith order ", frequency, frequency2, order); + sprintf(composition_txt, "bandpass Bessel %f-%fHz %ith order ", frequency, frequency2, order); } } @@ -449,29 +600,51 @@ { if(model == 0) { - sprintf(composition_txt + strlen(composition_txt), "bandstop Butterworth %f-%fHz %ith order ", frequency, frequency2, order); + sprintf(composition_txt, "bandstop Butterworth %f-%fHz %ith order ", frequency, frequency2, order); } if(model == 1) { - sprintf(composition_txt + strlen(composition_txt), "bandstop Chebyshev %f-%fHz %ith order %fdB ripple ", frequency, frequency2, order, ripple); + sprintf(composition_txt, "bandstop Chebyshev %f-%fHz %ith order %fdB ripple ", frequency, frequency2, order, ripple); } if(model == 2) { - sprintf(composition_txt + strlen(composition_txt), "bandstop Bessel %f-%fHz %ith order ", frequency, frequency2, order); + sprintf(composition_txt, "bandstop Bessel %f-%fHz %ith order ", frequency, frequency2, order); } } + remove_trailing_zeros(composition_txt); + + filterItem->appendRow(new QStandardItem(composition_txt)); + xml_go_up(xml_hdl); xml_go_up(xml_hdl); } - sprintf(composition_txt + strlen(composition_txt), " %f/cm offset: %f", voltpercm, (double)screen_offset * mainwindow->pixelsizefactor * voltpercm); + if(!xml_goto_nth_element_inside(xml_hdl, "ecg_filter", 0)) + { + if(xml_goto_nth_element_inside(xml_hdl, "type", 0)) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); + messagewindow.exec(); + xml_close(xml_hdl); + return; + } + result = xml_get_content_of_element(xml_hdl); + type = atoi(result); + free(result); + + if(type == 1) + { + sprintf(composition_txt, "ECG heartrate detection"); + } - remove_trailing_zeros(composition_txt); + filterItem->appendRow(new QStandardItem(composition_txt)); - textedit1->append(composition_txt); + xml_go_up(xml_hdl); + xml_go_up(xml_hdl); + } signalcomps_read++; } @@ -483,10 +656,10 @@ result = xml_get_content_of_element(xml_hdl); timescale = atof(result); timescale /= TIME_DIMENSION; - sprintf(composition_txt, "\n timescale: %f seconds", timescale); + sprintf(composition_txt, "timescale: %f seconds", timescale); remove_trailing_zeros(composition_txt); - textedit1->append(composition_txt); free(result); + parentItem->appendRow(new QStandardItem(composition_txt)); } xml_close(xml_hdl); diff -Nru edfbrowser-1.30/view_montage_dialog.h edfbrowser-1.38/view_montage_dialog.h --- edfbrowser-1.30/view_montage_dialog.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/view_montage_dialog.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * @@ -45,6 +45,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -76,8 +80,6 @@ QDialog *ViewMontageDialog; - QTextEdit *textedit1; - QPushButton *CloseButton, *SelectButton; @@ -85,6 +87,10 @@ QHBoxLayout *hbox; + QTreeView *tree; + + QStandardItemModel *t_model; + char mtg_path[1024], mtg_dir[1024]; diff -Nru edfbrowser-1.30/wav2edf.cpp edfbrowser-1.38/wav2edf.cpp --- edfbrowser-1.30/wav2edf.cpp 1970-01-01 00:00:00.000000000 +0000 +++ edfbrowser-1.38/wav2edf.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -0,0 +1,714 @@ +/* +*************************************************************************** +* +* Author: Teunis van Beelen +* +* Copyright (C) 2011 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 "wav2edf.h" + + + +#if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) + +#define fopeno fopen + +#else + +#define fseeko fseeko64 +#define ftello ftello64 +#define fopeno fopen64 + +#endif + + + + +UI_WAV2EDFwindow::UI_WAV2EDFwindow(char *recent_dir, char *save_dir) +{ + recent_opendir = recent_dir; + recent_savedir = save_dir; + + myobjectDialog = new QDialog; + + myobjectDialog->setMinimumSize(QSize(600, 300)); + myobjectDialog->setMaximumSize(QSize(600, 300)); + myobjectDialog->setWindowTitle("Wave to EDF converter"); + myobjectDialog->setModal(TRUE); + myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, TRUE); + + PatientnameLabel = new QLabel(myobjectDialog); + PatientnameLabel->setGeometry(QRect(20, 20, 140, 16)); + PatientnameLabel->setText("Subject"); + + RecordingLabel = new QLabel(myobjectDialog); + RecordingLabel->setGeometry(QRect(20, 50, 140, 16)); + RecordingLabel->setText("Recording"); + + DatetimeLabel = new QLabel(myobjectDialog); + DatetimeLabel->setGeometry(QRect(20, 80, 140, 16)); + DatetimeLabel->setText("Startdate and time"); + + PhysDimLabel = new QLabel(myobjectDialog); + PhysDimLabel->setGeometry(QRect(20, 110, 140, 16)); + PhysDimLabel->setText("Physical dimension"); + + PhysMaxLabel = new QLabel(myobjectDialog); + PhysMaxLabel->setGeometry(QRect(20, 140, 140, 16)); + PhysMaxLabel->setText("Physical maximum"); + + PatientnameLineEdit = new QLineEdit(myobjectDialog); + PatientnameLineEdit->setGeometry(QRect(160, 20, 420, 21)); + PatientnameLineEdit->setMaxLength(80); + + RecordingLineEdit = new QLineEdit(myobjectDialog); + RecordingLineEdit->setGeometry(QRect(160, 50, 420, 21)); + RecordingLineEdit->setMaxLength(80); + + StartDatetimeedit = new QDateTimeEdit(myobjectDialog); + StartDatetimeedit->setGeometry(QRect(160, 80, 140, 22)); + StartDatetimeedit->setDisplayFormat("dd/MM/yyyy hh:mm:ss"); + StartDatetimeedit->setDateTime(QDateTime::currentDateTime()); + + PhysDimLineEdit = new QLineEdit(myobjectDialog); + PhysDimLineEdit->setGeometry(QRect(160, 110, 140, 21)); + PhysDimLineEdit->setMaxLength(8); + PhysDimLineEdit->setText("mV"); + + PhysMaxSpinBox = new QDoubleSpinBox(myobjectDialog); + PhysMaxSpinBox->setGeometry(QRect(160, 140, 140, 21)); + PhysMaxSpinBox->setDecimals(5); + PhysMaxSpinBox->setRange(1.0, 1000000.0); + PhysMaxSpinBox->setValue(2000.0); + + pushButton1 = new QPushButton(myobjectDialog); + pushButton1->setGeometry(QRect(20, 250, 100, 26)); + pushButton1->setText("Select File"); + + pushButton2 = new QPushButton(myobjectDialog); + pushButton2->setGeometry(QRect(480, 250, 100, 26)); + pushButton2->setText("Close"); + + QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton())); + QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close())); + + myobjectDialog->exec(); +} + + + +void UI_WAV2EDFwindow::SelectFileButton() +{ + FILE *inputfile=NULL; + + int i, j, k, + edfsignals, + sf, + resolution, + edf_hdl, + readbufsize, + *writebuf, + bytes_per_sample, + sf_divider; + +unsigned int fmt_chunk_offset, + data_chunk_offset, + tmp; + + char path[1024], + outputfilename[1024], + scratchpad[512], + *readbuf; + + long long blocks, + leftover; + + union { + unsigned int one; + signed int one_signed; + unsigned short two[2]; + signed short two_signed[2]; + unsigned char four[4]; + } var; + + + enable_widgets(FALSE); + + if(!(strlen(PatientnameLineEdit->text().toLatin1().data()))) + { + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a subject name."); + messagewindow.exec(); + enable_widgets(TRUE); + return; + } + + if(!(strlen(RecordingLineEdit->text().toLatin1().data()))) + { + QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a recording description."); + messagewindow.exec(); + enable_widgets(TRUE); + return; + } + + strcpy(path, QFileDialog::getOpenFileName(0, "Select inputfile", recent_opendir, "Text files (*.wav *.WAV)").toLatin1().data()); + + if(!strcmp(path, "")) + { + enable_widgets(TRUE); + return; + } + + get_directory_from_path(recent_opendir, path, 1024); + + inputfile = fopeno(path, "rb"); + if(inputfile==NULL) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); + messagewindow.exec(); + enable_widgets(TRUE); + return; + } + +/***************** check if the wavefile is valid ******************************/ + + rewind(inputfile); + + if(fread(scratchpad, 256, 1, inputfile)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); + messagewindow.exec(); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + + if((strncmp(scratchpad, "RIFF", 4)) || (strncmp(scratchpad + 8, "WAVE", 4))) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "File is not a Wave file."); + messagewindow.exec(); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + + fmt_chunk_offset = 12; + + while(1) + { + fseeko(inputfile, (long long)fmt_chunk_offset, SEEK_SET); + + if(fread(scratchpad, 256, 1, inputfile)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find fmt chunk."); + messagewindow.exec(); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + + if(strncmp(scratchpad, "fmt ", 4) == 0) + { + break; + } + + tmp = *((unsigned int *)(scratchpad + 4)); + if(tmp < 2) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find fmt chunk."); + messagewindow.exec(); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + + if(tmp & 1) + { + tmp++; + } + + fmt_chunk_offset += (tmp + 8); + } + + if(*((signed short *)(scratchpad + 8)) != 1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "File contains compressed data.\nCan not convert compressed data."); + messagewindow.exec(); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + + edfsignals = *((unsigned short *)(scratchpad + 10)); + + if(edfsignals < 1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Channels < 1"); + messagewindow.exec(); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + + if(edfsignals > MAXSIGNALS) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Channels > MAXSIGNALS"); + messagewindow.exec(); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + + sf = *((unsigned int *)(scratchpad + 12)); + + if(sf < 1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Samplefrequency < 1"); + messagewindow.exec(); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + + if(sf > 500000) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Samplefrequency > 500000"); + messagewindow.exec(); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + + resolution = *((unsigned short *)(scratchpad + 22)); + + if(resolution < 8) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Resolution < 8 bit"); + messagewindow.exec(); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + + if(resolution > 24) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Resolution > 24"); + messagewindow.exec(); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + + if((resolution != 8) && (resolution != 16) && (resolution != 24)) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Resolution (bitdepth) must be 8, 16 or 24 bit."); + messagewindow.exec(); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + + bytes_per_sample = 2; + + if(resolution > 16) + { + bytes_per_sample = 3; + } + + if(resolution < 9) + { + bytes_per_sample = 1; + } + +/////////////////////////////////////////////////////////////////////////////// + + data_chunk_offset = 12; + + while(1) + { + fseeko(inputfile, (long long)data_chunk_offset, SEEK_SET); + + if(fread(scratchpad, 256, 1, inputfile)!=1) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find data chunk."); + messagewindow.exec(); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + + if(strncmp(scratchpad, "data", 4) == 0) + { + break; + } + + tmp = *((unsigned int *)(scratchpad + 4)); + if(tmp < 2) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find data chunk."); + messagewindow.exec(); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + + if(tmp & 1) + { + tmp++; + } + + data_chunk_offset += (tmp + 8); + } + +/////////////////////////////////////////////////////////////////////////////// + + sf_divider = 1; + + if((sf % 10) == 0) + { + sf_divider = 10; + + sf /= 10; + } + + blocks = (long long)(*((int *)(scratchpad + 4))); + + blocks /= (sf * edfsignals * bytes_per_sample); + + fseeko(inputfile, 0LL, SEEK_END); + + leftover = ftello(inputfile) - (long long)data_chunk_offset - 8LL; + + leftover /= (sf * edfsignals * bytes_per_sample); + + if(blocks > leftover) + { + blocks = leftover; + } + + if(blocks < 1LL) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Not enough data in file."); + messagewindow.exec(); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + + readbufsize = bytes_per_sample * sf * edfsignals; + + readbuf = (char *)malloc(readbufsize); + if(readbuf == NULL) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (readbuf)."); + messagewindow.exec(); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + + writebuf = (int *)malloc(sf * edfsignals * sizeof(int)); + if(writebuf == NULL) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (writebuf)."); + messagewindow.exec(); + free(readbuf); + fclose(inputfile); + enable_widgets(TRUE); + return; + } + +// printf("resolution is %i edfsignals is %i sf is %i blocks is %lli\n", resolution, edfsignals, sf, blocks); + +/***************** create a new EDF file *****************************************/ + + get_filename_from_path(outputfilename, path, 1024); + remove_extension_from_filename(outputfilename); + if(resolution > 16) + { + strcat(outputfilename, ".bdf"); + } + else + { + strcat(outputfilename, ".edf"); + } + + path[0] = 0; + if(recent_savedir[0]!=0) + { + strcpy(path, recent_savedir); + strcat(path, "/"); + } + strcat(path, outputfilename); + + if(resolution > 16) + { + strcpy(path, QFileDialog::getSaveFileName(0, "Output file", path, "BDF files (*.bdf *.BDF)").toLatin1().data()); + } + else + { + strcpy(path, QFileDialog::getSaveFileName(0, "Output file", path, "EDF files (*.edf *.EDF)").toLatin1().data()); + } + + if(!strcmp(path, "")) + { + enable_widgets(TRUE); + fclose(inputfile); + return; + } + + get_directory_from_path(recent_savedir, path, 1024); + + if(resolution > 16) + { + edf_hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_BDFPLUS, edfsignals); + } + else + { + edf_hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_EDFPLUS, edfsignals); + } + + if(edf_hdl < 0) + { + QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open output file for writing."); + messagewindow.exec(); + fclose(inputfile); + free(readbuf); + free(writebuf); + enable_widgets(TRUE); + return; + } + + for(i=0; i 16) + { + edf_set_digital_maximum(edf_hdl, i, 8388607); + } + else + { + if(resolution < 9) + { + edf_set_digital_maximum(edf_hdl, i, 127); + } + else + { + edf_set_digital_maximum(edf_hdl, i, 32767); + } + } + } + + for(i=0; i 16) + { + edf_set_digital_minimum(edf_hdl, i, -8388608); + } + else + { + if(resolution < 9) + { + edf_set_digital_minimum(edf_hdl, i, -128); + } + else + { + edf_set_digital_minimum(edf_hdl, i, -32768); + } + } + } + + for(i=0; ivalue()); + } + + for(i=0; ivalue() * -1.0); + } + + for(i=0; itext().toLatin1().data()); + } + + for(i=0; itext().toLatin1().data()); + + edf_set_recording_additional(edf_hdl, RecordingLineEdit->text().toLatin1().data()); + + edf_set_startdatetime(edf_hdl, StartDatetimeedit->date().year(), StartDatetimeedit->date().month(), StartDatetimeedit->date().day(), + StartDatetimeedit->time().hour(), StartDatetimeedit->time().minute(), StartDatetimeedit->time().second()); + + edfwrite_annotation_latin1(edf_hdl, 0LL, -1, "Recording starts"); + +/***************** start conversion **************************************/ + + fseeko(inputfile, (long long)data_chunk_offset + 8LL, SEEK_SET); + + QProgressDialog progress("Converting a Wave file ...", "Abort", 0, (int)blocks, myobjectDialog); + progress.setWindowModality(Qt::WindowModal); + progress.setMinimumDuration(200); + progress.setValue(0); + + for(k=0; k<10; k++) qApp->processEvents(); + + for(k=0; kprocessEvents(); + + if(progress.wasCanceled() == TRUE) + { + edfclose_file(edf_hdl); + fclose(inputfile); + free(readbuf); + free(writebuf); + enable_widgets(TRUE); + return; + } + } + + progress.reset(); + + edfwrite_annotation_latin1(edf_hdl, (blocks * 10000LL) / sf_divider, -1, "Recording ends"); + + edfclose_file(edf_hdl); + + fclose(inputfile); + + QMessageBox messagewindow(QMessageBox::Information, "Ready", "Done."); + messagewindow.exec(); + + free(readbuf); + free(writebuf); + + enable_widgets(TRUE); +} + + +void UI_WAV2EDFwindow::enable_widgets(bool toggle) +{ + StartDatetimeedit->setEnabled(toggle); + PatientnameLineEdit->setEnabled(toggle); + RecordingLineEdit->setEnabled(toggle); + pushButton1->setEnabled(toggle); + pushButton2->setEnabled(toggle); +} + + + diff -Nru edfbrowser-1.30/wav2edf.h edfbrowser-1.38/wav2edf.h --- edfbrowser-1.30/wav2edf.h 1970-01-01 00:00:00.000000000 +0000 +++ edfbrowser-1.38/wav2edf.h 2011-08-23 20:01:14.000000000 +0000 @@ -0,0 +1,108 @@ +/* +*************************************************************************** +* +* Author: Teunis van Beelen +* +* Copyright (C) 2011 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 +* +*************************************************************************** +*/ + + +#ifndef UI_WAV2EDFFORM_H +#define UI_WAV2EDFFORM_H + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "global.h" +#include "popup_messagewindow.h" +#include "utils.h" +#include "edflib.h" + + + + +class UI_WAV2EDFwindow : public QObject +{ + Q_OBJECT + +public: + UI_WAV2EDFwindow(char *recent_dir=NULL, char *save_dir=NULL); + +private: + +QDialog *myobjectDialog; + +QPushButton *pushButton1, + *pushButton2; + +QLabel *PatientnameLabel, + *RecordingLabel, + *DatetimeLabel, + *PhysDimLabel, + *PhysMaxLabel; + +QLineEdit *PatientnameLineEdit, + *RecordingLineEdit, + *PhysDimLineEdit; + +QDateTimeEdit *StartDatetimeedit; + +QDoubleSpinBox *PhysMaxSpinBox; + +char *recent_opendir, + *recent_savedir; + +void enable_widgets(bool); + + +private slots: + +void SelectFileButton(); + +}; + + + + +#endif + + diff -Nru edfbrowser-1.30/xml.cpp edfbrowser-1.38/xml.cpp --- edfbrowser-1.30/xml.cpp 2010-11-23 08:41:07.000000000 +0000 +++ edfbrowser-1.38/xml.cpp 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com * diff -Nru edfbrowser-1.30/xml.h edfbrowser-1.38/xml.h --- edfbrowser-1.30/xml.h 2010-11-19 14:43:08.000000000 +0000 +++ edfbrowser-1.38/xml.h 2011-08-23 20:01:14.000000000 +0000 @@ -3,7 +3,7 @@ * * Author: Teunis van Beelen * -* Copyright (C) 2007, 2008, 2009, 2010 Teunis van Beelen +* Copyright (C) 2007, 2008, 2009, 2010, 2011 Teunis van Beelen * * teuniz@gmail.com *