[med-svn] [edfbrowser] 01/04: New upstream version 1.61
Andreas Tille
tille at debian.org
Mon Nov 13 12:03:47 UTC 2017
This is an automated email from the git hooks/post-receive script.
tille pushed a commit to branch master
in repository edfbrowser.
commit 98c02ce47d3d58205c9389007b947eba556ea4d5
Author: Andreas Tille <tille at debian.org>
Date: Mon Nov 13 12:51:49 2017 +0100
New upstream version 1.61
---
README.txt | 12 +-
annotations_dock.cpp | 102 ++-
annotations_dock.h | 8 +-
annotlist_filter_dialog.cpp | 373 ++++++++
averager_dialog.h => annotlist_filter_dialog.h | 75 +-
averager_curve_wnd.cpp | 4 +-
averager_curve_wnd.h | 8 +-
averager_dialog.cpp | 61 +-
averager_dialog.h | 9 +-
doc/manual.html | 34 +-
edf_annot_list.c | 45 +
edf_annot_list.h | 2 +
edfbrowser.pro | 4 +
reduce_signals.cpp => export_filtered_signals.cpp | 1004 +++++++++++----------
export_filtered_signals.h | 140 +++
filteredblockread.cpp | 10 +-
global.h | 10 +-
images/splash.png | Bin 9306 -> 9150 bytes
mainwindow.cpp | 7 +
mainwindow.h | 8 +-
mainwindow_constr.cpp | 10 +-
options_dialog.cpp | 234 ++---
options_dialog.h | 7 +-
print_to_bdf.cpp | 2 -
print_to_edf.cpp | 2 -
read_write_settings.cpp | 100 +-
reduce_signals.cpp | 130 ++-
statistics_dialog.cpp | 119 ++-
statistics_dialog.h | 6 +-
version.txt | 18 +-
viewcurve.cpp | 62 +-
31 files changed, 1856 insertions(+), 750 deletions(-)
diff --git a/README.txt b/README.txt
index 2a72c23..9e36472 100644
--- a/README.txt
+++ b/README.txt
@@ -95,7 +95,7 @@ openSUSE: sudo zypper install -t pattern devel_basis
# #
# This will not mess with your system libraries. The new compiled libraries will be stored #
# #
-# in a new and separate directory: /usr/local/Qt-5.9.1 #
+# in a new and separate directory: /usr/local/Qt-5.9.2 #
# #
# It will not interfere with other Qt programs. #
# #
@@ -105,12 +105,14 @@ mkdir Qt5-source
cd Qt5-source
-wget http://ftp1.nluug.nl/languages/qt/official_releases/qt/5.9/5.9.1/single/qt-everywhere-opensource-src-5.9.1.tar.xz
+wget http://ftp1.nluug.nl/languages/qt/official_releases/qt/5.9/5.9.2/single/qt-everywhere-opensource-src-5.9.2.tar.xz
here is a list of download mirrors: https://download.qt.io/static/mirrorlist/
-The Qt source package you are going to need is: qt-everywhere-opensource-src-5.9.1.tar.xz
+The Qt source package you are going to need is: qt-everywhere-opensource-src-5.9.2.tar.xz
-tar -xvf qt-everywhere-opensource-src-5.9.1.tar.xz
+tar -xvf qt-everywhere-opensource-src-5.9.2.tar.xz
+
+cd qt-everywhere-opensource-src-5.9.2
./configure -v -release -opensource -confirm-license -c++std c++11 -static -accessibility -fontconfig -skip qtdeclarative -skip qtconnectivity -skip qtmultimedia -no-qml-debug -qt-zlib -no-mtdev -no-journald -qt-libpng -qt-libjpeg -system-freetype -qt-harfbuzz -no-openssl -no-libproxy -no-glib -nomake examples -nomake tests -no-compile-examples -cups -no-evdev -no-dbus -no-eglfs -qreal double -no-opengl -skip qtlocation -skip qtsensors -skip qtwayland -skip qtgamepad -skip qtserialbus
@@ -124,7 +126,7 @@ sudo make install
Now go to the directory that contains the EDFbrowser sourcecode and enter the following commands:
-/usr/local/Qt-5.9.1/bin/qmake
+/usr/local/Qt-5.9.2/bin/qmake
make -j8
diff --git a/annotations_dock.cpp b/annotations_dock.cpp
index 2439f3e..cfd8dd2 100644
--- a/annotations_dock.cpp
+++ b/annotations_dock.cpp
@@ -100,6 +100,8 @@ UI_Annotationswindow::UI_Annotationswindow(int file_number, QWidget *w_parent)
hide_all_BS_triggers_act = new QAction("Hide all Biosemi triggers", list);
unhide_all_NK_triggers_act = new QAction("Unhide all Nihon Kohden triggers", list);
unhide_all_BS_triggers_act = new QAction("Unhide all Biosemi triggers", list);
+ filt_ival_time_act = new QAction("Filter Interval Time", list);
+ show_stats_act = new QAction("Heart Rate Variability", list);
list->setContextMenuPolicy(Qt::ActionsContextMenu);
list->insertAction(NULL, show_between_act);
@@ -113,6 +115,8 @@ UI_Annotationswindow::UI_Annotationswindow(int file_number, QWidget *w_parent)
list->insertAction(NULL, unhide_all_NK_triggers_act);
list->insertAction(NULL, hide_all_BS_triggers_act);
list->insertAction(NULL, unhide_all_BS_triggers_act);
+ list->insertAction(NULL, filt_ival_time_act);
+ list->insertAction(NULL, show_stats_act);
h_layout = new QHBoxLayout;
h_layout->addWidget(checkbox1);
@@ -144,10 +148,76 @@ UI_Annotationswindow::UI_Annotationswindow(int file_number, QWidget *w_parent)
QObject::connect(hide_all_BS_triggers_act, SIGNAL(triggered(bool)), this, SLOT(hide_all_BS_triggers(bool)));
QObject::connect(unhide_all_NK_triggers_act, SIGNAL(triggered(bool)), this, SLOT(unhide_all_NK_triggers(bool)));
QObject::connect(unhide_all_BS_triggers_act, SIGNAL(triggered(bool)), this, SLOT(unhide_all_BS_triggers(bool)));
+ QObject::connect(filt_ival_time_act, SIGNAL(triggered(bool)), this, SLOT(filt_ival_time(bool)));
+ QObject::connect(show_stats_act, SIGNAL(triggered(bool)), this, SLOT(show_stats(bool)));
QObject::connect(lineedit1, SIGNAL(textEdited(const QString)), this, SLOT(filter_edited(const QString)));
}
+void UI_Annotationswindow::show_stats(bool)
+{
+ struct annotation_list *annot_list;
+
+ struct annotationblock *annot;
+
+ if(mainwindow->files_open < 1)
+ {
+ 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;
+ }
+
+ annot_list = &mainwindow->edfheaderlist[file_num]->annot_list;
+
+ annot = edfplus_annotation_get_item_visible_only(annot_list, list->currentRow());
+
+ UI_StatisticWindow stats_wndw(NULL, 0LL, annot_list, annot);
+}
+
+
+void UI_Annotationswindow::filt_ival_time(bool)
+{
+ struct annotation_list *annot_list;
+
+ struct annotationblock *annot;
+
+ if(mainwindow->files_open < 1)
+ {
+ 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;
+ }
+
+ annot_list = &mainwindow->edfheaderlist[file_num]->annot_list;
+
+ annot = edfplus_annotation_get_item_visible_only(annot_list, list->currentRow());
+
+ UI_AnnotFilterWindow filter_wndw(mainwindow, annot, mainwindow->annot_filter, file_num);
+}
+
+
void UI_Annotationswindow::hide_all_NK_triggers(bool)
{
int i, sz;
@@ -270,7 +340,7 @@ void UI_Annotationswindow::unhide_all_BS_triggers(bool)
void UI_Annotationswindow::filter_edited(const QString text)
{
- int i, n, len, sz;
+ int i, j, n, len, sz;
char filter_str[32];
@@ -308,7 +378,7 @@ void UI_Annotationswindow::filter_edited(const QString text)
len = strlen(filter_str);
- if(invert_filter == 0)
+ if(invert_filter == 0)
{
for(i=0; i<sz; i++)
{
@@ -321,9 +391,9 @@ void UI_Annotationswindow::filter_edited(const QString text)
n = strlen(annot->annotation) - len + 1;
- for(i=0; i<n; i++)
+ for(j=0; j<n; j++)
{
- if(!(strncmp(filter_str, annot->annotation + i, len)))
+ if(!(strncmp(filter_str, annot->annotation + j, len)))
{
annot->hided_in_list = 0;
@@ -348,9 +418,9 @@ void UI_Annotationswindow::filter_edited(const QString text)
n = strlen(annot->annotation) - len + 1;
- for(i=0; i<n; i++)
+ for(j=0; j<n; j++)
{
- if(!(strncmp(filter_str, annot->annotation + i, len)))
+ if(!(strncmp(filter_str, annot->annotation + j, len)))
{
annot->hided_in_list = 1;
@@ -468,12 +538,14 @@ void UI_Annotationswindow::hide_annot(bool)
if(n >= sz) return;
- annot = edfplus_annotation_get_item(annot_list, n);
+ annot = edfplus_annotation_get_item_visible_only(annot_list, n);
annot->hided_in_list = 1;
annot->hided = 1;
+ updateList();
+
mainwindow->maincurve->update();
}
@@ -503,6 +575,8 @@ void UI_Annotationswindow::unhide_annot(bool)
annot->hided = 0;
+ updateList();
+
mainwindow->maincurve->update();
}
@@ -530,7 +604,7 @@ void UI_Annotationswindow::hide_same_annots(bool)
if(n >= sz) return;
- annot = edfplus_annotation_get_item(annot_list, n);
+ annot = edfplus_annotation_get_item_visible_only(annot_list, n);
strcpy(str1, annot->annotation);
@@ -556,6 +630,8 @@ void UI_Annotationswindow::hide_same_annots(bool)
}
}
+ updateList();
+
mainwindow->maincurve->update();
}
@@ -579,7 +655,7 @@ void UI_Annotationswindow::unhide_same_annots(bool)
if(n >= sz) return;
- annot = edfplus_annotation_get_item(annot_list, n);
+ annot = edfplus_annotation_get_item_visible_only(annot_list, n);
strcpy(str1, annot->annotation);
@@ -605,6 +681,8 @@ void UI_Annotationswindow::unhide_same_annots(bool)
}
}
+ updateList();
+
mainwindow->maincurve->update();
}
@@ -628,13 +706,15 @@ void UI_Annotationswindow::unhide_all_annots(bool)
annot->hided_in_list = 0;
}
+ updateList();
+
mainwindow->maincurve->update();
}
void UI_Annotationswindow::average_annot(bool)
{
- if(mainwindow->files_open != 1)
+ if(mainwindow->files_open < 1)
{
return;
}
@@ -660,7 +740,7 @@ void UI_Annotationswindow::average_annot(bool)
return;
}
- UI_AveragerWindow average_wndw(mainwindow, list->currentRow());
+ UI_AveragerWindow average_wndw(mainwindow, list->currentRow(), file_num);
}
diff --git a/annotations_dock.h b/annotations_dock.h
index 3954332..d72d09a 100644
--- a/annotations_dock.h
+++ b/annotations_dock.h
@@ -62,6 +62,8 @@
#include "utils.h"
#include "averager_dialog.h"
#include "edf_annot_list.h"
+#include "annotlist_filter_dialog.h"
+#include "statistics_dialog.h"
class UI_Mainwindow;
@@ -116,7 +118,9 @@ private:
*hide_all_NK_triggers_act,
*hide_all_BS_triggers_act,
*unhide_all_NK_triggers_act,
- *unhide_all_BS_triggers_act;
+ *unhide_all_BS_triggers_act,
+ *filt_ival_time_act,
+ *show_stats_act;
private slots:
@@ -136,6 +140,8 @@ private slots:
void hide_all_BS_triggers(bool);
void unhide_all_NK_triggers(bool);
void unhide_all_BS_triggers(bool);
+ void filt_ival_time(bool);
+ void show_stats(bool);
};
diff --git a/annotlist_filter_dialog.cpp b/annotlist_filter_dialog.cpp
new file mode 100644
index 0000000..00eaecf
--- /dev/null
+++ b/annotlist_filter_dialog.cpp
@@ -0,0 +1,373 @@
+/*
+***************************************************************************
+*
+* Author: Teunis van Beelen
+*
+* Copyright (C) 2017 Teunis van Beelen
+*
+* Email: teuniz at 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, either version 3 of the License, or
+* (at your option) any later version.
+*
+* 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, see <http://www.gnu.org/licenses/>.
+*
+***************************************************************************
+*/
+
+
+
+
+#include "annotlist_filter_dialog.h"
+
+
+
+UI_AnnotFilterWindow::UI_AnnotFilterWindow(QWidget *w_parent, struct annotationblock *annot, struct annot_filter_struct *filter_p, int file_n)
+{
+ mainwindow = (UI_Mainwindow *)w_parent;
+
+ annot_filter_dialog = new QDialog(w_parent);
+
+ file_num = file_n;
+
+ annot_list = &mainwindow->edfheaderlist[file_num]->annot_list;
+
+ filter_params = filter_p;
+
+ annots_dock = mainwindow->annotations_dock[file_num];
+
+ annot_filter_dialog->setMinimumSize(430, 400);
+ annot_filter_dialog->setMaximumSize(430, 400);
+ annot_filter_dialog->setWindowTitle("Filter annotations");
+ annot_filter_dialog->setModal(true);
+ annot_filter_dialog->setAttribute(Qt::WA_DeleteOnClose, true);
+
+ annotLabel = new QLabel(annot_filter_dialog);
+ annotLabel->setGeometry(20, 20, 100, 25);
+ annotLabel->setText("Filter annotation:");
+ annotLabel->setToolTip("Label of the annotation to be filtered");
+
+ annotNameLabel = new QLabel(annot_filter_dialog);
+ annotNameLabel->setGeometry(160, 20, 200, 25);
+ annotNameLabel->setToolTip("Label of the annotation to be filtered");
+
+ t1Label = new QLabel(annot_filter_dialog);
+ t1Label->setGeometry(20, 65, 120, 25);
+ t1Label->setText("Minimum interval:");
+ t1Label->setToolTip("Minimum interval between two consegutive annotations");
+
+ t1_spinbox = new QSpinBox(annot_filter_dialog);
+ t1_spinbox->setGeometry(160, 65, 100, 25);
+ t1_spinbox->setRange(1, 500000);
+ t1_spinbox->setSuffix(" mSec");
+ t1_spinbox->setValue(filter_params->tmin);
+ t1_spinbox->setToolTip("Minimum interval between two consegutive annotations");
+
+ t2Label = new QLabel(annot_filter_dialog);
+ t2Label->setGeometry(20, 110, 120, 25);
+ t2Label->setText("Maximum interval:");
+ t2Label->setToolTip("Maximum interval between two consegutive annotations");
+
+ t2_spinbox = new QSpinBox(annot_filter_dialog);
+ t2_spinbox->setGeometry(160, 110, 100, 25);
+ t2_spinbox->setRange(1, 500000);
+ t2_spinbox->setSuffix(" mSec");
+ t2_spinbox->setValue(filter_params->tmax);
+ t2_spinbox->setToolTip("Maximum interval between two consegutive annotations");
+
+ invert_checkbox = new QCheckBox("Invert ", annot_filter_dialog);
+ invert_checkbox->setGeometry(20, 155, 200, 25);
+ invert_checkbox->setTristate(false);
+ invert_checkbox->setToolTip("Invert the filter result");
+ if(filter_params->invert)
+ {
+ invert_checkbox->setCheckState(Qt::Checked);
+ }
+ else
+ {
+ invert_checkbox->setCheckState(Qt::Unchecked);
+ }
+
+ hide_other_checkbox = new QCheckBox("Hide other annotations ", annot_filter_dialog);
+ hide_other_checkbox->setGeometry(20, 200, 200, 25);
+ hide_other_checkbox->setTristate(false);
+ hide_other_checkbox->setToolTip("Hide annotations with a different label");
+ if(filter_params->hide_other)
+ {
+ hide_other_checkbox->setCheckState(Qt::Checked);
+ }
+ else
+ {
+ hide_other_checkbox->setCheckState(Qt::Unchecked);
+ }
+
+ hide_in_list_checkbox = new QCheckBox("Filter list only ", annot_filter_dialog);
+ hide_in_list_checkbox->setGeometry(20, 245, 200, 25);
+ hide_in_list_checkbox->setTristate(false);
+ hide_in_list_checkbox->setToolTip("Filter affects the annotationlist only, not the annotation markers in the signal window");
+ if(filter_params->hide_in_list_only)
+ {
+ hide_in_list_checkbox->setCheckState(Qt::Checked);
+ }
+ else
+ {
+ hide_in_list_checkbox->setCheckState(Qt::Unchecked);
+ }
+
+ ApplyButton = new QPushButton(annot_filter_dialog);
+ ApplyButton->setGeometry(20, 355, 100, 25);
+ ApplyButton->setText("Apply");
+
+ UndoButton = new QPushButton(annot_filter_dialog);
+ UndoButton->setGeometry(165, 355, 100, 25);
+ UndoButton->setText("Undo");
+
+ CloseButton = new QPushButton(annot_filter_dialog);
+ CloseButton->setGeometry(310, 355, 100, 25);
+ CloseButton->setText("Close");
+
+ sel_annot_ptr = annot;
+ strcpy(sel_annot_str, sel_annot_ptr->annotation);
+ remove_leading_spaces(sel_annot_str);
+ remove_trailing_spaces(sel_annot_str);
+
+ annotNameLabel->setText(sel_annot_str);
+
+ QObject::connect(CloseButton, SIGNAL(clicked()), annot_filter_dialog, SLOT(close()));
+ QObject::connect(ApplyButton, SIGNAL(clicked()), this, SLOT(apply_filter()));
+ QObject::connect(UndoButton, SIGNAL(clicked()), this, SLOT(undo_filter()));
+
+ annot_filter_dialog->exec();
+}
+
+
+void UI_AnnotFilterWindow::undo_filter()
+{
+ int i, sz;
+
+ struct annotationblock *annot;
+
+ sz = edfplus_annotation_size(annot_list);
+
+ for(i=0; i<sz; i++)
+ {
+ annot = edfplus_annotation_get_item(annot_list, i);
+
+ annot->hided_in_list = 0;
+
+ annot->hided = 0;
+ }
+
+ annots_dock->updateList();
+
+ mainwindow->maincurve->update();
+}
+
+
+void UI_AnnotFilterWindow::apply_filter()
+{
+ int i,
+ sz,
+ is_set=0,
+ t1_val,
+ t2_val;
+
+ long long t1,
+ t_diff,
+ t_min,
+ t_max;
+
+ char annot_str[MAX_ANNOTATION_LEN + 1];
+
+ struct annotationblock *annot, *annot_before;
+
+ if(invert_checkbox->checkState() == Qt::Checked)
+ {
+ filter_params->invert = 1;
+ }
+ else
+ {
+ filter_params->invert = 0;
+ }
+
+ if(hide_in_list_checkbox->checkState() == Qt::Checked)
+ {
+ filter_params->hide_in_list_only = 1;
+ }
+ else
+ {
+ filter_params->hide_in_list_only = 0;
+ }
+
+ if(hide_other_checkbox->checkState() == Qt::Checked)
+ {
+ filter_params->hide_other = 1;
+ }
+ else
+ {
+ filter_params->hide_other = 0;
+ }
+
+ t1_val = t1_spinbox->value();
+
+ t2_val = t2_spinbox->value();
+
+ if(t1_val >= t2_val)
+ {
+ QMessageBox messagewindow(QMessageBox::Critical, "Error", "Minimum interval must be less than\n"
+ "maximum interval");
+ messagewindow.exec();
+ return;
+ }
+
+ filter_params->tmin = t1_val;
+
+ filter_params->tmax = t2_val;
+
+ t_min = filter_params->tmin * (TIME_DIMENSION / 1000LL);
+
+ t_max = filter_params->tmax * (TIME_DIMENSION / 1000LL);
+
+ sz = edfplus_annotation_size(annot_list);
+
+ for(i=0; i<sz; i++)
+ {
+ annot = edfplus_annotation_get_item(annot_list, i);
+
+ strcpy(annot_str, annot->annotation);
+ remove_leading_spaces(sel_annot_str);
+ remove_trailing_spaces(annot_str);
+
+ if(strcmp(annot_str, sel_annot_str))
+ {
+ if(filter_params->hide_other)
+ {
+ annot->hided_in_list = 1;
+
+ if(filter_params->hide_in_list_only)
+ {
+ annot->hided = 0;
+ }
+ else
+ {
+ annot->hided = 1;
+ }
+ }
+ else
+ {
+ annot->hided_in_list = 0;
+
+ annot->hided = 0;
+ }
+
+ continue;
+ }
+
+ if(is_set == 0)
+ {
+ is_set = 1;
+
+ t1 = annot->onset;
+
+ annot->hided_in_list = 1;
+
+ if(filter_params->hide_in_list_only)
+ {
+ annot->hided = 0;
+ }
+ else
+ {
+ annot->hided = 1;
+ }
+
+ annot_before = annot;
+
+ continue;
+ }
+
+ t_diff = annot->onset - t1;
+
+ t1 = annot->onset;
+
+ if(filter_params->invert)
+ {
+ if((t_diff < t_min) || (t_diff > t_max))
+ {
+ annot->hided_in_list = 1;
+
+ if(filter_params->hide_in_list_only)
+ {
+ annot->hided = 0;
+ }
+ else
+ {
+ annot->hided = 1;
+ }
+ }
+ else
+ {
+ annot->hided_in_list = 0;
+
+ annot->hided = 0;
+
+ annot_before->hided_in_list = 0;
+
+ annot_before->hided = 0;
+ }
+ }
+ else
+ {
+ if((t_diff >= t_min) && (t_diff <= t_max))
+ {
+ annot->hided_in_list = 1;
+
+ if(filter_params->hide_in_list_only)
+ {
+ annot->hided = 0;
+ }
+ else
+ {
+ annot->hided = 1;
+ }
+ }
+ else
+ {
+ annot->hided_in_list = 0;
+
+ annot->hided = 0;
+
+ annot_before->hided_in_list = 0;
+
+ annot_before->hided = 0;
+ }
+ }
+
+ annot_before = annot;
+ }
+
+ annots_dock->updateList();
+
+ mainwindow->maincurve->update();
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/averager_dialog.h b/annotlist_filter_dialog.h
similarity index 60%
copy from averager_dialog.h
copy to annotlist_filter_dialog.h
index 6f6a4fe..726a9ae 100644
--- a/averager_dialog.h
+++ b/annotlist_filter_dialog.h
@@ -3,7 +3,7 @@
*
* Author: Teunis van Beelen
*
-* Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017 Teunis van Beelen
+* Copyright (C) 2017 Teunis van Beelen
*
* Email: teuniz at gmail.com
*
@@ -28,25 +28,21 @@
-#ifndef AVERAGER_FORM1_H
-#define AVERAGER_FORM1_H
+#ifndef ANNOTFILTER_FORM1_H
+#define ANNOTFILTER_FORM1_H
#include <QtGlobal>
#include <QApplication>
#include <QObject>
-#include <QListWidget>
-#include <QListWidgetItem>
#include <QDialog>
#include <QPushButton>
#include <QLabel>
-#include <QProgressDialog>
-#include <QComboBox>
-#include <QList>
-#include <QTime>
-#include <QTimeEdit>
-#include <QDoubleSpinBox>
+#include <QMessageBox>
+#include <QSpinBox>
+#include <QCheckBox>
+#include <QToolTip>
#include <stdio.h>
#include <stdlib.h>
@@ -55,71 +51,78 @@
#include "global.h"
#include "mainwindow.h"
#include "edf_annot_list.h"
-#include "averager_curve_wnd.h"
#include "utils.h"
+#include "annotations_dock.h"
class UI_Mainwindow;
+class UI_Annotationswindow;
-class UI_AveragerWindow : public QObject
+
+class UI_AnnotFilterWindow : public QObject
{
Q_OBJECT
public:
- UI_AveragerWindow(QWidget *, int);
-
- ~UI_AveragerWindow();
+ UI_AnnotFilterWindow(QWidget *, struct annotationblock *, struct annot_filter_struct *, int);
UI_Mainwindow *mainwindow;
private:
-QDialog *averager_dialog;
+QDialog *annot_filter_dialog;
QLabel *annotLabel,
*annotNameLabel,
- *signalLabel,
- *ratioLabel,
- *bufsizeLabel,
- *time1Label,
- *time2Label;
+ *t1Label,
+ *t2Label;
QPushButton *CloseButton,
- *StartButton;
+ *ApplyButton,
+ *UndoButton;
QListWidget *list;
-QComboBox *ratioBox;
-
-QTimeEdit *timeEdit1,
- *timeEdit2;
+QSpinBox *t1_spinbox,
+ *t2_spinbox;
-QTime time1,
- time2;
+QCheckBox *hide_in_list_checkbox,
+ *hide_other_checkbox,
+ *invert_checkbox;
-QDoubleSpinBox *avg_periodspinbox;
+int file_num;
-char annot_str[MAX_ANNOTATION_LEN + 1];
+char sel_annot_str[MAX_ANNOTATION_LEN + 1];
-int signal_nr;
+struct annotation_list *annot_list;
-double *avgbuf;
+struct annotationblock *sel_annot_ptr;
+struct annot_filter_struct *filter_params;
-void process_avg(struct signalcompblock *);
+UI_Annotationswindow *annots_dock;
private slots:
-void startButtonClicked();
+void apply_filter();
+void undo_filter();
};
-#endif // AVERAGER_FORM1_H
+#endif // ANNOTFILTER_FORM1_H
+
+
+
+
+
+
+
+
diff --git a/averager_curve_wnd.cpp b/averager_curve_wnd.cpp
index d5db6b3..76f9ef0 100644
--- a/averager_curve_wnd.cpp
+++ b/averager_curve_wnd.cpp
@@ -41,7 +41,7 @@ UI_AverageCurveWindow::UI_AverageCurveWindow(struct signalcompblock *signal_comp
int acnt,
int trigger_position,
char *annotation,
- double avg__period)
+ int avg__period)
{
char str[1024];
@@ -464,7 +464,7 @@ void UI_AverageCurveWindow::export_edf(void)
}
edfwrite_annotation_latin1(edf_hdl,
- (avg_period * 10000.0) / (double)avg_trigger_position_ratio,
+ (avg_period * 10) / avg_trigger_position_ratio,
-1,
avg_annotation);
diff --git a/averager_curve_wnd.h b/averager_curve_wnd.h
index e2c01b7..dbd57cd 100644
--- a/averager_curve_wnd.h
+++ b/averager_curve_wnd.h
@@ -78,7 +78,7 @@ public:
int,
int,
char *,
- double);
+ int);
~UI_AverageCurveWindow();
@@ -95,13 +95,13 @@ private:
averagecurvedialognumber,
avg_cnt,
avg_trigger_position_ratio,
- flywheel_value;
+ flywheel_value,
+ avg_period;
double pagetime,
*avgbuf,
avg_max_value,
- avg_min_value,
- avg_period;
+ avg_min_value;
long long avg_samples_on_screen;
diff --git a/averager_dialog.cpp b/averager_dialog.cpp
index 14febea..8757b71 100644
--- a/averager_dialog.cpp
+++ b/averager_dialog.cpp
@@ -32,7 +32,7 @@
-UI_AveragerWindow::UI_AveragerWindow(QWidget *w_parent, int annot_nr)
+UI_AveragerWindow::UI_AveragerWindow(QWidget *w_parent, int annot_nr, int file_n)
{
int i;
@@ -42,6 +42,8 @@ UI_AveragerWindow::UI_AveragerWindow(QWidget *w_parent, int annot_nr)
mainwindow = (UI_Mainwindow *)w_parent;
+ file_num = file_n;
+
averager_dialog = new QDialog(w_parent);
averager_dialog->setMinimumSize(600, 400);
@@ -68,7 +70,7 @@ UI_AveragerWindow::UI_AveragerWindow(QWidget *w_parent, int annot_nr)
time1.setHMS(0, 0, 0, 0);
- recording_duration = (mainwindow->edfheaderlist[0]->datarecords * mainwindow->edfheaderlist[0]->long_data_record_duration) / TIME_DIMENSION;
+ recording_duration = (mainwindow->edfheaderlist[file_num]->datarecords * mainwindow->edfheaderlist[file_num]->long_data_record_duration) / TIME_DIMENSION;
time2.setHMS((recording_duration / 3600) % 24, (recording_duration % 3600) / 60, recording_duration % 60, 0);
@@ -110,11 +112,10 @@ UI_AveragerWindow::UI_AveragerWindow(QWidget *w_parent, int annot_nr)
bufsizeLabel->setGeometry(20, 250, 100, 25);
bufsizeLabel->setText("Average period:");
- avg_periodspinbox = new QDoubleSpinBox(averager_dialog);
+ avg_periodspinbox = new QSpinBox(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->setRange(10, 300000);
+ avg_periodspinbox->setSuffix(" mSec");
avg_periodspinbox->setValue(mainwindow->average_period);
CloseButton = new QPushButton(averager_dialog);
@@ -139,9 +140,10 @@ UI_AveragerWindow::UI_AveragerWindow(QWidget *w_parent, int annot_nr)
list->setCurrentRow(0, QItemSelectionModel::Select);
- annot_ptr = edfplus_annotation_get_item(&mainwindow->edfheaderlist[0]->annot_list, annot_nr);
+ annot_ptr = edfplus_annotation_get_item_visible_only(&mainwindow->edfheaderlist[file_num]->annot_list, annot_nr);
strcpy(annot_str, annot_ptr->annotation);
+ remove_leading_spaces(annot_str);
remove_trailing_spaces(annot_str);
annotNameLabel->setText(annot_str);
@@ -227,29 +229,30 @@ void UI_AveragerWindow::startButtonClicked()
break;
}
- backup_viewtime = mainwindow->edfheaderlist[0]->viewtime;
+ backup_viewtime = mainwindow->edfheaderlist[file_num]->viewtime;
backup_timescale = mainwindow->pagetime;
- mainwindow->pagetime = avg_periodspinbox->value() * TIME_DIMENSION;
+ mainwindow->pagetime = avg_periodspinbox->value() * (TIME_DIMENSION / 1000LL);
mainwindow->setup_viewbuf();
mainwindow->signal_averaging_active = 1;
- n = edfplus_annotation_size(&mainwindow->edfheaderlist[0]->annot_list);
+ n = edfplus_annotation_size(&mainwindow->edfheaderlist[file_num]->annot_list);
avg_cnt = 0;
for(i=0; i<n; i++)
{
- annot_ptr = edfplus_annotation_get_item(&mainwindow->edfheaderlist[0]->annot_list, i);
+ annot_ptr = edfplus_annotation_get_item(&mainwindow->edfheaderlist[file_num]->annot_list, i);
- if(((annot_ptr->onset - mainwindow->edfheaderlist[0]->starttime_offset) >= l_time1)
- && ((annot_ptr->onset - mainwindow->edfheaderlist[0]->starttime_offset) <= l_time2))
+ if(((annot_ptr->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) >= l_time1)
+ && ((annot_ptr->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) <= l_time2))
{
strcpy(str, annot_ptr->annotation);
+ remove_leading_spaces(str);
remove_trailing_spaces(str);
if(!strcmp(str, annot_str))
@@ -287,7 +290,7 @@ void UI_AveragerWindow::startButtonClicked()
QMessageBox messagewindow(QMessageBox::Critical, "Error", "Too many \"Average\" windows are open.\nClose some first.");
messagewindow.exec();
- mainwindow->edfheaderlist[0]->viewtime = backup_viewtime;
+ mainwindow->edfheaderlist[file_num]->viewtime = backup_viewtime;
mainwindow->pagetime = backup_timescale;
mainwindow->signal_averaging_active = 0;
mainwindow->setup_viewbuf();
@@ -302,7 +305,7 @@ void UI_AveragerWindow::startButtonClicked()
QMessageBox messagewindow(QMessageBox::Critical, "Error", "Too many samples in buf.");
messagewindow.exec();
- mainwindow->edfheaderlist[0]->viewtime = backup_viewtime;
+ mainwindow->edfheaderlist[file_num]->viewtime = backup_viewtime;
mainwindow->pagetime = backup_timescale;
mainwindow->signal_averaging_active = 0;
mainwindow->setup_viewbuf();
@@ -318,7 +321,7 @@ void UI_AveragerWindow::startButtonClicked()
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->edfheaderlist[file_num]->viewtime = backup_viewtime;
mainwindow->pagetime = backup_timescale;
mainwindow->signal_averaging_active = 0;
mainwindow->setup_viewbuf();
@@ -326,19 +329,25 @@ void UI_AveragerWindow::startButtonClicked()
return;
}
- n = edfplus_annotation_size(&mainwindow->edfheaderlist[0]->annot_list);
+ n = edfplus_annotation_size(&mainwindow->edfheaderlist[file_num]->annot_list);
avg_cnt = 0;
for(i=0; i<n; i++)
{
- annot_ptr = edfplus_annotation_get_item(&mainwindow->edfheaderlist[0]->annot_list, i);
+ annot_ptr = edfplus_annotation_get_item(&mainwindow->edfheaderlist[file_num]->annot_list, i);
+
+ if(annot_ptr->hided_in_list)
+ {
+ continue;
+ }
- if(((annot_ptr->onset - mainwindow->edfheaderlist[0]->starttime_offset) >= l_time1)
- && ((annot_ptr->onset - mainwindow->edfheaderlist[0]->starttime_offset) <= l_time2))
+ if(((annot_ptr->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) >= l_time1)
+ && ((annot_ptr->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) <= l_time2))
{
strcpy(str, annot_ptr->annotation);
+ remove_leading_spaces(str);
remove_trailing_spaces(str);
if(!strcmp(str, annot_str))
@@ -353,7 +362,7 @@ void UI_AveragerWindow::startButtonClicked()
{
free(avgbuf);
- mainwindow->edfheaderlist[0]->viewtime = backup_viewtime;
+ mainwindow->edfheaderlist[file_num]->viewtime = backup_viewtime;
mainwindow->pagetime = backup_timescale;
@@ -365,11 +374,11 @@ void UI_AveragerWindow::startButtonClicked()
}
}
- mainwindow->edfheaderlist[0]->viewtime = annot_ptr->onset;
+ mainwindow->edfheaderlist[file_num]->viewtime = annot_ptr->onset;
- mainwindow->edfheaderlist[0]->viewtime -= mainwindow->edfheaderlist[0]->starttime_offset;
+ mainwindow->edfheaderlist[file_num]->viewtime -= mainwindow->edfheaderlist[file_num]->starttime_offset;
- mainwindow->edfheaderlist[0]->viewtime -= (mainwindow->pagetime / trigger_position_ratio);
+ mainwindow->edfheaderlist[file_num]->viewtime -= (mainwindow->pagetime / trigger_position_ratio);
mainwindow->setup_viewbuf();
@@ -395,7 +404,7 @@ void UI_AveragerWindow::startButtonClicked()
free(avgbuf);
- mainwindow->edfheaderlist[0]->viewtime = backup_viewtime;
+ mainwindow->edfheaderlist[file_num]->viewtime = backup_viewtime;
mainwindow->pagetime = backup_timescale;
@@ -446,7 +455,7 @@ void UI_AveragerWindow::startButtonClicked()
}
}
- mainwindow->edfheaderlist[0]->viewtime = backup_viewtime;
+ mainwindow->edfheaderlist[file_num]->viewtime = backup_viewtime;
mainwindow->pagetime = backup_timescale;
diff --git a/averager_dialog.h b/averager_dialog.h
index 6f6a4fe..c2cbfbd 100644
--- a/averager_dialog.h
+++ b/averager_dialog.h
@@ -46,7 +46,7 @@
#include <QList>
#include <QTime>
#include <QTimeEdit>
-#include <QDoubleSpinBox>
+#include <QSpinBox>
#include <stdio.h>
#include <stdlib.h>
@@ -69,7 +69,7 @@ class UI_AveragerWindow : public QObject
Q_OBJECT
public:
- UI_AveragerWindow(QWidget *, int);
+ UI_AveragerWindow(QWidget *, int, int);
~UI_AveragerWindow();
@@ -101,11 +101,12 @@ QTimeEdit *timeEdit1,
QTime time1,
time2;
-QDoubleSpinBox *avg_periodspinbox;
+QSpinBox *avg_periodspinbox;
char annot_str[MAX_ANNOTATION_LEN + 1];
-int signal_nr;
+int signal_nr,
+ file_num;
double *avgbuf;
diff --git a/doc/manual.html b/doc/manual.html
index 86bf9a0..f0583c3 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -7,7 +7,7 @@
<meta name="description" content="EDFbrowser manual">
</head><body>
-<h1>EDFbrowser 1.60 manual</h1>
+<h1>EDFbrowser 1.61 manual</h1>
<p><br></p>
@@ -28,6 +28,7 @@
<li><a href="#Organize_signals">Organize signals</a></li>
<li><a href="#Navigation">Navigation</a></li>
<li><a href="#Annotations">Annotations</a></li>
+ <li><a href="#Annotations_Filter">Annotations Filter</a></li>
<li><a href="#Filters">Filters</a></li>
<li><a href="#Adjust_filters">Adjust filters</a></li>
<li><a href="#Powerspectrum">Powerspectrum</a></li>
@@ -49,6 +50,7 @@
<li><a href="#Header_editor">Header editor</a></li>
<li><a href="#EDFBDF_to_ASCII_format_converter">EDF(+)/BDF(+) to ASCII format converter</a></li>
<li><a href="#Reduce_signals">Reduce signals, duration and/or samplerate</a></li>
+ <li><a href="#Export_filtered_signals">Export filtered signals</a></li>
<li><a href="#Export_annotations">Export annotations/events</a></li>
<li><a href="#Import_annotations">Import annotations/events</a></li>
<li><a href="#Z_EEG">Z-EEG</a></li>
@@ -343,6 +345,21 @@
<p><br><br></p>
+<h3><a name="Annotations_Filter">Annotations Filter</a></h3>
+
+<p>
+ The annotations list can be filtered based on the maximum and minimum interval time<br>
+ between two consegutive annotations with the same name/label.<br>
+ Right-click on the annotations list and select "Filter Interval Time".<br>
+ A dialog will appear where you can set the filter parameters.<br>
+</p>
+
+<p><br></p>
+
+<p><a href="#Table_of_Contents">Table of Contents</a></p>
+
+<p><br><br></p>
+
<h3><a name="Filters">Filters</a></h3>
<p>
@@ -531,6 +548,8 @@
- Mean, the average of the RR-intervals.<br>
- SDNN, the standard deviation of RR-intervals.<br>
- RMSSD, the square root of the mean squared difference of successive RR's.<br>
+ - NN20, the number of pairs of successive RR's that differ by more than 20 ms.<br>
+ - pNN20, the proportion of NN20 divided by total number of RR's as a percentage.<br>
- NN50, the number of pairs of successive RR's that differ by more than 50 ms.<br>
- pNN50, the proportion of NN50 divided by total number of RR's as a percentage.<br>
<br>
@@ -877,6 +896,19 @@
<p><br><br></p>
+<h3><a name="Export_filtered_signals">Export filtered signals</a></h3>
+
+<p>
+ This tool can be used to export the signals which are visible on the screen to a new EDF/BDF file<br>
+ including any applied filters and or derivations.
+</p>
+
+<p><br></p>
+
+<p><a href="#Table_of_Contents">Table of Contents</a></p>
+
+<p><br><br></p>
+
<h3><a name="Export_annotations">Export annotations/events</a></h3>
<p>
diff --git a/edf_annot_list.c b/edf_annot_list.c
index 73bbaf6..6768a31 100644
--- a/edf_annot_list.c
+++ b/edf_annot_list.c
@@ -102,6 +102,26 @@ int edfplus_annotation_size(struct annotation_list *list)
}
+int edfplus_annotation_cnt(struct annotation_list *list, struct annotationblock *annot)
+{
+ int i, n=0;
+
+ struct annotationblock *tmp_annot;
+
+ for(i=0; i<list->sz; i++)
+ {
+ tmp_annot = &list->items[list->idx[i]];
+
+ if(!strcmp(tmp_annot->annotation, annot->annotation))
+ {
+ if(!tmp_annot->hided_in_list) n++;
+ }
+ }
+
+ return n;
+}
+
+
void edfplus_annotation_empty_list(struct annotation_list *list)
{
if(list == NULL) return;
@@ -144,6 +164,31 @@ struct annotationblock * edfplus_annotation_get_item(struct annotation_list *lis
}
+struct annotationblock * edfplus_annotation_get_item_visible_only(struct annotation_list *list, int n)
+{
+ int i, j=0;
+
+ if(list == NULL) return NULL;
+
+ if((n >= list->sz) || (n < 0)) return NULL;
+
+ for(i=0; i<list->sz; i++)
+ {
+ if(list->items[list->idx[i]].hided_in_list)
+ {
+ continue;
+ }
+
+ if(n == j++)
+ {
+ return &list->items[list->idx[i]];
+ }
+ }
+
+ return NULL;
+}
+
+
int edfplus_annotation_get_index_at(struct annotation_list *list, long long onset, int start)
{
int i;
diff --git a/edf_annot_list.h b/edf_annot_list.h
index 68bed2b..aeff32f 100644
--- a/edf_annot_list.h
+++ b/edf_annot_list.h
@@ -67,9 +67,11 @@ struct annotation_list{
int edfplus_annotation_add_item(struct annotation_list *, struct annotationblock);
int edfplus_annotation_size(struct annotation_list *);
+int edfplus_annotation_cnt(struct annotation_list *, struct annotationblock *);
void edfplus_annotation_empty_list(struct annotation_list *);
void edfplus_annotation_remove_item(struct annotation_list *, int);
struct annotationblock * edfplus_annotation_get_item(struct annotation_list *, int);
+struct annotationblock * edfplus_annotation_get_item_visible_only(struct annotation_list *, int);
int edfplus_annotation_get_index(struct annotation_list *, struct annotationblock *);
void edfplus_annotation_sort(struct annotation_list *, void (*)(void));
struct annotation_list * edfplus_annotation_create_list_copy(struct annotation_list *);
diff --git a/edfbrowser.pro b/edfbrowser.pro
index 47e8737..d14b78a 100644
--- a/edfbrowser.pro
+++ b/edfbrowser.pro
@@ -127,6 +127,8 @@ HEADERS += biox2edf.h
HEADERS += edf_helper.h
HEADERS += plif_ecg_subtract_filter.h
HEADERS += plif_ecg_subtract_filter_dialog.h
+HEADERS += annotlist_filter_dialog.h
+HEADERS += export_filtered_signals.h
HEADERS += third_party/fidlib/fidlib.h
HEADERS += third_party/fidlib/fidmkf.h
@@ -219,6 +221,8 @@ SOURCES += biox2edf.cpp
SOURCES += edf_helper.c
SOURCES += plif_ecg_subtract_filter.c
SOURCES += plif_ecg_subtract_filter_dialog.cpp
+SOURCES += annotlist_filter_dialog.cpp
+SOURCES += export_filtered_signals.cpp
SOURCES += third_party/fidlib/fidlib.c
diff --git a/reduce_signals.cpp b/export_filtered_signals.cpp
similarity index 58%
copy from reduce_signals.cpp
copy to export_filtered_signals.cpp
index e9c0de0..dbe924c 100644
--- a/reduce_signals.cpp
+++ b/export_filtered_signals.cpp
@@ -3,7 +3,7 @@
*
* Author: Teunis van Beelen
*
-* Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Teunis van Beelen
+* Copyright (C) 2017 Teunis van Beelen
*
* Email: teuniz at gmail.com
*
@@ -27,11 +27,11 @@
-#include "reduce_signals.h"
+#include "export_filtered_signals.h"
-UI_ReduceSignalsWindow::UI_ReduceSignalsWindow(QWidget *w_parent)
+UI_ExportFilteredSignalsWindow::UI_ExportFilteredSignalsWindow(QWidget *w_parent)
{
mainwindow = (UI_Mainwindow *)w_parent;
@@ -41,10 +41,21 @@ UI_ReduceSignalsWindow::UI_ReduceSignalsWindow(QWidget *w_parent)
myobjectDialog->setMinimumSize(715, 578);
myobjectDialog->setMaximumSize(715, 578);
- myobjectDialog->setWindowTitle("Reduce signals and/or duration");
+ myobjectDialog->setWindowTitle("Export Filtered Signals");
myobjectDialog->setModal(true);
myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true);
+ tree = new QTreeView(myobjectDialog);
+ tree->setGeometry(20, 66, 405, 432);
+ tree->setHeaderHidden(true);
+ tree->setIndentation(30);
+ tree->setSelectionMode(QAbstractItemView::NoSelection);
+ tree->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ tree->setSortingEnabled(false);
+ tree->setDragDropMode(QAbstractItemView::NoDragDrop);
+
+ t_model = new QStandardItemModel(this);
+
label1 = new QLabel(myobjectDialog);
label1->setGeometry(20, 20, 685, 25);
@@ -66,10 +77,6 @@ UI_ReduceSignalsWindow::UI_ReduceSignalsWindow(QWidget *w_parent)
label5->setGeometry(605, 447, 100, 25);
label5->setEnabled(false);
- label6 = new QLabel(myobjectDialog);
- label6->setGeometry(445, 232, 140, 25);
- label6->setText("Anti-aliasing filter order");
-
radioButton1 = new QRadioButton("whole duration", myobjectDialog);
radioButton1->setGeometry(485, 299, 120, 25);
radioButton1->setChecked(true);
@@ -91,33 +98,13 @@ UI_ReduceSignalsWindow::UI_ReduceSignalsWindow(QWidget *w_parent)
spinBox2->setValue(2147483647);
spinBox2->setEnabled(false);
- spinBox3 = new QSpinBox(myobjectDialog);
- spinBox3->setGeometry(595, 170, 100, 25);
- spinBox3->setRange(1, 100000);
- spinBox3->setValue(1);
- spinBox3->setEnabled(false);
-
- spinBox4 = new QSpinBox(myobjectDialog);
- spinBox4->setGeometry(595, 232, 100, 25);
- spinBox4->setRange(1, REDUCER_MAX_AA_FILTERS + 1);
- spinBox4->setValue(REDUCER_MAX_AA_FILTERS);
- spinBox4->setEnabled(false);
-
- SignalsTablewidget = new QTableWidget(myobjectDialog);
- SignalsTablewidget->setGeometry(20, 66, 405, 432);
- SignalsTablewidget->setSelectionMode(QAbstractItemView::NoSelection);
- SignalsTablewidget->setColumnCount(2);
- SignalsTablewidget->setColumnWidth(0, 180);
- SignalsTablewidget->setColumnWidth(1, 180);
-
- QStringList horizontallabels;
- horizontallabels += "Label";
- horizontallabels += "Samplerate divider";
- SignalsTablewidget->setHorizontalHeaderLabels(horizontallabels);
-
pushButton1 = new QPushButton(myobjectDialog);
pushButton1->setGeometry(20, 528, 100, 25);
pushButton1->setText("Select File");
+ if(mainwindow->files_open < 2)
+ {
+ pushButton1->setEnabled(false);
+ }
pushButton2 = new QPushButton(myobjectDialog);
pushButton2->setGeometry(575, 528, 100, 25);
@@ -125,39 +112,16 @@ UI_ReduceSignalsWindow::UI_ReduceSignalsWindow(QWidget *w_parent)
pushButton3 = new QPushButton(myobjectDialog);
pushButton3->setGeometry(200, 528, 100, 25);
- pushButton3->setText("Reduce");
+ pushButton3->setText("Export");
pushButton3->setEnabled(false);
- pushButton4 = new QPushButton(myobjectDialog);
- pushButton4->setGeometry(445, 66, 140, 25);
- pushButton4->setText("Select all signals");
- pushButton4->setEnabled(false);
-
- pushButton5 = new QPushButton(myobjectDialog);
- pushButton5->setGeometry(445, 118, 140, 25);
- pushButton5->setText("Deselect all signals");
- pushButton5->setEnabled(false);
-
- pushButton6 = new QPushButton(myobjectDialog);
- pushButton6->setGeometry(445, 170, 140, 25);
- pushButton6->setText("Set samplerate divider:");
- pushButton6->setEnabled(false);
-
- helpButton = new QPushButton(myobjectDialog);
- helpButton->setGeometry(400, 528, 100, 25);
- helpButton->setText("Help");
-
- QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton()));
- QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close()));
- QObject::connect(pushButton3, SIGNAL(clicked()), this, SLOT(StartConversion()));
- QObject::connect(pushButton4, SIGNAL(clicked()), this, SLOT(Select_all_signals()));
- QObject::connect(pushButton5, SIGNAL(clicked()), this, SLOT(Deselect_all_signals()));
- QObject::connect(pushButton6, SIGNAL(clicked()), this, SLOT(Set_SRdivider_all_signals()));
- QObject::connect(spinBox1, SIGNAL(valueChanged(int)), this, SLOT(spinBox1changed(int)));
- QObject::connect(spinBox2, SIGNAL(valueChanged(int)), this, SLOT(spinBox2changed(int)));
- QObject::connect(radioButton1, SIGNAL(toggled(bool)), this, SLOT(radioButton1Toggled(bool)));
- QObject::connect(radioButton2, SIGNAL(toggled(bool)), this, SLOT(radioButton2Toggled(bool)));
- QObject::connect(helpButton, SIGNAL(clicked()), this, SLOT(helpbuttonpressed()));
+ QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton()));
+ QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close()));
+ QObject::connect(pushButton3, SIGNAL(clicked()), this, SLOT(StartExport()));
+ QObject::connect(spinBox1, SIGNAL(valueChanged(int)), this, SLOT(spinBox1changed(int)));
+ QObject::connect(spinBox2, SIGNAL(valueChanged(int)), this, SLOT(spinBox2changed(int)));
+ QObject::connect(radioButton1, SIGNAL(toggled(bool)), this, SLOT(radioButton1Toggled(bool)));
+ QObject::connect(radioButton2, SIGNAL(toggled(bool)), this, SLOT(radioButton2Toggled(bool)));
edfhdr = NULL;
inputfile = NULL;
@@ -166,11 +130,16 @@ UI_ReduceSignalsWindow::UI_ReduceSignalsWindow(QWidget *w_parent)
inputpath[0] = 0;
+ if(mainwindow->files_open == 1)
+ {
+ SelectFileButton();
+ }
+
myobjectDialog->exec();
}
-void UI_ReduceSignalsWindow::spinBox1changed(int value)
+void UI_ExportFilteredSignalsWindow::spinBox1changed(int value)
{
long long seconds,
milliSec;
@@ -179,9 +148,9 @@ void UI_ReduceSignalsWindow::spinBox1changed(int value)
char scratchpad[256];
- QObject::disconnect(spinBox2, SIGNAL(valueChanged(int)), this, SLOT(spinBox2changed(int)));
+ QObject::disconnect(spinBox2, SIGNAL(valueChanged(int)), this, SLOT(spinBox2changed(int)));
spinBox2->setMinimum(value);
- QObject::connect(spinBox2, SIGNAL(valueChanged(int)), this, SLOT(spinBox2changed(int)));
+ QObject::connect(spinBox2, SIGNAL(valueChanged(int)), this, SLOT(spinBox2changed(int)));
if(edfhdr == NULL)
{
@@ -208,7 +177,7 @@ void UI_ReduceSignalsWindow::spinBox1changed(int value)
}
-void UI_ReduceSignalsWindow::spinBox2changed(int value)
+void UI_ExportFilteredSignalsWindow::spinBox2changed(int value)
{
long long seconds,
milliSec;
@@ -217,9 +186,9 @@ void UI_ReduceSignalsWindow::spinBox2changed(int value)
char scratchpad[256];
- QObject::disconnect(spinBox1, SIGNAL(valueChanged(int)), this, SLOT(spinBox1changed(int)));
+ QObject::disconnect(spinBox1, SIGNAL(valueChanged(int)), this, SLOT(spinBox1changed(int)));
spinBox1->setMaximum(value);
- QObject::connect(spinBox1, SIGNAL(valueChanged(int)), this, SLOT(spinBox1changed(int)));
+ QObject::connect(spinBox1, SIGNAL(valueChanged(int)), this, SLOT(spinBox1changed(int)));
if(edfhdr == NULL)
{
@@ -242,7 +211,7 @@ void UI_ReduceSignalsWindow::spinBox2changed(int value)
}
-void UI_ReduceSignalsWindow::radioButton1Toggled(bool checked)
+void UI_ExportFilteredSignalsWindow::radioButton1Toggled(bool checked)
{
long long seconds,
milliSec;
@@ -293,7 +262,7 @@ void UI_ReduceSignalsWindow::radioButton1Toggled(bool checked)
}
-void UI_ReduceSignalsWindow::radioButton2Toggled(bool checked)
+void UI_ExportFilteredSignalsWindow::radioButton2Toggled(bool checked)
{
if(checked == true)
{
@@ -307,100 +276,19 @@ void UI_ReduceSignalsWindow::radioButton2Toggled(bool checked)
}
-void UI_ReduceSignalsWindow::Select_all_signals()
-{
- int i;
-
- if(edfhdr==NULL)
- {
- return;
- }
-
- for(i=0; i<edfhdr->edfsignals; i++)
- {
- if(!edfhdr->edfparam[i].annotation)
- {
- ((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->setCheckState(Qt::Checked);
- }
- }
-}
-
-
-
-void UI_ReduceSignalsWindow::Deselect_all_signals()
+void UI_ExportFilteredSignalsWindow::SelectFileButton()
{
- int i;
-
- if(edfhdr==NULL)
- {
- return;
- }
-
- for(i=0; i<edfhdr->edfsignals; i++)
- {
- if(!edfhdr->edfparam[i].annotation)
- {
- ((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->setCheckState(Qt::Unchecked);
- }
- }
-}
-
-
-
-void UI_ReduceSignalsWindow::Set_SRdivider_all_signals()
-{
- int i, j, sr, idx;
-
- sr = spinBox3->value();
-
- for(i=0; i<edfhdr->edfsignals; i++)
- {
- if(edfhdr->edfparam[i].annotation)
- {
- continue;
- }
-
- idx = 0;
-
- for(j=1; j<=edfhdr->edfparam[i].smp_per_record; j++)
- {
- if(!(edfhdr->edfparam[i].smp_per_record % j))
- {
- if(j == sr)
- {
- if(idx < ((QComboBox *)(SignalsTablewidget->cellWidget(i, 1)))->count())
- {
- ((QComboBox *)(SignalsTablewidget->cellWidget(i, 1)))->setCurrentIndex(idx);
- }
-
- break;
- }
-
- idx++;
- }
- }
- }
-}
-
-
-
-void UI_ReduceSignalsWindow::SelectFileButton()
-{
- int i, j,
- days;
+ int days;
long long seconds,
milliSec;
- char txt_string[2048],
- str[256];
+ char txt_string[2048];
label1->clear();
label4->clear();
label5->clear();
- SignalsTablewidget->setRowCount(0);
-
inputfile = NULL;
outputfile = NULL;
@@ -411,13 +299,8 @@ void UI_ReduceSignalsWindow::SelectFileButton()
file_num = -1;
pushButton3->setEnabled(false);
- pushButton4->setEnabled(false);
- pushButton5->setEnabled(false);
- pushButton6->setEnabled(false);
spinBox1->setEnabled(false);
spinBox2->setEnabled(false);
- spinBox3->setEnabled(false);
- spinBox4->setEnabled(false);
radioButton1->setChecked(true);
radioButton1->setEnabled(false);
radioButton2->setEnabled(false);
@@ -426,11 +309,20 @@ void UI_ReduceSignalsWindow::SelectFileButton()
label4->setEnabled(false);
label5->setEnabled(false);
- UI_activeFileChooserWindow afchooser(&file_num, mainwindow);
+ t_model->clear();
- if(file_num < 0)
+ if(mainwindow->files_open > 1)
{
- return;
+ UI_activeFileChooserWindow afchooser(&file_num, mainwindow);
+
+ if(file_num < 0)
+ {
+ return;
+ }
+ }
+ else
+ {
+ file_num = 0;
}
edfhdr = mainwindow->edfheaderlist[file_num];
@@ -474,54 +366,12 @@ void UI_ReduceSignalsWindow::SelectFileButton()
label1->setText(inputpath);
- SignalsTablewidget->setRowCount(edfhdr->edfsignals);
-
- for(i=0; i<edfhdr->edfsignals; i++)
- {
- SignalsTablewidget->setRowHeight(i, 25);
-
- SignalsTablewidget->setCellWidget(i, 0, new QCheckBox(edfhdr->edfparam[i].label));
- ((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->setTristate(false);
- ((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->setCheckState(Qt::Checked);
-
- if(edfhdr->edfparam[i].annotation)
- {
- ((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->setEnabled(false);
- }
-
- if(!(edfhdr->edfparam[i].annotation))
- {
- SignalsTablewidget->setCellWidget(i, 1, new QComboBox);
- ((QComboBox *)(SignalsTablewidget->cellWidget(i, 1)))->setEditable(false);
-
- for(j=1; j<=edfhdr->edfparam[i].smp_per_record; j++)
- {
- if(!(edfhdr->edfparam[i].smp_per_record % j))
- {
-// snprintf(str, 256, "%i (%f", j, ((double)(edfhdr->edfparam[i].smp_per_record / j)) / edfhdr->data_record_duration);
- snprintf(str, 256, "%i (", j);
- convert_to_metric_suffix(str + strlen(str),
- ((double)(edfhdr->edfparam[i].smp_per_record / j)) / edfhdr->data_record_duration,
- 3);
- remove_trailing_zeros(str);
- strcat(str, "Hz)");
- ((QComboBox *)(SignalsTablewidget->cellWidget(i, 1)))->addItem(str, QVariant(j));
- }
- }
- }
- }
-
pushButton3->setEnabled(true);
- pushButton4->setEnabled(true);
- pushButton5->setEnabled(true);
- pushButton6->setEnabled(true);
spinBox1->setValue(1);
spinBox2->setMaximum(edfhdr->datarecords);
spinBox2->setValue(edfhdr->datarecords);
spinBox1->setMaximum(edfhdr->datarecords);
- spinBox3->setEnabled(true);
- spinBox4->setEnabled(true);
radioButton1->setEnabled(true);
radioButton2->setEnabled(true);
@@ -541,15 +391,18 @@ void UI_ReduceSignalsWindow::SelectFileButton()
sprintf(txt_string, "%i:%02i:%02i.%03i", (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60), (int)milliSec);
}
label5->setText(txt_string);
-}
+ populate_tree_view();
+}
-void UI_ReduceSignalsWindow::StartConversion()
+void UI_ExportFilteredSignalsWindow::StartExport()
{
- int i, j, k, n,
+ int i, j, k, p,
+ type,
new_edfsignals,
datarecords=0,
+ start_datarecord=0,
annot_smp_per_record,
annot_recordsize,
timestamp_digits=0,
@@ -560,22 +413,29 @@ void UI_ReduceSignalsWindow::StartConversion()
len,
annots_per_datrec=0,
smplrt,
- tmp,
- val,
progress_steps,
datrecs_processed,
- annot_list_sz=0;
+ annot_list_sz=0,
+ smp_per_record[MAXSIGNALS],
+ signalslist[MAXSIGNALS],
+ digmin,
+ digmax,
+ value;
- char *readbuf=NULL,
- scratchpad[256];
+ char scratchpad[4096];
+
+ double *filtered_blockread_buf[MAXSIGNALS],
+ bitvalue,
+ phys_offset,
+ frequency,
+ frequency2;
long long new_starttime,
time_diff,
onset_diff,
taltime,
l_temp,
- endtime=0,
- l_tmp;
+ endtime=0;
struct date_time_struct dts;
@@ -584,13 +444,14 @@ void UI_ReduceSignalsWindow::StartConversion()
struct annotationblock *annot_ptr=NULL;
- union {
- unsigned int one;
- signed int one_signed;
- unsigned short two[2];
- signed short two_signed[2];
- unsigned char four[4];
- } var;
+ FilteredBlockReadClass *block_reader[MAXSIGNALS];
+
+ struct signalcompblock *signalcomp[MAXSIGNALS];
+
+ for(i=0; i<MAXSIGNALS; i++)
+ {
+ block_reader[i] = NULL;
+ }
memset(&new_annot_list, 0, sizeof(struct annotation_list));
@@ -600,13 +461,8 @@ void UI_ReduceSignalsWindow::StartConversion()
progress.reset();
pushButton3->setEnabled(false);
- pushButton4->setEnabled(false);
- pushButton5->setEnabled(false);
- pushButton6->setEnabled(false);
spinBox1->setEnabled(false);
spinBox2->setEnabled(false);
- spinBox3->setEnabled(false);
- spinBox4->setEnabled(false);
radioButton1->setEnabled(false);
radioButton2->setEnabled(false);
label2->setEnabled(false);
@@ -622,48 +478,54 @@ void UI_ReduceSignalsWindow::StartConversion()
return;
}
- new_edfsignals = 0;
-
annot_smp_per_record = 0;
- aa_filter_order = spinBox4->value() - 1;
-
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; i<edfhdr->edfsignals; i++)
+ for(i=0, new_edfsignals=0; i<mainwindow->signalcomps; i++)
{
- if(!edfhdr->edfparam[i].annotation)
- {
- if(((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->checkState()==Qt::Checked)
- {
- signalslist[new_edfsignals] = i;
+ if(mainwindow->signalcomp[i]->filenum != file_num) continue;
- dividerlist[new_edfsignals] = ((QComboBox *)(SignalsTablewidget->cellWidget(i, 1)))->itemData(((QComboBox *)(SignalsTablewidget->cellWidget(i, 1)))->currentIndex()).toInt();
+ signalcomp[new_edfsignals] = mainwindow->signalcomp[i];
- new_edfsignals++;
- }
- }
+ signalslist[new_edfsignals] = signalcomp[new_edfsignals]->edfsignal[0];
+
+ block_reader[new_edfsignals] = new FilteredBlockReadClass;
+
+ filtered_blockread_buf[new_edfsignals] = block_reader[new_edfsignals]->init_signalcomp(signalcomp[new_edfsignals], 1, 0);
+
+ smp_per_record[new_edfsignals] = block_reader[new_edfsignals]->samples_in_buf();
+
+ new_edfsignals++;
}
- datarecords = spinBox2->value() - spinBox1->value() + 1;
+ if(!new_edfsignals)
+ {
+ showpopupmessage("Error", "No signals present on screen for selected file.");
+ goto END_1;
+ }
+
+ start_datarecord = spinBox1->value() - 1;
+
+ datarecords = spinBox2->value() - start_datarecord;
if(edfhdr->edfplus || edfhdr->bdfplus)
{
timestamp_decimals = edfplus_annotation_get_tal_timestamp_decimal_cnt(edfhdr);
if(timestamp_decimals < 0)
{
- showpopupmessage("Error", "Internal error, get_tal_timestamp_decimal_cnt(");
+ showpopupmessage("Error", "Internal error, get_tal_timestamp_decimal_cnt()");
goto END_1;
}
timestamp_digits = edfplus_annotation_get_tal_timestamp_digit_cnt(edfhdr);
if(timestamp_digits < 0)
{
- showpopupmessage("Error", "Internal error, get_tal_timestamp_digit_cnt(");
+ showpopupmessage("Error", "Internal error, get_tal_timestamp_digit_cnt()");
goto END_1;
}
@@ -751,31 +613,6 @@ void UI_ReduceSignalsWindow::StartConversion()
annot_recordsize = 0;
}
- readbuf = (char *)malloc(edfhdr->recordsize);
- if(readbuf==NULL)
- {
- showpopupmessage("Error", "Malloc error, (readbuf).");
- goto END_2;
- }
-///////////////////////////////////////////////////////////////////
-
- for(i=0; i<new_edfsignals; i++)
- {
- if(dividerlist[i] > 1)
- {
- for(j=0; j<aa_filter_order; j++)
- {
- filterlist[i][j] = create_ravg_filter(1, dividerlist[i]);
-
- if(filterlist[i][j] == NULL)
- {
- showpopupmessage("Error", "Malloc error, (create_ravg_filter()).");
-
- goto END_3;
- }
- }
- }
- }
///////////////////////////////////////////////////////////////////
outputpath[0] = 0;
@@ -789,13 +626,13 @@ void UI_ReduceSignalsWindow::StartConversion()
remove_extension_from_filename(outputpath);
if(edfhdr->edf)
{
- strcat(outputpath, "_reduced.edf");
+ strcat(outputpath, "_filtered.edf");
strcpy(outputpath, QFileDialog::getSaveFileName(0, "Save file", QString::fromLocal8Bit(outputpath), "EDF files (*.edf *.EDF)").toLocal8Bit().data());
}
else
{
- strcat(outputpath, "_reduced.bdf");
+ strcat(outputpath, "_filtered.bdf");
strcpy(outputpath, QFileDialog::getSaveFileName(0, "Save file", QString::fromLocal8Bit(outputpath), "BDF files (*.bdf *.BDF)").toLocal8Bit().data());
}
@@ -809,7 +646,7 @@ void UI_ReduceSignalsWindow::StartConversion()
if(mainwindow->file_is_opened(outputpath))
{
- showpopupmessage("Reduce signals", "Error, selected file is in use.");
+ showpopupmessage("Error", "Selected file is in use.");
goto END_3;
}
@@ -907,7 +744,10 @@ void UI_ReduceSignalsWindow::StartConversion()
for(i=0; i<new_edfsignals; i++)
{
- fprintf(outputfile, "%s", edfhdr->edfparam[signalslist[i]].label);
+ snprintf(scratchpad, 16, "%s", signalcomp[i]->signallabel);
+ strcat(scratchpad, " ");
+ scratchpad[16] = 0;
+ fprintf(outputfile, "%s", scratchpad);
}
if(edfhdr->edfplus)
{
@@ -995,7 +835,144 @@ void UI_ReduceSignalsWindow::StartConversion()
}
for(i=0; i<new_edfsignals; i++)
{
- fprintf(outputfile, "%s", edfhdr->edfparam[signalslist[i]].prefilter);
+// fprintf(outputfile, "%s", edfhdr->edfparam[signalslist[i]].prefilter);
+
+ strcpy(scratchpad, edfhdr->edfparam[signalslist[i]].prefilter);
+ strcat(scratchpad, " ");
+ for(p = strlen(scratchpad) - 1; p>=0; p--)
+ {
+ if(scratchpad[p]!=' ') break;
+ }
+ p++;
+ if(p) p++;
+
+ for(j=0; j<signalcomp[i]->filter_cnt; j++)
+ {
+ if(signalcomp[i]->filter[j]->is_LPF == 1)
+ {
+ p += sprintf(scratchpad + p, "LP:%f", signalcomp[i]->filter[j]->cutoff_frequency);
+ }
+
+ if(signalcomp[i]->filter[j]->is_LPF == 0)
+ {
+ p += sprintf(scratchpad + p, "HP:%f", signalcomp[i]->filter[j]->cutoff_frequency);
+ }
+
+ for(k=(p-1); k>0; k--)
+ {
+ if(scratchpad[k]!='0') break;
+ }
+
+ if(scratchpad[k]=='.') scratchpad[k] = 0;
+ else scratchpad[k+1] = 0;
+
+ strcat(scratchpad, "Hz ");
+
+ p = strlen(scratchpad);
+
+ if(p>80) break;
+ }
+
+ for(j=0; j<signalcomp[i]->fidfilter_cnt; j++)
+ {
+ type = signalcomp[i]->fidfilter_type[j];
+
+ frequency = signalcomp[i]->fidfilter_freq[j];
+
+ frequency2 = signalcomp[i]->fidfilter_freq2[j];
+
+ if(type == 0)
+ {
+ p += sprintf(scratchpad + p, "HP:%f", frequency);
+ }
+
+ if(type == 1)
+ {
+ p += sprintf(scratchpad + p, "LP:%f", frequency);
+ }
+
+ if(type == 2)
+ {
+ p += sprintf(scratchpad + p, "N:%f", frequency);
+ }
+
+ if(type == 3)
+ {
+ p += sprintf(scratchpad + p, "BP:%f", frequency);
+ }
+
+ if(type == 4)
+ {
+ p += sprintf(scratchpad + p, "BS:%f", frequency);
+ }
+
+ for(k=(p-1); k>0; k--)
+ {
+ if(scratchpad[k]!='0') break;
+ }
+
+ if(scratchpad[k]=='.') scratchpad[k] = 0;
+ else scratchpad[k+1] = 0;
+
+ p = strlen(scratchpad);
+
+ if((type == 3) || (type == 4))
+ {
+ p += sprintf(scratchpad + p, "-%f", frequency2);
+
+ for(k=(p-1); k>0; k--)
+ {
+ if(scratchpad[k]!='0') break;
+ }
+
+ if(scratchpad[k]=='.') scratchpad[k] = 0;
+ else scratchpad[k+1] = 0;
+ }
+
+ strcat(scratchpad, "Hz ");
+
+ p = strlen(scratchpad);
+
+ if(p>80) break;
+ }
+
+ for(j=0; j<signalcomp[i]->ravg_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 ");
+ }
+
+ if(signalcomp[i]->zratio_filter != NULL)
+ {
+ p += sprintf(scratchpad + p, "Z-ratio ");
+ }
+
+ for(;p<81; p++)
+ {
+ scratchpad[p] = ' ';
+ }
+
+ if(fwrite(scratchpad, 80, 1, outputfile)!=1)
+ {
+ showpopupmessage("Error", "Write error (2).");
+ goto END_4;
+ }
}
if(edfhdr->edfplus || edfhdr->bdfplus)
{
@@ -1006,7 +983,7 @@ void UI_ReduceSignalsWindow::StartConversion()
}
for(i=0; i<new_edfsignals; i++)
{
- fprintf(outputfile, "%-8i", edfhdr->edfparam[signalslist[i]].smp_per_record / dividerlist[i]);
+ fprintf(outputfile, "%-8i", edfhdr->edfparam[signalslist[i]].smp_per_record);
}
if(edfhdr->edfplus || edfhdr->bdfplus)
{
@@ -1034,8 +1011,6 @@ void UI_ReduceSignalsWindow::StartConversion()
progress_steps = 1;
}
- fseeko(inputfile, (long long)edfhdr->hdrsize + ((long long)(spinBox1->value() - 1) * (long long)edfhdr->recordsize), SEEK_SET);
-
for(datrecs_processed=0; datrecs_processed<datarecords; datrecs_processed++)
{
if(!(datrecs_processed % progress_steps))
@@ -1050,126 +1025,56 @@ void UI_ReduceSignalsWindow::StartConversion()
}
}
- if(fread(readbuf, edfhdr->recordsize, 1, inputfile) != 1)
+ for(i=0; i<new_edfsignals; i++)
{
- progress.reset();
- showpopupmessage("Error", "Read error (2).");
- goto END_4;
+ if(block_reader[i]->process_signalcomp(start_datarecord))
+ {
+ progress.reset();
+ showpopupmessage("Error", "Read error (2).");
+ goto END_4;
+ }
}
- if(edfhdr->edf)
- {
- for(i=0; i<new_edfsignals; i++)
- {
- if(dividerlist[i] == 1)
- {
- smplrt = edfhdr->edfparam[signalslist[i]].smp_per_record;
+ start_datarecord++;
- for(j=0; j<smplrt; j++)
- {
- fputc(readbuf[edfhdr->edfparam[signalslist[i]].buf_offset + (j * 2)], outputfile);
- if(fputc(readbuf[edfhdr->edfparam[signalslist[i]].buf_offset + (j * 2) + 1], outputfile)==EOF)
- {
- progress.reset();
- showpopupmessage("Error", "Write error (4).");
- goto END_4;
- }
- }
- }
- else
- {
- smplrt = edfhdr->edfparam[signalslist[i]].smp_per_record / dividerlist[i];
-
- for(j=0; j<smplrt; j++)
- {
- tmp = 0;
+ for(i=0; i<new_edfsignals; i++)
+ {
+ digmax = edfhdr->edfparam[signalslist[i]].dig_max;
- for(k=0; k<dividerlist[i]; k++)
- {
- val = *(((signed short *)(readbuf + edfhdr->edfparam[signalslist[i]].buf_offset)) + (dividerlist[i] * j) + k);
+ digmin = edfhdr->edfparam[signalslist[i]].dig_min;
- for(n=0; n<aa_filter_order; n++)
- {
- val = run_ravg_filter(val, filterlist[i][n]);
- }
+ bitvalue = edfhdr->edfparam[signalslist[i]].bitvalue;
- tmp += val;
- }
+ phys_offset = edfhdr->edfparam[signalslist[i]].offset;
- tmp /= dividerlist[i];
+ smplrt = smp_per_record[i];
- fputc(tmp & 0xff, outputfile);
- if(fputc((tmp >> 8) & 0xff, outputfile)==EOF)
- {
- progress.reset();
- showpopupmessage("Error", "Write error (4).");
- goto END_4;
- }
- }
- }
- }
- }
- else
- {
- for(i=0; i<new_edfsignals; i++)
+ for(j=0; j<smplrt; j++)
{
- if(dividerlist[i] == 1)
- {
- smplrt = edfhdr->edfparam[signalslist[i]].smp_per_record;
+ value = (filtered_blockread_buf[i][j] / bitvalue) - phys_offset;
- for(j=0; j<smplrt; j++)
- {
- fputc(readbuf[edfhdr->edfparam[signalslist[i]].buf_offset + (j * 3)], outputfile);
- fputc(readbuf[edfhdr->edfparam[signalslist[i]].buf_offset + (j * 3) + 1], outputfile);
- if(fputc(readbuf[edfhdr->edfparam[signalslist[i]].buf_offset + (j * 3) + 2], outputfile)==EOF)
- {
- progress.reset();
- showpopupmessage("Error", "Write error (4).");
- goto END_4;
- }
- }
- }
- else
+ if(value>digmax)
{
- smplrt = edfhdr->edfparam[signalslist[i]].smp_per_record / dividerlist[i];
+ value = digmax;
+ }
- for(j=0; j<smplrt; j++)
- {
- l_tmp = 0LL;
+ if(value<digmin)
+ {
+ value = digmin;
+ }
- for(k=0; k<dividerlist[i]; k++)
- {
- var.two[0] = *((unsigned short *)(readbuf + edfhdr->edfparam[signalslist[i]].buf_offset + (dividerlist[i] * j * 3) + (k * 3)));
- var.four[2] = *((unsigned char *)(readbuf + edfhdr->edfparam[signalslist[i]].buf_offset + (dividerlist[i] * j * 3) + (k * 3) + 2));
-
- if(var.four[2]&0x80)
- {
- var.four[3] = 0xff;
- }
- else
- {
- var.four[3] = 0x00;
- }
-
- for(n=0; n<aa_filter_order; n++)
- {
- var.one_signed = run_ravg_filter(var.one_signed, filterlist[i][n]);
- }
-
- l_tmp += var.one_signed;
- }
+ fputc(value&0xff, outputfile);
- l_tmp /= dividerlist[i];
+ if(fputc((value>>8)&0xff, outputfile)==EOF)
+ {
+ progress.reset();
+ showpopupmessage("Error", "Write error (4).");
+ goto END_4;
+ }
- fputc(l_tmp & 0xff, outputfile);
- fputc((l_tmp >> 8) & 0xff, outputfile);
- if(fputc((l_tmp >> 16) & 0xff, outputfile)==EOF)
- {
- progress.reset();
- showpopupmessage("Error", "Write error (4).");
- goto END_4;
- }
- }
+ if(edfhdr->bdf)
+ {
+ fputc((value>>16)&0xff, outputfile);
}
}
}
@@ -1206,60 +1111,57 @@ void UI_ReduceSignalsWindow::StartConversion()
{
for(i=0; i<annots_per_datrec; i++)
{
- if(annot_cnt < annot_list_sz)
- {
- annot_ptr = edfplus_annotation_get_item(&new_annot_list, annot_cnt);
+ if(annot_cnt >= annot_list_sz) break;
- len = snprintf(scratchpad, 256, "%+i.%07i",
- (int)(annot_ptr->onset / TIME_DIMENSION),
- (int)(annot_ptr->onset % TIME_DIMENSION));
+ annot_ptr = edfplus_annotation_get_item(&new_annot_list, annot_cnt++);
- for(j=0; j<7; j++)
- {
- if(scratchpad[len - j - 1] != '0')
- {
- break;
- }
- }
+ len = snprintf(scratchpad, 256, "%+i.%07i",
+ (int)(annot_ptr->onset / TIME_DIMENSION),
+ (int)(annot_ptr->onset % TIME_DIMENSION));
- if(j)
+ for(j=0; j<7; j++)
+ {
+ if(scratchpad[len - j - 1] != '0')
{
- len -= j;
-
- if(j == 7)
- {
- len--;
- }
+ break;
}
+ }
- if(fwrite(scratchpad, len, 1, outputfile) != 1)
+ if(j)
+ {
+ len -= j;
+
+ if(j == 7)
{
- progress.reset();
- showpopupmessage("Error", "Write error (5).");
- goto END_4;
+ len--;
}
+ }
- tallen += len;
-
- if(annot_ptr->duration[0]!=0)
- {
- fputc(21, outputfile);
- tallen++;
+ if(fwrite(scratchpad, len, 1, outputfile) != 1)
+ {
+ progress.reset();
+ showpopupmessage("Error", "Write error (5).");
+ goto END_4;
+ }
- tallen += fprintf(outputfile, "%s", annot_ptr->duration);
- }
+ tallen += len;
- fputc(20, outputfile);
+ if(annot_ptr->duration[0]!=0)
+ {
+ fputc(21, outputfile);
tallen++;
- tallen += fprintf(outputfile, "%s", annot_ptr->annotation);
+ tallen += fprintf(outputfile, "%s", annot_ptr->duration);
+ }
- fputc(20, outputfile);
- fputc(0, outputfile);
- tallen += 2;
+ fputc(20, outputfile);
+ tallen++;
- annot_cnt--;
- }
+ tallen += fprintf(outputfile, "%s", annot_ptr->annotation);
+
+ fputc(20, outputfile);
+ fputc(0, outputfile);
+ tallen += 2;
}
}
@@ -1282,24 +1184,7 @@ END_4:
END_3:
- for(i=0; i<new_edfsignals; i++)
- {
- if(dividerlist[i] > 1)
- {
- for(j=0; j<aa_filter_order; j++)
- {
- free_ravg_filter(filterlist[i][j]);
- }
- }
- }
-
-END_2:
-
- if(readbuf != NULL)
- {
- free(readbuf);
- readbuf = NULL;
- }
+//END_2:
END_1:
@@ -1317,11 +1202,17 @@ END_1:
edfplus_annotation_empty_list(&new_annot_list);
- SignalsTablewidget->setRowCount(0);
+ for(i=0; i<MAXSIGNALS; i++)
+ {
+ if(block_reader[i] != NULL)
+ {
+ delete block_reader[i];
+ }
+ }
}
-void UI_ReduceSignalsWindow::showpopupmessage(const char *str1, const char *str2)
+void UI_ExportFilteredSignalsWindow::showpopupmessage(const char *str1, const char *str2)
{
QMessageBox messagewindow(QMessageBox::NoIcon, str1, str2);
@@ -1329,20 +1220,226 @@ void UI_ReduceSignalsWindow::showpopupmessage(const char *str1, const char *str2
}
-void UI_ReduceSignalsWindow::helpbuttonpressed()
+void UI_ExportFilteredSignalsWindow::populate_tree_view()
{
-#ifdef Q_OS_LINUX
- QDesktopServices::openUrl(QUrl("file:///usr/share/doc/edfbrowser/manual.html#Reduce_signals"));
-#endif
-
-#ifdef Q_OS_WIN32
- char p_path[MAX_PATH_LENGTH];
-
- strcpy(p_path, "file:///");
- strcat(p_path, mainwindow->specialFolder(CSIDL_PROGRAM_FILES).toLocal8Bit().data());
- strcat(p_path, "\\EDFbrowser\\manual.html#Reduce_signals");
- QDesktopServices::openUrl(QUrl(p_path));
-#endif
+ int i, j,
+ type,
+ model,
+ order;
+
+ char txtbuf[2048];
+
+ double frequency,
+ frequency2,
+ ripple;
+
+ QStandardItem *parentItem,
+ *signalItem,
+ *filterItem;
+
+ t_model->clear();
+
+ parentItem = t_model->invisibleRootItem();
+
+ for(i=0; i<mainwindow->signalcomps; i++)
+ {
+ if(mainwindow->signalcomp[i]->filenum != file_num) continue;
+
+ txtbuf[0] = 0;
+
+ if(mainwindow->signalcomp[i]->alias[0] != 0)
+ {
+ strcpy(txtbuf, "alias: ");
+ strcat(txtbuf, mainwindow->signalcomp[i]->alias);
+ strcat(txtbuf, " ");
+ }
+
+ for(j=0; j<mainwindow->signalcomp[i]->num_of_signals; j++)
+ {
+ sprintf(txtbuf + strlen(txtbuf), "%+ix %s",
+ mainwindow->signalcomp[i]->factor[j],
+ mainwindow->signalcomp[i]->edfhdr->edfparam[mainwindow->signalcomp[i]->edfsignal[j]].label);
+
+ remove_trailing_spaces(txtbuf);
+
+ strcat(txtbuf, " ");
+ }
+
+ signalItem = new QStandardItem(txtbuf);
+
+ parentItem->appendRow(signalItem);
+
+ filterItem = new QStandardItem("Filters");
+
+ signalItem->appendRow(filterItem);
+
+ if(mainwindow->signalcomp[i]->spike_filter)
+ {
+ sprintf(txtbuf, "Spike: %.8f", mainwindow->signalcomp[i]->spike_filter_velocity);
+
+ remove_trailing_zeros(txtbuf);
+
+ sprintf(txtbuf + strlen(txtbuf), " %s/0.5mSec. Hold-off: %i mSec.",
+ mainwindow->signalcomp[i]->physdimension,
+ mainwindow->signalcomp[i]->spike_filter_holdoff);
+
+ filterItem->appendRow(new QStandardItem(txtbuf));
+ }
+
+ for(j=0; j<mainwindow->signalcomp[i]->filter_cnt; j++)
+ {
+ if(mainwindow->signalcomp[i]->filter[j]->is_LPF == 1)
+ {
+ sprintf(txtbuf, "LPF: %fHz", mainwindow->signalcomp[i]->filter[j]->cutoff_frequency);
+ }
+
+ if(mainwindow->signalcomp[i]->filter[j]->is_LPF == 0)
+ {
+ sprintf(txtbuf, "HPF: %fHz", mainwindow->signalcomp[i]->filter[j]->cutoff_frequency);
+ }
+
+ remove_trailing_zeros(txtbuf);
+
+ filterItem->appendRow(new QStandardItem(txtbuf));
+ }
+
+ for(j=0; j<mainwindow->signalcomp[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; j<mainwindow->signalcomp[i]->fidfilter_cnt; j++)
+ {
+ type = mainwindow->signalcomp[i]->fidfilter_type[j];
+
+ model = mainwindow->signalcomp[i]->fidfilter_model[j];
+
+ frequency = mainwindow->signalcomp[i]->fidfilter_freq[j];
+
+ frequency2 = mainwindow->signalcomp[i]->fidfilter_freq2[j];
+
+ order = mainwindow->signalcomp[i]->fidfilter_order[j];
+
+ ripple = mainwindow->signalcomp[i]->fidfilter_ripple[j];
+
+ if(type == 0)
+ {
+ if(model == 0)
+ {
+ sprintf(txtbuf, "highpass Butterworth %fHz %ith order", frequency, order);
+ }
+
+ if(model == 1)
+ {
+ sprintf(txtbuf, "highpass Chebyshev %fHz %ith order %fdB ripple", frequency, order, ripple);
+ }
+
+ if(model == 2)
+ {
+ sprintf(txtbuf, "highpass Bessel %fHz %ith order", frequency, order);
+ }
+ }
+
+ if(type == 1)
+ {
+ if(model == 0)
+ {
+ sprintf(txtbuf, "lowpass Butterworth %fHz %ith order", frequency, order);
+ }
+
+ if(model == 1)
+ {
+ sprintf(txtbuf, "lowpass Chebyshev %fHz %ith order %fdB ripple", frequency, order, ripple);
+ }
+
+ if(model == 2)
+ {
+ sprintf(txtbuf, "lowpass Bessel %fHz %ith order", frequency, order);
+ }
+ }
+
+ if(type == 2)
+ {
+ sprintf(txtbuf, "notch %fHz Q-factor %i", frequency, order);
+ }
+
+ if(type == 3)
+ {
+ if(model == 0)
+ {
+ sprintf(txtbuf, "bandpass Butterworth %f-%fHz %ith order", frequency, frequency2, order);
+ }
+
+ if(model == 1)
+ {
+ sprintf(txtbuf, "bandpass Chebyshev %f-%fHz %ith order %fdB ripple", frequency, frequency2, order, ripple);
+ }
+
+ if(model == 2)
+ {
+ sprintf(txtbuf, "bandpass Bessel %f-%fHz %ith order", frequency, frequency2, order);
+ }
+ }
+
+ if(type == 4)
+ {
+ if(model == 0)
+ {
+ sprintf(txtbuf, "bandstop Butterworth %f-%fHz %ith order", frequency, frequency2, order);
+ }
+
+ if(model == 1)
+ {
+ sprintf(txtbuf, "bandstop Chebyshev %f-%fHz %ith order %fdB ripple", frequency, frequency2, order, ripple);
+ }
+
+ if(model == 2)
+ {
+ sprintf(txtbuf, "bandstop Bessel %f-%fHz %ith order", frequency, frequency2, order);
+ }
+ }
+
+ remove_trailing_zeros(txtbuf);
+
+ filterItem->appendRow(new QStandardItem(txtbuf));
+ }
+
+ if(mainwindow->signalcomp[i]->ecg_filter != NULL)
+ {
+ sprintf(txtbuf, "ECG heartrate detection");
+
+ filterItem->appendRow(new QStandardItem(txtbuf));
+ }
+
+ if(mainwindow->signalcomp[i]->plif_ecg_filter != NULL)
+ {
+ sprintf(txtbuf, "Powerline interference removal: %iHz",
+ (mainwindow->signalcomp[i]->plif_ecg_subtract_filter_plf * 10) + 50);
+
+ filterItem->appendRow(new QStandardItem(txtbuf));
+ }
+
+ if(mainwindow->signalcomp[i]->zratio_filter != NULL)
+ {
+ sprintf(txtbuf, "Z-ratio cross-over frequency is %.1f Hz", mainwindow->signalcomp[i]->zratio_crossoverfreq);
+
+ filterItem->appendRow(new QStandardItem(txtbuf));
+ }
+ }
+
+ tree->setModel(t_model);
+
+ tree->expandAll();
}
@@ -1361,3 +1458,4 @@ void UI_ReduceSignalsWindow::helpbuttonpressed()
+
diff --git a/export_filtered_signals.h b/export_filtered_signals.h
new file mode 100644
index 0000000..5aec060
--- /dev/null
+++ b/export_filtered_signals.h
@@ -0,0 +1,140 @@
+/*
+***************************************************************************
+*
+* Author: Teunis van Beelen
+*
+* Copyright (C) 2017 Teunis van Beelen
+*
+* Email: teuniz at 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, either version 3 of the License, or
+* (at your option) any later version.
+*
+* 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, see <http://www.gnu.org/licenses/>.
+*
+***************************************************************************
+*/
+
+
+#ifndef UI_EXPORTFILTSIGNALSFORM_H
+#define UI_EXPORTFILTSIGNALSFORM_H
+
+
+#include <QtGlobal>
+#include <QApplication>
+#include <QDialog>
+#include <QLabel>
+#include <QPushButton>
+#include <QCheckBox>
+#include <QObject>
+#include <QTableWidget>
+#include <QFileDialog>
+#include <QCursor>
+#include <QString>
+#include <QSpinBox>
+#include <QRadioButton>
+#include <QMessageBox>
+#include <QComboBox>
+#include <QVariant>
+#include <QProgressDialog>
+#include <QDesktopServices>
+#include <QUrl>
+#include <QTreeView>
+#include <QStandardItemModel>
+#include <QStandardItem>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "global.h"
+#include "mainwindow.h"
+#include "check_edf_file.h"
+#include "utils.h"
+#include "utc_date_time.h"
+#include "active_file_chooser.h"
+#include "edf_annot_list.h"
+#include "edf_helper.h"
+#include "filteredblockread.h"
+
+
+
+class UI_Mainwindow;
+
+
+
+class UI_ExportFilteredSignalsWindow : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ UI_ExportFilteredSignalsWindow(QWidget *parent);
+
+ UI_Mainwindow *mainwindow;
+
+private:
+
+QLabel *label1,
+ *label2,
+ *label3,
+ *label4,
+ *label5;
+
+QPushButton *pushButton1,
+ *pushButton2,
+ *pushButton3;
+
+QSpinBox *spinBox1,
+ *spinBox2;
+
+QRadioButton *radioButton1,
+ *radioButton2;
+
+QDialog *myobjectDialog;
+
+QTreeView *tree;
+
+QStandardItemModel *t_model;
+
+int file_num;
+
+char inputpath[MAX_PATH_LENGTH],
+ outputpath[MAX_PATH_LENGTH],
+ *recent_savedir;
+
+FILE *inputfile,
+ *outputfile;
+
+struct edfhdrblock *edfhdr;
+
+void showpopupmessage(const char *, const char *);
+
+private slots:
+
+void SelectFileButton();
+void StartExport();
+void spinBox1changed(int);
+void spinBox2changed(int);
+void radioButton1Toggled(bool);
+void radioButton2Toggled(bool);
+void populate_tree_view();
+
+};
+
+
+
+
+#endif
+
+
diff --git a/filteredblockread.cpp b/filteredblockread.cpp
index 9e76575..aa9b8a9 100644
--- a/filteredblockread.cpp
+++ b/filteredblockread.cpp
@@ -165,27 +165,27 @@ int FilteredBlockReadClass::process_signalcomp(int datarecord_start)
if((datarecord_start < 0) || (datarecord_start >= hdr->datarecords))
{
- return(-1);
+ return(-2);
}
if(datarecord_cnt > (hdr->datarecords - datarecord_start))
{
- return(-1);
+ return(-3);
}
if(fseeko(inputfile, ((long long)hdr->hdrsize) + (((long long)datarecord_start) * ((long long) hdr->recordsize)), SEEK_SET) == -1LL)
{
- return(-1);
+ return(-4);
}
if(fread(readbuf, hdr->recordsize * datarecord_cnt, 1, inputfile) != 1)
{
- return(-1);
+ return(-5);
}
if((readbuf == NULL) || (processed_samples_buf == NULL))
{
- return(-1);
+ return(-6);
}
for(s=0; s<total_samples; s++)
diff --git a/global.h b/global.h
index 51d48b0..2d7c6c9 100644
--- a/global.h
+++ b/global.h
@@ -44,7 +44,7 @@
#endif
#define PROGRAM_NAME "EDFbrowser"
-#define PROGRAM_VERSION "1.60"
+#define PROGRAM_VERSION "1.61"
#define MINIMUM_QT4_VERSION 0x040701
#define MINIMUM_QT5_VERSION 0x050901
#define MAXFILES 32
@@ -288,6 +288,14 @@ struct video_player_struct{
int fpos;
};
+struct annot_filter_struct{
+ int tmin;
+ int tmax;
+ int invert;
+ int hide_other;
+ int hide_in_list_only;
+ };
+
#endif
diff --git a/images/splash.png b/images/splash.png
index 5eee368..6045572 100644
Binary files a/images/splash.png and b/images/splash.png differ
diff --git a/mainwindow.cpp b/mainwindow.cpp
index f37d4ae..64e2689 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -120,6 +120,7 @@ void UI_Mainwindow::closeEvent(QCloseEvent *cl_event)
free(import_annotations_var);
free(export_annotations_var);
free(video_player);
+ free(annot_filter);
cl_event->accept();
}
@@ -3216,6 +3217,12 @@ void UI_Mainwindow::export_ecg_rr_interval_to_ascii()
}
+void UI_Mainwindow::export_filtered_signals()
+{
+ UI_ExportFilteredSignalsWindow filt_signalswdw(this);
+}
+
+
void UI_Mainwindow::export_annotations()
{
if(!files_open)
diff --git a/mainwindow.h b/mainwindow.h
index 1177fe9..e596a6c 100644
--- a/mainwindow.h
+++ b/mainwindow.h
@@ -160,6 +160,7 @@
#include "biox2edf.h"
#include "plif_ecg_subtract_filter.h"
#include "plif_ecg_subtract_filter_dialog.h"
+#include "export_filtered_signals.h"
#include "third_party/fidlib/fidlib.h"
@@ -224,7 +225,8 @@ public:
timescale_doubler,
viewtime_indicator_type,
mainwindow_title_type,
- linear_interpol;
+ linear_interpol,
+ average_period;
long long pagetime,
maxfilesize_to_readin_annotations;
@@ -242,7 +244,6 @@ public:
double pixelsizefactor,
x_pixelsizefactor,
- average_period,
default_amplitude;
struct{
@@ -271,6 +272,8 @@ public:
struct video_player_struct *video_player;
+ struct annot_filter_struct *annot_filter;
+
UI_Annotationswindow *annotations_dock[MAXFILES];
UI_AnnotationEditwindow *annotationEditDock;
@@ -565,6 +568,7 @@ private slots:
void convert_mit_to_edf();
void convert_biox_to_edf();
void video_process_error(QProcess::ProcessError);
+ void export_filtered_signals();
// void search_pattern();
protected:
diff --git a/mainwindow_constr.cpp b/mainwindow_constr.cpp
index 71480e6..156ca1d 100644
--- a/mainwindow_constr.cpp
+++ b/mainwindow_constr.cpp
@@ -177,7 +177,7 @@ UI_Mainwindow::UI_Mainwindow()
export_annotations_var->format = 1;
export_annotations_var->duration = 0;
- average_period = 0.3;
+ average_period = 300;
average_ratio = 0;
@@ -212,6 +212,13 @@ UI_Mainwindow::UI_Mainwindow()
raw2edf_var.skipbytes = 1;
strcpy(raw2edf_var.phys_dim, "uV");
+ annot_filter = (struct annot_filter_struct *)calloc(1, sizeof(struct annot_filter_struct));
+ annot_filter->tmin = 1000;
+ annot_filter->tmax = 2000;
+ annot_filter->invert = 0;
+ annot_filter->hide_other = 1;
+ annot_filter->hide_in_list_only = 1;
+
read_general_settings();
maincurve = new ViewCurve(this);
@@ -686,6 +693,7 @@ UI_Mainwindow::UI_Mainwindow()
toolsmenu->addAction("Export annotations/events", this, SLOT(export_annotations()));
toolsmenu->addAction("Export EDF/BDF to ASCII", this, SLOT(export_to_ascii()));
toolsmenu->addAction("Export/Import ECG RR-interval", this, SLOT(export_ecg_rr_interval_to_ascii()));
+ toolsmenu->addAction("Export Filtered Signals", this, SLOT(export_filtered_signals()));
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()));
diff --git a/options_dialog.cpp b/options_dialog.cpp
index 9901115..a01730b 100644
--- a/options_dialog.cpp
+++ b/options_dialog.cpp
@@ -85,51 +85,51 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
BgColorButton->setColor(mainwindow->maincurve->backgroundcolor);
label2 = new QLabel(tab1);
- label2->setGeometry(20, 55, 200, 25);
+ label2->setGeometry(20, 45, 200, 25);
label2->setText("Small ruler color");
SrColorButton = new SpecialButton(tab1);
- SrColorButton->setGeometry(240, 60, 60, 15);
+ SrColorButton->setGeometry(240, 50, 60, 15);
SrColorButton->setColor(mainwindow->maincurve->small_ruler_color);
label3 = new QLabel(tab1);
- label3->setGeometry(20, 95, 200, 25);
+ label3->setGeometry(20, 75, 200, 25);
label3->setText("Big ruler color");
BrColorButton = new SpecialButton(tab1);
- BrColorButton->setGeometry(240, 100, 60, 15);
+ BrColorButton->setGeometry(240, 80, 60, 15);
BrColorButton->setColor(mainwindow->maincurve->big_ruler_color);
label4 = new QLabel(tab1);
- label4->setGeometry(20, 135, 200, 25);
+ label4->setGeometry(20, 105, 200, 25);
label4->setText("Mouse rectangle color");
MrColorButton = new SpecialButton(tab1);
- MrColorButton->setGeometry(240, 140, 60, 15);
+ MrColorButton->setGeometry(240, 110, 60, 15);
MrColorButton->setColor(mainwindow->maincurve->mouse_rect_color);
label5 = new QLabel(tab1);
- label5->setGeometry(20, 175, 200, 25);
+ label5->setGeometry(20, 135, 200, 25);
label5->setText("Text color");
TxtColorButton = new SpecialButton(tab1);
- TxtColorButton->setGeometry(240, 180, 60, 15);
+ TxtColorButton->setGeometry(240, 140, 60, 15);
TxtColorButton->setColor(mainwindow->maincurve->text_color);
label6 = new QLabel(tab1);
- label6->setGeometry(20, 215, 200, 25);
+ label6->setGeometry(20, 165, 200, 25);
label6->setText("Signals color");
SigColorButton = new SpecialButton(tab1);
- SigColorButton->setGeometry(240, 220, 60, 15);
+ SigColorButton->setGeometry(240, 170, 60, 15);
SigColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->signal_color);
label7 = new QLabel(tab1);
- label7->setGeometry(20, 255, 200, 25);
+ label7->setGeometry(20, 195, 200, 25);
label7->setText("Baseline color");
checkbox3 = new QCheckBox(tab1);
- checkbox3->setGeometry(200, 258, 20, 20);
+ checkbox3->setGeometry(200, 198, 20, 20);
checkbox3->setTristate(false);
if(mainwindow->show_baselines)
{
@@ -141,39 +141,39 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
}
BaseColorButton = new SpecialButton(tab1);
- BaseColorButton->setGeometry(240, 260, 60, 15);
+ BaseColorButton->setGeometry(240, 200, 60, 15);
BaseColorButton->setColor(mainwindow->maincurve->baseline_color);
label8 = new QLabel(tab1);
- label8->setGeometry(20, 295, 200, 25);
+ label8->setGeometry(20, 225, 200, 25);
label8->setText("Crosshair color");
Crh1ColorButton = new SpecialButton(tab1);
- Crh1ColorButton->setGeometry(240, 300, 60, 15);
+ Crh1ColorButton->setGeometry(240, 230, 60, 15);
Crh1ColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->crosshair_1.color);
label9 = new QLabel(tab1);
- label9->setGeometry(20, 335, 200, 25);
+ label9->setGeometry(20, 255, 200, 25);
label9->setText("2th Crosshair color");
Crh2ColorButton = new SpecialButton(tab1);
- Crh2ColorButton->setGeometry(240, 340, 60, 15);
+ Crh2ColorButton->setGeometry(240, 260, 60, 15);
Crh2ColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->crosshair_2.color);
label10 = new QLabel(tab1);
- label10->setGeometry(20, 375, 200, 25);
+ label10->setGeometry(20, 285, 200, 25);
label10->setText("Floating ruler color");
FrColorButton = new SpecialButton(tab1);
- FrColorButton->setGeometry(240, 380, 60, 15);
+ FrColorButton->setGeometry(240, 290, 60, 15);
FrColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->floating_ruler_color);
label12 = new QLabel(tab1);
- label12->setGeometry(20, 415, 200, 25);
+ label12->setGeometry(20, 315, 200, 25);
label12->setText("Annotation marker");
checkbox2 = new QCheckBox(tab1);
- checkbox2->setGeometry(200, 418, 20, 20);
+ checkbox2->setGeometry(200, 318, 20, 20);
checkbox2->setTristate(false);
if(mainwindow->show_annot_markers)
{
@@ -185,23 +185,23 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
}
AnnotMkrButton = new SpecialButton(tab1);
- AnnotMkrButton->setGeometry(240, 420, 60, 15);
+ AnnotMkrButton->setGeometry(240, 320, 60, 15);
AnnotMkrButton->setColor(mainwindow->maincurve->annot_marker_color);
label12_1 = new QLabel(tab1);
- label12_1->setGeometry(20, 455, 200, 25);
+ label12_1->setGeometry(20, 345, 200, 25);
label12_1->setText("Annotation duration background");
AnnotDurationButton = new SpecialButton(tab1);
- AnnotDurationButton->setGeometry(240, 460, 60, 15);
+ AnnotDurationButton->setGeometry(240, 350, 60, 15);
AnnotDurationButton->setColor(mainwindow->maincurve->annot_duration_color);
label11 = new QLabel(tab1);
- label11->setGeometry(20, 495, 200, 25);
+ label11->setGeometry(20, 375, 200, 25);
label11->setText("Print in grayscale");
checkbox1 = new QCheckBox(tab1);
- checkbox1->setGeometry(200, 498, 20, 20);
+ checkbox1->setGeometry(200, 378, 20, 20);
checkbox1->setTristate(false);
if(mainwindow->maincurve->blackwhite_printing)
{
@@ -213,11 +213,11 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
}
label13 = new QLabel(tab1);
- label13->setGeometry(20, 535, 200, 25);
+ label13->setGeometry(20, 405, 200, 25);
label13->setText("Clip signals to pane");
checkbox4 = new QCheckBox(tab1);
- checkbox4->setGeometry(200, 538, 20, 20);
+ checkbox4->setGeometry(200, 408, 20, 20);
checkbox4->setTristate(false);
if(mainwindow->clip_to_pane)
{
@@ -228,25 +228,28 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
checkbox4->setCheckState(Qt::Unchecked);
}
+ groupbox1 = new QGroupBox("Colorschema", tab1);
+ groupbox1->setGeometry(120, 490, 180, 195);
+
colorSchema_Dark_Button = new QPushButton(tab1);
- colorSchema_Dark_Button->setGeometry(140, 580, 140, 20);
- colorSchema_Dark_Button->setText("Colorschema \"Dark\"");
+ colorSchema_Dark_Button->setGeometry(150, 520, 120, 20);
+ colorSchema_Dark_Button->setText("\"Dark\"");
colorSchema_NK_Button = new QPushButton(tab1);
- colorSchema_NK_Button->setGeometry(140, 610, 140, 20);
- colorSchema_NK_Button->setText("Colorschema \"NK\"");
+ colorSchema_NK_Button->setGeometry(150, 550, 120, 20);
+ colorSchema_NK_Button->setText("\"NK\"");
- DefaultButton = new QPushButton(tab1);
- DefaultButton->setGeometry(140, 640, 140, 20);
- DefaultButton->setText("Default colorschema");
+ colorSchema_Blue_on_Gray_Button = new QPushButton(tab1);
+ colorSchema_Blue_on_Gray_Button->setGeometry(150, 580, 120, 20);
+ colorSchema_Blue_on_Gray_Button->setText("\"Blue on gray\"");
saveColorSchemaButton = new QPushButton(tab1);
- saveColorSchemaButton->setGeometry(140, 670, 140, 20);
- saveColorSchemaButton->setText("Save colorschema");
+ saveColorSchemaButton->setGeometry(150, 610, 120, 20);
+ saveColorSchemaButton->setText("Save");
loadColorSchemaButton = new QPushButton(tab1);
- loadColorSchemaButton->setGeometry(140, 700, 140, 20);
- loadColorSchemaButton->setText("Load colorschema");
+ loadColorSchemaButton->setGeometry(150, 640, 120, 20);
+ loadColorSchemaButton->setText("Load");
QObject::connect(BgColorButton, SIGNAL(clicked(SpecialButton *)), this, SLOT(BgColorButtonClicked(SpecialButton *)));
QObject::connect(SrColorButton, SIGNAL(clicked(SpecialButton *)), this, SLOT(SrColorButtonClicked(SpecialButton *)));
@@ -266,7 +269,7 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
QObject::connect(checkbox4, SIGNAL(stateChanged(int)), this, SLOT(checkbox4Clicked(int)));
QObject::connect(saveColorSchemaButton, SIGNAL(clicked()), this, SLOT(saveColorSchemaButtonClicked()));
QObject::connect(loadColorSchemaButton, SIGNAL(clicked()), this, SLOT(loadColorSchemaButtonClicked()));
- QObject::connect(DefaultButton, SIGNAL(clicked()), this, SLOT(DefaultButtonClicked()));
+ QObject::connect(colorSchema_Blue_on_Gray_Button, SIGNAL(clicked()), this, SLOT(loadColorSchema_blue_gray()));
QObject::connect(colorSchema_NK_Button, SIGNAL(clicked()), this, SLOT(loadColorSchema_NK()));
QObject::connect(colorSchema_Dark_Button, SIGNAL(clicked()), this, SLOT(loadColorSchema_Dark()));
@@ -1222,82 +1225,6 @@ void UI_OptionsDialog::checkbox4_6Clicked(int state)
}
-void UI_OptionsDialog::DefaultButtonClicked()
-{
- int i;
-
- QPalette palette;
-
- mainwindow->maincurve->backgroundcolor = Qt::gray;
- BgColorButton->setColor(mainwindow->maincurve->backgroundcolor);
-
- mainwindow->maincurve->small_ruler_color = Qt::black;
- SrColorButton->setColor(mainwindow->maincurve->small_ruler_color);
-
- mainwindow->maincurve->big_ruler_color = Qt::darkGray;
- BrColorButton->setColor(mainwindow->maincurve->big_ruler_color);
-
- mainwindow->maincurve->mouse_rect_color = Qt::black;
- MrColorButton->setColor(mainwindow->maincurve->mouse_rect_color);
-
- mainwindow->maincurve->text_color = Qt::black;
- TxtColorButton->setColor(mainwindow->maincurve->text_color);
-
- mainwindow->maincurve->signal_color = Qt::blue;
- SigColorButton->setColor(Qt::blue);
-
- mainwindow->maincurve->baseline_color = Qt::darkGray;
- BaseColorButton->setColor(Qt::darkGray);
- mainwindow->show_baselines = 1;
- checkbox3->setCheckState(Qt::Checked);
-
- mainwindow->maincurve->crosshair_1.color = Qt::red;
- Crh1ColorButton->setColor(Qt::red);
-
- mainwindow->maincurve->crosshair_2.color = Qt::cyan;
- Crh2ColorButton->setColor(Qt::cyan);
-
- mainwindow->maincurve->floating_ruler_color = Qt::red;
- FrColorButton->setColor(Qt::red);
-
- mainwindow->maincurve->annot_marker_color = Qt::white;
- AnnotMkrButton->setColor(Qt::white);
- mainwindow->show_annot_markers = 1;
- checkbox2->setCheckState(Qt::Checked);
-
- mainwindow->maincurve->annot_duration_color.setRed(0);
- mainwindow->maincurve->annot_duration_color.setGreen(127);
- mainwindow->maincurve->annot_duration_color.setBlue(127);
- mainwindow->maincurve->annot_duration_color.setAlpha(32);
- AnnotDurationButton->setColor(mainwindow->maincurve->annot_duration_color);
-
- palette.setColor(QPalette::Text, mainwindow->maincurve->text_color);
- palette.setColor(QPalette::Base, mainwindow->maincurve->backgroundcolor);
-
- for(i=0; i<mainwindow->files_open; i++)
- {
- if(mainwindow->annotations_dock[i])
- {
- mainwindow->annotations_dock[i]->list->setPalette(palette);
- }
- }
-
- for(i=0; i<mainwindow->signalcomps; i++)
- {
- mainwindow->signalcomp[i]->color = mainwindow->maincurve->signal_color;
- }
-
- mainwindow->maincurve->blackwhite_printing = 1;
-
- checkbox1->setCheckState(Qt::Checked);
-
- checkbox4->setCheckState(Qt::Unchecked);
-
- mainwindow->maincurve->update();
-}
-
-
-
void UI_OptionsDialog::BgColorButtonClicked(SpecialButton *)
{
int i;
@@ -2055,6 +1982,81 @@ void UI_OptionsDialog::loadColorSchema_Dark()
}
+void UI_OptionsDialog::loadColorSchema_blue_gray()
+{
+ int i;
+
+ QPalette palette;
+
+ mainwindow->maincurve->backgroundcolor = Qt::gray;
+ BgColorButton->setColor(mainwindow->maincurve->backgroundcolor);
+
+ mainwindow->maincurve->small_ruler_color = Qt::black;
+ SrColorButton->setColor(mainwindow->maincurve->small_ruler_color);
+
+ mainwindow->maincurve->big_ruler_color = Qt::darkGray;
+ BrColorButton->setColor(mainwindow->maincurve->big_ruler_color);
+
+ mainwindow->maincurve->mouse_rect_color = Qt::black;
+ MrColorButton->setColor(mainwindow->maincurve->mouse_rect_color);
+
+ mainwindow->maincurve->text_color = Qt::black;
+ TxtColorButton->setColor(mainwindow->maincurve->text_color);
+
+ mainwindow->maincurve->signal_color = Qt::blue;
+ SigColorButton->setColor(Qt::blue);
+
+ mainwindow->maincurve->baseline_color = Qt::darkGray;
+ BaseColorButton->setColor(Qt::darkGray);
+ mainwindow->show_baselines = 1;
+ checkbox3->setCheckState(Qt::Checked);
+
+ mainwindow->maincurve->crosshair_1.color = Qt::red;
+ Crh1ColorButton->setColor(Qt::red);
+
+ mainwindow->maincurve->crosshair_2.color = Qt::cyan;
+ Crh2ColorButton->setColor(Qt::cyan);
+
+ mainwindow->maincurve->floating_ruler_color = Qt::red;
+ FrColorButton->setColor(Qt::red);
+
+ mainwindow->maincurve->annot_marker_color = Qt::white;
+ AnnotMkrButton->setColor(Qt::white);
+ mainwindow->show_annot_markers = 1;
+ checkbox2->setCheckState(Qt::Checked);
+
+ mainwindow->maincurve->annot_duration_color.setRed(0);
+ mainwindow->maincurve->annot_duration_color.setGreen(127);
+ mainwindow->maincurve->annot_duration_color.setBlue(127);
+ mainwindow->maincurve->annot_duration_color.setAlpha(32);
+ AnnotDurationButton->setColor(mainwindow->maincurve->annot_duration_color);
+
+ palette.setColor(QPalette::Text, mainwindow->maincurve->text_color);
+ palette.setColor(QPalette::Base, mainwindow->maincurve->backgroundcolor);
+
+ for(i=0; i<mainwindow->files_open; i++)
+ {
+ if(mainwindow->annotations_dock[i])
+ {
+ mainwindow->annotations_dock[i]->list->setPalette(palette);
+ }
+ }
+
+ for(i=0; i<mainwindow->signalcomps; i++)
+ {
+ mainwindow->signalcomp[i]->color = mainwindow->maincurve->signal_color;
+ }
+
+ mainwindow->maincurve->blackwhite_printing = 1;
+
+ checkbox1->setCheckState(Qt::Checked);
+
+ checkbox4->setCheckState(Qt::Unchecked);
+
+ mainwindow->maincurve->update();
+}
+
+
diff --git a/options_dialog.h b/options_dialog.h
index 44ea74f..827e400 100644
--- a/options_dialog.h
+++ b/options_dialog.h
@@ -61,6 +61,7 @@
#include <QGridLayout>
#include <QDesktopWidget>
#include <QFileDialog>
+#include <QGroupBox>
#include "global.h"
#include "mainwindow.h"
@@ -106,7 +107,7 @@ QVBoxLayout *mainLayout;
QHBoxLayout *horLayout;
QPushButton *CloseButton,
- *DefaultButton,
+ *colorSchema_Blue_on_Gray_Button,
*colorSchema_NK_Button,
*colorSchema_Dark_Button,
*ApplyButton,
@@ -199,6 +200,8 @@ QRadioButton *radiobutton1,
QLineEdit *lineEdit3_1;
+QGroupBox *groupbox1;
+
void update_interface(void);
private slots:
@@ -226,7 +229,6 @@ void checkbox4_3Clicked(int);
void checkbox4_4Clicked(int);
void checkbox4_5Clicked(int);
void checkbox4_6Clicked(int);
-void DefaultButtonClicked();
void ApplyButtonClicked();
void colorBarButtonClicked(SpecialButton *);
void DefaultButton2Clicked();
@@ -248,6 +250,7 @@ void saveColorSchemaButtonClicked();
void loadColorSchemaButtonClicked();
void loadColorSchema_NK();
void loadColorSchema_Dark();
+void loadColorSchema_blue_gray();
void dspinbox4_4ValueChanged(double);
};
diff --git a/print_to_bdf.cpp b/print_to_bdf.cpp
index af9363f..cd132c5 100644
--- a/print_to_bdf.cpp
+++ b/print_to_bdf.cpp
@@ -694,8 +694,6 @@ void print_screen_to_bdf(UI_Mainwindow *mainwindow)
else scratchpad[k+1] = 0;
p = strlen(scratchpad);
-
- if(p>80) break;
}
for(j=0; j<signalcomp[i]->filter_cnt; j++)
diff --git a/print_to_edf.cpp b/print_to_edf.cpp
index ce7fa35..ce2d8c2 100644
--- a/print_to_edf.cpp
+++ b/print_to_edf.cpp
@@ -691,8 +691,6 @@ void print_screen_to_edf(UI_Mainwindow *mainwindow)
else scratchpad[k+1] = 0;
p = strlen(scratchpad);
-
- if(p>80) break;
}
for(j=0; j<signalcomp[i]->filter_cnt; j++)
diff --git a/read_write_settings.cpp b/read_write_settings.cpp
index a3f5737..e514ba0 100644
--- a/read_write_settings.cpp
+++ b/read_write_settings.cpp
@@ -1213,7 +1213,9 @@ void UI_Mainwindow::read_general_settings()
return;
}
- average_period = atof(result);
+ average_period = atoi(result);
+
+ if(average_period < 1) average_period = 300;
xml_go_up(xml_hdl);
}
@@ -1622,6 +1624,86 @@ void UI_Mainwindow::read_general_settings()
xml_go_up(xml_hdl);
}
+ if(!(xml_goto_nth_element_inside(xml_hdl, "annotfilter_var", 0)))
+ {
+ if(!(xml_goto_nth_element_inside(xml_hdl, "tmin", 0)))
+ {
+ if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN))
+ {
+ xml_close(xml_hdl);
+ return;
+ }
+
+ annot_filter->tmin = atoi(result);
+ if(annot_filter->tmin < 1) annot_filter->tmin = 1;
+ if(annot_filter->tmin > 500000) annot_filter->tmin = 500000;
+
+ xml_go_up(xml_hdl);
+ }
+
+ if(!(xml_goto_nth_element_inside(xml_hdl, "tmax", 0)))
+ {
+ if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN))
+ {
+ xml_close(xml_hdl);
+ return;
+ }
+
+ annot_filter->tmax = atoi(result);
+ if(annot_filter->tmax < 1) annot_filter->tmax = 1;
+ if(annot_filter->tmax > 500000) annot_filter->tmax = 500000;
+
+ xml_go_up(xml_hdl);
+ }
+
+ if(!(xml_goto_nth_element_inside(xml_hdl, "invert", 0)))
+ {
+ if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN))
+ {
+ xml_close(xml_hdl);
+ return;
+ }
+
+ annot_filter->invert = atoi(result);
+ if(annot_filter->invert < 0) annot_filter->invert = 0;
+ if(annot_filter->invert > 1) annot_filter->invert = 1;
+
+ xml_go_up(xml_hdl);
+ }
+
+ if(!(xml_goto_nth_element_inside(xml_hdl, "hide_other", 0)))
+ {
+ if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN))
+ {
+ xml_close(xml_hdl);
+ return;
+ }
+
+ annot_filter->hide_other = atoi(result);
+ if(annot_filter->hide_other < 0) annot_filter->hide_other = 0;
+ if(annot_filter->hide_other > 1) annot_filter->hide_other = 1;
+
+ xml_go_up(xml_hdl);
+ }
+
+ if(!(xml_goto_nth_element_inside(xml_hdl, "hide_in_list_only", 0)))
+ {
+ if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN))
+ {
+ xml_close(xml_hdl);
+ return;
+ }
+
+ annot_filter->hide_in_list_only = atoi(result);
+ if(annot_filter->hide_in_list_only < 0) annot_filter->hide_in_list_only = 0;
+ if(annot_filter->hide_in_list_only > 1) annot_filter->hide_in_list_only = 1;
+
+ xml_go_up(xml_hdl);
+ }
+
+ xml_go_up(xml_hdl);
+ }
+
if(!(xml_goto_nth_element_inside(xml_hdl, "check_for_updates", 0)))
{
if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN))
@@ -1994,7 +2076,7 @@ void UI_Mainwindow::write_settings()
fprintf(cfgfile, " <mousewheelsens>%i</mousewheelsens>\n", mousewheelsens);
- fprintf(cfgfile, " <average_period>%f</average_period>\n", average_period);
+ fprintf(cfgfile, " <average_period>%i</average_period>\n", average_period);
fprintf(cfgfile, " <average_ratio>%i</average_ratio>\n", average_ratio);
@@ -2048,6 +2130,20 @@ void UI_Mainwindow::write_settings()
fprintf(cfgfile, " </raw2edf_var>\n");
+ fprintf(cfgfile, " <annotfilter_var>\n");
+
+ fprintf(cfgfile, " <tmin>%i</tmin>\n", annot_filter->tmin);
+
+ fprintf(cfgfile, " <tmax>%i</tmax>\n", annot_filter->tmax);
+
+ fprintf(cfgfile, " <invert>%i</invert>\n", annot_filter->invert);
+
+ fprintf(cfgfile, " <hide_other>%i</hide_other>\n", annot_filter->hide_other);
+
+ fprintf(cfgfile, " <hide_in_list_only>%i</hide_in_list_only>\n", annot_filter->hide_in_list_only);
+
+ fprintf(cfgfile, " </annotfilter_var>\n");
+
fprintf(cfgfile, " <check_for_updates>%i</check_for_updates>\n", check_for_updates);
fprintf(cfgfile, " <viewtime_indicator_type>%i</viewtime_indicator_type>\n", viewtime_indicator_type);
diff --git a/reduce_signals.cpp b/reduce_signals.cpp
index e9c0de0..e040c10 100644
--- a/reduce_signals.cpp
+++ b/reduce_signals.cpp
@@ -118,6 +118,10 @@ UI_ReduceSignalsWindow::UI_ReduceSignalsWindow(QWidget *w_parent)
pushButton1 = new QPushButton(myobjectDialog);
pushButton1->setGeometry(20, 528, 100, 25);
pushButton1->setText("Select File");
+ if(mainwindow->files_open < 2)
+ {
+ pushButton1->setEnabled(false);
+ }
pushButton2 = new QPushButton(myobjectDialog);
pushButton2->setGeometry(575, 528, 100, 25);
@@ -166,6 +170,11 @@ UI_ReduceSignalsWindow::UI_ReduceSignalsWindow(QWidget *w_parent)
inputpath[0] = 0;
+ if(mainwindow->files_open == 1)
+ {
+ SelectFileButton();
+ }
+
myobjectDialog->exec();
}
@@ -386,8 +395,7 @@ void UI_ReduceSignalsWindow::Set_SRdivider_all_signals()
void UI_ReduceSignalsWindow::SelectFileButton()
{
- int i, j,
- days;
+ int i, j, k, days, found;
long long seconds,
milliSec;
@@ -426,11 +434,18 @@ void UI_ReduceSignalsWindow::SelectFileButton()
label4->setEnabled(false);
label5->setEnabled(false);
- UI_activeFileChooserWindow afchooser(&file_num, mainwindow);
+ if(mainwindow->files_open > 1)
+ {
+ UI_activeFileChooserWindow afchooser(&file_num, mainwindow);
- if(file_num < 0)
+ if(file_num < 0)
+ {
+ return;
+ }
+ }
+ else
{
- return;
+ file_num = 0;
}
edfhdr = mainwindow->edfheaderlist[file_num];
@@ -498,7 +513,6 @@ void UI_ReduceSignalsWindow::SelectFileButton()
{
if(!(edfhdr->edfparam[i].smp_per_record % j))
{
-// snprintf(str, 256, "%i (%f", j, ((double)(edfhdr->edfparam[i].smp_per_record / j)) / edfhdr->data_record_duration);
snprintf(str, 256, "%i (", j);
convert_to_metric_suffix(str + strlen(str),
((double)(edfhdr->edfparam[i].smp_per_record / j)) / edfhdr->data_record_duration,
@@ -511,6 +525,35 @@ void UI_ReduceSignalsWindow::SelectFileButton()
}
}
+ for(i=0, found=0; i<edfhdr->edfsignals; i++)
+ {
+ if(edfhdr->edfparam[i].annotation) continue;
+
+ for(j=0; j<mainwindow->signalcomps; j++)
+ {
+ for(k=0; k<mainwindow->signalcomp[j]->num_of_signals; k++)
+ {
+ if(mainwindow->signalcomp[j]->edfsignal[k] == i)
+ {
+ found = 1;
+
+ break;
+ }
+ }
+
+ if(found) break;
+ }
+
+ if(found)
+ {
+ found = 0;
+ }
+ else
+ {
+ ((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->setCheckState(Qt::Unchecked);
+ }
+ }
+
pushButton3->setEnabled(true);
pushButton4->setEnabled(true);
pushButton5->setEnabled(true);
@@ -1206,60 +1249,57 @@ void UI_ReduceSignalsWindow::StartConversion()
{
for(i=0; i<annots_per_datrec; i++)
{
- if(annot_cnt < annot_list_sz)
- {
- annot_ptr = edfplus_annotation_get_item(&new_annot_list, annot_cnt);
+ if(annot_cnt >= annot_list_sz) break;
- len = snprintf(scratchpad, 256, "%+i.%07i",
- (int)(annot_ptr->onset / TIME_DIMENSION),
- (int)(annot_ptr->onset % TIME_DIMENSION));
+ annot_ptr = edfplus_annotation_get_item(&new_annot_list, annot_cnt++);
- for(j=0; j<7; j++)
- {
- if(scratchpad[len - j - 1] != '0')
- {
- break;
- }
- }
+ len = snprintf(scratchpad, 256, "%+i.%07i",
+ (int)(annot_ptr->onset / TIME_DIMENSION),
+ (int)(annot_ptr->onset % TIME_DIMENSION));
- if(j)
+ for(j=0; j<7; j++)
+ {
+ if(scratchpad[len - j - 1] != '0')
{
- len -= j;
-
- if(j == 7)
- {
- len--;
- }
+ break;
}
+ }
- if(fwrite(scratchpad, len, 1, outputfile) != 1)
+ if(j)
+ {
+ len -= j;
+
+ if(j == 7)
{
- progress.reset();
- showpopupmessage("Error", "Write error (5).");
- goto END_4;
+ len--;
}
+ }
- tallen += len;
-
- if(annot_ptr->duration[0]!=0)
- {
- fputc(21, outputfile);
- tallen++;
+ if(fwrite(scratchpad, len, 1, outputfile) != 1)
+ {
+ progress.reset();
+ showpopupmessage("Error", "Write error (5).");
+ goto END_4;
+ }
- tallen += fprintf(outputfile, "%s", annot_ptr->duration);
- }
+ tallen += len;
- fputc(20, outputfile);
+ if(annot_ptr->duration[0]!=0)
+ {
+ fputc(21, outputfile);
tallen++;
- tallen += fprintf(outputfile, "%s", annot_ptr->annotation);
+ tallen += fprintf(outputfile, "%s", annot_ptr->duration);
+ }
- fputc(20, outputfile);
- fputc(0, outputfile);
- tallen += 2;
+ fputc(20, outputfile);
+ tallen++;
- annot_cnt--;
- }
+ tallen += fprintf(outputfile, "%s", annot_ptr->annotation);
+
+ fputc(20, outputfile);
+ fputc(0, outputfile);
+ tallen += 2;
}
}
diff --git a/statistics_dialog.cpp b/statistics_dialog.cpp
index bb74ecd..4b8f473 100644
--- a/statistics_dialog.cpp
+++ b/statistics_dialog.cpp
@@ -31,15 +31,29 @@
#include "statistics_dialog.h"
+#define STAT_JOB_SRC_SIGNAL 0
+#define STAT_JOB_SRC_ECG 1
+#define STAT_JOB_SRC_ANNOT 2
-UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp, long long pagetime)
+#define BEAT_IVAL_SIZE 262144
+
+
+
+
+UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp,
+ long long pagetime,
+ struct annotation_list *annot_list,
+ struct annotationblock *annot)
{
int i,
tmp,
+ NN20,
+ pNN20,
NN50,
- pNN50;
+ pNN50,
+ job_src=0;
- char stat_str[2048];
+ char stat_str[2048]={""};
double d_tmp,
average_bpm,
@@ -48,7 +62,11 @@ UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp, long
sdnn_rr,
*buf_bpm,
rmssd_rr,
- *beat_interval_list;
+ *beat_interval_list=NULL;
+
+ long long l_tmp=0;
+
+ struct annotationblock *tmp_annot;
StatDialog = new QDialog;
StatDialog->setWindowTitle("Statistics");
@@ -57,7 +75,25 @@ UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp, long
StatDialog->setWindowFlags(Qt::Window | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint);
StatDialog->setWindowIcon(QIcon(":/images/edf.png"));
- if(signalcomp->ecg_filter != NULL)
+ if(signalcomp != NULL)
+ {
+ if(signalcomp->ecg_filter != NULL)
+ {
+ job_src = STAT_JOB_SRC_ECG;
+ }
+ else
+ {
+ job_src = STAT_JOB_SRC_SIGNAL;
+ }
+ }
+ else
+ {
+ job_src = STAT_JOB_SRC_ANNOT;
+
+ beat_interval_list = (double *)malloc(sizeof(double) * BEAT_IVAL_SIZE);
+ }
+
+ if((job_src == STAT_JOB_SRC_ECG) || (job_src == STAT_JOB_SRC_ANNOT))
{
StatDialog->setMinimumSize(600, 400);
StatDialog->setSizeGripEnabled(true);
@@ -79,10 +115,22 @@ UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp, long
curve1->setBackgroundColor(Qt::black);
curve1->setRasterColor(Qt::gray);
curve1->setTraceWidth(0);
- curve1->setH_label(signalcomp->physdimension);
+ if(job_src == STAT_JOB_SRC_ECG)
+ {
+ curve1->setH_label(signalcomp->physdimension);
+ }
curve1->setLowerLabel("HR (beats/min)");
curve1->setDashBoardEnabled(false);
- curve1->setUpperLabel1("Distribution");
+ if(job_src == STAT_JOB_SRC_ANNOT)
+ {
+ strcpy(stat_str, "Distribution ");
+ strcat(stat_str, annot->annotation);
+ curve1->setUpperLabel1(stat_str);
+ }
+ else
+ {
+ curve1->setUpperLabel1("Distribution");
+ }
curve1->setFillSurfaceEnabled(true);
vlayout2_1 = new QVBoxLayout;
@@ -91,7 +139,8 @@ UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp, long
vlayout2_1->addWidget(startSlider);
vlayout2_1->addWidget(stopSlider);
}
- else
+
+ if(job_src == STAT_JOB_SRC_SIGNAL)
{
StatDialog->setMinimumSize(300, 400);
StatDialog->setMaximumSize(300, 400);
@@ -116,7 +165,7 @@ UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp, long
hlayout1 = new QHBoxLayout;
hlayout1->addLayout(vlayout1_1, 1);
- if(signalcomp->ecg_filter != NULL)
+ if((job_src == STAT_JOB_SRC_ECG) || (job_src == STAT_JOB_SRC_ANNOT))
{
hlayout1->addLayout(vlayout2_1, 100);
}
@@ -130,7 +179,7 @@ UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp, long
bpm_distribution[i] = 0;
}
- if(signalcomp->ecg_filter == NULL)
+ if(job_src == STAT_JOB_SRC_SIGNAL)
{
if((signalcomp->stat_cnt < 1) || (pagetime < 10LL))
{
@@ -191,11 +240,39 @@ UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp, long
}
}
}
- else
+
+ if((job_src == STAT_JOB_SRC_ECG) || (job_src == STAT_JOB_SRC_ANNOT))
{
- beat_cnt = ecg_filter_get_beat_cnt(signalcomp->ecg_filter);
+ if(job_src == STAT_JOB_SRC_ECG)
+ {
+ beat_cnt = ecg_filter_get_beat_cnt(signalcomp->ecg_filter);
- beat_interval_list = ecg_filter_get_interval_beatlist(signalcomp->ecg_filter);
+ beat_interval_list = ecg_filter_get_interval_beatlist(signalcomp->ecg_filter);
+ }
+
+ if(job_src == STAT_JOB_SRC_ANNOT)
+ {
+ for(i=0, beat_cnt=0; beat_cnt<BEAT_IVAL_SIZE; i++)
+ {
+ tmp_annot = edfplus_annotation_get_item_visible_only(annot_list, i);
+
+ if(tmp_annot == NULL) break;
+
+ if(!strcmp(tmp_annot->annotation, annot->annotation))
+ {
+ if(beat_cnt)
+ {
+ beat_interval_list[beat_cnt - 1] = ((double)(tmp_annot->onset - l_tmp)) / (double)TIME_DIMENSION;
+ }
+
+ l_tmp = tmp_annot->onset;
+
+ beat_cnt++;
+ }
+ }
+
+ if(beat_cnt) beat_cnt--;
+ }
if(beat_cnt < 3)
{
@@ -208,6 +285,7 @@ UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp, long
sdnn_bpm = 0.0;
sdnn_rr = 0.0;
rmssd_rr = 0.0;
+ NN20 = 0;
NN50 = 0;
buf_bpm = (double *)malloc(sizeof(double) * beat_cnt);
@@ -231,6 +309,11 @@ UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp, long
rmssd_rr += (d_tmp * d_tmp);
+ if(((beat_interval_list[i] - beat_interval_list[i + 1]) > 0.02 ) || ((beat_interval_list[i + 1] - beat_interval_list[i]) > 0.02 ))
+ {
+ NN20++;
+ }
+
if(((beat_interval_list[i] - beat_interval_list[i + 1]) > 0.05 ) || ((beat_interval_list[i + 1] - beat_interval_list[i]) > 0.05 ))
{
NN50++;
@@ -243,6 +326,7 @@ UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp, long
rmssd_rr /= beat_cnt;
rmssd_rr = sqrt(rmssd_rr);
+ pNN20 = (NN20 * 100) / (beat_cnt - 1);
pNN50 = (NN50 * 100) / (beat_cnt - 1);
for(i=0; i<beat_cnt; i++)
@@ -262,6 +346,8 @@ UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp, long
"RMSSD RR: %3i ms\n\n"
"Mean HR: %3.3f bpm\n\n"
"SDNN HR: %3.3f bpm\n\n"
+ "NN20: %3i\n\n"
+ "pNN20: %3i %%\n\n"
"NN50: %3i\n\n"
"pNN50: %3i %%\n\n",
beat_cnt,
@@ -270,6 +356,8 @@ UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp, long
(int)rmssd_rr,
average_bpm,
sdnn_bpm,
+ NN20,
+ pNN20,
NN50,
pNN50);
@@ -339,6 +427,11 @@ UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp, long
}
}
+ if(job_src == STAT_JOB_SRC_ANNOT)
+ {
+ free(beat_interval_list);
+ }
+
Label1->setText(stat_str);
StatDialog->exec();
diff --git a/statistics_dialog.h b/statistics_dialog.h
index 01f6883..d03c667 100644
--- a/statistics_dialog.h
+++ b/statistics_dialog.h
@@ -51,6 +51,7 @@
#include "global.h"
#include "ecg_filter.h"
#include "signalcurve.h"
+#include "edf_annot_list.h"
@@ -61,7 +62,10 @@ class UI_StatisticWindow : public QObject
public:
-UI_StatisticWindow(struct signalcompblock *, long long);
+UI_StatisticWindow(struct signalcompblock *,
+ long long,
+ struct annotation_list *annot_list=NULL,
+ struct annotationblock *annot=NULL);
private:
diff --git a/version.txt b/version.txt
index bb4337e..0ea6393 100644
--- a/version.txt
+++ b/version.txt
@@ -1,5 +1,21 @@
- version 1.60 to be defined
+ version 1.61 November 1, 2017
+ --------------
+
+ - Fixed a bug that caused a freeze/lockup when using the annotationlist filter.
+
+ - Added the possibility to filter annotations based on minimum and maximum interval time.
+
+ - Fixed a regression bug that could cause a crash when using the "reduce signals" tool
+ with an EDF+ file.
+
+ - Added a tool to export filtered and or derived signals to a new file.
+
+ - Added the possibility to view the Heart Rate Variability using the annotation list.
+
+
+
+ version 1.60 September 16, 2017
--------------
- Improve parameter checking for signal composition when loading a montage file.
diff --git a/viewcurve.cpp b/viewcurve.cpp
index 1bd0bec..cc8a8e9 100644
--- a/viewcurve.cpp
+++ b/viewcurve.cpp
@@ -63,18 +63,52 @@ ViewCurve::ViewCurve(QWidget *w_parent) : QWidget(w_parent)
original_sensitivity = (double *)calloc(1, sizeof(double[MAXSIGNALS]));
- backgroundcolor = Qt::gray;
- small_ruler_color = Qt::black;
- big_ruler_color = Qt::darkGray;
- mouse_rect_color = Qt::black;
- text_color = Qt::black;
- signal_color = Qt::blue;
- baseline_color = Qt::darkGray;
- crosshair_1.color = Qt::red;
- crosshair_2.color = Qt::cyan;
- floating_ruler_color = Qt::red;
- annot_marker_color = Qt::white;
- annot_duration_color = QColor(0, 127, 127, 32);
+////////////////////////////////////////////////////////
+
+ backgroundcolor.setRed(64);
+ backgroundcolor.setGreen(64);
+ backgroundcolor.setBlue(64);
+
+ small_ruler_color.setRed(255);
+ small_ruler_color.setGreen(255);
+ small_ruler_color.setBlue(255);
+
+ big_ruler_color.setRed(128);
+ big_ruler_color.setGreen(128);
+ big_ruler_color.setBlue(128);
+
+ mouse_rect_color.setRed(255);
+ mouse_rect_color.setGreen(255);
+ mouse_rect_color.setBlue(255);
+
+ text_color.setRed(255);
+ text_color.setGreen(255);
+ text_color.setBlue(255);
+
+ baseline_color.setRed(128);
+ baseline_color.setGreen(128);
+ baseline_color.setBlue(128);
+
+ annot_marker_color.setRed(255);
+ annot_marker_color.setGreen(255);
+ annot_marker_color.setBlue(255);
+
+ annot_duration_color.setRed(0);
+ annot_duration_color.setGreen(127);
+ annot_duration_color.setBlue(127);
+ annot_duration_color.setAlpha(32);
+
+ signal_color = 12;
+
+ floating_ruler_color = 10;
+
+ blackwhite_printing = 1;
+
+ crosshair_1.color = 7;
+
+ crosshair_2.color = 10;
+
+/////////////////////////////////////////////////////////
crosshair_1.active = 0;
crosshair_2.active = 0;
@@ -1490,7 +1524,7 @@ void ViewCurve::drawCurve_stage_2(QPainter *painter, int w_width, int w_height,
{
l_tmp = annot->onset - mainwindow->edfheaderlist[i]->starttime_offset;
- if(((l_tmp + annot->long_duration) > (mainwindow->edfheaderlist[i]->viewtime - TIME_DIMENSION)) && (!annot->hided) && (!annot->hided_in_list))
+ if(((l_tmp + annot->long_duration) > (mainwindow->edfheaderlist[i]->viewtime - TIME_DIMENSION)) && (!annot->hided))
{
if(l_tmp > (mainwindow->edfheaderlist[i]->viewtime + mainwindow->pagetime))
{
@@ -1934,7 +1968,7 @@ void ViewCurve::drawCurve_stage_2(QPainter *painter, int w_width, int w_height,
l_tmp = annot->onset - mainwindow->edfheaderlist[i]->starttime_offset;
- if((l_tmp > (mainwindow->edfheaderlist[i]->viewtime - TIME_DIMENSION)) && (!annot->hided) && (!annot->hided_in_list))
+ if((l_tmp > (mainwindow->edfheaderlist[i]->viewtime - TIME_DIMENSION)) && (!annot->hided))
{
if(l_tmp > (mainwindow->edfheaderlist[i]->viewtime + mainwindow->pagetime))
{
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/edfbrowser.git
More information about the debian-med-commit
mailing list