Skip to content
Commits on Source (6)
......@@ -97,7 +97,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.6 #
# in a new and separate directory: /usr/local/Qt-5.9.7-static #
# #
# It will not interfere with other Qt programs. #
# #
......@@ -107,16 +107,16 @@ mkdir Qt5-source
cd Qt5-source
wget http://ftp1.nluug.nl/languages/qt/official_releases/qt/5.9/5.9.6/single/qt-everywhere-opensource-src-5.9.6.tar.xz
wget http://ftp1.nluug.nl/languages/qt/official_releases/qt/5.9/5.9.7/single/qt-everywhere-opensource-src-5.9.7.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.6.tar.xz
The Qt source package you are going to need is: qt-everywhere-opensource-src-5.9.7.tar.xz
tar -xvf qt-everywhere-opensource-src-5.9.6.tar.xz
tar -xvf qt-everywhere-opensource-src-5.9.7.tar.xz
cd qt-everywhere-opensource-src-5.9.6
cd qt-everywhere-opensource-src-5.9.7
./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
./configure -v -prefix /usr/local/Qt-5.9.7-static -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
(takes about 1.5 minutes)
......@@ -128,7 +128,7 @@ sudo make install
Now go to the directory that contains the EDFbrowser sourcecode and enter the following commands:
/usr/local/Qt-5.9.6/bin/qmake
/usr/local/Qt-5.9.7-static/bin/qmake
make -j8
......
......@@ -83,6 +83,9 @@ UI_Annotationswindow::UI_Annotationswindow(int file_number, QWidget *w_parent)
checkbox2->setTristate(false);
checkbox2->setCheckState(Qt::Unchecked);
more_button = new QPushButton("More");
more_button->setMaximumWidth(40);
list = new QListWidget(dialog1);
list->setFont(*mainwindow->monofont);
list->setAutoFillBackground(true);
......@@ -123,6 +126,7 @@ UI_Annotationswindow::UI_Annotationswindow(int file_number, QWidget *w_parent)
h_layout->addWidget(label1);
h_layout->addWidget(lineedit1);
h_layout->addWidget(checkbox2);
h_layout->addWidget(more_button);
v_layout = new QVBoxLayout(dialog1);
v_layout->addLayout(h_layout);
......@@ -137,6 +141,7 @@ UI_Annotationswindow::UI_Annotationswindow(int file_number, QWidget *w_parent)
QObject::connect(docklist, SIGNAL(visibilityChanged(bool)), this, SLOT(hide_editdock(bool)));
QObject::connect(checkbox1, SIGNAL(stateChanged(int)), this, SLOT(checkbox1_clicked(int)));
QObject::connect(checkbox2, SIGNAL(stateChanged(int)), this, SLOT(checkbox2_clicked(int)));
QObject::connect(more_button, SIGNAL(clicked(bool)), this, SLOT(more_button_clicked(bool)));
QObject::connect(hide_annot_act, SIGNAL(triggered(bool)), this, SLOT(hide_annot(bool)));
QObject::connect(unhide_annot_act, SIGNAL(triggered(bool)), this, SLOT(unhide_annot(bool)));
QObject::connect(hide_same_annots_act, SIGNAL(triggered(bool)), this, SLOT(hide_same_annots(bool)));
......@@ -154,8 +159,18 @@ UI_Annotationswindow::UI_Annotationswindow(int file_number, QWidget *w_parent)
}
void UI_Annotationswindow::more_button_clicked(bool)
{
QMessageBox messagewindow(QMessageBox::Information, "Info", "Right-click on an annotation for more options.");
messagewindow.exec();
return;
}
void UI_Annotationswindow::show_stats(bool)
{
char str[4096]="";
struct annotation_list *annot_list;
struct annotationblock *annot;
......@@ -169,7 +184,6 @@ void UI_Annotationswindow::show_stats(bool)
{
QMessageBox messagewindow(QMessageBox::Critical, "Error", "Close the annotation editor and try again.");
messagewindow.exec();
return;
}
......@@ -179,10 +193,24 @@ void UI_Annotationswindow::show_stats(bool)
}
annot_list = &mainwindow->edfheaderlist[file_num]->annot_list;
if(annot_list == NULL)
{
sprintf(str, "Nullpointer returned: file: %s line %i", __FILE__, __LINE__);
QMessageBox messagewindow(QMessageBox::Critical, "Error", str);
messagewindow.exec();
return;
}
annot = edfplus_annotation_get_item_visible_only(annot_list, list->currentRow());
if(annot == NULL)
{
sprintf(str, "Nullpointer returned: file: %s line %i", __FILE__, __LINE__);
QMessageBox messagewindow(QMessageBox::Critical, "Error", str);
messagewindow.exec();
return;
}
UI_StatisticWindow stats_wndw(NULL, 0LL, annot_list, annot);
UI_StatisticWindow stats_wndw(NULL, 0LL, mainwindow, annot_list, annot);
}
......@@ -389,6 +417,15 @@ void UI_Annotationswindow::filter_edited(const QString text)
{
annot->hided_in_list = 1;
if(mainwindow->annot_filter->hide_in_list_only)
{
annot->hided = 0;
}
else
{
annot->hided = 1;
}
n = strlen(annot->annotation) - len + 1;
for(j=0; j<n; j++)
......@@ -416,6 +453,8 @@ void UI_Annotationswindow::filter_edited(const QString text)
{
annot->hided_in_list = 0;
annot->hided = 0;
n = strlen(annot->annotation) - len + 1;
for(j=0; j<n; j++)
......@@ -424,7 +463,10 @@ void UI_Annotationswindow::filter_edited(const QString text)
{
annot->hided_in_list = 1;
if(!mainwindow->annot_filter->hide_in_list_only)
{
annot->hided = 1;
}
break;
}
......
......@@ -50,6 +50,7 @@
#include <QAction>
#include <QMessageBox>
#include <QVariant>
#include <QPushButton>
#include <stdio.h>
#include <stdlib.h>
......@@ -108,6 +109,8 @@ private:
QLineEdit *lineedit1;
QPushButton *more_button;
QAction *show_between_act,
*average_annot_act,
*hide_annot_act,
......@@ -128,6 +131,7 @@ private slots:
void hide_editdock(bool);
void checkbox1_clicked(int);
void checkbox2_clicked(int);
void more_button_clicked(bool);
void show_between(bool);
void average_annot(bool);
void hide_annot(bool);
......
......@@ -238,7 +238,7 @@ void UI_AverageCurveWindow::export_edf(void)
smpls_left;
char path[MAX_PATH_LENGTH],
str[512];
str[4096];
double *buf,
frequency,
......@@ -407,6 +407,11 @@ void UI_AverageCurveWindow::export_edf(void)
if(p>80) break;
}
if(signalcomp->fir_filter)
{
p += sprintf(str + p, "FIR ");
}
strcat(str, signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].prefilter);
edf_set_prefilter(edf_hdl, 0, str);
edf_set_transducer(edf_hdl, 0, signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].transducer);
......
......@@ -603,6 +603,16 @@ void UI_AveragerWindow::process_avg(struct signalcompblock *signalcomp)
dig_value = signalcomp->fidfuncp[k](signalcomp->fidbuf[k], dig_value);
}
if(signalcomp->fir_filter != NULL)
{
if(s==signalcomp->sample_start)
{
fir_filter_restore_buf(signalcomp->fir_filter);
}
dig_value = run_fir_filter(dig_value, signalcomp->fir_filter);
}
if(signalcomp->plif_ecg_filter)
{
if(s==signalcomp->sample_start)
......
edfbrowser (1.66+dfsg-1) unstable; urgency=medium
* New upstream version
* Standards-Version: 4.2.1
* Remove trailing whitespace in debian/changelog
-- Andreas Tille <tille@debian.org> Wed, 28 Nov 2018 08:06:10 +0100
edfbrowser (1.65+dfsg-1) unstable; urgency=medium
* New upstream version
......
......@@ -10,7 +10,7 @@ Build-Depends: debhelper (>= 11~),
libqt5opengl5-dev,
qttools5-dev-tools,
libedf-dev
Standards-Version: 4.1.5
Standards-Version: 4.2.1
Vcs-Browser: https://salsa.debian.org/med-team/edfbrowser
Vcs-Git: https://salsa.debian.org/med-team/edfbrowser.git
Homepage: http://www.teuniz.net/edfbrowser/
......
......@@ -7,7 +7,7 @@
<meta name="description" content="EDFbrowser manual">
</head><body>
<h1>EDFbrowser 1.65 manual</h1>
<h1>EDFbrowser 1.66 manual</h1>
<p><br></p>
......@@ -32,10 +32,12 @@
<li><a href="#Filters">Filters</a></li>
<li><a href="#Adjust_filters">Adjust filters</a></li>
<li><a href="#Powerspectrum">Powerspectrum</a></li>
<li><a href="#Averaging_EP">Averaging (evoked potentials or other triggers)</a></li>
<li><a href="#Averaging_EP">Averaging (evoked potentials, heart beats or other triggers)</a></li>
<li><a href="#ECG_PLIF_filter">ECG powerline interference filter</a></li>
<li><a href="#ECG_detection">ECG heartrate detection</a></li>
<li><a href="#HR_statistics">Heart Rate statistics</a></li>
<li><a href="#Export_Import_ECG_RR_interval">Export/Import ECG RR-interval</a></li>
<li><a href="#Custom_fir_filter">Custom FIR filter</a></li>
<li><a href="#Spike_filter">Spike filter</a></li>
<li><a href="#Zoomfunction">Zoomfunction</a></li>
<li><a href="#Floatingruler">Floating ruler</a></li>
......@@ -448,7 +450,7 @@
<p><br><br></p>
<h3><a name="Averaging_EP">Averaging (evoked potentials or other triggers)</a></h3>
<h3><a name="Averaging_EP">Averaging (evoked potentials, heart beats or other triggers)</a></h3>
<p>
Averaging waveforms (multiple parts of a signal) can be done by rightclicking on an annotation (trigger) in<br>
......@@ -539,7 +541,7 @@
<br>
Some statistics about the Heart Rate (variability) are available <a href="#HR_statistics">here</a>.<br>
<br>
Important: before using the Heart Rate detection, go to the settings menu (Settings -&gt; Other) and adjust the "Powerline Frequency" to the frequency used in the country<br>
Note: before using the Heart Rate detection, go to the settings menu (Settings -&gt; Other) and adjust the "Powerline Frequency" to the frequency used in the country<br>
where the recording of the ECG took place (50 or 60 Hz). Otherwise the powerline noise suppression filter in the Heart Rate detection algorithm will not work correctly.
</p>
......@@ -564,7 +566,31 @@
- 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>
The data used for the statistics is derived from the timewindow that is visible on the screen.
The data used for the statistics is derived from the timewindow that is visible on the screen.<br>
<br>
In case you want to see this info permanently at the bottom of the screen during navigation through the file,<br>
use the following procedure.<br>
First, import the output of the <a href="#ECG_detection">ECG heartrate detection</a> as annotations as described here: <a href="#Export_Import_ECG_RR_interval">Export/Import ECG RR-interval</a><br>
Now right-click on an annotation named "R-onset" and select "Heart Rate Variability".<br>
A new window with the statistics will appear. Close it.<br>
From now on, after changing file position e.g. PgUp/PgDn, you will see the updated statistics at the bottom of the screen.
</p>
<p><br></p>
<p><a href="#Table_of_Contents">Table of Contents</a></p>
<p><br><br></p>
<h3><a name="Export_Import_ECG_RR_interval">Export/Import ECG RR-interval</a></h3>
<p>
This tool can be used to export the output of the <a href="#ECG_detection">ECG heartrate detection</a>,<br>
or<br>
it can be used to import the output of the <a href="#ECG_detection">ECG heartrate detection</a> as annotations.<br>
<br>
After having imported the <a href="#ECG_detection">ECG heartrate detection</a> output as annotations, more options<br>
are available by right-clicking on one of the annotations in the annotationlist.
</p>
<p><br></p>
......@@ -573,6 +599,38 @@
<p><br><br></p>
<h3><a name="Custom_fir_filter">Custom FIR filter</a></h3>
<p>
The Custom FIR filter can be used to create a customized FIR filter.<br>
Simply copy and paste a list of filter coefficients (so-called "filter taps") in the Filter taps list<br>
and select the signals which to apply to.<br>
The maximum number of filter taps is limited to 5000.<br>
An easy way to create FIR filters is to use an online design tool like <a href="http://t-filter.engineerjs.com/">http://t-filter.engineerjs.com/</a><br>
It generates a list of filter coefficients which can be copy and pasted into EDFbrowser's Custom FIR filter dialog.<br>
For example, the following list of filter coefficients is equivalent to a moving average filter (boxcar filter) with 10 samples (filter taps):<br>
(You can copy and paste the following list into EDFbrowser as an example.)
</p>
<pre>
0.1
0.1
0.1
0.1
0.1
0.1
0.1
0.1
0.1
0.1
</pre>
<p><br></p>
<p><a href="#Table_of_Contents">Table of Contents</a></p>
<p><br><br></p>
<h3><a name="Spike_filter">Spike filter</a></h3>
<p>
......
......@@ -39,6 +39,8 @@
// #define ECG_FILTER_DEBUG_ACTIVE
// #define ECG_FILTER_DEBUG_ACTIVE_2
struct ecg_filter_settings * create_ecg_filter(double sf, double bitval, int powerlinefreq)
......@@ -539,6 +541,9 @@ double run_ecg_filter(double new_sample, struct ecg_filter_settings *settings)
}
settings->stat_buf_idx++;
#ifdef ECG_FILTER_DEBUG_ACTIVE_2
printf("beats: %i\n", settings->stat_buf_idx);
#endif
}
settings->sample_cntr = 1;
......
......@@ -41,6 +41,10 @@
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
......@@ -131,7 +135,6 @@ struct ecg_filter_settings{
};
struct ecg_filter_settings * create_ecg_filter(double, double, int);
double run_ecg_filter(double, struct ecg_filter_settings *);
void free_ecg_filter(struct ecg_filter_settings *);
......@@ -141,6 +144,13 @@ void reset_ecg_filter(struct ecg_filter_settings *);
int ecg_filter_get_beat_cnt(struct ecg_filter_settings *);
long long * ecg_filter_get_onset_beatlist(struct ecg_filter_settings *);
double * ecg_filter_get_interval_beatlist(struct ecg_filter_settings *);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
......
/*
***************************************************************************
*
* Author: Teunis van Beelen
*
* Copyright (C) 2018 Teunis van Beelen
*
* Email: teuniz@gmail.com
*
***************************************************************************
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, 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 "ecg_statistics.h"
int ecg_get_hr_statistics(double *beat_interval_list, int beat_cnt, struct ecg_hr_statistics_struct *ecg_stats)
{
int i,
NN20=0,
NN50=0;
double d_tmp,
average_bpm=0,
average_rr=0,
sdnn_bpm=0,
sdnn_rr=0,
rmssd_rr=0,
*buf_bpm=NULL;
if(beat_interval_list == NULL) return -1;
if(ecg_stats == NULL) return -2;
if(beat_cnt < 3) return -3;
buf_bpm = (double *)malloc(sizeof(double) * beat_cnt);
if(buf_bpm == NULL)
{
return -4;
}
for(i=0; i<beat_cnt; i++)
{
if(beat_interval_list[i] < 1e-15)
{
free(buf_bpm);
buf_bpm = NULL;
return -5;
}
buf_bpm[i] = 60.0 / beat_interval_list[i];
average_bpm += buf_bpm[i];
average_rr += beat_interval_list[i];
if(i < (beat_cnt - 1))
{
d_tmp = (beat_interval_list[i] - beat_interval_list[i + 1]) * 1000.0;
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++;
}
}
}
average_bpm /= beat_cnt;
average_rr /= beat_cnt;
rmssd_rr /= beat_cnt;
rmssd_rr = sqrt(rmssd_rr);
for(i=0; i<beat_cnt; i++)
{
sdnn_bpm += (buf_bpm[i] - average_bpm) * (buf_bpm[i] - average_bpm);
sdnn_rr += (beat_interval_list[i] - average_rr) * (beat_interval_list[i] - average_rr);
}
sdnn_bpm = sqrt(sdnn_bpm / beat_cnt);
sdnn_rr = sqrt(sdnn_rr / beat_cnt);
ecg_stats->beat_cnt = beat_cnt;
ecg_stats->mean_rr = average_rr * 1000.0;
ecg_stats->sdnn_rr = sdnn_rr * 1000.0;
ecg_stats->rmssd_rr = rmssd_rr;
ecg_stats->mean_hr = average_bpm;
ecg_stats->sdnn_hr = sdnn_bpm;
ecg_stats->NN20 = NN20;
ecg_stats->NN50 = NN50;
ecg_stats->pNN20 = (NN20 * 100.0) / (beat_cnt - 1);
ecg_stats->pNN50 = (NN50 * 100.0) / (beat_cnt - 1);
free(buf_bpm);
buf_bpm = NULL;
return 0;
}
/*
***************************************************************************
*
* Author: Teunis van Beelen
*
* Copyright (C) 2018 Teunis van Beelen
*
* Email: teuniz@gmail.com
*
***************************************************************************
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, 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 ecg_statistics_INCLUDED
#define ecg_statistics_INCLUDED
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#ifdef __cplusplus
extern "C" {
#endif
struct ecg_hr_statistics_struct{
int beat_cnt;
double mean_rr;
double sdnn_rr;
double rmssd_rr;
double mean_hr;
double sdnn_hr;
int NN20;
double pNN20;
int NN50;
double pNN50;
};
int ecg_get_hr_statistics(double *, int, struct ecg_hr_statistics_struct *);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
......@@ -131,6 +131,9 @@ HEADERS += plif_ecg_subtract_filter_dialog.h
HEADERS += annotlist_filter_dialog.h
HEADERS += export_filtered_signals.h
HEADERS += fft_wrap.h
HEADERS += ecg_statistics.h
HEADERS += fir_filter.h
HEADERS += fir_filter_dialog.h
HEADERS += third_party/fidlib/fidlib.h
HEADERS += third_party/fidlib/fidmkf.h
......@@ -154,7 +157,7 @@ SOURCES += signal_chooser.cpp
SOURCES += ascii_export.cpp
SOURCES += edf_compat.cpp
SOURCES += colordialog.cpp
SOURCES += filter.cpp
SOURCES += filter.c
SOURCES += filter_dialog.cpp
SOURCES += jump_dialog.cpp
SOURCES += about_dialog.cpp
......@@ -162,7 +165,7 @@ SOURCES += edf_annotations.cpp
SOURCES += annotations_dock.cpp
SOURCES += options_dialog.cpp
SOURCES += nk2edf.cpp
SOURCES += xml.cpp
SOURCES += xml.c
SOURCES += save_montage_dialog.cpp
SOURCES += load_montage_dialog.cpp
SOURCES += view_montage_dialog.cpp
......@@ -198,26 +201,26 @@ SOURCES += biosemi2bdfplus.cpp
SOURCES += bdf_triggers.cpp
SOURCES += adjustfiltersettings.cpp
SOURCES += import_annotations.cpp
SOURCES += ravg_filter.cpp
SOURCES += ravg_filter.c
SOURCES += wav2edf.cpp
SOURCES += fma_ecg2edf.cpp
SOURCES += mortara2edf.cpp
SOURCES += averager_dialog.cpp
SOURCES += averager_curve_wnd.cpp
SOURCES += ecg_filter.cpp
SOURCES += ecg_filter.c
SOURCES += ecg_export.cpp
SOURCES += statistics_dialog.cpp
SOURCES += filteredblockread.cpp
SOURCES += flywheel.cpp
SOURCES += z_score_dialog.cpp
SOURCES += z_ratio_filter.cpp
SOURCES += z_ratio_filter.c
SOURCES += raw2edf.cpp
SOURCES += check_for_updates.cpp
SOURCES += manscan2edf.cpp
SOURCES += scp_ecg2edf.cpp
SOURCES += unisens2edf.cpp
SOURCES += date_time_stamp_parser.c
SOURCES += spike_filter.cpp
SOURCES += spike_filter.c
SOURCES += spike_filter_dialog.cpp
SOURCES += mit2edf.cpp
SOURCES += biox2edf.cpp
......@@ -227,6 +230,9 @@ SOURCES += plif_ecg_subtract_filter_dialog.cpp
SOURCES += annotlist_filter_dialog.cpp
SOURCES += export_filtered_signals.cpp
SOURCES += fft_wrap.c
SOURCES += ecg_statistics.c
SOURCES += fir_filter.c
SOURCES += fir_filter_dialog.cpp
SOURCES += third_party/fidlib/fidlib.c
......
......@@ -745,7 +745,8 @@ void UI_ExportFilteredSignalsWindow::StartExport()
for(i=0; i<new_edfsignals; i++)
{
snprintf(scratchpad, 16, "%s", signalcomp[i]->signallabel);
strcpy(scratchpad, signalcomp[i]->signallabel);
scratchpad[16] = 0;
strcat(scratchpad, " ");
scratchpad[16] = 0;
fprintf(outputfile, "%s", scratchpad);
......@@ -954,6 +955,11 @@ void UI_ExportFilteredSignalsWindow::StartExport()
if(p>80) break;
}
if(signalcomp[i]->fir_filter)
{
p += sprintf(scratchpad + p, "FIR ");
}
if(signalcomp[i]->ecg_filter != NULL)
{
p += sprintf(scratchpad + p, "ECG:HR ");
......
......@@ -41,6 +41,9 @@
#include <math.h>
#ifdef __cplusplus
extern "C" {
#endif
struct filter_settings{
......@@ -62,6 +65,10 @@ double get_filter_factor(double, double);
struct filter_settings * create_filter_copy(struct filter_settings *);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
......
......@@ -258,6 +258,11 @@ int FilteredBlockReadClass::process_signalcomp(int datarecord_start)
dig_value = signalcomp->fidfuncp[k](signalcomp->fidbuf[k], dig_value);
}
if(signalcomp->fir_filter)
{
dig_value = run_fir_filter(dig_value, signalcomp->fir_filter);
}
if(signalcomp->plif_ecg_filter)
{
dig_value = plif_run_subtract_filter(dig_value, signalcomp->plif_ecg_filter);
......
......@@ -113,7 +113,7 @@ void UI_FINO2EDFwindow::SelectFileButton()
phys_max[MAX_SIGNALS][9],
patientname[81],
recording[81],
datetime[17];
datetime[128];
double sensitivity[MAX_SIGNALS],
......
/*
***************************************************************************
*
* Author: Teunis van Beelen
*
* Copyright (C) 2018 Teunis van Beelen
*
* Email: teuniz@gmail.com
*
**************************************************************************
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, 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 "fir_filter.h"
struct fir_filter_settings * create_fir_filter(double *vars, int sz)
{
struct fir_filter_settings *settings;
if((vars == NULL) || (sz < 1) || (sz > 1000)) return NULL;
settings = (struct fir_filter_settings *)calloc(1, sizeof(struct fir_filter_settings));
if(settings == NULL)
{
return NULL;
}
settings->vars = (double *)calloc(1, sizeof(double) * sz);
if(settings == NULL)
{
free(settings);
return NULL;
}
settings->buf = (double *)calloc(1, sizeof(double) * sz);
if(settings == NULL)
{
free(settings->vars);
free(settings);
return NULL;
}
settings->buf_sav = (double *)calloc(1, sizeof(double) * sz);
if(settings == NULL)
{
free(settings->buf);
free(settings->vars);
free(settings);
return NULL;
}
settings->sz = sz;
settings->idx = 0;
settings->idx_sav = 0;
memcpy(settings->vars, vars, sizeof(double) * sz);
return settings;
}
double run_fir_filter(double val, struct fir_filter_settings *settings)
{
int i, j;
double result = 0;
if(settings == NULL) return 0;
j = settings->idx;
settings->buf[settings->idx++] = val;
settings->idx %= settings->sz;
for(i=0; i<settings->sz; i++)
{
result += settings->buf[j--] * settings->vars[i];
if(j < 0) j = settings->sz - 1;
}
return result;
}
void free_fir_filter(struct fir_filter_settings *settings)
{
if(settings == NULL) return;
free(settings->vars);
free(settings->buf);
free(settings->buf_sav);
free(settings);
}
void reset_fir_filter(double val, struct fir_filter_settings *settings)
{
int i;
if(settings == NULL) return;
for(i=0; i<settings->sz; i++)
{
settings->buf[i] = val;
}
}
struct fir_filter_settings * create_fir_filter_copy(struct fir_filter_settings *settings)
{
int i;
struct fir_filter_settings *new_settings;
if(settings == NULL) return NULL;
new_settings = create_fir_filter(settings->vars, settings->sz);
if(new_settings == NULL) return NULL;
for(i=0; i<settings->sz; i++)
{
new_settings->buf[i] = settings->buf[i];
}
return new_settings;
}
int fir_filter_size(struct fir_filter_settings *settings)
{
if(settings == NULL) return 0;
return settings->sz;
}
double fir_filter_tap(int idx, struct fir_filter_settings *settings)
{
if(settings == NULL) return 0;
if((idx < 0) || (idx >= settings->sz)) return 0;
return settings->vars[idx];
}
void fir_filter_save_buf(struct fir_filter_settings *settings)
{
int i;
for(i=0; i<settings->sz; i++)
{
settings->buf_sav[i] = settings->buf[i];
}
settings->idx_sav = settings->idx;
}
void fir_filter_restore_buf(struct fir_filter_settings *settings)
{
int i;
for(i=0; i<settings->sz; i++)
{
settings->buf[i] = settings->buf_sav[i];
}
settings->idx = settings->idx_sav;
}
/*
***************************************************************************
*
* Author: Teunis van Beelen
*
* Copyright (C) 2018 Teunis van Beelen
*
* Email: teuniz@gmail.com
*
***************************************************************************
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, 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 FIR_filter_INCLUDED
#define FIR_filter_INCLUDED
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
struct fir_filter_settings{
double *vars;
double *buf;
double *buf_sav;
int sz;
int idx;
int idx_sav;
};
struct fir_filter_settings * create_fir_filter(double *, int);
double run_fir_filter(double, struct fir_filter_settings *);
void free_fir_filter(struct fir_filter_settings *);
void reset_fir_filter(double, struct fir_filter_settings *);
struct fir_filter_settings * create_fir_filter_copy(struct fir_filter_settings *);
int fir_filter_size(struct fir_filter_settings *);
double fir_filter_tap(int, struct fir_filter_settings *);
void fir_filter_restore_buf(struct fir_filter_settings *);
void fir_filter_save_buf(struct fir_filter_settings *);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif