[med-svn] [Git][med-team/edfbrowser][upstream] New upstream version 1.71+dfsg
Andreas Tille
gitlab at salsa.debian.org
Sun Jan 5 12:13:00 GMT 2020
Andreas Tille pushed to branch upstream at Debian Med / edfbrowser
Commits:
4ac48100 by Andreas Tille at 2020-01-05T12:38:45+01:00
New upstream version 1.71+dfsg
- - - - -
22 changed files:
- README.txt
- doc/manual.html
- edfbrowser.pro
- fft_wrap.c
- fft_wrap.h
- global.h
- import_annotations.cpp
- + ishne2edf.cpp
- + ishne2edf.h
- mainwindow.cpp
- mainwindow.h
- mainwindow_constr.cpp
- options_dialog.cpp
- options_dialog.h
- read_write_settings.cpp
- signalcurve.cpp
- signals_dialog.cpp
- signals_dialog.h
- spectrum_dock.cpp
- spectrumanalyzer.cpp
- version.txt
- videoplayer.cpp
Changes:
=====================================
README.txt
=====================================
@@ -91,7 +91,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.12.3-static #
+# in a new and separate directory: /usr/local/Qt-5.12.6-static #
# #
# It will not interfere with other Qt programs. #
# #
@@ -101,28 +101,28 @@ mkdir Qt5-source
cd Qt5-source
-wget http://ftp1.nluug.nl/languages/qt/official_releases/qt/5.12/5.12.3/single/qt-everywhere-src-5.12.3.tar.xz
+wget http://ftp1.nluug.nl/languages/qt/official_releases/qt/5.12/5.12.6/single/qt-everywhere-src-5.12.6.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-src-5.12.3.tar.xz
+The Qt source package you are going to need is: qt-everywhere-src-5.12.6.tar.xz
-tar -xvf qt-everywhere-src-5.12.3.tar.xz
+tar -xvf qt-everywhere-src-5.12.6.tar.xz
-cd qt-everywhere-src-5.12.3
+cd qt-everywhere-src-5.12.6
-./configure -v -prefix /usr/local/Qt-5.12.3-static -release -opensource -confirm-license -c++std c++11 -static -accessibility -fontconfig -skip qtdeclarative -skip qtconnectivity -skip qtmultimedia -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 -skip qt3d -skip qtpurchasing -skip qtquickcontrols -skip qtquickcontrols2 -skip qtspeech -skip qtwebengine
+./configure -v -prefix /usr/local/Qt-5.12.6-static -release -opensource -confirm-license -c++std c++11 -static -accessibility -fontconfig -skip qtdeclarative -skip qtconnectivity -skip qtmultimedia -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 -skip qt3d -skip qtpurchasing -skip qtquickcontrols -skip qtquickcontrols2 -skip qtspeech -skip qtwebengine
(takes about 2 minutes)
make -j6 (change option -j according to number of available cpu cores e.g -j4 or -j8)
-(takes about 11 minutes)
+(takes about 12 minutes)
sudo make install
Now go to the directory that contains the EDFbrowser sourcecode and enter the following commands:
-/usr/local/Qt-5.12.3-static/bin/qmake
+/usr/local/Qt-5.12.6-static/bin/qmake
make -j6 (change option -j according to number of available cpu cores e.g -j4 or -j8)
=====================================
doc/manual.html
=====================================
@@ -7,7 +7,7 @@
<meta name="description" content="EDFbrowser manual">
</head><body>
-<h1>EDFbrowser 1.70 manual</h1>
+<h1>EDFbrowser 1.71 manual</h1>
<p><br></p>
=====================================
edfbrowser.pro
=====================================
@@ -134,6 +134,7 @@ HEADERS += fft_wrap.h
HEADERS += ecg_statistics.h
HEADERS += fir_filter.h
HEADERS += fir_filter_dialog.h
+HEADERS += ishne2edf.h
HEADERS += third_party/fidlib/fidlib.h
HEADERS += third_party/fidlib/fidmkf.h
@@ -240,6 +241,7 @@ SOURCES += fft_wrap.c
SOURCES += ecg_statistics.c
SOURCES += fir_filter.c
SOURCES += fir_filter_dialog.cpp
+SOURCES += ishne2edf.cpp
SOURCES += third_party/fidlib/fidlib.c
=====================================
fft_wrap.c
=====================================
@@ -41,7 +41,7 @@ struct fft_wrap_settings_struct * fft_wrap_create(double *buf, int buf_size, int
if(buf_size < 4) return NULL;
if(dft_size < 4) return NULL;
if(dft_size & 1) dft_size--;
- if((window_type < 0) || (window_type > 7)) return NULL;
+ if((window_type < 0) || (window_type > 8)) return NULL;
if((overlap < 1) || (overlap > 5)) return NULL;
st = (struct fft_wrap_settings_struct *)calloc(1, sizeof(struct fft_wrap_settings_struct));
@@ -291,13 +291,21 @@ static void window_func(const double *src, double *dest, double *coef, int sz, i
- (0.324954578e-2 * cos((14.0 * M_PI * i) / (sz - 1))) + (0.13801040e-3 * cos((16.0 * M_PI * i) / (sz - 1))) - (0.132725e-5 * cos((18.0 * M_PI * i) / (sz - 1))); /* 9-term HFT223D */
}
}
- else
- {
- for(i=0; i<sz2; i++)
+ else if(type == FFT_WNDW_TYPE_HFT95)
+ { /* Spectrum and spectral density estimation by the Discrete Fourier transform (DFT), including a comprehensive list of window functions and some new at-top windows Max Planck Institute */
+ for(i=0; i<sz2; i++)
+ {
+ coef[i] = 1.0 - (1.9383379 * cos((2.0 * M_PI * i) / (sz - 1))) + (1.3045202 * cos((4.0 * M_PI * i) / (sz - 1)))
+ - (0.4028270 * cos((6.0 * M_PI * i) / (sz - 1))) + (0.0350665 * cos((8.0 * M_PI * i) / (sz - 1)));
+ }
+ }
+ else
{
- coef[i] = 0;
+ for(i=0; i<sz2; i++)
+ {
+ coef[i] = 0;
+ }
}
- }
set_gain_unity(coef, sz2);
}
=====================================
fft_wrap.h
=====================================
@@ -47,6 +47,7 @@
#define FFT_WNDW_TYPE_NUTTALL4C 5
#define FFT_WNDW_TYPE_HANN 6
#define FFT_WNDW_TYPE_HFT223D 7
+#define FFT_WNDW_TYPE_HFT95 8
#ifdef __cplusplus
=====================================
global.h
=====================================
@@ -58,7 +58,7 @@
#endif
#define PROGRAM_NAME "EDFbrowser"
-#define PROGRAM_VERSION "1.70"
+#define PROGRAM_VERSION "1.71"
#define PROGRAM_BETA_SUFFIX ""
#define MINIMUM_QT4_VERSION 0x040701
#define MINIMUM_QT5_VERSION 0x050901
=====================================
import_annotations.cpp
=====================================
@@ -1244,7 +1244,14 @@ int UI_ImportAnnotationswindow::import_from_ascii(void)
startline = DatastartSpinbox->value();
- descr_column = DescriptionColumnSpinBox->value() - 1;
+ if(manualdescription)
+ {
+ descr_column = -1;
+ }
+ else
+ {
+ descr_column = DescriptionColumnSpinBox->value() - 1;
+ }
onset_column = OnsetColumnSpinBox->value() - 1;
@@ -1422,7 +1429,7 @@ int UI_ImportAnnotationswindow::import_from_ascii(void)
#ifdef IMPORT_ANNOTS_DEBUG
printf(" line %i\n", line_nr);
#endif
- if(onset_is_set && descr_is_set)
+ if(onset_is_set && (descr_is_set || manualdescription))
{
if((!ignore_consecutive) || strcmp(description, last_description))
{
=====================================
ishne2edf.cpp
=====================================
@@ -0,0 +1,682 @@
+/*
+***************************************************************************
+*
+* Author: Teunis van Beelen
+*
+* Copyright (C) 2019 Teunis van Beelen
+*
+* Email: teuniz at protonmail.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 "ishne2edf.h"
+
+
+#define ISHNE_MAX_CHNS (12)
+
+
+
+UI_IshneEDFwindow::UI_IshneEDFwindow(QWidget *w_parent, char *recent_dir, char *save_dir)
+{
+ mainwindow = (UI_Mainwindow *)w_parent;
+
+ recent_opendir = recent_dir;
+ recent_savedir = save_dir;
+
+ myobjectDialog = new QDialog;
+
+ myobjectDialog->setMinimumSize(600, 480);
+ myobjectDialog->setMaximumSize(600, 480);
+ myobjectDialog->setWindowTitle("ISHNE ECG to EDF converter");
+ myobjectDialog->setModal(true);
+ myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true);
+
+ textEdit1 = new QTextEdit(myobjectDialog);
+ textEdit1->setGeometry(20, 20, 560, 380);
+ textEdit1->setFrameStyle(QFrame::Panel | QFrame::Sunken);
+ textEdit1->setReadOnly(true);
+ textEdit1->setLineWrapMode(QTextEdit::NoWrap);
+ textEdit1->append("ISHNE ECG to EDF converter\n");
+
+ pushButton1 = new QPushButton(myobjectDialog);
+ pushButton1->setGeometry(20, 430, 100, 25);
+ pushButton1->setText("Select File");
+
+ pushButton2 = new QPushButton(myobjectDialog);
+ pushButton2->setGeometry(480, 430, 100, 25);
+ pushButton2->setText("Close");
+
+ crc_ccitt_init();
+
+ QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton()));
+ QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close()));
+
+ myobjectDialog->exec();
+}
+
+
+
+void UI_IshneEDFwindow::SelectFileButton()
+{
+int i, j,
+ var_block_sz,
+ ecg_smpl_sz,
+ var_block_offset,
+ ecg_block_offset,
+ chns,
+ sf,
+ lead_spec[ISHNE_MAX_CHNS],
+ amp_resolution[ISHNE_MAX_CHNS],
+ sex,
+ edf_hdl=-99,
+ birthdate_valid=0,
+ total_blocks=0,
+ blocks_written=0;
+
+ unsigned long long int file_sz=0;
+
+ short *inbuf=NULL,
+ *outbuf=NULL;
+
+ char path[MAX_PATH_LENGTH]={""},
+ hdr[4096]={""},
+ scratchpad[4096]={""},
+ tmp_str[128]={""};
+
+ const char *lead_label[20]={"Unknown","Generic bipolar","X bipolar","Y bipolar","Z bipolar","I","II","III","aVR","aVL",
+ "aVF","V1","V2","V3","V4","V5","V6","ES","AS","AI"};
+
+ FILE *inputfile=NULL;
+
+ QProgressDialog progress("Converting ECG data ...", "Abort", 0, 0, myobjectDialog);
+ progress.reset();
+
+struct
+{
+ int day;
+ int month;
+ int year;
+ int hour;
+ int minute;
+ int second;
+} start_dt;
+
+struct
+{
+ int day;
+ int month;
+ int year;
+} birth_d;
+
+///////////////////////////////////////// OPEN THE ECG FILE ///////////////////////
+
+ strlcpy(path, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "ECG files (*.ecg *.ECG)").toLocal8Bit().data(), MAX_PATH_LENGTH);
+
+ if(!strcmp(path, ""))
+ {
+ return;
+ }
+
+ get_directory_from_path(recent_opendir, path, MAX_PATH_LENGTH);
+
+ inputfile = fopen(path, "rb");
+
+ if(inputfile == NULL)
+ {
+ snprintf(scratchpad, 4096, "Error, can not open file:\n%s\n", path);
+ textEdit1->append(QString::fromLocal8Bit(scratchpad));
+ return;
+ }
+
+ snprintf(scratchpad, 4096, "Processing file:\n%s", path);
+ textEdit1->append(QString::fromLocal8Bit(scratchpad));
+
+ fseek(inputfile, 0, SEEK_END);
+
+ file_sz = ftell(inputfile);
+
+ if(file_sz < 522)
+ {
+ textEdit1->append("Error, file is too small.");
+ goto OUT_EXIT;
+ }
+
+ rewind(inputfile);
+
+ if(fread(hdr, 522, 1, inputfile) != 1)
+ {
+ textEdit1->append("A read error occurred when trying to read the header.");
+ goto OUT_EXIT;
+ }
+
+ if(strncmp(hdr, "ISHNE1.0", 8))
+ {
+ textEdit1->append("Error, wrong magic string in header.");
+ goto OUT_EXIT;
+ }
+
+////////////////////////////////// GET THE HEADER DATA ////////////////////////
+
+ var_block_sz = *((int *)(hdr + 10));
+ if(var_block_sz < 0)
+ {
+ textEdit1->append("Error, parameter size of variable length block in header is lower than zero.");
+ goto OUT_EXIT;
+ }
+
+ ecg_smpl_sz = *((int *)(hdr + 14));
+ if(ecg_smpl_sz < 0)
+ {
+ textEdit1->append("Error, parameter ECG sample size in header is lower than zero.");
+ goto OUT_EXIT;
+ }
+
+ var_block_offset = *((int *)(hdr + 18));
+ if(var_block_offset != 522)
+ {
+ textEdit1->append("Error, parameter offset of variable length block in header differs from 522");
+ goto OUT_EXIT;
+ }
+
+ ecg_block_offset = *((int *)(hdr + 22));
+ if(ecg_block_offset != (var_block_sz + 522))
+ {
+ textEdit1->append("Error, parameter offset of ECG block in header differs from 522 + variable length block");
+ goto OUT_EXIT;
+ }
+
+ if((unsigned long)ecg_block_offset > file_sz)
+ {
+ textEdit1->append("Error, start of ECG block is after end of file.");
+ goto OUT_EXIT;
+ }
+
+ chns = *((short *)(hdr + 156));
+ if(chns < 1)
+ {
+ textEdit1->append("Error, number of leads is less than 1.");
+ goto OUT_EXIT;
+ }
+
+ if(chns > ISHNE_MAX_CHNS)
+ {
+ textEdit1->append("Error, number of leads is more than 12.");
+ goto OUT_EXIT;
+ }
+
+ sf = *((short *)(hdr + 272));
+ if(sf < 1)
+ {
+ textEdit1->append("Error, sampling rate is less than 1Hz.");
+ goto OUT_EXIT;
+ }
+
+ sex = *((short *)(hdr + 128));
+ if((sex < 0) || (sex > 2))
+ {
+ textEdit1->append("Error, subject sex is out of range.");
+ goto OUT_EXIT;
+ }
+
+ total_blocks = ecg_smpl_sz / sf;
+ if(total_blocks < 1)
+ {
+ textEdit1->append("Error, not enough samples in file (recording duration is less than one second).");
+ goto OUT_EXIT;
+ }
+
+ if(file_sz < (unsigned int)(ecg_block_offset + (ecg_smpl_sz * chns * 2)))
+ {
+ textEdit1->append("Error, file size is less than file size based on header parameters.");
+ goto OUT_EXIT;
+ }
+
+ if(check_crc(inputfile, var_block_offset + var_block_sz))
+ {
+ textEdit1->append("CRC error, file header is corrupt.");
+ goto OUT_EXIT;
+ }
+
+////////////////////////////// GET THE LEAD DATA ////////////////////////////////////
+
+ for(i=0; i<chns; i++)
+ {
+ lead_spec[i] = *((short *)(hdr + 158 + (i * 2)));
+ if((lead_spec[i] < 0) || (lead_spec[i] > 19))
+ {
+ snprintf(scratchpad, 4096, "Error, lead specification of lead %i is out of range.", i + 1);
+ textEdit1->append(scratchpad);
+ goto OUT_EXIT;
+ }
+
+ amp_resolution[i] = *((short *)(hdr + 206 + (i * 2)));
+ if(amp_resolution[i] < 1)
+ {
+ snprintf(scratchpad, 4096, "Error, amplitude resolution of lead %i is less than 1nV.", i + 1);
+ textEdit1->append(scratchpad);
+ goto OUT_EXIT;
+ }
+ }
+
+/////////////////////////////////////// GET THE START DATE AND TIME /////////////////////
+
+ start_dt.day = *((short *)(hdr + 138));
+ if((start_dt.day < 1) || (start_dt.day > 31))
+ {
+ textEdit1->append("Error, illegal start date.");
+ goto OUT_EXIT;
+ }
+
+ start_dt.month = *((short *)(hdr + 140));
+ if((start_dt.month < 1) || (start_dt.month > 12))
+ {
+ textEdit1->append("Error, illegal start date.");
+ goto OUT_EXIT;
+ }
+
+ start_dt.year = *((short *)(hdr + 142));
+ if((start_dt.year < 1000) || (start_dt.year > 3000))
+ {
+ textEdit1->append("Error, illegal start date.");
+ goto OUT_EXIT;
+ }
+
+ start_dt.hour = *((short *)(hdr + 150));
+ if((start_dt.hour < 0) || (start_dt.hour > 23))
+ {
+ textEdit1->append("Error, illegal start time.");
+ goto OUT_EXIT;
+ }
+
+ start_dt.minute = *((short *)(hdr + 152));
+ if((start_dt.minute < 0) || (start_dt.minute > 59))
+ {
+ textEdit1->append("Error, illegal start time.");
+ goto OUT_EXIT;
+ }
+
+ start_dt.second = *((short *)(hdr + 154));
+ if((start_dt.second < 0) || (start_dt.second > 59))
+ {
+ textEdit1->append("Error, illegal start time.");
+ goto OUT_EXIT;
+ }
+
+ birthdate_valid = 1;
+
+ birth_d.year = *((short *)(hdr + 136));
+ if((birth_d.year < 1000) || (birth_d.year > 3000))
+ {
+ birthdate_valid = 0;
+ }
+
+ birth_d.month = *((short *)(hdr + 134));
+ if((birth_d.month < 1) || (birth_d.month > 12))
+ {
+ birthdate_valid = 0;
+ }
+
+ birth_d.day = *((short *)(hdr + 132));
+ if((birth_d.day < 1) || (birth_d.day > 31))
+ {
+ birthdate_valid = 0;
+ }
+
+// if(!birthdate_valid)
+// {
+// snprintf(scratchpad, 4096, "Skipping illegal date of birth: %04i-%02i-%02i", birth_d.year, birth_d.month, birth_d.day);
+// textEdit1->append(scratchpad);
+// }
+
+/////////////////////////////////////// STORE TO EDF ///////////////////////////////
+
+ remove_extension_from_filename(path);
+ strlcat(path, ".edf", MAX_PATH_LENGTH);
+
+ strlcpy(path, QFileDialog::getSaveFileName(0, "Select outputfile", QString::fromLocal8Bit(path), "EDF files (*.edf *.EDF)").toLocal8Bit().data(), MAX_PATH_LENGTH);
+
+ if(!strcmp(path, ""))
+ {
+ goto OUT_EXIT;
+ }
+
+ get_directory_from_path(recent_savedir, path, MAX_PATH_LENGTH);
+
+ edf_hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_EDFPLUS, chns);
+ if(edf_hdl < 0)
+ {
+ textEdit1->append("Error, can not open EDF file for writing\n");
+ goto OUT_EXIT;
+ }
+
+ for(i=0; i<chns; i++)
+ {
+ if(edf_set_samplefrequency(edf_hdl, i, sf))
+ {
+ textEdit1->append("Error, edf_set_samplefrequency()\n");
+ goto OUT_EXIT;
+ }
+
+ if(edf_set_digital_maximum(edf_hdl, i, 32767))
+ {
+ textEdit1->append("Error, edf_set_digital_maximum()\n");
+ goto OUT_EXIT;
+ }
+
+ if(edf_set_digital_minimum(edf_hdl, i, -32768))
+ {
+ textEdit1->append("Error, edf_set_digital_minimum()\n");
+ goto OUT_EXIT;
+ }
+
+ if(edf_set_physical_dimension(edf_hdl, i, "uV"))
+ {
+ textEdit1->append("Error, edf_set_physical_dimension()\n");
+ goto OUT_EXIT;
+ }
+
+ if(edf_set_physical_maximum(edf_hdl, i, 32.767 * amp_resolution[i]))
+ {
+ textEdit1->append("Error, edf_set_physical_maximum()\n");
+ goto OUT_EXIT;
+ }
+
+ if(edf_set_physical_minimum(edf_hdl, i, -32.768 * amp_resolution[i]))
+ {
+ textEdit1->append("Error, edf_set_physical_minimum()\n");
+ goto OUT_EXIT;
+ }
+
+ if(edf_set_label(edf_hdl, i, lead_label[lead_spec[i]]))
+ {
+ textEdit1->append("Error, edf_set_label()\n");
+ goto OUT_EXIT;
+ }
+ }
+
+ if(edf_set_startdatetime(edf_hdl, start_dt.year, start_dt.month, start_dt.day, start_dt.hour, start_dt.minute, start_dt.second))
+ {
+ textEdit1->append("Error, edf_set_startdatetime()\n");
+ goto OUT_EXIT;
+ }
+
+ strncpy(tmp_str, hdr + 28, 40);
+ tmp_str[40] = 0;
+
+ remove_leading_spaces(tmp_str);
+ remove_trailing_spaces(tmp_str);
+ strlcat(tmp_str, " ", 128);
+
+ strncpy(scratchpad, hdr + 68, 40);
+ scratchpad[40] = 0;
+
+ remove_leading_spaces(scratchpad);
+ remove_trailing_spaces(scratchpad);
+
+ strlcat(tmp_str, scratchpad, 128);
+ remove_trailing_spaces(tmp_str);
+
+ if(strlen(tmp_str))
+ {
+ if(edf_set_patientname(edf_hdl, tmp_str))
+ {
+ textEdit1->append("Error, edf_set_patientname()\n");
+ goto OUT_EXIT;
+ }
+ }
+
+ strncpy(tmp_str, hdr + 108, 20);
+ tmp_str[20] = 0;
+
+ remove_leading_spaces(tmp_str);
+ remove_trailing_spaces(tmp_str);
+
+ if(strlen(tmp_str))
+ {
+ if(edf_set_patientcode(edf_hdl, tmp_str))
+ {
+ textEdit1->append("Error, edf_set_patientcode()\n");
+ goto OUT_EXIT;
+ }
+ }
+
+ if(sex == 1)
+ {
+ if(edf_set_gender(edf_hdl, 1))
+ {
+ textEdit1->append("Error, edf_set_gender()\n");
+ goto OUT_EXIT;
+ }
+ }
+ else if(sex == 2)
+ {
+ if(edf_set_gender(edf_hdl, 0))
+ {
+ textEdit1->append("Error, edf_set_gender()\n");
+ goto OUT_EXIT;
+ }
+ }
+
+ if(birthdate_valid)
+ {
+ if(edf_set_birthdate(edf_hdl, birth_d.year, birth_d.month, birth_d.day))
+ {
+ textEdit1->append("Error, edf_set_birthdate()\n");
+ goto OUT_EXIT;
+ }
+ }
+
+ strncpy(tmp_str, hdr + 232, 40);
+ tmp_str[40] = 0;
+
+ remove_leading_spaces(tmp_str);
+ remove_trailing_spaces(tmp_str);
+
+ if(strlen(tmp_str))
+ {
+ if(edf_set_equipment(edf_hdl, tmp_str))
+ {
+ textEdit1->append("Error, edf_set_equipment()\n");
+ goto OUT_EXIT;
+ }
+ }
+
+/////////////////// Start conversion //////////////////////////////////////////
+
+// printf("sf: %i chns: %i var_block_offset: %i var_block_sz: %i ecg_block_offset: %i ecg_smpl_sz: %i total_blocks: %i\n",
+// sf, chns, var_block_offset, var_block_sz, ecg_block_offset, ecg_smpl_sz, total_blocks);
+
+ inbuf = (short *)malloc(sf * chns * sizeof(short));
+ if(inbuf == NULL)
+ {
+ textEdit1->append("Malloc() error\n");
+ goto OUT_EXIT;
+ }
+
+ outbuf = (short *)malloc(sf * chns * sizeof(short));
+ if(outbuf == NULL)
+ {
+ textEdit1->append("Malloc() error\n");
+ goto OUT_EXIT;
+ }
+
+ fseek(inputfile, ecg_block_offset, SEEK_SET);
+
+ progress.setMaximum(total_blocks);
+ progress.setWindowModality(Qt::WindowModal);
+ progress.setMinimumDuration(200);
+
+ for(blocks_written=0; blocks_written<total_blocks; blocks_written++)
+ {
+ if(!(blocks_written % 10))
+ {
+ progress.setValue(blocks_written);
+
+ qApp->processEvents();
+
+ if(progress.wasCanceled() == true)
+ {
+ textEdit1->append("Conversion aborted by user.\n");
+ break;
+ }
+ }
+
+ if(fread(inbuf, sf * chns * 2, 1, inputfile) != 1)
+ {
+ textEdit1->append("Error, could not read from input file.");
+ goto OUT_EXIT;
+ }
+
+ for(i=0; i<chns; i++)
+ {
+ for(j=0; j<sf; j++)
+ {
+ *(outbuf + (i * sf) + j) = *(inbuf + (j * chns) + i);
+ }
+ }
+
+ if(edf_blockwrite_digital_short_samples(edf_hdl, outbuf))
+ {
+ textEdit1->append("Error, edf_blockwrite_digital_short_samples()\n");
+ goto OUT_EXIT;
+ }
+ }
+
+ textEdit1->append("Done\n");
+
+OUT_EXIT:
+
+ progress.reset();
+
+ if(edf_hdl >= 0) edfclose_file(edf_hdl);
+
+ if(inputfile != NULL) fclose(inputfile);
+
+ free(inbuf);
+ free(outbuf);
+}
+
+
+int UI_IshneEDFwindow::check_crc(FILE *inputfile, int len)
+{
+ unsigned short crc=0xFFFF, crc2=0x0000;
+
+ unsigned char *buf=NULL;
+
+ buf = (unsigned char *)malloc(len);
+ if(buf == NULL)
+ {
+ return -99;
+ }
+
+ rewind(inputfile);
+
+ if(fread(buf, len, 1, inputfile) != 1)
+ {
+ free(buf);
+ return -88;
+ }
+
+ crc2 = *((unsigned short *)(buf + 8));
+
+ crc = crc_ccitt(buf + 10, len - 10, crc);
+
+// printf("crc: %04X crc2: %04X\n", crc, crc2);
+
+ if(crc != crc2)
+ {
+ free(buf);
+ return -1;
+ }
+
+ free(buf);
+
+ return 0;
+}
+
+
+unsigned short UI_IshneEDFwindow::crc_ccitt(const unsigned char *message, int nbytes, unsigned short remainder)
+{
+ int byte;
+
+ unsigned char data;
+
+ for(byte=0; byte<nbytes; byte++) /* Divide the message by the polynomial, a byte at a time. */
+ {
+ data = message[byte] ^ (remainder >> 8);
+
+ remainder = crc_ccitt_table[data] ^ (remainder << 8);
+ }
+
+ return remainder; /* The final remainder is the CRC. */
+}
+
+
+void UI_IshneEDFwindow::crc_ccitt_init(void)
+{
+ int dividend;
+
+ unsigned short remainder;
+
+ unsigned char bit;
+
+ for(dividend=0; dividend<256; dividend++) /* Compute the remainder of each possible dividend. */
+ {
+ remainder = dividend << 8; /* Start with the dividend followed by zeros. */
+
+ for(bit=8; bit>0; bit--) /* Perform modulo-2 division, a bit at a time. */
+ {
+ if(remainder & 32768) /* Try to divide the current data bit. */
+ {
+ remainder = (remainder << 1) ^ 0x1021; /* polynomial */
+ }
+ else
+ {
+ remainder = (remainder << 1);
+ }
+ }
+
+ crc_ccitt_table[dividend] = remainder; /* Store the result into the table. */
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
=====================================
ishne2edf.h
=====================================
@@ -0,0 +1,107 @@
+/*
+***************************************************************************
+*
+* Author: Teunis van Beelen
+*
+* Copyright (C) 2019 Teunis van Beelen
+*
+* Email: teuniz at protonmail.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_ISHNE2EDFFORM_H
+#define UI_ISHNE2EDFFORM_H
+
+
+#include <QtGlobal>
+#include <QApplication>
+#include <QDialog>
+#include <QLabel>
+#include <QLineEdit>
+#include <QDateTimeEdit>
+#include <QPushButton>
+#include <QObject>
+#include <QFileDialog>
+#include <QCheckBox>
+#include <QCursor>
+#include <QDoubleSpinBox>
+#include <QProgressDialog>
+#include <QMessageBox>
+#include <QString>
+#include <QPixmap>
+#include <QDesktopServices>
+#include <QUrl>
+#include <QTextEdit>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "global.h"
+#include "mainwindow.h"
+#include "utils.h"
+#include "edflib.h"
+
+
+
+class UI_Mainwindow;
+
+
+class UI_IshneEDFwindow : public QObject
+{
+ Q_OBJECT
+
+public:
+ UI_IshneEDFwindow(QWidget *, char *recent_dir=NULL, char *save_dir=NULL);
+
+ UI_Mainwindow *mainwindow;
+
+private:
+
+QDialog *myobjectDialog;
+
+QTextEdit *textEdit1;
+
+QPushButton *pushButton1,
+ *pushButton2;
+
+char *recent_opendir,
+ *recent_savedir;
+
+unsigned short crc_ccitt_table[256];
+
+void crc_ccitt_init(void);
+
+unsigned short crc_ccitt(const unsigned char *, int, unsigned short);
+
+int check_crc(FILE *, int);
+
+private slots:
+
+void SelectFileButton();
+
+};
+
+
+
+
+#endif
+
+
=====================================
mainwindow.cpp
=====================================
@@ -625,6 +625,12 @@ void UI_Mainwindow::convert_mortara_to_edf()
}
+void UI_Mainwindow::convert_ishne_to_edf()
+{
+ UI_IshneEDFwindow ishne2edf(this, recent_opendir, recent_savedir);
+}
+
+
void UI_Mainwindow::convert_nexfin_to_edf()
{
UI_NEXFIN2EDFwindow nexfin2edf(recent_opendir, recent_savedir);
=====================================
mainwindow.h
=====================================
@@ -172,6 +172,7 @@
#include "plif_ecg_subtract_filter_dialog.h"
#include "export_filtered_signals.h"
#include "fir_filter_dialog.h"
+#include "ishne2edf.h"
#include "third_party/fidlib/fidlib.h"
@@ -230,8 +231,17 @@ public:
spectrum_bw,
spectrum_sqrt,
spectrum_vlog,
+ spectrum_window,
+ spectrum_blocksize_predefined,
+ spectrum_blocksize_userdefined,
+ spectrum_overlap,
+ spectrumdock_bw,
spectrumdock_sqrt,
spectrumdock_vlog,
+ spectrumdock_window,
+ spectrumdock_blocksize_predefined,
+ spectrumdock_blocksize_userdefined,
+ spectrumdock_overlap,
spectrumdock_colorbars,
use_threads,
check_for_updates,
@@ -242,7 +252,8 @@ public:
linear_interpol,
auto_update_annot_onset,
average_period,
- font_size;
+ font_size,
+ use_diverse_signal_colors;
unsigned long long pagetime,
maxfilesize_to_readin_annotations;
@@ -567,6 +578,7 @@ private slots:
void convert_wave_to_edf();
void convert_fm_audio_to_edf();
void convert_mortara_to_edf();
+ void convert_ishne_to_edf();
void convert_nexfin_to_edf();
void edfd_converter();
void slider_moved(int);
=====================================
mainwindow_constr.cpp
=====================================
@@ -144,6 +144,8 @@ UI_Mainwindow::UI_Mainwindow()
auto_update_annot_onset = 0;
+ use_diverse_signal_colors = 0;
+
toolbar_stats.sz = 0;
toolbar_stats.active = 0;
toolbar_stats.annot_label[0] = 0;
@@ -228,12 +230,32 @@ UI_Mainwindow::UI_Mainwindow()
spectrum_vlog = 0;
+ spectrum_window = 0;
+
+ spectrum_blocksize_predefined = 0;
+
+ spectrum_blocksize_userdefined = 200;
+
+ spectrum_overlap = 0;
+
+ spectrumdock_bw = 0;
+
spectrumdock_sqrt = 0;
spectrumdock_vlog = 0;
+ spectrum_window = 0;
+
+ spectrumdock_blocksize_predefined = 0;
+
+ spectrumdock_blocksize_userdefined = 200;
+
+ spectrumdock_overlap = 0;
+
spectrumdock_colorbars = 0;
+ spectrumdock_window = 0;
+
z_score_var.crossoverfreq = 7.5;
z_score_var.z_threshold = 0.0;
z_score_var.zscore_page_len = 30;
@@ -754,6 +776,7 @@ UI_Mainwindow::UI_Mainwindow()
toolsmenu->addAction("Convert Biox CB-1305-C to EDF", this, SLOT(convert_biox_to_edf()));
toolsmenu->addAction("Convert FM Audio ECG to EDF", this, SLOT(convert_fm_audio_to_edf()));
toolsmenu->addAction("Convert Mortara ECG XML to EDF", this, SLOT(convert_mortara_to_edf()));
+ toolsmenu->addAction("Convert ISHNE ECG to EDF", this, SLOT(convert_ishne_to_edf()));
toolsmenu->addAction("Convert Binary/raw data to EDF", this, SLOT(convert_binary_to_edf()));
toolsmenu->addSeparator();
toolsmenu->addAction("Options", this, SLOT(show_options_dialog()));
=====================================
options_dialog.cpp
=====================================
@@ -41,7 +41,7 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
optionsdialog = new QDialog(w_parent);
- if(QApplication::desktop()->screenGeometry().height() < 900)
+ if(QApplication::desktop()->screenGeometry().height() < 940)
{
showminimized = 1;
}
@@ -60,8 +60,8 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
}
else
{
- optionsdialog->setMinimumSize(440, 820);
- optionsdialog->setMaximumSize(440, 820);
+ optionsdialog->setMinimumSize(440, 860);
+ optionsdialog->setMaximumSize(440, 860);
}
optionsdialog->setWindowTitle("Settings");
optionsdialog->setModal(true);
@@ -124,12 +124,30 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
SigColorButton->setGeometry(240, 170, 60, 15);
SigColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->signal_color);
+ label16 = new QLabel(tab1);
+ label16->setGeometry(20, 195, 200, 25);
+ label16->setText("Vary signal colors");
+ label16->setToolTip("When adding signals to the screen, vary the traces' color");
+
+ checkbox16 = new QCheckBox(tab1);
+ checkbox16->setGeometry(200, 198, 20, 20);
+ checkbox16->setTristate(false);
+ checkbox16->setToolTip("When adding signals to the screen, vary the traces' color");
+ if(mainwindow->use_diverse_signal_colors)
+ {
+ checkbox16->setCheckState(Qt::Checked);
+ }
+ else
+ {
+ checkbox16->setCheckState(Qt::Unchecked);
+ }
+
label7 = new QLabel(tab1);
- label7->setGeometry(20, 195, 200, 25);
+ label7->setGeometry(20, 225, 200, 25);
label7->setText("Baseline color");
checkbox3 = new QCheckBox(tab1);
- checkbox3->setGeometry(200, 198, 20, 20);
+ checkbox3->setGeometry(200, 228, 20, 20);
checkbox3->setTristate(false);
if(mainwindow->show_baselines)
{
@@ -141,39 +159,39 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
}
BaseColorButton = new SpecialButton(tab1);
- BaseColorButton->setGeometry(240, 200, 60, 15);
+ BaseColorButton->setGeometry(240, 230, 60, 15);
BaseColorButton->setColor(mainwindow->maincurve->baseline_color);
label8 = new QLabel(tab1);
- label8->setGeometry(20, 225, 200, 25);
+ label8->setGeometry(20, 255, 200, 25);
label8->setText("Crosshair color");
Crh1ColorButton = new SpecialButton(tab1);
- Crh1ColorButton->setGeometry(240, 230, 60, 15);
+ Crh1ColorButton->setGeometry(240, 260, 60, 15);
Crh1ColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->crosshair_1.color);
label9 = new QLabel(tab1);
- label9->setGeometry(20, 255, 200, 25);
+ label9->setGeometry(20, 285, 200, 25);
label9->setText("2th Crosshair color");
Crh2ColorButton = new SpecialButton(tab1);
- Crh2ColorButton->setGeometry(240, 260, 60, 15);
+ Crh2ColorButton->setGeometry(240, 290, 60, 15);
Crh2ColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->crosshair_2.color);
label10 = new QLabel(tab1);
- label10->setGeometry(20, 285, 200, 25);
+ label10->setGeometry(20, 315, 200, 25);
label10->setText("Floating ruler color");
FrColorButton = new SpecialButton(tab1);
- FrColorButton->setGeometry(240, 290, 60, 15);
+ FrColorButton->setGeometry(240, 320, 60, 15);
FrColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->floating_ruler_color);
label12 = new QLabel(tab1);
- label12->setGeometry(20, 315, 200, 25);
+ label12->setGeometry(20, 345, 200, 25);
label12->setText("Annotation marker");
checkbox2 = new QCheckBox(tab1);
- checkbox2->setGeometry(200, 318, 20, 20);
+ checkbox2->setGeometry(200, 348, 20, 20);
checkbox2->setTristate(false);
if(mainwindow->show_annot_markers)
{
@@ -185,15 +203,15 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
}
AnnotMkrButton = new SpecialButton(tab1);
- AnnotMkrButton->setGeometry(240, 320, 60, 15);
+ AnnotMkrButton->setGeometry(240, 350, 60, 15);
AnnotMkrButton->setColor(mainwindow->maincurve->annot_marker_color);
label12_2 = new QLabel(tab1);
- label12_2->setGeometry(20, 345, 200, 25);
+ label12_2->setGeometry(20, 375, 200, 25);
label12_2->setText("Show duration at marker");
checkbox2_1 = new QCheckBox(tab1);
- checkbox2_1->setGeometry(200, 348, 20, 20);
+ checkbox2_1->setGeometry(200, 378, 20, 20);
checkbox2_1->setTristate(false);
if(mainwindow->annotations_show_duration)
{
@@ -205,19 +223,19 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
}
label12_1 = new QLabel(tab1);
- label12_1->setGeometry(20, 375, 200, 25);
+ label12_1->setGeometry(20, 405, 200, 25);
label12_1->setText("Annotation duration background");
AnnotDurationButton = new SpecialButton(tab1);
- AnnotDurationButton->setGeometry(240, 380, 60, 15);
+ AnnotDurationButton->setGeometry(240, 410, 60, 15);
AnnotDurationButton->setColor(mainwindow->maincurve->annot_duration_color);
label12_3 = new QLabel(tab1);
- label12_3->setGeometry(20, 405, 200, 25);
+ label12_3->setGeometry(20, 435, 200, 25);
label12_3->setText("Show only at screen bottom");
checkbox2_2 = new QCheckBox(tab1);
- checkbox2_2->setGeometry(200, 408, 20, 20);
+ checkbox2_2->setGeometry(200, 438, 20, 20);
checkbox2_2->setTristate(false);
if(mainwindow->annotations_duration_background_type)
{
@@ -229,11 +247,11 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
}
label14 = new QLabel(tab1);
- label14->setGeometry(20, 435, 200, 25);
+ label14->setGeometry(20, 465, 200, 25);
label14->setText("Annotations: filter list only");
checkbox5 = new QCheckBox(tab1);
- checkbox5->setGeometry(200, 438, 20, 20);
+ checkbox5->setGeometry(200, 468, 20, 20);
checkbox5->setTristate(false);
checkbox5->setToolTip("Annotation filter affects the annotationlist only, not the annotation markers in the signal window");
if(mainwindow->annot_filter->hide_in_list_only)
@@ -246,11 +264,11 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
}
label11 = new QLabel(tab1);
- label11->setGeometry(20, 465, 200, 25);
+ label11->setGeometry(20, 495, 200, 25);
label11->setText("Print in grayscale");
checkbox1 = new QCheckBox(tab1);
- checkbox1->setGeometry(200, 468, 20, 20);
+ checkbox1->setGeometry(200, 498, 20, 20);
checkbox1->setTristate(false);
if(mainwindow->maincurve->blackwhite_printing)
{
@@ -262,11 +280,11 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
}
label13 = new QLabel(tab1);
- label13->setGeometry(20, 495, 200, 25);
+ label13->setGeometry(20, 525, 200, 25);
label13->setText("Clip signals to pane");
checkbox4 = new QCheckBox(tab1);
- checkbox4->setGeometry(200, 498, 20, 20);
+ checkbox4->setGeometry(200, 528, 20, 20);
checkbox4->setTristate(false);
if(mainwindow->clip_to_pane)
{
@@ -278,26 +296,26 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
}
groupbox1 = new QGroupBox("Colorschema", tab1);
- groupbox1->setGeometry(120, 540, 180, 195);
+ groupbox1->setGeometry(120, 570, 180, 195);
colorSchema_Dark_Button = new QPushButton(tab1);
- colorSchema_Dark_Button->setGeometry(150, 570, 120, 20);
+ colorSchema_Dark_Button->setGeometry(150, 600, 120, 20);
colorSchema_Dark_Button->setText("\"Dark\"");
colorSchema_NK_Button = new QPushButton(tab1);
- colorSchema_NK_Button->setGeometry(150, 600, 120, 20);
+ colorSchema_NK_Button->setGeometry(150, 630, 120, 20);
colorSchema_NK_Button->setText("\"NK\"");
colorSchema_Blue_on_Gray_Button = new QPushButton(tab1);
- colorSchema_Blue_on_Gray_Button->setGeometry(150, 630, 120, 20);
+ colorSchema_Blue_on_Gray_Button->setGeometry(150, 660, 120, 20);
colorSchema_Blue_on_Gray_Button->setText("\"Blue on gray\"");
saveColorSchemaButton = new QPushButton(tab1);
- saveColorSchemaButton->setGeometry(150, 660, 120, 20);
+ saveColorSchemaButton->setGeometry(150, 690, 120, 20);
saveColorSchemaButton->setText("Save");
loadColorSchemaButton = new QPushButton(tab1);
- loadColorSchemaButton->setGeometry(150, 690, 120, 20);
+ loadColorSchemaButton->setGeometry(150, 720, 120, 20);
loadColorSchemaButton->setText("Load");
QObject::connect(BgColorButton, SIGNAL(clicked(SpecialButton *)), this, SLOT(BgColorButtonClicked(SpecialButton *)));
@@ -319,6 +337,7 @@ UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent)
QObject::connect(checkbox3, SIGNAL(stateChanged(int)), this, SLOT(checkbox3Clicked(int)));
QObject::connect(checkbox4, SIGNAL(stateChanged(int)), this, SLOT(checkbox4Clicked(int)));
QObject::connect(checkbox5, SIGNAL(stateChanged(int)), this, SLOT(checkbox5Clicked(int)));
+ QObject::connect(checkbox16, SIGNAL(stateChanged(int)), this, SLOT(checkbox16Clicked(int)));
QObject::connect(saveColorSchemaButton, SIGNAL(clicked()), this, SLOT(saveColorSchemaButtonClicked()));
QObject::connect(loadColorSchemaButton, SIGNAL(clicked()), this, SLOT(loadColorSchemaButtonClicked()));
QObject::connect(colorSchema_Blue_on_Gray_Button, SIGNAL(clicked()), this, SLOT(loadColorSchema_blue_gray()));
@@ -1241,6 +1260,20 @@ void UI_OptionsDialog::checkbox5Clicked(int state)
}
+void UI_OptionsDialog::checkbox16Clicked(int state)
+{
+ if(state==Qt::Checked)
+ {
+ mainwindow->use_diverse_signal_colors = 1;
+ }
+
+ if(state==Qt::Unchecked)
+ {
+ mainwindow->use_diverse_signal_colors = 0;
+ }
+}
+
+
void UI_OptionsDialog::checkbox3_1Clicked(int state)
{
if(state==Qt::Checked)
=====================================
options_dialog.h
=====================================
@@ -150,6 +150,7 @@ QLabel *label1,
*label12_3,
*label13,
*label14,
+ *label16,
*label4_1,
*label4_2,
*label4_3,
@@ -191,6 +192,7 @@ QCheckBox *checkbox1,
*checkbox3_1,
*checkbox4,
*checkbox5,
+ *checkbox16,
*checkbox4_1,
*checkbox4_2,
*checkbox4_3,
@@ -234,6 +236,7 @@ void checkbox2_2Clicked(int);
void checkbox3Clicked(int);
void checkbox4Clicked(int);
void checkbox5Clicked(int);
+void checkbox16Clicked(int);
void checkbox3_1Clicked(int);
void checkbox4_1Clicked(int);
void checkbox4_2Clicked(int);
=====================================
read_write_settings.cpp
=====================================
@@ -1838,6 +1838,23 @@ void UI_Mainwindow::read_general_settings()
xml_go_up(xml_hdl);
}
+ if(!(xml_goto_nth_element_inside(xml_hdl, "use_diverse_signal_colors", 0)))
+ {
+ if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN))
+ {
+ xml_close(xml_hdl);
+ return;
+ }
+
+ use_diverse_signal_colors = atoi(result);
+ if(use_diverse_signal_colors != 1)
+ {
+ use_diverse_signal_colors = 0;
+ }
+
+ xml_go_up(xml_hdl);
+ }
+
xml_close(xml_hdl);
}
@@ -2225,6 +2242,8 @@ void UI_Mainwindow::write_settings()
fprintf(cfgfile, " <auto_update_annot_onset>%i</auto_update_annot_onset>\n", auto_update_annot_onset);
+ fprintf(cfgfile, " <use_diverse_signal_colors>%i</use_diverse_signal_colors>\n", use_diverse_signal_colors);
+
fprintf(cfgfile, " </UI>\n</config>\n");
fclose(cfgfile);
=====================================
signalcurve.cpp
=====================================
@@ -1031,7 +1031,14 @@ void SignalCurve::drawWidget_to_printer(QPainter *painter, int curve_w, int curv
continue;
}
- q_str.setNum((double)i / (double)p2_multiplier, 'f', precision);
+ if((precision == 0) && (max_value > 1000.0))
+ {
+ q_str.setNum((double)i / (double)p2_multiplier, 'e', precision);
+ }
+ else
+ {
+ q_str.setNum((double)i / (double)p2_multiplier, 'f', precision);
+ }
p2_tmp = (double)(i - p2_ruler_startvalue) * p2_pixels_per_unit;
@@ -1594,7 +1601,14 @@ void SignalCurve::drawWidget(QPainter *painter, int curve_w, int curve_h)
continue;
}
- q_str.setNum((double)lk / (double)p2_multiplier, 'f', precision);
+ if((precision == 0) && (max_value > 1000.0))
+ {
+ q_str.setNum((double)lk / (double)p2_multiplier, 'e', precision);
+ }
+ else
+ {
+ q_str.setNum((double)lk / (double)p2_multiplier, 'f', precision);
+ }
p2_tmp = (double)(lk - p2_ruler_startvalue) * p2_pixels_per_unit;
=====================================
signals_dialog.cpp
=====================================
@@ -37,6 +37,17 @@ UI_Signalswindow::UI_Signalswindow(QWidget *w_parent)
mainwindow = (UI_Mainwindow *)w_parent;
+ smp_per_record = 0;
+
+ last_default_color = 0;
+
+ default_color_list[0] = Qt::yellow;
+ default_color_list[1] = Qt::green;
+ default_color_list[2] = Qt::red;
+ default_color_list[3] = Qt::cyan;
+ default_color_list[4] = Qt::magenta;
+ default_color_list[5] = Qt::blue;
+
SignalsDialog = new QDialog;
SignalsDialog->setMinimumSize(800, 500);
@@ -124,8 +135,6 @@ UI_Signalswindow::UI_Signalswindow(QWidget *w_parent)
compositionlist->setSelectionBehavior(QAbstractItemView::SelectRows);
compositionlist->setSelectionMode(QAbstractItemView::ExtendedSelection);
- smp_per_record = 0;
-
QObject::connect(CloseButton, SIGNAL(clicked()), SignalsDialog, SLOT(close()));
QObject::connect(SelectAllButton, SIGNAL(clicked()), this, SLOT(SelectAllButtonClicked()));
QObject::connect(HelpButton, SIGNAL(clicked()), this, SLOT(HelpButtonClicked()));
@@ -195,7 +204,15 @@ void UI_Signalswindow::DisplayCompButtonClicked()
newsignalcomp->edfhdr = mainwindow->edfheaderlist[newsignalcomp->filenum];
newsignalcomp->file_duration = newsignalcomp->edfhdr->long_data_record_duration * newsignalcomp->edfhdr->datarecords;
newsignalcomp->voltpercm = mainwindow->default_amplitude;
- newsignalcomp->color = curve_color;
+ if(mainwindow->use_diverse_signal_colors)
+ {
+ newsignalcomp->color = default_color_list[last_default_color++];
+ last_default_color %= 6;
+ }
+ else
+ {
+ newsignalcomp->color = curve_color;
+ }
newsignalcomp->hasruler = 0;
newsignalcomp->polarity = 1;
@@ -297,7 +314,15 @@ void UI_Signalswindow::DisplayButtonClicked()
newsignalcomp->edfhdr = mainwindow->edfheaderlist[newsignalcomp->filenum];
newsignalcomp->file_duration = newsignalcomp->edfhdr->long_data_record_duration * newsignalcomp->edfhdr->datarecords;
newsignalcomp->voltpercm = mainwindow->default_amplitude;
- newsignalcomp->color = curve_color;
+ if(mainwindow->use_diverse_signal_colors)
+ {
+ newsignalcomp->color = default_color_list[last_default_color++];
+ last_default_color %= 6;
+ }
+ else
+ {
+ newsignalcomp->color = curve_color;
+ }
newsignalcomp->hasruler = 0;
newsignalcomp->polarity = 1;
=====================================
signals_dialog.h
=====================================
@@ -102,7 +102,9 @@ private:
SpecialButton *ColorButton;
int smp_per_record,
- curve_color;
+ curve_color,
+ default_color_list[32],
+ last_default_color;
char physdimension[64];
=====================================
spectrum_dock.cpp
=====================================
@@ -224,8 +224,12 @@ UI_SpectrumDockWindow::UI_SpectrumDockWindow(QWidget *w_parent)
windowBox->addItem("Nuttall4c");
windowBox->addItem("Hann");
windowBox->addItem("HFT223D");
+ windowBox->addItem("HFT95");
windowBox->setCurrentIndex(window_type);
windowBox->setToolTip("Window");
+ windowBox->setCurrentIndex(mainwindow->spectrumdock_window);
+
+ window_type = mainwindow->spectrumdock_window;
overlap_box = new QComboBox;
overlap_box->setMinimumSize(70, 25);
@@ -234,6 +238,9 @@ UI_SpectrumDockWindow::UI_SpectrumDockWindow(QWidget *w_parent)
overlap_box->addItem("Overlap: 67%");
overlap_box->addItem("Overlap: 75%");
overlap_box->addItem("Overlap: 80%");
+ overlap_box->setCurrentIndex(mainwindow->spectrumdock_overlap);
+
+ overlap = mainwindow->spectrumdock_overlap + 1;
dftsz_label = new QLabel;
dftsz_label->setText("Blocksize:");
@@ -356,6 +363,8 @@ void UI_SpectrumDockWindow::windowBox_changed(int idx)
window_type = idx;
+ mainwindow->spectrumdock_window = idx;
+
init_maxvalue = 1;
update_curve();
@@ -382,6 +391,8 @@ void UI_SpectrumDockWindow::overlap_box_changed(int idx)
if(overlap == (idx + 1)) return;
+ mainwindow->spectrumdock_overlap = idx;
+
overlap = idx + 1;
init_maxvalue = 1;
@@ -390,14 +401,87 @@ void UI_SpectrumDockWindow::overlap_box_changed(int idx)
}
-void UI_SpectrumDockWindow::open_close_dock(bool)
+void UI_SpectrumDockWindow::open_close_dock(bool visible)
{
+ char str[512]={""};
+
if(mainwindow->files_open != 1 || signal_nr < 0)
{
dock->hide();
return;
}
+
+ if(visible)
+ {
+ overlap_box->setCurrentIndex(mainwindow->spectrumdock_overlap);
+
+ overlap = mainwindow->spectrumdock_overlap + 1;
+
+ windowBox->setCurrentIndex(mainwindow->spectrumdock_window);
+
+ window_type = mainwindow->spectrumdock_window;
+
+ if(mainwindow->spectrumdock_sqrt)
+ {
+ sqrtButton->setChecked(true);
+
+ snprintf(str, 512, "Amplitude Spectrum %.64s", signallabel);
+
+ dock->setWindowTitle(str);
+
+ if(mainwindow->spectrumdock_vlog)
+ {
+ snprintf(str, 512, "log10(%s)", physdimension);
+ curve1->setV_label(str);
+ }
+ else
+ {
+ curve1->setV_label(physdimension);
+ }
+ }
+ else
+ {
+ sqrtButton->setChecked(false);
+
+ snprintf(str, 512, "Power Spectrum %.64s", signallabel);
+
+ dock->setWindowTitle(str);
+
+ if(mainwindow->spectrumdock_vlog)
+ {
+ snprintf(str, 512, "log((%s)^2/Hz)", physdimension);
+ }
+ else
+ {
+ snprintf(str, 512, "(%s)^2/Hz", physdimension);
+ }
+
+ curve1->setV_label(str);
+ }
+
+ if(mainwindow->spectrumdock_vlog)
+ {
+ vlogButton->setChecked(true);
+
+ log_minslider->setVisible(true);
+ }
+ else
+ {
+ vlogButton->setChecked(false);
+
+ log_minslider->setVisible(false);
+ }
+
+ if(mainwindow->spectrumdock_colorbars)
+ {
+ colorBarButton->setCheckState(Qt::Checked);
+ }
+ else
+ {
+ colorBarButton->setCheckState(Qt::Unchecked);
+ }
+ }
}
=====================================
spectrumanalyzer.cpp
=====================================
@@ -289,6 +289,7 @@ UI_FreqSpectrumWindow::UI_FreqSpectrumWindow(struct signalcompblock *signal_comp
dftsz_box->addItem("Blocksize: 5000000");
dftsz_box->addItem("Blocksize: 8388608");
dftsz_box->addItem("Blocksize: 10000000");
+ dftsz_box->setCurrentIndex(mainwindow->spectrum_blocksize_predefined);
windowBox = new QComboBox;
windowBox->setMinimumSize(70, 25);
@@ -300,15 +301,35 @@ UI_FreqSpectrumWindow::UI_FreqSpectrumWindow(struct signalcompblock *signal_comp
windowBox->addItem("Nuttall4c");
windowBox->addItem("Hann");
windowBox->addItem("HFT223D");
+ windowBox->addItem("HFT95");
windowBox->setCurrentIndex(window_type);
windowBox->setToolTip("Window");
+ windowBox->setCurrentIndex(mainwindow->spectrum_window);
+
+ window_type = mainwindow->spectrum_window;
dftsz_spinbox = new QSpinBox;
dftsz_spinbox->setMinimumSize(70, 25);
dftsz_spinbox->setMinimum(10);
- dftsz_spinbox->setMaximum(1000);
dftsz_spinbox->setSingleStep(2);
- dftsz_spinbox->setValue(dftblocksize);
+ if(mainwindow->spectrum_blocksize_predefined)
+ {
+ dftsz_spinbox->setMaximum(10000000);
+
+ dftsz_spinbox->setValue(dftsz_range[mainwindow->spectrum_blocksize_predefined]);
+
+ dftblocksize = dftsz_range[mainwindow->spectrum_blocksize_predefined];
+
+ dftsz_spinbox->setEnabled(false);
+ }
+ else
+ {
+ dftsz_spinbox->setMaximum(1000);
+
+ dftsz_spinbox->setValue(mainwindow->spectrum_blocksize_userdefined);
+
+ dftblocksize = mainwindow->spectrum_blocksize_userdefined;
+ }
overlap_box = new QComboBox;
overlap_box->setMinimumSize(70, 25);
@@ -317,6 +338,9 @@ UI_FreqSpectrumWindow::UI_FreqSpectrumWindow(struct signalcompblock *signal_comp
overlap_box->addItem("Overlap: 67%");
overlap_box->addItem("Overlap: 75%");
overlap_box->addItem("Overlap: 80%");
+ overlap_box->setCurrentIndex(mainwindow->spectrum_overlap);
+
+ overlap = mainwindow->spectrum_overlap + 1;
vlayout3 = new QVBoxLayout;
vlayout3->addStretch(100);
@@ -428,6 +452,8 @@ void UI_FreqSpectrumWindow::windowBox_changed(int idx)
if(window_type == idx) return;
+ mainwindow->spectrum_window = idx;
+
window_type = idx;
busy = 1;
@@ -464,6 +490,8 @@ void UI_FreqSpectrumWindow::dftsz_value_changed(int new_val)
void UI_FreqSpectrumWindow::dftsz_box_changed(int idx)
{
+ mainwindow->spectrum_blocksize_predefined = idx;
+
if(idx)
{
if(dftsz_range[idx] > samples)
@@ -503,6 +531,8 @@ void UI_FreqSpectrumWindow::overlap_box_changed(int idx)
if(overlap == (idx + 1)) return;
+ mainwindow->spectrum_overlap = idx;
+
overlap = idx + 1;
busy = 1;
@@ -600,6 +630,8 @@ void UI_FreqSpectrumWindow::print_to_txt()
break;
case FFT_WNDW_TYPE_HFT223D : fprintf(outputfile, "FFT window function: HFT223D\n");
break;
+ case FFT_WNDW_TYPE_HFT95 : fprintf(outputfile, "FFT window function: HFT95\n");
+ break;
}
switch(overlap)
{
=====================================
version.txt
=====================================
@@ -1,5 +1,24 @@
+ version 1.71 December 21, 2019
+ --------------
+
+ - Added an option in the settings dialog to enable to assign varying colors to traces
+ when adding traces to the screen.
+
+ - Spectrumanalyzer: switch to exponential notation in case of big numbers.
+
+ - Spectrum Analyzer: added window type "HFT95".
+
+ - Converters: added a ISHNE Holter ECG to EDF converter.
+
+ - Videoplayer: fixed a bug that could cause a wrong synchronization between the video and the EDF file.
+
+ - Import annotations: solved a bug that prevented to import annotations stored in an ASCII file when
+ the option "Manual description" was enabled.
+
+
+
version 1.70 September 7, 2019
--------------
=====================================
videoplayer.cpp
=====================================
@@ -496,7 +496,7 @@ void UI_Mainwindow::video_poll_timer_func()
if(video_player->fpos != vpos)
{
- jump_to_time_millisec(video_player->utc_starttime - edfheaderlist[sel_viewtime]->utc_starttime + (vpos * 1000LL) - (pagetime / 20000));
+ jump_to_time_millisec(((video_player->utc_starttime - edfheaderlist[sel_viewtime]->utc_starttime + vpos) * 1000LL) - (pagetime / 20000LL));
video_player->fpos = vpos;
View it on GitLab: https://salsa.debian.org/med-team/edfbrowser/commit/4ac4810027b859d7f08c3c9ae1633c97e005b54e
--
View it on GitLab: https://salsa.debian.org/med-team/edfbrowser/commit/4ac4810027b859d7f08c3c9ae1633c97e005b54e
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20200105/9cbaf8ea/attachment-0001.html>
More information about the debian-med-commit
mailing list