./PaxHeaders.7921/edfbrowser_157_source0000644000000000000000000000013212646460742014746 xustar0030 mtime=1452958178.269246659 30 atime=1452958178.221246821 30 ctime=1452958178.269246659 edfbrowser_157_source/0000755000175000001440000000000012646460742015227 5ustar00guvusers00000000000000edfbrowser_157_source/PaxHeaders.7921/z_ratio_filter.cpp0000644000000000000000000000013212646460742020406 xustar0030 mtime=1452958178.249246726 30 atime=1452958178.249246726 30 ctime=1452958178.249246726 edfbrowser_157_source/z_ratio_filter.cpp0000644000175000001440000001363412646460742020756 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "z_ratio_filter.h" #define ZRATIO_EPOCH_LEN 2 #define ZRATIO_F1 3.0 #define ZRATIO_F3 12.0 #define ZRATIO_F4 25.0 struct zratio_filter_settings * create_zratio_filter(int smp_per_record, long long long_data_record_duration, double crossoverf, double bitval) { struct zratio_filter_settings * settings; settings = (struct zratio_filter_settings *)calloc(1, sizeof(struct zratio_filter_settings)); if(settings == NULL) { return(NULL); } settings->crossoverfreq = crossoverf; settings->bitvalue = bitval; settings->dftblocksize = ((long long)smp_per_record * (ZRATIO_EPOCH_LEN * TIME_DIMENSION)) / long_data_record_duration; if(settings->dftblocksize < (ZRATIO_EPOCH_LEN * 100)) { free(settings); return(NULL); } settings->samplefreq = (double)smp_per_record / ((double)long_data_record_duration / TIME_DIMENSION); if(settings->samplefreq < 99.9999999) { free(settings); return(NULL); } settings->fft_outputbufsize = settings->dftblocksize / 2; settings->freqstep = settings->samplefreq / (double)settings->dftblocksize; if(settings->freqstep > 1.0001) { free(settings); return(NULL); } settings->f2 = settings->crossoverfreq / settings->freqstep; settings->f1 = ZRATIO_F1 / settings->freqstep; settings->f3 = ZRATIO_F3 / settings->freqstep; settings->f4 = ZRATIO_F4 / settings->freqstep; settings->fft_inputbuf = (double *)malloc(sizeof(double) * settings->dftblocksize); if(settings->fft_inputbuf == NULL) { free(settings); return(NULL); } settings->fft_inputbuf_bu = (double *)malloc(sizeof(double) * settings->dftblocksize); if(settings->fft_inputbuf_bu == NULL) { free(settings->fft_inputbuf); free(settings); return(NULL); } settings->fft_outputbuf = (double *)calloc(1, sizeof(double) * settings->fft_outputbufsize); if(settings->fft_outputbuf == NULL) { free(settings->fft_inputbuf); free(settings->fft_inputbuf_bu); free(settings); return(NULL); } settings->kiss_fftbuf = (kiss_fft_cpx *)malloc((settings->fft_outputbufsize + 1) * sizeof(kiss_fft_cpx)); if(settings->kiss_fftbuf == NULL) { free(settings->fft_inputbuf); free(settings->fft_inputbuf_bu); free(settings->fft_outputbuf); free(settings); return(NULL); } settings->cfg = kiss_fftr_alloc(settings->dftblocksize, 0, NULL, NULL); settings->smpls_in_inputbuf = 0; settings->zratio_value = 0.0; return(settings); } double run_zratio_filter(double new_sample, struct zratio_filter_settings *settings) { int i; double power_delta, power_theta, power_alpha, power_beta, power_total; settings->fft_inputbuf[settings->smpls_in_inputbuf++] = new_sample; if(settings->smpls_in_inputbuf >= settings->dftblocksize) { settings->smpls_in_inputbuf = 0; kiss_fftr(settings->cfg, settings->fft_inputbuf, settings->kiss_fftbuf); power_delta = 0.0; power_theta = 0.0; power_alpha = 0.0; power_beta = 0.0; power_total = 0.0; for(i=0; ifft_outputbufsize; i++) { settings->fft_outputbuf[i] = (((settings->kiss_fftbuf[i].r * settings->kiss_fftbuf[i].r) + (settings->kiss_fftbuf[i].i * settings->kiss_fftbuf[i].i)) / settings->fft_outputbufsize); if((i > 0) && (i < settings->f1)) { power_delta += settings->fft_outputbuf[i]; } if((i >= settings->f1) && (i < settings->f2)) { power_theta += settings->fft_outputbuf[i]; } if((i >= settings->f2) && (i < settings->f3)) { power_alpha += settings->fft_outputbuf[i]; } if((i >= settings->f3) && (i <= settings->f4)) { power_beta += settings->fft_outputbuf[i]; } power_total += settings->fft_outputbuf[i]; } if(power_total <= 0.0) { settings->zratio_value = 0.0; } else { settings->zratio_value = ((power_delta + power_theta) - (power_alpha + power_beta)) / power_total; } } return(settings->zratio_value / settings->bitvalue); } void zratio_filter_save_buf(struct zratio_filter_settings *settings) { settings->smpls_in_inputbuf_bu = settings->smpls_in_inputbuf; settings->zratio_value_bu = settings->zratio_value; memcpy(settings->fft_inputbuf_bu, settings->fft_inputbuf, settings->dftblocksize); } void zratio_filter_restore_buf(struct zratio_filter_settings *settings) { settings->smpls_in_inputbuf = settings->smpls_in_inputbuf_bu; settings->zratio_value = settings->zratio_value_bu; memcpy(settings->fft_inputbuf, settings->fft_inputbuf_bu, settings->dftblocksize); } void free_zratio_filter(struct zratio_filter_settings *settings) { free(settings->fft_inputbuf); free(settings->fft_inputbuf_bu); free(settings->fft_outputbuf); free(settings->kiss_fftbuf); free(settings->cfg); free(settings); } void reset_zratio_filter(struct zratio_filter_settings *settings) { settings->smpls_in_inputbuf = 0; settings->zratio_value = 0.0; } edfbrowser_157_source/PaxHeaders.7921/signal_chooser.h0000644000000000000000000000013212646460742020036 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/signal_chooser.h0000644000175000001440000000415012646460742020377 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef SIGNAL_CHOOSERFORM1_H #define SIGNAL_CHOOSERFORM1_H #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "viewcurve.h" #include "adjustfiltersettings.h" #include "ecg_filter.h" #include "utils.h" class UI_Mainwindow; class ViewCurve; class UI_SignalChooser : public QObject { Q_OBJECT public: UI_SignalChooser(QWidget *, int, int *sgnl_nr = NULL); UI_Mainwindow *mainwindow; private: QDialog *signalchooser_dialog; QPushButton *CloseButton, *UpButton, *DownButton, *DeleteButton, *InvertButton; QListWidget *list; int task, *signal_nr; void strip_types_from_label(char *); void load_signalcomps(void); int get_selectionlist(int *); private slots: void call_sidemenu(QListWidgetItem *); void signalUp(); void signalDown(); void signalDelete(); void signalInvert(); }; #endif // SIGNAL_CHOOSERFORM1_H edfbrowser_157_source/PaxHeaders.7921/biox2edf.h0000644000000000000000000000013212646460742016541 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/biox2edf.h0000644000175000001440000000353212646460742017105 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_BIOX2EDFFORM_H #define UI_BIOX2EDFFORM_H #include #include #include #include #include #include #include #include #include #if QT_VERSION < 0x050000 #include #include #endif #include #include #include #include #include #include #include "global.h" #include "utils.h" #include "edflib.h" #include "utc_date_time.h" class UI_BIOX2EDFwindow : public QObject { Q_OBJECT public: UI_BIOX2EDFwindow(char *recent_dir=NULL, char *save_dir=NULL); private: QPushButton *pushButton1, *pushButton2; QTextEdit *textEdit1; QDialog *myobjectDialog; char *recent_opendir, *recent_savedir; private slots: void SelectFileButton(); }; #endif edfbrowser_157_source/PaxHeaders.7921/edflib.h0000644000000000000000000000013212646460742016264 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/edflib.h0000644000175000001440000007643712646460742016646 0ustar00guvusers00000000000000/* ***************************************************************************** * * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Teunis van Beelen * All rights reserved. * * email: teuniz@gmail.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY Teunis van Beelen ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL Teunis van Beelen BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************** */ /* compile with options "-D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE" */ #ifndef EDFLIB_INCLUDED #define EDFLIB_INCLUDED #include #include #include #include #define EDFLIB_TIME_DIMENSION (10000000LL) #define EDFLIB_MAXSIGNALS 512 #define EDFLIB_MAX_ANNOTATION_LEN 512 #define EDFSEEK_SET 0 #define EDFSEEK_CUR 1 #define EDFSEEK_END 2 /* the following defines are used in the member "filetype" of the edf_hdr_struct */ /* and as return value for the function edfopen_file_readonly() */ #define EDFLIB_FILETYPE_EDF 0 #define EDFLIB_FILETYPE_EDFPLUS 1 #define EDFLIB_FILETYPE_BDF 2 #define EDFLIB_FILETYPE_BDFPLUS 3 #define EDFLIB_MALLOC_ERROR -1 #define EDFLIB_NO_SUCH_FILE_OR_DIRECTORY -2 #define EDFLIB_FILE_CONTAINS_FORMAT_ERRORS -3 #define EDFLIB_MAXFILES_REACHED -4 #define EDFLIB_FILE_READ_ERROR -5 #define EDFLIB_FILE_ALREADY_OPENED -6 #define EDFLIB_FILETYPE_ERROR -7 #define EDFLIB_FILE_WRITE_ERROR -8 #define EDFLIB_NUMBER_OF_SIGNALS_INVALID -9 #define EDFLIB_FILE_IS_DISCONTINUOUS -10 #define EDFLIB_INVALID_READ_ANNOTS_VALUE -11 /* values for annotations */ #define EDFLIB_DO_NOT_READ_ANNOTATIONS 0 #define EDFLIB_READ_ANNOTATIONS 1 #define EDFLIB_READ_ALL_ANNOTATIONS 2 /* the following defines are possible errors returned by edfopen_file_writeonly() */ #define EDFLIB_NO_SIGNALS -20 #define EDFLIB_TOO_MANY_SIGNALS -21 #define EDFLIB_NO_SAMPLES_IN_RECORD -22 #define EDFLIB_DIGMIN_IS_DIGMAX -23 #define EDFLIB_DIGMAX_LOWER_THAN_DIGMIN -24 #define EDFLIB_PHYSMIN_IS_PHYSMAX -25 #ifdef __cplusplus extern "C" { #endif /* For more info about the EDF and EDF+ format, visit: http://edfplus.info/specs/ */ /* For more info about the BDF and BDF+ format, visit: http://www.teuniz.net/edfbrowser/bdfplus%20format%20description.html */ struct edf_param_struct{ /* this structure contains all the relevant EDF-signal parameters of one signal */ char label[17]; /* label (name) of the signal, null-terminated string */ long long smp_in_file; /* number of samples of this signal in the file */ double phys_max; /* physical maximum, usually the maximum input of the ADC */ double phys_min; /* physical minimum, usually the minimum input of the ADC */ int dig_max; /* digital maximum, usually the maximum output of the ADC, can not not be higher than 32767 for EDF or 8388607 for BDF */ int dig_min; /* digital minimum, usually the minimum output of the ADC, can not not be lower than -32768 for EDF or -8388608 for BDF */ int smp_in_datarecord; /* number of samples of this signal in a datarecord */ char physdimension[9]; /* physical dimension (uV, bpm, mA, etc.), null-terminated string */ char prefilter[81]; /* null-terminated string */ char transducer[81]; /* null-terminated string */ }; struct edf_annotation_struct{ /* this structure is used for annotations */ long long onset; /* onset time of the event, expressed in units of 100 nanoSeconds and relative to the starttime in the header */ char duration[16]; /* duration time, this is a null-terminated ASCII text-string */ char annotation[EDFLIB_MAX_ANNOTATION_LEN + 1]; /* description of the event in UTF-8, this is a null terminated string */ }; struct edf_hdr_struct{ /* this structure contains all the relevant EDF header info and will be filled when calling the function edf_open_file_readonly() */ int handle; /* a handle (identifier) used to distinguish the different files */ int filetype; /* 0: EDF, 1: EDFplus, 2: BDF, 3: BDFplus, a negative number means an error */ int edfsignals; /* number of EDF signals in the file, annotation channels are NOT included */ long long file_duration; /* duration of the file expressed in units of 100 nanoSeconds */ int startdate_day; int startdate_month; int startdate_year; long long starttime_subsecond; /* starttime offset expressed in units of 100 nanoSeconds. Is always less than 10000000 (one second). Only used by EDFplus and BDFplus */ int starttime_second; int starttime_minute; int starttime_hour; char patient[81]; /* null-terminated string, contains patientfield of header, is always empty when filetype is EDFPLUS or BDFPLUS */ char recording[81]; /* null-terminated string, contains recordingfield of header, is always empty when filetype is EDFPLUS or BDFPLUS */ char patientcode[81]; /* null-terminated string, is always empty when filetype is EDF or BDF */ char gender[16]; /* null-terminated string, is always empty when filetype is EDF or BDF */ char birthdate[16]; /* null-terminated string, is always empty when filetype is EDF or BDF */ char patient_name[81]; /* null-terminated string, is always empty when filetype is EDF or BDF */ char patient_additional[81]; /* null-terminated string, is always empty when filetype is EDF or BDF */ char admincode[81]; /* null-terminated string, is always empty when filetype is EDF or BDF */ char technician[81]; /* null-terminated string, is always empty when filetype is EDF or BDF */ char equipment[81]; /* null-terminated string, is always empty when filetype is EDF or BDF */ char recording_additional[81]; /* null-terminated string, is always empty when filetype is EDF or BDF */ long long datarecord_duration; /* duration of a datarecord expressed in units of 100 nanoSeconds */ long long datarecords_in_file; /* number of datarecords in the file */ long long annotations_in_file; /* number of annotations in the file */ struct edf_param_struct signalparam[EDFLIB_MAXSIGNALS]; /* array of structs which contain the relevant signal parameters */ }; /***************** the following functions are used to read files **************************/ int edfopen_file_readonly(const char *path, struct edf_hdr_struct *edfhdr, int read_annotations); /* opens an existing file for reading */ /* path is a null-terminated string containing the path to the file */ /* hdr is a pointer to an edf_hdr_struct, all fields in this struct will be overwritten */ /* the edf_hdr_struct will be filled with all the relevant header- and signalinfo/parameters */ /* read_annotations must have one of the following values: */ /* EDFLIB_DO_NOT_READ_ANNOTATIONS annotations will not be read (this saves time when opening a very large EDFplus or BDFplus file */ /* EDFLIB_READ_ANNOTATIONS annotations will be read immediately, stops when an annotation has */ /* been found which contains the description "Recording ends" */ /* EDFLIB_READ_ALL_ANNOTATIONS all annotations will be read immediately */ /* returns 0 on success, in case of an error it returns -1 and an errorcode will be set in the member "filetype" of struct edf_hdr_struct */ /* This function is required if you want to read a file */ int edfread_physical_samples(int handle, int edfsignal, int n, double *buf); /* reads n samples from edfsignal, starting from the current sample position indicator, into buf (edfsignal starts at 0) */ /* the values are converted to their physical values e.g. microVolts, beats per minute, etc. */ /* bufsize should be equal to or bigger than sizeof(double[n]) */ /* the sample position indicator will be increased with the amount of samples read */ /* returns the amount of samples read (this can be less than n or zero!) */ /* or -1 in case of an error */ int edfread_digital_samples(int handle, int edfsignal, int n, int *buf); /* reads n samples from edfsignal, starting from the current sample position indicator, into buf (edfsignal starts at 0) */ /* the values are the "raw" digital values */ /* bufsize should be equal to or bigger than sizeof(int[n]) */ /* the sample position indicator will be increased with the amount of samples read */ /* returns the amount of samples read (this can be less than n or zero!) */ /* or -1 in case of an error */ long long edfseek(int handle, int edfsignal, long long offset, int whence); /* The edfseek() function sets the sample position indicator for the edfsignal pointed to by edfsignal. */ /* The new position, measured in samples, is obtained by adding offset samples to the position specified by whence. */ /* If whence is set to EDFSEEK_SET, EDFSEEK_CUR, or EDFSEEK_END, the offset is relative to the start of the file, */ /* the current position indicator, or end-of-file, respectively. */ /* Returns the current offset. Otherwise, -1 is returned. */ /* note that every signal has it's own independent sample position indicator and edfseek() affects only one of them */ long long edftell(int handle, int edfsignal); /* The edftell() function obtains the current value of the sample position indicator for the edfsignal pointed to by edfsignal. */ /* Returns the current offset. Otherwise, -1 is returned */ /* note that every signal has it's own independent sample position indicator and edftell() affects only one of them */ void edfrewind(int handle, int edfsignal); /* The edfrewind() function sets the sample position indicator for the edfsignal pointed to by edfsignal to the beginning of the file. */ /* It is equivalent to: (void) edfseek(int handle, int edfsignal, 0LL, EDFSEEK_SET) */ /* note that every signal has it's own independent sample position indicator and edfrewind() affects only one of them */ int edf_get_annotation(int handle, int n, struct edf_annotation_struct *annot); /* Fills the edf_annotation_struct with the annotation n, returns 0 on success, otherwise -1 */ /* The string that describes the annotation/event is encoded in UTF-8 */ /* To obtain the number of annotations in a file, check edf_hdr_struct -> annotations_in_file. */ /* Notes: Annotationsignals EDFplus and BDFplus store the annotations in one or more signals (in order to be backwards compatibel with EDF and BDF). The counting of the signals in the file starts at 0. Signals used for annotations are skipped by EDFlib. This means that the annotationsignal(s) in the file are hided. Use the function edf_get_annotation() to get the annotations. So, when a file contains 5 signals and the third signal is used to store the annotations, the library will report that there are only 4 signals in the file. The library will "map" the signalnumbers as follows: 0->0, 1->1, 2->3, 3->4. This way you don't need to worry about which signals are annotationsignals. The library will do it for you. How the library stores time-values To avoid rounding errors, the library stores some timevalues in variables of type long long int. In order not to loose the subsecond precision, all timevalues have been multiplied by 10000000. This will limit the timeresolution to 100 nanoSeconds. To calculate the amount of seconds, divide the timevalue by 10000000 or use the macro EDFLIB_TIME_DIMENSION which is declared in edflib.h. The following variables do use this when you open a file in read mode: "file_duration", "starttime_subsecond" and "onset". */ /***************** the following functions are used to read or write files **************************/ int edfclose_file(int handle); /* closes (and in case of writing, finalizes) the file */ /* returns -1 in case of an error, 0 on success */ /* this function MUST be called when you are finished reading or writing */ /* This function is required after reading or writing. Failing to do so will cause */ /* unnessecary memory usage and in case of writing it will cause a corrupted and incomplete file */ int edflib_version(void); /* Returns the version number of this library, multiplied by hundred. if version is "1.00" than it will return 100 */ int edflib_is_file_used(const char *path); /* returns 1 if the file is used, either for reading or writing */ /* otherwise returns 0 */ int edflib_get_number_of_open_files(void); /* returns the number of open files, either for reading or writing */ int edflib_get_handle(int file_number); /* returns the handle of an opened file, either for reading or writing */ /* file_number starts with 0 */ /* returns -1 if the file is not opened */ /***************** the following functions are used to write files **************************/ int edfopen_file_writeonly(const char *path, int filetype, int number_of_signals); /* opens an new file for writing. warning, an already existing file with the same name will be silently overwritten without advance warning!! */ /* path is a null-terminated string containing the path and name of the file */ /* filetype must be EDFLIB_FILETYPE_EDFPLUS or EDFLIB_FILETYPE_BDFPLUS */ /* returns a handle on success, you need this handle for the other functions */ /* in case of an error it returns a negative number corresponding to one of the following values: */ /* EDFLIB_MALLOC_ERROR */ /* EDFLIB_NO_SUCH_FILE_OR_DIRECTORY */ /* EDFLIB_MAXFILES_REACHED */ /* EDFLIB_FILE_ALREADY_OPENED */ /* EDFLIB_NUMBER_OF_SIGNALS_INVALID */ /* This function is required if you want to write a file */ int edf_set_samplefrequency(int handle, int edfsignal, int samplefrequency); /* Sets the samplefrequency of signal edfsignal. */ /* Returns 0 on success, otherwise -1 */ /* This function is required for every signal and can be called only after opening a */ /* file in writemode and before the first sample write action */ int edf_set_physical_maximum(int handle, int edfsignal, double phys_max); /* Sets the maximum physical value of signal edfsignal. (the value of the input of the ADC when the output equals the value of "digital maximum") */ /* Returns 0 on success, otherwise -1 */ /* This function is required for every signal and can be called only after opening a */ /* file in writemode and before the first sample write action */ int edf_set_physical_minimum(int handle, int edfsignal, double phys_min); /* Sets the minimum physical value of signal edfsignal. (the value of the input of the ADC when the output equals the value of "digital minimum") */ /* Usually this will be (-(phys_max)) */ /* Returns 0 on success, otherwise -1 */ /* This function is required for every signal and can be called only after opening a */ /* file in writemode and before the first sample write action */ int edf_set_digital_maximum(int handle, int edfsignal, int dig_max); /* Sets the maximum digital value of signal edfsignal. The maximum value is 32767 for EDF+ and 8388607 for BDF+ */ /* Usually it's the extreme output of the ADC */ /* Returns 0 on success, otherwise -1 */ /* This function is required for every signal and can be called only after opening a file in writemode */ /* and before the first sample write action */ int edf_set_digital_minimum(int handle, int edfsignal, int dig_min); /* Sets the minimum digital value of signal edfsignal. The minimum value is -32768 for EDF+ and -8388608 for BDF+ */ /* Usually it's the extreme output of the ADC */ /* Usually this will be (-(dig_max + 1)) */ /* Returns 0 on success, otherwise -1 */ /* This function is required for every signal and can be called only after opening a file in writemode */ /* and before the first sample write action */ int edf_set_label(int handle, int edfsignal, const char *label); /* Sets the label (name) of signal edfsignal. ("FP1", "SaO2", etc.) */ /* label is a pointer to a NULL-terminated ASCII-string containing the label (name) of the signal edfsignal */ /* Returns 0 on success, otherwise -1 */ /* This function is recommended for every signal when you want to write a file */ /* and can be called only after opening a file in writemode and before the first sample write action */ int edf_set_prefilter(int handle, int edfsignal, const char *prefilter); /* Sets the prefilter of signal edfsignal ("HP:0.1Hz", "LP:75Hz N:50Hz", etc.). */ /* prefilter is a pointer to a NULL-terminated ASCII-string containing the prefilter text of the signal edfsignal */ /* Returns 0 on success, otherwise -1 */ /* This function is optional and can be called only after opening a file in writemode and before */ /* the first sample write action */ int edf_set_transducer(int handle, int edfsignal, const char *transducer); /* Sets the transducer of signal edfsignal ("AgAgCl cup electrodes", etc.). */ /* transducer is a pointer to a NULL-terminated ASCII-string containing the transducer text of the signal edfsignal */ /* Returns 0 on success, otherwise -1 */ /* This function is optional and can be called only after opening a file in writemode and before */ /* the first sample write action */ int edf_set_physical_dimension(int handle, int edfsignal, const char *phys_dim); /* Sets the physical dimension of signal edfsignal. ("uV", "BPM", "mA", "Degr.", etc.) */ /* phys_dim is a pointer to a NULL-terminated ASCII-string containing the physical dimension of the signal edfsignal */ /* Returns 0 on success, otherwise -1 */ /* This function is recommanded for every signal when you want to write a file */ /* and can be called only after opening a file in writemode and before the first sample write action */ int edf_set_startdatetime(int handle, int startdate_year, int startdate_month, int startdate_day, int starttime_hour, int starttime_minute, int starttime_second); /* Sets the startdate and starttime. */ /* year: 1970 - 3000, month: 1 - 12, day: 1 - 31 */ /* hour: 0 - 23, minute: 0 - 59, second: 0 - 59 */ /* If not called, the library will use the system date and time at runtime */ /* Returns 0 on success, otherwise -1 */ /* This function is optional and can be called only after opening a file in writemode */ /* and before the first sample write action */ int edf_set_patientname(int handle, const char *patientname); /* Sets the patientname. patientname is a pointer to a null-terminated ASCII-string. */ /* Returns 0 on success, otherwise -1 */ /* This function is optional and can be called only after opening a file in writemode */ /* and before the first sample write action */ int edf_set_patientcode(int handle, const char *patientcode); /* Sets the patientcode. patientcode is a pointer to a null-terminated ASCII-string. */ /* Returns 0 on success, otherwise -1 */ /* This function is optional and can be called only after opening a file in writemode */ /* and before the first sample write action */ int edf_set_gender(int handle, int gender); /* Sets the gender. 1 is male, 0 is female. */ /* Returns 0 on success, otherwise -1 */ /* This function is optional and can be called only after opening a file in writemode */ /* and before the first sample write action */ int edf_set_birthdate(int handle, int birthdate_year, int birthdate_month, int birthdate_day); /* Sets the birthdate. */ /* year: 1800 - 3000, month: 1 - 12, day: 1 - 31 */ /* This function is optional */ /* Returns 0 on success, otherwise -1 */ /* This function is optional and can be called only after opening a file in writemode */ /* and before the first sample write action */ int edf_set_patient_additional(int handle, const char *patient_additional); /* Sets the additional patientinfo. patient_additional is a pointer to a null-terminated ASCII-string. */ /* Returns 0 on success, otherwise -1 */ /* This function is optional and can be called only after opening a file in writemode */ /* and before the first sample write action */ int edf_set_admincode(int handle, const char *admincode); /* Sets the admincode. admincode is a pointer to a null-terminated ASCII-string. */ /* Returns 0 on success, otherwise -1 */ /* This function is optional and can be called only after opening a file in writemode */ /* and before the first sample write action */ int edf_set_technician(int handle, const char *technician); /* Sets the technicians name. technician is a pointer to a null-terminated ASCII-string. */ /* Returns 0 on success, otherwise -1 */ /* This function is optional and can be called only after opening a file in writemode */ /* and before the first sample write action */ int edf_set_equipment(int handle, const char *equipment); /* Sets the name of the equipment used during the aquisition. equipment is a pointer to a null-terminated ASCII-string. */ /* Returns 0 on success, otherwise -1 */ /* This function is optional and can be called only after opening a file in writemode */ /* and before the first sample write action */ int edf_set_recording_additional(int handle, const char *recording_additional); /* Sets the additional recordinginfo. recording_additional is a pointer to a null-terminated ASCII-string. */ /* Returns 0 on success, otherwise -1 */ /* This function is optional and can be called only after opening a file in writemode */ /* and before the first sample write action */ int edfwrite_physical_samples(int handle, double *buf); /* Writes n physical samples (uV, mA, Ohm) from *buf belonging to one signal */ /* where n is the samplefrequency of that signal. */ /* The physical samples will be converted to digital samples using the */ /* values of physical maximum, physical minimum, digital maximum and digital minimum */ /* The number of samples written is equal to the samplefrequency of the signal */ /* Size of buf should be equal to or bigger than sizeof(double[samplefrequency]) */ /* Call this function for every signal in the file. The order is important! */ /* When there are 4 signals in the file, the order of calling this function */ /* must be: signal 0, signal 1, signal 2, signal 3, signal 0, signal 1, signal 2, etc. */ /* Returns 0 on success, otherwise -1 */ int edf_blockwrite_physical_samples(int handle, double *buf); /* Writes physical samples (uV, mA, Ohm) from *buf */ /* buf must be filled with samples from all signals, starting with n samples of signal 0, n samples of signal 1, n samples of signal 2, etc. */ /* where n is the samplefrequency of that signal. */ /* buf must be filled with samples from all signals, starting with signal 0, 1, 2, etc. */ /* one block equals one second */ /* The physical samples will be converted to digital samples using the */ /* values of physical maximum, physical minimum, digital maximum and digital minimum */ /* The number of samples written is equal to the sum of the samplefrequencies of all signals */ /* Size of buf should be equal to or bigger than sizeof(double) multiplied by the sum of the samplefrequencies of all signals */ /* Returns 0 on success, otherwise -1 */ int edfwrite_digital_short_samples(int handle, short *buf); /* Writes n "raw" digital samples from *buf belonging to one signal */ /* where n is the samplefrequency of that signal. */ /* The samples will be written to the file without any conversion. */ /* Because the size of a short is 16-bit, do not use this function with BDF (24-bit) */ /* The number of samples written is equal to the samplefrequency of the signal */ /* Size of buf should be equal to or bigger than sizeof(short[samplefrequency]) */ /* Call this function for every signal in the file. The order is important! */ /* When there are 4 signals in the file, the order of calling this function */ /* must be: signal 0, signal 1, signal 2, signal 3, signal 0, signal 1, signal 2, etc. */ /* Returns 0 on success, otherwise -1 */ int edfwrite_digital_samples(int handle, int *buf); /* Writes n "raw" digital samples from *buf belonging to one signal */ /* where n is the samplefrequency of that signal. */ /* The 16 (or 24 in case of BDF) least significant bits of the sample will be written to the */ /* file without any conversion. */ /* The number of samples written is equal to the samplefrequency of the signal */ /* Size of buf should be equal to or bigger than sizeof(int[samplefrequency]) */ /* Call this function for every signal in the file. The order is important! */ /* When there are 4 signals in the file, the order of calling this function */ /* must be: signal 0, signal 1, signal 2, signal 3, signal 0, signal 1, signal 2, etc. */ /* Returns 0 on success, otherwise -1 */ int edf_blockwrite_digital_3byte_samples(int handle, void *buf); /* Writes "raw" digital samples from *buf. */ /* buf must be filled with samples from all signals, starting with n samples of signal 0, n samples of signal 1, n samples of signal 2, etc. */ /* where n is the samplefrequency of that signal. */ /* One block equals one second. One sample equals 3 bytes, order is little endian (least significant byte first) */ /* Encoding is second's complement, most significant bit of most significant byte is the sign-bit */ /* The samples will be written to the file without any conversion. */ /* Because the size of a 3-byte sample is 24-bit, this function can only be used when writing a BDF file */ /* The number of samples written is equal to the sum of the samplefrequencies of all signals. */ /* Size of buf should be equal to or bigger than: the sum of the samplefrequencies of all signals x 3 bytes */ /* Returns 0 on success, otherwise -1 */ int edf_blockwrite_digital_short_samples(int handle, short *buf); /* Writes "raw" digital samples from *buf. */ /* buf must be filled with samples from all signals, starting with n samples of signal 0, n samples of signal 1, n samples of signal 2, etc. */ /* where n is the samplefrequency of that signal. */ /* One block equals one second. */ /* The samples will be written to the file without any conversion. */ /* Because the size of a short is 16-bit, do not use this function with BDF (24-bit) */ /* The number of samples written is equal to the sum of the samplefrequencies of all signals. */ /* Size of buf should be equal to or bigger than sizeof(short) multiplied by the sum of the samplefrequencies of all signals */ /* Returns 0 on success, otherwise -1 */ int edf_blockwrite_digital_samples(int handle, int *buf); /* Writes "raw" digital samples from *buf. */ /* buf must be filled with samples from all signals, starting with n samples of signal 0, n samples of signal 1, n samples of signal 2, etc. */ /* where n is the samplefrequency of that signal. */ /* One block equals one second. */ /* The 16 (or 24 in case of BDF) least significant bits of the sample will be written to the */ /* file without any conversion. */ /* The number of samples written is equal to the sum of the samplefrequencies of all signals. */ /* Size of buf should be equal to or bigger than sizeof(int) multiplied by the sum of the samplefrequencies of all signals */ /* Returns 0 on success, otherwise -1 */ int edfwrite_annotation_utf8(int handle, long long onset, long long duration, const char *description); /* writes an annotation/event to the file */ /* onset is relative to the starttime and startdate of the file */ /* onset and duration are in units of 100 microSeconds! resolution is 0.0001 second! */ /* for example: 34.071 seconds must be written as 340710 */ /* if duration is unknown or not applicable: set a negative number (-1) */ /* description is a null-terminated UTF8-string containing the text that describes the event */ /* This function is optional and can be called only after opening a file in writemode */ /* and before closing the file */ int edfwrite_annotation_latin1(int handle, long long onset, long long duration, const char *description); /* writes an annotation/event to the file */ /* onset is relative to the starttime and startdate of the file */ /* onset and duration are in units of 100 microSeconds! resolution is 0.0001 second! */ /* for example: 34.071 seconds must be written as 340710 */ /* if duration is unknown or not applicable: set a negative number (-1) */ /* description is a null-terminated Latin1-string containing the text that describes the event */ /* This function is optional and can be called only after opening a file in writemode */ /* and before closing the file */ int edf_set_datarecord_duration(int handle, int duration); /* Sets the datarecord duration. The default value is 1 second. */ /* ATTENTION: the argument "duration" is expressed in units of 10 microSeconds! */ /* So, if you want to set the datarecord duration to 0.1 second, you must give */ /* the argument "duration" a value of "10000". */ /* This function is optional, normally you don't need to change the default value. */ /* The datarecord duration must be in the range 0.001 to 60 seconds. */ /* Returns 0 on success, otherwise -1 */ /* This function is NOT REQUIRED but can be called after opening a */ /* file in writemode and before the first sample write action. */ /* This function can be used when you want to use a samplerate */ /* which is not an integer. For example, if you want to use a samplerate of 0.5 Hz, */ /* set the samplefrequency to 5 Hz and the datarecord duration to 10 seconds, */ /* or set the samplefrequency to 1 Hz and the datarecord duration to 2 seconds. */ /* Do not use this function, except when absolutely necessary! */ int edf_set_number_of_annotation_signals(int handle, int annot_signals); /* Sets the number of annotation signals. The default value is 1 */ /* This function is optional and can be called only after opening a file in writemode */ /* and before the first sample write action */ /* Normally you don't need to change the default value. Only when the number of annotations */ /* you want to write is more than the number of seconds of the duration of the recording, you can use */ /* this function to increase the storage space for annotations */ /* Minimum is 1, maximum is 64 */ #ifdef __cplusplus } /* extern "C" */ #endif #endif edfbrowser_157_source/PaxHeaders.7921/ascii2edf.h0000644000000000000000000000013212646460742016670 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/ascii2edf.h0000644000175000001440000000635112646460742017236 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_ASCII2EDFFORM_H #define UI_ASCII2EDFFORM_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "xml.h" #include "utils.h" #define ASCII_MAX_EDF_SIGNALS 512 #define ASCII_MAX_LINE_LEN 2048 class UI_ASCII2EDFapp : public QObject { Q_OBJECT public: UI_ASCII2EDFapp(char *recent_dir=NULL, char *save_dir=NULL); private: QDialog *ascii2edfDialog; QLabel *SeparatorLabel, *NumsignalsLabel, *DatastartLabel, *SamplefreqLabel, *PatientnameLabel, *RecordingLabel, *DatetimeLabel, *SignalsLabel, *autoPhysicalMaximumLabel; QRadioButton *edfButton, *bdfButton; QGroupBox *groupbox1; QVBoxLayout *vbox1; QLineEdit *SeparatorLineEdit, *PatientnameLineEdit, *RecordingLineEdit; QSpinBox *NumcolumnsSpinbox, *DatastartSpinbox; QDoubleSpinBox *SamplefreqSpinbox; QDateTimeEdit *StartDatetimeedit; QCheckBox *autoPhysicalMaximumCheckbox; QTableWidget *SignalsTablewidget; QPushButton *GoButton, *CloseButton, *SaveButton, *LoadButton; char separator, *recent_opendir, *recent_savedir; int edfsignals, startline, columns, column_enabled[ASCII_MAX_EDF_SIGNALS], autoPhysicalMaximum, edf_format; double samplefrequency, datrecduration, sensitivity[ASCII_MAX_EDF_SIGNALS], value[ASCII_MAX_EDF_SIGNALS], physmax[ASCII_MAX_EDF_SIGNALS]; int check_input(void); private slots: void numofcolumnschanged(int); void gobuttonpressed(); void savebuttonpressed(); void loadbuttonpressed(); void autoPhysicalMaximumCheckboxChanged(int); }; #endif edfbrowser_157_source/PaxHeaders.7921/videoplayer.cpp0000644000000000000000000000013212646460742017715 xustar0030 mtime=1452958178.249246726 30 atime=1452958178.249246726 30 ctime=1452958178.249246726 edfbrowser_157_source/videoplayer.cpp0000644000175000001440000002674312646460742020272 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "mainwindow.h" // #define DEBUG_VIDEOPLAYER #ifdef DEBUG_VIDEOPLAYER FILE *debug_vpr; #endif // Next parts of code are tested with VLC media player 2.1.2 and later with 2.1.5 Rincewind on Linux. // On windows it's disabled because the console interface of VLC on windows is broken. // Once they (videolan.org) has fixed this, we can test it and hopefully enable it on windows too. void UI_Mainwindow::start_stop_video() { if(video_player->status != VIDEO_STATUS_STOPPED) { stop_video_generic(); return; } if(playback_realtime_active) { return; } if(live_stream_active) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open a video during a live stream."); messagewindow.exec(); return; } if(video_player->status != VIDEO_STATUS_STOPPED) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There is already a video running."); messagewindow.exec(); return; } if(signalcomps < 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Put some signals on the screen first."); messagewindow.exec(); return; } if(annot_editor_active) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Close the annotation editor first."); messagewindow.exec(); return; } strcpy(videopath, QFileDialog::getOpenFileName(this, "Select video", QString::fromLocal8Bit(recent_opendir), "Video files (*.ogv *.OGV *.ogg *.OGG *.mkv *.MKV *.avi *.AVI" " *.mp4 *.MP4 *.mpeg *.MPEG *.mpg *.MPG *.wmv *.WMV)").toLocal8Bit().data()); if(!strcmp(videopath, "")) { return; } get_directory_from_path(recent_opendir, videopath, MAX_PATH_LENGTH); video_player->utc_starttime = parse_date_time_stamp(videopath); if(video_player->utc_starttime < 0LL) { QMessageBox messagewindow(QMessageBox::Warning, "Warning", "Unable to get startdate and starttime from video filename.\n" " \nAssume video starttime equals EDF/BDF starttime?\n "); messagewindow.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); messagewindow.setDefaultButton(QMessageBox::Yes); if(messagewindow.exec() == QMessageBox::Cancel) return; video_player->utc_starttime = edfheaderlist[sel_viewtime]->utc_starttime; } video_player->stop_det_counter = 0; video_player->fpos = 0; video_player->starttime_diff = (int)(edfheaderlist[sel_viewtime]->utc_starttime - video_player->utc_starttime); if((edfheaderlist[sel_viewtime]->utc_starttime + edfheaderlist[sel_viewtime]->recording_len_sec) < video_player->utc_starttime) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The video registration and the EDF/BDF registration do not overlap (in time)!"); messagewindow.exec(); return; } if((video_player->utc_starttime + 259200LL) < edfheaderlist[sel_viewtime]->utc_starttime) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The video registration and the EDF/BDF registration do not overlap (in time)!"); messagewindow.exec(); return; } video_process = new QProcess(this); #ifdef Q_OS_WIN32 QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert("PATH", env.value("PATH") + ";C:\\Program Files\\VideoLAN\\VLC"); video_process->setProcessEnvironment(env); #endif connect(video_process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(video_process_error(QProcess::ProcessError))); QStringList arguments; arguments << "--video-on-top" << "-I" << "rc"; video_process->start("vlc", arguments); if(video_process->waitForStarted(5000) == false) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Unable to start VLC mediaplayer.\n" "Check your installation of VLC.\n" "Also, check if VLC is present in the PATH evironment variable."); messagewindow.exec(); return; } #ifdef DEBUG_VIDEOPLAYER debug_vpr = fopen("debug_vpr.txt", "wb"); #endif video_player->status = VIDEO_STATUS_STARTUP_1; video_player->poll_timer = 100; video_player->cntdwn_timer = 5000; video_poll_timer->start(video_player->poll_timer); video_act->setText("Stop video"); } void UI_Mainwindow::video_poll_timer_func() { int i, err, len, vpos=0; char buf[4096]; if(video_player->status == VIDEO_STATUS_STOPPED) return; if(video_player->status != VIDEO_STATUS_PAUSED) { video_player->cntdwn_timer -= video_player->poll_timer; } if(video_player->cntdwn_timer <= 0) { stop_video_generic(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "Videoplayer: time-out."); messagewindow.exec(); return; } len = mpr_read(buf, 4095); if(len < 1) { video_poll_timer->start(video_player->poll_timer); return; } if(video_player->status == VIDEO_STATUS_STARTUP_1) { if(!strncmp(buf, "Command Line Interface initialized.", 35)) { video_player->status = VIDEO_STATUS_STARTUP_2; } } if(video_player->status < VIDEO_STATUS_PLAYING) { if(!strncmp(buf, "> ", 2)) { if(video_player->status == VIDEO_STATUS_STARTUP_2) { mpr_write("clear\n"); video_process->waitForBytesWritten(1000); video_player->status = VIDEO_STATUS_STARTUP_3; video_player->cntdwn_timer = 5000; } else if(video_player->status == VIDEO_STATUS_STARTUP_3) { strcpy(buf, "add "); strcat(buf, videopath); strcat(buf, "\n"); mpr_write(buf); video_process->waitForBytesWritten(1000); video_player->status = VIDEO_STATUS_STARTUP_4; video_player->cntdwn_timer = 5000; } else if(video_player->status == VIDEO_STATUS_STARTUP_4) { mpr_write("volume 255\n"); video_process->waitForBytesWritten(1000); video_player->status = VIDEO_STATUS_PLAYING; video_pause_act->setText("Pause"); video_pause_act->setToolTip("Pause video"); video_player->cntdwn_timer = 5000; } } video_poll_timer->start(video_player->poll_timer); return; } if(video_player->status == VIDEO_STATUS_PLAYING) { if(!strncmp(buf, "> ", 2)) { if((len > 4) && (buf[len-1] == '\n')) { err = 0; for(i=2; i<(len-1); i++) { if((buf[i] < '0') || (buf[i] > '9')) err = 1; break; } if(!err) { vpos = atoi(buf + 2); if(video_player->fpos != vpos) { jump_to_time_millisec(video_player->utc_starttime - edfheaderlist[sel_viewtime]->utc_starttime + (vpos * 1000LL)); video_player->fpos = vpos; video_player->stop_det_counter = 0; } video_player->cntdwn_timer = 5000; } } else if(buf[2] == '\r') { video_player->stop_det_counter += video_player->poll_timer; if(video_player->stop_det_counter > 1500) { stop_video_generic(); QMessageBox messagewindow(QMessageBox::NoIcon, "Stopped", " \nVideo has reached the end \n"); messagewindow.exec(); return; } } } mpr_write("get_time\n"); video_process->waitForBytesWritten(1000); } if(!strncmp(buf, "( state stopped )", 17)) { stop_video_generic(); return; } video_poll_timer->start(video_player->poll_timer); } void UI_Mainwindow::video_player_seek(int sec) { char str[512]; if((video_player->status != VIDEO_STATUS_PLAYING) && (video_player->status != VIDEO_STATUS_PAUSED)) return; sec += video_player->starttime_diff; if(sec < 0) sec = 0; sprintf(str, "seek %i\n", sec); mpr_write(str); video_process->waitForBytesWritten(1000); video_player->cntdwn_timer = 5000; } void UI_Mainwindow::video_player_toggle_pause() { if(video_player->status == VIDEO_STATUS_STOPPED) { start_stop_video(); return; } if((video_player->status != VIDEO_STATUS_PLAYING) && (video_player->status != VIDEO_STATUS_PAUSED)) { return; } mpr_write("pause\n"); if(video_player->status == VIDEO_STATUS_PLAYING) { video_player->status = VIDEO_STATUS_PAUSED; video_pause_act->setText("Play"); video_pause_act->setToolTip("Play video"); video_player->cntdwn_timer = 5000; } else { video_player->status = VIDEO_STATUS_PLAYING; video_pause_act->setText("Pause"); video_pause_act->setToolTip("Pause video"); } } void UI_Mainwindow::stop_video_generic() { video_poll_timer->stop(); if(video_player->status == VIDEO_STATUS_STOPPED) return; video_player->status = VIDEO_STATUS_STOPPED; disconnect(video_process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(video_process_error(QProcess::ProcessError))); mpr_write("quit\n"); video_process->waitForFinished(1000); video_process->kill(); delete video_process; video_act->setText("Start video"); video_pause_act->setText("Play"); #ifdef DEBUG_VIDEOPLAYER fclose(debug_vpr); #endif } void UI_Mainwindow::video_process_error(QProcess::ProcessError err) { char str[1024]; if(video_player->status == VIDEO_STATUS_STOPPED) return; stop_video_generic(); strcpy(str, "The process that runs the mediaplayer reported an error:\n"); if(err == QProcess::FailedToStart) { strcat(str, "\nFailed to start."); } if(err == QProcess::Crashed) { strcat(str, "\nCrashed."); } if(err == QProcess::Timedout) { strcat(str, "\nTimed out."); } if(err == QProcess::WriteError) { strcat(str, "\nWrite error."); } if(err == QProcess::ReadError) { strcat(str, "\nRead error."); } if(err == QProcess::UnknownError) { strcat(str, "\nUnknown error."); } QMessageBox messagewindow(QMessageBox::Critical, "Error", str); messagewindow.exec(); } inline void UI_Mainwindow::mpr_write(const char *cmd_str) { #ifdef DEBUG_VIDEOPLAYER fprintf(debug_vpr, "edfbr: %s", cmd_str); #endif video_process->write(cmd_str); } inline int UI_Mainwindow::mpr_read(char *buf, int sz) { #ifdef DEBUG_VIDEOPLAYER int n; n = video_process->readLine(buf, sz); if(n > 0) { fprintf(debug_vpr, "vlc: %s ", buf); for(int i=0; ireadLine(buf, sz); #endif } edfbrowser_157_source/PaxHeaders.7921/about_dialog.h0000644000000000000000000000013212646460742017470 xustar0030 mtime=1452958178.237246767 30 atime=1452958178.237246767 30 ctime=1452958178.237246767 edfbrowser_157_source/about_dialog.h0000644000175000001440000000304012646460742020026 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef ABOUT_FORM1_H #define ABOUT_FORM1_H #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" class UI_Aboutwindow : public QObject { Q_OBJECT public: UI_Aboutwindow(UI_Mainwindow *); private: QDialog *AboutDialog; QPushButton *pushButton1; QTextEdit *textedit1; QHBoxLayout *hlayout1; QVBoxLayout *vlayout1; }; #endif // ABOUT_FORM1_H edfbrowser_157_source/PaxHeaders.7921/adjustfiltersettings.h0000644000000000000000000000013212646460742021320 xustar0030 mtime=1452958178.237246767 30 atime=1452958178.237246767 30 ctime=1452958178.237246767 edfbrowser_157_source/adjustfiltersettings.h0000644000175000001440000000460712646460742021670 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef ADJUSTFILTERSETTINGS_H #define ADJUSTFILTERSETTINGS_H #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "viewcurve.h" #include "ravg_filter.h" #include "utils.h" #include "third_party/fidlib/fidlib.h" class UI_Mainwindow; class ViewCurve; class AdjustFilterSettings : public QObject { Q_OBJECT public: AdjustFilterSettings(struct signalcompblock *, QWidget *); private: int filter_nr, filter_cnt, type, model, order, size, brand[MAXFILTERS]; double frequency1, frequency2, ripple; struct signalcompblock * signalcomp; UI_Mainwindow *mainwindow; ViewCurve *maincurve; QDialog *filtersettings_dialog; QLabel *label[5]; QComboBox *filterbox, *stepsizebox; QSpinBox *orderbox; QDoubleSpinBox *freq1box, *freq2box; QPushButton *CloseButton, *RemoveButton; void update_filter(void); void loadFilterSettings(void); private slots: void freqbox1valuechanged(double); void freqbox2valuechanged(double); void orderboxvaluechanged(int); void stepsizeboxchanged(int); void filterboxchanged(int); void removeButtonClicked(); }; #endif // ADJUSTFILTERSETTINGS_H edfbrowser_157_source/PaxHeaders.7921/date_time_stamp_parser.h0000644000000000000000000000013212646460742021552 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/date_time_stamp_parser.h0000644000175000001440000000230112646460742022107 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef DATE_TIME_STAMP_PARSER_INCLUDED #define DATE_TIME_STAMP_PARSER_INCLUDED #ifdef __cplusplus extern "C" { #endif long long parse_date_time_stamp(const char *); #ifdef __cplusplus } /* extern "C" */ #endif #endif edfbrowser_157_source/PaxHeaders.7921/save_annots.h0000644000000000000000000000013212646460742017357 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/save_annots.h0000644000175000001440000000260512646460742017723 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef SAVE_ANNOTATIONS_H #define SAVE_ANNOTATIONS_H #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "utils.h" #include "edf_annot_list.h" int save_annotations(UI_Mainwindow *, FILE *, struct edfhdrblock *, struct annotationblock *); #endif edfbrowser_157_source/PaxHeaders.7921/averager_curve_wnd.cpp0000644000000000000000000000013212646460742021242 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/averager_curve_wnd.cpp0000644000175000001440000004153412646460742021612 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "averager_curve_wnd.h" UI_AverageCurveWindow::UI_AverageCurveWindow(struct signalcompblock *signal_comp, QWidget *w_parent, int number, double *abuf, double maxvalue, double minvalue, long long apagetime, long long samples_on_screen, int acnt, int trigger_position, char *annotation, double avg__period) { char str[1024]; averager_curve_dialog_is_destroyed = 0; class_is_deleted = 0; mainwindow = (UI_Mainwindow *)w_parent; signalcomp = signal_comp; averagecurvedialognumber = number; pagetime = apagetime; pagetime /= TIME_DIMENSION; avgbuf = abuf; avg_max_value = maxvalue; avg_min_value = minvalue; avg_samples_on_screen = samples_on_screen; avg_cnt = acnt; avg_trigger_position_ratio = trigger_position; avg_period = avg__period; strcpy(avg_annotation, annotation); flywheel_value = 1000; averager_curve_dialog = new QDialog; averager_curve_dialog->setAttribute(Qt::WA_DeleteOnClose, true); averager_curve_dialog->setMinimumSize(650, 480); averager_curve_dialog->setSizeGripEnabled(true); averager_curve_dialog->setModal(false); averager_curve_dialog->setWindowFlags(Qt::Window | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); averager_curve_dialog->setWindowIcon(QIcon(":/images/edf.png")); strcpy(str, "Averaging "); strcat(str, signalcomp->signallabel); averager_curve_dialog->setWindowTitle(str); curve1 = new SignalCurve; curve1->setSignalColor(Qt::green); curve1->setBackgroundColor(Qt::black); curve1->setRasterColor(Qt::gray); curve1->setCrosshairColor(Qt::red); curve1->setTraceWidth(0); curve1->setH_label("sec"); curve1->setLowerLabel("Time"); curve1->setV_label(signalcomp->physdimension); curve1->setDashBoardEnabled(false); curve1->setMarker1Color(Qt::yellow); curve1->create_button("to EDF/BDF"); sprintf(str, "Averaging %i triggers \"%s\"", avg_cnt, avg_annotation); curve1->setUpperLabel1(str); flywheel1 = new UI_Flywheel; flywheel1->setMinimumSize(20, 85); amplitudeSlider = new QSlider; amplitudeSlider->setOrientation(Qt::Vertical); amplitudeSlider->setMinimum(1); amplitudeSlider->setMaximum(2000); amplitudeSlider->setValue(1100); amplitudeSlider->setInvertedAppearance(true); amplitudeSlider->setMinimumSize(15, 280); amplitudeLabel = new QLabel; amplitudeLabel->setText("Amplitude"); amplitudeLabel->setMinimumSize(100, 15); amplitudeLabel->setAlignment(Qt::AlignHCenter); inversionCheckBox = new QCheckBox("Invert"); inversionCheckBox->setMinimumSize(70, 25); inversionCheckBox->setTristate(false); if(mainwindow->average_upsidedown == 1) { inversionCheckBox->setCheckState(Qt::Checked); } else { inversionCheckBox->setCheckState(Qt::Unchecked); } BWCheckBox = new QCheckBox("B/W"); BWCheckBox->setMinimumSize(70, 25); BWCheckBox->setTristate(false); if(mainwindow->average_bw == 1) { BWCheckBox->setCheckState(Qt::Checked); } else { BWCheckBox->setCheckState(Qt::Unchecked); } vlayout3 = new QVBoxLayout; vlayout3->addStretch(100); vlayout3->addWidget(flywheel1, 100); vlayout3->addStretch(100); hlayout4 = new QHBoxLayout; hlayout4->addStretch(100); hlayout4->addLayout(vlayout3, 100); hlayout4->addStretch(100); hlayout4->addWidget(amplitudeSlider, 300); vlayout2 = new QVBoxLayout; vlayout2->setSpacing(20); vlayout2->addStretch(100); vlayout2->addWidget(amplitudeLabel, 0, Qt::AlignHCenter); vlayout2->addLayout(hlayout4, 200); vlayout2->addWidget(inversionCheckBox); vlayout2->addWidget(BWCheckBox); spanSlider = new QSlider; spanSlider->setOrientation(Qt::Horizontal); spanSlider->setMinimum(10); spanSlider->setMaximum(1000); spanSlider->setValue(1000); spanSlider->setMinimumSize(500, 15); spanLabel = new QLabel; spanLabel->setText("Span"); spanLabel->setMinimumSize(110, 15); spanLabel->setAlignment(Qt::AlignHCenter); centerSlider = new QSlider; centerSlider->setOrientation(Qt::Horizontal); centerSlider->setMinimum(0); centerSlider->setMaximum(1000); centerSlider->setValue(250); centerSlider->setMinimumSize(500, 15); centerLabel = new QLabel; centerLabel->setText("Center"); centerLabel->setMinimumSize(110, 15); centerLabel->setAlignment(Qt::AlignHCenter); hlayout1 = new QHBoxLayout; hlayout1->setSpacing(20); hlayout1->addLayout(vlayout2); hlayout1->addWidget(curve1, 100); hlayout2 = new QHBoxLayout; hlayout2->setSpacing(20); hlayout2->addWidget(spanLabel); hlayout2->addWidget(spanSlider); hlayout2->addStretch(100); hlayout3 = new QHBoxLayout; hlayout3->setSpacing(20); hlayout3->addWidget(centerLabel); hlayout3->addWidget(centerSlider); hlayout3->addStretch(100); vlayout1 = new QVBoxLayout; vlayout1->setSpacing(20); vlayout1->addLayout(hlayout1); vlayout1->addLayout(hlayout2); vlayout1->addLayout(hlayout3); averager_curve_dialog->setLayout(vlayout1); QObject::connect(amplitudeSlider, SIGNAL(valueChanged(int)), this, SLOT(sliderMoved(int))); QObject::connect(inversionCheckBox, SIGNAL(stateChanged(int)), this, SLOT(sliderMoved(int))); QObject::connect(BWCheckBox, SIGNAL(stateChanged(int)), this, SLOT(sliderMoved(int))); QObject::connect(spanSlider, SIGNAL(valueChanged(int)), this, SLOT(sliderMoved(int))); QObject::connect(centerSlider, SIGNAL(valueChanged(int)), this, SLOT(sliderMoved(int))); QObject::connect(averager_curve_dialog, SIGNAL(destroyed(QObject *)), this, SLOT(averager_curve_dialogDestroyed(QObject *))); QObject::connect(curve1, SIGNAL(extra_button_clicked()), this, SLOT(export_edf())); QObject::connect(flywheel1, SIGNAL(dialMoved(int)), this, SLOT(update_flywheel(int))); sliderMoved(0); averager_curve_dialog->show(); } void UI_AverageCurveWindow::export_edf(void) { int i, j, k, p, type, edf_hdl, smp_per_record, datarecords, smpls_left; char path[MAX_PATH_LENGTH], str[512]; double *buf, frequency, frequency2; smp_per_record = signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record; datarecords = avg_samples_on_screen / smp_per_record; smpls_left = avg_samples_on_screen % smp_per_record; path[0] = 0; if(mainwindow->recent_savedir[0]!=0) { strcpy(path, mainwindow->recent_savedir); strcat(path, "/"); } get_filename_from_path(path + strlen(path), signalcomp->edfhdr->filename, 512); remove_extension_from_filename(path); sprintf(path + strlen(path), " averaging %s %i triggers [%s]", signalcomp->signallabel, avg_cnt, avg_annotation); if(signalcomp->edfhdr->edf) { strcat(path, ".edf"); strcpy(path, QFileDialog::getSaveFileName(0, "Save as EDF", QString::fromLocal8Bit(path), "EDF files (*.edf *.EDF)").toLocal8Bit().data()); } else { strcat(path, ".bdf"); strcpy(path, QFileDialog::getSaveFileName(0, "Save as BDF", QString::fromLocal8Bit(path), "BDF files (*.bdf *.BDF)").toLocal8Bit().data()); } if(!strcmp(path, "")) { return; } get_directory_from_path(mainwindow->recent_savedir, path, MAX_PATH_LENGTH); if(signalcomp->edfhdr->edf) { edf_hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_EDFPLUS, 1); } else { edf_hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_BDFPLUS, 1); } if(edf_hdl < 0) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open output file for writing."); messagewindow.exec(); return; } edf_set_samplefrequency(edf_hdl, 0, smp_per_record); if(edf_set_datarecord_duration(edf_hdl, signalcomp->edfhdr->long_data_record_duration / 100LL)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Datarecordduration out of range."); messagewindow.exec(); return; } if(signalcomp->edfhdr->edf) { edf_set_digital_maximum(edf_hdl, 0, 32767); edf_set_digital_minimum(edf_hdl, 0, -32768); } else { edf_set_digital_maximum(edf_hdl, 0, 8388607); edf_set_digital_minimum(edf_hdl, 0, -8388608); } edf_set_physical_maximum(edf_hdl, 0, avg_max_value); edf_set_physical_minimum(edf_hdl, 0, avg_min_value); edf_set_label(edf_hdl, 0, signalcomp->signallabel); edf_set_physical_dimension(edf_hdl, 0, signalcomp->physdimension); p = 0; for(j=0; jfidfilter_cnt; j++) { type = signalcomp->fidfilter_type[j]; frequency = signalcomp->fidfilter_freq[j]; frequency2 = signalcomp->fidfilter_freq2[j]; if(type == 0) { p += sprintf(str + p, "HP:%f", frequency); } if(type == 1) { p += sprintf(str + p, "LP:%f", frequency); } if(type == 2) { p += sprintf(str + p, "N:%f", frequency); } if(type == 3) { p += sprintf(str + p, "BP:%f", frequency); } if(type == 4) { p += sprintf(str + p, "BS:%f", frequency); } for(k=(p-1); k>0; k--) { if(str[k]!='0') break; } if(str[k]=='.') str[k] = 0; else str[k+1] = 0; p = strlen(str); if((type == 3) || (type == 4)) { p += sprintf(str + p, "-%f", frequency2); for(k=(p-1); k>0; k--) { if(str[k]!='0') break; } if(str[k]=='.') str[k] = 0; else str[k+1] = 0; } strcat(str, "Hz "); p = strlen(str); if(p>80) break; } for(j=0; jravg_filter_cnt; j++) { if(signalcomp->ravg_filter_type[j] == 0) { p += sprintf(str + p, "HP:%iSmpls ", signalcomp->ravg_filter[j]->size); } if(signalcomp->ravg_filter_type[j] == 1) { p += sprintf(str + p, "LP:%iSmpls ", signalcomp->ravg_filter[j]->size); } p = strlen(str); if(p>80) break; } strcat(str, signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].prefilter); edf_set_prefilter(edf_hdl, 0, str); edf_set_transducer(edf_hdl, 0, signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].transducer); if((signalcomp->edfhdr->edfplus) || (signalcomp->edfhdr->bdfplus)) { edf_set_patientname(edf_hdl, signalcomp->edfhdr->plus_patient_name); sprintf(str, "%i triggers \"%s\" averaged. %s", avg_cnt, avg_annotation, signalcomp->edfhdr->plus_recording_additional); edf_set_recording_additional(edf_hdl, str); edf_set_patientcode(edf_hdl, signalcomp->edfhdr->plus_patientcode); if(signalcomp->edfhdr->plus_gender[0] == 'M') { edf_set_gender(edf_hdl, 1); } if(signalcomp->edfhdr->plus_gender[0] == 'F') { edf_set_gender(edf_hdl, 0); } edf_set_patient_additional(edf_hdl, signalcomp->edfhdr->plus_patient_additional); edf_set_admincode(edf_hdl, signalcomp->edfhdr->plus_admincode); edf_set_technician(edf_hdl, signalcomp->edfhdr->plus_technician); edf_set_equipment(edf_hdl, signalcomp->edfhdr->plus_equipment); } else { edf_set_patientname(edf_hdl, signalcomp->edfhdr->patient); sprintf(str, "%i triggers \"%s\" averaged. %s", avg_cnt, avg_annotation, signalcomp->edfhdr->recording); edf_set_recording_additional(edf_hdl, str); } for(i=0; ivalue() * steps / 1000; startstep = centerSlider->value() * (steps - spanstep) / 1000; stopstep = startstep + spanstep; avg_mid_value = (avg_max_value + avg_min_value) / 2.0; avg_peak_value = (avg_max_value - avg_min_value) / 2.0; avg_peak_value = (avg_peak_value * (double)amplitudeSlider->value() / 1000.0) * ((double)flywheel_value / 1000.0); dtmp1 = avg_mid_value + avg_peak_value; dtmp2 = avg_mid_value - avg_peak_value; if(inversionCheckBox->isChecked() == true) { curve1->setUpsidedownEnabled(true); mainwindow->average_upsidedown = 1; } else { curve1->setUpsidedownEnabled(false); mainwindow->average_upsidedown = 0; } if(BWCheckBox->isChecked() == true) { curve1->setSignalColor(Qt::black); curve1->setBackgroundColor(Qt::white); curve1->setRasterColor(Qt::black); curve1->setMarker1Color(Qt::black); curve1->setBorderColor(Qt::white); curve1->setTextColor(Qt::black); curve1->setCrosshairColor(Qt::black); mainwindow->average_bw = 1; } else { curve1->setSignalColor(Qt::green); curve1->setBackgroundColor(Qt::black); curve1->setRasterColor(Qt::gray); curve1->setMarker1Color(Qt::yellow); curve1->setBorderColor(Qt::lightGray); curve1->setTextColor(Qt::black); curve1->setCrosshairColor(Qt::red); mainwindow->average_bw = 0; } curve1->drawCurve(avgbuf + startstep, stopstep - startstep, dtmp1, dtmp2); max_sec = pagetime * stopstep / steps - (pagetime * (1.0 / avg_trigger_position_ratio)); precision = 0; if(max_sec < 100.0) { precision = 1; } if(max_sec < 10.0) { precision = 2; } if(max_sec < 1.0) { precision = 3; } if(max_sec < 0.1) { precision = 4; } start_sec = pagetime * startstep / steps - (pagetime * (1.0 / avg_trigger_position_ratio)); curve1->setH_RulerValues(start_sec, max_sec); centerLabel->setText(QString::number(start_sec + ((max_sec - start_sec) / 2.0), 'f', precision).append(" sec").prepend("Center ")); spanLabel->setText(QString::number(max_sec - start_sec, 'f', precision).append(" sec").prepend("Span ")); if(avg_trigger_position_ratio > 0) { markerstep = steps / avg_trigger_position_ratio; if((markerstep > startstep) && (markerstep < stopstep)) { curve1->setMarker1Enabled(true); curve1->setMarker1Position((((double)steps / (double)avg_trigger_position_ratio) - (double)startstep) / (double)spanstep); } else { curve1->setMarker1Enabled(false); } } else { curve1->setMarker1Enabled(false); } } void UI_AverageCurveWindow::averager_curve_dialogDestroyed(QObject *) { averager_curve_dialog_is_destroyed = 1; mainwindow->averagecurvedialog[averagecurvedialognumber] = NULL; if(!class_is_deleted) { delete this; } } UI_AverageCurveWindow::~UI_AverageCurveWindow() { int i; class_is_deleted = 1; if(!averager_curve_dialog_is_destroyed) { averager_curve_dialog->close(); } if(avgbuf != NULL) { free(avgbuf); } mainwindow->averagecurvedialog[averagecurvedialognumber] = NULL; for(i=0; iavg_dialog[i] == (averagecurvedialognumber + 1)) { signalcomp->avg_dialog[i] = 0; } } } void UI_AverageCurveWindow::update_flywheel(int new_value) { flywheel_value += new_value; if(flywheel_value < 10) { flywheel_value = 10; } if(flywheel_value > 100000) { flywheel_value = 100000; } sliderMoved(0); } edfbrowser_157_source/PaxHeaders.7921/utc_date_time.h0000644000000000000000000000013212646460742017645 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/utc_date_time.h0000644000175000001440000000275512646460742020217 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UTC_DATE_TIME_INCLUDED #define UTC_DATE_TIME_INCLUDED #include #ifdef __cplusplus extern "C" { #endif struct date_time_struct{ int year; int month; int day; int hour; int minute; int second; char month_str[4]; }; void utc_to_date_time(long long, struct date_time_struct *); void date_time_to_utc(long long *, struct date_time_struct); #ifdef __cplusplus } /* extern "C" */ #endif #endif edfbrowser_157_source/PaxHeaders.7921/edfbrowser.pro0000644000000000000000000000013212646460742017552 xustar0030 mtime=1452958178.253246713 30 atime=1452958178.253246713 30 ctime=1452958178.253246713 edfbrowser_157_source/edfbrowser.pro0000644000175000001440000001514712646460742020123 0ustar00guvusers00000000000000 contains(QT_MAJOR_VERSION, 4) { LIST = 0 1 2 3 4 5 6 for(a, LIST):contains(QT_MINOR_VERSION, $$a):error("This project needs Qt4 version >= 4.7.1 or Qt5 version >= 5.5.1") contains(QT_MINOR_VERSION, 7) { LIST = 0 for(a, LIST):contains(QT_PATCH_VERSION, $$a):error("This project needs Qt4 version >= 4.7.1 or Qt5 version >= 5.5.1") } } contains(QT_MAJOR_VERSION, 5) { LIST = 0 1 2 3 4 for(a, LIST):contains(QT_MINOR_VERSION, $$a):error("This project needs Qt4 version >= 4.7.1 or Qt5 version >= 5.5.1") contains(QT_MINOR_VERSION, 5) { LIST = 0 for(a, LIST):contains(QT_PATCH_VERSION, $$a):error("This project needs Qt4 version >= 4.7.1 or Qt5 version >= 5.5.1") } } TEMPLATE = app TARGET = edfbrowser DEPENDPATH += . INCLUDEPATH += . CONFIG += qt CONFIG += warn_on CONFIG += release CONFIG += static CONFIG += largefile QT += network contains(QT_MAJOR_VERSION, 5) { QT += widgets QT += printsupport win32 { QTPLUGIN += windowsprintersupport } else:mac { QTPLUGIN += cocoaprintersupport } else { QTPLUGIN += cupsprintersupport } } OBJECTS_DIR = ./objects MOC_DIR = ./moc HEADERS += global.h HEADERS += mainwindow.h HEADERS += viewcurve.h HEADERS += check_edf_file.h HEADERS += show_edf_hdr.h HEADERS += signals_dialog.h HEADERS += signal_chooser.h HEADERS += ascii_export.h HEADERS += edf_compat.h HEADERS += colordialog.h HEADERS += filter.h HEADERS += filter_dialog.h HEADERS += jump_dialog.h HEADERS += about_dialog.h HEADERS += edf_annotations.h HEADERS += annotations_dock.h HEADERS += options_dialog.h HEADERS += nk2edf.h HEADERS += xml.h HEADERS += save_montage_dialog.h HEADERS += load_montage_dialog.h HEADERS += view_montage_dialog.h HEADERS += show_actual_montage_dialog.h HEADERS += print_to_edf.h HEADERS += pagetime_dialog.h HEADERS += print_to_bdf.h HEADERS += ascii2edf.h HEADERS += fino2edf.h HEADERS += nexfin2edf.h HEADERS += edfplusd_cnv.h HEADERS += utc_date_time.h HEADERS += emsa2edf.h HEADERS += special_button.h HEADERS += bdf2edf.h HEADERS += edit_annotation_dock.h HEADERS += popup_save_cancelwindow.h HEADERS += save_annots.h HEADERS += filtercurve.h HEADERS += utils.h HEADERS += signalcurve.h HEADERS += spectrumanalyzer.h HEADERS += bi9800.h HEADERS += edflib.h HEADERS += export_annotations.h HEADERS += edit_predefined_mtg.h HEADERS += spectrum_dock.h HEADERS += edf_annot_list.h HEADERS += reduce_signals.h HEADERS += active_file_chooser.h HEADERS += header_editor.h HEADERS += biosemi2bdfplus.h HEADERS += bdf_triggers.h HEADERS += adjustfiltersettings.h HEADERS += import_annotations.h HEADERS += ravg_filter.h HEADERS += wav2edf.h HEADERS += fma_ecg2edf.h HEADERS += averager_dialog.h HEADERS += averager_curve_wnd.h HEADERS += ecg_filter.h HEADERS += ecg_export.h HEADERS += statistics_dialog.h HEADERS += filteredblockread.h HEADERS += flywheel.h HEADERS += z_score_dialog.h HEADERS += z_ratio_filter.h HEADERS += raw2edf.h HEADERS += check_for_updates.h HEADERS += manscan2edf.h HEADERS += scp_ecg2edf.h HEADERS += unisens2edf.h HEADERS += date_time_stamp_parser.h HEADERS += spike_filter.h HEADERS += spike_filter_dialog.h HEADERS += mit2edf.h HEADERS += biox2edf.h HEADERS += third_party/fidlib/fidlib.h HEADERS += third_party/fidlib/fidmkf.h HEADERS += third_party/fidlib/fidrf_cmdlist.h HEADERS += third_party/kiss_fft/kiss_fft.h HEADERS += third_party/kiss_fft/_kiss_fft_guts.h HEADERS += third_party/kiss_fft/kiss_fftr.h SOURCES += main.cpp SOURCES += mainwindow_constr.cpp SOURCES += mainwindow.cpp SOURCES += viewbuf.cpp SOURCES += videoplayer.cpp SOURCES += read_write_settings.cpp SOURCES += viewcurve.cpp SOURCES += check_edf_file.cpp SOURCES += show_edf_hdr.cpp SOURCES += signals_dialog.cpp SOURCES += signal_chooser.cpp SOURCES += ascii_export.cpp SOURCES += edf_compat.cpp SOURCES += colordialog.cpp SOURCES += filter.cpp SOURCES += filter_dialog.cpp SOURCES += jump_dialog.cpp SOURCES += about_dialog.cpp SOURCES += edf_annotations.cpp SOURCES += annotations_dock.cpp SOURCES += options_dialog.cpp SOURCES += nk2edf.cpp SOURCES += xml.cpp SOURCES += save_montage_dialog.cpp SOURCES += load_montage_dialog.cpp SOURCES += view_montage_dialog.cpp SOURCES += show_actual_montage_dialog.cpp SOURCES += print_to_edf.cpp SOURCES += pagetime_dialog.cpp SOURCES += print_to_bdf.cpp SOURCES += ascii2edf.cpp SOURCES += fino2edf.cpp SOURCES += nexfin2edf.cpp SOURCES += edfplusd_cnv.cpp SOURCES += utc_date_time.c SOURCES += emsa2edf.cpp SOURCES += special_button.cpp SOURCES += bdf2edf.cpp SOURCES += edit_annotation_dock.cpp SOURCES += popup_save_cancelwindow.cpp SOURCES += save_annots.cpp SOURCES += filtercurve.cpp SOURCES += utils.c SOURCES += signalcurve.cpp SOURCES += spectrumanalyzer.cpp SOURCES += bi9800.cpp SOURCES += edflib.c SOURCES += export_annotations.cpp SOURCES += edit_predefined_mtg.cpp SOURCES += spectrum_dock.cpp SOURCES += edf_annot_list.c SOURCES += reduce_signals.cpp SOURCES += active_file_chooser.cpp SOURCES += header_editor.cpp SOURCES += biosemi2bdfplus.cpp SOURCES += bdf_triggers.cpp SOURCES += adjustfiltersettings.cpp SOURCES += import_annotations.cpp SOURCES += ravg_filter.cpp SOURCES += wav2edf.cpp SOURCES += fma_ecg2edf.cpp SOURCES += averager_dialog.cpp SOURCES += averager_curve_wnd.cpp SOURCES += ecg_filter.cpp 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 += 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_dialog.cpp SOURCES += mit2edf.cpp SOURCES += biox2edf.cpp SOURCES += third_party/fidlib/fidlib.c SOURCES += third_party/kiss_fft/kiss_fft.c SOURCES += third_party/kiss_fft/kiss_fftr.c RESOURCES = images.qrc win32 { RC_FILE = edfbrowser.rc } QMAKE_CXXFLAGS += -Wextra -Wshadow -Wformat-nonliteral -Wformat-security -Wtype-limits -Wfatal-errors unix { target.path = /usr/bin target.files = edfbrowser INSTALLS += target documentation.path = /usr/share/doc/edfbrowser documentation.files = doc/* INSTALLS += documentation icon_a.path = /usr/share/icons icon_a.files = images/edf.png INSTALLS += icon_a icon_b.path += /usr/share/pixmaps icon_b.files = images/edf.png INSTALLS += icon_b icon_c.path += /usr/share/icons/hicolor/48x48/apps icon_c.files = images/edf.png INSTALLS += icon_c icon_d.path += /usr/share/icons/hicolor/48x48/mimetypes icon_d.files = images/edf.png INSTALLS += icon_d desktop_link.path += /usr/share/applications desktop_link.files += install/edfbrowser.desktop INSTALLS += desktop_link mime.path += /usr/share/mime/packages mime.files += install/edfbrowser.xml INSTALLS += mime } edfbrowser_157_source/PaxHeaders.7921/biosemi2bdfplus.cpp0000644000000000000000000000013212646460742020463 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/biosemi2bdfplus.cpp0000644000175000001440000005666212646460742021043 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "biosemi2bdfplus.h" UI_BIOSEMI2BDFPLUSwindow::UI_BIOSEMI2BDFPLUSwindow(QWidget *w_parent) { int i; char str[128]; mainwindow = (UI_Mainwindow *)w_parent; recent_opendir = mainwindow->recent_opendir; recent_savedir = mainwindow->recent_savedir; myobjectDialog = new QDialog; myobjectDialog->setMinimumSize(600, 630); myobjectDialog->setMaximumSize(600, 630); myobjectDialog->setWindowTitle("Biosemi to BDF+ converter"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); label2 = new QLabel(myobjectDialog); label2->setGeometry(20, 20, 200, 25); label2->setText("Trigger Input descriptions:"); label3 = new QLabel(myobjectDialog); label3->setGeometry(290, 350, 200, 25); label3->setText("Annotations will be generated at"); label4 = new QLabel(myobjectDialog); label4->setGeometry(290, 440, 200, 25); label4->setText("of trigger input."); for(i=0; i<16; i++) { label1[i] = new QLabel(myobjectDialog); label1[i]->setGeometry(20, 50 + (i * 30), 20, 25); sprintf(str, "%i", i + 1); label1[i]->setText(str); lineEdit1[i] = new QLineEdit(myobjectDialog); lineEdit1[i]->setGeometry(70, 50 + (i * 30), 120, 25); sprintf(str, "Trigger Input %i", i + 1); lineEdit1[i]->setText(str); lineEdit1[i]->setMaxLength(16); } radioButton1 = new QRadioButton(myobjectDialog); radioButton1->setGeometry(290, 385, 150, 20); radioButton1->setText("rising edge"); radioButton1->setChecked(true); radioButton2 = new QRadioButton(myobjectDialog); radioButton2->setGeometry(290, 415, 150, 20); radioButton2->setText("falling edge"); checkBox1 = new QCheckBox(myobjectDialog); checkBox1->setGeometry(290, 500, 200, 20); checkBox1->setText("measure event duration"); checkBox1->setTristate(false); checkBox1->setChecked(false); selectButton = new QPushButton(myobjectDialog); selectButton->setGeometry(20, 584, 100, 25); selectButton->setText("Select File"); closeButton = new QPushButton(myobjectDialog); closeButton->setGeometry(480, 584, 100, 25); closeButton->setText("Close"); QObject::connect(selectButton, SIGNAL(clicked()), this, SLOT(SelectFileButton())); QObject::connect(closeButton, SIGNAL(clicked()), myobjectDialog, SLOT(close())); inputpath[0] = 0; outputpath[0] = 0; myobjectDialog->exec(); } void UI_BIOSEMI2BDFPLUSwindow::SelectFileButton() { int i, j, k, error, hdl_in, hdl_out, edfsignals, status_signal=0, status_samples_in_datarecord=0, rising_edge, set_duration, status[24], totalSamplesInDatarecord, *buf, buf_offset[EDFLIB_MAXSIGNALS], sf, new_sf, samplerate_divider; char str[2048], triggerlabel[24][64], outputfilename[MAX_PATH_LENGTH]; long long datarecords, status_sample_duration, trigger_cnt, progress_steps; struct edf_hdr_struct hdr; struct annotationblock *annotlist=NULL; struct annotationblock *annotation; for(i=0; i<16; i++) { if(!lineEdit1[i]->text().length()) { sprintf(str, "Trigger Input label %i is empty!", i + 1); QMessageBox messagewindow(QMessageBox::Critical, "Error", str); messagewindow.exec(); return; } } for(i=0; i<16; i++) { for(j=0; j<16; j++) { if(i != j) { if(!strcmp(lineEdit1[i]->text().toLocal8Bit().data(), lineEdit1[j]->text().toLocal8Bit().data())) { sprintf(str, "Trigger Input labels %i and %i are the same!", i + 1, j + 1); QMessageBox messagewindow(QMessageBox::Critical, "Error", str); messagewindow.exec(); return; } } } } str[0] = 0; strcpy(inputpath, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "BDF files (*.bdf *.BDF)").toLocal8Bit().data()); if(!strcmp(inputpath, "")) { return; } get_directory_from_path(recent_opendir, inputpath, MAX_PATH_LENGTH); error = edfopen_file_readonly(inputpath, &hdr, EDFLIB_DO_NOT_READ_ANNOTATIONS); if(error < 0) { error = hdr.filetype; switch(error) { case EDFLIB_MALLOC_ERROR : strcpy(str, "EDFlib: malloc error."); break; case EDFLIB_NO_SUCH_FILE_OR_DIRECTORY : strcpy(str, "EDFlib: no such file or directory."); break; case EDFLIB_FILE_CONTAINS_FORMAT_ERRORS : strcpy(str, "EDFlib: file contains format errors.\nOpen the file in EDFbrowser to get more info."); break; case EDFLIB_MAXFILES_REACHED : strcpy(str, "EDFlib: maximum amount of files reached."); break; case EDFLIB_FILE_READ_ERROR : strcpy(str, "EDFlib: a file read error occurred."); break; case EDFLIB_FILE_ALREADY_OPENED : strcpy(str, "EDFlib: file is already opened."); break; case EDFLIB_FILETYPE_ERROR : strcpy(str, "EDFlib: filetype error."); break; case EDFLIB_FILE_WRITE_ERROR : strcpy(str, "EDFlib: file write error."); break; case EDFLIB_NUMBER_OF_SIGNALS_INVALID : strcpy(str, "EDFlib: invalid number of signals."); break; case EDFLIB_FILE_IS_DISCONTINUOUS : strcpy(str, "EDFlib: file is discontinuous."); break; case EDFLIB_INVALID_READ_ANNOTS_VALUE : strcpy(str, "EDFlib: invalid read annotations argument."); break; default : strcpy(str, "EDFlib: unknown error."); } QMessageBox messagewindow(QMessageBox::Critical, "Error", str); messagewindow.exec(); return; } hdl_in = hdr.handle; /////////////////// check file ///////////////////////////////////////////// if(hdr.filetype == EDFLIB_FILETYPE_BDFPLUS) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Selected file is already a BDF-plus file."); messagewindow.exec(); edfclose_file(hdl_in); return; } if(hdr.filetype != EDFLIB_FILETYPE_BDF) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Selected file is not a BDF file."); messagewindow.exec(); edfclose_file(hdl_in); return; } if(hdr.datarecord_duration != EDFLIB_TIME_DIMENSION) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Datarecord duration of inputfile must be 1 second."); messagewindow.exec(); edfclose_file(hdl_in); return; } edfsignals = hdr.edfsignals; if(edfsignals < 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There are no signals in the selected file."); messagewindow.exec(); edfclose_file(hdl_in); return; } sf = hdr.signalparam[0].smp_in_datarecord; for(i=1; itext().toUtf8().data()); triggerlabel[i][16] = 0; } strcpy(&triggerlabel[16][0], "new epoch"); if(radioButton1->isChecked() == true) { rising_edge = 1; for(i=0; i<16; i++) { status[i] = 1; } } else { rising_edge = 0; for(i=0; i<16; i++) { status[i] = 0; } } if(checkBox1->isChecked() == true) { set_duration = 1; } else { set_duration = 0; } for(i=16; i<24; i++) { status[i] = 1; } strcpy(outputfilename, inputpath); remove_extension_from_filename(outputfilename); strcat(outputfilename, "_+.bdf"); outputpath[0] = 0; if(recent_savedir[0]!=0) { strcpy(outputpath, recent_savedir); strcat(outputpath, "/"); } strcat(outputpath, outputfilename); strcpy(outputpath, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(outputpath), "BDF files (*.bdf *.BDF)").toLocal8Bit().data()); if(!strcmp(outputpath, "")) { edfclose_file(hdl_in); return; } get_directory_from_path(recent_savedir, outputpath, MAX_PATH_LENGTH); if(mainwindow->file_is_opened(outputpath)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Outputfile is already opened in EDFbrowser.\nClose the file and try again."); messagewindow.exec(); edfclose_file(hdl_in); return; } if(!(strcmp(inputpath, outputpath))) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Inputfile and outputfile are the same."); messagewindow.exec(); edfclose_file(hdl_in); return; } hdl_out = edfopen_file_writeonly(outputpath, EDFLIB_FILETYPE_BDFPLUS, edfsignals); if(hdl_out < 0) { switch(hdl_out) { case EDFLIB_MALLOC_ERROR : strcpy(str, "EDFlib: malloc error."); break; case EDFLIB_NO_SUCH_FILE_OR_DIRECTORY : strcpy(str, "EDFlib: no such file or directory."); break; case EDFLIB_MAXFILES_REACHED : strcpy(str, "EDFlib: maximum amount of files reached."); break; case EDFLIB_FILE_READ_ERROR : strcpy(str, "EDFlib: a file read error occurred."); break; case EDFLIB_FILE_ALREADY_OPENED : strcpy(str, "EDFlib: file is already opened."); break; case EDFLIB_FILETYPE_ERROR : strcpy(str, "EDFlib: filetype error."); break; case EDFLIB_FILE_WRITE_ERROR : strcpy(str, "EDFlib: file write error."); break; case EDFLIB_NUMBER_OF_SIGNALS_INVALID : strcpy(str, "EDFlib: invalid number of signals."); break; default : strcpy(str, "EDFlib: unknown error."); } QMessageBox messagewindow(QMessageBox::Critical, "Error", str); messagewindow.exec(); edfclose_file(hdl_in); return; } /////////////////// copy header ///////////////////////////////////////////// for(i=0; i= ((hdr.datarecords_in_file * 32) - 2)) { break; } if(trigger_cnt >= 100000) { break; } if(!(datarecords % progress_steps)) { progress.setValue((int)datarecords); qApp->processEvents(); if(progress.wasCanceled()) { edfclose_file(hdl_in); edfclose_file(hdl_out); free(buf); edfplus_annotation_delete_list(&annotlist); return; } } if(edfread_digital_samples(hdl_in, status_signal, status_samples_in_datarecord, buf) < 0) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read error occurred during the collection of triggers."); messagewindow.exec(); edfclose_file(hdl_in); edfclose_file(hdl_out); free(buf); edfplus_annotation_delete_list(&annotlist); return; } for(i=0; ionset = (datarecords * EDFLIB_TIME_DIMENSION) + ((long long)i * status_sample_duration); annotation->onset += hdr.starttime_subsecond; strcpy(annotation->annotation, triggerlabel[j]); edfplus_annotation_add_item(&annotlist, annotation); trigger_cnt++; } else { if(set_duration) { k = edfplus_annotation_count(&annotlist); for(; k>0; k--) { annotation = edfplus_annotation_item(&annotlist, k - 1); if(annotation == NULL) { break; } if(!strcmp(annotation->annotation, triggerlabel[j])) { sprintf(str, "%.4f", (double)((datarecords * EDFLIB_TIME_DIMENSION) + ((long long)i * status_sample_duration) - annotation->onset) / (double)EDFLIB_TIME_DIMENSION); str[15] = 0; strcpy(annotation->duration, str); break; } } } } status[j] = 0; } else // rising edge detected { if(rising_edge || (j == 16)) { annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); if(annotation == NULL) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error (annotation)."); messagewindow.exec(); edfclose_file(hdl_in); edfclose_file(hdl_out); free(buf); edfplus_annotation_delete_list(&annotlist); return; } annotation->onset = (datarecords * EDFLIB_TIME_DIMENSION) + ((long long)i * status_sample_duration); annotation->onset += hdr.starttime_subsecond; strcpy(annotation->annotation, triggerlabel[j]); edfplus_annotation_add_item(&annotlist, annotation); trigger_cnt++; } else { if(set_duration) { k = edfplus_annotation_count(&annotlist); for(; k>0; k--) { annotation = edfplus_annotation_item(&annotlist, k - 1); if(annotation == NULL) { break; } if(!strcmp(annotation->annotation, triggerlabel[j])) { sprintf(str, "%.4f", (double)((datarecords * EDFLIB_TIME_DIMENSION) + ((long long)i * status_sample_duration) - annotation->onset) / (double)EDFLIB_TIME_DIMENSION); str[15] = 0; strcpy(annotation->duration, str); break; } } } } status[j] = 1; } } } } } edfwrite_annotation_latin1(hdl_out, 0LL, -1LL, "Recording starts"); j = edfplus_annotation_count(&annotlist); for(i=0; iduration[0] == 0) { edfwrite_annotation_utf8(hdl_out, annotation->onset / 1000LL, -1LL, annotation->annotation); } else { edfwrite_annotation_utf8(hdl_out, annotation->onset / 1000LL, (long long)(atof(annotation->duration) * 10000.0), annotation->annotation); } } free(buf); edfwrite_annotation_latin1(hdl_out, hdr.datarecords_in_file * 10000LL, -1LL, "Recording ends"); /////////////////// choose datarecord duration ///////////////////////////////////////////// samplerate_divider = 1; i = edfplus_annotation_count(&annotlist); edfplus_annotation_delete_list(&annotlist); annotlist = NULL; if(i % 2) { i++; } i += 2; while(i > hdr.datarecords_in_file) { samplerate_divider *= 2; i /= 2; if(samplerate_divider == 32) { break; } } if(samplerate_divider > 1) { for(i=0; iprocessEvents(); if(progress.wasCanceled()) { edfclose_file(hdl_in); edfclose_file(hdl_out); free(buf); return; } } for(i=0; i. * *************************************************************************** */ #include "about_dialog.h" UI_Aboutwindow::UI_Aboutwindow(UI_Mainwindow *mainwindow) { char str[512]; strcpy(str, " QT version at runtime is "); strncat(str, qVersion(), 32); strcat(str, "\n QT version at compiletime is "); strncat(str, QT_VERSION_STR, 32); strncat(str, "\n Compiled on " __DATE__ " " __TIME__, 40); sprintf(str + strlen(str), "\n CPU-cores detected on this system: %i", mainwindow->maincurve->cpu_cnt); if(mainwindow->use_threads == 1) { strcat(str, "\n Multi-Threading is enabled."); } else { strcat(str, "\n Multi-Threading is disabled."); } str[511] = 0; AboutDialog = new QDialog; AboutDialog->setMinimumSize(640, 480); AboutDialog->setGeometry(300, 250, 640, 480); AboutDialog->setWindowTitle("About"); AboutDialog->setModal(true); AboutDialog->setAttribute(Qt::WA_DeleteOnClose, true); textedit1 = new QTextEdit; textedit1->setFrameStyle(QFrame::Panel | QFrame::Sunken); textedit1->setReadOnly(true); textedit1->setLineWrapMode(QTextEdit::NoWrap); textedit1->setPlainText( "\n " PROGRAM_NAME " " PROGRAM_VERSION "\n" "\n This program is made by Teunis van Beelen.\n" "\n Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Teunis van Beelen.\n" "\n Email: teuniz@gmail.com\n" "\n Disclaimer:\n" " Despite this software is intend to be useful, there is no warranty, use this software at your own risk!\n" " EDFbrowser may NOT be used in safety-critical applications, such as life-support medical systems.\n" " The author is NOT responsible for any consequences. For research and educational purpose only.\n"); textedit1->append(str); textedit1->append( "\n\n GNU GENERAL PUBLIC LICENSE\n" " Version 3, 29 June 2007\n\n" " Copyright (C) 2007 Free Software Foundation, Inc. \n" " Everyone is permitted to copy and distribute verbatim copies\n" " of this license document, but changing it is not allowed.\n\n" " Preamble\n\n" " The GNU General Public License is a free, copyleft license for\n" " software and other kinds of works.\n\n" " The licenses for most software and other practical works are designed\n" " to take away your freedom to share and change the works. By contrast,\n" " the GNU General Public License is intended to guarantee your freedom to\n" " share and change all versions of a program--to make sure it remains free\n" " software for all its users. We, the Free Software Foundation, use the\n" " GNU General Public License for most of our software; it applies also to\n" " any other work released this way by its authors. You can apply it to\n" " your programs, too.\n\n" " When we speak of free software, we are referring to freedom, not\n" " price. Our General Public Licenses are designed to make sure that you\n" " have the freedom to distribute copies of free software (and charge for\n" " them if you wish), that you receive source code or can get it if you\n" " want it, that you can change the software or use pieces of it in new\n" " free programs, and that you know you can do these things.\n\n" " To protect your rights, we need to prevent others from denying you\n" " these rights or asking you to surrender the rights. Therefore, you have\n" " certain responsibilities if you distribute copies of the software, or if\n" " you modify it: responsibilities to respect the freedom of others.\n\n" " For example, if you distribute copies of such a program, whether\n" " gratis or for a fee, you must pass on to the recipients the same\n" " freedoms that you received. You must make sure that they, too, receive\n" " or can get the source code. And you must show them these terms so they\n" " know their rights.\n\n"); textedit1->append( " Developers that use the GNU GPL protect your rights with two steps:\n" " (1) assert copyright on the software, and (2) offer you this License\n" " giving you legal permission to copy, distribute and/or modify it.\n\n" " For the developers' and authors' protection, the GPL clearly explains\n" " that there is no warranty for this free software. For both users' and\n" " authors' sake, the GPL requires that modified versions be marked as\n" " changed, so that their problems will not be attributed erroneously to\n" " authors of previous versions.\n\n" " Some devices are designed to deny users access to install or run\n" " modified versions of the software inside them, although the manufacturer\n" " can do so. This is fundamentally incompatible with the aim of\n" " protecting users' freedom to change the software. The systematic\n" " pattern of such abuse occurs in the area of products for individuals to\n" " use, which is precisely where it is most unacceptable. Therefore, we\n" " have designed this version of the GPL to prohibit the practice for those\n" " products. If such problems arise substantially in other domains, we\n" " stand ready to extend this provision to those domains in future versions\n" " of the GPL, as needed to protect the freedom of users.\n\n" " Finally, every program is threatened constantly by software patents.\n" " States should not allow patents to restrict development and use of\n" " software on general-purpose computers, but in those that do, we wish to\n" " avoid the special danger that patents applied to a free program could\n" " make it effectively proprietary. To prevent this, the GPL assures that\n" " patents cannot be used to render the program non-free.\n\n" " The precise terms and conditions for copying, distribution and\n" " modification follow.\n\n"); textedit1->append( " TERMS AND CONDITIONS\n\n" " 0. Definitions.\n\n" " \"This License\" refers to version 3 of the GNU General Public License.\n\n" " \"Copyright\" also means copyright-like laws that apply to other kinds of\n" " works, such as semiconductor masks.\n\n" " \"The Program\" refers to any copyrightable work licensed under this\n" " License. Each licensee is addressed as \"you\". \"Licensees\" and\n" " \"recipients\" may be individuals or organizations.\n\n" " To \"modify\" a work means to copy from or adapt all or part of the work\n" " in a fashion requiring copyright permission, other than the making of an\n" " exact copy. The resulting work is called a \"modified version\" of the\n" " earlier work or a work \"based on\" the earlier work.\n\n" " A \"covered work\" means either the unmodified Program or a work based\n" " on the Program.\n\n" " To \"propagate\" a work means to do anything with it that, without\n" " permission, would make you directly or secondarily liable for\n" " infringement under applicable copyright law, except executing it on a\n" " computer or modifying a private copy. Propagation includes copying,\n" " distribution (with or without modification), making available to the\n" " public, and in some countries other activities as well.\n\n" " To \"convey\" a work means any kind of propagation that enables other\n" " parties to make or receive copies. Mere interaction with a user through\n" " a computer network, with no transfer of a copy, is not conveying.\n\n" " An interactive user interface displays \"Appropriate Legal Notices\"\n" " to the extent that it includes a convenient and prominently visible\n" " feature that (1) displays an appropriate copyright notice, and (2)\n" " tells the user that there is no warranty for the work (except to the\n" " extent that warranties are provided), that licensees may convey the\n" " work under this License, and how to view a copy of this License. If\n" " the interface presents a list of user commands or options, such as a\n" " menu, a prominent item in the list meets this criterion.\n\n"); textedit1->append( " 1. Source Code.\n\n" " The \"source code\" for a work means the preferred form of the work\n" " for making modifications to it. \"Object code\" means any non-source\n" " form of a work.\n\n" " A \"Standard Interface\" means an interface that either is an official\n" " standard defined by a recognized standards body, or, in the case of\n" " interfaces specified for a particular programming language, one that\n" " is widely used among developers working in that language.\n\n" " The \"System Libraries\" of an executable work include anything, other\n" " than the work as a whole, that (a) is included in the normal form of\n" " packaging a Major Component, but which is not part of that Major\n" " Component, and (b) serves only to enable use of the work with that\n" " Major Component, or to implement a Standard Interface for which an\n" " implementation is available to the public in source code form. A\n" " \"Major Component\", in this context, means a major essential component\n" " (kernel, window system, and so on) of the specific operating system\n" " (if any) on which the executable work runs, or a compiler used to\n" " produce the work, or an object code interpreter used to run it.\n\n" " The \"Corresponding Source\" for a work in object code form means all\n" " the source code needed to generate, install, and (for an executable\n" " work) run the object code and to modify the work, including scripts to\n" " control those activities. However, it does not include the work's\n" " System Libraries, or general-purpose tools or generally available free\n" " programs which are used unmodified in performing those activities but\n" " which are not part of the work. For example, Corresponding Source\n" " includes interface definition files associated with source files for\n" " the work, and the source code for shared libraries and dynamically\n" " linked subprograms that the work is specifically designed to require,\n" " such as by intimate data communication or control flow between those\n" " subprograms and other parts of the work.\n\n" " The Corresponding Source need not include anything that users\n" " can regenerate automatically from other parts of the Corresponding\n" " Source.\n\n" " The Corresponding Source for a work in source code form is that\n" " same work.\n\n"); textedit1->append( " 2. Basic Permissions.\n\n" " All rights granted under this License are granted for the term of\n" " copyright on the Program, and are irrevocable provided the stated\n" " conditions are met. This License explicitly affirms your unlimited\n" " permission to run the unmodified Program. The output from running a\n" " covered work is covered by this License only if the output, given its\n" " content, constitutes a covered work. This License acknowledges your\n" " rights of fair use or other equivalent, as provided by copyright law.\n\n" " You may make, run and propagate covered works that you do not\n" " convey, without conditions so long as your license otherwise remains\n" " in force. You may convey covered works to others for the sole purpose\n" " of having them make modifications exclusively for you, or provide you\n" " with facilities for running those works, provided that you comply with\n" " the terms of this License in conveying all material for which you do\n" " not control copyright. Those thus making or running the covered works\n" " for you must do so exclusively on your behalf, under your direction\n" " and control, on terms that prohibit them from making any copies of\n" " your copyrighted material outside their relationship with you.\n\n" " Conveying under any other circumstances is permitted solely under\n" " the conditions stated below. Sublicensing is not allowed; section 10\n" " makes it unnecessary.\n\n"); textedit1->append( " 3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n" " No covered work shall be deemed part of an effective technological\n" " measure under any applicable law fulfilling obligations under article\n" " 11 of the WIPO copyright treaty adopted on 20 December 1996, or\n" " similar laws prohibiting or restricting circumvention of such\n" " measures.\n\n" " When you convey a covered work, you waive any legal power to forbid\n" " circumvention of technological measures to the extent such circumvention\n" " is effected by exercising rights under this License with respect to\n" " the covered work, and you disclaim any intention to limit operation or\n" " modification of the work as a means of enforcing, against the work's\n" " users, your or third parties' legal rights to forbid circumvention of\n" " technological measures.\n\n" " 4. Conveying Verbatim Copies.\n\n" " You may convey verbatim copies of the Program's source code as you\n" " receive it, in any medium, provided that you conspicuously and\n" " appropriately publish on each copy an appropriate copyright notice;\n" " keep intact all notices stating that this License and any\n" " non-permissive terms added in accord with section 7 apply to the code;\n" " keep intact all notices of the absence of any warranty; and give all\n" " recipients a copy of this License along with the Program.\n\n" " You may charge any price or no price for each copy that you convey,\n" " and you may offer support or warranty protection for a fee.\n\n"); textedit1->append( " 5. Conveying Modified Source Versions.\n\n" " You may convey a work based on the Program, or the modifications to\n" " produce it from the Program, in the form of source code under the\n" " terms of section 4, provided that you also meet all of these conditions:\n\n" " a) The work must carry prominent notices stating that you modified\n" " it, and giving a relevant date.\n\n" " b) The work must carry prominent notices stating that it is\n" " released under this License and any conditions added under section\n" " 7. This requirement modifies the requirement in section 4 to\n" " \"keep intact all notices\".\n\n" " c) You must license the entire work, as a whole, under this\n" " License to anyone who comes into possession of a copy. This\n" " License will therefore apply, along with any applicable section 7\n" " additional terms, to the whole of the work, and all its parts,\n" " regardless of how they are packaged. This License gives no\n" " permission to license the work in any other way, but it does not\n" " invalidate such permission if you have separately received it.\n\n" " d) If the work has interactive user interfaces, each must display\n" " Appropriate Legal Notices; however, if the Program has interactive\n" " interfaces that do not display Appropriate Legal Notices, your\n" " work need not make them do so.\n\n" " A compilation of a covered work with other separate and independent\n" " works, which are not by their nature extensions of the covered work,\n" " and which are not combined with it such as to form a larger program,\n" " in or on a volume of a storage or distribution medium, is called an\n" " \"aggregate\" if the compilation and its resulting copyright are not\n" " used to limit the access or legal rights of the compilation's users\n" " beyond what the individual works permit. Inclusion of a covered work\n" " in an aggregate does not cause this License to apply to the other\n" " parts of the aggregate.\n\n"); textedit1->append( " 6. Conveying Non-Source Forms.\n\n" " You may convey a covered work in object code form under the terms\n" " of sections 4 and 5, provided that you also convey the\n" " machine-readable Corresponding Source under the terms of this License,\n" " in one of these ways:\n\n" " a) Convey the object code in, or embodied in, a physical product\n" " (including a physical distribution medium), accompanied by the\n" " Corresponding Source fixed on a durable physical medium\n" " customarily used for software interchange.\n\n" " b) Convey the object code in, or embodied in, a physical product\n" " (including a physical distribution medium), accompanied by a\n" " written offer, valid for at least three years and valid for as\n" " long as you offer spare parts or customer support for that product\n" " model, to give anyone who possesses the object code either (1) a\n" " copy of the Corresponding Source for all the software in the\n" " product that is covered by this License, on a durable physical\n" " medium customarily used for software interchange, for a price no\n" " more than your reasonable cost of physically performing this\n" " conveying of source, or (2) access to copy the\n" " Corresponding Source from a network server at no charge.\n\n" " c) Convey individual copies of the object code with a copy of the\n" " written offer to provide the Corresponding Source. This\n" " alternative is allowed only occasionally and noncommercially, and\n" " only if you received the object code with such an offer, in accord\n" " with subsection 6b.\n\n" " d) Convey the object code by offering access from a designated\n" " place (gratis or for a charge), and offer equivalent access to the\n" " Corresponding Source in the same way through the same place at no\n" " further charge. You need not require recipients to copy the\n" " Corresponding Source along with the object code. If the place to\n" " copy the object code is a network server, the Corresponding Source\n" " may be on a different server (operated by you or a third party)\n" " that supports equivalent copying facilities, provided you maintain\n" " clear directions next to the object code saying where to find the\n" " Corresponding Source. Regardless of what server hosts the\n" " Corresponding Source, you remain obligated to ensure that it is\n" " available for as long as needed to satisfy these requirements.\n\n" " e) Convey the object code using peer-to-peer transmission, provided\n" " you inform other peers where the object code and Corresponding\n" " Source of the work are being offered to the general public at no\n" " charge under subsection 6d.\n\n" " A separable portion of the object code, whose source code is excluded\n" " from the Corresponding Source as a System Library, need not be\n" " included in conveying the object code work.\n\n" " A \"User Product\" is either (1) a \"consumer product\", which means any\n" " tangible personal property which is normally used for personal, family,\n" " or household purposes, or (2) anything designed or sold for incorporation\n" " into a dwelling. In determining whether a product is a consumer product,\n" " doubtful cases shall be resolved in favor of coverage. For a particular\n" " product received by a particular user, \"normally used\" refers to a\n" " typical or common use of that class of product, regardless of the status\n" " of the particular user or of the way in which the particular user\n" " actually uses, or expects or is expected to use, the product. A product\n" " is a consumer product regardless of whether the product has substantial\n" " commercial, industrial or non-consumer uses, unless such uses represent\n" " the only significant mode of use of the product.\n\n" " \"Installation Information\" for a User Product means any methods,\n" " procedures, authorization keys, or other information required to install\n" " and execute modified versions of a covered work in that User Product from\n" " a modified version of its Corresponding Source. The information must\n" " suffice to ensure that the continued functioning of the modified object\n" " code is in no case prevented or interfered with solely because\n" " modification has been made.\n\n" " If you convey an object code work under this section in, or with, or\n" " specifically for use in, a User Product, and the conveying occurs as\n" " part of a transaction in which the right of possession and use of the\n" " User Product is transferred to the recipient in perpetuity or for a\n" " fixed term (regardless of how the transaction is characterized), the\n" " Corresponding Source conveyed under this section must be accompanied\n" " by the Installation Information. But this requirement does not apply\n" " if neither you nor any third party retains the ability to install\n" " modified object code on the User Product (for example, the work has\n" " been installed in ROM).\n\n" " The requirement to provide Installation Information does not include a\n" " requirement to continue to provide support service, warranty, or updates\n" " for a work that has been modified or installed by the recipient, or for\n" " the User Product in which it has been modified or installed. Access to a\n" " network may be denied when the modification itself materially and\n" " adversely affects the operation of the network or violates the rules and\n" " protocols for communication across the network.\n\n" " Corresponding Source conveyed, and Installation Information provided,\n" " in accord with this section must be in a format that is publicly\n" " documented (and with an implementation available to the public in\n" " source code form), and must require no special password or key for\n" " unpacking, reading or copying.\n\n"); textedit1->append( " 7. Additional Terms.\n\n" " \"Additional permissions\" are terms that supplement the terms of this\n" " License by making exceptions from one or more of its conditions.\n" " Additional permissions that are applicable to the entire Program shall\n" " be treated as though they were included in this License, to the extent\n" " that they are valid under applicable law. If additional permissions\n" " apply only to part of the Program, that part may be used separately\n" " under those permissions, but the entire Program remains governed by\n" " this License without regard to the additional permissions.\n\n" " When you convey a copy of a covered work, you may at your option\n" " remove any additional permissions from that copy, or from any part of\n" " it. (Additional permissions may be written to require their own\n" " removal in certain cases when you modify the work.) You may place\n" " additional permissions on material, added by you to a covered work,\n" " for which you have or can give appropriate copyright permission.\n\n" " Notwithstanding any other provision of this License, for material you\n" " add to a covered work, you may (if authorized by the copyright holders of\n" " that material) supplement the terms of this License with terms:\n\n" " a) Disclaiming warranty or limiting liability differently from the\n" " terms of sections 15 and 16 of this License; or\n\n" " b) Requiring preservation of specified reasonable legal notices or\n" " author attributions in that material or in the Appropriate Legal\n" " Notices displayed by works containing it; or\n\n" " c) Prohibiting misrepresentation of the origin of that material, or\n" " requiring that modified versions of such material be marked in\n" " reasonable ways as different from the original version; or\n\n" " d) Limiting the use for publicity purposes of names of licensors or\n" " authors of the material; or\n\n" " e) Declining to grant rights under trademark law for use of some\n" " trade names, trademarks, or service marks; or\n\n" " f) Requiring indemnification of licensors and authors of that\n" " material by anyone who conveys the material (or modified versions of\n" " it) with contractual assumptions of liability to the recipient, for\n" " any liability that these contractual assumptions directly impose on\n" " those licensors and authors.\n\n" " All other non-permissive additional terms are considered \"further\n" " restrictions\" within the meaning of section 10. If the Program as you\n" " received it, or any part of it, contains a notice stating that it is\n" " governed by this License along with a term that is a further\n" " restriction, you may remove that term. If a license document contains\n" " a further restriction but permits relicensing or conveying under this\n" " License, you may add to a covered work material governed by the terms\n" " of that license document, provided that the further restriction does\n" " not survive such relicensing or conveying.\n\n" " If you add terms to a covered work in accord with this section, you\n" " must place, in the relevant source files, a statement of the\n" " additional terms that apply to those files, or a notice indicating\n" " where to find the applicable terms.\n\n" " Additional terms, permissive or non-permissive, may be stated in the\n" " form of a separately written license, or stated as exceptions;\n" " the above requirements apply either way.\n\n"); textedit1->append( " 8. Termination.\n\n" " You may not propagate or modify a covered work except as expressly\n" " provided under this License. Any attempt otherwise to propagate or\n" " modify it is void, and will automatically terminate your rights under\n" " this License (including any patent licenses granted under the third\n" " paragraph of section 11).\n\n" " However, if you cease all violation of this License, then your\n" " license from a particular copyright holder is reinstated (a)\n" " provisionally, unless and until the copyright holder explicitly and\n" " finally terminates your license, and (b) permanently, if the copyright\n" " holder fails to notify you of the violation by some reasonable means\n" " prior to 60 days after the cessation.\n\n" " Moreover, your license from a particular copyright holder is\n" " reinstated permanently if the copyright holder notifies you of the\n" " violation by some reasonable means, this is the first time you have\n" " received notice of violation of this License (for any work) from that\n" " copyright holder, and you cure the violation prior to 30 days after\n" " your receipt of the notice.\n\n" " Termination of your rights under this section does not terminate the\n" " licenses of parties who have received copies or rights from you under\n" " this License. If your rights have been terminated and not permanently\n" " reinstated, you do not qualify to receive new licenses for the same\n" " material under section 10.\n\n" " 9. Acceptance Not Required for Having Copies.\n\n" " You are not required to accept this License in order to receive or\n" " run a copy of the Program. Ancillary propagation of a covered work\n" " occurring solely as a consequence of using peer-to-peer transmission\n" " to receive a copy likewise does not require acceptance. However,\n" " nothing other than this License grants you permission to propagate or\n" " modify any covered work. These actions infringe copyright if you do\n" " not accept this License. Therefore, by modifying or propagating a\n" " covered work, you indicate your acceptance of this License to do so.\n\n" " 10. Automatic Licensing of Downstream Recipients.\n\n" " Each time you convey a covered work, the recipient automatically\n" " receives a license from the original licensors, to run, modify and\n" " propagate that work, subject to this License. You are not responsible\n" " for enforcing compliance by third parties with this License.\n\n" " An \"entity transaction\" is a transaction transferring control of an\n" " organization, or substantially all assets of one, or subdividing an\n" " organization, or merging organizations. If propagation of a covered\n" " work results from an entity transaction, each party to that\n" " transaction who receives a copy of the work also receives whatever\n" " licenses to the work the party's predecessor in interest had or could\n" " give under the previous paragraph, plus a right to possession of the\n" " Corresponding Source of the work from the predecessor in interest, if\n" " the predecessor has it or can get it with reasonable efforts.\n\n" " You may not impose any further restrictions on the exercise of the\n" " rights granted or affirmed under this License. For example, you may\n" " not impose a license fee, royalty, or other charge for exercise of\n" " rights granted under this License, and you may not initiate litigation\n" " (including a cross-claim or counterclaim in a lawsuit) alleging that\n" " any patent claim is infringed by making, using, selling, offering for\n" " sale, or importing the Program or any portion of it.\n\n"); textedit1->append( " 11. Patents.\n\n" " A \"contributor\" is a copyright holder who authorizes use under this\n" " License of the Program or a work on which the Program is based. The\n" " work thus licensed is called the contributor's \"contributor version\".\n\n" " A contributor's \"essential patent claims\" are all patent claims\n" " owned or controlled by the contributor, whether already acquired or\n" " hereafter acquired, that would be infringed by some manner, permitted\n" " by this License, of making, using, or selling its contributor version,\n" " but do not include claims that would be infringed only as a\n" " consequence of further modification of the contributor version. For\n" " purposes of this definition, \"control\" includes the right to grant\n" " patent sublicenses in a manner consistent with the requirements of\n" " this License.\n\n" " Each contributor grants you a non-exclusive, worldwide, royalty-free\n" " patent license under the contributor's essential patent claims, to\n" " make, use, sell, offer for sale, import and otherwise run, modify and\n" " propagate the contents of its contributor version.\n" " In the following three paragraphs, a \"patent license\" is any express\n" " agreement or commitment, however denominated, not to enforce a patent\n" " (such as an express permission to practice a patent or covenant not to\n" " sue for patent infringement). To \"grant\" such a patent license to a\n" " party means to make such an agreement or commitment not to enforce a\n" " patent against the party.\n\n" " If you convey a covered work, knowingly relying on a patent license,\n" " and the Corresponding Source of the work is not available for anyone\n" " to copy, free of charge and under the terms of this License, through a\n" " publicly available network server or other readily accessible means,\n" " then you must either (1) cause the Corresponding Source to be so\n" " available, or (2) arrange to deprive yourself of the benefit of the\n" " patent license for this particular work, or (3) arrange, in a manner\n" " consistent with the requirements of this License, to extend the patent\n" " license to downstream recipients. \"Knowingly relying\" means you have\n" " actual knowledge that, but for the patent license, your conveying the\n" " covered work in a country, or your recipient's use of the covered work\n" " in a country, would infringe one or more identifiable patents in that\n" " country that you have reason to believe are valid.\n\n" " If, pursuant to or in connection with a single transaction or\n" " arrangement, you convey, or propagate by procuring conveyance of, a\n" " covered work, and grant a patent license to some of the parties\n" " receiving the covered work authorizing them to use, propagate, modify\n" " or convey a specific copy of the covered work, then the patent license\n" " you grant is automatically extended to all recipients of the covered\n" " work and works based on it.\n\n" " A patent license is \"discriminatory\" if it does not include within\n" " the scope of its coverage, prohibits the exercise of, or is\n" " conditioned on the non-exercise of one or more of the rights that are\n" " specifically granted under this License. You may not convey a covered\n" " work if you are a party to an arrangement with a third party that is\n" " in the business of distributing software, under which you make payment\n" " to the third party based on the extent of your activity of conveying\n" " the work, and under which the third party grants, to any of the\n" " parties who would receive the covered work from you, a discriminatory\n" " patent license (a) in connection with copies of the covered work\n" " conveyed by you (or copies made from those copies), or (b) primarily\n" " for and in connection with specific products or compilations that\n" " contain the covered work, unless you entered into that arrangement,\n" " or that patent license was granted, prior to 28 March 2007.\n\n" " Nothing in this License shall be construed as excluding or limiting\n" " any implied license or other defenses to infringement that may\n" " otherwise be available to you under applicable patent law.\n\n"); textedit1->append( " 12. No Surrender of Others' Freedom.\n\n" " If conditions are imposed on you (whether by court order, agreement or\n" " otherwise) that contradict the conditions of this License, they do not\n" " excuse you from the conditions of this License. If you cannot convey a\n" " covered work so as to satisfy simultaneously your obligations under this\n" " License and any other pertinent obligations, then as a consequence you may\n" " not convey it at all. For example, if you agree to terms that obligate you\n" " to collect a royalty for further conveying from those to whom you convey\n" " the Program, the only way you could satisfy both those terms and this\n" " License would be to refrain entirely from conveying the Program.\n\n" " 13. Use with the GNU Affero General Public License.\n\n" " Notwithstanding any other provision of this License, you have\n" " permission to link or combine any covered work with a work licensed\n" " under version 3 of the GNU Affero General Public License into a single\n" " combined work, and to convey the resulting work. The terms of this\n" " License will continue to apply to the part which is the covered work,\n" " but the special requirements of the GNU Affero General Public License,\n" " section 13, concerning interaction through a network will apply to the\n" " combination as such.\n\n" " 14. Revised Versions of this License.\n\n" " The Free Software Foundation may publish revised and/or new versions of\n" " the GNU General Public License from time to time. Such new versions will\n" " be similar in spirit to the present version, but may differ in detail to\n" " address new problems or concerns.\n\n" " Each version is given a distinguishing version number. If the\n" " Program specifies that a certain numbered version of the GNU General\n" " Public License \"or any later version\" applies to it, you have the\n" " option of following the terms and conditions either of that numbered\n" " version or of any later version published by the Free Software\n" " Foundation. If the Program does not specify a version number of the\n" " GNU General Public License, you may choose any version ever published\n" " by the Free Software Foundation.\n\n" " If the Program specifies that a proxy can decide which future\n" " versions of the GNU General Public License can be used, that proxy's\n" " public statement of acceptance of a version permanently authorizes you\n" " to choose that version for the Program.\n\n" " Later license versions may give you additional or different\n" " permissions. However, no additional obligations are imposed on any\n" " author or copyright holder as a result of your choosing to follow a\n" " later version.\n\n" " 15. Disclaimer of Warranty.\n\n" " THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\n" " APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\n" " HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\n" " OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\n" " THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n" " PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\n" " IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\n" " ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n" " 16. Limitation of Liability.\n\n" " IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n" " WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\n" " THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\n" " GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\n" " USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\n" " DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\n" " PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\n" " EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\n" " SUCH DAMAGES.\n\n" " 17. Interpretation of Sections 15 and 16.\n\n" " If the disclaimer of warranty and limitation of liability provided\n" " above cannot be given local legal effect according to their terms,\n" " reviewing courts shall apply local law that most closely approximates\n" " an absolute waiver of all civil liability in connection with the\n" " Program, unless a warranty or assumption of liability accompanies a\n" " copy of the Program in return for a fee.\n\n" " END OF TERMS AND CONDITIONS\n\n"); pushButton1 = new QPushButton; pushButton1->setText("Close"); hlayout1 = new QHBoxLayout; hlayout1->insertStretch(0, 100); hlayout1->addWidget(pushButton1); vlayout1 = new QVBoxLayout; vlayout1->addWidget(textedit1); vlayout1->setStretchFactor(textedit1, 100); vlayout1->addLayout(hlayout1); vlayout1->setStretchFactor(hlayout1, 0); AboutDialog->setLayout(vlayout1); QObject::connect(pushButton1, SIGNAL(clicked()), AboutDialog, SLOT(close())); AboutDialog->exec(); } edfbrowser_157_source/PaxHeaders.7921/save_annots.cpp0000644000000000000000000000012712646460742017716 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/save_annots.cpp0000644000175000001440000003410612646460742020257 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "save_annots.h" int save_annotations(UI_Mainwindow *mainwindow, FILE *outputfile, struct edfhdrblock *hdr, struct annotationblock *annotlist) { int i, j, k, n, p=0, new_edfsignals=0, signalslist[MAXSIGNALS], datarecords, annot_len, annot_smp_per_record, annot_recordsize, timestamp_decimals, timestamp_digits, annots_per_datrec, space, progress_steps; char *readbuf, scratchpad[256], *annot_buf; long long time; FILE *inputfile; struct annotationblock *annot; inputfile = hdr->file_hdl; for(i=0; iedfsignals; i++) { if(!hdr->edfparam[i].annotation) { signalslist[new_edfsignals] = i; new_edfsignals++; } } datarecords = hdr->datarecords; time = (hdr->datarecords * hdr->long_data_record_duration) / TIME_DIMENSION; timestamp_decimals = get_tal_timestamp_decimal_cnt(hdr); if(timestamp_decimals < 0) { return(1); } timestamp_digits = get_tal_timestamp_digit_cnt(hdr); if(timestamp_digits < 0) { return(1); } annot = annotlist; annot_len = get_max_annotation_strlen(&annot); i = edfplus_annotation_count(&annot); annots_per_datrec = i / datarecords; if(i % datarecords) { annots_per_datrec++; } annot_recordsize = (annot_len * annots_per_datrec) + timestamp_digits + timestamp_decimals + 4; if(timestamp_decimals) { annot_recordsize++; } if(hdr->edf) { annot_smp_per_record = annot_recordsize / 2; if(annot_recordsize % annot_smp_per_record) { annot_smp_per_record++; annot_recordsize = annot_smp_per_record * 2; } } else { annot_smp_per_record = annot_recordsize / 3; if(annot_recordsize % annot_smp_per_record) { annot_smp_per_record++; annot_recordsize = annot_smp_per_record * 3; } } readbuf = (char *)malloc(hdr->recordsize); if(readbuf==NULL) { return(1); } annot_buf = (char *)malloc(annot_recordsize + 10); if(annot_buf==NULL) { free(readbuf); return(1); } /////////////////////////////////////////////////////////////////// rewind(outputfile); if(hdr->edf) { fprintf(outputfile, "0 "); } else { fprintf(outputfile, "XBIOSEMI"); rewind(outputfile); fputc(255, outputfile); fseeko(outputfile, 0LL, SEEK_END); } fseeko(inputfile, 8LL, SEEK_SET); if((hdr->edfplus)||(hdr->bdfplus)) { if(fread(scratchpad, 176, 1, inputfile)!=1) { free(readbuf); free(annot_buf); return(2); } if((hdr->genuine_nk) && (hdr->nk_triggers_read)) { space = 0; for(n=80; n<160; n++) { if(scratchpad[n] == ' ') { space++; if(space > 3) { break; } } } n += 14; if(n<150) { if(!strncmp(scratchpad + n, "EEG", 3)) { scratchpad[n] = 'e'; scratchpad[n+1] = 'e'; scratchpad[n+2] = 'g'; } } } if(fwrite(scratchpad, 176, 1, outputfile)!=1) { free(readbuf); free(annot_buf); return(3); } } else { sprintf(scratchpad, "X X X X "); if(fread(scratchpad + 8, 80, 1, inputfile)!=1) { free(readbuf); free(annot_buf); return(2); } if(fwrite(scratchpad, 80, 1, outputfile)!=1) { free(readbuf); free(annot_buf); return(3); } sprintf(scratchpad, "Startdate X X X X "); if(fread(scratchpad + 18, 80, 1, inputfile)!=1) { free(readbuf); free(annot_buf); return(2); } if(fwrite(scratchpad, 80, 1, outputfile)!=1) { free(readbuf); free(annot_buf); return(3); } if(fread(scratchpad, 16, 1, inputfile)!=1) { free(readbuf); free(annot_buf); return(2); } if(fwrite(scratchpad, 16, 1, outputfile)!=1) { free(readbuf); free(annot_buf); return(3); } } fprintf(outputfile, "%-8i", (new_edfsignals * 256) + 512); if(hdr->edf) { fprintf(outputfile, "EDF+C"); } else { fprintf(outputfile, "BDF+C"); } for(i=0; i<39; i++) { fputc(' ', outputfile); } fprintf(outputfile, "%-8i", datarecords); snprintf(scratchpad, 256, "%.12f", hdr->data_record_duration); remove_trailing_zeros(scratchpad); strcat(scratchpad, " "); if((!strncmp(scratchpad, "0.", 2)) && (scratchpad[8] != ' ')) { scratchpad[9] = 0; fprintf(outputfile, "%s", scratchpad + 1); } else { scratchpad[8] = 0; fprintf(outputfile, "%s", scratchpad); } fprintf(outputfile, "%-4i", new_edfsignals + 1); for(i=0; iedfparam[signalslist[i]].label); } if(hdr->edf) { fprintf(outputfile, "%s", "EDF Annotations "); } else { fprintf(outputfile, "%s", "BDF Annotations "); } for(i=0; iedfparam[signalslist[i]].transducer); } for(i=0; i<80; i++) { fputc(' ', outputfile); } for(i=0; iedfparam[signalslist[i]].physdimension); } for(i=0; i<8; i++) { fputc(' ', outputfile); } for(i=0; iedfparam[signalslist[i]].phys_min); for(k=0; k<8; k++) { if(scratchpad[k]=='.') { for(j=7; j>=0; j--) { if((scratchpad[j]!='.')&&(scratchpad[j]!='0')) { break; } if(scratchpad[j]=='.') { scratchpad[j] = ' '; break; } scratchpad[j] = ' '; } break; } scratchpad[8] = 0; } fprintf(outputfile, "%s", scratchpad); } fprintf(outputfile, "-1 "); for(i=0; iedfparam[signalslist[i]].phys_max); for(k=0; k<8; k++) { if(scratchpad[k]=='.') { for(j=7; j>=0; j--) { if((scratchpad[j]!='.')&&(scratchpad[j]!='0')) { break; } if(scratchpad[j]=='.') { scratchpad[j] = ' '; break; } scratchpad[j] = ' '; } break; } } scratchpad[8] = 0; fprintf(outputfile, "%s", scratchpad); } fprintf(outputfile, "1 "); for(i=0; iedfparam[signalslist[i]].dig_min); } if(hdr->edf) { fprintf(outputfile, "%s", "-32768 "); } else { fprintf(outputfile, "%s", "-8388608"); } for(i=0; iedfparam[signalslist[i]].dig_max); } if(hdr->edf) { fprintf(outputfile, "%s", "32767 "); } else { fprintf(outputfile, "%s", "8388607 "); } for(i=0; iedfparam[signalslist[i]].prefilter); } for(i=0; i<80; i++) { fputc(' ', outputfile); } for(i=0; iedfparam[signalslist[i]].smp_per_record); } fprintf(outputfile, "%-8i", annot_smp_per_record); for(i=0; i<((new_edfsignals * 32) + 32); i++) { fputc(' ', outputfile); } /////////////////////////////////////////////////////////////////// QProgressDialog progress("Saving file...", "Abort", 0, datarecords, mainwindow); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); progress_steps = datarecords / 100; if(progress_steps < 1) { progress_steps = 1; } fseeko(inputfile, (long long)(hdr->hdrsize), SEEK_SET); annot = annotlist; time = hdr->starttime_offset; for(k=0; kprocessEvents(); if(progress.wasCanceled() == true) { free(readbuf); free(annot_buf); return(4); } } if(fread(readbuf, hdr->recordsize, 1, inputfile) != 1) { progress.reset(); free(readbuf); free(annot_buf); return(2); } if(hdr->edf) { for(i=0; iedfparam[signalslist[i]].smp_per_record; j++) { fputc(*((unsigned char *)(readbuf + hdr->edfparam[signalslist[i]].buf_offset + (j * 2))), outputfile); fputc(*((unsigned char *)(readbuf + hdr->edfparam[signalslist[i]].buf_offset + (j * 2) + 1)), outputfile); } } } else { for(i=0; iedfparam[signalslist[i]].smp_per_record; j++) { fputc(*((unsigned char *)(readbuf + hdr->edfparam[signalslist[i]].buf_offset + (j * 3))), outputfile); fputc(*((unsigned char *)(readbuf + hdr->edfparam[signalslist[i]].buf_offset + (j * 3) + 1)), outputfile); fputc(*((unsigned char *)(readbuf + hdr->edfparam[signalslist[i]].buf_offset + (j * 3) + 2)), outputfile); } } } #ifdef Q_OS_WIN32 switch(timestamp_decimals) { case 0 : p = __mingw_snprintf(annot_buf, 16, "+%lli", time / TIME_DIMENSION); break; case 1 : p = __mingw_snprintf(annot_buf, 16, "+%lli.%01lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 1000000LL); break; case 2 : p = __mingw_snprintf(annot_buf, 16, "+%lli.%02lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 100000LL); break; case 3 : p = __mingw_snprintf(annot_buf, 16, "+%lli.%03lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 10000LL); break; case 4 : p = __mingw_snprintf(annot_buf, 16, "+%lli.%04lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 1000LL); break; case 5 : p = __mingw_snprintf(annot_buf, 16, "+%lli.%05lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 100LL); break; case 6 : p = __mingw_snprintf(annot_buf, 16, "+%lli.%06lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 10LL); break; case 7 : p = __mingw_snprintf(annot_buf, 16, "+%lli.%07lli", time / TIME_DIMENSION, time % TIME_DIMENSION); break; } #else switch(timestamp_decimals) { case 0 : p = snprintf(annot_buf, 16, "+%lli", time / TIME_DIMENSION); break; case 1 : p = snprintf(annot_buf, 16, "+%lli.%01lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 1000000LL); break; case 2 : p = snprintf(annot_buf, 16, "+%lli.%02lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 100000LL); break; case 3 : p = snprintf(annot_buf, 16, "+%lli.%03lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 10000LL); break; case 4 : p = snprintf(annot_buf, 16, "+%lli.%04lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 1000LL); break; case 5 : p = snprintf(annot_buf, 16, "+%lli.%05lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 100LL); break; case 6 : p = snprintf(annot_buf, 16, "+%lli.%06lli", time / TIME_DIMENSION, (time % TIME_DIMENSION) / 10LL); break; case 7 : p = snprintf(annot_buf, 16, "+%lli.%07lli", time / TIME_DIMENSION, time % TIME_DIMENSION); break; } #endif annot_buf[p++] = 20; annot_buf[p++] = 20; annot_buf[p++] = 0; if(annot!=NULL) { for(i=0; ionset<0) { #ifdef Q_OS_WIN32 p += __mingw_snprintf(annot_buf + p, 20, "-%lli.%07lli", -(annot->onset / TIME_DIMENSION), -(annot->onset % TIME_DIMENSION)); #else p += snprintf(annot_buf + p, 20, "-%lli.%07lli", -(annot->onset / TIME_DIMENSION), -(annot->onset % TIME_DIMENSION)); #endif } else { #ifdef Q_OS_WIN32 p += __mingw_snprintf(annot_buf + p, 20, "+%lli.%07lli", annot->onset / TIME_DIMENSION, annot->onset % TIME_DIMENSION); #else p += snprintf(annot_buf + p, 20, "+%lli.%07lli", annot->onset / TIME_DIMENSION, annot->onset % TIME_DIMENSION); #endif } for(j=0; j<7; j++) { if(annot_buf[p - j - 1] != '0') { break; } } if(j) { p -= j; if(j == 7) { p--; } } if(annot->duration[0]) { annot_buf[p++] = 21; p += sprintf(annot_buf + p, "%s", annot->duration); } annot_buf[p++] = 20; p += sprintf(annot_buf + p, "%s", annot->annotation); annot_buf[p++] = 20; annot_buf[p++] = 0; annot = annot->next_annotation; } } } for(; plong_data_record_duration; } progress.reset(); free(readbuf); free(annot_buf); return(0); } edfbrowser_157_source/PaxHeaders.7921/view_montage_dialog.cpp0000644000000000000000000000013212646460742021375 xustar0030 mtime=1452958178.249246726 30 atime=1452958178.249246726 30 ctime=1452958178.249246726 edfbrowser_157_source/view_montage_dialog.cpp0000644000175000001440000007111512646460742021743 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "view_montage_dialog.h" UI_ViewMontagewindow::UI_ViewMontagewindow(QWidget *w_parent) { mainwindow = (UI_Mainwindow *)w_parent; mtg_path[0] = 0; mtg_dir[0] = 0; if(mainwindow->recent_montagedir[0]!=0) { strcpy(mtg_dir, mainwindow->recent_montagedir); } ViewMontageDialog = new QDialog; ViewMontageDialog->setMinimumSize(500, 300); ViewMontageDialog->resize(500, 440); ViewMontageDialog->setWindowTitle("View montage"); ViewMontageDialog->setModal(true); ViewMontageDialog->setAttribute(Qt::WA_DeleteOnClose, true); t_model = new QStandardItemModel(this); tree = new QTreeView; tree->setHeaderHidden(true); tree->setIndentation(30); tree->setSelectionMode(QAbstractItemView::NoSelection); tree->setEditTriggers(QAbstractItemView::NoEditTriggers); tree->setSortingEnabled(false); tree->setDragDropMode(QAbstractItemView::NoDragDrop); tree->setModel(t_model); SelectButton = new QPushButton; SelectButton->setFixedSize(100, 25); SelectButton->setText("Select montage"); CloseButton = new QPushButton; CloseButton->setFixedSize(100, 25); CloseButton->setText("Close"); hbox = new QHBoxLayout; hbox->addWidget(SelectButton, 0, Qt::AlignLeft); hbox->addWidget(CloseButton, 0, Qt::AlignRight); box = new QBoxLayout(QBoxLayout::TopToBottom, ViewMontageDialog); box->addWidget(tree); box->addLayout(hbox); QObject::connect(CloseButton, SIGNAL(clicked()), ViewMontageDialog, SLOT(close())); QObject::connect(SelectButton, SIGNAL(clicked()), this, SLOT(SelectButtonClicked())); ViewMontageDialog->exec(); } void UI_ViewMontagewindow::SelectButtonClicked() { int signalcomps_read=0, signals_read, signal_cnt, filters_read, color, filter_cnt=0, spike_filter_cnt=0, ravg_filter_cnt=0, fidfilter_cnt=0, islpf, factor[MAXSIGNALS], signalcomps, screen_offset, order, model, type, size, polarity=1, holdoff=100; char result[XML_STRBUFLEN], composition_txt[2048], label[256]; double frequency, frequency2, voltpercm, ripple, timescale, d_tmp, velocity; QStandardItem *parentItem, *signalItem, *filterItem; struct xml_handle *xml_hdl; strcpy(mtg_path, QFileDialog::getOpenFileName(0, "Choose a montage", QString::fromLocal8Bit(mtg_dir), "Montage files (*.mtg *.MTG)").toLocal8Bit().data()); if(!strcmp(mtg_path, "")) { return; } get_directory_from_path(mtg_dir, mtg_path, MAX_PATH_LENGTH); xml_hdl = xml_get_handle(mtg_path); if(xml_hdl==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); messagewindow.exec(); return; } if(strcmp(xml_hdl->elementname[xml_hdl->level], PROGRAM_NAME "_montage")) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } ViewMontageDialog->setWindowTitle(mtg_path); t_model->clear(); parentItem = t_model->invisibleRootItem(); for(signalcomps=0; ; signalcomps++) { xml_goto_root(xml_hdl); signals_read = 0; filter_cnt = 0; ravg_filter_cnt = 0; fidfilter_cnt = 0; if(xml_goto_nth_element_inside(xml_hdl, "signalcomposition", signalcomps_read)) { break; } if(xml_goto_nth_element_inside(xml_hdl, "num_of_signals", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } signal_cnt = atoi(result); if((signal_cnt<1)||(signal_cnt>256)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "voltpercm", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } voltpercm = atof(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "screen_offset", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } screen_offset = atoi(result); xml_go_up(xml_hdl); if(!(xml_goto_nth_element_inside(xml_hdl, "polarity", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } polarity = atoi(result); if(polarity != -1) { polarity = 1; } xml_go_up(xml_hdl); } if(xml_goto_nth_element_inside(xml_hdl, "color", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } color = atoi(result); xml_go_up(xml_hdl); if(!(xml_goto_nth_element_inside(xml_hdl, "spike_filter_cnt", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } spike_filter_cnt = atoi(result); xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "filter_cnt", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } filter_cnt = atoi(result); xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "ravg_filter_cnt", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } ravg_filter_cnt = atoi(result); xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "fidfilter_cnt", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } fidfilter_cnt = atoi(result); xml_go_up(xml_hdl); } composition_txt[0] = 0; if(!(xml_goto_nth_element_inside(xml_hdl, "alias", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } if(result[0] != 0) { strcpy(composition_txt, "alias: "); strcat(composition_txt, result); strcat(composition_txt, " "); } xml_go_up(xml_hdl); } for(signals_read=0; signals_readappendRow(signalItem); sprintf(composition_txt, "amplitude: %f", voltpercm); remove_trailing_zeros(composition_txt); sprintf(composition_txt + strlen(composition_txt), "/cm offset: %f", (double)screen_offset * mainwindow->pixelsizefactor * voltpercm); remove_trailing_zeros(composition_txt); strcat(composition_txt, " color: "); switch(color) { case Qt::white : strcat(composition_txt, "white"); break; case Qt::black : strcat(composition_txt, "black"); break; case Qt::red : strcat(composition_txt, "red"); break; case Qt::darkRed : strcat(composition_txt, "dark red"); break; case Qt::green : strcat(composition_txt, "green"); break; case Qt::darkGreen : strcat(composition_txt, "dark green"); break; case Qt::blue : strcat(composition_txt, "blue"); break; case Qt::darkBlue : strcat(composition_txt, "dark blue"); break; case Qt::cyan : strcat(composition_txt, "cyan"); break; case Qt::darkCyan : strcat(composition_txt, "dark cyan"); break; case Qt::magenta : strcat(composition_txt, "magenta"); break; case Qt::darkMagenta : strcat(composition_txt, "dark magenta"); break; case Qt::yellow : strcat(composition_txt, "yellow"); break; case Qt::darkYellow : strcat(composition_txt, "dark yellow"); break; case Qt::gray : strcat(composition_txt, "gray"); break; case Qt::darkGray : strcat(composition_txt, "dark gray"); break; case Qt::lightGray : strcat(composition_txt, "light gray"); break; } signalItem->appendRow(new QStandardItem(composition_txt)); filterItem = new QStandardItem("Filters"); signalItem->appendRow(filterItem); for(filters_read=0; filters_read 10E9) velocity = 10E9; xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "holdoff", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file. (holdoff)"); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } holdoff = atoi(result); if(holdoff < 10) holdoff = 10; if(holdoff > 1000) holdoff = 1000; sprintf(composition_txt, "Spike: Velocity: %.8f", velocity); remove_trailing_zeros(composition_txt); sprintf(composition_txt + strlen(composition_txt), " Hold-off: %i milli-Sec.", holdoff); filterItem->appendRow(new QStandardItem(composition_txt)); xml_go_up(xml_hdl); xml_go_up(xml_hdl); } for(filters_read=0; filters_readappendRow(new QStandardItem(composition_txt)); xml_go_up(xml_hdl); xml_go_up(xml_hdl); } for(filters_read=0; filters_readappendRow(new QStandardItem(composition_txt)); xml_go_up(xml_hdl); xml_go_up(xml_hdl); } for(filters_read=0; filters_readappendRow(new QStandardItem(composition_txt)); xml_go_up(xml_hdl); xml_go_up(xml_hdl); } if(!xml_goto_nth_element_inside(xml_hdl, "ecg_filter", 0)) { if(xml_goto_nth_element_inside(xml_hdl, "type", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } type = atoi(result); if(type == 1) { sprintf(composition_txt, "ECG heartrate detection"); } filterItem->appendRow(new QStandardItem(composition_txt)); xml_go_up(xml_hdl); xml_go_up(xml_hdl); } if(!xml_goto_nth_element_inside(xml_hdl, "zratio_filter", 0)) { if(xml_goto_nth_element_inside(xml_hdl, "type", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } type = atoi(result); xml_go_up(xml_hdl); if(type == 1) { if(xml_goto_nth_element_inside(xml_hdl, "crossoverfreq", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } d_tmp = atof(result); sprintf(composition_txt, "Z-ratio cross-over frequency is %.1f", d_tmp); } filterItem->appendRow(new QStandardItem(composition_txt)); xml_go_up(xml_hdl); xml_go_up(xml_hdl); } signalcomps_read++; } xml_goto_root(xml_hdl); if(!(xml_goto_nth_element_inside(xml_hdl, "pagetime", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } timescale = atof(result); timescale /= TIME_DIMENSION; sprintf(composition_txt, "timescale: %f seconds", timescale); remove_trailing_zeros(composition_txt); parentItem->appendRow(new QStandardItem(composition_txt)); } xml_close(xml_hdl); tree->expandAll(); } edfbrowser_157_source/PaxHeaders.7921/print_to_bdf.h0000644000000000000000000000012712646460742017514 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/print_to_bdf.h0000644000175000001440000000275312646460742020060 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef PRINT_SCREEN_TO_BDF_H #define PRINT_SCREEN_TO_BDF_H #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "filter.h" #include "utc_date_time.h" #include "third_party/fidlib/fidlib.h" class UI_Mainwindow; void print_screen_to_bdf(UI_Mainwindow *); #endif // PRINT_SCREEN_TO_BDF_H edfbrowser_157_source/PaxHeaders.7921/mainwindow_constr.cpp0000644000000000000000000000013212646460742021136 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/mainwindow_constr.cpp0000644000175000001440000010255112646460742021503 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "mainwindow.h" UI_Mainwindow::UI_Mainwindow() { int i, j, k; setMinimumSize(640, 480); setWindowTitle(PROGRAM_NAME); setWindowIcon(QIcon(":/images/edf.png")); myfont = new QFont; monofont = new QFont; #ifdef Q_OS_WIN32 myfont->setFamily("Tahoma"); myfont->setPixelSize(11); monofont->setFamily("courier"); monofont->setPixelSize(12); #else myfont->setFamily("Arial"); myfont->setPixelSize(12); monofont->setFamily("andale mono"); monofont->setPixelSize(12); #endif QApplication::setFont(*myfont); setlocale(LC_NUMERIC, "C"); pixelsizefactor = 0.0294382; x_pixelsizefactor = 0.0294382; viewtime_indicator_type = 1; mainwindow_title_type = 1; check_for_updates = 1; use_threads = 1; auto_dpi = 1; show_annot_markers = 1; show_baselines = 1; clip_to_pane = 0; annotations_onset_relative = 1; auto_reload_mtg = 1; read_biosemi_status_signal = 1; read_nk_trigger_signal = 1; maxfilesize_to_readin_annotations = 10485760000LL; exit_in_progress = 0; live_stream_active = 0; playback_realtime_active = 0; signal_averaging_active = 0; live_stream_update_interval = 500; powerlinefreq = 50; mousewheelsens = 10; amplitude_doubler = 10; timescale_doubler = 10; default_amplitude = 100; linear_interpol = 0; recent_montagedir[0] = 0; recent_savedir[0] = 0; recent_opendir[0] = 0; recent_colordir[0] = 0; cfg_app_version[0] = 0; for(i=0; ifreq[i] = 1.0; spectrum_colorbar->color[i] = Qt::white; } spectrum_colorbar->items = 5; spectrum_colorbar->freq[0] = 4.0; spectrum_colorbar->freq[1] = 8.0; spectrum_colorbar->freq[2] = 12.0; spectrum_colorbar->freq[3] = 30.0; spectrum_colorbar->freq[4] = 100.0; spectrum_colorbar->color[0] = Qt::darkRed; spectrum_colorbar->color[1] = Qt::darkGreen; spectrum_colorbar->color[2] = Qt::darkBlue; spectrum_colorbar->color[3] = Qt::darkCyan; spectrum_colorbar->color[4] = Qt::darkMagenta; spectrum_colorbar->method = 0; spectrum_colorbar->auto_adjust = 1; spectrum_colorbar->max_colorbar_value = 10.0; maxdftblocksize = 1000; import_annotations_var = (import_annotations_var_block *)calloc(1, sizeof(struct import_annotations_var_block)); strcpy(import_annotations_var->separator, "tab"); import_annotations_var->format = 1; import_annotations_var->onsettimeformat = 0; import_annotations_var->onsetcolumn = 1; import_annotations_var->descriptioncolumn = 2; import_annotations_var->useduration = 0; import_annotations_var->durationcolumn = 3; import_annotations_var->datastartline = 1; import_annotations_var->dceventbittime = 10; import_annotations_var->triggerlevel = 500.0; import_annotations_var->manualdescription = 0; import_annotations_var->description[0] = 0; import_annotations_var->ignoreconsecutive = 0; export_annotations_var = (export_annotations_var_block *)calloc(1, sizeof(struct export_annotations_var_block)); export_annotations_var->separator = 0; export_annotations_var->format = 1; export_annotations_var->duration = 0; average_period = 0.3; average_ratio = 0; average_upsidedown = 0; average_bw = 0; spectrum_bw = 0; spectrum_sqrt = 0; spectrum_vlog = 0; spectrumdock_sqrt = 0; spectrumdock_vlog = 0; z_score_var.crossoverfreq = 7.5; z_score_var.z_threshold = 0.0; z_score_var.zscore_page_len = 30; z_score_var.zscore_error_detection = 80; z_score_var.z_hysteresis = 0.0; raw2edf_var.sf = 256; raw2edf_var.chns = 1; raw2edf_var.phys_max = 3000; raw2edf_var.straightbinary = 0; raw2edf_var.endianness = 0; raw2edf_var.samplesize = 2; raw2edf_var.offset = 0; raw2edf_var.skipblocksize = 0; raw2edf_var.skipbytes = 1; strcpy(raw2edf_var.phys_dim, "uV"); read_general_settings(); maincurve = new ViewCurve(this); dpix = maincurve->logicalDpiX(); dpiy = maincurve->logicalDpiY(); if(auto_dpi) { pixelsizefactor = 1.0 / ((double)dpiy / 2.54); x_pixelsizefactor = 1.0 / ((double)dpix / 2.54); } read_color_settings(); video_player = (struct video_player_struct *)calloc(1, sizeof(struct video_player_struct)); video_player->poll_timer = 100; live_stream_timer = new QTimer; live_stream_timer->setSingleShot(true); QObject::connect(live_stream_timer, SIGNAL(timeout()), this, SLOT(live_stream_timer_func())); video_poll_timer = new QTimer; video_poll_timer->setSingleShot(true); QObject::connect(video_poll_timer, SIGNAL(timeout()), this, SLOT(video_poll_timer_func())); playback_realtime_time = new QTime(); playback_realtime_timer = new QTimer; playback_realtime_timer->setInterval(20); QObject::connect(playback_realtime_timer, SIGNAL(timeout()), this, SLOT(playback_realtime_timer_func())); #if QT_VERSION >= 0x050000 live_stream_timer->setTimerType(Qt::PreciseTimer); video_poll_timer->setTimerType(Qt::PreciseTimer); playback_realtime_timer->setTimerType(Qt::PreciseTimer); #endif setCentralWidget(maincurve); menubar = menuBar(); recent_filesmenu = new QMenu(this); recent_filesmenu->setTitle("Recent files"); connect(recent_filesmenu, SIGNAL(triggered(QAction *)), this, SLOT(recent_file_action_func(QAction *))); close_filemenu = new QMenu(this); close_filemenu->setTitle("Close"); connect(close_filemenu, SIGNAL(triggered(QAction *)), this, SLOT(close_file_action_func(QAction *))); print_img_menu = new QMenu(this); print_img_menu->setTitle("to Image"); print_img_menu->addAction("640 x 480", this, SLOT(print_to_img_640x480())); print_img_menu->addAction("800 x 600", this, SLOT(print_to_img_800x600())); print_img_menu->addAction("1024 x 768", this, SLOT(print_to_img_1024x768())); print_img_menu->addAction("1280 x 1024", this, SLOT(print_to_img_1280x1024())); print_img_menu->addAction("1600 x 1200", this, SLOT(print_to_img_1600x1200())); printmenu = new QMenu(this); printmenu->setTitle("Print"); printmenu->addAction("to Printer", maincurve, SLOT(print_to_printer()), QKeySequence::Print); #if QT_VERSION < 0x050000 printmenu->addAction("to PostScript", maincurve, SLOT(print_to_postscript())); #endif printmenu->addAction("to PDF", maincurve, SLOT(print_to_pdf())); printmenu->addMenu(print_img_menu); printmenu->addAction("to EDF", this, SLOT(print_to_edf())); printmenu->addAction("to BDF", this, SLOT(print_to_bdf())); save_act = new QAction("Save as", this); save_act->setShortcut(QKeySequence::Save); save_act->setEnabled(false); connect(save_act, SIGNAL(triggered()), this, SLOT(save_file())); video_act = new QAction("Start video", this); connect(video_act, SIGNAL(triggered()), this, SLOT(start_stop_video())); video_act->setShortcut(QKeySequence("Ctrl+Shift+V")); filemenu = new QMenu(this); filemenu->setTitle("&File"); filemenu->addAction("Open", this, SLOT(open_new_file()), QKeySequence::Open); filemenu->addSeparator(); filemenu->addAction("Open stream", this, SLOT(open_stream()), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_O)); filemenu->addSeparator(); #ifdef Q_OS_LINUX filemenu->addAction(video_act); filemenu->addSeparator(); #endif filemenu->addAction("Playback file", this, SLOT(playback_realtime()), QKeySequence("Ctrl+Space")); filemenu->addSeparator(); filemenu->addAction(save_act); filemenu->addMenu(recent_filesmenu); filemenu->addMenu(printmenu); filemenu->addAction("Info", this, SLOT(show_file_info())); filemenu->addMenu(close_filemenu); filemenu->addAction("Close all", this, SLOT(close_all_files()), QKeySequence::Close); filemenu->addAction("Exit", this, SLOT(exit_program()), QKeySequence::Quit); menubar->addMenu(filemenu); signalmenu = new QMenu(this); signalmenu->setTitle("&Signals"); signalmenu->addAction("Properties", this, SLOT(signalproperties_dialog())); signalmenu->addAction("Add", this, SLOT(add_signals_dialog())); signalmenu->addAction("Organize", this, SLOT(organize_signals())); signalmenu->addAction("Remove all", this, SLOT(remove_all_signals())); menubar->addMenu(signalmenu); displaymenu = new QMenu(this); displaymenu->setTitle("&Timescale"); displaymenu->addAction("3 cm/sec", this, SLOT(page_3cmsec())); displaymenu->addSeparator(); page_10u = new QAction("10 uSec/page", this); displaymenu->addAction(page_10u); page_20u = new QAction("20 uSec/page", this); displaymenu->addAction(page_20u); page_50u = new QAction("50 uSec/page", this); displaymenu->addAction(page_50u); page_100u = new QAction("100 uSec/page", this); displaymenu->addAction(page_100u); page_200u = new QAction("200 uSec/page", this); displaymenu->addAction(page_200u); page_500u = new QAction("500 uSec/page", this); displaymenu->addAction(page_500u); page_1m = new QAction("1 mSec/page", this); displaymenu->addAction(page_1m); page_2m = new QAction("2 mSec/page", this); displaymenu->addAction(page_2m); page_5m = new QAction("5 mSec/page", this); displaymenu->addAction(page_5m); page_10m = new QAction("10 mSec/page", this); displaymenu->addAction(page_10m); page_20m = new QAction("20 mSec/page", this); displaymenu->addAction(page_20m); page_50m = new QAction("50 mSec/page", this); displaymenu->addAction(page_50m); page_100m = new QAction("100 mSec/page", this); displaymenu->addAction(page_100m); page_200m = new QAction("200 mSec/page", this); displaymenu->addAction(page_200m); page_500m = new QAction("500 mSec/page", this); displaymenu->addAction(page_500m); page_1 = new QAction("1 Sec/page", this); displaymenu->addAction(page_1); page_2 = new QAction("2 Sec/page", this); displaymenu->addAction(page_2); page_5 = new QAction("5 Sec/page", this); displaymenu->addAction(page_5); page_10 = new QAction("10 Sec/page", this); displaymenu->addAction(page_10); page_15 = new QAction("15 Sec/page", this); displaymenu->addAction(page_15); page_20 = new QAction("20 Sec/page", this); displaymenu->addAction(page_20); page_30 = new QAction("30 Sec/page", this); page_30->setChecked(true); displaymenu->addAction(page_30); page_60 = new QAction("60 Sec/page", this); displaymenu->addAction(page_60); page_300 = new QAction("5 min/page", this); displaymenu->addAction(page_300); page_1200 = new QAction("20 min/page", this); displaymenu->addAction(page_1200); page_3600 = new QAction("1 hour/page", this); displaymenu->addAction(page_3600); displaymenu->addSeparator(); page_div2 = new QAction("Timescale / 2", this); page_div2->setShortcut(QKeySequence::ZoomIn); connect(page_div2, SIGNAL(triggered()), this, SLOT(set_page_div2())); displaymenu->addAction(page_div2); page_mult2 = new QAction("Timescale x 2", this); page_mult2->setShortcut(QKeySequence::ZoomOut); connect(page_mult2, SIGNAL(triggered()), this, SLOT(set_page_mult2())); displaymenu->addAction(page_mult2); displaymenu->addSeparator(); page_user_defined = new QAction("user defined", this); connect(page_user_defined, SIGNAL(triggered()), this, SLOT(set_user_defined_display_time())); displaymenu->addAction(page_user_defined); displaymenu->addSeparator(); page_whole_rec = new QAction("whole recording", this); connect(page_whole_rec, SIGNAL(triggered()), this, SLOT(set_display_time_whole_rec())); displaymenu->addAction(page_whole_rec); menubar->addMenu(displaymenu); DisplayGroup = new QActionGroup(this); DisplayGroup->addAction(page_10u); DisplayGroup->addAction(page_20u); DisplayGroup->addAction(page_50u); DisplayGroup->addAction(page_100u); DisplayGroup->addAction(page_200u); DisplayGroup->addAction(page_500u); DisplayGroup->addAction(page_1m); DisplayGroup->addAction(page_2m); DisplayGroup->addAction(page_5m); DisplayGroup->addAction(page_10m); DisplayGroup->addAction(page_20m); DisplayGroup->addAction(page_50m); DisplayGroup->addAction(page_100m); DisplayGroup->addAction(page_200m); DisplayGroup->addAction(page_500m); DisplayGroup->addAction(page_1); DisplayGroup->addAction(page_2); DisplayGroup->addAction(page_5); DisplayGroup->addAction(page_10); DisplayGroup->addAction(page_15); DisplayGroup->addAction(page_20); DisplayGroup->addAction(page_30); DisplayGroup->addAction(page_60); DisplayGroup->addAction(page_300); DisplayGroup->addAction(page_1200); DisplayGroup->addAction(page_3600); connect(DisplayGroup, SIGNAL(triggered(QAction *)), this, SLOT(set_display_time(QAction *))); amplitudemenu = new QMenu(this); amplitudemenu->setTitle("&Amplitude"); fit_to_pane = new QAction("Fit to pane", this); connect(fit_to_pane, SIGNAL(triggered()), this, SLOT(fit_signals_to_pane())); amplitudemenu->addAction(fit_to_pane); fit_to_dc = new QAction("Adjust offset", this); connect(fit_to_dc, SIGNAL(triggered()), this, SLOT(fit_signals_dc_offset())); amplitudemenu->addAction(fit_to_dc); amplitudemenu->addAction("Offset -> 0", this, SLOT(set_dc_offset_to_zero())); amplitudemenu->addSeparator(); amp_50000 = new QAction("50000", this); amplitudemenu->addAction(amp_50000); amp_20000 = new QAction("20000", this); amplitudemenu->addAction(amp_20000); amp_10000 = new QAction("10000", this); amplitudemenu->addAction(amp_10000); amp_5000 = new QAction("5000", this); amplitudemenu->addAction(amp_5000); amp_2000 = new QAction("2000", this); amplitudemenu->addAction(amp_2000); amp_1000 = new QAction("1000", this); amplitudemenu->addAction(amp_1000); amp_500 = new QAction("500", this); amplitudemenu->addAction(amp_500); amp_200 = new QAction("200", this); amplitudemenu->addAction(amp_200); amp_100 = new QAction("100 (50uV/5mm)", this); amplitudemenu->addAction(amp_100); amp_50 = new QAction("50", this); amplitudemenu->addAction(amp_50); amp_20 = new QAction("20", this); amplitudemenu->addAction(amp_20); amp_10 = new QAction("10", this); amplitudemenu->addAction(amp_10); amp_5 = new QAction("5", this); amplitudemenu->addAction(amp_5); amp_2 = new QAction("2", this); amplitudemenu->addAction(amp_2); amp_1 = new QAction("1", this); amplitudemenu->addAction(amp_1); amp_05 = new QAction("0.5", this); amplitudemenu->addAction(amp_05); amp_02 = new QAction("0.2", this); amplitudemenu->addAction(amp_02); amp_01 = new QAction("0.1", this); amplitudemenu->addAction(amp_01); amp_005 = new QAction("0.05", this); amplitudemenu->addAction(amp_005); amp_002 = new QAction("0.02", this); amplitudemenu->addAction(amp_002); amp_001 = new QAction("0.01", this); amplitudemenu->addAction(amp_001); amp_0005 = new QAction("0.005", this); amplitudemenu->addAction(amp_0005); amp_0002 = new QAction("0.002", this); amplitudemenu->addAction(amp_0002); amp_0001 = new QAction("0.001", this); amplitudemenu->addAction(amp_0001); amp_00005 = new QAction("0.0005", this); amplitudemenu->addAction(amp_00005); amp_00002 = new QAction("0.0002", this); amplitudemenu->addAction(amp_00002); amp_00001 = new QAction("0.0001", this); amplitudemenu->addAction(amp_00001); amplitudemenu->addSeparator(); amp_plus = new QAction("Amplitude x 2", this); amp_plus->setShortcut(Qt::Key_Minus); connect(amp_plus, SIGNAL(triggered()), this, SLOT(set_amplitude_mult2())); amplitudemenu->addAction(amp_plus); amp_minus = new QAction("Amplitude / 2", this); amp_minus->setShortcut(Qt::Key_Plus); connect(amp_minus, SIGNAL(triggered()), this, SLOT(set_amplitude_div2())); amplitudemenu->addAction(amp_minus); menubar->addMenu(amplitudemenu); AmplitudeGroup = new QActionGroup(this); AmplitudeGroup->addAction(amp_00001); AmplitudeGroup->addAction(amp_00002); AmplitudeGroup->addAction(amp_00005); AmplitudeGroup->addAction(amp_0001); AmplitudeGroup->addAction(amp_0002); AmplitudeGroup->addAction(amp_0005); AmplitudeGroup->addAction(amp_001); AmplitudeGroup->addAction(amp_002); AmplitudeGroup->addAction(amp_005); AmplitudeGroup->addAction(amp_01); AmplitudeGroup->addAction(amp_02); AmplitudeGroup->addAction(amp_05); AmplitudeGroup->addAction(amp_1); AmplitudeGroup->addAction(amp_2); AmplitudeGroup->addAction(amp_5); AmplitudeGroup->addAction(amp_10); AmplitudeGroup->addAction(amp_20); AmplitudeGroup->addAction(amp_50); AmplitudeGroup->addAction(amp_100); AmplitudeGroup->addAction(amp_200); AmplitudeGroup->addAction(amp_500); AmplitudeGroup->addAction(amp_1000); AmplitudeGroup->addAction(amp_2000); AmplitudeGroup->addAction(amp_5000); AmplitudeGroup->addAction(amp_10000); AmplitudeGroup->addAction(amp_20000); AmplitudeGroup->addAction(amp_50000); connect(AmplitudeGroup, SIGNAL(triggered(QAction *)), this, SLOT(set_amplitude(QAction *))); filtermenu = new QMenu(this); filtermenu->setTitle("&Filter"); filtermenu->addAction("New", this, SLOT(add_new_filter())); filtermenu->addAction("Adjust", this, SLOT(filterproperties_dialog())); filtermenu->addAction("Remove all", this, SLOT(remove_all_filters())); filtermenu->addSeparator(); filtermenu->addAction("Spike", this, SLOT(add_spike_filter())); filtermenu->addAction("Remove all spike filters", this, SLOT(remove_all_spike_filters())); menubar->addMenu(filtermenu); // math_func_menu = new QMenu(this); // math_func_menu->setTitle("&Math"); // math_func_menu->addAction("New", this, SLOT(add_new_math_func())); // math_func_menu->addAction("Remove all", this, SLOT(remove_all_math_funcs())); // menubar->addMenu(math_func_menu); load_predefined_mtg_act[0] = new QAction("Empty", this); load_predefined_mtg_act[0]->setShortcut(Qt::Key_F1); load_predefined_mtg_act[1] = new QAction("Empty", this); load_predefined_mtg_act[1]->setShortcut(Qt::Key_F2); load_predefined_mtg_act[2] = new QAction("Empty", this); load_predefined_mtg_act[2]->setShortcut(Qt::Key_F3); load_predefined_mtg_act[3] = new QAction("Empty", this); load_predefined_mtg_act[3]->setShortcut(Qt::Key_F4); load_predefined_mtg_act[4] = new QAction("Empty", this); load_predefined_mtg_act[4]->setShortcut(Qt::Key_F5); load_predefined_mtg_act[5] = new QAction("Empty", this); load_predefined_mtg_act[5]->setShortcut(Qt::Key_F6); load_predefined_mtg_act[6] = new QAction("Empty", this); load_predefined_mtg_act[6]->setShortcut(Qt::Key_F7); load_predefined_mtg_act[7] = new QAction("Empty", this); load_predefined_mtg_act[7]->setShortcut(Qt::Key_F8); load_predefined_mtg_act[8] = new QAction("Empty", this); load_predefined_mtg_act[8]->setShortcut(Qt::Key_F9); load_predefined_mtg_act[9] = new QAction("Empty", this); load_predefined_mtg_act[9]->setShortcut(Qt::Key_F10); load_predefined_mtg_act[10] = new QAction("Empty", this); load_predefined_mtg_act[10]->setShortcut(Qt::Key_F11); load_predefined_mtg_act[11] = new QAction("Empty", this); load_predefined_mtg_act[11]->setShortcut(Qt::Key_F12); load_predefined_mtg_group = new QActionGroup(this); for(i=0; i < MAXPREDEFINEDMONTAGES; i++) { load_predefined_mtg_group->addAction(load_predefined_mtg_act[i]); } connect(load_predefined_mtg_group, SIGNAL(triggered(QAction *)), this, SLOT(load_predefined_mtg(QAction *))); montagemenu = new QMenu(this); montagemenu->setTitle("&Montage"); montagemenu->addAction("View this montage", this, SLOT(show_this_montage())); montagemenu->addAction("View saved montages", this, SLOT(view_montage())); montagemenu->addAction("Save", this, SLOT(save_montage())); montagemenu->addAction("Load", this, SLOT(load_montage())); montagemenu->addSeparator(); montagemenu->addAction("Edit key-bindings for montages", this, SLOT(edit_predefined_montages())); montagemenu->addSeparator(); for(i=0; i < MAXPREDEFINEDMONTAGES; i++) { montagemenu->addAction(load_predefined_mtg_act[i]); } menubar->addMenu(montagemenu); // patternmenu = new QMenu(this); // patternmenu->setTitle("&Pattern"); // patternmenu->addAction("Search", this, SLOT(search_pattern())); // menubar->addMenu(patternmenu); toolsmenu = new QMenu(this); toolsmenu->setTitle("T&ools"); toolsmenu->addAction("Check EDF/BDF compatibility", this, SLOT(check_edf_compatibility())); toolsmenu->addSeparator(); toolsmenu->addAction("Header editor", this, SLOT(edit_header())); toolsmenu->addAction("Reduce signals, duration or samplerate", this, SLOT(reduce_signals())); toolsmenu->addAction("Remove duplicates in annotations", this, SLOT(edfplus_annotation_remove_duplicates())); toolsmenu->addSeparator(); toolsmenu->addAction("Import annotations/events", this, SLOT(import_annotations())); toolsmenu->addAction("Export annotations/events", this, SLOT(export_annotations())); toolsmenu->addAction("Export EDF/BDF to ASCII", this, SLOT(export_to_ascii())); toolsmenu->addAction("Export/Import ECG RR-interval", this, SLOT(export_ecg_rr_interval_to_ascii())); toolsmenu->addSeparator(); toolsmenu->addAction("Convert Nihon Kohden to EDF+", this, SLOT(nk2edf_converter())); toolsmenu->addAction("Convert ASCII to EDF/BDF", this, SLOT(convert_ascii_to_edf())); toolsmenu->addAction("Convert Manscan to EDF+", this, SLOT(convert_manscan_to_edf())); toolsmenu->addAction("Convert SCP ECG to EDF+", this, SLOT(convert_scpecg_to_edf())); toolsmenu->addAction("Convert MIT to EDF+", this, SLOT(convert_mit_to_edf())); toolsmenu->addAction("Convert Finometer to EDF", this, SLOT(convert_fino_to_edf())); toolsmenu->addAction("Convert Nexfin to EDF", this, SLOT(convert_nexfin_to_edf())); toolsmenu->addAction("Convert Emsa to EDF+", this, SLOT(convert_emsa_to_edf())); toolsmenu->addAction("Convert EDF+D to EDF+C", this, SLOT(edfd_converter())); toolsmenu->addAction("Convert Biosemi to BDF+", this, SLOT(biosemi2bdfplus_converter())); toolsmenu->addAction("Convert BDF to EDF", this, SLOT(bdf2edf_converter())); toolsmenu->addAction("Convert Unisens to EDF+", this, SLOT(unisens2edf_converter())); toolsmenu->addAction("Convert BI9800TL+3 to EDF", this, SLOT(BI98002edf_converter())); toolsmenu->addAction("Convert Wave to EDF", this, SLOT(convert_wave_to_edf())); 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 Binary/raw data to EDF", this, SLOT(convert_binary_to_edf())); toolsmenu->addSeparator(); toolsmenu->addAction("Options", this, SLOT(show_options_dialog())); menubar->addMenu(toolsmenu); menubar->addAction("S&ettings", this, SLOT(show_options_dialog())); former_page_Act = new QAction("<<", this); former_page_Act->setShortcut(QKeySequence::MoveToPreviousPage); connect(former_page_Act, SIGNAL(triggered()), this, SLOT(former_page())); menubar->addAction(former_page_Act); shift_page_left_Act = new QAction("<", this); shift_page_left_Act->setShortcut(QKeySequence::MoveToPreviousChar); connect(shift_page_left_Act, SIGNAL(triggered()), this, SLOT(shift_page_left())); menubar->addAction(shift_page_left_Act); playback_realtime_Act = new QAction("[play]", this); connect(playback_realtime_Act, SIGNAL(triggered()), this, SLOT(playback_realtime())); menubar->addAction(playback_realtime_Act); shift_page_right_Act = new QAction(">", this); shift_page_right_Act->setShortcut(QKeySequence::MoveToNextChar); connect(shift_page_right_Act, SIGNAL(triggered()), this, SLOT(shift_page_right())); menubar->addAction(shift_page_right_Act); next_page_Act = new QAction(">>", this); next_page_Act->setShortcut(QKeySequence::MoveToNextPage); connect(next_page_Act, SIGNAL(triggered()), this, SLOT(next_page())); menubar->addAction(next_page_Act); shift_page_up_Act = new QAction("^", this); shift_page_up_Act->setShortcut(QKeySequence::MoveToPreviousLine); connect(shift_page_up_Act, SIGNAL(triggered()), this, SLOT(shift_page_up())); menubar->addAction(shift_page_up_Act); shift_page_down_Act = new QAction("v", this); shift_page_down_Act->setShortcut(QKeySequence::MoveToNextLine); connect(shift_page_down_Act, SIGNAL(triggered()), this, SLOT(shift_page_down())); menubar->addAction(shift_page_down_Act); zoomback_Act = new QAction("zoomback", this); zoomback_Act->setShortcut(Qt::Key_Backspace); connect(zoomback_Act, SIGNAL(triggered()), this, SLOT(zoomback())); menubar->addAction(zoomback_Act); zoomforward_Act = new QAction("zoomforward", this); zoomforward_Act->setShortcut(Qt::Key_Insert); connect(zoomforward_Act, SIGNAL(triggered()), this, SLOT(forward())); menubar->addAction(zoomforward_Act); no_timesync_act = new QAction("no timelock", this); no_timesync_act->setCheckable(true); offset_timesync_act = new QAction("synchronize start of files (offset)", this); offset_timesync_act->setCheckable(true); absolut_timesync_act = new QAction("synchronize absolute time", this); absolut_timesync_act->setCheckable(true); user_def_sync_act = new QAction("user defined synchronizing", this); user_def_sync_act->setCheckable(true); timelock_act_group = new QActionGroup(this); timelock_act_group->addAction(no_timesync_act); timelock_act_group->addAction(offset_timesync_act); timelock_act_group->addAction(absolut_timesync_act); timelock_act_group->addAction(user_def_sync_act); absolut_timesync_act->setChecked(true); connect(timelock_act_group, SIGNAL(triggered(QAction *)), this, SLOT(set_timesync(QAction *))); sel_viewtime_act_group = new QActionGroup(this); connect(sel_viewtime_act_group, SIGNAL(triggered(QAction *)), this, SLOT(set_timesync_reference(QAction *))); timemenu = new QMenu(this); timemenu->setTitle("T&imesync"); timemenu->addAction("Go to start of file", this, SLOT(jump_to_start()), QKeySequence::MoveToStartOfDocument); timemenu->addAction("Go to end of file", this, SLOT(jump_to_end()), QKeySequence::MoveToEndOfDocument); timemenu->addAction("Jump to", this, SLOT(jump_to_dialog())); timemenu->addSeparator()->setText("Timelock"); timemenu->addAction(no_timesync_act); timemenu->addAction(offset_timesync_act); timemenu->addAction(absolut_timesync_act); timemenu->addAction(user_def_sync_act); timemenu->addSeparator(); timemenu->addAction("synchronize by crosshairs", this, SLOT(sync_by_crosshairs())); timemenu->addSeparator()->setText("Time reference"); menubar->addMenu(timemenu); windowmenu = new QMenu(this); windowmenu->setTitle("&Window"); windowmenu->addAction("Annotations", this, SLOT(show_annotations())); windowmenu->addAction("Annotation editor", this, SLOT(annotation_editor())); windowmenu->addAction("Power Spectrum", this, SLOT(show_spectrum_dock())); menubar->addMenu(windowmenu); helpmenu = new QMenu(this); helpmenu->setTitle("&Help"); #ifdef Q_OS_LINUX helpmenu->addAction("Manual", this, SLOT(show_help())); #endif #ifdef Q_OS_WIN32 helpmenu->addAction("Manual", this, SLOT(show_help())); #endif helpmenu->addAction("Keyboard shortcuts", this, SLOT(show_kb_shortcuts())); helpmenu->addAction("About EDFbrowser", this, SLOT(show_about_dialog())); helpmenu->addAction("Show splashscreen", this, SLOT(show_splashscreen())); menubar->addMenu(helpmenu); Escape_act = new QAction(this); Escape_act->setShortcut(Qt::Key_Escape); connect(Escape_act, SIGNAL(triggered()), this, SLOT(Escape_fun())); maincurve->addAction(Escape_act); positionslider = new QSlider(Qt::Horizontal); positionslider->setRange(0, 1000000); positionslider->setSingleStep(10000); positionslider->setPageStep(100000); video_pause_act = new QAction("Play", this); connect(video_pause_act, SIGNAL(triggered()), this, SLOT(video_player_toggle_pause())); video_pause_act->setToolTip("Play video"); video_stop_act = new QAction("Stop", this); connect(video_stop_act, SIGNAL(triggered()), this, SLOT(start_stop_video())); video_stop_act->setToolTip("Stop video"); slidertoolbar = new QToolBar(); slidertoolbar->setFloatable(false); slidertoolbar->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea); #ifdef Q_OS_LINUX slidertoolbar->addAction(video_stop_act); slidertoolbar->addAction(video_pause_act); #endif slidertoolbar->addWidget(positionslider); addToolBar(Qt::BottomToolBarArea, slidertoolbar); QObject::connect(positionslider, SIGNAL(valueChanged(int)), this, SLOT(slider_moved(int))); slidertoolbar->setEnabled(false); positionslider->blockSignals(true); files_open = 0; signalcomps = 0; sel_viewtime = 0; viewtime_sync = VIEWTIME_SYNCED_ABSOLUT; pagetime = 10 * TIME_DIMENSION; viewtime_string[0] = 0; pagetime_string[0] = 0; totalviewbufsize = 0; print_to_edf_active = 0; annot_editor_active = 0; annotations_edited = 0; viewbuf = NULL; for(i=0; ihistory_size_tail = 0; zoomhistory->history_size_front = 0; for(i=0; i<64; i++) { zoomhistory->pntr = 0; zoomhistory->pagetime[i] = 10 * TIME_DIMENSION; for(j=0; jviewtime[i][j] = 0; } for(j=0; jvoltpercm[i][j] = 70.0; zoomhistory->screen_offset[i][j] = 0.0; for(k=0; ksensitivity[i][j][k] = 0.0475; } } } path[0] = 0; recent_montagedir[0] = 0; recent_savedir[0] = 0; recent_opendir[0] = 0; montagepath[0] = 0; option_str[0] = 0; for(i=0; isetText(predefined_mtg_path[i]); } } annotationEditDock = new UI_AnnotationEditwindow(files_open, this); addDockWidget(Qt::BottomDockWidgetArea, annotationEditDock->dockedit, Qt::Horizontal); annotationEditDock->dockedit->hide(); for(i=0; idock, Qt::Horizontal); spectrumdock[i]->dock->hide(); } setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); setCorner(Qt::BottomLeftCorner, Qt::BottomDockWidgetArea); setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea); char tmp_str[MAX_PATH_LENGTH]; cmdlineargument = 0; cmdlineoption = 0; if(QCoreApplication::arguments().size()>1) { strcpy(tmp_str, QCoreApplication::arguments().at(1).toLocal8Bit().data()); if((strlen(tmp_str) > 2) && (!strncmp(tmp_str, "--", 2))) { strcpy(option_str, tmp_str); cmdlineoption++; } else { strcpy(path, tmp_str); cmdlineargument++; } if(QCoreApplication::arguments().size()>2) { strcpy(tmp_str, QCoreApplication::arguments().at(2).toLocal8Bit().data()); if(!cmdlineargument) { strcpy(path, tmp_str); } else { strcpy(montagepath, tmp_str); } cmdlineargument++; if(cmdlineargument == 1) { if(QCoreApplication::arguments().size()>3) { strcpy(montagepath, QCoreApplication::arguments().at(3).toLocal8Bit().data()); cmdlineargument++; } } } } showMaximized(); oldwindowheight = height(); if(cmdlineargument) { if(cmdlineoption) { if(!strcmp(option_str, "--stream")) { open_stream(); } } else { open_new_file(); } } if(QT_VERSION < MINIMUM_QT_VERSION) { QMessageBox messagewindow(QMessageBox::Warning, "Warning", "Qt version is too old"); messagewindow.exec(); } else { int v_nr; char v_str[32]; strncpy(v_str, qVersion(), 32); v_str[31] = 0; v_nr = 0x10000 * atoi(v_str); v_nr += 0x100 * atoi(v_str + 2); v_nr += atoi(v_str + 4); if(v_nr < MINIMUM_QT_VERSION) { QMessageBox messagewindow(QMessageBox::Warning, "Warning", "Qt version is too old"); messagewindow.exec(); } } pixmap = new QPixmap(":/images/splash.png"); splash = new QSplashScreen(this, *pixmap, Qt::WindowStaysOnTopHint); update_checker = NULL; if(check_for_updates) { update_checker = new Check_for_updates; } } edfbrowser_157_source/PaxHeaders.7921/reduce_signals.h0000644000000000000000000000013212646460742020026 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/reduce_signals.h0000644000175000001440000000605612646460742020376 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_REDUCESIGNALSFORM_H #define UI_REDUCESIGNALSFORM_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "check_edf_file.h" #include "utils.h" #include "utc_date_time.h" #include "active_file_chooser.h" #include "edf_annot_list.h" #include "ravg_filter.h" #define REDUCER_MAX_AA_FILTERS 4 class UI_Mainwindow; class UI_ReduceSignalsWindow : public QObject { Q_OBJECT public: UI_ReduceSignalsWindow(QWidget *parent); UI_Mainwindow *mainwindow; private: QLabel *label1, *label2, *label3, *label4, *label5, *label6; QPushButton *pushButton1, *pushButton2, *pushButton3, *pushButton4, *pushButton5, *pushButton6; QSpinBox *spinBox1, *spinBox2, *spinBox3, *spinBox4; QRadioButton *radioButton1, *radioButton2; QTableWidget *SignalsTablewidget; QDialog *myobjectDialog; int signalslist[MAXSIGNALS], dividerlist[MAXSIGNALS], file_num, aa_filter_order; char inputpath[MAX_PATH_LENGTH], outputpath[MAX_PATH_LENGTH], *recent_savedir; FILE *inputfile, *outputfile; struct edfhdrblock *edfhdr; struct ravg_filter_settings *filterlist[MAXSIGNALS][REDUCER_MAX_AA_FILTERS]; void showpopupmessage(const char *, const char *); private slots: void SelectFileButton(); void StartConversion(); void Select_all_signals(); void Deselect_all_signals(); void Set_SRdivider_all_signals(); void spinBox1changed(int); void spinBox2changed(int); void radioButton1Toggled(bool); void radioButton2Toggled(bool); }; #endif edfbrowser_157_source/PaxHeaders.7921/averager_curve_wnd.h0000644000000000000000000000013212646460742020707 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/averager_curve_wnd.h0000644000175000001440000000576712646460742021267 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef AVERAGERCURVEWND_H #define AVERAGERCURVEWND_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "signalcurve.h" #include "edflib.h" #include "utils.h" #include "flywheel.h" class UI_Mainwindow; class UI_AverageCurveWindow : public QWidget { Q_OBJECT public: UI_AverageCurveWindow(struct signalcompblock *, QWidget *, int, double *, double, double, long long, long long, int, int, char *, double); ~UI_AverageCurveWindow(); UI_Mainwindow *mainwindow; QDialog *averager_curve_dialog; struct signalcompblock *signalcomp; private: int averager_curve_dialog_is_destroyed, class_is_deleted, averagecurvedialognumber, avg_cnt, avg_trigger_position_ratio, flywheel_value; double pagetime, *avgbuf, avg_max_value, avg_min_value, avg_period; long long avg_samples_on_screen; char avg_annotation[MAX_ANNOTATION_LEN + 1]; QHBoxLayout *hlayout1, *hlayout2, *hlayout3, *hlayout4; QVBoxLayout *vlayout1, *vlayout2, *vlayout3; SignalCurve *curve1; QSlider *amplitudeSlider, *spanSlider, *centerSlider; QLabel *spanLabel, *centerLabel, *amplitudeLabel; QCheckBox *inversionCheckBox, *BWCheckBox; UI_Flywheel *flywheel1; private slots: void sliderMoved(int); void averager_curve_dialogDestroyed(QObject *); void export_edf(void); void update_flywheel(int); }; #endif edfbrowser_157_source/PaxHeaders.7921/filter.cpp0000644000000000000000000000013212646460742016657 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/filter.cpp0000644000175000001440000000634712646460742017232 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "filter.h" struct filter_settings * create_filter(int is_LPF, double cutoff_frequency, double sample_frequency) { struct filter_settings *settings; settings = (struct filter_settings *) calloc(1, sizeof(struct filter_settings)); if(settings==NULL) return(NULL); settings->is_LPF = is_LPF; settings->cutoff_frequency = cutoff_frequency; settings->sample_frequency = sample_frequency; settings->factor = get_filter_factor(cutoff_frequency, sample_frequency); settings->old_input = 0.0; settings->old_output = 0.0; settings->first_sample = 1; return(settings); } struct filter_settings * create_filter_copy(struct filter_settings *src) { struct filter_settings *settings; settings = (struct filter_settings *)calloc(1, sizeof(struct filter_settings)); if(settings==NULL) { return(NULL); } memcpy(settings, src, sizeof(struct filter_settings)); return(settings); } void reset_filter(int offset, struct filter_settings *settings) { settings->first_sample = 0; settings->old_input = offset; if(settings->is_LPF) { settings->old_output = offset; } else { settings->old_output = 0.0; } } int first_order_filter(int new_input, struct filter_settings *settings) { double new_output; if(settings->first_sample) { settings->first_sample = 0; settings->old_input = new_input; if(settings->is_LPF) { settings->old_output = new_input; return(new_input); } else { settings->old_output = 0.0; return(0); } } if(settings->is_LPF) { new_output = settings->old_output + ((settings->old_input - settings->old_output) * settings->factor); } else { new_output = settings->old_output * (1.0 - settings->factor); new_output += new_input - settings->old_input; } settings->old_input = new_input; settings->old_output = new_output; return((int)new_output); } double get_filter_factor(double cutoff_frequency, double sample_frequency) { double t; t = (cutoff_frequency * 2.0 * M_PI) / sample_frequency; t = exp(-t); t = 1.0 - t; // now t will be in the range 0.001 (at high sample-frequency and low cut-off) // to 0.999 (at low sample-frequency and high cut-off) return(t); } edfbrowser_157_source/PaxHeaders.7921/jump_dialog.h0000644000000000000000000000012712646460742017335 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/jump_dialog.h0000644000175000001440000000407512646460742017700 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef JUMPMENUFORM1_H #define JUMPMENUFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" class UI_Mainwindow; class UI_JumpMenuDialog : public QObject { Q_OBJECT public: UI_JumpMenuDialog(QWidget *parent=0); UI_Mainwindow *mainwindow; private: QDialog *jump_dialog; QPushButton *CloseButton, *jumpButton; QLabel *label1, *label2, *label3; QTimeEdit *timeEdit1, *timeEdit2; QTime time1, time2; QSpinBox *daybox1, *daybox2; long long recording_duration, starttime; private slots: void jumpbutton_pressed(); void absolutetime_changed(const QTime &); void offsettime_changed(const QTime &); void absoluteday_changed(int); void offsetday_changed(int); }; #endif // JUMPMENUFORM1_H edfbrowser_157_source/PaxHeaders.7921/statistics_dialog.cpp0000644000000000000000000000013212646460742021103 xustar0030 mtime=1452958178.249246726 30 atime=1452958178.249246726 30 ctime=1452958178.249246726 edfbrowser_157_source/statistics_dialog.cpp0000644000175000001440000002704412646460742021453 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "statistics_dialog.h" UI_StatisticWindow::UI_StatisticWindow(struct signalcompblock *signalcomp, long long pagetime) { int i, tmp, NN50, pNN50; char stat_str[2048]; double d_tmp, average_bpm, average_rr, sdnn_bpm, sdnn_rr, *buf_bpm, rmssd_rr, *beat_interval_list; StatDialog = new QDialog; StatDialog->setWindowTitle("Statistics"); StatDialog->setModal(true); StatDialog->setAttribute(Qt::WA_DeleteOnClose, true); StatDialog->setWindowFlags(Qt::Window | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); StatDialog->setWindowIcon(QIcon(":/images/edf.png")); if(signalcomp->ecg_filter != NULL) { StatDialog->setMinimumSize(600, 400); StatDialog->setSizeGripEnabled(true); startSlider = new QSlider; startSlider->setOrientation(Qt::Horizontal); startSlider->setMinimum(0); startSlider->setMaximum(295); startSlider->setValue(0); stopSlider = new QSlider; stopSlider->setOrientation(Qt::Horizontal); stopSlider->setMinimum(5); stopSlider->setMaximum(300); stopSlider->setValue(300); curve1 = new SignalCurve(StatDialog); curve1->setSignalColor(Qt::darkGreen); curve1->setBackgroundColor(Qt::black); curve1->setRasterColor(Qt::gray); curve1->setTraceWidth(0); curve1->setH_label(signalcomp->physdimension); curve1->setLowerLabel("HR (beats/min)"); curve1->setDashBoardEnabled(false); curve1->setUpperLabel1("Distribution"); curve1->setFillSurfaceEnabled(true); vlayout2_1 = new QVBoxLayout; vlayout2_1->setSpacing(20); vlayout2_1->addWidget(curve1); vlayout2_1->addWidget(startSlider); vlayout2_1->addWidget(stopSlider); } else { StatDialog->setMinimumSize(300, 400); StatDialog->setMaximumSize(300, 400); } Label1 = new QLabel(StatDialog); Label1->setAlignment(Qt::AlignLeft | Qt::AlignTop); pushButton1 = new QPushButton(StatDialog); pushButton1->setMinimumSize(100, 25); pushButton1->setText("&Close"); hlayout1_1_1 = new QHBoxLayout; hlayout1_1_1->addWidget(pushButton1); hlayout1_1_1->addStretch(100); vlayout1_1 = new QVBoxLayout; vlayout1_1->setSpacing(20); vlayout1_1->addWidget(Label1); vlayout1_1->addStretch(100); vlayout1_1->addLayout(hlayout1_1_1); hlayout1 = new QHBoxLayout; hlayout1->addLayout(vlayout1_1, 1); if(signalcomp->ecg_filter != NULL) { hlayout1->addLayout(vlayout2_1, 100); } StatDialog->setLayout(hlayout1); QObject::connect(pushButton1, SIGNAL(clicked()), StatDialog, SLOT(close())); for(i=0; i<300; i++) { bpm_distribution[i] = 0; } if(signalcomp->ecg_filter == NULL) { if((signalcomp->stat_cnt < 1) || (pagetime < 10LL)) { if(signalcomp->alias[0] != 0) { sprintf(stat_str, "Signal: %s\n\nSamples: 0\n\nSum: 0 %s\n\nMean: 0 %s\n\nRMS: 0 %s\n\nMRS: 0 %s\n\nZero crossings: 0\n\nFrequency: 0 Hz", signalcomp->alias, signalcomp->physdimension, signalcomp->physdimension, signalcomp->physdimension, signalcomp->physdimension); } else { sprintf(stat_str, "Signal: %s\n\nSamples: 0\n\nSum: 0 %s\n\nMean: 0 %s\n\nRMS: 0 %s\n\nMRS: 0 %s\n\nZero crossings: 0\n\nFrequency: 0 Hz", signalcomp->signallabel, signalcomp->physdimension, signalcomp->physdimension, signalcomp->physdimension, signalcomp->physdimension); } } else { if(signalcomp->alias[0] != 0) { sprintf(stat_str, "Signal: %s\n\nSamples: %i\n\nSum: %f %s\n\nMean: %f %s\n\nRMS: %f %s\n\nMRS: %f %s\n\nZero crossings: %i\n\nFrequency: %f Hz", signalcomp->alias, signalcomp->stat_cnt, signalcomp->stat_sum * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue, signalcomp->physdimension, (signalcomp->stat_sum * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue) / signalcomp->stat_cnt, signalcomp->physdimension, sqrt(signalcomp->stat_sum_sqr / signalcomp->stat_cnt) * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue, signalcomp->physdimension, (signalcomp->stat_sum_rectified / signalcomp->stat_cnt) * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue, signalcomp->physdimension, signalcomp->stat_zero_crossing_cnt, (((double)signalcomp->stat_zero_crossing_cnt / 2.0)) / ((double)pagetime / (double)TIME_DIMENSION) ); } else { sprintf(stat_str, "Signal: %s\n\nSamples: %i\n\nSum: %f %s\n\nMean: %f %s\n\nRMS: %f %s\n\nMRS: %f %s\n\nZero crossings: %i\n\nFrequency: %f Hz", signalcomp->signallabel, signalcomp->stat_cnt, signalcomp->stat_sum * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue, signalcomp->physdimension, (signalcomp->stat_sum * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue) / signalcomp->stat_cnt, signalcomp->physdimension, sqrt(signalcomp->stat_sum_sqr / signalcomp->stat_cnt) * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue, signalcomp->physdimension, (signalcomp->stat_sum_rectified / signalcomp->stat_cnt) * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue, signalcomp->physdimension, signalcomp->stat_zero_crossing_cnt, (((double)signalcomp->stat_zero_crossing_cnt / 2.0)) / ((double)pagetime / (double)TIME_DIMENSION) ); } } } else { beat_cnt = ecg_filter_get_beat_cnt(signalcomp->ecg_filter); beat_interval_list = ecg_filter_get_interval_beatlist(signalcomp->ecg_filter); if(beat_cnt < 3) { sprintf(stat_str, "Not enough beats."); } else { average_bpm = 0.0; average_rr = 0.0; sdnn_bpm = 0.0; sdnn_rr = 0.0; rmssd_rr = 0.0; NN50 = 0; buf_bpm = (double *)malloc(sizeof(double) * beat_cnt); if(buf_bpm == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); messagewindow.exec(); return; } for(i=0; i 0.05 ) || ((beat_interval_list[i + 1] - beat_interval_list[i]) > 0.05 )) { NN50++; } } } average_bpm /= beat_cnt; average_rr /= beat_cnt; rmssd_rr /= beat_cnt; rmssd_rr = sqrt(rmssd_rr); pNN50 = (NN50 * 100) / (beat_cnt - 1); for(i=0; i 0) && (tmp < 301)) { bpm_distribution[tmp-1]++; } } max_val = 1; for(i=0; i<300; i++) { if(bpm_distribution[i] > max_val) { max_val = bpm_distribution[i]; } } for(i=0; i<300; i++) { if(bpm_distribution[i] > (max_val / 70)) { start_ruler = i; break; } } for(i=299; i>=0; i--) { if(bpm_distribution[i] > (max_val / 70)) { end_ruler = i + 1; if(end_ruler > 300) { end_ruler = 300; } break; } } if(start_ruler >= end_ruler) { start_ruler = 0; end_ruler = 300; } startSlider->setValue(start_ruler); stopSlider->setValue(end_ruler); curve1->setH_RulerValues(start_ruler + 1, end_ruler + 1); curve1->drawCurve(bpm_distribution + start_ruler, end_ruler - start_ruler, (int)(max_val * 1.1) + 1, 0.0); QObject::connect(startSlider, SIGNAL(valueChanged(int)), this, SLOT(startSliderMoved(int))); QObject::connect(stopSlider, SIGNAL(valueChanged(int)), this, SLOT(stopSliderMoved(int))); } } Label1->setText(stat_str); StatDialog->exec(); } void UI_StatisticWindow::startSliderMoved(int) { startSlider->blockSignals(true); stopSlider->blockSignals(true); start_ruler = startSlider->value(); end_ruler = stopSlider->value(); if(end_ruler < (start_ruler + 5)) { end_ruler = start_ruler + 5; stopSlider->setValue(end_ruler); } curve1->setH_RulerValues(start_ruler + 1, end_ruler + 1); curve1->drawCurve(bpm_distribution + start_ruler, end_ruler - start_ruler, (int)(max_val * 1.1) + 1, 0.0); startSlider->blockSignals(false); stopSlider->blockSignals(false); } void UI_StatisticWindow::stopSliderMoved(int) { startSlider->blockSignals(true); stopSlider->blockSignals(true); start_ruler = startSlider->value(); end_ruler = stopSlider->value(); if(start_ruler > (end_ruler - 5)) { start_ruler = end_ruler - 5; startSlider->setValue(start_ruler); } curve1->setH_RulerValues(start_ruler + 1, end_ruler + 1); curve1->drawCurve(bpm_distribution + start_ruler, end_ruler - start_ruler, (int)(max_val * 1.1) + 1, 0.0); startSlider->blockSignals(false); stopSlider->blockSignals(false); } edfbrowser_157_source/PaxHeaders.7921/flywheel.cpp0000644000000000000000000000013212646460742017211 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/flywheel.cpp0000644000175000001440000002006312646460742017553 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "flywheel.h" UI_Flywheel::UI_Flywheel(QWidget *w_parent) : QWidget(w_parent) { int i; use_move_events = 0; wheel_position = 0.0; spinning = 0; knobs = 10; cursor_above_object = 0; dial_speed = 0; dial_speed_ptr = 0; for(i=0; i<4; i++) { dial_speed_arr[i] = 0; } bordercolor_up = new QColor(224, 224, 224); bordercolor_down = new QColor(92, 92, 92); linearGrad = new QLinearGradient(); // linearGrad->setColorAt(0, QColor(155, 155, 155)); // linearGrad->setColorAt(1, QColor(95, 95, 95)); linearGrad->setColorAt(0, QColor(175, 175, 175)); linearGrad->setColorAt(1, QColor(75, 75, 75)); t1 = new QTimer(this); t2 = new QTimer(this); t2->setSingleShot(true); #if QT_VERSION >= 0x050000 t1->setTimerType(Qt::PreciseTimer); t2->setTimerType(Qt::PreciseTimer); #endif connect(t1, SIGNAL(timeout()), this, SLOT(wheel_rotate())); connect(t2, SIGNAL(timeout()), this, SLOT(t2_time_out())); } UI_Flywheel::~UI_Flywheel() { delete bordercolor_up; delete bordercolor_down; delete linearGrad; } void UI_Flywheel::t2_time_out(void) { dial_speed = 0; } void UI_Flywheel::wheel_rotate(void) { int h, cumulative_pixels=0; double circum; t2->start(100); h = height(); circum = (M_PI * (double)h); if(use_move_events && (!spinning)) { wheel_position += (((M_PI * 2.0) / (circum / (double)mouse_delta_y)) + (M_PI * 2.0)); while(wheel_position >= (M_PI * 2.0)) { wheel_position -= (M_PI * 2.0); } while(wheel_position < 0.0) { wheel_position += (M_PI * 2.0); } cumulative_pixels = mouse_delta_y; } if(spinning) { if(dial_speed) { wheel_position += ((M_PI * 2.0) / (circum / ((double)dial_speed / 25.0))); cumulative_pixels = (double)dial_speed / 25.0; while(wheel_position >= (M_PI * 2.0)) { wheel_position -= (M_PI * 2.0); } while(wheel_position < 0.0) { wheel_position += (M_PI * 2.0); } if(holdoff) { holdoff--; } else { if(dial_speed > 0) { dial_speed -= 25; if(dial_speed < 0) { dial_speed = 0; } } else { dial_speed += 25; if(dial_speed > 0) { dial_speed = 0; } } if((dial_speed < 500) && (dial_speed > -500)) { if((dial_speed < 125) && (dial_speed > -125)) { holdoff = 6; } else { holdoff = 3; } } } } if(dial_speed == 0) { t1->stop(); spinning = 0; } } update(); emit dialMoved(cumulative_pixels); } void UI_Flywheel::paintEvent(QPaintEvent *) { int w, h, h_2, i, j, b1, b2; double knobstep, rad, rad_offset; QPainter painter(this); #if QT_VERSION >= 0x050000 painter.setRenderHint(QPainter::Qt4CompatiblePainting, true); #endif w = width(); h = height(); h_2 = h / 2; knobstep = (M_PI * 2.0) / (double)(knobs * 2); linearGrad->setStart(QPoint(w / 2, 0)); linearGrad->setFinalStop(QPoint(w / 2, h)); painter.fillRect(0, 0, w-1, h-1, QBrush(*linearGrad)); rad_offset = wheel_position; while(rad_offset > (knobstep * 2.0)) { rad_offset -= (knobstep * 2.0); } for(i=0; i= M_PI) { b2 = h; } else { b2 = h_2 - (h_2 * cos(rad)); } // j = 222.0 - ((60.0 / (double)h) * (((double)b1 + (double)b2) / 2.0)); j = 240.0 - ((100.0 / (double)h) * (((double)b1 + (double)b2) / 2.0)); painter.fillRect(1, b1, w-2, b2 - b1, QColor(j, j, j)); if(b1 > h_2) { if(b1 > (h * 0.75)) { if(b1 > (h * 0.9)) { painter.fillRect(1, b1, w-2, 3, *bordercolor_up); } else { painter.fillRect(1, b1, w-2, 2, *bordercolor_up); } } painter.setPen(*bordercolor_up); painter.drawLine(1, b1, w-2, b1); } if(b2 < h_2) { if(b2 < (h * 0.25)) { if(b2 < (h * 0.1)) { painter.fillRect(1, b2, w-2, 2, *bordercolor_down); } else { painter.fillRect(1, b2, w-2, 2, *bordercolor_down); } } painter.setPen(*bordercolor_down); painter.drawLine(1, b2, w-2, b2); } } painter.setPen(Qt::black); painter.drawRect(0, 0, w-1, h-1); } void UI_Flywheel::mousePressEvent(QMouseEvent *press_event) { int i; if(press_event->button()==Qt::LeftButton) { for(i=0; i<4; i++) { dial_speed_arr[i] = 0; } spinning = 0; dial_speed = 0; t1->stop(); mouse_old_y = press_event->y(); gettimeofday(&tv, NULL); time_old = tv.tv_usec; time_new = tv.tv_usec; use_move_events = 1; cursor_above_object = 1; setMouseTracking(true); t2->start(100); } } void UI_Flywheel::mouseReleaseEvent(QMouseEvent *release_event) { if(release_event->button()==Qt::LeftButton) { if(use_move_events && (!spinning)) { if((dial_speed > 50) || (dial_speed < -50)) { spinning = 1; holdoff = 0; t1->start(40); } } setMouseTracking(false); use_move_events = 0; cursor_above_object = 0; } } void UI_Flywheel::mouseMoveEvent(QMouseEvent *move_event) { int i, mouse_x; if(use_move_events) { mouse_y = move_event->y(); mouse_x = move_event->x(); mouse_delta_y = mouse_y - mouse_old_y; mouse_old_y = mouse_y; if((mouse_y > height()) || (mouse_y < 0) || (mouse_x > width()) || (mouse_x < 0)) { if((cursor_above_object == 1) && (!spinning)) { if((dial_speed > 50) || (dial_speed < -50)) { spinning = 1; holdoff = 0; t1->start(40); } } cursor_above_object = 0; } else { if(cursor_above_object == 1) { gettimeofday(&tv, NULL); time_old = time_new; time_new = tv.tv_usec; if(time_new > time_old) { dial_speed_arr[dial_speed_ptr] = (mouse_delta_y * 1000000) / (time_new - time_old); } else { dial_speed_arr[dial_speed_ptr] = (mouse_delta_y * 1000000) / (1000000 + time_new - time_old); } dial_speed_ptr++; dial_speed_ptr %= 4; dial_speed = 0; for(i=0; i<4; i++) { dial_speed += dial_speed_arr[i]; } dial_speed /= 4; } spinning = 0; t1->stop(); cursor_above_object = 1; wheel_rotate(); } } } edfbrowser_157_source/PaxHeaders.7921/filtercurve.cpp0000644000000000000000000000013212646460742017724 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/filtercurve.cpp0000644000175000001440000001676612646460742020305 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "filtercurve.h" FilterCurve::FilterCurve(QWidget *w_parent) : QWidget(w_parent) { setAttribute(Qt::WA_OpaquePaintEvent); SignalColor1 = Qt::blue; SignalColor2 = QColor(210, 210, 0); tracewidth = 0; BackgroundColor = Qt::gray; RasterColor = Qt::darkGray; MarkerColor = Qt::black; h_rastersize = 10; v_rastersize = 10; drawcurve_before_raster = 0; buf1 = NULL; buf2 = NULL; marker_1 = 0; marker_2 = 0; } void FilterCurve::paintEvent(QPaintEvent *) { int i, w, h; double v_sens, offset, h_step, rasterstep; w = width(); h = height(); QPainter painter(this); #if QT_VERSION >= 0x050000 painter.setRenderHint(QPainter::Qt4CompatiblePainting, true); #endif painter.fillRect(0, 0, w, h, BackgroundColor); if(w < 5) return; if(h < 5) return; /////////////////////////////////// draw the curve /////////////////////////////////////////// if(drawcurve_before_raster) { if(buf1 == NULL) return; if(buf2 != NULL) { if(max_value2 == min_value2) return; if(bufsize2 < 2) return; offset = (-(max_value2)); v_sens = (-(h / (max_value2 - min_value2))); h_step = (double)w / (double)(bufsize2 - 1); painter.setPen(QPen(QBrush(SignalColor2, Qt::SolidPattern), tracewidth, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin)); for(i = 0; i < (bufsize2 - 1); i++) { painter.drawLine(i * h_step, (buf2[i] + offset) * v_sens, (i + 1) * h_step, (buf2[i + 1] + offset) * v_sens); } } if(max_value1 == min_value1) return; if(bufsize1 < 2) return; offset = (-(max_value1)); v_sens = (-(h / (max_value1 - min_value1))); h_step = (double)w / (double)(bufsize1 - 1); painter.setPen(QPen(QBrush(SignalColor1, Qt::SolidPattern), tracewidth, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin)); for(i = 0; i < (bufsize1 - 1); i++) { painter.drawLine(i * h_step, (buf1[i] + offset) * v_sens, (i + 1) * h_step, (buf1[i + 1] + offset) * v_sens); } } /////////////////////////////////// draw the rasters /////////////////////////////////////////// painter.setPen(RasterColor); painter.drawRect (0, 0, w - 1, h - 1); if(h_rastersize > 1) { rasterstep = (double)w / h_rastersize; for(i = 1; i < h_rastersize; i++) { painter.drawLine(i * rasterstep, 0, i * rasterstep, h); } } if(v_rastersize > 1) { rasterstep = (double)h / v_rastersize; for(i = 1; i < v_rastersize; i++) { painter.drawLine(0, i * rasterstep, w, i * rasterstep); } } /////////////////////////////////// draw the curve /////////////////////////////////////////// if(!drawcurve_before_raster) { if(buf1 == NULL) return; if(buf2 != NULL) { if(max_value2 == min_value2) return; if(bufsize2 < 2) return; offset = (-(max_value2)); v_sens = (-(h / (max_value2 - min_value2))); h_step = (double)w / (double)(bufsize2 - 1); painter.setPen(QPen(QBrush(SignalColor2, Qt::SolidPattern), tracewidth, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin)); for(i = 0; i < (bufsize2 - 1); i++) { painter.drawLine(i * h_step, (buf2[i] + offset) * v_sens, (i + 1) * h_step, (buf2[i + 1] + offset) * v_sens); } } if(max_value1 == min_value1) return; if(bufsize1 < 2) return; offset = (-(max_value1)); v_sens = (-(h / (max_value1 - min_value1))); h_step = (double)w / (double)(bufsize1 - 1); painter.setPen(QPen(QBrush(SignalColor1, Qt::SolidPattern), tracewidth, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin)); for(i = 0; i < (bufsize1 - 1); i++) { painter.drawLine(i * h_step, (buf1[i] + offset) * v_sens, (i + 1) * h_step, (buf1[i + 1] + offset) * v_sens); } } /////////////////////////////////// draw the markers /////////////////////////////////////////// painter.setFont(QFont("Arial", 8)); if((marker_1) || (marker_2)) { painter.drawText(2, 10, "0 Hz"); } if(marker_1) { painter.drawText(2 + marker_1, 10, "F1"); } if(marker_2) { painter.drawText(1 + marker_2, 10, "F2"); } if((marker_1) || (marker_2)) { painter.setPen(SignalColor2); painter.drawText(w - 35, 10, "0 degr."); painter.drawText(w - 45, h - 2, "360 degr."); } if(marker_1) { painter.setPen(QPen(QBrush(MarkerColor, Qt::SolidPattern), 0, Qt::DotLine, Qt::SquareCap, Qt::BevelJoin)); painter.drawLine(marker_1, 0, marker_1, h); } if(marker_2) { painter.setPen(QPen(QBrush(MarkerColor, Qt::SolidPattern), 0, Qt::DotLine, Qt::SquareCap, Qt::BevelJoin)); painter.drawLine(marker_2, 0, marker_2, h); } } void FilterCurve::drawCurve(double *samplebuf, int bsize, double max_val, double min_val) { buf1 = samplebuf; bufsize1 = bsize; max_value1 = max_val; min_value1 = min_val; buf2 = NULL; marker_1 = 0; marker_2 = 0; update(); } void FilterCurve::drawCurve(double *samplebuf, int bsize, double max_val, double min_val, double *samplebuf2, int size2, double max_val2, double min_val2, int mrkr1, int mrkr2) { buf1 = samplebuf; bufsize1 = bsize; max_value1 = max_val; min_value1 = min_val; buf2 = samplebuf2; bufsize2 = size2; max_value2 = max_val2; min_value2 = min_val2; if(mrkr1 > 0) { marker_1 = mrkr1; } else { marker_1 = 0; } if(mrkr2 > 0) { marker_2 = mrkr2; } else { marker_2 = 0; } update(); } void FilterCurve::setSignalColor1(QColor newColor) { SignalColor1 = newColor; update(); } void FilterCurve::setSignalColor2(QColor newColor) { SignalColor2 = newColor; update(); } void FilterCurve::setTraceWidth(int tr_width) { tracewidth = tr_width; if(tracewidth < 0) tracewidth = 0; update(); } void FilterCurve::setBackgroundColor(QColor newColor) { BackgroundColor = newColor; update(); } void FilterCurve::setRasterColor(QColor newColor) { RasterColor = newColor; update(); } void FilterCurve::setMarkerColor(QColor newColor) { MarkerColor = newColor; update(); } void FilterCurve::setH_RasterSize(int newsize) { h_rastersize = newsize; update(); } void FilterCurve::setV_RasterSize(int newsize) { v_rastersize = newsize; update(); } edfbrowser_157_source/PaxHeaders.7921/xml.h0000644000000000000000000000013212646460742015637 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/xml.h0000644000175000001440000000514312646460742016203 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef xml_INCLUDED #define xml_INCLUDED #include #include #include #define XML_STRBUFLEN 4096 /* XML max element depth */ #define XML_MAX_ED 32 #define XML_ERROR_GEN -1 #define XML_ERROR_STRLEN -2 #define XML_ERROR_MEMBUFSZ -3 #define XML_ERROR_INV_HDL -4 struct xml_handle { FILE *file; int encoding; int level; int offset[XML_MAX_ED]; int one_tag[XML_MAX_ED]; char elementname[XML_MAX_ED][XML_STRBUFLEN]; char attributes[XML_MAX_ED][XML_STRBUFLEN]; char tag_search_result[XML_STRBUFLEN]; char content[XML_MAX_ED][XML_STRBUFLEN]; }; struct xml_handle * xml_get_handle(const char *); void xml_close(struct xml_handle *); void xml_go_up(struct xml_handle *); int xml_goto_nth_element_inside(struct xml_handle *, const char *, int); int xml_goto_next_element_with_same_name(struct xml_handle *); int xml_goto_next_element_at_same_level(struct xml_handle *); void xml_goto_root(struct xml_handle *); int xml_get_content_of_element(struct xml_handle *, char *, int); int xml_character_encoding_type(struct xml_handle *); int xml_get_attribute_of_element(struct xml_handle *, const char *, char *, int); int xml_get_name_of_element(struct xml_handle *, char *, int); void xml_fwrite_encode_entity(FILE *, const char *); void xml_fnwrite_encode_entity(FILE *, const char *, int); void xml_strcpy_encode_entity(char *, const char *); int xml_strncpy_encode_entity(char *, const char *, int); void xml_strcpy_decode_entity(char *, const char *); int xml_strncpy_decode_entity(char *, const char *, int); #endif edfbrowser_157_source/PaxHeaders.7921/date_time_stamp_parser.c0000644000000000000000000000013212646460742021545 xustar0030 mtime=1452958178.243246747 30 atime=1452958178.243246747 30 ctime=1452958178.243246747 edfbrowser_157_source/date_time_stamp_parser.c0000644000175000001440000000710612646460742022112 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2014, 2015, 2016 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 . * *************************************************************************** */ #include #include #include #include "utc_date_time.h" #include "date_time_stamp_parser.h" #define DATE_TIME_STAMP_LEN 20 long long parse_date_time_stamp(const char *src) { int i, len, probes; char str[1024], *ptr; len = strlen(src); if(len < DATE_TIME_STAMP_LEN + 4) goto ERROR; strcpy(str, src); len = strlen(str); if(len < DATE_TIME_STAMP_LEN) goto ERROR; probes = len - DATE_TIME_STAMP_LEN + 1; for(i=0; i '9') || (ptr[1] < '0') || (ptr[1] > '9') || (ptr[7] < '0') || (ptr[7] > '9') || (ptr[8] < '0') || (ptr[8] > '9') || (ptr[9] < '0') || (ptr[9] > '9') || (ptr[10] < '0') || (ptr[10] > '9')) continue; if((ptr[12] < '0') || (ptr[12] > '9') || (ptr[13] < '0') || (ptr[13] > '9') || (ptr[15] < '0') || (ptr[15] > '9') || (ptr[16] < '0') || (ptr[16] > '9') || (ptr[18] < '0') || (ptr[18] > '9') || (ptr[19] < '0') || (ptr[19] > '9')) continue; break; } if(i == probes) goto ERROR; /* * We are looking for a string formatted like this: * 03-MAY-2013_14h45m49 * */ ptr[DATE_TIME_STAMP_LEN] = 0; ptr[2] = 0; ptr[6] = 0; ptr[11] = 0; ptr[14] = 0; ptr[17] = 0; struct date_time_struct dat_time; dat_time.day = atoi(ptr); dat_time.year = atoi(ptr + 7); dat_time.hour = atoi(ptr + 12); dat_time.minute = atoi(ptr + 15); dat_time.second = atoi(ptr + 18); if((dat_time.day < 1) || (dat_time.day > 31) || (dat_time.year < 1970) || (dat_time.year > 2999) || (dat_time.hour < 0) || (dat_time.hour > 23) || (dat_time.minute < 0) || (dat_time.minute > 59) || (dat_time.second < 0) || (dat_time.second > 59)) goto ERROR; dat_time.month = -1; if(!strcmp(ptr + 3, "JAN")) dat_time.month = 1; if(!strcmp(ptr + 3, "FEB")) dat_time.month = 2; if(!strcmp(ptr + 3, "MAR")) dat_time.month = 3; if(!strcmp(ptr + 3, "APR")) dat_time.month = 4; if(!strcmp(ptr + 3, "MAY")) dat_time.month = 5; if(!strcmp(ptr + 3, "JUN")) dat_time.month = 6; if(!strcmp(ptr + 3, "JUL")) dat_time.month = 7; if(!strcmp(ptr + 3, "AUG")) dat_time.month = 8; if(!strcmp(ptr + 3, "SEP")) dat_time.month = 9; if(!strcmp(ptr + 3, "OCT")) dat_time.month = 10; if(!strcmp(ptr + 3, "NOV")) dat_time.month = 11; if(!strcmp(ptr + 3, "DEC")) dat_time.month = 12; if(dat_time.month == -1) goto ERROR; long long utc_time; date_time_to_utc(&utc_time, dat_time); return utc_time; ERROR: return -1LL; } edfbrowser_157_source/PaxHeaders.7921/unisens2edf.cpp0000644000000000000000000000013212646460742017617 xustar0030 mtime=1452958178.249246726 30 atime=1452958178.249246726 30 ctime=1452958178.249246726 edfbrowser_157_source/unisens2edf.cpp0000644000175000001440000021606112646460742020166 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "unisens2edf.h" #define US_DATATYPE_FLOAT_LI 0 #define US_DATATYPE_FLOAT_BI 1 #define US_DATATYPE_DOUBLE_LI 2 #define US_DATATYPE_DOUBLE_BI 3 #define US_DATATYPE_INT64_LI 4 #define US_DATATYPE_INT64_BI 5 #define US_DATATYPE_UINT64_LI 6 #define US_DATATYPE_UINT64_BI 7 #define US_DATATYPE_INT32_LI 8 #define US_DATATYPE_INT32_BI 9 #define US_DATATYPE_UINT32_LI 10 #define US_DATATYPE_UINT32_BI 11 #define US_DATATYPE_INT24_LI 12 #define US_DATATYPE_INT24_BI 13 #define US_DATATYPE_UINT24_LI 14 #define US_DATATYPE_UINT24_BI 15 #define US_DATATYPE_INT16_LI 16 #define US_DATATYPE_INT16_BI 17 #define US_DATATYPE_UINT16_LI 18 #define US_DATATYPE_UINT16_BI 19 #define US_DATATYPE_INT8_LI 20 #define US_DATATYPE_INT8_BI 21 #define US_DATATYPE_UINT8_LI 22 #define US_DATATYPE_UINT8_BI 23 #define US_SAMPLERATE_OUT_OF_RANGE 22 UI_UNISENS2EDFwindow::UI_UNISENS2EDFwindow(char *recent_dir, char *save_dir) { char txt_string[2048]; recent_opendir = recent_dir; recent_savedir = save_dir; myobjectDialog = new QDialog; myobjectDialog->setMinimumSize(600, 480); myobjectDialog->setMaximumSize(600, 480); myobjectDialog->setWindowTitle("Unisens to EDF+ converter"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); 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"); textEdit1 = new QTextEdit(myobjectDialog); textEdit1->setGeometry(20, 20, 560, 380); textEdit1->setFrameStyle(QFrame::Panel | QFrame::Sunken); textEdit1->setReadOnly(true); textEdit1->setLineWrapMode(QTextEdit::NoWrap); sprintf(txt_string, "Unisens to EDF+ converter.\n"); textEdit1->append(txt_string); QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton())); QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close())); myobjectDialog->exec(); } void UI_UNISENS2EDFwindow::SelectFileButton() { int i, j, k, n, tmp, chns, hdl, err, *buf2, bufsize, blocks_written, progress_steps, lines; short tmp3; char path[MAX_PATH_LENGTH], binfilepath[MAX_PATH_LENGTH], outputfilename[MAX_PATH_LENGTH], scratchpad[2048], str[256], *buf1, tmp2, linebuf[512]; struct xml_handle *xml_hdl; strcpy(path, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "XML files (*.xml *.XML)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(recent_opendir, path, MAX_PATH_LENGTH); xml_hdl = xml_get_handle(path); if(xml_hdl == NULL) { sprintf(scratchpad, "Error, can not open file:\n%s\n", path); textEdit1->append(QString::fromLocal8Bit(scratchpad)); return; } sprintf(scratchpad, "Processing file:\n%s", path); textEdit1->append(QString::fromLocal8Bit(scratchpad)); char_encoding = xml_hdl->encoding; if(char_encoding == 0) // attribute encoding not present { char_encoding = 2; // fallback to UTF-8 because it is the default for XML } else if(char_encoding > 2) // unknown encoding FIX ME!! { char_encoding = 1; // fallback to ISO-8859-1 (Latin1) } if(strcmp(xml_hdl->elementname[xml_hdl->level], "unisens")) { textEdit1->append("Error, can not find root element \"unisens\".\n"); xml_close(xml_hdl); return; } if(xml_get_attribute_of_element(xml_hdl, "timestampStart", str, 255) < 0) { textEdit1->append("Error, can not find attribute \"timestampStart\".\n"); return; } if((strlen(str) < 19) || (strlen(str) > 23) || (str[4] != '-') || (str[7] != '-') || (str[10] != 'T') || (str[13] != ':') || (str[16] != ':')) { textEdit1->append("Error, can not find attribute \"timestampStart\".\n"); return; } err = 0; for(i=0; i<19; i++) { if((i == 4) || (i == 7) || (i == 10) || (i == 13) || (i == 16)) continue; if(!(isdigit(str[i]))) err = 1; } if(strlen(str) == 23) { if(str[19] != '.') err = 1; for(i=20; i<23; i++) { if(!(isdigit(str[i]))) err = 1; } starttime_fraction = atoi(str + 20); if((starttime_fraction < 0) || (starttime_fraction > 999)) err = 1; } else { starttime_fraction = 0; } if(err) { textEdit1->append("Error, invalid format in attribute \"timestampStart\".\n"); return; } strncpy(str_timestampStart, str, 19); str_timestampStart[19] = 0; if(xml_get_attribute_of_element(xml_hdl, "measurementId", str, 255) < 0) { textEdit1->append("Error, can not find attribute \"measurementId\".\n"); return; } if(strlen(str) < 1) { textEdit1->append("Error, attribute \"measurementId\" has no data.\n"); return; } if(char_encoding == 1) // Latin-1 { strncpy(str_measurementId, QString::fromLatin1(str).toLocal8Bit().data(), 128); } else if(char_encoding == 2) { strncpy(str_measurementId, QString::fromUtf8(str).toLocal8Bit().data(), 128); } else { // strncpy(str_measurementId, str, 128); strncpy(str_measurementId, QString::fromUtf8(str).toLocal8Bit().data(), 128); // default for XML is UTF-8 } str_measurementId[127] = 0; xml_goto_root(xml_hdl); ////////////////////////// read parameters from XML-file ////////////////////////////////////////// total_edf_signals = 0; bdf = 0; int skip = 0; sf_less_1 = 0; for(file_cnt=0; file_cntappend("Error, can not find element \"csvFileFormat\".\n"); xml_close(xml_hdl); for(i=0; iappend("Error, can not find attribute \"separator\".\n"); xml_close(xml_hdl); for(i=0; iappend("Error, value for \"separator\" must be one character.\n"); xml_close(xml_hdl); for(i=0; iappend("Error, value for \"decimalSeparator\" must be one character.\n"); xml_close(xml_hdl); for(i=0; iappend("Error, attribute \"decimalSeparator\" and \"separator\" have equal values.\n"); xml_close(xml_hdl); for(i=0; iappend("Error, can not find element \"binFileFormat\".\n"); xml_close(xml_hdl); for(i=0; iappend("Error, can not find attribute \"endianess\".\n"); xml_close(xml_hdl); for(i=0; iappend("Error, can not find attribute \"endianess\".\n"); xml_close(xml_hdl); for(i=0; iappend("Error, attribute \"endianess\" has an unknown value.\n"); xml_close(xml_hdl); for(i=0; iappend("Error, can not find attribute \"name\" in element \"channel\".\n"); xml_close(xml_hdl); for(i=0; iappend("Error, no signals in element \"signalEntry\" or in element \"csvFileFormat\".\n"); xml_close(xml_hdl); for(i=0; i= MAXSIGNALS) { textEdit1->append("Error, too many signals.\n"); xml_close(xml_hdl); for(i=0; iappend(QString::fromLocal8Bit(scratchpad)); xml_close(xml_hdl); for(i=0; iappend("Error, can not find element \"csvFileFormat\".\n"); xml_close(xml_hdl); for(i=0; iappend("Error, can not find attribute \"separator\".\n"); xml_close(xml_hdl); for(i=0; iappend("Error, value for \"separator\" must be one character.\n"); xml_close(xml_hdl); for(i=0; iappend("Error, value for \"decimalSeparator\" must be one character.\n"); xml_close(xml_hdl); for(i=0; iappend("Error, attribute \"decimalSeparator\" and \"separator\" have equal values.\n"); xml_close(xml_hdl); for(i=0; iappend("Error, can not find attribute \"name\" in element \"channel\".\n"); xml_close(xml_hdl); for(i=0; iappend("Error, no signals in element \"valuesEntry\".\n"); xml_close(xml_hdl); for(i=0; i= MAXSIGNALS) { textEdit1->append("Error, too many signals.\n"); xml_close(xml_hdl); for(i=0; iappend(QString::fromLocal8Bit(scratchpad)); xml_close(xml_hdl); for(i=0; iappend("Error, can not find element \"signalEntry\" or element \"csvFileFormat\".\n"); xml_close(xml_hdl); return; } if(total_edf_signals > (MAXSIGNALS - 1)) { textEdit1->append("Error, too many signals (limit is 511).\n"); for(i=0; i max_datablocks) { max_datablocks = datablocks[k]; } } ////////////////////////////////////// Check for and count the triggers //////////////////////////////////////////////////////////// total_annotations = 0; xml_goto_root(xml_hdl); trig_file_cnt = 0; for(k=0; kappend("Error, can not find attribute \"separator\".\n"); xml_close(xml_hdl); for(i=0; iappend("Error, value for \"separator\" must be one character.\n"); xml_close(xml_hdl); for(i=0; iappend("Error, value for \"decimalSeparator\" must be one character.\n"); xml_close(xml_hdl); for(i=0; iappend("Error, attribute \"decimalSeparator\" and \"separator\" have equal values.\n"); xml_close(xml_hdl); for(i=0; iappend(QString::fromLocal8Bit(scratchpad)); for(i=0; i max_datablocks) { tmp = (total_annotations / max_datablocks) + 1; if(tmp > 64) tmp = 64; if(edf_set_number_of_annotation_signals(hdl, tmp)) err = 1; } if(err) { textEdit1->append("An error occurred during initializing the EDF-header.\n"); for(i=0; iappend("Malloc error (buf1)\n"); for(i=0; iappend("Malloc error (buf2)\n"); for(i=0; iprocessEvents(); if(progress.wasCanceled() == true) { break; } } for(k=0; kappend("A read error occurred during the conversion.\n"); for(i=0; iappend("A read error occurred during the conversion.\n"); for(i=0; i> 8) | (((unsigned short)tmp3 & 0x00FF) << 8)) ) - adcz; } } } else if(datatype[k] == US_DATATYPE_UINT16_BI) { for(i=0; i> 8) | (((unsigned short)tmp3 & 0x00FF) << 8)) ) - adcz; } } } else if(datatype[k] == US_DATATYPE_INT24_BI) { for(i=0; i> 24) | (((unsigned int)tmp & 0x00FF0000) >> 8) | (((unsigned int)tmp & 0x0000FF00) << 8) | (((unsigned int)tmp & 0x000000FF) << 24)) ) - adcz; } } } else if(datatype[k] == US_DATATYPE_UINT32_BI) { for(i=0; i> 24) | (((unsigned int)tmp & 0x00FF0000) >> 8) | (((unsigned int)tmp & 0x0000FF00) << 8) | (((unsigned int)tmp & 0x000000FF) << 24)) ) - adcz; } } } else if(datatype[k] == US_DATATYPE_FLOAT_LI) { for(i=0; i> 24) | (((unsigned int)tmp & 0x00FF0000) >> 8) | (((unsigned int)tmp & 0x0000FF00) << 8) | (((unsigned int)tmp & 0x000000FF) << 24)); buf2_t[(j * sf_t) + i] = var.flp - adcz; } } } else if(datatype[k] == US_DATATYPE_DOUBLE_LI) { for(i=0; i> 56) | ((ul_tmp & 0x00FF000000000000) >> 40) | ((ul_tmp & 0x0000FF0000000000) >> 24) | ((ul_tmp & 0x000000FF00000000) >> 8) | ((ul_tmp & 0x00000000FF000000) << 8) | ((ul_tmp & 0x0000000000FF0000) << 24) | ((ul_tmp & 0x000000000000FF00) << 40) | ((ul_tmp & 0x00000000000000FF) << 56)); buf2_t[(j * sf_t) + i] = var2.dflp - adcz; } } } else if(datatype[k] == US_DATATYPE_INT64_LI) { for(i=0; i> 56) | ((ul_tmp & 0x00FF000000000000) >> 40) | ((ul_tmp & 0x0000FF0000000000) >> 24) | ((ul_tmp & 0x000000FF00000000) >> 8) | ((ul_tmp & 0x00000000FF000000) << 8) | ((ul_tmp & 0x0000000000FF0000) << 24) | ((ul_tmp & 0x000000000000FF00) << 40) | ((ul_tmp & 0x00000000000000FF) << 56)) ); buf2_t[(j * sf_t) + i] = var2.lone_signed - adcz; } } } else if(datatype[k] == US_DATATYPE_UINT64_BI) { for(i=0; i> 56) | ((ul_tmp & 0x00FF000000000000) >> 40) | ((ul_tmp & 0x0000FF0000000000) >> 24) | ((ul_tmp & 0x000000FF00000000) >> 8) | ((ul_tmp & 0x00000000FF000000) << 8) | ((ul_tmp & 0x0000000000FF0000) << 24) | ((ul_tmp & 0x000000000000FF00) << 40) | ((ul_tmp & 0x00000000000000FF) << 56)) ); buf2_t[(j * sf_t) + i] = var2.lone - adcz; } } } } } } else if(blocks_written == datablocks[k]) { if(!nedval_enc[k]) { for(i=0; iappend("A write error occurred.\n"); for(i=0; iappend("Done\n"); } int UI_UNISENS2EDFwindow::get_events_from_csv_files(int max_files, int edf_hdl, const char *path) { int i, k, len, len2, progress_steps, triggers_written=0; char scratchpad[2048], csvfilepath[MAX_PATH_LENGTH], linebuf[1024], *ptr, sep, annotation[64]; long long onset; FILE *csvfile; QProgressDialog progress("Converting triggers ...", "Cancel", 0, total_annotations, myobjectDialog); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); progress_steps = total_annotations / 100; if(progress_steps < 1) { progress_steps = 1; } for(k=0; kappend(QString::fromLocal8Bit(scratchpad)); return(1); } sep = csv_sep[k]; while(1) { if(!(triggers_written % progress_steps)) { progress.setValue(triggers_written); qApp->processEvents(); if(progress.wasCanceled() == true) { fclose(csvfile); return(1); } } ptr = fgets(linebuf, 1024, csvfile); if(ptr == NULL) break; len = strlen(linebuf); if(len < 3) continue; for(i=0; i 0)) { *ptr = 0; onset = atoi(linebuf); strncpy(annotation, ++ptr, 46); annotation[45] = 0; len2 = strlen(annotation); if(annotation[len2 - 1] == '\n') { annotation[--len2] = 0; } if(annotation[len2 - 1] == '\r') { annotation[--len2] = 0; } if(annotation[len2 - 1] == sep) { annotation[--len2] = 0; } remove_leading_spaces(annotation); remove_trailing_spaces(annotation); onset *= 10000LL; onset /= evt_sf[k]; if(char_encoding == 1) { if(edfwrite_annotation_latin1(edf_hdl, onset, -1LL, annotation)) { progress.reset(); textEdit1->append("An error occurred while writing the events to the EDF-file.\n"); return(1); } } if(char_encoding == 2) { if(edfwrite_annotation_utf8(edf_hdl, onset, -1LL, annotation)) { progress.reset(); textEdit1->append("An error occurred while writing the events to the EDF-file.\n"); return(1); } } triggers_written++; break; } else { break; } } ptr++; } } fclose(csvfile); } progress.reset(); return(0); } int UI_UNISENS2EDFwindow::count_events_from_csv_files(int max_files, const char *path, int *result) { int evt_cnt=0, k; char scratchpad[2048], csvfilepath[MAX_PATH_LENGTH], linebuf[1024], *ptr; FILE *csvfile; *result = 0; for(k=0; kappend(QString::fromLocal8Bit(scratchpad)); return(1); } while(1) { ptr = fgets(linebuf, 1024, csvfile); if(ptr == NULL) break; evt_cnt++; } fclose(csvfile); } *result = evt_cnt; return(0); } int UI_UNISENS2EDFwindow::get_signalparameters_from_BIN_attributes(struct xml_handle *xml_hdl, int file_nr) { char str[256], scratchpad[2048]; double d_tmp; if(xml_get_attribute_of_element(xml_hdl, "id", str, 255) < 0) { textEdit1->append("Error, can not find attribute \"id\".\n"); return(1); } if(strlen(str) < 1) { textEdit1->append("Error, attribute \"id\" has no value.\n"); return(1); } strncpy(binfilename[file_nr], str, MAX_PATH_LENGTH - 1); if(xml_get_attribute_of_element(xml_hdl, "adcResolution", str, 255) < 0) { adcres[file_nr] = 0; } else if(strlen(str) < 1) { adcres[file_nr] = 0; } else adcres[file_nr] = atoi(str); if(xml_get_attribute_of_element(xml_hdl, "unit", str, 255) < 0) { strcpy(physdim[file_nr], "X"); } else if(strlen(str) < 1) { strcpy(physdim[file_nr], "X"); } else if(char_encoding == 1) // Latin-1 { strncpy(physdim[file_nr], str, 8); } else if(char_encoding == 2) { strncpy(physdim[file_nr], QString::fromUtf8(str).toLatin1().data(), 8); } else { // strncpy(physdim[file_nr], str, 8); strncpy(physdim[file_nr], QString::fromUtf8(str).toLatin1().data(), 8); // default for XML is UTF-8 } physdim[file_nr][8] = 0; remove_leading_spaces(physdim[file_nr]); remove_trailing_spaces(physdim[file_nr]); if(xml_get_attribute_of_element(xml_hdl, "sampleRate", str, 255) < 0) { textEdit1->append("Error, can not find attribute \"sampleRate\".\n"); return(1); } if(strlen(str) < 1) { textEdit1->append("Error, attribute \"sampleRate\" has no value."); return(1); } sf_inv[file_nr] = 0; sf[file_nr] = nearbyint(atof(str)); if((sf[file_nr] < 1) || (sf[file_nr] > 1000000)) { if(sf[file_nr] < 1) { d_tmp = atof(str); if(d_tmp >= 0.001) { sf_inv[file_nr] = nearbyint(1.0 / d_tmp); sf[file_nr] = 1; sf_less_1 = 1; } else { return(US_SAMPLERATE_OUT_OF_RANGE); } } else { return(US_SAMPLERATE_OUT_OF_RANGE); } } if(!xml_get_attribute_of_element(xml_hdl, "baseline", str, 255) < 0) { if(strlen(str) < 1) { textEdit1->append("Error, attribute \"baseline\" has no value.\n"); return(1); } baseline[file_nr] = strtoll(str, NULL, 0); } else { baseline[file_nr] = 0LL; } if(!xml_get_attribute_of_element(xml_hdl, "adcZero", str, 255) < 0) { if(strlen(str) < 1) { textEdit1->append("Error, attribute \"adcZero\" has no value.\n"); return(1); } adczero[file_nr] = strtoll(str, NULL, 0); } else { adczero[file_nr] = 0LL; } if(xml_get_attribute_of_element(xml_hdl, "lsbValue", str, 255) < 0) { lsbval[file_nr] = 1.0; } else if(strlen(str) < 1) { lsbval[file_nr] = 1.0; } else lsbval[file_nr] = atof(str); if((lsbval[file_nr] < -1000000.0) || (lsbval[file_nr] > 1000000.0)) { textEdit1->append("Error, attribute \"lsbValue\" is out of range.\n"); return(1); } physmax[file_nr] = lsbval[file_nr]; physmin[file_nr] = lsbval[file_nr]; if(xml_get_attribute_of_element(xml_hdl, "dataType", str, 255) < 0) { textEdit1->append("Error, can not find attribute \"dataType\".\n"); return(1); } if(csv_enc[file_nr]) { if(!strcmp(str, "double")) { datatype[file_nr] = US_DATATYPE_DOUBLE_LI; bdf = 1; straightbinary[file_nr] = 0; samplesize[file_nr] = 8; physmax[file_nr] *= (8388607LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-8388608LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 8388607; digmin[file_nr] = -8388608; } else if(!strcmp(str, "float")) { datatype[file_nr] = US_DATATYPE_FLOAT_LI; bdf = 1; straightbinary[file_nr] = 0; samplesize[file_nr] = 4; physmax[file_nr] *= (8388607LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-8388608LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 8388607; digmin[file_nr] = -8388608; } else if(!strcmp(str, "int32")) { datatype[file_nr] = US_DATATYPE_INT32_LI; bdf = 1; straightbinary[file_nr] = 0; samplesize[file_nr] = 4; physmax[file_nr] *= (8388607LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-8388608LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 8388607; digmin[file_nr] = -8388608; } else if(!strcmp(str, "uint32")) { datatype[file_nr] = US_DATATYPE_UINT32_LI; bdf = 1; straightbinary[file_nr] = 1; samplesize[file_nr] = 4; physmax[file_nr] *= (8388607LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-8388608LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 8388607; digmin[file_nr] = -8388608; } else if(!strcmp(str, "int16")) { datatype[file_nr] = US_DATATYPE_INT16_LI; straightbinary[file_nr] = 0; samplesize[file_nr] = 2; physmax[file_nr] *= (32767LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-32768LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 32767; digmin[file_nr] = -32768; } else if(!strcmp(str, "uint16")) { datatype[file_nr] = US_DATATYPE_UINT16_LI; straightbinary[file_nr] = 1; samplesize[file_nr] = 2; physmax[file_nr] *= (32767LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-32768LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 32767; digmin[file_nr] = -32768; } else if(!strcmp(str, "int8")) { datatype[file_nr] = US_DATATYPE_INT8_LI; straightbinary[file_nr] = 0; samplesize[file_nr] = 1; physmax[file_nr] *= (127 - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-128 - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 127; digmin[file_nr] = -128; } else if(!strcmp(str, "uint8")) { datatype[file_nr] = US_DATATYPE_UINT8_LI; straightbinary[file_nr] = 1; samplesize[file_nr] = 1; physmax[file_nr] *= (127 - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-128 - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 127; digmin[file_nr] = -128; } else if(!strcmp(str, "int64")) { datatype[file_nr] = US_DATATYPE_INT64_LI; bdf = 1; straightbinary[file_nr] = 0; samplesize[file_nr] = 8; physmax[file_nr] *= (8388607LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-8388608LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 8388607; digmin[file_nr] = -8388608; } else if(!strcmp(str, "uint64")) { datatype[file_nr] = US_DATATYPE_UINT64_LI; bdf = 1; straightbinary[file_nr] = 1; samplesize[file_nr] = 8; physmax[file_nr] *= (8388607LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-8388608LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 8388607; digmin[file_nr] = -8388608; } else { snprintf(scratchpad, 2047, "Error, unsupported combination of datatype: %s and csv file\n", str); textEdit1->append(scratchpad); return(1); } } else { if(!strcmp(str, "uint8")) { datatype[file_nr] = US_DATATYPE_UINT8_LI; straightbinary[file_nr] = 1; samplesize[file_nr] = 1; physmax[file_nr] *= (127 - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-128 - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 127; digmin[file_nr] = -128; } else if(!strcmp(str, "int8")) { datatype[file_nr] = US_DATATYPE_INT8_LI; straightbinary[file_nr] = 0; samplesize[file_nr] = 1; physmax[file_nr] *= (127 - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-128 - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 127; digmin[file_nr] = -128; } else if(!strcmp(str, "uint16")) { datatype[file_nr] = US_DATATYPE_UINT16_LI; straightbinary[file_nr] = 1; samplesize[file_nr] = 2; physmax[file_nr] *= (32767LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-32768LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 32767; digmin[file_nr] = -32768; } else if(!strcmp(str, "int16")) { datatype[file_nr] = US_DATATYPE_INT16_LI; straightbinary[file_nr] = 0; samplesize[file_nr] = 2; physmax[file_nr] *= (32767LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-32768LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 32767; digmin[file_nr] = -32768; } else if(!strcmp(str, "uint24")) { datatype[file_nr] = US_DATATYPE_UINT24_LI; bdf = 1; straightbinary[file_nr] = 1; samplesize[file_nr] = 3; physmax[file_nr] *= (8388607LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-8388608LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 8388607; digmin[file_nr] = -8388608; } else if(!strcmp(str, "int24")) { datatype[file_nr] = US_DATATYPE_INT24_LI; bdf = 1; straightbinary[file_nr] = 0; samplesize[file_nr] = 3; physmax[file_nr] *= (8388607LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-8388608LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 8388607; digmin[file_nr] = -8388608; } else if(!strcmp(str, "uint32")) { datatype[file_nr] = US_DATATYPE_UINT32_LI; bdf = 1; straightbinary[file_nr] = 1; samplesize[file_nr] = 4; physmax[file_nr] *= (8388607LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-8388608LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 8388607; digmin[file_nr] = -8388608; } else if(!strcmp(str, "int32")) { datatype[file_nr] = US_DATATYPE_INT32_LI; bdf = 1; straightbinary[file_nr] = 0; samplesize[file_nr] = 4; physmax[file_nr] *= (8388607LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-8388608LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 8388607; digmin[file_nr] = -8388608; } else if(!strcmp(str, "float")) { datatype[file_nr] = US_DATATYPE_FLOAT_LI; bdf = 1; straightbinary[file_nr] = 0; samplesize[file_nr] = 4; physmax[file_nr] *= (8388607LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-8388608LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 8388607; digmin[file_nr] = -8388608; } else if(!strcmp(str, "double")) { datatype[file_nr] = US_DATATYPE_DOUBLE_LI; bdf = 1; straightbinary[file_nr] = 0; samplesize[file_nr] = 8; physmax[file_nr] *= (8388607LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-8388608LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 8388607; digmin[file_nr] = -8388608; } else if(!strcmp(str, "uint64")) { datatype[file_nr] = US_DATATYPE_UINT64_LI; bdf = 1; straightbinary[file_nr] = 1; samplesize[file_nr] = 8; physmax[file_nr] *= (8388607LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-8388608LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 8388607; digmin[file_nr] = -8388608; } else if(!strcmp(str, "int64")) { datatype[file_nr] = US_DATATYPE_INT64_LI; bdf = 1; straightbinary[file_nr] = 0; samplesize[file_nr] = 8; physmax[file_nr] *= (8388607LL - (baseline[file_nr] - adczero[file_nr])); physmin[file_nr] *= (-8388608LL - (baseline[file_nr] - adczero[file_nr])); digmax[file_nr] = 8388607; digmin[file_nr] = -8388608; } else { snprintf(scratchpad, 2047, "Error, unsupported combination of datatype: %s and binary file\n", str); textEdit1->append(scratchpad); return(1); } } return(0); } int UI_UNISENS2EDFwindow::get_signalparameters_from_EVT_attributes(struct xml_handle *xml_hdl, int file_nr) { char str[256]; if(xml_get_attribute_of_element(xml_hdl, "id", str, 255) < 0) { textEdit1->append("Error, can not find attribute \"id\".\n"); return(1); } if(strlen(str) < 1) { textEdit1->append("Error, attribute \"id\" has no value.\n"); return(1); } strncpy(evtfilename[file_nr], str, MAX_PATH_LENGTH - 1); if(xml_get_attribute_of_element(xml_hdl, "sampleRate", str, 255) < 0) { textEdit1->append("Error, can not find attribute \"sampleRate\".\n"); return(1); } if(strlen(str) < 1) { textEdit1->append("Error, attribute \"sampleRate\" has no value.\n"); return(1); } evt_sf[file_nr] = atoi(str); if((evt_sf[file_nr] < 1) || (evt_sf[file_nr] > 1000000)) { textEdit1->append("Error, attribute \"sampleRate\" is out of range.\n"); return(1); } return(0); } edfbrowser_157_source/PaxHeaders.7921/main.cpp0000644000000000000000000000013212646460742016316 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/main.cpp0000644000175000001440000000122112646460742016653 0ustar00guvusers00000000000000 #include #include #include #include #include #include "mainwindow.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); app.setAttribute(Qt::AA_DontUseNativeMenuBar); QPixmap pixmap(":/images/splash.png"); QSplashScreen splash(pixmap, Qt::WindowStaysOnTopHint); QTimer t1; t1.setSingleShot(true); #if QT_VERSION >= 0x050000 t1.setTimerType(Qt::PreciseTimer); #endif QObject::connect(&t1, SIGNAL(timeout()), &splash, SLOT(close())); splash.show(); t1.start(3000); qApp->processEvents(); class UI_Mainwindow MainWindow; return app.exec(); } edfbrowser_157_source/PaxHeaders.7921/edfplusd_cnv.h0000644000000000000000000000013212646460742017513 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/edfplusd_cnv.h0000644000175000001440000000376712646460742020071 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_EDFD2EDFCFORM_H #define UI_EDFD2EDFCFORM_H #include #include #include #include #include #include #include #include #include #if QT_VERSION < 0x050000 #include #include #endif #include #include #include #include #include #include "global.h" #include "check_edf_file.h" #include "edf_annotations.h" #include "utils.h" class UI_EDFDwindow : public QObject { Q_OBJECT public: UI_EDFDwindow(char *, char *); private: QPushButton *pushButton1, *pushButton2; QTextEdit *textEdit1; QDialog *myobjectDialog; char *recent_opendir, *recent_savedir; long long get_datarecord_timestamp(char *); void write_values_to_hdr(FILE *, long long, int, struct edfhdrblock *); void free_annotations(struct annotationblock *); private slots: void SelectFileButton(); }; #endif edfbrowser_157_source/PaxHeaders.7921/edfplusd_cnv.cpp0000644000000000000000000000013212646460742020046 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/edfplusd_cnv.cpp0000644000175000001440000004412512646460742020415 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "edfplusd_cnv.h" UI_EDFDwindow::UI_EDFDwindow(char *recent_ope_dir, char *recent_sav_dir) { char txt_string[2048]; recent_opendir = recent_ope_dir; recent_savedir = recent_sav_dir; myobjectDialog = new QDialog; myobjectDialog->setMinimumSize(600, 480); myobjectDialog->setMaximumSize(600, 480); myobjectDialog->setWindowTitle("EDF+D/BDF+D to EDF+C/BDF+C converter"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); 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"); textEdit1 = new QTextEdit(myobjectDialog); textEdit1->setGeometry(20, 20, 560, 380); textEdit1->setFrameStyle(QFrame::Panel | QFrame::Sunken); textEdit1->setReadOnly(true); textEdit1->setLineWrapMode(QTextEdit::NoWrap); sprintf(txt_string, "EDF+D/BDF+D to EDF+C/BDF+C converter.\n"); textEdit1->append(txt_string); QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton())); QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close())); myobjectDialog->exec(); } void UI_EDFDwindow::SelectFileButton() { FILE *inputfile=NULL, *outputfile=NULL; int i, file_number, offset, offset_2, datarecords, datarecords_read, datarecords_written, cnt, annot_signal_size, annot_signal_size_2, annot_signal_nr, annot_signal_nr_2, annots_written, len, progress_steps; long long former_timestamp, next_timestamp, new_hdr_timestamp, chunk_starttime, chunk_endtime; char txt_string[2048], inputpath[MAX_PATH_LENGTH], output_path[MAX_PATH_LENGTH], *fileheader, *readbuf, *tal; struct annotationblock *annotationlist[1], *annotblock; struct edfhdrblock *edfhdr=NULL; pushButton1->setEnabled(false); strcpy(inputpath, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "EDF/BDF files (*.edf *.EDF *.bdf *.BDF *.rec *.REC)").toLocal8Bit().data()); if(!strcmp(inputpath, "")) { pushButton1->setEnabled(true); return; } get_directory_from_path(recent_opendir, inputpath, MAX_PATH_LENGTH); inputfile = fopeno(inputpath, "rb"); if(inputfile==NULL) { snprintf(txt_string, 2048, "Error, can not open file %s for reading.\n", inputpath); textEdit1->append(QString::fromLocal8Bit(txt_string)); pushButton1->setEnabled(true); return; } snprintf(txt_string, 2048, "Processing file %s", inputpath); textEdit1->append(txt_string); /***************** check if the file is valid ******************************/ EDFfileCheck EDFfilechecker; edfhdr = EDFfilechecker.check_edf_file(inputfile, txt_string); if(edfhdr==NULL) { fclose(inputfile); textEdit1->append("Error, file is not a valid EDF or BDF file.\n"); pushButton1->setEnabled(true); return; } if(((!edfhdr->edfplus)&&(!edfhdr->bdfplus))||(!edfhdr->discontinuous)) { free(edfhdr->edfparam); free(edfhdr); fclose(inputfile); textEdit1->append("Error, file is not an EDF+D or BDF+D file.\n"); pushButton1->setEnabled(true); return; } /****************** get annotations ******************************/ edfhdr->file_hdl = inputfile; EDF_annotations annotations_func; annotationlist[0] = NULL; if(annotations_func.get_annotations(0, edfhdr, &annotationlist[0], 0)) { free_annotations(annotationlist[0]); free(edfhdr->edfparam); free(edfhdr); fclose(inputfile); textEdit1->append("Error, there is an incompatibility with the annotations.\n"); pushButton1->setEnabled(true); return; } if(edfhdr->annots_not_read) { free_annotations(annotationlist[0]); free(edfhdr->edfparam); free(edfhdr); fclose(inputfile); textEdit1->append("Aborted.\n"); pushButton1->setEnabled(true); return; } annotblock = annotationlist[0]; /***************** start conversion ******************************/ datarecords = edfhdr->datarecords; annot_signal_nr = edfhdr->annot_ch[0]; offset = edfhdr->edfparam[annot_signal_nr].buf_offset; if(edfhdr->edfplus) { annot_signal_size = edfhdr->edfparam[annot_signal_nr].smp_per_record * 2; } else { annot_signal_size = edfhdr->edfparam[annot_signal_nr].smp_per_record * 3; } fileheader = (char *)calloc(1, edfhdr->hdrsize); if(fileheader==NULL) { textEdit1->append("Malloc error, (fileheader).\n"); free_annotations(annotationlist[0]); free(edfhdr->edfparam); free(edfhdr); fclose(inputfile); pushButton1->setEnabled(true); return; } readbuf = (char *)calloc(1, edfhdr->recordsize); if(readbuf==NULL) { textEdit1->append("Malloc error, (readbuf).\n"); free_annotations(annotationlist[0]); free(edfhdr->edfparam); free(edfhdr); free(fileheader); fclose(inputfile); pushButton1->setEnabled(true); return; } rewind(inputfile); if(fread(fileheader, edfhdr->hdrsize, 1, inputfile) != 1) { textEdit1->append("Read error.\n"); free_annotations(annotationlist[0]); free(edfhdr->edfparam); free(edfhdr); free(fileheader); free(readbuf); fclose(inputfile); pushButton1->setEnabled(true); return; } /////////////////////////////////////////////////////////////////// file_number = 1; strcpy(output_path, inputpath); remove_extension_from_filename(output_path); if(edfhdr->edfplus) { sprintf(output_path + strlen(output_path), "_%04i.edf", file_number); } else { sprintf(output_path + strlen(output_path), "_%04i.bdf", file_number); } strcpy(txt_string, "Creating file "); len = strlen(txt_string); get_filename_from_path(txt_string + len, output_path, MAX_PATH_LENGTH - len); textEdit1->append(QString::fromLocal8Bit(txt_string)); outputfile = fopeno(output_path, "w+b"); if(outputfile==NULL) { textEdit1->append("Error, can not open outputfile for writing.\n"); free_annotations(annotationlist[0]); free(edfhdr->edfparam); free(edfhdr); free(fileheader); free(readbuf); fclose(inputfile); pushButton1->setEnabled(true); return; } if(fwrite(fileheader, edfhdr->hdrsize, 1, outputfile) != 1) { textEdit1->append("Write error.\n"); free_annotations(annotationlist[0]); free(edfhdr->edfparam); free(edfhdr); free(fileheader); free(readbuf); fclose(inputfile); fclose(outputfile); pushButton1->setEnabled(true); return; } QProgressDialog progress("Processing file...", "Abort", 0, datarecords); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); progress_steps = datarecords / 100; if(progress_steps < 1) { progress_steps = 1; } datarecords_written = 0; new_hdr_timestamp = 0LL; former_timestamp = 0LL; next_timestamp = 0LL; chunk_starttime = 0LL; chunk_endtime = 0LL; tal = readbuf + offset; fseeko(inputfile, (long long)(edfhdr->hdrsize), SEEK_SET); for(datarecords_read=0; datarecords_readprocessEvents(); if(progress.wasCanceled() == true) { textEdit1->append("Aborted.\n"); break; } } if(fread(readbuf, edfhdr->recordsize, 1, inputfile) != 1) { progress.reset(); textEdit1->append("Read error.\n"); free_annotations(annotationlist[0]); free(edfhdr->edfparam); free(edfhdr); free(fileheader); free(readbuf); fclose(inputfile); fclose(outputfile); pushButton1->setEnabled(true); return; } if(edfhdr->nr_annot_chns>1) { for(i=1; inr_annot_chns; i++) { annot_signal_nr_2 = edfhdr->annot_ch[i]; offset_2 = edfhdr->edfparam[annot_signal_nr_2].buf_offset; if(edfhdr->edfplus) { annot_signal_size_2 = edfhdr->edfparam[annot_signal_nr_2].smp_per_record * 2; } else { annot_signal_size_2 = edfhdr->edfparam[annot_signal_nr_2].smp_per_record * 3; } memset(readbuf + offset_2, 0, annot_signal_size_2); } } next_timestamp = get_datarecord_timestamp(tal); if(!datarecords_read) { former_timestamp = next_timestamp - edfhdr->long_data_record_duration; } if(next_timestamp!=(former_timestamp + edfhdr->long_data_record_duration)) { chunk_endtime = next_timestamp; write_values_to_hdr(outputfile, new_hdr_timestamp, datarecords_written, edfhdr); annotblock = annotationlist[0]; annots_written = 0; if(annotblock!=NULL) { while(annotblock!=NULL) { if(((annotblock->onset>=chunk_starttime)||(file_number==1)) &&(annotblock->onsethdrsize + (annots_written * edfhdr->recordsize) + offset), SEEK_SET); for(cnt=1; ; cnt++) { if(fgetc(outputfile)==0) break; } fseeko(outputfile, 0LL, SEEK_CUR); cnt += fprintf(outputfile, "+%i", (int)((annotblock->onset - new_hdr_timestamp) / TIME_DIMENSION)); if(annotblock->onset%TIME_DIMENSION) { cnt += fprintf(outputfile, ".%07i", (int)((annotblock->onset - new_hdr_timestamp) % TIME_DIMENSION)); fseeko(outputfile, -1LL, SEEK_CUR); while(fgetc(outputfile)=='0') { fseeko(outputfile, -2LL, SEEK_CUR); cnt--; } } fseeko(outputfile, 0LL, SEEK_CUR); if(annotblock->duration[0]!=0) { fputc(21, outputfile); cnt++; cnt += fprintf(outputfile, "%s", annotblock->duration); } fputc(20, outputfile); cnt++; for(i = 0; i < (annot_signal_size - cnt - 2); i++) { if(annotblock->annotation[i]==0) break; fputc(annotblock->annotation[i], outputfile); cnt++; } fputc(20, outputfile); cnt++; for(i = cnt; i < annot_signal_size; i++) { fputc(0, outputfile); } annots_written++; } annotblock = annotblock->next_annotation; } } fclose(outputfile); datarecords_written = 0; new_hdr_timestamp = next_timestamp; new_hdr_timestamp -= next_timestamp % TIME_DIMENSION; chunk_starttime = next_timestamp; file_number++; strcpy(output_path, inputpath); remove_extension_from_filename(output_path); if(edfhdr->edfplus) { sprintf(output_path + strlen(output_path), "_%04i.edf", file_number); } else { sprintf(output_path + strlen(output_path), "_%04i.bdf", file_number); } strcpy(txt_string, "Creating file "); len = strlen(txt_string); get_filename_from_path(txt_string + len, output_path, MAX_PATH_LENGTH - len); textEdit1->append(txt_string); outputfile = fopeno(output_path, "w+b"); if(outputfile==NULL) { progress.reset(); textEdit1->append("Error, can not open outputfile for writing.\n"); free_annotations(annotationlist[0]); free(edfhdr->edfparam); free(edfhdr); free(fileheader); free(readbuf); fclose(inputfile); pushButton1->setEnabled(true); return; } if(fwrite(fileheader, edfhdr->hdrsize, 1, outputfile) != 1) { progress.reset(); textEdit1->append("Write error.\n"); free_annotations(annotationlist[0]); free(edfhdr->edfparam); free(edfhdr); free(fileheader); free(readbuf); fclose(inputfile); fclose(outputfile); pushButton1->setEnabled(true); return; } } cnt = sprintf(tal, "+%i", (int)((next_timestamp - new_hdr_timestamp) / TIME_DIMENSION)); if((next_timestamp - new_hdr_timestamp)%TIME_DIMENSION) { cnt += sprintf(tal + cnt, ".%07i", (int)((next_timestamp - new_hdr_timestamp) % TIME_DIMENSION)); for(i=cnt-1; i>0; i--) { if(tal[i]!='0') break; cnt--; } } tal[cnt++] = 20; tal[cnt++] = 20; for(i=cnt; irecordsize, 1, outputfile) != 1) { progress.reset(); textEdit1->append("Write error.\n"); free_annotations(annotationlist[0]); free(edfhdr->edfparam); free(edfhdr); free(fileheader); free(readbuf); fclose(inputfile); fclose(outputfile); pushButton1->setEnabled(true); return; } datarecords_written++; former_timestamp = next_timestamp; } write_values_to_hdr(outputfile, new_hdr_timestamp, datarecords_written, edfhdr); annotblock = annotationlist[0]; annots_written = 0; if(annotblock!=NULL) { while(annotblock!=NULL) { if((annotblock->onset>=chunk_starttime)&&(annots_writtenhdrsize + (annots_written * edfhdr->recordsize) + offset), SEEK_SET); for(cnt=1; ; cnt++) { if(fgetc(outputfile)==0) break; } fseeko(outputfile, 0LL, SEEK_CUR); cnt += fprintf(outputfile, "+%i", (int)((annotblock->onset - new_hdr_timestamp) / TIME_DIMENSION)); if(annotblock->onset%TIME_DIMENSION) { cnt += fprintf(outputfile, ".%07i", (int)((annotblock->onset - new_hdr_timestamp) % TIME_DIMENSION)); fseeko(outputfile, -1LL, SEEK_CUR); while(fgetc(outputfile)=='0') { fseeko(outputfile, -2LL, SEEK_CUR); cnt--; } } fseeko(outputfile, 0LL, SEEK_CUR); if(annotblock->duration[0]!=0) { fputc(21, outputfile); cnt++; cnt += fprintf(outputfile, "%s", annotblock->duration); } fputc(20, outputfile); cnt++; for(i = 0; i < (annot_signal_size - cnt - 2); i++) { if(annotblock->annotation[i]==0) break; fputc(annotblock->annotation[i], outputfile); cnt++; } fputc(20, outputfile); cnt++; for(i = cnt; i < annot_signal_size; i++) { fputc(0, outputfile); } annots_written++; } annotblock = annotblock->next_annotation; } } free_annotations(annotationlist[0]); free(edfhdr->edfparam); free(edfhdr); free(fileheader); free(readbuf); fclose(inputfile); fclose(outputfile); progress.reset(); textEdit1->append("Done\n"); pushButton1->setEnabled(true); } void UI_EDFDwindow::write_values_to_hdr(FILE *outputfile, long long timestamp, int datarecords, struct edfhdrblock *edfhdr) { int i; struct date_time_struct date_time; utc_to_date_time(edfhdr->utc_starttime + (timestamp / TIME_DIMENSION), &date_time); fseeko(outputfile, 98LL, SEEK_SET); fprintf(outputfile, "%02i-%s-%04i", date_time.day, date_time.month_str, date_time.year); fseeko(outputfile, 168LL, SEEK_SET); fprintf(outputfile, "%02i.%02i.%02i%02i.%02i.%02i", date_time.day, date_time.month, date_time.year % 100, date_time.hour, date_time.minute, date_time.second); fseeko(outputfile, 192LL, SEEK_SET); if(edfhdr->edfplus) { fprintf(outputfile, "EDF+C"); } else { fprintf(outputfile, "BDF+C"); } for(i=0; i<39; i++) { fputc(' ', outputfile); } fseeko(outputfile, 236LL, SEEK_SET); fprintf(outputfile, "%-8i", datarecords); } long long UI_EDFDwindow::get_datarecord_timestamp(char *str) { int i, len=8, hasdot=0, dotposition=0; long long value=0LL, radix; for(i=0; ; i++) { if(str[i]==20) { len = i; break; } } for(i=0; i=1; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } radix = TIME_DIMENSION / 10; for(i=dotposition+1; i=1; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } } if(str[0]=='-') { value = -value; } return(value); } void UI_EDFDwindow::free_annotations(struct annotationblock *annot) { if(annot==NULL) { return; } while(annot->next_annotation) { annot = annot->next_annotation; free(annot->former_annotation); } free(annot); } edfbrowser_157_source/PaxHeaders.7921/fino2edf.cpp0000644000000000000000000000013212646460742017066 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/fino2edf.cpp0000644000175000001440000004777412646460742017452 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "fino2edf.h" UI_FINO2EDFwindow::UI_FINO2EDFwindow(char *recent_dir, char *save_dir) { recent_opendir = recent_dir; recent_savedir = save_dir; myobjectDialog = new QDialog; myobjectDialog->setMinimumSize(600, 240); myobjectDialog->setMaximumSize(600, 240); myobjectDialog->setWindowTitle("Finometer to EDF converter"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); PatientnameLabel = new QLabel(myobjectDialog); PatientnameLabel->setGeometry(20, 20, 140, 25); PatientnameLabel->setText("Subject name"); RecordingLabel = new QLabel(myobjectDialog); RecordingLabel->setGeometry(20, 55, 140, 25); RecordingLabel->setText("Recording"); DatetimeLabel = new QLabel(myobjectDialog); DatetimeLabel->setGeometry(20, 90, 140, 25); DatetimeLabel->setText("Startdate and time"); PatientnameLineEdit = new QLineEdit(myobjectDialog); PatientnameLineEdit->setGeometry(160, 20, 420, 25); PatientnameLineEdit->setMaxLength(80); RecordingLineEdit = new QLineEdit(myobjectDialog); RecordingLineEdit->setGeometry(160, 55, 420, 25); RecordingLineEdit->setMaxLength(80); RecordingLineEdit->setText("Finometer"); StartDatetimeedit = new QDateTimeEdit(myobjectDialog); StartDatetimeedit->setGeometry(160, 90, 140, 25); StartDatetimeedit->setDisplayFormat("dd/MM/yyyy hh:mm:ss"); StartDatetimeedit->setDateTime(QDateTime::currentDateTime()); pushButton1 = new QPushButton(myobjectDialog); pushButton1->setGeometry(20, 190, 100, 25); pushButton1->setText("Select File"); pushButton2 = new QPushButton(myobjectDialog); pushButton2->setGeometry(480, 190, 100, 25); pushButton2->setText("Close"); QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton())); QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close())); myobjectDialog->exec(); } void UI_FINO2EDFwindow::SelectFileButton() { FILE *inputfile=NULL, *outputfile=NULL; int i, j, k, p, temp, separator=';', edfsignals=0, ok, timestep, new_smpl_time=0, datarecords, str_start, column, line_nr; char txt_string[2048], path[512], outputfilename[MAX_PATH_LENGTH], line[2048], scratchpad[128], labels[MAX_SIGNALS][17], phys_dim[MAX_SIGNALS][9], phys_min[MAX_SIGNALS][9], phys_max[MAX_SIGNALS][9], patientname[81], recording[81], datetime[17]; double sensitivity[MAX_SIGNALS], new_value[MAX_SIGNALS], old_value[MAX_SIGNALS]; union{ short two; char one[2]; } var; for(j=0; jtext().toLatin1().data()))) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a subjectname."); messagewindow.exec(); enable_widgets(true); return; } if(!(strlen(RecordingLineEdit->text().toLatin1().data()))) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a recordingdescription."); messagewindow.exec(); enable_widgets(true); return; } strcpy(path, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "Text files (*.txt *.TXT)").toLocal8Bit().data()); if(!strcmp(path, "")) { enable_widgets(true); return; } get_directory_from_path(recent_opendir, path, MAX_PATH_LENGTH); inputfile = fopeno(path, "rb"); if(inputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for reading.", path); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); enable_widgets(true); return; } /***************** check if the txtfile is valid ******************************/ rewind(inputfile); if(fread(scratchpad, 5, 1, inputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading the inputfile."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(strncmp(scratchpad, "\"T\";", 4)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Unknown data in file (1)."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } while(1) { temp = fgetc(inputfile); if(temp==EOF) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Reached end of file unexpectedly (2)."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(temp=='\n') break; } if(fread(scratchpad, 2, 1, inputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading inputfile (3)."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(strncmp(scratchpad, "\"s\";", 4)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Unknown data in file (4)."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } /***************** collect items *****************************************/ rewind(inputfile); while(1) { temp = fgetc(inputfile); if(temp==EOF) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Reached end of file unexpectedly (5)."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(temp==separator) { break; } } i = 0; while(temp!='\n') { temp = fgetc(inputfile); if(temp==EOF) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Reached end of file unexpectedly (6)."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(temp=='\r') { continue; } if((temp==separator)||(temp=='\n')) { if(edfsignals>=MAX_SIGNALS) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Too many labels/signals (7)."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } line[i] = 0; ok = 0; if(!strcmp(line, "\" reSYS\"")) { strcpy(labels[edfsignals], "reSYS "); strcpy(phys_dim[edfsignals], "mmHg "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "\" fiSYS\"")) { strcpy(labels[edfsignals], "fiSYS "); strcpy(phys_dim[edfsignals], "mmHg "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "\" reDIA\"")) { strcpy(labels[edfsignals], "reDIA "); strcpy(phys_dim[edfsignals], "mmHg "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "\" fiDIA\"")) { strcpy(labels[edfsignals], "fiDIA "); strcpy(phys_dim[edfsignals], "mmHg "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "\" reMAP\"")) { strcpy(labels[edfsignals], "reMAP "); strcpy(phys_dim[edfsignals], "mmHg "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "\" fiMAP\"")) { strcpy(labels[edfsignals], "fiMAP "); strcpy(phys_dim[edfsignals], "mmHg "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "\" HR\"")) { strcpy(labels[edfsignals], "HR "); strcpy(phys_dim[edfsignals], "bpm "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "\" IBI\"")) { strcpy(labels[edfsignals], "IBI "); strcpy(phys_dim[edfsignals], "s "); strcpy(phys_min[edfsignals], "-31.744 "); strcpy(phys_max[edfsignals], "31.744 "); sensitivity[edfsignals] = 1000.0; ok = 1; } if(!strcmp(line, "\" SV\"")) { strcpy(labels[edfsignals], "SV "); strcpy(phys_dim[edfsignals], "ml "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "\" CO\"")) { strcpy(labels[edfsignals], "CO "); strcpy(phys_dim[edfsignals], "lpm "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "\" EJT\"")) { strcpy(labels[edfsignals], "EJT "); strcpy(phys_dim[edfsignals], "s "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "\" TPR\"")) { strcpy(labels[edfsignals], "TPR "); strcpy(phys_dim[edfsignals], "MU "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "\" Artifact\"")) { strcpy(labels[edfsignals], "Artifact "); strcpy(phys_dim[edfsignals], "_TPSROD2"); strcpy(phys_min[edfsignals], "0 "); strcpy(phys_max[edfsignals], "10000000"); sensitivity[edfsignals] = 0.0063488; ok = 1; } if(!strcmp(line, "\" Zao\"")) { strcpy(labels[edfsignals], "Zao "); strcpy(phys_dim[edfsignals], "mMU "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "\" Cwk\"")) { strcpy(labels[edfsignals], "Cwk "); strcpy(phys_dim[edfsignals], "MU "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "\" Height\"")) { strcpy(labels[edfsignals], "Height "); strcpy(phys_dim[edfsignals], "mmHg "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!ok) { snprintf(txt_string, 2048, "Found unknown label/signal: %s", line); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } edfsignals++; i = 0; } if(temp==separator) { continue; } line[i++] = temp; } if(!edfsignals) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There are no labels/signals."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } p = sprintf(patientname, "%s", PatientnameLineEdit->text().toLatin1().data()); latin1_to_ascii(patientname, p); for( ; p<80; p++) { patientname[p] = ' '; } patientname[80] = 0; p = sprintf(recording, "%s", RecordingLineEdit->text().toLatin1().data()); latin1_to_ascii(recording, p); for( ; p<80; p++) { recording[p] = ' '; } recording[80] = 0; sprintf(datetime, "%02i.%02i.%02i%02i.%02i.%02i", StartDatetimeedit->date().day(), StartDatetimeedit->date().month(), StartDatetimeedit->date().year() % 100, StartDatetimeedit->time().hour(), StartDatetimeedit->time().minute(), StartDatetimeedit->time().second()); datetime[16] = 0; /***************** write header *****************************************/ get_filename_from_path(outputfilename, path, MAX_PATH_LENGTH); remove_extension_from_filename(outputfilename); strcat(outputfilename, "_finometer.edf"); path[0] = 0; if(recent_savedir[0]!=0) { strcpy(path, recent_savedir); strcat(path, "/"); } strcat(path, outputfilename); strcpy(path, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(path), "EDF files (*.edf *.EDF)").toLocal8Bit().data()); if(!strcmp(path, "")) { enable_widgets(true); fclose(inputfile); return; } get_directory_from_path(recent_savedir, path, MAX_PATH_LENGTH); outputfile = fopeno(path, "wb"); if(outputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for writing.", path); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); enable_widgets(true); fclose(inputfile); return; } fprintf(outputfile, "0 "); fprintf(outputfile, "%s", patientname); fprintf(outputfile, "%s", recording); fprintf(outputfile, "%s", datetime); fprintf(outputfile, "%-8i", 256 * edfsignals + 256); fprintf(outputfile, " "); fprintf(outputfile, "-1 "); fprintf(outputfile, "0.01 "); fprintf(outputfile, "%-4i", edfsignals); for(i=0; i1) break; } QApplication::setOverrideCursor(Qt::WaitCursor); for(k=0; k<10; k++) qApp->processEvents(); i = 0; column = 0; datarecords = 0; str_start = 0; line_nr = 2; while(1) { temp = fgetc(inputfile); if(temp==EOF) { for(k=0; k31744) temp = 31744; if(temp<-31744) temp = -31744; var.two = (short)temp; fputc(var.one[0], outputfile); fputc(var.one[1], outputfile); } datarecords++; break; } line[i] = temp; /**************************************/ if(line[i]==',') { line[i] = '.'; } if((line[i]==separator)||(line[i]=='\n')) { if(column) { new_value[column-1] = atof(line + str_start); } else { new_smpl_time = (int)(atof(line + str_start) * 100.0); } if(line[i]=='\n') { /**************************************/ line_nr++; if(column!=edfsignals) { QApplication::restoreOverrideCursor(); snprintf(txt_string, 2048, "Number of separators in line %i is wrong.", line_nr); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); fclose(inputfile); fclose(outputfile); enable_widgets(true); return; } timestep = new_smpl_time - datarecords; if(timestep<=0) { QApplication::restoreOverrideCursor(); snprintf(txt_string, 2048, "Timestep <= 0 in line %i.", line_nr); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); fclose(inputfile); fclose(outputfile); enable_widgets(true); return; } for(j=0; j31744) temp = 31744; if(temp<-31744) temp = -31744; var.two = (short)temp; fputc(var.one[0], outputfile); fputc(var.one[1], outputfile); } datarecords++; } for(j=0; j2046) { QApplication::restoreOverrideCursor(); snprintf(txt_string, 2048, "Line %i is too long.", line_nr); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); fclose(inputfile); fclose(outputfile); enable_widgets(true); return; } } QApplication::restoreOverrideCursor(); fseeko(outputfile, 236LL, SEEK_SET); fprintf(outputfile, "%-8i", datarecords); if(fclose(outputfile)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while closing outputfile."); messagewindow.exec(); enable_widgets(true); fclose(inputfile); return; } if(fclose(inputfile)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while closing inputfile."); messagewindow.exec(); } snprintf(txt_string, 2048, "Done, EDF file is located at %s", path); QMessageBox messagewindow(QMessageBox::Information, "Ready", txt_string); messagewindow.setIconPixmap(QPixmap(":/images/ok.png")); messagewindow.exec(); enable_widgets(true); } void UI_FINO2EDFwindow::enable_widgets(bool toggle) { StartDatetimeedit->setEnabled(toggle); PatientnameLineEdit->setEnabled(toggle); RecordingLineEdit->setEnabled(toggle); pushButton1->setEnabled(toggle); pushButton2->setEnabled(toggle); } edfbrowser_157_source/PaxHeaders.7921/save_montage_dialog.h0000644000000000000000000000013212646460742021026 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/save_montage_dialog.h0000644000175000001440000000351712646460742021375 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef SAVEMONTAGEFORM1_H #define SAVEMONTAGEFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "xml.h" #include "spectrum_dock.h" class UI_Mainwindow; class UI_SaveMontagewindow : public QObject { Q_OBJECT public: UI_SaveMontagewindow(QWidget *parent); UI_Mainwindow *mainwindow; private: QDialog *SaveMontageDialog; QLabel *label1; QListWidget *filelist; QPushButton *CloseButton, *SaveButton; private slots: void SaveButtonClicked(); }; #endif // SAVEMONTAGEFORM1_H edfbrowser_157_source/PaxHeaders.7921/gpl.txt0000644000000000000000000000013212646460742016211 xustar0030 mtime=1452958178.262246682 30 atime=1452958178.262246682 30 ctime=1452958178.262246682 edfbrowser_157_source/gpl.txt0000644000175000001440000010532212646460742016555 0ustar00guvusers00000000000000 This is free software, it is experimental and available under the GPL License version 3. Despite this software is intend to be useful, there is no warranty, Use this software at your own risk! EDFbrowser may NOT be used in safety-critical applications, such as life-support medical systems. The author is NOT responsible for any consequences. For research and educational purpose only. GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . edfbrowser_157_source/PaxHeaders.7921/signalcurve.cpp0000644000000000000000000000012712646460742017720 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/signalcurve.cpp0000644000175000001440000016776212646460742020300 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "signalcurve.h" SignalCurve::SignalCurve(QWidget *w_parent) : QWidget(w_parent) { setAttribute(Qt::WA_OpaquePaintEvent); recent_savedir[0] = 0; SignalColor = Qt::blue; tracewidth = 0; BackgroundColor = Qt::gray; RasterColor = Qt::darkGray; BorderColor = Qt::lightGray; RulerColor = Qt::black; TextColor = Qt::black; crosshair_1_color = Qt::red; Marker1Pen.setStyle(Qt::DashLine); Marker1Pen.setColor(Qt::yellow); Marker2Pen.setStyle(Qt::DashLine); Marker2Pen.setColor(Qt::yellow); bufsize = 0; dbuf = NULL; fbuf = NULL; ibuf = NULL; bordersize = 60; drawHruler = 1; drawVruler = 1; h_ruler_startvalue = 0.0; h_ruler_endvalue = 100.0; drawcurve_before_raster = 0; h_label[0] = 0; v_label[0] = 0; upperlabel1[0] = 0; upperlabel2[0] = 0; lowerlabel[0] = 0; max_value = 100.0; min_value = -100.0; extra_button = 0; extra_button_txt[0] = 0; use_move_events = 0; crosshair_1_active = 0; crosshair_1_moving = 0; crosshair_1_value = 0.0; crosshair_1_value_2 = 0.0; crosshair_1_x_position = 0; marker_1_position = 0.25; marker_1_moving = 0; marker_2_position = 0.75; marker_2_moving = 0; fillsurface = 0; cursorEnabled = true; printEnabled = true; dashBoardEnabled = true; updates_enabled = true; Marker1Enabled = false; Marker1MovableEnabled = false; Marker2Enabled = false; Marker2MovableEnabled = false; curveUpSideDown = false; line1Enabled = false; spectrum_color = NULL; old_w = 10000; } void SignalCurve::clear() { dbuf = NULL; fbuf = NULL; ibuf = NULL; bufsize = 0; use_move_events = 0; crosshair_1_active = 0; crosshair_1_moving = 0; crosshair_1_value = 0.0; crosshair_1_value_2 = 0.0; crosshair_1_x_position = 0; marker_1_position = 0.25; marker_2_position = 0.75; Marker1Enabled = false; Marker1MovableEnabled = false; Marker2Enabled = false; Marker2MovableEnabled = false; line1Enabled = false; update(); } void SignalCurve::mousePressEvent(QMouseEvent *press_event) { int m_x, m_y; setFocus(Qt::MouseFocusReason); w = width(); h = height(); m_x = press_event->x() - bordersize; m_y = press_event->y() - bordersize; if(m_x < 0 || m_x > (w - (bordersize * 2)) || m_y < 0 || m_y > (h - (bordersize * 2))) { return; } if(press_event->button()==Qt::LeftButton) { if(printEnabled == true) { if((m_y<21)&&(m_y>3)&&(m_x>((w - (bordersize * 2)) - 43))&&(m_x<((w - (bordersize * 2)) - 3))) { exec_sidemenu(); return; } } if(dashBoardEnabled == true) { if((m_y<61)&&(m_y>43)&&(m_x>((w - (bordersize * 2)) - 43))&&(m_x<((w - (bordersize * 2)) - 3))) { emit dashBoardClicked(); return; } } if(cursorEnabled == true) { if((m_y<41)&&(m_y>23)&&(m_x>((w - (bordersize * 2)) - 43))&&(m_x<((w - (bordersize * 2)) - 3))) { if(crosshair_1_active) { crosshair_1_active = 0; crosshair_1_moving = 0; use_move_events = 0; setMouseTracking(false); } else { crosshair_1_active = 1; if(!crosshair_1_x_position) { crosshair_1_value = 0.0; crosshair_1_x_position = (w - (bordersize * 2)) / 2; crosshair_1_y_position = (h - (bordersize * 2)) / 2; mouse_old_x = crosshair_1_x_position; mouse_old_y = crosshair_1_y_position; } } update(); return; } } if(crosshair_1_active) { if((m_y<(crosshair_1_y_position + 15))&&(m_y>(crosshair_1_y_position - 25))&&(m_x>crosshair_1_x_position)&&(m_x<(crosshair_1_x_position + 65))) { crosshair_1_moving = 1; use_move_events = 1; setMouseTracking(true); mouse_old_x = m_x; mouse_old_y = m_y; } if(m_x>(crosshair_1_x_position-10)&&(m_x<(crosshair_1_x_position + 10))) { crosshair_1_moving = 1; use_move_events = 1; setMouseTracking(true); mouse_old_x = m_x; mouse_old_y = m_y; } } if((Marker1MovableEnabled == true) && (Marker1Enabled == true)) { marker_1_x_position = (w - (bordersize * 2)) * marker_1_position; if(m_x > (marker_1_x_position - 5) && (m_x < (marker_1_x_position + 5))) { marker_1_moving = 1; use_move_events = 1; setMouseTracking(true); mouse_old_x = m_x; mouse_old_y = m_y; } } if((Marker2MovableEnabled == true) && (Marker2Enabled == true)) { marker_2_x_position = (w - (bordersize * 2)) * marker_2_position; if(m_x > (marker_2_x_position - 5) && (m_x < (marker_2_x_position + 5))) { marker_2_moving = 1; use_move_events = 1; setMouseTracking(true); mouse_old_x = m_x; mouse_old_y = m_y; } } } } void SignalCurve::mouseReleaseEvent(QMouseEvent *) { crosshair_1_moving = 0; marker_1_moving = 0; marker_2_moving = 0; use_move_events = 0; setMouseTracking(false); } void SignalCurve::mouseMoveEvent(QMouseEvent *move_event) { if(!use_move_events) { return; } mouse_x = move_event->x() - bordersize; mouse_y = move_event->y() - bordersize; if(crosshair_1_moving) { crosshair_1_x_position += (mouse_x - mouse_old_x); mouse_old_x = mouse_x; if(crosshair_1_x_position<2) { crosshair_1_x_position = 2; } if(crosshair_1_x_position>(w-(bordersize * 2) -2)) { crosshair_1_x_position = w-(bordersize * 2) -2; } crosshair_1_y_position += (mouse_y - mouse_old_y); mouse_old_y = mouse_y; if(crosshair_1_y_position<25) { crosshair_1_y_position = 25; } if(crosshair_1_y_position>(h-(bordersize * 2) -25)) { crosshair_1_y_position = h-(bordersize * 2) -25; } } if(marker_1_moving) { marker_1_x_position += (mouse_x - mouse_old_x); mouse_old_x = mouse_x; if(marker_1_x_position<2) { marker_1_x_position = 2; } if(marker_1_x_position>(w-(bordersize * 2) - 2)) { marker_1_x_position = w-(bordersize * 2) - 2; } marker_1_position = (double)marker_1_x_position / (double)(w-(bordersize * 2)); emit markerHasMoved(); } if(marker_2_moving) { marker_2_x_position += (mouse_x - mouse_old_x); mouse_old_x = mouse_x; if(marker_2_x_position<2) { marker_2_x_position = 2; } if(marker_2_x_position>(w-(bordersize * 2) - 2)) { marker_2_x_position = w-(bordersize * 2) - 2; } marker_2_position = (double)marker_2_x_position / (double)(w-(bordersize * 2)); emit markerHasMoved(); } update(); } void SignalCurve::shiftCursorIndexLeft(int idxs) { int idx; double ppi; if(!crosshair_1_active) { return; } if(bufsize < 2) { return; } w = width(); ppi = (double)(w-(bordersize * 2)) / (double)bufsize; idx = (double)crosshair_1_x_position / ppi; idx -= idxs; if(idx < 0) { idx = 0; } if(idx >= bufsize) { idx = bufsize - 1; } crosshair_1_x_position = (double)idx * ppi + (0.5 * ppi); update(); } void SignalCurve::shiftCursorIndexRight(int idxs) { int idx; double ppi; if(!crosshair_1_active) { return; } if(bufsize < 2) { return; } w = width(); ppi = (double)(w-(bordersize * 2)) / (double)bufsize; idx = (double)crosshair_1_x_position / ppi; idx += idxs; if(idx < 0) { idx = 0; } if(idx >= bufsize) { idx = bufsize - 1; } crosshair_1_x_position = (double)idx * ppi + (0.5 * ppi); update(); } void SignalCurve::shiftCursorPixelsLeft(int pixels) { if(!crosshair_1_active) { return; } crosshair_1_x_position -= pixels; if(crosshair_1_x_position<2) { crosshair_1_x_position = 2; } update(); } void SignalCurve::shiftCursorPixelsRight(int pixels) { if(!crosshair_1_active) { return; } w = width(); crosshair_1_x_position += pixels; if(crosshair_1_x_position>(w-(bordersize * 2) -2)) { crosshair_1_x_position = w-(bordersize * 2) -2; } update(); } void SignalCurve::resizeEvent(QResizeEvent *resize_event) { if(crosshair_1_active) { crosshair_1_x_position *= ((double)(width() - (bordersize * 2)) / (double)(old_w - (bordersize * 2))); } QWidget::resizeEvent(resize_event); } void SignalCurve::exec_sidemenu() { sidemenu = new QDialog(this); if(extra_button) { sidemenu->setMinimumSize(120, 190); sidemenu->setMaximumSize(120, 190); } else { sidemenu->setMinimumSize(120, 160); sidemenu->setMaximumSize(120, 160); } sidemenu->setWindowTitle("Print"); sidemenu->setModal(true); sidemenu->setAttribute(Qt::WA_DeleteOnClose, true); sidemenuButton1 = new QPushButton(sidemenu); sidemenuButton1->setGeometry(10, 10, 100, 20); sidemenuButton1->setText("to printer"); #if QT_VERSION < 0x050000 sidemenuButton2 = new QPushButton(sidemenu); sidemenuButton2->setGeometry(10, 40, 100, 20); sidemenuButton2->setText("to Postscript"); #endif sidemenuButton3 = new QPushButton(sidemenu); sidemenuButton3->setGeometry(10, 70, 100, 20); sidemenuButton3->setText("to PDF"); sidemenuButton4 = new QPushButton(sidemenu); sidemenuButton4->setGeometry(10, 100, 100, 20); sidemenuButton4->setText("to Image"); sidemenuButton5 = new QPushButton(sidemenu); sidemenuButton5->setGeometry(10, 130, 100, 20); sidemenuButton5->setText("to ASCII"); if(extra_button) { sidemenuButton6 = new QPushButton(sidemenu); sidemenuButton6->setGeometry(10, 160, 100, 20); sidemenuButton6->setText(extra_button_txt); } QObject::connect(sidemenuButton1, SIGNAL(clicked()), this, SLOT(print_to_printer())); #if QT_VERSION < 0x050000 QObject::connect(sidemenuButton2, SIGNAL(clicked()), this, SLOT(print_to_postscript())); #endif QObject::connect(sidemenuButton3, SIGNAL(clicked()), this, SLOT(print_to_pdf())); QObject::connect(sidemenuButton4, SIGNAL(clicked()), this, SLOT(print_to_image())); QObject::connect(sidemenuButton5, SIGNAL(clicked()), this, SLOT(print_to_ascii())); if(extra_button) { QObject::connect(sidemenuButton6, SIGNAL(clicked()), this, SLOT(send_button_event())); } sidemenu->exec(); } void SignalCurve::send_button_event() { emit extra_button_clicked(); sidemenu->close(); } void SignalCurve::create_button(const char *txt) { extra_button = 1; strncpy(extra_button_txt, txt, 16); extra_button_txt[15] = 0; } void SignalCurve::backup_colors_for_printing(void) { backup_color_1 = SignalColor; SignalColor = Qt::black; backup_color_2 = RasterColor; RasterColor = Qt::black; backup_color_3 = BorderColor; BorderColor = Qt::black; backup_color_4 = RulerColor; RulerColor = Qt::black; backup_color_5 = TextColor; TextColor = Qt::black; backup_color_6 = Marker1Pen.color(); Marker1Pen.setColor(Qt::black); } void SignalCurve::restore_colors_after_printing(void) { SignalColor = backup_color_1; RasterColor = backup_color_2; BorderColor = backup_color_3; RulerColor = backup_color_4; TextColor = backup_color_5; Marker1Pen.setColor(backup_color_6); } void SignalCurve::print_to_ascii() { int i; char path[SC_MAX_PATH_LEN]; FILE *outputfile; path[0] = 0; if(recent_savedir[0]!=0) { strcpy(path, recent_savedir); strcat(path, "/"); } strcat(path, "curve.csv"); strcpy(path, QFileDialog::getSaveFileName(0, "Print to ASCII / CSV", QString::fromLocal8Bit(path), "ASCII / CSV files (*.csv *.CSV *.txt *.TXT)").toLocal8Bit().data()); if(!strcmp(path, "")) { sidemenu->close(); return; } get_directory_from_path(recent_savedir, path, SC_MAX_PATH_LEN); outputfile = fopen(path, "wb"); if(path == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open outputfile for writing."); messagewindow.exec(); return; } if(ibuf != NULL) { for(i=0; iclose(); } #if QT_VERSION < 0x050000 void SignalCurve::print_to_postscript() { char path[SC_MAX_PATH_LEN]; path[0] = 0; if(recent_savedir[0]!=0) { strcpy(path, recent_savedir); strcat(path, "/"); } strcat(path, "curve.ps"); strcpy(path, QFileDialog::getSaveFileName(0, "Print to PostScript", QString::fromLocal8Bit(path), "PostScript files (*.ps *.PS)").toLocal8Bit().data()); if(!strcmp(path, "")) { sidemenu->close(); return; } get_directory_from_path(recent_savedir, path, SC_MAX_PATH_LEN); QPrinter curve_printer(QPrinter::HighResolution); curve_printer.setOutputFormat(QPrinter::PostScriptFormat); curve_printer.setOutputFileName(path); curve_printer.setPageSize(QPrinter::A4); curve_printer.setOrientation(QPrinter::Landscape); backup_colors_for_printing(); QPainter paint(&curve_printer); drawWidget_to_printer(&paint, curve_printer.pageRect().width(), curve_printer.pageRect().height()); restore_colors_after_printing(); sidemenu->close(); } #endif void SignalCurve::print_to_pdf() { char path[SC_MAX_PATH_LEN]; path[0] = 0; if(recent_savedir[0]!=0) { strcpy(path, recent_savedir); strcat(path, "/"); } strcat(path, "curve.pdf"); strcpy(path, QFileDialog::getSaveFileName(0, "Print to PDF", QString::fromLocal8Bit(path), "PDF files (*.pdf *.PDF)").toLocal8Bit().data()); if(!strcmp(path, "")) { sidemenu->close(); return; } get_directory_from_path(recent_savedir, path, SC_MAX_PATH_LEN); QPrinter curve_printer(QPrinter::HighResolution); curve_printer.setOutputFormat(QPrinter::PdfFormat); curve_printer.setOutputFileName(path); curve_printer.setPageSize(QPrinter::A4); curve_printer.setOrientation(QPrinter::Landscape); backup_colors_for_printing(); QPainter paint(&curve_printer); #if QT_VERSION >= 0x050000 paint.setRenderHint(QPainter::Qt4CompatiblePainting, true); #endif drawWidget_to_printer(&paint, curve_printer.pageRect().width(), curve_printer.pageRect().height()); restore_colors_after_printing(); sidemenu->close(); } void SignalCurve::print_to_image() { char path[SC_MAX_PATH_LEN]; path[0] = 0; if(recent_savedir[0]!=0) { strcpy(path, recent_savedir); strcat(path, "/"); } strcat(path, "curve.png"); strcpy(path, QFileDialog::getSaveFileName(0, "Print to Image", QString::fromLocal8Bit(path), "PNG files (*.png *.PNG)").toLocal8Bit().data()); if(!strcmp(path, "")) { sidemenu->close(); return; } get_directory_from_path(recent_savedir, path, SC_MAX_PATH_LEN); QPixmap pixmap(width(), height()); QPainter paint(&pixmap); #if QT_VERSION >= 0x050000 paint.setRenderHint(QPainter::Qt4CompatiblePainting, true); #endif drawWidget(&paint, width(), height()); pixmap.save(path, "PNG", 90); sidemenu->close(); } void SignalCurve::print_to_printer() { QPrinter curve_printer(QPrinter::HighResolution); curve_printer.setOutputFormat(QPrinter::NativeFormat); curve_printer.setPageSize(QPrinter::A4); curve_printer.setOrientation(QPrinter::Landscape); QPrintDialog printerdialog(&curve_printer, this); printerdialog.setWindowTitle("Print"); if(!(printerdialog.exec()==QDialog::Accepted)) { sidemenu->close(); return; } backup_colors_for_printing(); QPainter paint(&curve_printer); #if QT_VERSION >= 0x050000 paint.setRenderHint(QPainter::Qt4CompatiblePainting, true); #endif drawWidget_to_printer(&paint, curve_printer.pageRect().width(), curve_printer.pageRect().height()); restore_colors_after_printing(); sidemenu->close(); } void SignalCurve::drawWidget_to_printer(QPainter *painter, int curve_w, int curve_h) { int i, j, precision, bordersize_backup=0, p_w, p_divisor, p_range, p_tmp, p_h, p2_divisor, p2_range, p2_multiplier, p2_ruler_startvalue, p2_ruler_endvalue, p2_tmp; long long p_multiplier, p_ruler_startvalue, p_ruler_endvalue; char str[128]; double v_sens, offset, h_step, value, p_factor, p_pixels_per_unit, p2_pixels_per_unit; QString q_str; QFont curve_font; QPen printer_pen; curve_w -= 30; curve_h -= 30; p_factor = (double)curve_w / width(); bordersize_backup = bordersize; bordersize *= p_factor; curve_font.setFamily("Arial"); curve_font.setPixelSize((int)((double)curve_w / 104.0)); painter->setFont(curve_font); if((curve_w < ((bordersize * 2) + 5)) || (curve_h < ((bordersize * 2) + 5))) { bordersize = bordersize_backup; return; } printer_pen = QPen(Qt::SolidPattern, 2, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin); printer_pen.setColor(Qt::black); painter->setPen(printer_pen); /////////////////////////////////// draw the window /////////////////////////////////////////// painter->drawLine(0, 0, 0, curve_h); painter->drawLine(0, 0, curve_w, 0); painter->drawLine(curve_w, curve_h, curve_w, 0); painter->drawLine(curve_w, curve_h, 0, curve_h); /////////////////////////////////// draw the rulers /////////////////////////////////////////// p_w = curve_w - bordersize - bordersize; p_multiplier = 1; while((h_ruler_endvalue * p_multiplier) < 10000.0) { p_multiplier *= 10; if(p_multiplier > 100000000000000LL) { break; } } p_ruler_startvalue = h_ruler_startvalue * p_multiplier; p_ruler_endvalue = h_ruler_endvalue * p_multiplier; p_range = p_ruler_endvalue - p_ruler_startvalue; p_pixels_per_unit = (double)p_w / (double)p_range; p_divisor = 1; while((p_range / p_divisor) > 10) { p_divisor *= 2; if((p_range / p_divisor) <= 10) { break; } p_divisor /= 2; p_divisor *= 5; if((p_range / p_divisor) <= 10) { break; } p_divisor *= 2; } if(drawHruler && (bordersize > (19 * p_factor))) { painter->drawLine(bordersize, curve_h - bordersize + (5 * p_factor), curve_w - bordersize, curve_h - bordersize + (5 * p_factor)); for(i = (p_ruler_startvalue / p_divisor) * p_divisor; i <= p_ruler_endvalue; i += p_divisor) { if(i < p_ruler_startvalue) { continue; } convert_to_metric_suffix(str, (double)i / (double)p_multiplier, 4); remove_trailing_zeros(str); p_tmp = (double)(i - p_ruler_startvalue) * p_pixels_per_unit; painter->drawText(bordersize + p_tmp - (30 * p_factor), curve_h - bordersize + (18 * p_factor), 60 * p_factor, 16 * p_factor, Qt::AlignCenter | Qt::TextSingleLine, str); painter->drawLine(bordersize + p_tmp, curve_h - bordersize + (5 * p_factor), bordersize + p_tmp, curve_h - bordersize + ((5 + 10) * p_factor)); } painter->drawText(curve_w - bordersize + (20 * p_factor), curve_h - bordersize + (18 * p_factor), 40 * p_factor, 16 * p_factor, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, h_label); } /////////////////////////////////// draw the vertical ruler /////////////////////////////////////////// p_h = curve_h - bordersize - bordersize; p2_multiplier = 1; while(((max_value - min_value) * p2_multiplier) < 10000.0) { p2_multiplier *= 10; if(p2_multiplier > 10000000) { break; } } p2_ruler_startvalue = min_value * p2_multiplier; p2_ruler_endvalue = max_value * p2_multiplier; p2_range = p2_ruler_endvalue - p2_ruler_startvalue; if(p2_range < 0) p2_range *= -1; p2_pixels_per_unit = (double)p_h / (double)p2_range; p2_divisor = 1; while((p2_range / p2_divisor) > 10) { p2_divisor *= 2; if((p2_range / p2_divisor) <= 10) { break; } p2_divisor /= 2; p2_divisor *= 5; if((p2_range / p2_divisor) <= 10) { break; } p2_divisor *= 2; } if(drawVruler && (bordersize > (29 * p_factor))) { painter->drawLine(bordersize - (5 * p_factor), bordersize, bordersize - (5 * p_factor), curve_h - bordersize); precision = 0; if((max_value < 10.0) && (max_value > -10.0) && (min_value < 10.0) && (min_value > -10.0)) { precision = 1; if((max_value < 1.0) && (max_value > -1.0) && (min_value < 1.0) && (min_value > -1.0)) { precision = 2; if((max_value < 0.1) && (max_value > -0.1) && (min_value < 0.1) && (min_value > -0.1)) { precision = 3; if((max_value < 0.01) && (max_value > -0.01) && (min_value < 0.01) && (min_value > -0.01)) { precision = 4; } } } } for(i = (p2_ruler_startvalue / p2_divisor) * p2_divisor; i <= p2_ruler_endvalue; i += p2_divisor) { if(i < p2_ruler_startvalue) { continue; } q_str.setNum((double)i / (double)p2_multiplier, 'f', precision); p2_tmp = (double)(i - p2_ruler_startvalue) * p2_pixels_per_unit; if(curveUpSideDown == false) { painter->drawText((3 * p_factor), curve_h - bordersize - p2_tmp - (8 * p_factor), (40 * p_factor), (16 * p_factor), Qt::AlignRight | Qt::AlignVCenter | Qt::TextSingleLine, q_str); painter->drawLine(bordersize - (5 * p_factor), curve_h - bordersize - p2_tmp, bordersize - (15 * p_factor), curve_h - bordersize - p2_tmp); } else { painter->drawText((3 * p_factor), bordersize + p2_tmp - (8 * p_factor), (40 * p_factor), (16 * p_factor), Qt::AlignRight | Qt::AlignVCenter | Qt::TextSingleLine, q_str); painter->drawLine(bordersize - (5 * p_factor), bordersize + p2_tmp, bordersize - (15 * p_factor), bordersize + p2_tmp); } } } /////////////////////////////////// draw the labels /////////////////////////////////////////// painter->setFont(curve_font); if(v_label[0] != 0) { painter->drawText(8 * p_factor, 30 * p_factor, 100 * p_factor, 16 * p_factor, Qt::AlignCenter | Qt::TextSingleLine, v_label); } if(upperlabel1[0] != 0) { painter->drawText(curve_w / 2 - (150 * p_factor), 10 * p_factor, 300 * p_factor, 16 * p_factor, Qt::AlignCenter | Qt::TextSingleLine, upperlabel1); } if(upperlabel2[0] != 0) { painter->drawText(curve_w / 2 - (150 * p_factor), 30 * p_factor, 300 * p_factor, 16 * p_factor, Qt::AlignCenter | Qt::TextSingleLine, upperlabel2); } if(lowerlabel[0] != 0) { painter->drawText(curve_w / 2 - (80 * p_factor), curve_h - (20 * p_factor), 160 * p_factor, 16 * p_factor, Qt::AlignCenter | Qt::TextSingleLine, lowerlabel); } /////////////////////////////////// translate coordinates, draw and fill a rectangle /////////////////////////////////////////// painter->translate(QPoint(bordersize, bordersize)); curve_w -= (bordersize * 2); curve_h -= (bordersize * 2); painter->setClipping(true); painter->setClipRegion(QRegion(0, 0, curve_w, curve_h), Qt::ReplaceClip); /////////////////////////////////// draw the rasters /////////////////////////////////////////// painter->drawRect (0, 0, curve_w - 1, curve_h - 1); for(i = (p_ruler_startvalue / p_divisor) * p_divisor; i <= p_ruler_endvalue; i += p_divisor) { if(i < p_ruler_startvalue) { continue; } p_tmp = (double)(i - p_ruler_startvalue) * p_pixels_per_unit; painter->drawLine(p_tmp, 0, p_tmp, curve_h); } for(i = (p2_ruler_startvalue / p2_divisor) * p2_divisor; i <= p2_ruler_endvalue; i += p2_divisor) { if(i < p2_ruler_startvalue) { continue; } p2_tmp = (double)(i - p2_ruler_startvalue) * p2_pixels_per_unit; if(curveUpSideDown == false) { painter->drawLine(0, curve_h - p2_tmp, curve_w, curve_h - p2_tmp); } else { painter->drawLine(0, p2_tmp, curve_w, p2_tmp); } } /////////////////////////////////// draw the curve /////////////////////////////////////////// if((dbuf == NULL) && (ibuf == NULL) && (fbuf == NULL)) return; if(max_value <= min_value) return; if(bufsize < 2) return; if(curveUpSideDown == true) { offset = (-(min_value)); v_sens = curve_h / (max_value - min_value); } else { offset = (-(max_value)); v_sens = (-(curve_h / (max_value - min_value))); } h_step = (double)curve_w / (double)bufsize; if(dbuf) { for(i = 0; i < bufsize; i++) { if(fillsurface) { if(bufsize < curve_w) { for(j = 0; j < h_step; j++) { painter->drawLine((i * h_step) + j, (dbuf[i] + offset) * v_sens, (i * h_step) + j, curve_h); } } else { painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, i * h_step, curve_h); } } else { if(bufsize < (curve_w / 2)) { painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i] + offset) * v_sens); if(i) { painter->drawLine(i * h_step, (dbuf[i - 1] + offset) * v_sens, i * h_step, (dbuf[i] + offset) * v_sens); } } else { if(i < (bufsize - 1)) { { painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i + 1] + offset) * v_sens); } } } } if(crosshair_1_active) { if(i==((int)(((double)crosshair_1_x_position * p_factor) / h_step))) { crosshair_1_y_value = (dbuf[i] + offset) * v_sens; crosshair_1_value = dbuf[i]; value = (h_ruler_endvalue - h_ruler_startvalue) / bufsize; crosshair_1_value_2 = (i * value) + (0.5 * value) + h_ruler_startvalue; } } } } if(ibuf) { for(i = 0; i < bufsize; i++) { if(fillsurface) { if(bufsize < curve_w) { for(j = 0; j < h_step; j++) { painter->drawLine((i * h_step) + j, ((double)(ibuf[i]) + offset) * v_sens, (i * h_step) + j, curve_h); } } else { painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, i * h_step, curve_h); } } else { if(bufsize < (curve_w / 2)) { painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, (i + 1) * h_step, ((double)(ibuf[i]) + offset) * v_sens); if(i) { painter->drawLine(i * h_step, ((double)(ibuf[i - 1]) + offset) * v_sens, i * h_step, ((double)(ibuf[i]) + offset) * v_sens); } } else { if(i < (bufsize - 1)) { { painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, (i + 1) * h_step, ((double)(ibuf[i + 1]) + offset) * v_sens); } } } } if(crosshair_1_active) { if(i==((int)(((double)crosshair_1_x_position * p_factor) / h_step))) { crosshair_1_y_value = ((double)(ibuf[i]) + offset) * v_sens; crosshair_1_value = (double)(ibuf[i]); value = (h_ruler_endvalue - h_ruler_startvalue) / bufsize; crosshair_1_value_2 = (i * value) + (0.5 * value) + h_ruler_startvalue; } } } } if(fbuf) { for(i = 0; i < bufsize; i++) { if(fillsurface) { if(bufsize < curve_w) { for(j = 0; j < h_step; j++) { painter->drawLine((i * h_step) + j, (fbuf[i] + offset) * v_sens, (i * h_step) + j, curve_h); } } else { painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, i * h_step, curve_h); } } else { if(bufsize < (curve_w / 2)) { painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i] + offset) * v_sens); if(i) { painter->drawLine(i * h_step, (fbuf[i - 1] + offset) * v_sens, i * h_step, (fbuf[i] + offset) * v_sens); } } else { if(i < (bufsize - 1)) { { painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i + 1] + offset) * v_sens); } } } } if(crosshair_1_active) { if(i==((int)(((double)crosshair_1_x_position * p_factor) / h_step))) { crosshair_1_y_value = (fbuf[i] + offset) * v_sens; crosshair_1_value = fbuf[i]; value = (h_ruler_endvalue - h_ruler_startvalue) / bufsize; crosshair_1_value_2 = (i * value) + (0.5 * value) + h_ruler_startvalue; } } } } /////////////////////////////////// draw the line /////////////////////////////////////////// if(line1Enabled == true) { painter->drawLine(line1_start_x * h_step, (line1_start_y + offset) * v_sens, line1_end_x * h_step, (line1_end_y + offset) * v_sens); } /////////////////////////////////// draw the markers /////////////////////////////////////////// if(Marker1Enabled == true) { painter->drawLine(curve_w * marker_1_position, 0, curve_w * marker_1_position, curve_h); } if(Marker2Enabled == true) { painter->drawLine(curve_w * marker_2_position, 0, curve_w * marker_2_position, curve_h); } /////////////////////////////////// draw the cursor /////////////////////////////////////////// if(crosshair_1_active) { QPainterPath path; path.moveTo(crosshair_1_x_position * p_factor, crosshair_1_y_value); path.lineTo((crosshair_1_x_position - 4) * p_factor, crosshair_1_y_value - (9 * p_factor)); path.lineTo((crosshair_1_x_position + 4) * p_factor, crosshair_1_y_value - (9 * p_factor)); path.lineTo(crosshair_1_x_position * p_factor, crosshair_1_y_value); painter->fillPath(path, QBrush(Qt::black)); snprintf(str, 128, "%f", crosshair_1_value); painter->drawText((crosshair_1_x_position + 8) * p_factor, (crosshair_1_y_position - 10) * p_factor, str); convert_to_metric_suffix(str, crosshair_1_value_2, 3); strcat(str, h_label); painter->drawText((crosshair_1_x_position + 8) * p_factor, (crosshair_1_y_position + 10) * p_factor, str); } bordersize = bordersize_backup; } void SignalCurve::setUpdatesEnabled(bool enabled) { updates_enabled = enabled; } void SignalCurve::paintEvent(QPaintEvent *) { if(updates_enabled == true) { QPainter paint(this); #if QT_VERSION >= 0x050000 paint.setRenderHint(QPainter::Qt4CompatiblePainting, true); #endif drawWidget(&paint, width(), height()); old_w = width(); } } void SignalCurve::drawWidget(QPainter *painter, int curve_w, int curve_h) { int i, j, precision, p_w, p_divisor, p_range, p_tmp, p_h, p2_divisor, p2_range, p2_multiplier, p2_ruler_startvalue, p2_ruler_endvalue, p2_tmp; long long p_multiplier, p_ruler_startvalue, p_ruler_endvalue; double v_sens=0.0, offset=0.0, h_step=0.0, value, pixelsPerUnit, sum_colorbar_value, p_pixels_per_unit, p2_pixels_per_unit; char str[128]; QString q_str; painter->setFont(QFont("Arial", 8)); painter->fillRect(0, 0, curve_w, curve_h, BorderColor); if((curve_w < ((bordersize * 2) + 5)) || (curve_h < ((bordersize * 2) + 5))) { return; } /////////////////////////////////// draw the horizontal ruler /////////////////////////////////////////// p_w = curve_w - bordersize - bordersize; p_multiplier = 1; while((h_ruler_endvalue * p_multiplier) < 10000.0) { p_multiplier *= 10; if(p_multiplier > 100000000000000LL) { break; } } p_ruler_startvalue = h_ruler_startvalue * p_multiplier; p_ruler_endvalue = h_ruler_endvalue * p_multiplier; p_range = p_ruler_endvalue - p_ruler_startvalue; p_pixels_per_unit = (double)p_w / (double)p_range; p_divisor = 1; while((p_range / p_divisor) > 10) { p_divisor *= 2; if((p_range / p_divisor) <= 10) { break; } p_divisor /= 2; p_divisor *= 5; if((p_range / p_divisor) <= 10) { break; } p_divisor *= 2; } // printf("p_multiplier is %lli\n" // "p_ruler_startvalue is %lli\n" // "p_ruler_endvalue is %lli\n" // "p_range is %i\n" // "p_divisor is %i\n" // "p_pixels_per_unit is %f\n\n", // p_multiplier, // p_ruler_startvalue, // p_ruler_endvalue, // p_range, // p_divisor, // p_pixels_per_unit); if(drawHruler && (bordersize > 19)) { painter->setPen(RulerColor); painter->drawLine(bordersize, curve_h - bordersize + 5, curve_w - bordersize, curve_h - bordersize + 5); for(i = (p_ruler_startvalue / p_divisor) * p_divisor; i <= p_ruler_endvalue; i += p_divisor) { if(i < p_ruler_startvalue) { continue; } convert_to_metric_suffix(str, (double)i / (double)p_multiplier, 4); remove_trailing_zeros(str); p_tmp = (double)(i - p_ruler_startvalue) * p_pixels_per_unit; painter->drawText(bordersize + p_tmp - 30, curve_h - bordersize + 18, 60, 16, Qt::AlignCenter | Qt::TextSingleLine, str); painter->drawLine(bordersize + p_tmp, curve_h - bordersize + 5, bordersize + p_tmp, curve_h - bordersize + 5 + 10); } painter->drawText(curve_w - bordersize + 20, curve_h - bordersize + 18, 40, 16, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, h_label); } /////////////////////////////////// draw the vertical ruler /////////////////////////////////////////// p_h = curve_h - bordersize - bordersize; p2_multiplier = 1; while(((max_value - min_value) * p2_multiplier) < 10000.0) { p2_multiplier *= 10; if(p2_multiplier > 10000000) { break; } } p2_ruler_startvalue = min_value * p2_multiplier; p2_ruler_endvalue = max_value * p2_multiplier; p2_range = p2_ruler_endvalue - p2_ruler_startvalue; if(p2_range < 0) p2_range *= -1; p2_pixels_per_unit = (double)p_h / (double)p2_range; p2_divisor = 1; while((p2_range / p2_divisor) > 10) { p2_divisor *= 2; if((p2_range / p2_divisor) <= 10) { break; } p2_divisor /= 2; p2_divisor *= 5; if((p2_range / p2_divisor) <= 10) { break; } p2_divisor *= 2; } // printf("p2_multiplier is %i\n" // "p2_ruler_startvalue is %i\n" // "p2_ruler_endvalue is %i\n" // "p2_range is %i\n" // "p2_divisor is %i\n" // "p2_pixels_per_unit is %f\n" // "max_value is %f\n" // "min_value is %f\n\n", // p2_multiplier, // p2_ruler_startvalue, // p2_ruler_endvalue, // p2_range, // p2_divisor, // p2_pixels_per_unit, // max_value, // min_value); if(drawVruler && (bordersize > 29)) { painter->setPen(RulerColor); painter->drawLine(bordersize - 5, bordersize, bordersize - 5, curve_h - bordersize); precision = 0; if((max_value < 10.0) && (max_value > -10.0) && (min_value < 10.0) && (min_value > -10.0)) { precision = 1; if((max_value < 1.0) && (max_value > -1.0) && (min_value < 1.0) && (min_value > -1.0)) { precision = 2; if((max_value < 0.1) && (max_value > -0.1) && (min_value < 0.1) && (min_value > -0.1)) { precision = 3; if((max_value < 0.01) && (max_value > -0.01) && (min_value < 0.01) && (min_value > -0.01)) { precision = 4; } } } } for(i = (p2_ruler_startvalue / p2_divisor) * p2_divisor; i <= p2_ruler_endvalue; i += p2_divisor) { if(i < p2_ruler_startvalue) { continue; } q_str.setNum((double)i / (double)p2_multiplier, 'f', precision); p2_tmp = (double)(i - p2_ruler_startvalue) * p2_pixels_per_unit; if(curveUpSideDown == false) { painter->drawText(3, curve_h - bordersize - p2_tmp - 8, 40, 16, Qt::AlignRight | Qt::AlignVCenter | Qt::TextSingleLine, q_str); painter->drawLine(bordersize - 5, curve_h - bordersize - p2_tmp, bordersize - 5 - 10, curve_h - bordersize - p2_tmp); } else { painter->drawText(3, bordersize + p2_tmp - 8, 40, 16, Qt::AlignRight | Qt::AlignVCenter | Qt::TextSingleLine, q_str); painter->drawLine(bordersize - 5, bordersize + p2_tmp, bordersize - 5 - 10, bordersize + p2_tmp); } } } /////////////////////////////////// draw the labels /////////////////////////////////////////// painter->setPen(TextColor); painter->setFont(QFont("Arial", 8)); if(v_label[0] != 0) { painter->drawText(8, 30, 100, 16, Qt::AlignCenter | Qt::TextSingleLine, v_label); } if(upperlabel1[0] != 0) { painter->drawText(curve_w / 2 - 150, 20, 300, 16, Qt::AlignCenter | Qt::TextSingleLine, upperlabel1); } if(lowerlabel[0] != 0) { painter->drawText(curve_w / 2 - 80, curve_h - 20, 160, 16, Qt::AlignCenter | Qt::TextSingleLine, lowerlabel); } /////////////////////////////////// translate coordinates, draw and fill a rectangle /////////////////////////////////////////// painter->translate(QPoint(bordersize, bordersize)); curve_w -= (bordersize * 2); curve_h -= (bordersize * 2); painter->fillRect(0, 0, curve_w, curve_h, BackgroundColor); painter->setClipping(true); painter->setClipRegion(QRegion(0, 0, curve_w, curve_h), Qt::ReplaceClip); /////////////////////////////////// draw the colorbars ///////////////////////////////////////// int t; if(spectrum_color != NULL) { if(spectrum_color->auto_adjust) { spectrum_color->max_colorbar_value = 0.0; } sum_colorbar_value = 0.0; for(i=0; i < spectrum_color->items; i++) { sum_colorbar_value += spectrum_color->value[i]; if(spectrum_color->auto_adjust) { if(spectrum_color->value[i] > spectrum_color->max_colorbar_value) { spectrum_color->max_colorbar_value = spectrum_color->value[i]; } } } if(spectrum_color->auto_adjust) { spectrum_color->max_colorbar_value *= 1.05; } pixelsPerUnit = (double)curve_w / (h_ruler_endvalue - h_ruler_startvalue); if((spectrum_color->freq[0] > h_ruler_startvalue) && (spectrum_color->items > 1)) { t = (spectrum_color->max_colorbar_value - spectrum_color->value[0]) * ((double)curve_h / spectrum_color->max_colorbar_value); if(t < 0) t = 0; if(t <= curve_h) { painter->fillRect(0, t, (spectrum_color->freq[0] - h_ruler_startvalue) * pixelsPerUnit, curve_h - t, (Qt::GlobalColor)spectrum_color->color[0]); } strcpy(str, spectrum_color->label[0]); if(spectrum_color->method == 0) { sprintf(str + strlen(str), " (%.1f%%)", (spectrum_color->value[i] * 100.0) / sum_colorbar_value); } painter->setPen(Qt::lightGray); painter->drawText(10, 20, str); } for(i=1; i < spectrum_color->items; i++) { if(spectrum_color->freq[i] > h_ruler_startvalue) { t = (spectrum_color->max_colorbar_value - spectrum_color->value[i]) * ((double)curve_h / spectrum_color->max_colorbar_value); if(t < 0) t = 0; if(t <= curve_h) { painter->fillRect((spectrum_color->freq[i-1] - h_ruler_startvalue) * pixelsPerUnit, t, (spectrum_color->freq[i] - spectrum_color->freq[i-1]) * pixelsPerUnit, curve_h - t, (Qt::GlobalColor)spectrum_color->color[i]); } strcpy(str, spectrum_color->label[i]); if(spectrum_color->method == 0) { sprintf(str + strlen(str), " (%.1f%%)", (spectrum_color->value[i] * 100.0) / sum_colorbar_value); } painter->setPen(Qt::lightGray); painter->drawText((spectrum_color->freq[i-1] - h_ruler_startvalue) * pixelsPerUnit + 10, 20 + ((i%2) * 20), str); } } if(spectrum_color->method == 0) { sprintf(str, "Total Power: %.1f", sum_colorbar_value); painter->drawText(curve_w - 200, 20 + ((i%2) * 20), str); } } /////////////////////////////////// draw the curve /////////////////////////////////////////// if(drawcurve_before_raster) { if((dbuf == NULL) && (ibuf == NULL) && (fbuf == NULL)) return; if(max_value <= min_value) return; if(bufsize < 2) return; if(curveUpSideDown == true) { offset = (-(min_value)); v_sens = curve_h / (max_value - min_value); } else { offset = (-(max_value)); v_sens = (-(curve_h / (max_value - min_value))); } h_step = (double)curve_w / (double)bufsize; painter->setPen(QPen(QBrush(SignalColor, Qt::SolidPattern), tracewidth, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin)); if(dbuf) { for(i = 0; i < bufsize; i++) { if(fillsurface) { if(bufsize < curve_w) { for(j = 0; j < h_step; j++) { painter->drawLine((i * h_step) + j, (dbuf[i] + offset) * v_sens, (i * h_step) + j, curve_h); } } else { painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, i * h_step, curve_h); } } else { if(bufsize < (curve_w / 2)) { painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i] + offset) * v_sens); if(i) { painter->drawLine(i * h_step, (dbuf[i - 1] + offset) * v_sens, i * h_step, (dbuf[i] + offset) * v_sens); } } else { if(i < (bufsize - 1)) { { painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i + 1] + offset) * v_sens); } } } } if(crosshair_1_active) { if(i==((int)(((double)crosshair_1_x_position) / h_step))) { crosshair_1_y_value = (dbuf[i] + offset) * v_sens; crosshair_1_value = dbuf[i]; value = (h_ruler_endvalue - h_ruler_startvalue) / bufsize; crosshair_1_value_2 = (i * value) + h_ruler_startvalue; } } } } if(ibuf) { for(i = 0; i < bufsize; i++) { if(fillsurface) { if(bufsize < curve_w) { for(j = 0; j < h_step; j++) { painter->drawLine((i * h_step) + j, ((double)(ibuf[i]) + offset) * v_sens, (i * h_step) + j, curve_h); } } else { painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, i * h_step, curve_h); } } else { if(bufsize < (curve_w / 2)) { painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, (i + 1) * h_step, ((double)(ibuf[i]) + offset) * v_sens); if(i) { painter->drawLine(i * h_step, ((double)(ibuf[i - 1]) + offset) * v_sens, i * h_step, ((double)(ibuf[i]) + offset) * v_sens); } } else { if(i < (bufsize - 1)) { { painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, (i + 1) * h_step, ((double)(ibuf[i + 1]) + offset) * v_sens); } } } } if(crosshair_1_active) { if(i==((int)(((double)crosshair_1_x_position) / h_step))) { crosshair_1_y_value = ((double)(ibuf[i]) + offset) * v_sens; crosshair_1_value = (double)(ibuf[i]); value = (h_ruler_endvalue - h_ruler_startvalue) / bufsize; crosshair_1_value_2 = (i * value) + h_ruler_startvalue; } } } } if(fbuf) { for(i = 0; i < bufsize; i++) { if(fillsurface) { if(bufsize < curve_w) { for(j = 0; j < h_step; j++) { painter->drawLine((i * h_step) + j, (fbuf[i] + offset) * v_sens, (i * h_step) + j, curve_h); } } else { painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, i * h_step, curve_h); } } else { if(bufsize < (curve_w / 2)) { painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i] + offset) * v_sens); if(i) { painter->drawLine(i * h_step, (fbuf[i - 1] + offset) * v_sens, i * h_step, (fbuf[i] + offset) * v_sens); } } else { if(i < (bufsize - 1)) { { painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i + 1] + offset) * v_sens); } } } } if(crosshair_1_active) { if(i==((int)(((double)crosshair_1_x_position) / h_step))) { crosshair_1_y_value = (fbuf[i] + offset) * v_sens; crosshair_1_value = fbuf[i]; value = (h_ruler_endvalue - h_ruler_startvalue) / bufsize; crosshair_1_value_2 = (i * value) + h_ruler_startvalue; } } } } } /////////////////////////////////// draw the rasters /////////////////////////////////////////// painter->setPen(RasterColor); painter->drawRect (0, 0, curve_w - 1, curve_h - 1); for(i = (p_ruler_startvalue / p_divisor) * p_divisor; i <= p_ruler_endvalue; i += p_divisor) { if(i < p_ruler_startvalue) { continue; } p_tmp = (double)(i - p_ruler_startvalue) * p_pixels_per_unit; painter->drawLine(p_tmp, 0, p_tmp, curve_h); } for(i = (p2_ruler_startvalue / p2_divisor) * p2_divisor; i <= p2_ruler_endvalue; i += p2_divisor) { if(i < p2_ruler_startvalue) { continue; } p2_tmp = (double)(i - p2_ruler_startvalue) * p2_pixels_per_unit; if(curveUpSideDown == false) { painter->drawLine(0, curve_h - p2_tmp, curve_w, curve_h - p2_tmp); } else { painter->drawLine(0, p2_tmp, curve_w, p2_tmp); } } /////////////////////////////////// draw the curve /////////////////////////////////////////// if(!drawcurve_before_raster) { if((dbuf == NULL) && (ibuf == NULL) && (fbuf == NULL)) return; if(max_value <= min_value) return; if(bufsize < 2) return; if(curveUpSideDown == true) { offset = (-(min_value)); v_sens = curve_h / (max_value - min_value); } else { offset = (-(max_value)); v_sens = (-(curve_h / (max_value - min_value))); } h_step = (double)curve_w / (double)bufsize; painter->setPen(QPen(QBrush(SignalColor, Qt::SolidPattern), tracewidth, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin)); if(dbuf) { for(i = 0; i < bufsize; i++) { if(fillsurface) { if(bufsize < curve_w) { for(j = 0; j < h_step; j++) { painter->drawLine((i * h_step) + j, (dbuf[i] + offset) * v_sens, (i * h_step) + j, curve_h); } } else { painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, i * h_step, curve_h); } } else { if(bufsize < (curve_w / 2)) { painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i] + offset) * v_sens); if(i) { painter->drawLine(i * h_step, (dbuf[i - 1] + offset) * v_sens, i * h_step, (dbuf[i] + offset) * v_sens); } } else { if(i < (bufsize - 1)) { painter->drawLine(i * h_step, (dbuf[i] + offset) * v_sens, (i + 1) * h_step, (dbuf[i + 1] + offset) * v_sens); } } } if(crosshair_1_active) { if(i==((int)(((double)crosshair_1_x_position) / h_step))) { crosshair_1_y_value = (dbuf[i] + offset) * v_sens; crosshair_1_value = dbuf[i]; value = (h_ruler_endvalue - h_ruler_startvalue) / bufsize; crosshair_1_value_2 = (i * value) + h_ruler_startvalue; } } } } if(ibuf) { for(i = 0; i < bufsize; i++) { if(fillsurface) { if(bufsize < curve_w) { for(j = 0; j < h_step; j++) { painter->drawLine((i * h_step) + j, ((double)(ibuf[i]) + offset) * v_sens, (i * h_step) + j, curve_h); } } else { painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, i * h_step, curve_h); } } else { if(bufsize < (curve_w / 2)) { painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, (i + 1) * h_step, ((double)(ibuf[i]) + offset) * v_sens); if(i) { painter->drawLine(i * h_step, ((double)(ibuf[i - 1]) + offset) * v_sens, i * h_step, ((double)(ibuf[i]) + offset) * v_sens); } } else { if(i < (bufsize - 1)) { { painter->drawLine(i * h_step, ((double)(ibuf[i]) + offset) * v_sens, (i + 1) * h_step, ((double)(ibuf[i + 1]) + offset) * v_sens); } } } } if(crosshair_1_active) { if(i==((int)(((double)crosshair_1_x_position) / h_step))) { crosshair_1_y_value = ((double)(ibuf[i]) + offset) * v_sens; crosshair_1_value = (double)(ibuf[i]); value = (h_ruler_endvalue - h_ruler_startvalue) / bufsize; crosshair_1_value_2 = (i * value) + h_ruler_startvalue; } } } } if(fbuf) { for(i = 0; i < bufsize; i++) { if(fillsurface) { if(bufsize < curve_w) { for(j = 0; j < h_step; j++) { painter->drawLine((i * h_step) + j, (fbuf[i] + offset) * v_sens, (i * h_step) + j, curve_h); } } else { painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, i * h_step, curve_h); } } else { if(bufsize < (curve_w / 2)) { painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i] + offset) * v_sens); if(i) { painter->drawLine(i * h_step, (fbuf[i - 1] + offset) * v_sens, i * h_step, (fbuf[i] + offset) * v_sens); } } else { if(i < (bufsize - 1)) { { painter->drawLine(i * h_step, (fbuf[i] + offset) * v_sens, (i + 1) * h_step, (fbuf[i + 1] + offset) * v_sens); } } } } if(crosshair_1_active) { if(i==((int)(((double)crosshair_1_x_position) / h_step))) { crosshair_1_y_value = (fbuf[i] + offset) * v_sens; crosshair_1_value = fbuf[i]; value = (h_ruler_endvalue - h_ruler_startvalue) / bufsize; crosshair_1_value_2 = (i * value) + h_ruler_startvalue; } } } } } /////////////////////////////////// draw the line /////////////////////////////////////////// if(line1Enabled == true) { painter->setPen(QPen(QBrush(line1Color, Qt::SolidPattern), tracewidth, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin)); painter->drawLine(line1_start_x * h_step, (line1_start_y + offset) * v_sens, line1_end_x * h_step, (line1_end_y + offset) * v_sens); } /////////////////////////////////// draw the markers /////////////////////////////////////////// if(Marker1Enabled == true) { painter->setPen(Marker1Pen); painter->drawLine(curve_w * marker_1_position, 0, curve_w * marker_1_position, curve_h); } if(Marker2Enabled == true) { painter->setPen(Marker2Pen); painter->drawLine(curve_w * marker_2_position, 0, curve_w * marker_2_position, curve_h); } /////////////////////////////////// draw the cursor /////////////////////////////////////////// if(crosshair_1_active) { painter->setPen(crosshair_1_color); QPainterPath path; path.moveTo(crosshair_1_x_position, crosshair_1_y_value); path.lineTo(crosshair_1_x_position - 4, crosshair_1_y_value - 10); path.lineTo(crosshair_1_x_position + 5, crosshair_1_y_value - 10); path.lineTo(crosshair_1_x_position, crosshair_1_y_value); painter->fillPath(path, QBrush(crosshair_1_color)); painter->setFont(QFont("Arial", 10)); painter->fillRect(crosshair_1_x_position + 6, crosshair_1_y_position - 23, 60, 16, BackgroundColor); snprintf(str, 128, "%f", crosshair_1_value); painter->drawText(crosshair_1_x_position + 8, crosshair_1_y_position - 10, str); painter->fillRect(crosshair_1_x_position + 6, crosshair_1_y_position - 3, 60, 16, BackgroundColor); convert_to_metric_suffix(str, crosshair_1_value_2, 3); strcat(str, h_label); painter->drawText(crosshair_1_x_position + 8, crosshair_1_y_position + 10, str); } /////////////////////////////////// draw the buttons /////////////////////////////////////////// painter->setPen(Qt::black); painter->setFont(QFont("Arial", 8)); if(printEnabled == true) { painter->fillRect(curve_w - 43, 3, 40, 18, Qt::gray); painter->drawText(curve_w - 38, 16, "print"); } if(cursorEnabled == true) { painter->fillRect(curve_w - 43, 23, 40, 18, Qt::gray); painter->drawText(curve_w - 38, 36, "cursor"); } if(dashBoardEnabled == true) { painter->fillRect(curve_w - 43, 43, 40, 18, Qt::gray); painter->drawText(curve_w - 38, 56, "ctls"); } } void SignalCurve::drawLine(int start_x, double start_y, int end_x, double end_y, QColor lineColor) { line1Color = lineColor; line1_start_x = start_x; if(line1_start_x < 0) { line1_start_x = 0; } if(line1_start_x >= bufsize) { line1_start_x = bufsize - 1; } line1_start_y = start_y; line1_end_x = end_x; if(line1_end_x < 0) { line1_end_x = 0; } if(line1_end_x >= bufsize) { line1_end_x = bufsize - 1; } line1_end_y = end_y; line1Enabled = true; update(); } void SignalCurve::setLineEnabled(bool stat) { line1Enabled = stat; update(); } void SignalCurve::drawCurve(double *samplebuf, int bsize, double max_val, double min_val) { dbuf = samplebuf; ibuf = NULL; fbuf = NULL; bufsize = bsize; max_value = max_val; min_value = min_val; update(); } void SignalCurve::drawCurve(int *samplebuf, int bsize, double max_val, double min_val) { ibuf = samplebuf; dbuf = NULL; fbuf = NULL; bufsize = bsize; max_value = max_val; min_value = min_val; update(); } void SignalCurve::drawCurve(float *samplebuf, int bsize, double max_val, double min_val) { fbuf = samplebuf; dbuf = NULL; ibuf = NULL; bufsize = bsize; max_value = max_val; min_value = min_val; update(); } void SignalCurve::setFillSurfaceEnabled(bool enabled) { if(enabled == true) { fillsurface = 1; } else { fillsurface = 0; } update(); } void SignalCurve::setMarker1Position(double mrk_pos) { marker_1_position = mrk_pos; if(marker_1_position > 1.01) marker_1_position = 1.01; if(marker_1_position < 0.0001) marker_1_position = 0.0001; update(); } void SignalCurve::setMarker1Enabled(bool on) { Marker1Enabled = on; update(); } void SignalCurve::setMarker1MovableEnabled(bool on) { Marker1MovableEnabled = on; update(); } void SignalCurve::setMarker1Color(QColor color) { Marker1Pen.setColor(color); update(); } double SignalCurve::getMarker1Position(void) { return(marker_1_position); } void SignalCurve::setMarker2Position(double mrk_pos) { marker_2_position = mrk_pos; if(marker_2_position > 1.01) marker_2_position = 1.01; if(marker_2_position < 0.0001) marker_2_position = 0.0001; update(); } void SignalCurve::setMarker2Enabled(bool on) { Marker2Enabled = on; update(); } void SignalCurve::setMarker2MovableEnabled(bool on) { Marker2MovableEnabled = on; update(); } void SignalCurve::setMarker2Color(QColor color) { Marker2Pen.setColor(color); update(); } double SignalCurve::getMarker2Position(void) { return(marker_2_position); } void SignalCurve::setH_RulerValues(double start, double end) { h_ruler_startvalue = start; h_ruler_endvalue = end; update(); } void SignalCurve::setSignalColor(QColor newColor) { SignalColor = newColor; update(); } void SignalCurve::setCrosshairColor(QColor newColor) { crosshair_1_color = newColor; update(); } void SignalCurve::setTraceWidth(int tr_width) { tracewidth = tr_width; if(tracewidth < 0) tracewidth = 0; update(); } void SignalCurve::setBackgroundColor(QColor newColor) { BackgroundColor = newColor; update(); } void SignalCurve::setRasterColor(QColor newColor) { RasterColor = newColor; update(); } void SignalCurve::setBorderColor(QColor newColor) { BorderColor = newColor; update(); } void SignalCurve::setTextColor(QColor newColor) { TextColor = newColor; update(); } void SignalCurve::setBorderSize(int newsize) { bordersize = newsize; if(bordersize < 0) bordersize = 0; update(); } void SignalCurve::setH_label(const char *str) { strncpy(h_label, str, 32); h_label[31] = 0; update(); } void SignalCurve::setV_label(const char *str) { strncpy(v_label, str, 20); v_label[20] = 0; update(); } void SignalCurve::setUpperLabel1(const char *str) { strncpy(upperlabel1, str, 64); upperlabel1[63] = 0; update(); } void SignalCurve::setUpperLabel2(const char *str) { strncpy(upperlabel2, str, 64); upperlabel2[63] = 0; update(); } void SignalCurve::setLowerLabel(const char *str) { strncpy(lowerlabel, str, 64); lowerlabel[63] = 0; update(); } void SignalCurve::setCursorEnabled(bool value) { cursorEnabled = value; } bool SignalCurve::isCursorEnabled(void) { return(cursorEnabled); } bool SignalCurve::isCursorActive(void) { return(crosshair_1_active); } void SignalCurve::setPrintEnabled(bool value) { printEnabled = value; } void SignalCurve::setDashBoardEnabled(bool value) { dashBoardEnabled = value; } void SignalCurve::enableSpectrumColors(struct spectrum_markersblock *spectr_col) { spectrum_color = spectr_col; update(); } void SignalCurve::disableSpectrumColors() { spectrum_color = NULL; update(); } void SignalCurve::setV_rulerEnabled(bool value) { if(value == true) { drawVruler = 1; } else { drawVruler = 0; } } void SignalCurve::setUpsidedownEnabled(bool value) { curveUpSideDown = value; } int SignalCurve::getCursorPosition(void) { return(crosshair_1_value_2); } /* size is size of destination, returns length of directory */ /* last character of destination is not a slash! */ int SignalCurve::get_directory_from_path(char *dest, const char *src, int ssize) { int i, len; if(ssize<1) { return(-1); } if(ssize<2) { dest[0] = 0; return(0); } len = strlen(src); if(len < 1) { dest[0] = 0; return(0); } for(i=len-1; i>=0; i--) { if((src[i]=='/') || (src[i]=='\\')) { break; } } strncpy(dest, src, ssize); if(i < ssize) { dest[i] = 0; } else { dest[ssize-1] = 0; } return(strlen(dest)); } edfbrowser_157_source/PaxHeaders.7921/raw2edf.cpp0000644000000000000000000000012712646460742016730 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/raw2edf.cpp0000644000175000001440000006462012646460742017275 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "raw2edf.h" UI_RAW2EDFapp::UI_RAW2EDFapp(struct raw2edf_var_struct *raw2edf_var_p, char *recent_dir, char *save_dir) { recent_opendir = recent_dir; recent_savedir = save_dir; raw2edf_var = raw2edf_var_p; edf_format = 1; raw2edfDialog = new QDialog; raw2edfDialog->setMinimumSize(600, 480); raw2edfDialog->setMaximumSize(600, 480); raw2edfDialog->setWindowTitle("Binary/raw data to EDF converter"); raw2edfDialog->setModal(true); raw2edfDialog->setAttribute(Qt::WA_DeleteOnClose, true); SamplefreqLabel = new QLabel(raw2edfDialog); SamplefreqLabel->setGeometry(20, 20, 140, 25); SamplefreqLabel->setText("Samplefrequency"); SamplefreqSpinbox = new QSpinBox(raw2edfDialog); SamplefreqSpinbox->setGeometry(160, 20, 120, 25); SamplefreqSpinbox->setRange(1,1000000); SamplefreqSpinbox->setSuffix(" Hz"); SamplefreqSpinbox->setValue(raw2edf_var->sf); SamplefreqSpinbox->setToolTip("Samplerate"); SignalsLabel = new QLabel(raw2edfDialog); SignalsLabel->setGeometry(20, 60, 140, 25); SignalsLabel->setText("Number of signals"); SignalsSpinbox = new QSpinBox(raw2edfDialog); SignalsSpinbox->setGeometry(160, 60, 120, 25); SignalsSpinbox->setRange(1,256); SignalsSpinbox->setValue(raw2edf_var->chns); SignalsSpinbox->setToolTip("Number of channels"); SampleSizeLabel = new QLabel(raw2edfDialog); SampleSizeLabel->setGeometry(20, 100, 140, 25); SampleSizeLabel->setText("Sample size"); SampleSizeSpinbox = new QSpinBox(raw2edfDialog); SampleSizeSpinbox->setGeometry(160, 100, 120, 25); SampleSizeSpinbox->setRange(1,2); SampleSizeSpinbox->setValue(raw2edf_var->samplesize); SampleSizeSpinbox->setSuffix(" byte(s)"); SampleSizeSpinbox->setToolTip("Bytes per sample"); OffsetLabel = new QLabel(raw2edfDialog); OffsetLabel->setGeometry(20, 140, 140, 25); OffsetLabel->setText("Offset"); OffsetSpinbox = new QSpinBox(raw2edfDialog); OffsetSpinbox->setGeometry(160, 140, 120, 25); OffsetSpinbox->setRange(0,1000000); OffsetSpinbox->setValue(raw2edf_var->offset); OffsetSpinbox->setToolTip("Bytes to skip from start of file to data startpoint"); EncodingLabel = new QLabel(raw2edfDialog); EncodingLabel->setGeometry(20, 180, 140, 25); EncodingLabel->setText("Encoding"); EncodingCombobox = new QComboBox(raw2edfDialog); EncodingCombobox->setGeometry(160, 180, 120, 25); EncodingCombobox->addItem("2's complement"); EncodingCombobox->addItem("bipolar offset binary"); EncodingCombobox->setCurrentIndex(raw2edf_var->straightbinary); EncodingCombobox->setToolTip("bipolar offset binary or\n" "2's complement"); EndiannessLabel = new QLabel(raw2edfDialog); EndiannessLabel->setGeometry(20, 220, 140, 25); EndiannessLabel->setText("Endianness"); EndiannessCombobox = new QComboBox(raw2edfDialog); EndiannessCombobox->setGeometry(160, 220, 120, 25); EndiannessCombobox->addItem("little endian"); EndiannessCombobox->addItem("big endian"); EndiannessCombobox->setCurrentIndex(raw2edf_var->endianness); EndiannessCombobox->setToolTip("little endian: least significant byte comes first\n" "big endian: most significant byte comes first"); skipblocksizeLabel = new QLabel(raw2edfDialog); skipblocksizeLabel->setGeometry(320, 20, 140, 25); skipblocksizeLabel->setText("Data blocksize"); skipblocksizeSpinbox = new QSpinBox(raw2edfDialog); skipblocksizeSpinbox->setGeometry(460, 20, 120, 25); skipblocksizeSpinbox->setRange(0, 1000000); skipblocksizeSpinbox->setValue(raw2edf_var->skipblocksize); skipblocksizeSpinbox->setToolTip("Skip after every n databytes"); skipbytesLabel = new QLabel(raw2edfDialog); skipbytesLabel->setGeometry(320, 60, 140, 25); skipbytesLabel->setText("Skip bytes"); skipbytesSpinbox = new QSpinBox(raw2edfDialog); skipbytesSpinbox->setGeometry(460, 60, 120, 25); skipbytesSpinbox->setRange(1, 1000000); skipbytesSpinbox->setValue(raw2edf_var->skipbytes); skipbytesSpinbox->setToolTip("Number of bytes that must be skipped"); PhysicalMaximumLabel = new QLabel(raw2edfDialog); PhysicalMaximumLabel->setGeometry(320, 100, 140, 25); PhysicalMaximumLabel->setText("Physical maximum"); PhysicalMaximumSpinbox = new QSpinBox(raw2edfDialog); PhysicalMaximumSpinbox->setGeometry(460, 100, 120, 25); PhysicalMaximumSpinbox->setRange(1, 10000000); PhysicalMaximumSpinbox->setValue(raw2edf_var->phys_max); PhysicalMaximumSpinbox->setToolTip("The maximum physical value that can be measured\n" "e.g. the maximum value of an inputchannel."); PhysicalDimensionLabel = new QLabel(raw2edfDialog); PhysicalDimensionLabel->setGeometry(320, 140, 140, 25); PhysicalDimensionLabel->setText("Physical dimension"); PhysicalDimensionLineEdit = new QLineEdit(raw2edfDialog); PhysicalDimensionLineEdit->setGeometry(460, 140, 120, 25); PhysicalDimensionLineEdit->setMaxLength(8); PhysicalDimensionLineEdit->setText(raw2edf_var->phys_dim); PhysicalDimensionLineEdit->setToolTip("uV, bpm, mL, Ltr, etc."); PhysicalDimensionLineEdited(PhysicalDimensionLineEdit->text()); variableTypeLabel = new QLabel(raw2edfDialog); variableTypeLabel->setGeometry(320, 180, 140, 25); variableTypeLabel->setText("sampletype: i16"); PatientnameLabel = new QLabel(raw2edfDialog); PatientnameLabel->setGeometry(20, 260, 140, 25); PatientnameLabel->setText("Subject name"); PatientnameLineEdit = new QLineEdit(raw2edfDialog); PatientnameLineEdit->setGeometry(160, 260, 420, 25); PatientnameLineEdit->setMaxLength(80); RecordingLabel = new QLabel(raw2edfDialog); RecordingLabel->setGeometry(20, 300, 140, 25); RecordingLabel->setText("Recording"); RecordingLineEdit = new QLineEdit(raw2edfDialog); RecordingLineEdit->setGeometry(160, 300, 420, 25); RecordingLineEdit->setMaxLength(80); DatetimeLabel = new QLabel(raw2edfDialog); DatetimeLabel->setGeometry(20, 340, 140, 25); DatetimeLabel->setText("Startdate and time"); StartDatetimeedit = new QDateTimeEdit(raw2edfDialog); StartDatetimeedit->setGeometry(160, 340, 180, 25); StartDatetimeedit->setDisplayFormat("dd/MM/yyyy hh:mm:ss"); StartDatetimeedit->setDateTime(QDateTime::currentDateTime()); StartDatetimeedit->setToolTip("dd/MM/yyyy hh:mm:ss"); GoButton = new QPushButton(raw2edfDialog); GoButton->setGeometry(20, 440, 75, 25); GoButton->setText("Start"); GoButton->setToolTip("Start the conversion"); CloseButton = new QPushButton(raw2edfDialog); CloseButton->setGeometry(160, 440, 75, 25); CloseButton->setText("Close"); SaveButton = new QPushButton(raw2edfDialog); SaveButton->setGeometry(400, 440, 75, 25); SaveButton->setText("Save"); SaveButton->setToolTip("Save the entered parameters to a template for later use"); LoadButton = new QPushButton(raw2edfDialog); LoadButton->setGeometry(510, 440, 75, 25); LoadButton->setText("Load"); LoadButton->setToolTip("Load parameters from a template"); edfsignals = 1; QObject::connect(GoButton, SIGNAL(clicked()), this, SLOT(gobuttonpressed())); QObject::connect(CloseButton, SIGNAL(clicked()), raw2edfDialog, SLOT(close())); QObject::connect(SaveButton, SIGNAL(clicked()), this, SLOT(savebuttonpressed())); QObject::connect(LoadButton, SIGNAL(clicked()), this, SLOT(loadbuttonpressed())); QObject::connect(PhysicalDimensionLineEdit, SIGNAL(textEdited(QString)), this, SLOT(PhysicalDimensionLineEdited(QString))); QObject::connect(SampleSizeSpinbox, SIGNAL(valueChanged(int)), this, SLOT(sampleTypeChanged(int))); QObject::connect(EncodingCombobox, SIGNAL(currentIndexChanged(int)), this, SLOT(sampleTypeChanged(int))); sampleTypeChanged(0); raw2edfDialog->exec(); } void UI_RAW2EDFapp::gobuttonpressed() { int i, j, k, r, hdl, chns, sf, *buf, datarecords, tmp, straightbinary, samplesize, skipblocksize, skipbytes, skipblockcntr, bytecntr, big_endian; char str[256], path[MAX_PATH_LENGTH]; double phys_max; long long d_offset; FILE *inputfile; sf = SamplefreqSpinbox->value(); raw2edf_var->sf = sf; chns = SignalsSpinbox->value(); raw2edf_var->chns = chns; phys_max = PhysicalMaximumSpinbox->value(); raw2edf_var->phys_max = phys_max; straightbinary = EncodingCombobox->currentIndex(); raw2edf_var->straightbinary = straightbinary; big_endian = EndiannessCombobox->currentIndex(); raw2edf_var->endianness = big_endian; samplesize = SampleSizeSpinbox->value(); raw2edf_var->samplesize = samplesize; d_offset = OffsetSpinbox->value(); raw2edf_var->offset = d_offset; skipblocksize = skipblocksizeSpinbox->value(); raw2edf_var->skipblocksize = skipblocksize; skipbytes = skipbytesSpinbox->value(); raw2edf_var->skipbytes = skipbytes; strcpy(raw2edf_var->phys_dim, PhysicalDimensionLineEdit->text().toLatin1().data()); remove_leading_spaces(raw2edf_var->phys_dim); remove_trailing_spaces(raw2edf_var->phys_dim); if(!(strlen(PatientnameLineEdit->text().toLatin1().data()))) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a subjectname."); messagewindow.exec(); return; } if(!(strlen(RecordingLineEdit->text().toLatin1().data()))) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a recording description."); messagewindow.exec(); return; } strcpy(path, QFileDialog::getOpenFileName(0, "Open data file", QString::fromLocal8Bit(recent_opendir), "All files (*)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(recent_opendir, path, MAX_PATH_LENGTH); inputfile = fopeno(path, "rb"); if(inputfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); messagewindow.exec(); return; } remove_extension_from_filename(path); strcat(path, ".edf"); hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_EDFPLUS, chns); if(hdl<0) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for writing.\nedfopen_file_writeonly()"); messagewindow.exec(); fclose(inputfile); return; } for(i=0; iphys_dim)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "edf_set_physical_dimension()"); messagewindow.exec(); fclose(inputfile); return; } } for(i=0; idate().year(), StartDatetimeedit->date().month(), StartDatetimeedit->date().day(), StartDatetimeedit->time().hour(), StartDatetimeedit->time().minute(), StartDatetimeedit->time().second())) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "edf_set_startdatetime()"); messagewindow.exec(); fclose(inputfile); edfclose_file(hdl); return; } buf = (int *)malloc(sizeof(int) * sf * chns); if(buf == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "malloc()"); messagewindow.exec(); fclose(inputfile); edfclose_file(hdl); return; } // printf("samplefrequency: %14i Hz\n" // "channels: %14i\n" // "physical maximum: %14.6f uV\n" // "straightbinary: %14i\n" // "samplesize: %14i byte(s)\n" // "offset: %14lli bytes\n" // "skip blocksize: %14i bytes\n" // "skip bytes: %14i bytes\n\n", // sf, // chns, // phys_max, // straightbinary, // samplesize, // d_offset, // skipblocksize, // skipbytes); fseeko(inputfile, d_offset, SEEK_SET); datarecords = 0; union{ int one[1]; signed short two[2]; char four[4]; } var; skipblockcntr = 0; bytecntr = 0; while(1) { for(j=0; j skipblocksize) { for(r=0; r skipblocksize) { for(r=0; r>= 8; } buf[j + (k * sf)] = var.two[0]; } } if(edf_blockwrite_digital_samples(hdl, buf)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Write error during conversion.\nedf_blockwrite_digital_samples()"); messagewindow.exec(); edfclose_file(hdl); fclose(inputfile); free(buf); return; } datarecords++; // if(datarecords == 1) break; } END_1: edfclose_file(hdl); fclose(inputfile); free(buf); sprintf(str, "A new EDF file has been created:\n\n%s", path); QMessageBox messagewindow(QMessageBox::Information, "Ready", str); messagewindow.setIconPixmap(QPixmap(":/images/ok.png")); messagewindow.exec(); } void UI_RAW2EDFapp::savebuttonpressed() { char path[MAX_PATH_LENGTH], str[128]; FILE *outputfile; raw2edf_var->sf = SamplefreqSpinbox->value(); raw2edf_var->chns = SignalsSpinbox->value(); raw2edf_var->phys_max = PhysicalMaximumSpinbox->value(); raw2edf_var->straightbinary = EncodingCombobox->currentIndex(); raw2edf_var->endianness = EndiannessCombobox->currentIndex(); raw2edf_var->samplesize = SampleSizeSpinbox->value(); raw2edf_var->offset = OffsetSpinbox->value(); raw2edf_var->skipblocksize = skipblocksizeSpinbox->value(); raw2edf_var->skipbytes = skipbytesSpinbox->value(); strcpy(raw2edf_var->phys_dim, PhysicalDimensionLineEdit->text().toLatin1().data()); remove_leading_spaces(raw2edf_var->phys_dim); remove_trailing_spaces(raw2edf_var->phys_dim); path[0] = 0; if(recent_savedir[0]!=0) { strcpy(path, recent_savedir); strcat(path, "/"); } strcat(path, "binary_to_edf.template"); strcpy(path, QFileDialog::getSaveFileName(0, "Save parameters", QString::fromLocal8Bit(path), "Template files (*.template *.TEMPLATE)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(recent_savedir, path, MAX_PATH_LENGTH); outputfile = fopeno(path, "wb"); if(outputfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for writing."); messagewindow.exec(); return; } fprintf(outputfile, "\n<" PROGRAM_NAME "_raw2edf_template>\n"); fprintf(outputfile, " %i\n", raw2edf_var->sf); fprintf(outputfile, " %i\n", raw2edf_var->chns); fprintf(outputfile, " %i\n", raw2edf_var->phys_max); fprintf(outputfile, " %i\n", raw2edf_var->straightbinary); fprintf(outputfile, " %i\n", raw2edf_var->endianness); fprintf(outputfile, " %i\n", raw2edf_var->samplesize); fprintf(outputfile, " %i\n", raw2edf_var->offset); fprintf(outputfile, " %i\n", raw2edf_var->skipblocksize); fprintf(outputfile, " %i\n", raw2edf_var->skipbytes); xml_strcpy_encode_entity(str, raw2edf_var->phys_dim); fprintf(outputfile, " %s\n", str); fprintf(outputfile, "\n"); fclose(outputfile); } void UI_RAW2EDFapp::loadbuttonpressed() { char path[MAX_PATH_LENGTH], result[XML_STRBUFLEN]; struct xml_handle *xml_hdl; strcpy(path, QFileDialog::getOpenFileName(0, "Load parameters", QString::fromLocal8Bit(recent_opendir), "Template files (*.template *.TEMPLATE)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(recent_opendir, path, MAX_PATH_LENGTH); xml_hdl = xml_get_handle(path); if(xml_hdl==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); messagewindow.exec(); return; } if(strcmp(xml_hdl->elementname[xml_hdl->level], PROGRAM_NAME "_raw2edf_template")) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } if(!(xml_goto_nth_element_inside(xml_hdl, "sf", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var->sf = atoi(result); if(raw2edf_var->sf < 1) raw2edf_var->sf = 1; if(raw2edf_var->sf > 1000000) raw2edf_var->sf = 1000000; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "chns", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var->chns = atoi(result); if(raw2edf_var->chns < 1) raw2edf_var->chns = 1; if(raw2edf_var->chns > 256) raw2edf_var->chns = 256; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "phys_max", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var->phys_max = atoi(result); if(raw2edf_var->phys_max < 1) raw2edf_var->phys_max = 1; if(raw2edf_var->phys_max > 10000000) raw2edf_var->phys_max = 10000000; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "straightbinary", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var->straightbinary = atoi(result); if(raw2edf_var->straightbinary < 0) raw2edf_var->straightbinary = 0; if(raw2edf_var->straightbinary > 1) raw2edf_var->straightbinary = 1; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "endianness", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var->endianness = atoi(result); if(raw2edf_var->endianness < 0) raw2edf_var->endianness = 0; if(raw2edf_var->endianness > 1) raw2edf_var->endianness = 1; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "samplesize", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var->samplesize = atoi(result); if(raw2edf_var->samplesize < 1) raw2edf_var->samplesize = 1; if(raw2edf_var->samplesize > 2) raw2edf_var->samplesize = 2; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "offset", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var->offset = atoi(result); if(raw2edf_var->offset < 0) raw2edf_var->offset = 0; if(raw2edf_var->offset > 1000000) raw2edf_var->offset = 1000000; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "skipblocksize", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var->skipblocksize = atoi(result); if(raw2edf_var->skipblocksize < 0) raw2edf_var->skipblocksize = 0; if(raw2edf_var->skipblocksize > 1000000) raw2edf_var->skipblocksize = 1000000; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "skipbytes", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var->skipbytes = atoi(result); if(raw2edf_var->skipbytes < 1) raw2edf_var->skipbytes = 1; if(raw2edf_var->skipbytes > 1000000) raw2edf_var->skipbytes = 1000000; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "phys_dim", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } strncpy(raw2edf_var->phys_dim, result, 16); raw2edf_var->phys_dim[15] = 0; latin1_to_ascii(raw2edf_var->phys_dim, 16); remove_leading_spaces(raw2edf_var->phys_dim); remove_trailing_spaces(raw2edf_var->phys_dim); xml_go_up(xml_hdl); } xml_close(xml_hdl); SamplefreqSpinbox->setValue(raw2edf_var->sf); SignalsSpinbox->setValue(raw2edf_var->chns); PhysicalMaximumSpinbox->setValue(raw2edf_var->phys_max); EncodingCombobox->setCurrentIndex(raw2edf_var->straightbinary); EndiannessCombobox->setCurrentIndex(raw2edf_var->endianness); SampleSizeSpinbox->setValue(raw2edf_var->samplesize); OffsetSpinbox->setValue(raw2edf_var->offset); skipblocksizeSpinbox->setValue(raw2edf_var->skipblocksize); skipbytesSpinbox->setValue(raw2edf_var->skipbytes); } void UI_RAW2EDFapp::sampleTypeChanged(int) { if(SampleSizeSpinbox->value() == 1) { if(EncodingCombobox->currentIndex() == 0) { variableTypeLabel->setText("sampletype: I8"); } else { variableTypeLabel->setText("sampletype: U8"); } EndiannessCombobox->setEnabled(false); } else { if(EncodingCombobox->currentIndex() == 0) { variableTypeLabel->setText("sampletype: I16"); } else { variableTypeLabel->setText("sampletype: U16"); } EndiannessCombobox->setEnabled(true); } } void UI_RAW2EDFapp::PhysicalDimensionLineEdited(QString qstr) { qstr.prepend(" "); PhysicalMaximumSpinbox->setSuffix(qstr); } edfbrowser_157_source/PaxHeaders.7921/import_annotations.h0000644000000000000000000000012712646460742020772 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/import_annotations.h0000644000175000001440000001006412646460742021330 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef IMPORTANNOTATIONSFORM1_H #define IMPORTANNOTATIONSFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "utc_date_time.h" #include "edf_annot_list.h" #include "utils.h" #include "annotations_dock.h" #include "xml.h" #include "edflib.h" #include "check_edf_file.h" #include "edf_annotations.h" class UI_Mainwindow; struct import_annotations_var_block { char separator[4]; int format; int onsettimeformat; int onsetcolumn; int descriptioncolumn; int manualdescription; int useduration; int durationcolumn; char description[21]; int datastartline; int dceventbittime; double triggerlevel; int ignoreconsecutive; }; class UI_ImportAnnotationswindow : public QObject { Q_OBJECT public: UI_ImportAnnotationswindow(QWidget *parent); UI_Mainwindow *mainwindow; private: QDialog *ImportAnnotsDialog; QTabWidget *tabholder; QWidget *tab[4]; QLabel *SeparatorLabel, *OnsetColumnLabel, *DatastartLabel, *OnsetTimeLabel, *DCEventSignalLabel, *DCEventBitTimeLabel, *DCEventTriggerLevelLabel; QLineEdit *SeparatorLineEdit, *DescriptionLineEdit; QSpinBox *OnsetColumnSpinBox, *DurationColumnSpinBox, *DescriptionColumnSpinBox, *DatastartSpinbox, *BitTimeSpinbox; QDoubleSpinBox *DCEventTriggerLevelSpinBox; QComboBox *RelativeTimeComboBox, *DCEventSignalComboBox; QVBoxLayout *asciiSettingsVBoxLayout, *DCEventVBoxLayout, *mainLayout; QHBoxLayout *asciiSettingsHBoxLayout1, *asciiSettingsHBoxLayout2, *asciiSettingsHBoxLayout3, *asciiSettingsHBoxLayout4, *asciiSettingsHBoxLayout5, *asciiSettingsHBoxLayout6, *asciiSettingsHBoxLayout7, *DCEventHBoxLayout1, *DCEventHBoxLayout2, *DCEventHBoxLayout3, *horLayout; QRadioButton *DescriptionColumnRadioButton, *UseManualDescriptionRadioButton; QCheckBox *IgnoreConsecutiveCheckBox, *DurationCheckBox; QPushButton *CloseButton, *ImportButton; int tab_index_array[4]; int import_from_xml(void); int import_from_ascii(void); int import_from_edfplus(void); int import_from_dcevent(void); private slots: void ImportButtonClicked(); void descriptionRadioButtonClicked(bool); void DCEventSignalChanged(int); void DurationCheckBoxChanged(int); void TabChanged(int); }; #endif edfbrowser_157_source/PaxHeaders.7921/check_edf_file.h0000644000000000000000000000013212646460742017731 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/check_edf_file.h0000644000175000001440000000273612646460742020302 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef CHECK_EDF_FILE1_H #define CHECK_EDF_FILE1_H #include #include #include #include "global.h" #include "utc_date_time.h" #include class EDFfileCheck { public: struct edfhdrblock * check_edf_file(FILE *, char *, int live_stream=0); private: struct edfhdrblock *edfhdr; int is_integer_number(char *); int is_number(char *); long long get_long_duration(char *); }; #endif // CHECK_EDF_FILE1_H edfbrowser_157_source/PaxHeaders.7921/edit_annotation_dock.cpp0000644000000000000000000000013212646460742021551 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/edit_annotation_dock.cpp0000644000175000001440000002557312646460742022126 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "annotations_dock.h" UI_AnnotationEditwindow::UI_AnnotationEditwindow(int file_number, QWidget *w_parent) { mainwindow = (UI_Mainwindow *)w_parent; file_num = file_number; annotation = mainwindow->annotationlist[file_num]; dockedit = new QDockWidget("Annotation editor", w_parent); dockedit->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); dockedit->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable); annot_edit_dialog = new QDialog; annot_edit_dialog->setMinimumSize(640, 45); dockedit->setWidget(annot_edit_dialog); descriptionLabel = new QLabel(annot_edit_dialog); descriptionLabel->setGeometry(10, 10, 78, 25); descriptionLabel->setText("Description"); annot_descript_lineEdit = new QLineEdit(annot_edit_dialog); annot_descript_lineEdit->setGeometry(90, 10, 150, 25); onsetLabel = new QLabel(annot_edit_dialog); onsetLabel->setGeometry(250, 10, 48, 25); onsetLabel->setText("Onset"); posNegTimebox = new QComboBox(annot_edit_dialog); posNegTimebox->setGeometry(300, 10, 35, 25); posNegTimebox->setEditable(false); posNegTimebox->addItem("+"); posNegTimebox->addItem("-"); onset_daySpinbox = new QSpinBox(annot_edit_dialog); onset_daySpinbox->setGeometry(335, 10, 45, 25); onset_daySpinbox->setRange(0, 99); onset_daySpinbox->setSingleStep(1); onset_daySpinbox->setValue(0); onset_timeEdit = new QTimeEdit(annot_edit_dialog); onset_timeEdit->setGeometry(380, 10, 100, 25); onset_timeEdit->setDisplayFormat("hh:mm:ss.zzz"); onset_timeEdit->setMinimumTime(QTime(-1, 0, 0, 0)); durationLabel = new QLabel(annot_edit_dialog); durationLabel->setGeometry(490, 10, 58, 25); durationLabel->setText("Duration"); duration_spinbox = new QDoubleSpinBox(annot_edit_dialog); duration_spinbox->setGeometry(550, 10, 120, 25); duration_spinbox->setRange(-1.0, 10000.0); duration_spinbox->setSingleStep(1.0); duration_spinbox->setDecimals(3); duration_spinbox->setSuffix(" sec"); duration_spinbox->setValue(-1.0); modifybutton = new QPushButton(annot_edit_dialog); modifybutton->setGeometry(720, 10, 100, 25); modifybutton->setText("Modify"); modifybutton->setEnabled(false); deletebutton = new QPushButton(annot_edit_dialog); deletebutton->setGeometry(840, 10, 100, 25); deletebutton->setText("Delete"); deletebutton->setEnabled(false); createbutton = new QPushButton(annot_edit_dialog); createbutton->setGeometry(960, 10, 100, 25); createbutton->setText("Create"); QObject::connect(modifybutton, SIGNAL(clicked()), this, SLOT(modifyButtonClicked())); QObject::connect(deletebutton, SIGNAL(clicked()), this, SLOT(deleteButtonClicked())); QObject::connect(createbutton, SIGNAL(clicked()), this, SLOT(createButtonClicked())); QObject::connect(dockedit, SIGNAL(visibilityChanged(bool)), this, SLOT(open_close_dock(bool))); } void UI_AnnotationEditwindow::open_close_dock(bool visible) { if(visible==true) { mainwindow->annot_editor_active = 1; mainwindow->show_annot_markers = 1; if(mainwindow->annotationlist_backup==NULL) { mainwindow->annotationlist_backup = edfplus_annotation_copy_list(&mainwindow->annotationlist[0]); } } else { modifybutton->setEnabled(false); deletebutton->setEnabled(false); mainwindow->annot_editor_active = 0; } } void UI_AnnotationEditwindow::modifyButtonClicked() { annotation = edfplus_annotation_item(&mainwindow->annotationlist[file_num], annot_num); annotation->onset = onset_daySpinbox->value() * 86400 * TIME_DIMENSION; annotation->onset += onset_timeEdit->time().hour() * 3600 * TIME_DIMENSION; annotation->onset += onset_timeEdit->time().minute() * 60 * TIME_DIMENSION; annotation->onset += onset_timeEdit->time().second() * TIME_DIMENSION; annotation->onset += onset_timeEdit->time().msec() * (TIME_DIMENSION / 1000); if(posNegTimebox->currentIndex() == 1) { annotation->onset = -(annotation->onset); } annotation->onset += mainwindow->edfheaderlist[file_num]->starttime_offset; if(duration_spinbox->value()>0.0) { snprintf(annotation->duration, 16, "%f", duration_spinbox->value()); } else { annotation->duration[0] = 0; } strncpy(annotation->annotation, annot_descript_lineEdit->text().toUtf8().data(), MAX_ANNOTATION_LEN); annotation->annotation[MAX_ANNOTATION_LEN] = 0; annotation->modified = 1; annotation->selected = 1; mainwindow->annotations_edited = 1; mainwindow->annotations_dock[file_num]->updateList(); mainwindow->maincurve->update(); } void UI_AnnotationEditwindow::deleteButtonClicked() { edfplus_annotation_delete(&mainwindow->annotationlist[file_num], annot_num); annotation = edfplus_annotation_item(&mainwindow->annotationlist[file_num], annot_num); if(annotation!=NULL) { annotation->selected = 1; annotation->jump = 1; } modifybutton->setEnabled(false); deletebutton->setEnabled(false); mainwindow->annotations_edited = 1; mainwindow->save_act->setEnabled(true); mainwindow->annotations_dock[file_num]->updateList(); mainwindow->maincurve->update(); } void UI_AnnotationEditwindow::createButtonClicked() { annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); annotation->onset = onset_daySpinbox->value() * 86400 * TIME_DIMENSION; annotation->onset += onset_timeEdit->time().hour() * 3600 * TIME_DIMENSION; annotation->onset += onset_timeEdit->time().minute() * 60 * TIME_DIMENSION; annotation->onset += onset_timeEdit->time().second() * TIME_DIMENSION; annotation->onset += onset_timeEdit->time().msec() * (TIME_DIMENSION / 1000); if(posNegTimebox->currentIndex() == 1) { annotation->onset = -(annotation->onset); } annotation->onset += mainwindow->edfheaderlist[file_num]->starttime_offset; annotation->file_num = file_num; if(duration_spinbox->value()>0.0) { snprintf(annotation->duration, 16, "%f", duration_spinbox->value()); } else { annotation->duration[0] = 0; } strncpy(annotation->annotation, annot_descript_lineEdit->text().toUtf8().data(), MAX_ANNOTATION_LEN); annotation->annotation[MAX_ANNOTATION_LEN] = 0; annotation->modified = 1; edfplus_annotation_add_item(&mainwindow->annotationlist[file_num], annotation); mainwindow->annotations_edited = 1; mainwindow->annotations_dock[file_num]->updateList(); mainwindow->maincurve->update(); } void UI_AnnotationEditwindow::annotEditSetOnset(long long onset) { QTime ta; if(onset < 0LL) { onset_daySpinbox->setValue((-(onset)) / TIME_DIMENSION / 86400); ta.setHMS(((-(onset)) / TIME_DIMENSION / 3600) % 24, (((-(onset)) / TIME_DIMENSION) % 3600) / 60, ((-(onset)) / TIME_DIMENSION) % 60, ((-(onset)) % TIME_DIMENSION) / 10000); posNegTimebox->setCurrentIndex(1); } else { onset_daySpinbox->setValue(onset / TIME_DIMENSION / 86400); ta.setHMS((onset / TIME_DIMENSION / 3600) % 24, ((onset / TIME_DIMENSION) % 3600) / 60, (onset / TIME_DIMENSION) % 60, (onset % TIME_DIMENSION) / 10000); posNegTimebox->setCurrentIndex(0); } onset_timeEdit->setTime(ta); } void UI_AnnotationEditwindow::annotEditSetDuration(long long duration) { double tmp; tmp = duration; tmp /= TIME_DIMENSION; duration_spinbox->setValue(tmp); } void UI_AnnotationEditwindow::set_selected_annotation(int file_nr, int annot_nr) { long long l_tmp; QTime ta; file_num = file_nr; annot_num = annot_nr; annotation = edfplus_annotation_item(&mainwindow->annotationlist[file_num], annot_num); annot_descript_lineEdit->setText(QString::fromUtf8(annotation->annotation)); l_tmp = annotation->onset - mainwindow->edfheaderlist[annotation->file_num]->starttime_offset; if(l_tmp < 0LL) { onset_daySpinbox->setValue((-(l_tmp)) / TIME_DIMENSION / 86400); ta.setHMS(((-(l_tmp)) / TIME_DIMENSION / 3600) % 24, (((-(l_tmp)) / TIME_DIMENSION) % 3600) / 60, ((-(l_tmp)) / TIME_DIMENSION) % 60, ((-(l_tmp)) % TIME_DIMENSION) / 10000); posNegTimebox->setCurrentIndex(1); } else { onset_daySpinbox->setValue(l_tmp / TIME_DIMENSION / 86400); ta.setHMS((l_tmp / TIME_DIMENSION / 3600) % 24, ((l_tmp / TIME_DIMENSION) % 3600) / 60, (l_tmp / TIME_DIMENSION) % 60, (l_tmp % TIME_DIMENSION) / 10000); posNegTimebox->setCurrentIndex(0); } onset_timeEdit->setTime(ta); if(strlen(annotation->duration)) { duration_spinbox->setValue(atof(annotation->duration)); } else { duration_spinbox->setValue(-1); } modifybutton->setEnabled(true); deletebutton->setEnabled(true); } void UI_AnnotationEditwindow::set_selected_annotation(struct annotationblock *annot) { long long l_tmp; QTime ta; annotation = annot; file_num = annot->file_num; annot_descript_lineEdit->setText(QString::fromUtf8(annotation->annotation)); l_tmp = annotation->onset - mainwindow->edfheaderlist[annotation->file_num]->starttime_offset; if(l_tmp < 0LL) { onset_daySpinbox->setValue((-(l_tmp)) / TIME_DIMENSION / 86400); ta.setHMS(((-(l_tmp)) / TIME_DIMENSION / 3600) % 24, (((-(l_tmp)) / TIME_DIMENSION) % 3600) / 60, ((-(l_tmp)) / TIME_DIMENSION) % 60, ((-(l_tmp)) % TIME_DIMENSION) / 10000); posNegTimebox->setCurrentIndex(1); } else { onset_daySpinbox->setValue(l_tmp / TIME_DIMENSION / 86400); ta.setHMS((l_tmp / TIME_DIMENSION / 3600) % 24, ((l_tmp / TIME_DIMENSION) % 3600) / 60, (l_tmp / TIME_DIMENSION) % 60, (l_tmp % TIME_DIMENSION) / 10000); posNegTimebox->setCurrentIndex(0); } onset_timeEdit->setTime(ta); if(strlen(annotation->duration)) { duration_spinbox->setValue(atof(annotation->duration)); } else { duration_spinbox->setValue(-1); } modifybutton->setEnabled(false); deletebutton->setEnabled(false); } edfbrowser_157_source/PaxHeaders.7921/scp_ecg2edf.h0000644000000000000000000000013212646460742017203 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/scp_ecg2edf.h0000644000175000001440000000675412646460742017560 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_SCPECG2EDFFORM_H #define UI_SCPECG2EDFFORM_H #include #include #include #include #include #include #include #include #include #if QT_VERSION < 0x050000 #include #include #endif #include #include #include #include #include #include #include "global.h" #include "utils.h" #include "edflib.h" #include "utc_date_time.h" class UI_SCPECG2EDFwindow : public QObject { Q_OBJECT public: UI_SCPECG2EDFwindow(char *recent_dir=NULL, char *save_dir=NULL); private: QPushButton *pushButton1, *pushButton2; QTextEdit *textEdit1; QDialog *myobjectDialog; char *recent_opendir, *recent_savedir; unsigned short crc_ccitt_table[256]; struct section_prop_struct{ int present; long long file_offset; unsigned short crc; int section_id; int section_length; int section_version; int section_protocol_version; char reserved[6]; } sp[12]; struct lead_prop_struct{ int start; int end; int samples; int bytes; unsigned char label; } lp[256]; struct huffmantable_struct{ int h_tables_cnt; int code_structs_cnt; int prefix_bits; int total_bits; int table_mode_switch; int base_value; int base_code; } ht; struct patient_data_struct{ char pat_id[21]; int startdate_year; int startdate_month; int startdate_day; int starttime_hour; int starttime_minute; int starttime_second; char last_name[21]; char first_name[21]; int birthdate_year; int birthdate_month; int birthdate_day; int sex; char device_model[6]; char device_serial[49]; char device_ident[49]; char manufacturer[49]; unsigned char lang_code; } pat_dat; int read_data_section_zero(FILE *, char *, long long); int read_section_header(int, FILE *, long long, char *); int check_crc(FILE *, long long, long long, unsigned short, char *); void crc_ccitt_init(void); unsigned short crc_ccitt(const unsigned char *, int, unsigned short); inline unsigned char reverse_bitorder(unsigned char); void lead_label_lookup(unsigned char, char *); int get_patient_data(FILE *); private slots: void SelectFileButton(); }; #endif edfbrowser_157_source/PaxHeaders.7921/save_montage_dialog.cpp0000644000000000000000000000012712646460742021365 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/save_montage_dialog.cpp0000644000175000001440000002477012646460742021734 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "save_montage_dialog.h" UI_SaveMontagewindow::UI_SaveMontagewindow(QWidget *w_parent) { int i; mainwindow = (UI_Mainwindow *)w_parent; if(mainwindow->files_open==1) { SaveMontageDialog = NULL; SaveButtonClicked(); return; } SaveMontageDialog = new QDialog; SaveMontageDialog->setMinimumSize(800, 180); SaveMontageDialog->setMaximumSize(800, 180); SaveMontageDialog->setWindowTitle("Save montage"); SaveMontageDialog->setModal(true); SaveMontageDialog->setAttribute(Qt::WA_DeleteOnClose, true); label1 = new QLabel(SaveMontageDialog); label1->setGeometry(10, 10, 780, 25); label1->setText("Choose from which file you want to save the montage:"); filelist = new QListWidget(SaveMontageDialog); filelist->setGeometry(10, 35, 780, 75); filelist->setSelectionBehavior(QAbstractItemView::SelectRows); filelist->setSelectionMode(QAbstractItemView::SingleSelection); for(i=0; ifiles_open; i++) { new QListWidgetItem(QString::fromLocal8Bit(mainwindow->edfheaderlist[i]->filename), filelist); } SaveButton = new QPushButton(SaveMontageDialog); SaveButton->setGeometry(10, 140, 100, 25); SaveButton->setText("Save"); CloseButton = new QPushButton(SaveMontageDialog); CloseButton->setGeometry(690, 140, 100, 25); CloseButton->setText("Close"); QObject::connect(CloseButton, SIGNAL(clicked()), SaveMontageDialog, SLOT(close())); QObject::connect(SaveButton, SIGNAL(clicked()), this, SLOT(SaveButtonClicked())); filelist->setCurrentRow(mainwindow->files_open - 1); SaveMontageDialog->exec(); } void UI_SaveMontagewindow::SaveButtonClicked() { int i, j, n; char mtg_path[MAX_PATH_LENGTH]; FILE *mtgfile; if(mainwindow->files_open==1) n = 0; else n = filelist->currentRow(); strcpy(mtg_path, mainwindow->recent_montagedir); strcat(mtg_path, "/my_montage.mtg"); strcpy(mtg_path, QFileDialog::getSaveFileName(0, "Save montage", QString::fromLocal8Bit(mtg_path), "Montage files (*.mtg *.MTG)").toLocal8Bit().data()); if(!strcmp(mtg_path, "")) { return; } if(strlen(mtg_path) > 4) { if(strcmp(mtg_path + strlen(mtg_path) - 4, ".mtg")) { strcat(mtg_path, ".mtg"); } } get_directory_from_path(mainwindow->recent_montagedir, mtg_path, MAX_PATH_LENGTH); mtgfile = fopeno(mtg_path, "wb"); if(mtgfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for writing."); messagewindow.exec(); return; } fprintf(mtgfile, "\n<" PROGRAM_NAME "_montage>\n"); for(i=0; isignalcomps; i++) { if(!strcmp(mainwindow->signalcomp[i]->edfhdr->filename, mainwindow->edfheaderlist[n]->filename)) { fprintf(mtgfile, " \n"); fprintf(mtgfile, " "); xml_fwrite_encode_entity(mtgfile, mainwindow->signalcomp[i]->alias); fprintf(mtgfile, "\n"); fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->num_of_signals); fprintf(mtgfile, " %f\n", mainwindow->signalcomp[i]->voltpercm); fprintf(mtgfile, " %f\n", mainwindow->signalcomp[i]->screen_offset); fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->polarity); fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->color); if(mainwindow->signalcomp[i]->spike_filter) { fprintf(mtgfile, " %i\n", 1); } fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->filter_cnt); fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->fidfilter_cnt); fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->ravg_filter_cnt); for(j=0; jsignalcomp[i]->num_of_signals; j++) { fprintf(mtgfile, " \n"); fprintf(mtgfile, " \n"); fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->factor[j]); fprintf(mtgfile, " \n"); } if(mainwindow->signalcomp[i]->spike_filter) { fprintf(mtgfile, " \n"); fprintf(mtgfile, " %.16f\n", mainwindow->signalcomp[i]->spike_filter_velocity); fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->spike_filter_holdoff); fprintf(mtgfile, " \n"); } for(j=0; jsignalcomp[i]->filter_cnt; j++) { fprintf(mtgfile, " \n"); fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->filter[j]->is_LPF); fprintf(mtgfile, " %.16f\n", mainwindow->signalcomp[i]->filter[j]->cutoff_frequency); fprintf(mtgfile, " \n"); } for(j=0; jsignalcomp[i]->ravg_filter_cnt; j++) { fprintf(mtgfile, " \n"); fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->ravg_filter[j]->type); fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->ravg_filter[j]->size); fprintf(mtgfile, " \n"); } for(j=0; jsignalcomp[i]->fidfilter_cnt; j++) { fprintf(mtgfile, " \n"); fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->fidfilter_type[j]); fprintf(mtgfile, " %.16f\n", mainwindow->signalcomp[i]->fidfilter_freq[j]); fprintf(mtgfile, " %.16f\n", mainwindow->signalcomp[i]->fidfilter_freq2[j]); fprintf(mtgfile, " %.16f\n", mainwindow->signalcomp[i]->fidfilter_ripple[j]); fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->fidfilter_order[j]); fprintf(mtgfile, " %i\n", mainwindow->signalcomp[i]->fidfilter_model[j]); fprintf(mtgfile, " \n"); } if(mainwindow->signalcomp[i]->ecg_filter != NULL) { fprintf(mtgfile, " \n"); fprintf(mtgfile, " 1\n"); fprintf(mtgfile, " \n"); } if(mainwindow->signalcomp[i]->zratio_filter != NULL) { fprintf(mtgfile, " \n"); fprintf(mtgfile, " 1\n"); fprintf(mtgfile, " %f\n", mainwindow->signalcomp[i]->zratio_crossoverfreq); fprintf(mtgfile, " \n"); } if(mainwindow->signalcomp[i]->hasruler) { fprintf(mtgfile, " \n"); fprintf(mtgfile, " 1\n"); fprintf(mtgfile, " %i\n", mainwindow->maincurve->ruler_x_position); fprintf(mtgfile, " %i\n", mainwindow->maincurve->ruler_y_position); fprintf(mtgfile, " %i\n", mainwindow->maincurve->floating_ruler_value); fprintf(mtgfile, " \n"); } fprintf(mtgfile, " \n"); } } #ifdef Q_OS_WIN32 __mingw_fprintf(mtgfile, " %lli\n", mainwindow->pagetime); #else fprintf(mtgfile, " %lli\n", mainwindow->pagetime); #endif struct spectrumdocksettings settings; for(i=0; ispectrumdock[i]->dock->isVisible()) { mainwindow->spectrumdock[i]->getsettings(&settings); if(settings.signalnr >= 0) { fprintf(mtgfile, " \n"); fprintf(mtgfile, " %i\n", settings.signalnr); fprintf(mtgfile, " %i\n", settings.amp); fprintf(mtgfile, " %i\n", settings.log_min_sl); fprintf(mtgfile, " %i\n", settings.wheel); fprintf(mtgfile, " %i\n", settings.span); fprintf(mtgfile, "
%i
\n", settings.center); fprintf(mtgfile, " %i\n", settings.log); fprintf(mtgfile, " %i\n", settings.sqrt); fprintf(mtgfile, " %i\n", settings.colorbar); fprintf(mtgfile, " %.10f\n", settings.maxvalue); fprintf(mtgfile, " %.10f\n", settings.maxvalue_sqrt); fprintf(mtgfile, " %.10f\n", settings.maxvalue_vlog); fprintf(mtgfile, " %.10f\n", settings.maxvalue_sqrt_vlog); fprintf(mtgfile, " %.10f\n", settings.minvalue_vlog); fprintf(mtgfile, " %.10f\n", settings.minvalue_sqrt_vlog); fprintf(mtgfile, "
\n"); } } } fprintf(mtgfile, "\n"); fclose(mtgfile); if(mainwindow->files_open == 1) { strcpy(&mainwindow->recent_file_mtg_path[0][0], mtg_path); } if(SaveMontageDialog!=NULL) SaveMontageDialog->close(); } edfbrowser_157_source/PaxHeaders.7921/version.txt0000644000000000000000000000013212646460742017114 xustar0030 mtime=1452958178.267246665 30 atime=1452958178.267246665 30 ctime=1452958178.267246665 edfbrowser_157_source/version.txt0000644000175000001440000006432312646460742017465 0ustar00guvusers00000000000000 version 1.57 January 16, 2016 -------------- - Update annotation markers when switching between real and relative time. - Added an EDF converter for the Biox CB-1305-C 3-channel ambulatory ECG recorder/holter. - Spectrumanalyzer: make numbers like frequency more "human readable" by using suffix like K(ilo), M(ega), etc. - Increase the maximum DFT blocksize to 16777216 (2^24) samples. - Don't use the native menubar. - Realtime playback function added. - Added the possibility to choose between "stairsteps" or linear interpolation between two consecutive samples for drawing the traces when number of samples on the screen is less than number of horizontal screen pixels. You can select it in the settings menu, tab "Other" (Tools -> Options). - Added the possibility to open a streaming file from the commandline. version 1.56 June 25, 2015 -------------- - Fixed a bug that caused the Unisens converter to fail. - Added a tool that converts an audiorecording containing an FM modulated ECG waveform to EDF. - Added an anti-aliasing filter to the samplerate divider/decimator in the file reducer tool. The order of this filter can be choosen. - Make it possible to remove just one filter. (Before, you could only remove all filters.) - Make it possible to close just one file. (Before, you could only close all files.) - Make the Nihon Kohden converter work with "EEG-1100A V02.00" files. - Changed licence to GPLv3. - Added a new setting in the settings menu. Now you can set the default amplitude that will be applied when you add new signals. Before the default was always 100. - Qt has been updated to 4.8.7. version 1.55 February 7, 2015 ------------ - Added a MIT to EDF+ converter (to convert files from PhysioBank at physionet.org). At this moment it supports the "Format 212" and "Format 16". Most of the signal files in PhysioBank are written in format 212. Other formats will be probably added in future. Annotations (in the *.atr or *.ari file) will be read and converted to EDF+ as well. - docked Power Spectrum: show percentage when using colorbars, in the settingsmenu, it's now possible to select between auto-gain or manual sensitivity for the colorbars. - Allow to open multiple docked Power Spectrum windows. - Correct the screen-offset when inverting a signal that contains a dc-offset. - Removed a bug in the "Organize signals" dialog that caused a crash when selecting signals in reverse order. - Removed a bug that caused a crash when selecting a bessel bandstop/pass filter with an order > 10. - Increased the maximum number of filters from 8 to 16. - Added a Spike filter which can be used to filter out spikes, glitches, fast transients or pacemaker impulses. version 1.54 October 11, 2014 ------------ - The Unisens to EDF converter now supports also files with binary format double, int64 or uint64. - The Power Spectrum now can plot a logarithmic vertical scale. - The docked Power Spectrum now auto-adjust the y-scale only once. - The docked Power Spectrum now can also be used in streaming mode. - The settings of the docked Power Spectrum will be stored in the montage as well. - EDFbrowser can now play video's (Linux version only). Have a look at the manual for the details. - Fixed a bug in the filter dialog that could cause some widgets not being shown. - Removed compile-errors when using Qt5 (due to bugs in Qt5, it's not advised to use Qt5 yet). - From now on, the Mingw-w64 compiler needs to be used for Windows. (see README.txt) - Qt has been updated to 4.8.6. version 1.53 December 10, 2013 ------------ - The activity of the floating ruler will now be stored in the montages as well. - Added a filter to the annotationslist. - Modified the BI9800 to EDF converter to make it work with 48-hour recordings. - Made the viewtime (fileposition) indicator configurable. Added the date to the viewtime indicator in the left down corner of the screen. This can be configured in the settings menu. - Made the window title bar configurable. This can be configured in the settings menu. - fixed a bug in the EDF+D to EDF+C converter. - Added the possibility to save and load different color schemas. - Added support for the Unisens fileformat. You will find the converter in the Tools menu. - Added the possibility to save and load colorschemas. version 1.52 September 7, 2013 ------------ - Added an SCP-ECG file to EDF+ converter. Bimodal compression or customized Hufmanntables are not supported. Lossless compression using default Hufmanntable and/or 1th/2th differences is supported. Character-encoding other than ASCII/Latin-1 is not supported. - Added two shortcuts (Plus and Minus keys) to increase or decrease the amplitude of the signals (sensitivity). - Added the possibility to choose between little endian or big endian encoding in the binary/raw to EDF converter tool. - Increased the number of pre-defined montage shortcuts from 8 to 12 (keys F1 to F12). - Added the possibility to use aliases for the signallabels on the screen. - Qt has been updated to 4.8.5. version 1.51 May 11, 2013 ------------ - Added a Manscan MICROAMPS binary file to EDF+ converter. - Solved another bug in the sorting algorithm used for the annotationlist. version 1.50 April 20, 2013 ------------ - Fixed a bug in the ECG heartrate detection algorithm when a high samplerate was used. - Improved the sorting algorithm used for the annotationlist, it was very slow when the annotationlist contains more than 10000 annotations. - Added the possibility to adjust the samplerate divider for all signals at once in the reducer/decimator tool. - EDFbrowser now checks online for a newer version during startup. This can be switched off in the settings menu. version 1.49 February 5, 2013 ------------ - Added a binary/raw to EDF converter tool. - Solved a bug in the "Import annotations" tool. When importing from ascii, wrong onset-times were created when there were more than 7 digits after the decimal point. - Added a scrollbar to the options- / settingsdialog in order to make it fit on screens with low vertical height (modern laptops with 16:9 screen). - Removed GTK-style support because it's broken. - Updated Qt to 4.8.4 version 1.48 June 8, 2012 ------------ - Added sub-second precision for annotations when using the Nihon Kohden converter. (Before, the onsettimes of the annotations were rounded to seconds.) - Added Z-EEG measurement. - Improved the header editor/fixer. Now it accepts files with a maximum of 2048 signals. (Before it was limited to files with a maximum of 256 signals.) Now, it can also fix the digital minimum/maximum fields in the header (e.g. when a broken number was written instead of an integer number). - Updated Qt to 4.8.2 version 1.47 May 7, 2012 ------------ - Solved a bug that caused a crash when saving an EDF- or BDF-file after importing annotations. - Changed the "Export ECG RR-interval" tool in such a way that you can easily export the whole recording. Also, now it's possible to import them as annotations directly. - The tool "Import annotations/events" can now also import the duration of an annotation/event (from ASCII- or XML-files). - Added the possibility to hide or unhide annotations from the screen. (Right-click on an annotation in the annotationswindow.) version 1.46 April 13, 2012 ------------ - Solved a bug that caused a crash when the "Abort" button was clicked when opening a BDF-file. - Solved some small bugs and made some enhancements. - Updated Qt to 4.8.1. version 1.45 March 31, 2012 ------------ - Added the possibility to disable scanning for annotations or triggers when opening a file, depending of the filesize. This can be useful when working with big files that take a lot of time to read-in annotations, events or triggers. (Due to the nature of the EDF-format, the annotations-channel(s) needs to be read from the beginning till the end of the file.) In the "Settings -> other" dialog you can adjust the filesize which above EDFbrowser will not scan the file for annotations. (between 100 MB and 10 GB) - extended the capabilities of the header-editor. Now it can also fix files that have a wrong number of datarecords written in the header or when the file does not end at the boundary of a datarecord. See the manual for the details. - Improved the ECG heartrate detection algorithm. - Fixed some bugs related to signals with inversed polarity (i.e. when physical maximum is lower than physical minimum). version 1.44 March 4, 2012 ------------ - Fixed a bug that caused the "print to PDF / Postscript / Image" to fail when non-ascii characters where present in the new filename. - Fixed a bug that caused "printing to image" drawing the signals too thick and wrong rulers. - Fixed a bug in the ECG heartrate detection algorithm that could cause wrong measurements with high heartrates (more than 120 bpm). - Added Mousewheel zoom-in/out by pressing the Ctrl-key. version 1.43 Februari 17, 2012 ------------ - Fixed multiple bugs related to annotationmarkers and EDFplus feature to use subsecondprecision in the starttime of the file. (Only affects files that uses the subsecond starttime offset EDF+ feature.) version 1.42 Februari 1, 2012 ------------ - Fixed a problem with EDFbrowser not capable to handle filenames and/or directories that contain non-ascii characters. From now on, filenames/paths will be handled and saved using the local 8-bit encoding. - Added multi-threading capabilities to the drawing engine. EDFbrowser will now use all available cpu-cores in your system to speedup the drawing of the signals. version 1.41 December 4, 2011 ------------ - Fixed a bug (introduced with ver. 1.40) that caused a long time to open an EDF+ or BDF+ file when it contains many annotations. - Improved printing quality. On some printers or pdf-readers, the signals and rulers were hardly visible because the linewidth was too small. - Added the possibility to set the colors of the averaging window to black/white. - Added the possibility to check for and remove duplicate annotations (Tools menu). version 1.40 December 1, 2011 ------------ - Added the possibility to reduce the samplerate of one or more signals in the tool "Reduce signals, duration or samplerate" (Tools menu). - Added the possibility to change/edit the starttime/date of a file with the EDF/BDF header editor (Tools menu). - The Statistics dialog shows also the number of zero-crossings and the frequency of a signal. - The Nihon Kohden to EDF+ converter now processes also the Trigger/Marker channel. For example, photo- or dc-triggers will be processed by the converter and can be displayed by EDFbrowser. - Fixed a bug in the signalcurve (graph) of the averaging window, when "invert" was selected, the vertical ruler could disappear. - Fixed a bug in the floating ruler. - Raised the maximum amount of signals per file limit from 256 to 512. version 1.39 September 20, 2011 ------------ - Fixed another bug related to annotationmarkers and EDFplus feature to use subsecondprecision in the starttime of the file. - Updated Qt to 4.7.4 version 1.38 August 24, 2011 ------------ - Fixed lots of regression bugs introduced with version 1.37. - Fixed a bug related to annotationmarkers and EDFplus feature to use subsecondprecision in the starttime of the file. - Fixed a bug in the ascii to edf converter that caused to produce an invalid edf file when all samples in have value "0.0". version 1.37 August 17, 2011 ------------ - Removed the limitation that no more annotations can be saved than the amount of datarecords. EDFbrowser could only write one annotation per datarecord. From now on, if there are more annotations than datarecords, the size (smpls/record) of the annotationchannel will increase automatically in order to fit multiple annotations as needed. version 1.36 June 16, 2011 ------------ - Solved a bug when importing events/annotations from an ascii-file. version 1.35 June 16, 2011 ------------ - Changed the selectionbehaviour of the signallist in Signals -> Organize. Now you can select multiple signals when organizing the signals on the screen. - Solved a bug that caused showing the wrong signal when there are duplicate signalnames in a file. - Solved a bug that caused a cryptic error message "avg_cnt is ..." when averaging a signal using a trigger/annotation which was not inside the selected timewindow. - Now it is possible to start/open multiple averagingwindows applied on the same signal. - Added the possibility to invert te waveform of the averagingwindow. - Solved a bug that caused an errormessage when trying to open a large file (>2.1GB) on a Mac. - Removed some bugs in the heartrate detection code. - Now you can choose between different kinds of data (R onset or RR-interval or both) when exporting the heartrate data. version 1.34 May 9, 2011 ------------ - Added ECG heartrate detection (it calculates beats per minute from the ECG-waveform). - Added the possibility to import annotations, also from discontinues EDF+D or BDF+D files. - Added mousewheel scrolling. - Added the possibility to save the data from averaging as EDF/BDF. - Added the possibility to (re-)organize (re-order and/or invert) the signals on the screen in an easy way via Menu -> Signals -> Organize. - Modified the annotation editor, from now on annotations with an onsettime more than 24 hours can be edited as well. - Solved a bug that prevented a messagebox to appear when trying to open a BDF+D file. - Changed the way the onsettime of the annotations are presented. version 1.33 March 22, 2011 ------------ - Added the possibility to import/extract triggers/events from/recorded on a dc-coupled channel. - Added the possibility to perform "averaging" (evoked potentials or other triggers) using (imported) annotations, events or other kind of triggers. - Added a WAV to EDF converter. - Modified the Nihon Kohden to EDF converter so that it will use the electrodenames defined by the user in the aquisition software. - Fixed a bug that caused writing a wrong value in the datarecorddurationfield of the header when saving annotations and when the number in the datarecorddurationfield of the sourcefile has more than six digits after the dot. - Fixed a bug related to a rarely used EDFplus feature to use subsecondprecision in the starttime of the file. Some tools ignored this feature, this has been fixed. - Updated Qt to 4.7.2 version 1.32 December 16, 2010 ------------ - Fixed a bug that prevented from updating the screen when in streaming mode and after all signals were removed. - Fixed a bug in EDFlib. version 1.31 December 8, 2010 ------------ - Added a streaming mode. The stream must be a "growing" file. This mode can be used when you have an aquisitionprogram running that writes EDF or BDF. While the aquisitionprogram writes the data to the file, you can use EDFbrowser to watch (follow) the actual data. EDFbrowser will regularly check the actual filesize and show the last part of the file i.e. the most actual/recent data. - Added a "moving average" filtermodel (high- and lowpass). - The "View montage" dialogs got a facelift. version 1.30 November 24, 2010 ------------ - Added the possibility to import events/annotations from a text/csv or XML file. - Enhanced the "Export annotations/events" tool. Now you can choose the separator character (comma or tab) and you can choose different ISO time (and date) timestamps encodings. XML export is possible as well. - Solved a bug in de the "adjust filter" dialogue. When using a notchfilter, the "order" widget was shown instead of the "Q-factor" widget. - Updated Qt to version 4.7.1. version 1.29 November 9, 2010 ------------ - Added the possibility to adjust the filter settings while watching the result (realtime). - Fixed a bug that caused the program to remember the wrong montage. - Added a possibility in the ASCII to EDF converter to detect the physical maximum values of the signals automatically. - The ASCII to EDF converter can also convert to BDF (24-bit). version 1.28 October 27, 2010 ------------ - Added support for reading the "Status" signal in Biosemi data files. This can be switched on/off in the settings menu. - Added a Biosemi to BDF+ converter. It converts the Biosemi trigger inputs to annotations which can be read and processed by EDFbrowser. - Added an EDF-converter for the Bmeye Nexfin / FrameInspector csv-output (beat-to-beat data, bloodpressure waveform, analog inputs). - Added zoom-in/zoom-out function using Ctrl++ and Ctrl--. - Added keyboard shortcuts and accelerators to the menu's. - From now on, the timescale will be saved in montages as well. - When opening a file, the last used montage (with that file) will be applied automatically. This behaviour can be switched off in the settingsmenu. version 1.27 September 27, 2010 ------------ - Made all the file-open/save dialogs native. This improves the speed in file-listing on some windows-pc's. version 1.26 September 7, 2010 ------------ - Added an header-editor. - Added a file reducer/cropper. - Added the possibility to clip the signals to their pane. - Solved a bug that rendered the settingsmenu invisible on the Mac. version 1.25 August 2, 2010 ------------ - Solved a bug that caused writing invalid files and/or caused to reject opening a file because of an incompatibility while in reality the file was valid. This was caused by a localizationproblem which occured only on systems where countrysettings are used that uses a comma as a decimal separator. - Changed the name of the "Display" menu to "Timescale". - Added the entry "3 cm/sec" to the the Timescale menu. - From now on EDFbrowser will use the DPI-settings from the underlying windowmanager in order to calibrate the screen. If this doesn't work well in your situation, you can still calibrate the screen manually in the settingsmenu. - Solved a bug that caused malformed waveforms when opening large files (>4 GB) and when navigating to the end of the file. This was caused by an integer overflow. - Solved a bug in the ASCII to EDF converter (couldn't open templates). - Changed the sourcecode to improve Mac compatibility. version 1.24 June 28, 2010 ------------ - Solved a bug in the Nihon Kohden to EDF+ converter that caused a message "Can not open file *.log for reading,". version 1.23 June 23, 2010 ------------ - Changed the DFT-algorithm of the powerspectrum to an FFT-algorithm in order to avoid long computation times. - Added the possibility to adjust the blocksize for the powerspectrum (FFT). - Added an extra option to the Annotations export tool. Now you can choose to save the annotations in a comma separated textfile or in the EDFplus format. - Changed the position of the widgets in the annotation-editor window. The "Create" button will not be cut-off anymore when a monitor with a resolution of 1024 x 768 is used. - Qt has been updated to version 4.6.3 (windows version has still 4.6.2). version 1.22 june 4, 2010 ------------ - Added a docked powerspectrum which updates automatically when you navigate throug a file (PgUp,PgDn, etc,). - Added the possibility to use different backgroundcolors for different frequencyregions in the docked powerspectrum (colorbars). - Added an export function for the powerspectrum. This will export the data of the powerspectrum to a textfile. - Added a cursor to the powerspectrum. - Improved the way filters run-in. - Added an export function for annotations. This will export the annotations to a comma separated textfile. - Added a possibility to bind keys F1 ... F8 to predefined montages. This way you can quickly switch between different montages by pressing F1, F2, etc. - Removed a bug in the EDF+D to EDF+C converter that could cause a crash. - Removed a bug in the BDF+ to ASCII converter. version 1.21 may 11, 2010 ------------ - The Powerspectrum window will not block the mainwindow anymore. Now you can open multiple Powerspectrum windows (for example, to compare different blocks of data and/or different signals). - Made a printing option for the Powerspectrum. you can print the Powerspectrum to a printer, Postscript, PDF or an image by rightclicking on the curve of the Powerspectrum. - The ASCII to EDF converter now has a multiplierfactor. Cleaned up the code of the converter as well. - Fixed a bug that caused writing to a freed memory area which could cause a crash when closing the program (mainly noticeable on windows). - Fixed a memoryleak. version 1.20 may 4, 2010 ------------ - Added a power spectrum analyzer (Discrete Fourier Transform). - Removed a bug that caused wrong vertical ruler values during printing. - Removed a bug that caused a wrong screenoffset when changing the offset in the signalproperties dialog. version 1.19 april 20, 2010 ------------ - Added extra filter options: lowpass, highpass, notch, bandpass, bandstop, Butterworth, Chebyshev, Bessel, 1,2,3,...8 th order, adjustable bandpassripple or Q-factor. - Removed a bug in the BDF to EDF converter, clicking on "Select all signals" or "Deselect all signals" without a selected file, caused a crash. - Fixed a bug in the "Print to EDF" and "Print to BDF" function. Filter description in header was wrong (i.e. "LPF:" instead of "LP:"). - Fixed a bug in the Filter Dialog. When adding a new filter when signals have different samplerates, initialisation of the new filter could happen with wrong samplerate, causing a wrong frequency of the filter. - Updated Qt to version 4.6.2 version 1.18 januari 12, 2010 ------------ - added an annotation editor - solved a bug that could cause an errormessage "can not open file for reading" - solved a bug that could cause a false positive when checking the EDF-header of an EDFplus file (patientfield) version 1.17 november 4, 2009 ------------ - solved a bug in load_montage_dialog.cpp that caused a crash when loading a montage and a label was not found version 1.16 october 28, 2009 ------------ - solved a bug in the BDF+ to EDF+ converter - solved a bug in the XML parser - solved a memoryleak when using filters - solved some minor bugs - added a floating ruler - made some minor cosmetic changes - updated Qt to version 4.5.3 version 1.15 june 18, 2009 ----------- - solved a bug that could cause a crash when using crosshairs version 1.14 april 27, 2009 ----------- - solved a bug & optimized the code in the BDF to EDF converter - updated Qt to version 4.5.1 version 1.13 april 20, 2009 ----------- - added a BDF(+) to EDF(+) converter version 1.12 april 2, 2009 ----------- - bugfix release, solved a crash when removing a signal or a filter version 1.11 march 31, 2009 ----------- - added an EDF+D to EDF+C converter, it can convert discontinues files to continues files (interrupted recordings to un-interrupted recordings), can be used for BDF+D files as well - added an Emsa (*.PLG) EEG to EDF+ format converter - updated Qt to version 4.5.0 which has better GTK-style support when Gnome is used version 1.10 februari 13, 2009 ----------- - solved a bug that generated a false "read error" message when using filters at the start of the file (this bug appeared in version 1.09) version 1.09 februari 11, 2009 ----------- - solved a bug in the "Print to EDF/BDF" tools which could cause a crash - solved compilerwarnings in GCC 4.3.2 (warn_unused_result) version 1.08 december 15, 2008 ----------- - added a slider for navigating - solved a bug in the BDF+ compatibility checker - disabled the possibility to open discontinuous files (interrupted recordings) because of technical reasons version 1.07 november 5, 2008 ----------- - improved speed when a long displaytime is used - added support for the BDF+ format. Read the details here. - solved some minor bugs version 1.06 october 23, 2008 ----------- - solved a minor issue with the built-in EDF-checker - updated Qt to 4.4.3 version 1.05 september 17, 2008 ----------- - added a Finometer (Beatscope) to EDF format converter. (Finometer is a non-invasive stationary blood measurement and beat to beat haemodynamic monitoring system made by Finapres Medical Systems) read the documentation for the details. - solved a bug that causes a crash when a file was opened via the cmd-line with an unknown extension. - updated Qt to 4.4.1 Version 1.04 may 2, 2008 ----------- - added an ASCII to EDF format converter Version 1.03 march 31, 2008 ----------- - improved printing resolution - solved an issue with printermargins and fonts thanks to new printerframework in Qt 4.4.x - added option to "print" to an EDF or BDF file now you can extract one or more signals and write it to a new EDF file or you can combine signals from several files into one new EDF file printing to a BDF file is supported as well read the manual for the details - added option user defined displaytime (pagetime) - added option jump to end of recording - dropped the maximum datarecordblocksize of 61440 bytes requirement for EDF+ files from now on EDFbrowser will accept EDF+ files with larger blocksizes Version 1.02 februari 11, 2008 ----------- - solved a bug that potentially could crash the program when opening EDF+ files with a durationfield in annotations Version 1.01 januari 21, 2008 ----------- - solved two bugs that could create errors in timesyncing between multiple files - added support for large files (>2.1GB) - updated Qt to version 4.3.3 Version 1.00 januari 8, 2008 ----------- - Initial release. edfbrowser_157_source/PaxHeaders.7921/reduce_signals.cpp0000644000000000000000000000012712646460742020365 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/reduce_signals.cpp0000644000175000001440000010351412646460742020726 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "reduce_signals.h" UI_ReduceSignalsWindow::UI_ReduceSignalsWindow(QWidget *w_parent) { mainwindow = (UI_Mainwindow *)w_parent; recent_savedir = mainwindow->recent_savedir; myobjectDialog = new QDialog; myobjectDialog->setMinimumSize(715, 578); myobjectDialog->setMaximumSize(715, 578); myobjectDialog->setWindowTitle("Reduce signals and/or duration"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); label1 = new QLabel(myobjectDialog); label1->setGeometry(20, 20, 685, 25); label2 = new QLabel(myobjectDialog); label2->setGeometry(485, 359, 100, 25); label2->setText("from datarecord"); label2->setEnabled(false); label3 = new QLabel(myobjectDialog); label3->setGeometry(485, 424, 100, 25); label3->setText("to datarecord"); label3->setEnabled(false); label4 = new QLabel(myobjectDialog); label4->setGeometry(605, 382, 100, 25); label4->setEnabled(false); label5 = new QLabel(myobjectDialog); 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, 100, 25); radioButton1->setChecked(true); radioButton1->setEnabled(false); radioButton2 = new QRadioButton("selection", myobjectDialog); radioButton2->setGeometry(485, 324, 100, 25); radioButton2->setEnabled(false); spinBox1 = new QSpinBox(myobjectDialog); spinBox1->setGeometry(485, 384, 100, 25); spinBox1->setRange(1, 2147483647); spinBox1->setValue(1); spinBox1->setEnabled(false); spinBox2 = new QSpinBox(myobjectDialog); spinBox2->setGeometry(485, 449, 100, 25); spinBox2->setRange(1, 2147483647); 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 + 1); 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"); pushButton2 = new QPushButton(myobjectDialog); pushButton2->setGeometry(575, 528, 100, 25); pushButton2->setText("Close"); pushButton3 = new QPushButton(myobjectDialog); pushButton3->setGeometry(200, 528, 100, 25); pushButton3->setText("Reduce"); 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); 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))); edfhdr = NULL; inputfile = NULL; outputfile = NULL; file_num = -1; inputpath[0] = 0; myobjectDialog->exec(); } void UI_ReduceSignalsWindow::spinBox1changed(int value) { long long seconds, milliSec; int days; char scratchpad[256]; QObject::disconnect(spinBox2, SIGNAL(valueChanged(int)), this, SLOT(spinBox2changed(int))); spinBox2->setMinimum(value); QObject::connect(spinBox2, SIGNAL(valueChanged(int)), this, SLOT(spinBox2changed(int))); if(edfhdr == NULL) { return; } days = (int)((((value - 1) * edfhdr->long_data_record_duration) / TIME_DIMENSION) / 86400LL); seconds = ((value - 1) * edfhdr->long_data_record_duration) / TIME_DIMENSION; if(seconds < 0) { seconds = 0; } seconds %= 86400LL; milliSec = ((value - 1) * edfhdr->long_data_record_duration) % TIME_DIMENSION; milliSec /= 10000LL; if(days) { sprintf(scratchpad, "%id %i:%02i:%02i.%03i", days, (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60), (int)milliSec); } else { sprintf(scratchpad, "%i:%02i:%02i.%03i", (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60), (int)milliSec); } label4->setText(scratchpad); } void UI_ReduceSignalsWindow::spinBox2changed(int value) { long long seconds, milliSec; int days; char scratchpad[256]; QObject::disconnect(spinBox1, SIGNAL(valueChanged(int)), this, SLOT(spinBox1changed(int))); spinBox1->setMaximum(value); QObject::connect(spinBox1, SIGNAL(valueChanged(int)), this, SLOT(spinBox1changed(int))); if(edfhdr == NULL) { return; } days = (int)(((value * edfhdr->long_data_record_duration) / TIME_DIMENSION) / 86400LL); seconds = (value * edfhdr->long_data_record_duration) / TIME_DIMENSION; seconds %= 86400LL; milliSec = (value * edfhdr->long_data_record_duration) % TIME_DIMENSION; milliSec /= 10000LL; if(days) { sprintf(scratchpad, "%id %i:%02i:%02i.%03i", days, (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60), (int)milliSec); } else { sprintf(scratchpad, "%i:%02i:%02i.%03i", (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60), (int)milliSec); } label5->setText(scratchpad); } void UI_ReduceSignalsWindow::radioButton1Toggled(bool checked) { long long seconds, milliSec; int days; char scratchpad[256]; if(checked == true) { spinBox1->setEnabled(false); spinBox2->setEnabled(false); label2->setEnabled(false); label3->setEnabled(false); label4->setEnabled(false); label5->setEnabled(false); if(edfhdr == NULL) { return; } spinBox1->setValue(1); spinBox2->setMaximum(edfhdr->datarecords); spinBox2->setValue(edfhdr->datarecords); spinBox1->setMaximum(edfhdr->datarecords); days = (int)(((edfhdr->datarecords * edfhdr->long_data_record_duration) / TIME_DIMENSION) / 86400LL); seconds = (edfhdr->datarecords * edfhdr->long_data_record_duration) / TIME_DIMENSION; seconds %= 86400LL; milliSec = (edfhdr->datarecords * edfhdr->long_data_record_duration) % TIME_DIMENSION; milliSec /= 10000LL; if(days > 0) { label4->setText("0d 0:00:00.000"); sprintf(scratchpad, "%id %i:%02i:%02i.%03i", days, (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60), (int)milliSec); } else { label4->setText("0:00:00.000"); sprintf(scratchpad, "%i:%02i:%02i.%03i", (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60), (int)milliSec); } label5->setText(scratchpad); } } void UI_ReduceSignalsWindow::radioButton2Toggled(bool checked) { if(checked == true) { spinBox1->setEnabled(true); spinBox2->setEnabled(true); label2->setEnabled(true); label3->setEnabled(true); label4->setEnabled(true); label5->setEnabled(true); } } void UI_ReduceSignalsWindow::Select_all_signals() { int i; if(edfhdr==NULL) { return; } for(i=0; iedfsignals; i++) { if(!edfhdr->edfparam[i].annotation) { ((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->setCheckState(Qt::Checked); } } } void UI_ReduceSignalsWindow::Deselect_all_signals() { int i; if(edfhdr==NULL) { return; } for(i=0; iedfsignals; 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; iedfsignals; 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; long long seconds, milliSec; char txt_string[2048], str[256]; label1->clear(); label4->clear(); label5->clear(); SignalsTablewidget->setRowCount(0); inputfile = NULL; outputfile = NULL; inputpath[0] = 0; edfhdr = NULL; 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); label2->setEnabled(false); label3->setEnabled(false); label4->setEnabled(false); label5->setEnabled(false); UI_activeFileChooserWindow afchooser(&file_num, mainwindow); if(file_num < 0) { return; } edfhdr = mainwindow->edfheaderlist[file_num]; strcpy(inputpath, edfhdr->filename); inputfile = edfhdr->file_hdl; if(inputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for reading.", inputpath); QMessageBox messagewindow(QMessageBox::Critical, "Error", QString::fromLocal8Bit(txt_string)); messagewindow.exec(); inputpath[0] = 0; edfhdr = NULL; file_num = -1; return; } if(edfhdr->datarecords > 2147483647LL) { QMessageBox messagewindow(QMessageBox::Critical, "Failure", "This file contains more than 2147483647 datarecords.\n" "This tool can not handle more than 2147483647 datarecords."); messagewindow.exec(); inputfile = NULL; inputpath[0] = 0; edfhdr = NULL; file_num = -1; return; } /***************** load signalproperties ******************************/ label1->setText(inputpath); SignalsTablewidget->setRowCount(edfhdr->edfsignals); for(i=0; iedfsignals; 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); label4->setText("0:00:00.000"); days = (int)(((edfhdr->datarecords * edfhdr->long_data_record_duration) / TIME_DIMENSION) / 86400LL); seconds = (edfhdr->datarecords * edfhdr->long_data_record_duration) / TIME_DIMENSION; seconds %= 86400LL; milliSec = (edfhdr->datarecords * edfhdr->long_data_record_duration) % TIME_DIMENSION; milliSec /= 10000LL; if(days) { sprintf(txt_string, "%id %i:%02i:%02i.%03i", days, (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60), (int)milliSec); } else { sprintf(txt_string, "%i:%02i:%02i.%03i", (int)(seconds / 3600), (int)((seconds % 3600) / 60), (int)(seconds % 60), (int)milliSec); } label5->setText(txt_string); } void UI_ReduceSignalsWindow::StartConversion() { int i, j, k, n, new_edfsignals, datarecords=0, annot_smp_per_record, annot_recordsize, timestamp_digits=0, timestamp_decimals=0, annot_len, tallen=0, len, annot_cnt, annots_per_datrec=0, smplrt, tmp, val, progress_steps, datrecs_processed; char *readbuf=NULL, scratchpad[256]; long long new_starttime, time_diff, onset_diff, taltime, l_temp, endtime=0, l_tmp; struct date_time_struct dts; struct annotationblock *new_annot_list=NULL, *root_new_annot_list=NULL, *annot_list=NULL; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; QProgressDialog progress("Processing file...", "Abort", 0, 1); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); 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); label3->setEnabled(false); if(edfhdr==NULL) { return; } if(file_num < 0) { return; } new_edfsignals = 0; annot_smp_per_record = 0; annot_cnt = 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; iedfsignals; i++) { if(!edfhdr->edfparam[i].annotation) { if(((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->checkState()==Qt::Checked) { signalslist[new_edfsignals] = i; dividerlist[new_edfsignals] = ((QComboBox *)(SignalsTablewidget->cellWidget(i, 1)))->itemData(((QComboBox *)(SignalsTablewidget->cellWidget(i, 1)))->currentIndex()).toInt(); new_edfsignals++; } } } datarecords = spinBox2->value() - spinBox1->value() + 1; if(edfhdr->edfplus || edfhdr->bdfplus) { timestamp_decimals = get_tal_timestamp_decimal_cnt(edfhdr); if(timestamp_decimals < 0) { showpopupmessage("Error", "Internal error, get_tal_timestamp_decimal_cnt("); goto END_1; } timestamp_digits = get_tal_timestamp_digit_cnt(edfhdr); if(timestamp_digits < 0) { showpopupmessage("Error", "Internal error, get_tal_timestamp_digit_cnt("); goto END_1; } annot_list = mainwindow->annotationlist[file_num]; while(annot_list != NULL) { l_temp = annot_list->onset - time_diff; if((l_temp >= 0LL) && (l_temp <= endtime)) { annot_cnt++; edfplus_annotation_add_copy(&new_annot_list, annot_list); } annot_list = annot_list->next_annotation; } annot_list = new_annot_list; root_new_annot_list = new_annot_list; new_starttime = edfhdr->utc_starttime + ((time_diff + edfhdr->starttime_offset) / TIME_DIMENSION); onset_diff = (new_starttime - edfhdr->utc_starttime) * TIME_DIMENSION; while(annot_list != NULL) { annot_list->onset -= onset_diff; annot_list = annot_list->next_annotation; } edfplus_annotation_sort(&new_annot_list); annots_per_datrec = annot_cnt / datarecords; if(annot_cnt % datarecords) { annots_per_datrec++; } annot_len = get_max_annotation_strlen(&new_annot_list); if(!annot_cnt) { annots_per_datrec = 0; } annot_recordsize = (annot_len * annots_per_datrec) + timestamp_digits + timestamp_decimals + 4; if(timestamp_decimals) { annot_recordsize++; } if(edfhdr->edf) { annot_smp_per_record = annot_recordsize / 2; if(annot_recordsize % annot_smp_per_record) { annot_smp_per_record++; annot_recordsize = annot_smp_per_record * 2; } } else { annot_smp_per_record = annot_recordsize / 3; if(annot_recordsize % annot_smp_per_record) { annot_smp_per_record++; annot_recordsize = annot_smp_per_record * 3; } } } else { annot_smp_per_record = 0; annot_recordsize = 0; } readbuf = (char *)malloc(edfhdr->recordsize); if(readbuf==NULL) { showpopupmessage("Error", "Malloc error, (readbuf)."); goto END_2; } /////////////////////////////////////////////////////////////////// for(i=0; i 1) { for(j=0; jedf) { strcat(outputpath, "_reduced.edf"); strcpy(outputpath, QFileDialog::getSaveFileName(0, "Save file", QString::fromLocal8Bit(outputpath), "EDF files (*.edf *.EDF)").toLocal8Bit().data()); } else { strcat(outputpath, "_reduced.bdf"); strcpy(outputpath, QFileDialog::getSaveFileName(0, "Save file", QString::fromLocal8Bit(outputpath), "BDF files (*.bdf *.BDF)").toLocal8Bit().data()); } if(!strcmp(outputpath, "")) { goto END_3; } get_directory_from_path(recent_savedir, outputpath, MAX_PATH_LENGTH); if(mainwindow->file_is_opened(outputpath)) { showpopupmessage("Reduce signals", "Error, selected file is in use."); goto END_3; } outputfile = fopeno(outputpath, "wb"); if(outputfile==NULL) { showpopupmessage("Error", "Can not open outputfile for writing."); goto END_3; } new_starttime = edfhdr->utc_starttime + ((time_diff + edfhdr->starttime_offset) / TIME_DIMENSION); utc_to_date_time(new_starttime, &dts); rewind(inputfile); if(fread(scratchpad, 168, 1, inputfile)!=1) { showpopupmessage("Error", "Read error (1)."); goto END_4; } if(edfhdr->edfplus || edfhdr->bdfplus) { if(scratchpad[98] != 'X') { sprintf(scratchpad + 98, "%02i-%s-%04i", dts.day, dts.month_str, dts.year); scratchpad[109] = ' '; } } if(fwrite(scratchpad, 168, 1, outputfile)!=1) { showpopupmessage("Error", "Write error (1)."); goto END_4; } fprintf(outputfile, "%02i.%02i.%02i%02i.%02i.%02i", dts.day, dts.month, dts.year % 100, dts.hour, dts.minute, dts.second); if(edfhdr->edfplus || edfhdr->bdfplus) { fprintf(outputfile, "%-8i", new_edfsignals * 256 + 512); } else { fprintf(outputfile, "%-8i", new_edfsignals * 256 + 256); } if(edfhdr->edfplus) { fprintf(outputfile, "EDF+C"); for(i=0; i<39; i++) { fputc(' ', outputfile); } } if(edfhdr->bdfplus) { fprintf(outputfile, "BDF+C"); for(i=0; i<39; i++) { fputc(' ', outputfile); } } if((!edfhdr->edfplus) && (!edfhdr->bdfplus)) { for(i=0; i<44; i++) { fputc(' ', outputfile); } } fprintf(outputfile, "%-8i", datarecords); snprintf(scratchpad, 256, "%f", edfhdr->data_record_duration); convert_trailing_zeros_to_spaces(scratchpad); if(scratchpad[7]=='.') { scratchpad[7] = ' '; } scratchpad[8] = 0; fprintf(outputfile, "%s", scratchpad); if(edfhdr->edfplus || edfhdr->bdfplus) { fprintf(outputfile, "%-4i", new_edfsignals + 1); } else { fprintf(outputfile, "%-4i", new_edfsignals); } for(i=0; iedfparam[signalslist[i]].label); } if(edfhdr->edfplus) { fprintf(outputfile, "EDF Annotations "); } if(edfhdr->bdfplus) { fprintf(outputfile, "BDF Annotations "); } for(i=0; iedfparam[signalslist[i]].transducer); } if(edfhdr->edfplus || edfhdr->bdfplus) { for(i=0; i<80; i++) { fputc(' ', outputfile); } } for(i=0; iedfparam[signalslist[i]].physdimension); } if(edfhdr->edfplus || edfhdr->bdfplus) { for(i=0; i<8; i++) { fputc(' ', outputfile); } } for(i=0; iedfparam[signalslist[i]].phys_min); convert_trailing_zeros_to_spaces(scratchpad); if(scratchpad[7]=='.') { scratchpad[7] = ' '; } scratchpad[8] = 0; fprintf(outputfile, "%s", scratchpad); } if(edfhdr->edfplus || edfhdr->bdfplus) { fprintf(outputfile, "-1 "); } for(i=0; iedfparam[signalslist[i]].phys_max); convert_trailing_zeros_to_spaces(scratchpad); if(scratchpad[7]=='.') { scratchpad[7] = ' '; } scratchpad[8] = 0; fprintf(outputfile, "%s", scratchpad); } if(edfhdr->edfplus || edfhdr->bdfplus) { fprintf(outputfile, "1 "); } for(i=0; iedfparam[signalslist[i]].dig_min); } if(edfhdr->edfplus) { fprintf(outputfile, "-32768 "); } if(edfhdr->bdfplus) { fprintf(outputfile, "-8388608"); } for(i=0; iedfparam[signalslist[i]].dig_max); } if(edfhdr->edfplus) { fprintf(outputfile, "32767 "); } if(edfhdr->bdfplus) { fprintf(outputfile, "8388607 "); } for(i=0; iedfparam[signalslist[i]].prefilter); } if(edfhdr->edfplus || edfhdr->bdfplus) { for(i=0; i<80; i++) { fputc(' ', outputfile); } } for(i=0; iedfparam[signalslist[i]].smp_per_record / dividerlist[i]); } if(edfhdr->edfplus || edfhdr->bdfplus) { fprintf(outputfile, "%-8i", annot_smp_per_record); } for(i=0; i<(new_edfsignals * 32); i++) { fputc(' ', outputfile); } if(edfhdr->edfplus || edfhdr->bdfplus) { for(i=0; i<32; i++) { fputc(' ', outputfile); } } /////////////////////////////////////////////////////////////////// progress.setRange(0, datarecords); progress.setValue(0); progress_steps = datarecords / 100; if(progress_steps < 1) { 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_processedprocessEvents(); if(progress.wasCanceled() == true) { goto END_4; } } if(fread(readbuf, edfhdr->recordsize, 1, inputfile) != 1) { progress.reset(); showpopupmessage("Error", "Read error (2)."); goto END_4; } if(edfhdr->edf) { for(i=0; iedfparam[signalslist[i]].smp_per_record; for(j=0; jedfparam[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; jedfparam[signalslist[i]].buf_offset)) + (dividerlist[i] * j) + k); for(n=0; n> 8) & 0xff, outputfile)==EOF) { progress.reset(); showpopupmessage("Error", "Write error (4)."); goto END_4; } } } } } else { for(i=0; iedfparam[signalslist[i]].smp_per_record; for(j=0; jedfparam[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 { smplrt = edfhdr->edfparam[signalslist[i]].smp_per_record / dividerlist[i]; for(j=0; jedfparam[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> 8) & 0xff, outputfile); if(fputc((l_tmp >> 16) & 0xff, outputfile)==EOF) { progress.reset(); showpopupmessage("Error", "Write error (4)."); goto END_4; } } } } } if(edfhdr->edfplus || edfhdr->bdfplus) { switch(timestamp_decimals) { case 0 : tallen = fprintf(outputfile, "+%i", (int)(taltime / TIME_DIMENSION)); break; case 1 : tallen = fprintf(outputfile, "+%i.%01i", (int)(taltime / TIME_DIMENSION), (int)((taltime % TIME_DIMENSION) / 1000000LL)); break; case 2 : tallen = fprintf(outputfile, "+%i.%02i", (int)(taltime / TIME_DIMENSION), (int)((taltime % TIME_DIMENSION) / 100000LL)); break; case 3 : tallen = fprintf(outputfile, "+%i.%03i", (int)(taltime / TIME_DIMENSION), (int)((taltime % TIME_DIMENSION) / 10000LL)); break; case 4 : tallen = fprintf(outputfile, "+%i.%04i", (int)(taltime / TIME_DIMENSION), (int)((taltime % TIME_DIMENSION) / 1000LL)); break; case 5 : tallen = fprintf(outputfile, "+%i.%05i", (int)(taltime / TIME_DIMENSION), (int)((taltime % TIME_DIMENSION) / 100LL)); break; case 6 : tallen = fprintf(outputfile, "+%i.%06i", (int)(taltime / TIME_DIMENSION), (int)((taltime % TIME_DIMENSION) / 10LL)); break; case 7 : tallen = fprintf(outputfile, "+%i.%07i", (int)(taltime / TIME_DIMENSION), (int)(taltime % TIME_DIMENSION)); break; } fputc(20, outputfile); fputc(20, outputfile); fputc(0, outputfile); tallen += 3; if(new_annot_list != NULL) { for(i=0; ionset / TIME_DIMENSION), (int)(new_annot_list->onset % TIME_DIMENSION)); for(j=0; j<7; j++) { if(scratchpad[len - j - 1] != '0') { break; } } if(j) { len -= j; if(j == 7) { len--; } } if(fwrite(scratchpad, len, 1, outputfile) != 1) { progress.reset(); showpopupmessage("Error", "Write error (5)."); goto END_4; } tallen += len; if(new_annot_list->duration[0]!=0) { fputc(21, outputfile); tallen++; tallen += fprintf(outputfile, "%s", new_annot_list->duration); } fputc(20, outputfile); tallen++; tallen += fprintf(outputfile, "%s", new_annot_list->annotation); fputc(20, outputfile); fputc(0, outputfile); tallen += 2; new_annot_list = new_annot_list->next_annotation; } } } for(k=tallen; klong_data_record_duration; } } progress.reset(); showpopupmessage("Ready", "Done."); END_4: fclose(outputfile); outputfile = NULL; END_3: for(i=0; i 1) { for(j=0; jclear(); label4->clear(); label5->clear(); file_num = -1; edfhdr = NULL; edfplus_annotation_delete_list(&root_new_annot_list); root_new_annot_list = NULL; SignalsTablewidget->setRowCount(0); } void UI_ReduceSignalsWindow::showpopupmessage(const char *str1, const char *str2) { QMessageBox messagewindow(QMessageBox::NoIcon, str1, str2); messagewindow.exec(); } edfbrowser_157_source/PaxHeaders.7921/unisens2edf.h0000644000000000000000000000013212646460742017264 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/unisens2edf.h0000644000175000001440000000632112646460742017627 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_UNISENS2EDFFORM_H #define UI_UNISENS2EDFFORM_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "xml.h" #include "edflib.h" #include "utils.h" class UI_UNISENS2EDFwindow : public QObject { Q_OBJECT public: UI_UNISENS2EDFwindow(char *recent_dir=NULL, char *save_dir=NULL); private: QTextEdit *textEdit1; QPushButton *pushButton1, *pushButton2; QDialog *myobjectDialog; char *recent_opendir, *recent_savedir, binfilename[MAXFILES][MAX_PATH_LENGTH], evtfilename[MAXFILES][MAX_PATH_LENGTH], physdim[MAXFILES][9], signallabel[MAXSIGNALS][17], str_timestampStart[32], str_measurementId[128], csv_sep[MAXFILES], csv_dec_sep[MAXFILES]; int straightbinary[MAXFILES], big_endian[MAXFILES], samplesize[MAXFILES], datatype[MAXFILES], sf[MAXFILES], csv_enc[MAXFILES], nedval_enc[MAXFILES], nedval_smpl[MAXFILES], nedval_value[MAXFILES][MAXSIGNALS], nedval_value2[MAXFILES][MAXSIGNALS], sf_less_1, sf_inv[MAXFILES], sf_divider, digmax[MAXFILES], digmin[MAXFILES], adcres[MAXFILES], datablocks[MAXFILES], edf_signals[MAXFILES], total_edf_signals, edf_signal_start[MAXFILES], max_datablocks, file_cnt, trig_file_cnt, buf1_offset[MAXFILES], buf2_offset[MAXFILES], buf1_freadsize[MAXFILES], char_encoding, bdf, evt_sf[MAXFILES], total_annotations, starttime_fraction; long long adczero[MAXFILES], baseline[MAXFILES]; double physmax[MAXFILES], physmin[MAXFILES], lsbval[MAXFILES]; FILE *binfile[MAXFILES]; int get_signalparameters_from_BIN_attributes(struct xml_handle *, int); int get_signalparameters_from_EVT_attributes(struct xml_handle *, int); int get_events_from_csv_files(int, int, const char *); int count_events_from_csv_files(int, const char *, int *); private slots: void SelectFileButton(); }; #endif edfbrowser_157_source/PaxHeaders.7921/LICENSE0000644000000000000000000000013212646460742015673 xustar0030 mtime=1452958178.269246659 30 atime=1452958178.269246659 30 ctime=1452958178.269246659 edfbrowser_157_source/LICENSE0000644000175000001440000010451312646460742016240 0ustar00guvusers00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . edfbrowser_157_source/PaxHeaders.7921/filtercurve.h0000644000000000000000000000012712646460742017375 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/filtercurve.h0000644000175000001440000000441112646460742017732 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef FILTERCURVE_H #define FILTERCURVE_H #include #include #include #include class FilterCurve: public QWidget { Q_OBJECT public: FilterCurve(QWidget *parent=0); QSize sizeHint() const {return minimumSizeHint(); } QSize minimumSizeHint() const {return QSize(30,10); } void setSignalColor1(QColor); void setSignalColor2(QColor); void setTraceWidth(int); void setBackgroundColor(QColor); void setRasterColor(QColor); void setMarkerColor(QColor); void setH_RasterSize(int); void setV_RasterSize(int); void drawCurve(double *, int, double, double); void drawCurve(double *, int, double, double, double *, int, double, double, int mrkr1 = 0, int mrkr2 = 0); public slots: protected: void paintEvent(QPaintEvent *); private: QColor SignalColor1, SignalColor2, BackgroundColor, RasterColor, MarkerColor; double max_value1, min_value1, *buf1, max_value2, min_value2, *buf2; int bufsize1, bufsize2, h_rastersize, v_rastersize, drawcurve_before_raster, tracewidth, marker_1, marker_2; }; #endif edfbrowser_157_source/PaxHeaders.7921/ecg_filter.h0000644000000000000000000000013212646460742017142 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/ecg_filter.h0000644000175000001440000001140012646460742017477 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef ecg_filter_INCLUDED #define ecg_filter_INCLUDED #include #include #include struct ecg_filter_settings{ int avgfilter_50_size; double *avgfilter_50_buf; int avgfilter_50_idx; double avgfilter_50_mean; double *avgfilter_50_buf_bu; int avgfilter_50_idx_bu; double avgfilter_50_mean_bu; int avgfilter_35_size; double *avgfilter_35_buf; int avgfilter_35_idx; double avgfilter_35_mean; double *avgfilter_35_buf_bu; int avgfilter_35_idx_bu; double avgfilter_35_mean_bu; int avgfilter_25_size; double *avgfilter_25_buf; int avgfilter_25_idx; double avgfilter_25_mean; double *avgfilter_25_buf_bu; int avgfilter_25_idx_bu; double avgfilter_25_mean_bu; double *SV; int SV_sz; int SV_idx; double SV_bu[3]; int SV_idx_bu; int runin; int runin_bu; int M_startslope; int M_endslope; int smpl_n; double M[5]; int M_idx; double M_avg; double drain; double top; double sf; double *F; int F_size; int F_idx; int F_wd; double F_value; double F_sf_factor; int R[5]; int R_idx; int R_avg; double R_value; int R_startslope; int R_endslope; double bpm; double bitvalue; int M_startslope_bu; int M_endslope_bu; int smpl_n_bu; double M_bu[5]; int M_idx_bu; double M_avg_bu; double drain_bu; double top_bu; double *F_bu; int F_idx_bu; double F_value_bu; int R_bu[5]; int R_idx_bu; int R_avg_bu; double R_value_bu; int R_startslope_bu; int R_endslope_bu; double bpm_bu; int bu_filled; double *stat_buf; long long *stat_smpl_buf; int stat_buf_idx; int sample_cntr; double T_peak_avg; double T_peak_avg_bu; }; struct ecg_filter_settings * create_ecg_filter(double, double, int); double run_ecg_filter(double, struct ecg_filter_settings *); void free_ecg_filter(struct ecg_filter_settings *); void ecg_filter_save_buf(struct ecg_filter_settings *); void ecg_filter_restore_buf(struct ecg_filter_settings *); void reset_ecg_filter(struct ecg_filter_settings *); int ecg_filter_get_beat_cnt(struct ecg_filter_settings *); long long * ecg_filter_get_onset_beatlist(struct ecg_filter_settings *); double * ecg_filter_get_interval_beatlist(struct ecg_filter_settings *); #endif edfbrowser_157_source/PaxHeaders.7921/utils.c0000644000000000000000000000013212646460742016172 xustar0030 mtime=1452958178.243246747 30 atime=1452958178.243246747 30 ctime=1452958178.243246747 edfbrowser_157_source/utils.c0000644000175000001440000006465212646460742016550 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "utils.h" #define FLT_ROUNDS 1 /* removes extension including the dot */ void remove_extension_from_filename(char *str) { int i, len; len = strlen(str); if(len < 1) { return; } for(i=len-1; i>=0; i--) { if((str[i]=='/') || (str[i]=='\\')) { return; } if(str[i]=='.') { str[i] = 0; return; } } } /* size is size of destination, returns length of filename */ int get_filename_from_path(char *dest, const char *src, int size) { int i, len; if(size<1) { return(-1); } if(size<2) { dest[0] = 0; return(0); } len = strlen(src); if(len < 1) { dest[0] = 0; return(0); } for(i=len-1; i>=0; i--) { if((src[i]=='/') || (src[i]=='\\')) { break; } } i++; strncpy(dest, src + i, size); dest[size-1] = 0; return(strlen(dest)); } /* size is size of destination, returns length of directory */ /* last character of destination is not a slash! */ int get_directory_from_path(char *dest, const char *src, int size) { int i, len; if(size<1) { return(-1); } if(size<2) { dest[0] = 0; return(0); } len = strlen(src); if(len < 1) { dest[0] = 0; return(0); } for(i=len-1; i>=0; i--) { if((src[i]=='/') || (src[i]=='\\')) { break; } } strncpy(dest, src, size); if(i < size) { dest[i] = 0; } else { dest[size-1] = 0; } return(strlen(dest)); } void convert_trailing_zeros_to_spaces(char *str) { int i, j, len; len = strlen(str); for(i=0; i=0; j--) { if((str[j]!='.')&&(str[j]!='0')) { break; } if(str[j]=='.') { str[j] = ' '; break; } str[j] = ' '; } break; } } } void remove_trailing_spaces(char *str) { int i, len; len = strlen(str); for(i=(len-1); i>-1; i--) { if(str[i]!=' ') break; } str[i+1] = 0; } void remove_leading_spaces(char *str) { int i, diff, len; len = strlen(str); for(i=0; i '9')) { if(decimalzerofound) { if(str[i-decimalzerofound-1] == '.') { decimalzerofound++; } for(j=i; j<(len+1); j++) { str[j-decimalzerofound] = str[j]; } trailingzerofound = 1; break; } if(str[i] != '.') { numberfound = 0; dotfound = 0; decimalzerofound = 0; } } else { numberfound = 1; if(str[i] > '0') { decimalzerofound = 0; } } if((str[i] == '.') && numberfound) { dotfound = 1; } if((str[i] == '0') && dotfound) { decimalzerofound++; } } } if(decimalzerofound) { if(str[i-decimalzerofound-1] == '.') { decimalzerofound++; } for(j=i; j<(len+1); j++) { str[j-decimalzerofound] = str[j]; } } if(len > 1) { if(!((str[len - 2] < '0') || (str[i] > '9'))) { if(str[len - 1] == '.') { str[len - 1] = 0; } } } } void utf8_to_latin1(char *utf8_str) { int i, j, len; unsigned char *str; str = (unsigned char *)utf8_str; len = strlen(utf8_str); if(!len) { return; } j = 0; for(i=0; i 127) && (str[i] < 192))) { str[j++] = '.'; continue; } if(str[i] > 223) { str[j++] = 0; return; /* can only decode Latin-1 ! */ } if((str[i] & 224) == 192) /* found a two-byte sequence containing Latin-1, Greek, Cyrillic, Coptic, Armenian, Hebrew, etc. characters */ { if((i + 1) == len) { str[j++] = 0; return; } if((str[i] & 252) != 192) /* it's not a Latin-1 character */ { str[j++] = '.'; i++; continue; } if((str[i + 1] & 192) != 128) /* UTF-8 violation error */ { str[j++] = 0; return; } str[j] = str[i] << 6; str[j] += (str[i + 1] & 63); i++; j++; continue; } str[j++] = str[i]; } if(j126)&&(str[i]<160)) tmp_str[j] = '.'; if(str[i]>159) { if((len-j)<2) { tmp_str[j] = ' '; } else { tmp_str[j] = 192 + (str[i]>>6); j++; tmp_str[j] = 128 + (str[i]&63); } } j++; if(j>=len) break; } for(i=0; i31)&&(value<127)) { continue; } switch(value) { case 128 : str[i] = 'E'; break; case 130 : str[i] = ','; break; case 131 : str[i] = 'F'; break; case 132 : str[i] = '\"'; break; case 133 : str[i] = '.'; break; case 134 : str[i] = '+'; break; case 135 : str[i] = '+'; break; case 136 : str[i] = '^'; break; case 137 : str[i] = 'm'; break; case 138 : str[i] = 'S'; break; case 139 : str[i] = '<'; break; case 140 : str[i] = 'E'; break; case 142 : str[i] = 'Z'; break; case 145 : str[i] = '`'; break; case 146 : str[i] = '\''; break; case 147 : str[i] = '\"'; break; case 148 : str[i] = '\"'; break; case 149 : str[i] = '.'; break; case 150 : str[i] = '-'; break; case 151 : str[i] = '-'; break; case 152 : str[i] = '~'; break; case 154 : str[i] = 's'; break; case 155 : str[i] = '>'; break; case 156 : str[i] = 'e'; break; case 158 : str[i] = 'z'; break; case 159 : str[i] = 'Y'; break; case 171 : str[i] = '<'; break; case 180 : str[i] = '\''; break; case 181 : str[i] = 'u'; break; case 187 : str[i] = '>'; break; case 191 : str[i] = '\?'; break; case 192 : str[i] = 'A'; break; case 193 : str[i] = 'A'; break; case 194 : str[i] = 'A'; break; case 195 : str[i] = 'A'; break; case 196 : str[i] = 'A'; break; case 197 : str[i] = 'A'; break; case 198 : str[i] = 'E'; break; case 199 : str[i] = 'C'; break; case 200 : str[i] = 'E'; break; case 201 : str[i] = 'E'; break; case 202 : str[i] = 'E'; break; case 203 : str[i] = 'E'; break; case 204 : str[i] = 'I'; break; case 205 : str[i] = 'I'; break; case 206 : str[i] = 'I'; break; case 207 : str[i] = 'I'; break; case 208 : str[i] = 'D'; break; case 209 : str[i] = 'N'; break; case 210 : str[i] = 'O'; break; case 211 : str[i] = 'O'; break; case 212 : str[i] = 'O'; break; case 213 : str[i] = 'O'; break; case 214 : str[i] = 'O'; break; case 215 : str[i] = 'x'; break; case 216 : str[i] = 'O'; break; case 217 : str[i] = 'U'; break; case 218 : str[i] = 'U'; break; case 219 : str[i] = 'U'; break; case 220 : str[i] = 'U'; break; case 221 : str[i] = 'Y'; break; case 222 : str[i] = 'I'; break; case 223 : str[i] = 's'; break; case 224 : str[i] = 'a'; break; case 225 : str[i] = 'a'; break; case 226 : str[i] = 'a'; break; case 227 : str[i] = 'a'; break; case 228 : str[i] = 'a'; break; case 229 : str[i] = 'a'; break; case 230 : str[i] = 'e'; break; case 231 : str[i] = 'c'; break; case 232 : str[i] = 'e'; break; case 233 : str[i] = 'e'; break; case 234 : str[i] = 'e'; break; case 235 : str[i] = 'e'; break; case 236 : str[i] = 'i'; break; case 237 : str[i] = 'i'; break; case 238 : str[i] = 'i'; break; case 239 : str[i] = 'i'; break; case 240 : str[i] = 'd'; break; case 241 : str[i] = 'n'; break; case 242 : str[i] = 'o'; break; case 243 : str[i] = 'o'; break; case 244 : str[i] = 'o'; break; case 245 : str[i] = 'o'; break; case 246 : str[i] = 'o'; break; case 247 : str[i] = '-'; break; case 248 : str[i] = '0'; break; case 249 : str[i] = 'u'; break; case 250 : str[i] = 'u'; break; case 251 : str[i] = 'u'; break; case 252 : str[i] = 'u'; break; case 253 : str[i] = 'y'; break; case 254 : str[i] = 't'; break; case 255 : str[i] = 'y'; break; default : str[i] = ' '; break; } } } int antoi(const char *input_str, int len) { char str[1024]; strncpy(str, input_str, len); str[len] = 0; return(atoi_nonlocalized(str)); } /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */ /* if sign is zero, only negative numbers will have the sign '-' character */ /* if sign is one, the sign '+' or '-' character will always be printed */ /* returns the amount of characters printed */ int fprint_int_number_nonlocalized(FILE *file, int q, int minimum, int sign) { int flag=0, z, i, j=0, base = 1000000000; if(minimum < 0) { minimum = 0; } if(minimum > 9) { flag = 1; } if(q < 0) { fputc('-', file); j++; q = -q; } else { if(sign) { fputc('+', file); j++; } } for(i=10; i; i--) { if(minimum == i) { flag = 1; } z = q / base; q %= base; if(z || flag) { fputc('0' + z, file); j++; flag = 1; } base /= 10; } if(!flag) { fputc('0', file); j++; } return(j); } /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */ /* if sign is zero, only negative numbers will have the sign '-' character */ /* if sign is one, the sign '+' or '-' character will always be printed */ /* returns the amount of characters printed */ int fprint_ll_number_nonlocalized(FILE *file, long long q, int minimum, int sign) { int flag=0, z, i, j=0; long long base = 1000000000000000000LL; if(minimum < 0) { minimum = 0; } if(minimum > 18) { flag = 1; } if(q < 0LL) { fputc('-', file); j++; q = -q; } else { if(sign) { fputc('+', file); j++; } } for(i=19; i; i--) { if(minimum == i) { flag = 1; } z = q / base; q %= base; if(z || flag) { fputc('0' + z, file); j++; flag = 1; } base /= 10LL; } if(!flag) { fputc('0', file); j++; } return(j); } /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */ /* if sign is zero, only negative numbers will have the sign '-' character */ /* if sign is one, the sign '+' or '-' character will always be printed */ /* returns the amount of characters printed */ int sprint_int_number_nonlocalized(char *str, int q, int minimum, int sign) { int flag=0, z, i, j=0, base = 1000000000; if(minimum < 0) { minimum = 0; } if(minimum > 9) { flag = 1; } if(q < 0) { str[j++] = '-'; q = -q; } else { if(sign) { str[j++] = '+'; } } for(i=10; i; i--) { if(minimum == i) { flag = 1; } z = q / base; q %= base; if(z || flag) { str[j++] = '0' + z; flag = 1; } base /= 10; } if(!flag) { str[j++] = '0'; } str[j] = 0; return(j); } /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */ /* if sign is zero, only negative numbers will have the sign '-' character */ /* if sign is one, the sign '+' or '-' character will always be printed */ /* returns the amount of characters printed */ int sprint_ll_number_nonlocalized(char *str, long long q, int minimum, int sign) { int flag=0, z, i, j=0; long long base = 1000000000000000000LL; if(minimum < 0) { minimum = 0; } if(minimum > 18) { flag = 1; } if(q < 0LL) { str[j++] = '-'; q = -q; } else { if(sign) { str[j++] = '+'; } } for(i=19; i; i--) { if(minimum == i) { flag = 1; } z = q / base; q %= base; if(z || flag) { str[j++] = '0' + z; flag = 1; } base /= 10LL; } if(!flag) { str[j++] = '0'; } str[j] = 0; return(j); } int sprint_number_nonlocalized(char *str, double nr) { int flag=0, z, i, j=0, q, base = 1000000000; double var; q = (int)nr; var = nr - q; if(nr < 0.0) { str[j++] = '-'; if(q < 0) { q = -q; } } for(i=10; i; i--) { z = q / base; q %= base; if(z || flag) { str[j++] = '0' + z; flag = 1; } base /= 10; } if(!flag) { str[j++] = '0'; } base = 100000000; var *= (base * 10); q = (int)var; if(q < 0) { q = -q; } if(!q) { str[j] = 0; return(j); } str[j++] = '.'; for(i=9; i; i--) { z = q / base; q %= base; str[j++] = '0' + z; base /= 10; } str[j] = 0; j--; for(; j>0; j--) { if(str[j] == '0') { str[j] = 0; } else { j++; break; } } return(j); } double atof_nonlocalized(const char *str) { int i=0, dot_pos=-1, decimals=0, sign=1; double value, value2=0.0; value = atoi_nonlocalized(str); while(str[i] == ' ') { i++; } if((str[i] == '+') || (str[i] == '-')) { if(str[i] == '-') { sign = -1; } i++; } for(; ; i++) { if(str[i] == 0) { break; } if(((str[i] < '0') || (str[i] > '9')) && (str[i] != '.')) { break; } if(dot_pos >= 0) { if((str[i] >= '0') && (str[i] <= '9')) { decimals++; } else { break; } } if(str[i] == '.') { if(dot_pos < 0) { dot_pos = i; } } } if(decimals) { value2 = atoi_nonlocalized(str + dot_pos + 1) * sign; i = 1; while(decimals--) { i *= 10; } value2 /= i; } return(value + value2); } int atoi_nonlocalized(const char *str) { int i=0, value=0, sign=1; while(str[i] == ' ') { i++; } if((str[i] == '+') || (str[i] == '-')) { if(str[i] == '-') { sign = -1; } i++; } for( ; ; i++) { if(str[i] == 0) { break; } if((str[i] < '0') || (str[i] > '9')) { break; } value *= 10; value += (str[i] - '0'); } return(value * sign); } long long atoll_x(const char *str, int dimension) { int i, radix, negative=0; long long value=0LL; while(*str==' ') { str++; } if(*str=='-') { negative = 1; str++; } else { if(*str=='+') { str++; } } for(i=0; ; i++) { if(str[i]=='.') { str += (i + 1); break; } if((str[i]<'0') || (str[i]>'9')) { if(negative) { return(value * dimension * -1LL); } else { return(value * dimension); } } value *= 10LL; value += str[i] - '0'; } radix = 1; for(i=0; radix'9')) { break; } radix *= 10; value *= 10LL; value += str[i] - '0'; } if(negative) { return(value * (dimension / radix) * -1LL); } else { return(value * (dimension / radix)); } } int is_integer_number(char *str) { int i=0, l, hasspace = 0, hassign=0, digit=0; l = strlen(str); if(!l) return(1); if((str[0]=='+')||(str[0]=='-')) { hassign++; i++; } for(; i57)) { return(1); } else { if(hasspace) { return(1); } digit++; } } } if(digit) return(0); else return(1); } int is_number(char *str) { int i=0, l, hasspace = 0, hassign=0, digit=0, hasdot=0, hasexp=0; l = strlen(str); if(!l) return(1); if((str[0]=='+')||(str[0]=='-')) { hassign++; i++; } for(; i57))&&str[i]!='.') { return(1); } else { if(hasspace) { return(1); } if(str[i]=='.') { if(hasdot) return(1); hasdot++; } else { digit++; } } } } if(hasexp) { if(++i==l) { return(1); } if((str[i]=='+')||(str[i]=='-')) { hassign++; i++; } for(; i57)) { return(1); } else { if(hasspace) { return(1); } digit++; } } } } if(digit) return(0); else return(1); } void strntolower(char *s, int n) { int i; for(i=0; i 1000) value /=10; while(value < 100) value *=10; if(value > 670) { return(10); } else if(value > 300) { return(50); } else if(value > 135) { return(20); } else { return(10); } return(10); } void hextoascii(char *str) { int i, len; char scratchpad[4]; len = strlen(str) / 2; for(i=0; i 9.999) { val /= 10; exp++; } val = nearbyint(val); if(val > 4.999) { ltmp = 10; if(ratio != NULL) { *ratio = 2; } } else if(val > 1.999) { ltmp = 5; if(ratio != NULL) { *ratio = 2.5; } } else { ltmp = 2; if(ratio != NULL) { *ratio = 2; } } for(i=0; iexp; i--) { ltmp /= 10; } if((ltmp < 1e-13) && (ltmp > -1e-13)) { return 0; } return ltmp; } double round_down_step125(double val, double *ratio) { int i, exp=0; double ltmp; while(val < 0.999) { val *= 10; exp--; } while(val > 9.999) { val /= 10; exp++; } val = nearbyint(val); if(val < 1.001) { ltmp = 0.5; if(ratio != NULL) { *ratio = 2; } } else if(val < 2.001) { ltmp = 1; if(ratio != NULL) { *ratio = 2; } } else if(val < 5.001) { ltmp = 2; if(ratio != NULL) { *ratio = 2.5; } } else { ltmp = 5; if(ratio != NULL) { *ratio = 2; } } for(i=0; iexp; i--) { ltmp /= 10; } if((ltmp < 1e-13) && (ltmp > -1e-13)) { return 0; } return ltmp; } int convert_to_metric_suffix(char *buf, double value, int decimals) { double ltmp; char suffix=' '; if(value < 0) { ltmp = value * -1; } else { ltmp = value; } if(ltmp > 0.999999e12 && ltmp < 0.999999e15) { ltmp = ltmp / 1e12; suffix = 'T'; } else if(ltmp > 0.999999e9) { ltmp = ltmp / 1e9; suffix = 'G'; } else if(ltmp > 0.999999e6) { ltmp = ltmp / 1e6; suffix = 'M'; } else if(ltmp > 0.999999e3) { ltmp /= 1e3; suffix = 'K'; } else if(ltmp > 0.999999e-3 && ltmp < 0.999999) { ltmp *= 1e3; suffix = 'm'; } else if( ltmp > 0.999999e-6 && ltmp < 0.999999e-3) { ltmp *= 1e6; suffix = 'u'; } else if(ltmp > 0.999999e-9 && ltmp < 0.999999e-6) { ltmp *= 1e9; suffix = 'n'; } else if(ltmp > 0.999999e-12 && ltmp < 0.999999e-9) { ltmp *= 1e12; suffix = 'p'; } if(value >= 0) { switch(decimals) { case 0: return sprintf(buf, "%.0f%c", ltmp, suffix); break; case 1: return sprintf(buf, "%.1f%c", ltmp, suffix); break; case 2: return sprintf(buf, "%.2f%c", ltmp, suffix); break; case 3: return sprintf(buf, "%.3f%c", ltmp, suffix); break; case 4: return sprintf(buf, "%.4f%c", ltmp, suffix); break; case 5: return sprintf(buf, "%.5f%c", ltmp, suffix); break; case 6: return sprintf(buf, "%.6f%c", ltmp, suffix); break; default: return sprintf(buf, "%.3f%c", ltmp, suffix); break; } } if(value < 0) { switch(decimals) { case 0: return sprintf(buf, "%.0f%c", ltmp * -1, suffix); break; case 1: return sprintf(buf, "%.1f%c", ltmp * -1, suffix); break; case 2: return sprintf(buf, "%.2f%c", ltmp * -1, suffix); break; default: return sprintf(buf, "%.3f%c", ltmp * -1, suffix); break; } } strcpy(buf, "0"); return 1; } int strtoipaddr(unsigned int *dest, const char *src) { int i, err=1; unsigned int val; char *ptr, str[64]; if(strlen(src) < 7) { return -1; } strncpy(str, src, 64); str[63] = 0; ptr = strtok(str, "."); if(ptr != NULL) { val = atoi(ptr) << 24; for(i=0; i<3; i++) { ptr = strtok(NULL, "."); if(ptr == NULL) { break; } val += atoi(ptr) << (16 - (i * 8)); } err = 0; } if(err) { return -1; } *dest = val; return 0; } int dblcmp(double val1, double val2) { long double diff = (long double)val1 - (long double)val2; if(diff > 1e-13) { return 1; } else if(-diff > 1e-13) { return -1; } else { return 0; } } edfbrowser_157_source/PaxHeaders.7921/header_editor.h0000644000000000000000000000012712646460742017641 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/header_editor.h0000644000175000001440000000602012646460742020174 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_HEADEREDITORFORM_H #define UI_HEADEREDITORFORM_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "utils.h" class UI_Mainwindow; class UI_headerEditorWindow : public QDialog { Q_OBJECT public: UI_headerEditorWindow(QWidget *parent); UI_Mainwindow *mainwindow; private: QTabWidget *tabholder; QWidget *tab1, *tab2; QTableWidget *signallist; QLabel *label1, *label2, *label3, *label4, *label5, *label6, *label7, *label8, *label9, *label11, *label12, *fileNameLabel, *charsleft1Label, *charsleft2Label, *startTimeDateLabel; QLineEdit *lineEdit1, *lineEdit2, *lineEdit3, *lineEdit4, *lineEdit5, *lineEdit6, *lineEdit7, *lineEdit8, *lineEdit9; QComboBox *comboBox1; QCheckBox *checkBox1; QDateEdit *dateEdit1; QPushButton *pushButton1, *pushButton2, *pushButton3; QDateTimeEdit *startTimeDate; int edfplus, bdfplus, edf, bdf, edfsignals, has_startdate, recordsize, datrecs; char path[MAX_PATH_LENGTH], *hdr; FILE *file; private slots: void open_file(); void save_hdr(); void read_header(); void closeEvent(QCloseEvent *); void calculate_chars_left_name(const QString &); void calculate_chars_left_recording(const QString &); }; #endif edfbrowser_157_source/PaxHeaders.7921/read_write_settings.cpp0000644000000000000000000000012712646460742021443 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/read_write_settings.cpp0000644000175000001440000014312612646460742022007 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "mainwindow.h" void UI_Mainwindow::get_rgbcolor_settings(struct xml_handle *xml_hdl, const char *id, int cnt, QColor *rgb_color) { char result[XML_STRBUFLEN]; QColor tmp_color; if(xml_goto_nth_element_inside(xml_hdl, id, cnt)) { return; } if(xml_goto_nth_element_inside(xml_hdl, "red", 0)) { return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { return; } tmp_color.setRed(atoi(result)); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "green", 0)) { return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { return; } tmp_color.setGreen(atoi(result)); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "blue", 0)) { return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { return; } tmp_color.setBlue(atoi(result)); *rgb_color = tmp_color; xml_go_up(xml_hdl); xml_go_up(xml_hdl); } void UI_Mainwindow::read_color_settings() { char cfg_path[MAX_PATH_LENGTH], result[XML_STRBUFLEN]; struct xml_handle *xml_hdl; cfg_path[0] = 0; #ifdef Q_OS_WIN32 strcpy(cfg_path, specialFolder(CSIDL_APPDATA).toLocal8Bit().data()); strcat(cfg_path, "\\"); strcat(cfg_path, PROGRAM_NAME); strcat(cfg_path, "\\settings.xml"); #else strcpy(cfg_path, getenv("HOME")); strcat(cfg_path, "/."); strcat(cfg_path, PROGRAM_NAME); strcat(cfg_path, "/settings.xml"); #endif xml_hdl = xml_get_handle(cfg_path); if(!xml_hdl) { return; } if(strcmp(xml_hdl->elementname[xml_hdl->level], "config")) { xml_close(xml_hdl); return; } if(xml_goto_nth_element_inside(xml_hdl, "UI", 0)) { xml_close(xml_hdl); return; } if(xml_goto_nth_element_inside(xml_hdl, "colors", 0)) { xml_close(xml_hdl); return; } get_rgbcolor_settings(xml_hdl, "backgroundcolor", 0, &maincurve->backgroundcolor); get_rgbcolor_settings(xml_hdl, "small_ruler_color", 0, &maincurve->small_ruler_color); get_rgbcolor_settings(xml_hdl, "big_ruler_color", 0, &maincurve->big_ruler_color); get_rgbcolor_settings(xml_hdl, "mouse_rect_color", 0, &maincurve->mouse_rect_color); get_rgbcolor_settings(xml_hdl, "text_color", 0, &maincurve->text_color); get_rgbcolor_settings(xml_hdl, "baseline_color", 0, &maincurve->baseline_color); get_rgbcolor_settings(xml_hdl, "annot_marker_color", 0, &maincurve->annot_marker_color); if(xml_goto_nth_element_inside(xml_hdl, "signal_color", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } maincurve->signal_color = atoi(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "floating_ruler_color", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } maincurve->floating_ruler_color = atoi(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "blackwhite_printing", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } maincurve->blackwhite_printing = atoi(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "show_annot_markers", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } show_annot_markers = atoi(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "show_baselines", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } show_baselines = atoi(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "crosshair_1_color", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } maincurve->crosshair_1.color = atoi(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "crosshair_2_color", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } maincurve->crosshair_2.color = atoi(result); xml_close(xml_hdl); } void UI_Mainwindow::read_recent_file_settings() { int i; char cfg_path[MAX_PATH_LENGTH], result[XML_STRBUFLEN]; struct xml_handle *xml_hdl; cfg_path[0] = 0; #ifdef Q_OS_WIN32 strcpy(cfg_path, specialFolder(CSIDL_APPDATA).toLocal8Bit().data()); strcat(cfg_path, "\\"); strcat(cfg_path, PROGRAM_NAME); strcat(cfg_path, "\\settings.xml"); #else strcpy(cfg_path, getenv("HOME")); strcat(cfg_path, "/."); strcat(cfg_path, PROGRAM_NAME); strcat(cfg_path, "/settings.xml"); #endif xml_hdl = xml_get_handle(cfg_path); if(xml_hdl==NULL) { return; } if(strcmp(xml_hdl->elementname[xml_hdl->level], "config")) { xml_close(xml_hdl); return; } if(xml_goto_nth_element_inside(xml_hdl, "UI", 0)) { xml_close(xml_hdl); return; } if(!(xml_goto_nth_element_inside(xml_hdl, "recent_montagedir", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } strncpy(recent_montagedir, result, MAX_PATH_LENGTH); recent_montagedir[MAX_PATH_LENGTH - 1] = 0; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "recent_savedir", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } strncpy(recent_savedir, result, MAX_PATH_LENGTH); recent_savedir[MAX_PATH_LENGTH - 1] = 0; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "recent_opendir", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } strncpy(recent_opendir, result, MAX_PATH_LENGTH); recent_opendir[MAX_PATH_LENGTH - 1] = 0; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "recent_colordir", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } strncpy(recent_colordir, result, MAX_PATH_LENGTH); recent_opendir[MAX_PATH_LENGTH - 1] = 0; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "recent_file", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } if(result[0] != 0) { strncpy(&recent_file_path[0][0], result, MAX_PATH_LENGTH); recent_file_path[0][MAX_PATH_LENGTH - 1] = 0; recent_filesmenu->addAction(QString::fromLocal8Bit(&recent_file_path[0][0])); for(i=1; iaddAction(QString::fromLocal8Bit(&recent_file_path[i][0])); } } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "recent_file_mtg", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } strncpy(&recent_file_mtg_path[0][0], result, MAX_PATH_LENGTH); recent_file_mtg_path[0][MAX_PATH_LENGTH - 1] = 0; for(i=1; ielementname[xml_hdl->level], "config")) { xml_close(xml_hdl); return; } if(!xml_goto_nth_element_inside(xml_hdl, "cfg_app_version", 0)) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } strncpy(cfg_app_version, result, 16); cfg_app_version[16] = 0; xml_go_up(xml_hdl); } if(xml_goto_nth_element_inside(xml_hdl, "UI", 0)) { xml_close(xml_hdl); return; } if(xml_goto_nth_element_inside(xml_hdl, "pixelsizefactor", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } pixelsizefactor = atof(result); if(pixelsizefactor < 0.00001) { pixelsizefactor = 0.0294382; } xml_go_up(xml_hdl); if(!(xml_goto_nth_element_inside(xml_hdl, "auto_dpi", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } auto_dpi = atoi(result); if((auto_dpi < 0) || (auto_dpi > 1)) { auto_dpi = 1; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "x_pixelsizefactor", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } x_pixelsizefactor = atof(result); if(x_pixelsizefactor < 0.00001) { x_pixelsizefactor = 0.0294382; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "clip_to_pane", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } clip_to_pane = atoi(result); if((clip_to_pane < 0) || (clip_to_pane > 1)) { clip_to_pane = 0; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "auto_reload_mtg", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } auto_reload_mtg = atoi(result); if((auto_reload_mtg < 0) || (auto_reload_mtg > 1)) { auto_reload_mtg = 1; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "read_biosemi_status_signal", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } read_biosemi_status_signal = atoi(result); if((read_biosemi_status_signal < 0) || (read_biosemi_status_signal > 1)) { read_biosemi_status_signal = 1; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "read_nk_trigger_signal", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } read_nk_trigger_signal = atoi(result); if((read_nk_trigger_signal < 0) || (read_nk_trigger_signal > 1)) { read_nk_trigger_signal = 1; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "maxfilesize_to_readin_annotations", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } maxfilesize_to_readin_annotations = atoll(result); if((maxfilesize_to_readin_annotations < 104857600LL) || (maxfilesize_to_readin_annotations > 10485760000LL)) { maxfilesize_to_readin_annotations = 10485760000LL; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "use_threads", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } use_threads = atoi(result); if((use_threads < 0) || (use_threads > 1)) { use_threads = 1; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "spectrummarkerblock", 0))) { if(xml_goto_nth_element_inside(xml_hdl, "items", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } if((atoi(result) > MAXSPECTRUMMARKERS) || (atoi(result) < 0)) { xml_close(xml_hdl); return; } spectrum_colorbar->items = atoi(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "method", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } if((atoi(result) > 2) || (atoi(result) < 0)) { xml_close(xml_hdl); return; } spectrum_colorbar->method = atoi(result); xml_go_up(xml_hdl); if(!xml_goto_nth_element_inside(xml_hdl, "auto_adjust", 0)) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } spectrum_colorbar->auto_adjust = atoi(result); if((spectrum_colorbar->auto_adjust > 1) || (spectrum_colorbar->auto_adjust < 0)) { spectrum_colorbar->auto_adjust = 1; } xml_go_up(xml_hdl); } if(!xml_goto_nth_element_inside(xml_hdl, "max_colorbar_value", 0)) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } spectrum_colorbar->max_colorbar_value = atof(result); if((spectrum_colorbar->max_colorbar_value > 100000.0) || (spectrum_colorbar->max_colorbar_value < 0.0001)) { spectrum_colorbar->max_colorbar_value = 1.0; } xml_go_up(xml_hdl); } if(xml_goto_nth_element_inside(xml_hdl, "frequency", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } if((atof(result) > 1000000.0) || (atof(result) < 0.00001)) { xml_close(xml_hdl); return; } spectrum_colorbar->freq[0] = atof(result); for(i=1; i < spectrum_colorbar->items; i++) { if(xml_goto_next_element_with_same_name(xml_hdl)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } if(i < spectrum_colorbar->items) { if((atof(result) > 1000000.0) || (atof(result) <= spectrum_colorbar->freq[i-1])) { xml_close(xml_hdl); return; } } spectrum_colorbar->freq[i] = atof(result); } xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "color", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } if((atoi(result) > 18) || (atoi(result) < 2)) { xml_close(xml_hdl); return; } spectrum_colorbar->color[0] = atoi(result); for(i=1; i < spectrum_colorbar->items; i++) { if(xml_goto_next_element_with_same_name(xml_hdl)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } if((atoi(result) > 18) || (atoi(result) < 2)) { xml_close(xml_hdl); return; } spectrum_colorbar->color[i] = atoi(result); } xml_go_up(xml_hdl); if(!(xml_goto_nth_element_inside(xml_hdl, "label", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } strncpy(spectrum_colorbar->label[0], result, 16); spectrum_colorbar->label[0][16] = 0; for(i=1; i < spectrum_colorbar->items; i++) { if(xml_goto_next_element_with_same_name(xml_hdl)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } strncpy(spectrum_colorbar->label[i], result, 16); spectrum_colorbar->label[i][16] = 0; } xml_go_up(xml_hdl); } } xml_go_up(xml_hdl); if(!(xml_goto_nth_element_inside(xml_hdl, "maxdftblocksize", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } maxdftblocksize = atoi(result); if(maxdftblocksize > (32768 * 512)) { maxdftblocksize = 32768 * 512; } if(maxdftblocksize < 10) { maxdftblocksize = 1000; } } xml_go_up(xml_hdl); if(!(xml_goto_nth_element_inside(xml_hdl, "annotations_import_var", 0))) { if(!(xml_goto_nth_element_inside(xml_hdl, "format", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } import_annotations_var->format = atoi(result); if((import_annotations_var->format < 0) || (import_annotations_var->format > 3)) { import_annotations_var->format = 1; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "onsettimeformat", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } import_annotations_var->onsettimeformat = atoi(result); xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "onsetcolumn", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } import_annotations_var->onsetcolumn = atoi(result); xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "descriptioncolumn", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } import_annotations_var->descriptioncolumn = atoi(result); xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "useduration", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } import_annotations_var->useduration = atoi(result); if(import_annotations_var->useduration != 1) { import_annotations_var->useduration = 0; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "durationcolumn", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } import_annotations_var->durationcolumn = atoi(result); if(import_annotations_var->durationcolumn < 0) { import_annotations_var->durationcolumn = 0; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "datastartline", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } import_annotations_var->datastartline = atoi(result); xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "separator", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } strncpy(import_annotations_var->separator, result, 3); import_annotations_var->separator[3] = 0; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "dceventbittime", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } import_annotations_var->dceventbittime = atoi(result); xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "triggerlevel", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } import_annotations_var->triggerlevel = atof(result); xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "manualdescription", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } import_annotations_var->manualdescription = atoi(result); if((import_annotations_var->manualdescription < 0) || (import_annotations_var->manualdescription > 1)) { import_annotations_var->manualdescription = 0; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "description", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } strncpy(import_annotations_var->description, result, 20); import_annotations_var->description[20] = 0; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "ignoreconsecutive", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } import_annotations_var->ignoreconsecutive = atoi(result); if(import_annotations_var->ignoreconsecutive != 1) { import_annotations_var->ignoreconsecutive = 0; } xml_go_up(xml_hdl); } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "annotations_export_var", 0))) { if(!(xml_goto_nth_element_inside(xml_hdl, "separator", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } export_annotations_var->separator = atoi(result); xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "format", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } export_annotations_var->format = atoi(result); xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "duration", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } export_annotations_var->duration = atoi(result); xml_go_up(xml_hdl); } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "live_stream_update_interval", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } live_stream_update_interval = atoi(result); if((live_stream_update_interval < 100) || (live_stream_update_interval > 3000)) { live_stream_update_interval = 500; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "powerlinefreq", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } powerlinefreq = atoi(result); if((powerlinefreq != 50) && (powerlinefreq != 60)) { powerlinefreq = 50; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "mousewheelsens", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } mousewheelsens = atoi(result); if((mousewheelsens < 0) || (mousewheelsens > 100)) { mousewheelsens = 10; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "average_period", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } average_period = atof(result); xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "average_ratio", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } average_ratio = atoi(result); if((average_ratio < 0) || (average_ratio > 2)) { average_ratio = 0; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "average_upsidedown", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } if(atoi(result) == 1) { average_upsidedown = 1; } else { average_upsidedown = 0; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "average_bw", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } if(atoi(result) == 1) { average_bw = 1; } else { average_bw = 0; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "spectrum_bw", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } if(atoi(result) == 1) { spectrum_bw = 1; } else { spectrum_bw = 0; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "spectrum_sqrt", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } if(atoi(result) == 1) { spectrum_sqrt = 1; } else { spectrum_sqrt = 0; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "spectrum_vlog", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } if(atoi(result) == 1) { spectrum_vlog = 1; } else { spectrum_vlog = 0; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "spectrumdock_sqrt", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } if(atoi(result) == 1) { spectrumdock_sqrt = 1; } else { spectrumdock_sqrt = 0; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "spectrumdock_vlog", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } if(atoi(result) == 1) { spectrumdock_vlog = 1; } else { spectrumdock_vlog = 0; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "z_score_var.zscore_page_len", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } z_score_var.zscore_page_len = atoi(result); if((z_score_var.zscore_page_len < 10) || (z_score_var.zscore_page_len > 60)) { z_score_var.zscore_page_len = 30; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "z_score_var.z_threshold", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } z_score_var.z_threshold = atof(result); if((z_score_var.z_threshold < -0.5) || (z_score_var.z_threshold > 0.5)) { z_score_var.z_threshold = 0.0; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "z_score_var.crossoverfreq", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } z_score_var.crossoverfreq = atof(result); if((z_score_var.crossoverfreq < 5.0) || (z_score_var.crossoverfreq > 9.5)) { z_score_var.crossoverfreq = 7.5; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "z_score_var.z_hysteresis", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } z_score_var.z_hysteresis = atof(result); if((z_score_var.z_hysteresis < 0.0) || (z_score_var.z_hysteresis > 0.25)) { z_score_var.z_hysteresis = 0.0; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "z_score_var.zscore_error_detection", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } z_score_var.zscore_error_detection = atoi(result); if((z_score_var.zscore_error_detection < 50) || (z_score_var.zscore_error_detection > 100)) { z_score_var.zscore_error_detection = 50; } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "raw2edf_var", 0))) { if(!(xml_goto_nth_element_inside(xml_hdl, "sf", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var.sf = atoi(result); if(raw2edf_var.sf < 1) raw2edf_var.sf = 1; if(raw2edf_var.sf > 1000000) raw2edf_var.sf = 1000000; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "chns", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var.chns = atoi(result); if(raw2edf_var.chns < 1) raw2edf_var.chns = 1; if(raw2edf_var.chns > 256) raw2edf_var.chns = 256; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "phys_max", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var.phys_max = atoi(result); if(raw2edf_var.phys_max < 1) raw2edf_var.phys_max = 1; if(raw2edf_var.phys_max > 10000000) raw2edf_var.phys_max = 10000000; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "straightbinary", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var.straightbinary = atoi(result); if(raw2edf_var.straightbinary < 0) raw2edf_var.straightbinary = 0; if(raw2edf_var.straightbinary > 1) raw2edf_var.straightbinary = 1; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "endianness", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var.endianness = atoi(result); if(raw2edf_var.endianness < 0) raw2edf_var.endianness = 0; if(raw2edf_var.endianness > 1) raw2edf_var.endianness = 1; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "samplesize", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var.samplesize = atoi(result); if(raw2edf_var.samplesize < 1) raw2edf_var.samplesize = 1; if(raw2edf_var.samplesize > 2) raw2edf_var.samplesize = 2; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "offset", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var.offset = atoi(result); if(raw2edf_var.offset < 0) raw2edf_var.offset = 0; if(raw2edf_var.offset > 1000000) raw2edf_var.offset = 1000000; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "skipblocksize", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var.skipblocksize = atoi(result); if(raw2edf_var.skipblocksize < 0) raw2edf_var.skipblocksize = 0; if(raw2edf_var.skipblocksize > 1000000) raw2edf_var.skipblocksize = 1000000; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "skipbytes", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } raw2edf_var.skipbytes = atoi(result); if(raw2edf_var.skipbytes < 1) raw2edf_var.skipbytes = 1; if(raw2edf_var.skipbytes > 1000000) raw2edf_var.skipbytes = 1000000; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "phys_dim", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } strncpy(raw2edf_var.phys_dim, result, 16); raw2edf_var.phys_dim[15] = 0; latin1_to_ascii(raw2edf_var.phys_dim, 16); remove_leading_spaces(raw2edf_var.phys_dim); remove_trailing_spaces(raw2edf_var.phys_dim); 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)) { xml_close(xml_hdl); return; } check_for_updates = atoi(result); if((check_for_updates < 0) || (check_for_updates > 1)) check_for_updates = 1; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "viewtime_indicator_type", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } viewtime_indicator_type = atoi(result); if((viewtime_indicator_type < 0) || (viewtime_indicator_type > 2)) viewtime_indicator_type = 1; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "mainwindow_title_type", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } mainwindow_title_type = atoi(result); if((mainwindow_title_type < 0) || (mainwindow_title_type > 2)) mainwindow_title_type = 1; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "default_amplitude", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } default_amplitude = atof(result); if((default_amplitude < 0.001) || (default_amplitude > 10000000)) default_amplitude = 100; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "linear_interpolation", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } linear_interpol = atoi(result); if(linear_interpol != 1) { linear_interpol = 0; } xml_go_up(xml_hdl); } xml_close(xml_hdl); } void UI_Mainwindow::write_settings() { int i, len; char cfg_path[MAX_PATH_LENGTH], str[1024]; FILE *cfgfile; cfg_path[0] = 0; #ifdef Q_OS_WIN32 strcpy(cfg_path, specialFolder(CSIDL_APPDATA).toLocal8Bit().data()); strcat(cfg_path, "\\"); strcat(cfg_path, PROGRAM_NAME); mkdir(cfg_path); strcat(cfg_path, "\\settings.xml"); #else strcpy(cfg_path, getenv("HOME")); strcat(cfg_path, "/."); strcat(cfg_path, PROGRAM_NAME); mkdir(cfg_path, S_IRWXU); strcat(cfg_path, "/settings.xml"); #endif cfgfile = fopeno(cfg_path, "wb"); if(cfgfile) { fprintf(cfgfile, "\n" "\n" " " PROGRAM_NAME " " PROGRAM_VERSION "\n" " \n" " \n"); fprintf(cfgfile, " \n" " %i\n" " %i\n" " %i\n" " \n", maincurve->backgroundcolor.red(), maincurve->backgroundcolor.green(), maincurve->backgroundcolor.blue()); fprintf(cfgfile, " \n" " %i\n" " %i\n" " %i\n" " \n", maincurve->small_ruler_color.red(), maincurve->small_ruler_color.green(), maincurve->small_ruler_color.blue()); fprintf(cfgfile, " \n" " %i\n" " %i\n" " %i\n" " \n", maincurve->big_ruler_color.red(), maincurve->big_ruler_color.green(), maincurve->big_ruler_color.blue()); fprintf(cfgfile, " \n" " %i\n" " %i\n" " %i\n" " \n", maincurve->mouse_rect_color.red(), maincurve->mouse_rect_color.green(), maincurve->mouse_rect_color.blue()); fprintf(cfgfile, " \n" " %i\n" " %i\n" " %i\n" " \n", maincurve->text_color.red(), maincurve->text_color.green(), maincurve->text_color.blue()); fprintf(cfgfile, " \n" " %i\n" " %i\n" " %i\n" " \n", maincurve->baseline_color.red(), maincurve->baseline_color.green(), maincurve->baseline_color.blue()); fprintf(cfgfile, " \n" " %i\n" " %i\n" " %i\n" " \n", maincurve->annot_marker_color.red(), maincurve->annot_marker_color.green(), maincurve->annot_marker_color.blue()); fprintf(cfgfile, " %i\n", maincurve->signal_color); fprintf(cfgfile, " %i\n", maincurve->crosshair_1.color); fprintf(cfgfile, " %i\n", maincurve->crosshair_2.color); fprintf(cfgfile, " %i\n", maincurve->floating_ruler_color); fprintf(cfgfile, " %i\n", maincurve->blackwhite_printing); fprintf(cfgfile, " %i\n", show_annot_markers); fprintf(cfgfile, " %i\n", show_baselines); fprintf(cfgfile, " %i\n", clip_to_pane); fprintf(cfgfile, " %i\n", auto_reload_mtg); fprintf(cfgfile, " %i\n", read_biosemi_status_signal); fprintf(cfgfile, " %i\n", read_nk_trigger_signal); fprintf(cfgfile, " %i\n", use_threads); #ifdef Q_OS_WIN32 __mingw_fprintf(cfgfile, " %lli\n", maxfilesize_to_readin_annotations); #else fprintf(cfgfile, " %lli\n", maxfilesize_to_readin_annotations); #endif len = strlen(path); for(i=len-1; i>=0; i--) { if((path[i] == '/')||(path[i] == '\\')) { break; } } path[i+1] = 0; fprintf(cfgfile, " \n %.10f\n %i\n %.10f\n ", pixelsizefactor, auto_dpi, x_pixelsizefactor); xml_fwrite_encode_entity(cfgfile, path); fprintf(cfgfile, "\n"); for(i=0; i"); xml_fwrite_encode_entity(cfgfile, &recent_file_path[i][0]); fprintf(cfgfile, "\n"); } for(i=0; i"); xml_fwrite_encode_entity(cfgfile, &recent_file_mtg_path[i][0]); fprintf(cfgfile, "\n"); } fprintf(cfgfile, " "); xml_fwrite_encode_entity(cfgfile, recent_montagedir); fprintf(cfgfile, "\n"); fprintf(cfgfile, " "); xml_fwrite_encode_entity(cfgfile, recent_savedir); fprintf(cfgfile, "\n"); fprintf(cfgfile, " "); xml_fwrite_encode_entity(cfgfile, recent_opendir); fprintf(cfgfile, "\n"); fprintf(cfgfile, " "); xml_fwrite_encode_entity(cfgfile, recent_colordir); fprintf(cfgfile, "\n"); for(i=0; i < MAXPREDEFINEDMONTAGES; i++) { fprintf(cfgfile, " "); xml_fwrite_encode_entity(cfgfile, &predefined_mtg_path[i][0]); fprintf(cfgfile, "\n"); } fprintf(cfgfile, " \n"); fprintf(cfgfile, " %i\n", spectrum_colorbar->items); for(i=0; i < MAXSPECTRUMMARKERS; i++) { fprintf(cfgfile, " %f\n", spectrum_colorbar->freq[i]); } for(i=0; i < MAXSPECTRUMMARKERS; i++) { fprintf(cfgfile, " %i\n", spectrum_colorbar->color[i]); } for(i=0; i < MAXSPECTRUMMARKERS; i++) { fprintf(cfgfile, " \n"); } fprintf(cfgfile, " %i\n", spectrum_colorbar->method); fprintf(cfgfile, " %i\n", spectrum_colorbar->auto_adjust); fprintf(cfgfile, " %.8f\n", spectrum_colorbar->max_colorbar_value); fprintf(cfgfile, " \n"); fprintf(cfgfile, " %i\n", maxdftblocksize); fprintf(cfgfile, " \n"); fprintf(cfgfile, " %i\n", import_annotations_var->format); fprintf(cfgfile, " %i\n", import_annotations_var->onsettimeformat); fprintf(cfgfile, " %i\n", import_annotations_var->onsetcolumn); fprintf(cfgfile, " %i\n", import_annotations_var->descriptioncolumn); fprintf(cfgfile, " %i\n", import_annotations_var->useduration); fprintf(cfgfile, " %i\n", import_annotations_var->durationcolumn); fprintf(cfgfile, " %i\n", import_annotations_var->datastartline); xml_strcpy_encode_entity(str, import_annotations_var->separator); fprintf(cfgfile, " %s\n", str); fprintf(cfgfile, " %i\n", import_annotations_var->dceventbittime); fprintf(cfgfile, " %.12f\n", import_annotations_var->triggerlevel); fprintf(cfgfile, " %i\n", import_annotations_var->manualdescription); xml_strcpy_encode_entity(str, import_annotations_var->description); fprintf(cfgfile, " %s\n", str); fprintf(cfgfile, " %i\n", import_annotations_var->ignoreconsecutive); fprintf(cfgfile, " \n"); fprintf(cfgfile, " \n"); fprintf(cfgfile, " %i\n", export_annotations_var->separator); fprintf(cfgfile, " %i\n", export_annotations_var->format); fprintf(cfgfile, " %i\n", export_annotations_var->duration); fprintf(cfgfile, " \n"); fprintf(cfgfile, " %i\n", live_stream_update_interval); fprintf(cfgfile, " %i\n", powerlinefreq); fprintf(cfgfile, " %i\n", mousewheelsens); fprintf(cfgfile, " %f\n", average_period); fprintf(cfgfile, " %i\n", average_ratio); fprintf(cfgfile, " %i\n", average_upsidedown); fprintf(cfgfile, " %i\n", average_bw); fprintf(cfgfile, " %i\n", spectrum_bw); fprintf(cfgfile, " %i\n", spectrum_sqrt); fprintf(cfgfile, " %i\n", spectrum_vlog); fprintf(cfgfile, " %i\n", spectrumdock_sqrt); fprintf(cfgfile, " %i\n", spectrumdock_vlog); fprintf(cfgfile, " %f\n", z_score_var.crossoverfreq); fprintf(cfgfile, " %f\n", z_score_var.z_threshold); fprintf(cfgfile, " %i\n", z_score_var.zscore_page_len); fprintf(cfgfile, " %i\n", z_score_var.zscore_error_detection); fprintf(cfgfile, " %f\n", z_score_var.z_hysteresis); fprintf(cfgfile, " \n"); fprintf(cfgfile, " %i\n", raw2edf_var.sf); fprintf(cfgfile, " %i\n", raw2edf_var.chns); fprintf(cfgfile, " %i\n", raw2edf_var.phys_max); fprintf(cfgfile, " %i\n", raw2edf_var.straightbinary); fprintf(cfgfile, " %i\n", raw2edf_var.endianness); fprintf(cfgfile, " %i\n", raw2edf_var.samplesize); fprintf(cfgfile, " %i\n", raw2edf_var.offset); fprintf(cfgfile, " %i\n", raw2edf_var.skipblocksize); fprintf(cfgfile, " %i\n", raw2edf_var.skipbytes); xml_strcpy_encode_entity(str, raw2edf_var.phys_dim); fprintf(cfgfile, " %s\n", str); fprintf(cfgfile, " \n"); fprintf(cfgfile, " %i\n", check_for_updates); fprintf(cfgfile, " %i\n", viewtime_indicator_type); fprintf(cfgfile, " %i\n", mainwindow_title_type); fprintf(cfgfile, " %f\n", default_amplitude); fprintf(cfgfile, " %i\n", linear_interpol); fprintf(cfgfile, " \n\n"); fclose(cfgfile); } } edfbrowser_157_source/PaxHeaders.7921/bi9800.cpp0000644000000000000000000000013212646460742016305 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/bi9800.cpp0000644000175000001440000002646412646460742016662 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "bi9800.h" UI_BI98002EDFwindow::UI_BI98002EDFwindow(char *recent_dir, char *save_dir) { recent_opendir = recent_dir; recent_savedir = save_dir; myobjectDialog = new QDialog; myobjectDialog->setMinimumSize(300, 75); myobjectDialog->setMaximumSize(300, 75); myobjectDialog->setWindowTitle("BI9800 to EDF+ converter"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); pushButton1 = new QPushButton(myobjectDialog); pushButton1->setGeometry(20, 30, 100, 25); pushButton1->setText("Select File"); pushButton2 = new QPushButton(myobjectDialog); pushButton2->setGeometry(180, 30, 100, 25); pushButton2->setText("Close"); QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton())); QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close())); myobjectDialog->exec(); } void UI_BI98002EDFwindow::SelectFileButton() { int i, j, n, tmp, end_of_file, samplefreq=0, chns = 3, hdl, samplesize=1, bufsize, *buf2, datablocks, blocks_written, checked_modelnumber=0, checked_samplerate=0, checked_recordhours=0, checked_recorddate=0, checked_recordtime=0, startdate_year=0, startdate_month=0, startdate_day=0, starttime_hour=0, starttime_minute=0, starttime_second=0, progress_steps; char path[MAX_PATH_LENGTH], outputfilename[MAX_PATH_LENGTH], str[2048], str2[128], *buf1, tmp2, modelnumber_str[32]; FILE *dcmfile, *evtfile; strcpy(path, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "DCM files (*.dcm *.DCM)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(recent_opendir, path, MAX_PATH_LENGTH); get_filename_from_path(outputfilename, path, MAX_PATH_LENGTH); dcmfile = fopeno(path, "rb"); if(dcmfile==NULL) { snprintf(str, 2048, "Can not open file %s for reading.", path); QMessageBox messagewindow(QMessageBox::Critical, "Error", QString::fromLocal8Bit(str)); messagewindow.exec(); return; } remove_extension_from_filename(path); strcat(path, ".EVT"); evtfile = fopeno(path, "rb"); if(evtfile==NULL) { remove_extension_from_filename(path); strcat(path, ".evt"); evtfile = fopeno(path, "rb"); if(evtfile==NULL) { snprintf(str, 2048, "Can not open file %s for reading.", path); QMessageBox messagewindow(QMessageBox::Critical, "Error", str); messagewindow.exec(); fclose(dcmfile); return; } } /***************** check if the file is valid ******************************/ for(end_of_file=0; end_of_file == 0; ) { for(i=0; i<256; i++) { tmp = fgetc(evtfile); if(tmp == '\n') { break; } if(tmp == EOF) { end_of_file = 1; break; } str[i] = tmp; } str[i] = 0; if(!(strncmp(str, "Sampling Rate=", 14))) { samplefreq = atoi(str + 14); switch(samplefreq) { case 128 : break; case 256 : break; case 512 : break; case 1024 : break; default : QMessageBox messagewindow(QMessageBox::Critical, "Error", "Unknown samplerate."); messagewindow.exec(); fclose(dcmfile); fclose(evtfile); return; } checked_samplerate = 1; } if(!(strncmp(str, "Model number=", 13))) { strncpy(modelnumber_str, str + 13, 8); modelnumber_str[8] = 0; if(strcmp(modelnumber_str, "TM SD01G") && strcmp(modelnumber_str, "SD SD02G")) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Wrong modelnumber."); messagewindow.exec(); fclose(dcmfile); fclose(evtfile); return; } checked_modelnumber = 1; } if(!(strncmp(str, "Record Date=", 12))) { strncpy(str2, str + 12, 10); str2[10] = 0; startdate_year = atoi(str2); startdate_month = atoi(str2 + 5); startdate_day = atoi(str2 + 8); if((startdate_year < 1970) || (startdate_year > 3000) || (startdate_month < 1) || (startdate_month > 12) || (startdate_day < 1) || (startdate_day > 31)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Wrong record date."); messagewindow.exec(); fclose(dcmfile); fclose(evtfile); return; } checked_recorddate = 1; } if(!(strncmp(str, "Record Time=", 12))) { strncpy(str2, str + 12, 10); str2[8] = 0; starttime_hour = atoi(str2); starttime_minute = atoi(str2 + 3); starttime_second = atoi(str2 + 6); if((starttime_hour < 0) || (starttime_hour > 23) || (starttime_minute < 0) || (starttime_minute > 59) || (starttime_second < 0) || (starttime_second > 59)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Wrong recordtime."); messagewindow.exec(); fclose(dcmfile); fclose(evtfile); return; } checked_recordtime = 1; } if(!(strncmp(str, "Record Hours=", 13))) { strncpy(str2, str + 13, 10); str2[2] = 0; if((atoi(str2) != 24) && (atoi(str2) != 48)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Wrong record hours."); messagewindow.exec(); fclose(dcmfile); fclose(evtfile); return; } checked_recordhours = 1; } } if(!checked_modelnumber || !checked_samplerate || !checked_recordhours || !checked_recorddate || !checked_recordtime) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Missing line."); messagewindow.exec(); fclose(dcmfile); fclose(evtfile); return; } /////////////////////////////////////////////////////////////////////////////////// bufsize = chns * samplesize * samplefreq; buf1 = (char *)malloc(bufsize); if(buf1 == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error."); messagewindow.exec(); fclose(dcmfile); fclose(evtfile); return; } buf2 = (int *)malloc(bufsize * sizeof(int)); if(buf2 == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error."); messagewindow.exec(); fclose(dcmfile); fclose(evtfile); free(buf1); return; } /////////////////////////////////////////////////////////////////////////////////// path[0] = 0; if(recent_savedir[0]!=0) { strcpy(path, recent_savedir); strcat(path, "/"); } strcat(path, outputfilename); remove_extension_from_filename(path); strcat(path, ".edf"); strcpy(path, QFileDialog::getSaveFileName(0, "Select outputfile", QString::fromLocal8Bit(path), "EDF files (*.edf *.EDF)").toLocal8Bit().data()); if(!strcmp(path, "")) { fclose(dcmfile); fclose(evtfile); free(buf1); free(buf2); return; } get_directory_from_path(recent_savedir, path, MAX_PATH_LENGTH); hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_EDFPLUS, chns); if(hdl<0) { snprintf(str, 2048, "Can not open file %s for writing.", path); QMessageBox messagewindow(QMessageBox::Critical, "Error", str); messagewindow.exec(); fclose(dcmfile); fclose(evtfile); free(buf1); free(buf2); return; } for(i=0; iprocessEvents(); if(progress.wasCanceled() == true) { break; } } n = fread(buf1, bufsize, 1, dcmfile); if(n != 1) { break; } for(i=0; i 23) || (starttime_minute < 0) || (starttime_minute > 59) || (starttime_second < 0) || (starttime_second > 59)) { } else { if(strlen(str) > 9) { edfwrite_annotation_latin1(hdl, (starttime_second + (starttime_minute * 60) + (starttime_hour * 3600)) * 10000, -1, str + 9); } } } } edfwrite_annotation_latin1(hdl, blocks_written * 10000LL, -1LL, "Recording ends"); edfclose_file(hdl); fclose(dcmfile); fclose(evtfile); free(buf1); free(buf2); } edfbrowser_157_source/PaxHeaders.7921/bdf_triggers.cpp0000644000000000000000000000013212646460742020033 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/bdf_triggers.cpp0000644000175000001440000001554712646460742020410 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "bdf_triggers.h" int BDF_triggers::get_triggers(struct edfhdrblock *hdr, struct annotationblock **list) { int i, j, sf, status_signal=0, error, edfsignals, bufsize, jump_file, trigger_cnt, status[24]; char *buf; long long datarecords, long_data_record_duration, records_read, status_sample_duration, progress_steps; FILE *inputfile; struct annotationblock *annotation=NULL; struct annotationblock *annotlist; *list = NULL; annotlist = NULL; inputfile = hdr->file_hdl; edfsignals = hdr->edfsignals; datarecords = hdr->datarecords; long_data_record_duration = hdr->long_data_record_duration; if(edfsignals < 1) { return(0); } if(long_data_record_duration != TIME_DIMENSION) { return(0); } sf = hdr->edfparam[0].smp_per_record; for(i=1; iedfparam[i].smp_per_record != sf) { return(0); } } error = 1; switch(sf) { case 16384 : error = 0; break; case 8192 : error = 0; break; case 4096 : error = 0; break; case 2048 : error = 0; break; case 1024 : error = 0; break; case 512 : error = 0; break; case 256 : error = 0; break; case 128 : error = 0; break; case 64 : error = 0; break; case 32 : error = 0; break; } if(error) { return(0); } for(i=0; iedfparam[i].label, "Status "))) { status_signal = i; break; } } if(i == edfsignals) { return(0); } bufsize = sf * 3; buf = (char *)calloc(1, bufsize); if(buf==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Memory allocation error occurred when trying to read triggers.\n(buf)"); messagewindow.exec(); return(1); } if(fseeko(inputfile, ((long long)edfsignals + 1LL) * 256LL, SEEK_SET)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when reading inputfile triggers."); messagewindow.exec(); free(buf); return(2); } jump_file = status_signal * sf * 3; status_sample_duration = TIME_DIMENSION / (long long)sf; trigger_cnt = 0; for(i=0; i<24; i++) { status[i] = 1; } QProgressDialog progress("Scanning file for triggers...", "Abort", 0, datarecords); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); progress_steps = datarecords / 100LL; if(progress_steps < 1LL) { progress_steps = 1LL; } for(records_read=0LL; records_readprocessEvents(); if(progress.wasCanceled() == true) { break; } } if(trigger_cnt >= 100000) { break; } if(fseeko(inputfile, (long long)jump_file, SEEK_CUR)) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when reading inputfile triggers."); messagewindow.exec(); free(buf); return(2); } if(fread(buf, bufsize, 1, inputfile)!=1) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when reading inputfile triggers."); messagewindow.exec(); free(buf); return(2); } for(i=0; ifile_num = hdr->file_num; annotation->onset = (records_read * TIME_DIMENSION) + ((long long)(i / 3) * status_sample_duration); annotation->onset += hdr->starttime_offset; sprintf(annotation->annotation, "new epoch"); annotation->ident = (1 << ANNOT_ID_BS_TRIGGER); edfplus_annotation_add_item(&annotlist, annotation); trigger_cnt++; status[16] = 1; } } else { if(status[16]) // falling edge detected { status[16] = 0; } } for(j=0; j<16; j++) { if(*((unsigned short *)(buf + i)) & (1 << j)) { if(!status[j]) // rising edge detected { annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); if(annotation == NULL) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error (annotation)."); messagewindow.exec(); *list = annotlist; free(buf); return(1); } annotation->onset = (records_read * TIME_DIMENSION) + ((long long)(i / 3) * status_sample_duration); annotation->onset += hdr->starttime_offset; sprintf(annotation->annotation, "Trigger Input %i", j + 1); annotation->ident = (1 << ANNOT_ID_BS_TRIGGER); edfplus_annotation_add_item(&annotlist, annotation); trigger_cnt++; status[j] = 1; } } else { if(status[j]) // falling edge detected { status[j] = 0; } } } } } progress.reset(); *list = annotlist; free(buf); hdr->genuine_biosemi = 1; return(0); } edfbrowser_157_source/PaxHeaders.7921/edf_annotations.h0000644000000000000000000000013212646460742020212 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/edf_annotations.h0000644000175000001440000000306512646460742020557 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef EDF_ANNOTATIONS_H #define EDF_ANNOTATIONS_H #include #include #include #include #include #include #include #include "global.h" #include "edf_annot_list.h" class EDF_annotations { public: int get_annotations(int, struct edfhdrblock *, struct annotationblock **, int); private: int is_duration_number(char *); int is_onset_number(char *); long long get_long_time(char *); int check_device(char *); }; #endif // EDF_ANNOTATIONS_H edfbrowser_157_source/PaxHeaders.7921/colordialog.cpp0000644000000000000000000000013212646460742017670 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/colordialog.cpp0000644000175000001440000001756312646460742020245 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "colordialog.h" UI_ColorMenuDialog::UI_ColorMenuDialog(int *newColor, QWidget *w_parent) { colormenu_dialog = new QDialog(w_parent); colormenu_dialog->setMinimumSize(105, 130); colormenu_dialog->setMaximumSize(105, 130); colormenu_dialog->setWindowTitle("Color"); colormenu_dialog->setModal(true); colormenu_dialog->setAttribute(Qt::WA_DeleteOnClose, true); color = newColor; *color = -1; CloseButton = new QPushButton(colormenu_dialog); CloseButton->setGeometry(5, 105, 95, 20); CloseButton->setText("Close"); ColorButton1 = new SpecialButton(colormenu_dialog); ColorButton1->setGeometry(5, 5, 20, 20); ColorButton1->setColor(Qt::black); ColorButton2 = new SpecialButton(colormenu_dialog); ColorButton2->setGeometry(30, 5, 20, 20); ColorButton2->setColor(Qt::red); ColorButton3 = new SpecialButton(colormenu_dialog); ColorButton3->setGeometry(55, 5, 20, 20); ColorButton3->setColor(Qt::darkRed); ColorButton4 = new SpecialButton(colormenu_dialog); ColorButton4->setGeometry(80, 5, 20, 20); ColorButton4->setColor(Qt::green); ColorButton5 = new SpecialButton(colormenu_dialog); ColorButton5->setGeometry(5, 30, 20, 20); ColorButton5->setColor(Qt::darkGreen); ColorButton6 = new SpecialButton(colormenu_dialog); ColorButton6->setGeometry(30, 30, 20, 20); ColorButton6->setColor(Qt::blue); ColorButton7 = new SpecialButton(colormenu_dialog); ColorButton7->setGeometry(55, 30, 20, 20); ColorButton7->setColor(Qt::darkBlue); ColorButton8 = new SpecialButton(colormenu_dialog); ColorButton8->setGeometry(80, 30, 20, 20); ColorButton8->setColor(Qt::cyan); ColorButton9 = new SpecialButton(colormenu_dialog); ColorButton9->setGeometry(5, 55, 20, 20); ColorButton9->setColor(Qt::darkCyan); ColorButton10 = new SpecialButton(colormenu_dialog); ColorButton10->setGeometry(30, 55, 20, 20); ColorButton10->setColor(Qt::magenta); ColorButton11 = new SpecialButton(colormenu_dialog); ColorButton11->setGeometry(55, 55, 20, 20); ColorButton11->setColor(Qt::darkMagenta); ColorButton12 = new SpecialButton(colormenu_dialog); ColorButton12->setGeometry(80, 55, 20, 20); ColorButton12->setColor(Qt::yellow); ColorButton13 = new SpecialButton(colormenu_dialog); ColorButton13->setGeometry(5, 80, 20, 20); ColorButton13->setColor(Qt::darkYellow); ColorButton14 = new SpecialButton(colormenu_dialog); ColorButton14->setGeometry(30, 80, 20, 20); ColorButton14->setColor(Qt::gray); ColorButton15 = new SpecialButton(colormenu_dialog); ColorButton15->setGeometry(55, 80, 20, 20); ColorButton15->setColor(Qt::darkGray); ColorButton16 = new SpecialButton(colormenu_dialog); ColorButton16->setGeometry(80, 80, 20, 20); ColorButton16->setColor(Qt::white); QObject::connect(CloseButton, SIGNAL(clicked()), colormenu_dialog, SLOT(close())); QObject::connect(ColorButton1, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButton1_pressed(SpecialButton *))); QObject::connect(ColorButton2, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButton2_pressed(SpecialButton *))); QObject::connect(ColorButton3, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButton3_pressed(SpecialButton *))); QObject::connect(ColorButton4, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButton4_pressed(SpecialButton *))); QObject::connect(ColorButton5, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButton5_pressed(SpecialButton *))); QObject::connect(ColorButton6, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButton6_pressed(SpecialButton *))); QObject::connect(ColorButton7, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButton7_pressed(SpecialButton *))); QObject::connect(ColorButton8, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButton8_pressed(SpecialButton *))); QObject::connect(ColorButton9, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButton9_pressed(SpecialButton *))); QObject::connect(ColorButton10, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButton10_pressed(SpecialButton *))); QObject::connect(ColorButton11, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButton11_pressed(SpecialButton *))); QObject::connect(ColorButton12, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButton12_pressed(SpecialButton *))); QObject::connect(ColorButton13, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButton13_pressed(SpecialButton *))); QObject::connect(ColorButton14, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButton14_pressed(SpecialButton *))); QObject::connect(ColorButton15, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButton15_pressed(SpecialButton *))); QObject::connect(ColorButton16, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButton16_pressed(SpecialButton *))); colormenu_dialog->exec(); } void UI_ColorMenuDialog::ColorButton1_pressed(SpecialButton *) { *color = Qt::black; colormenu_dialog->close(); } void UI_ColorMenuDialog::ColorButton2_pressed(SpecialButton *) { *color = Qt::red; colormenu_dialog->close(); } void UI_ColorMenuDialog::ColorButton3_pressed(SpecialButton *) { *color = Qt::darkRed; colormenu_dialog->close(); } void UI_ColorMenuDialog::ColorButton4_pressed(SpecialButton *) { *color = Qt::green; colormenu_dialog->close(); } void UI_ColorMenuDialog::ColorButton5_pressed(SpecialButton *) { *color = Qt::darkGreen; colormenu_dialog->close(); } void UI_ColorMenuDialog::ColorButton6_pressed(SpecialButton *) { *color = Qt::blue; colormenu_dialog->close(); } void UI_ColorMenuDialog::ColorButton7_pressed(SpecialButton *) { *color = Qt::darkBlue; colormenu_dialog->close(); } void UI_ColorMenuDialog::ColorButton8_pressed(SpecialButton *) { *color = Qt::cyan; colormenu_dialog->close(); } void UI_ColorMenuDialog::ColorButton9_pressed(SpecialButton *) { *color = Qt::darkCyan; colormenu_dialog->close(); } void UI_ColorMenuDialog::ColorButton10_pressed(SpecialButton *) { *color = Qt::magenta; colormenu_dialog->close(); } void UI_ColorMenuDialog::ColorButton11_pressed(SpecialButton *) { *color = Qt::darkMagenta; colormenu_dialog->close(); } void UI_ColorMenuDialog::ColorButton12_pressed(SpecialButton *) { *color = Qt::yellow; colormenu_dialog->close(); } void UI_ColorMenuDialog::ColorButton13_pressed(SpecialButton *) { *color = Qt::darkYellow; colormenu_dialog->close(); } void UI_ColorMenuDialog::ColorButton14_pressed(SpecialButton *) { *color = Qt::gray; colormenu_dialog->close(); } void UI_ColorMenuDialog::ColorButton15_pressed(SpecialButton *) { *color = Qt::darkGray; colormenu_dialog->close(); } void UI_ColorMenuDialog::ColorButton16_pressed(SpecialButton *) { *color = Qt::white; colormenu_dialog->close(); } edfbrowser_157_source/PaxHeaders.7921/fino2edf.h0000644000000000000000000000012712646460742016537 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/fino2edf.h0000644000175000001440000000416212646460742017077 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_FINO2EDFFORM_H #define UI_FINO2EDFFORM_H #include #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION < 0x050000 #include #include #endif #include #include #include #include #include #include #include "global.h" #include "utils.h" #define MAX_SIGNALS 32 class UI_FINO2EDFwindow : public QObject { Q_OBJECT public: UI_FINO2EDFwindow(char *recent_dir=NULL, char *save_dir=NULL); private: QDialog *myobjectDialog; QPushButton *pushButton1, *pushButton2; QLabel *PatientnameLabel, *RecordingLabel, *DatetimeLabel; QLineEdit *PatientnameLineEdit, *RecordingLineEdit; QDateTimeEdit *StartDatetimeedit; char *recent_opendir, *recent_savedir; void enable_widgets(bool); private slots: void SelectFileButton(); }; #endif edfbrowser_157_source/PaxHeaders.7921/bi9800.h0000644000000000000000000000013212646460742015752 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/bi9800.h0000644000175000001440000000341712646460742016320 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_BI98002EDFFORM_H #define UI_BI98002EDFFORM_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "edflib.h" #include "utils.h" class UI_BI98002EDFwindow : public QObject { Q_OBJECT public: UI_BI98002EDFwindow(char *recent_dir=NULL, char *save_dir=NULL); private: QPushButton *pushButton1, *pushButton2; QDialog *myobjectDialog; char *recent_opendir, *recent_savedir; private slots: void SelectFileButton(); }; #endif edfbrowser_157_source/PaxHeaders.7921/third_party0000644000000000000000000000013112646460742017141 xustar0030 mtime=1452958178.234246777 29 atime=1452958178.23324678 30 ctime=1452958178.234246777 edfbrowser_157_source/third_party/0000755000175000001440000000000012646460742017560 5ustar00guvusers00000000000000edfbrowser_157_source/third_party/PaxHeaders.7921/kiss_fft0000644000000000000000000000013112646460742020751 xustar0030 mtime=1452958178.234246777 29 atime=1452958178.23324678 30 ctime=1452958178.234246777 edfbrowser_157_source/third_party/kiss_fft/0000755000175000001440000000000012646460742021370 5ustar00guvusers00000000000000edfbrowser_157_source/third_party/kiss_fft/PaxHeaders.7921/kiss_fft.h0000644000000000000000000000012712646460742023014 xustar0029 mtime=1452958178.23324678 29 atime=1452958178.23324678 29 ctime=1452958178.23324678 edfbrowser_157_source/third_party/kiss_fft/kiss_fft.h0000644000175000001440000000632512646460742023357 0ustar00guvusers00000000000000#ifndef KISS_FFT_H #define KISS_FFT_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* ATTENTION! If you would like a : -- a utility that will handle the caching of fft objects -- real-only (no imaginary time component ) FFT -- a multi-dimensional FFT -- a command-line utility to perform ffts -- a command-line utility to perform fast-convolution filtering Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c in the tools/ directory. */ #ifdef USE_SIMD # include # define kiss_fft_scalar __m128 #define KISS_FFT_MALLOC(nbytes) _mm_malloc(nbytes,16) #define KISS_FFT_FREE _mm_free #else #define KISS_FFT_MALLOC malloc #define KISS_FFT_FREE free #endif #ifdef FIXED_POINT #include # if (FIXED_POINT == 32) # define kiss_fft_scalar int32_t # else # define kiss_fft_scalar int16_t # endif #else # ifndef kiss_fft_scalar /* default is float */ # define kiss_fft_scalar double # endif #endif typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; typedef struct kiss_fft_state* kiss_fft_cfg; /* * kiss_fft_alloc * * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. * * typical usage: kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL); * * The return value from fft_alloc is a cfg buffer used internally * by the fft routine or NULL. * * If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc. * The returned value should be free()d when done to avoid memory leaks. * * The state can be placed in a user supplied buffer 'mem': * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, * then the function places the cfg in mem and the size used in *lenmem * and returns mem. * * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), * then the function returns NULL and places the minimum cfg * buffer size in *lenmem. * */ kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem); /* * kiss_fft(cfg,in_out_buf) * * Perform an FFT on a complex input buffer. * for a forward FFT, * fin should be f[0] , f[1] , ... ,f[nfft-1] * fout will be F[0] , F[1] , ... ,F[nfft-1] * Note that each element is complex and can be accessed like f[k].r and f[k].i * */ void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); /* A more generic version of the above function. It reads its input from every Nth sample. * */ void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride); /* If kiss_fft_alloc allocated a buffer, it is one contiguous buffer and can be simply free()d when no longer needed*/ #define kiss_fft_free free /* Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up your compiler output to call this before you exit. */ void kiss_fft_cleanup(void); /* * Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5) */ int kiss_fft_next_fast_size(int n); /* for real ffts, we need an even size */ #define kiss_fftr_next_fast_size_real(n) \ (kiss_fft_next_fast_size( ((n)+1)>>1)<<1) #ifdef __cplusplus } #endif #endif edfbrowser_157_source/third_party/kiss_fft/PaxHeaders.7921/kiss_fftr.h0000644000000000000000000000012712646460742023176 xustar0029 mtime=1452958178.23324678 29 atime=1452958178.23324678 29 ctime=1452958178.23324678 edfbrowser_157_source/third_party/kiss_fft/kiss_fftr.h0000644000175000001440000000153212646460742023534 0ustar00guvusers00000000000000#ifndef KISS_FTR_H #define KISS_FTR_H #include "kiss_fft.h" #ifdef __cplusplus extern "C" { #endif /* Real optimized version can save about 45% cpu time vs. complex fft of a real seq. */ typedef struct kiss_fftr_state *kiss_fftr_cfg; kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem); /* nfft must be even If you don't care to allocate space, use mem = lenmem = NULL */ void kiss_fftr(kiss_fftr_cfg cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata); /* input timedata has nfft scalar points output freqdata has nfft/2+1 complex points */ void kiss_fftri(kiss_fftr_cfg cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata); /* input freqdata has nfft/2+1 complex points output timedata has nfft scalar points */ #define kiss_fftr_free free #ifdef __cplusplus } #endif #endif edfbrowser_157_source/third_party/kiss_fft/PaxHeaders.7921/_kiss_fft_guts.h0000644000000000000000000000012712646460742024215 xustar0029 mtime=1452958178.23324678 29 atime=1452958178.23324678 29 ctime=1452958178.23324678 edfbrowser_157_source/third_party/kiss_fft/_kiss_fft_guts.h0000644000175000001440000001324612646460742024560 0ustar00guvusers00000000000000/* Copyright (c) 2003-2010, Mark Borgerding All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* kiss_fft.h defines kiss_fft_scalar as either short or a float type and defines typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */ #include "kiss_fft.h" #include #define MAXFACTORS 32 /* e.g. an fft of length 128 has 4 factors as far as kissfft is concerned 4*4*4*2 */ struct kiss_fft_state{ int nfft; int inverse; int factors[2*MAXFACTORS]; kiss_fft_cpx twiddles[1]; }; /* Explanation of macros dealing with complex math: C_MUL(m,a,b) : m = a*b C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise C_SUB( res, a,b) : res = a - b C_SUBFROM( res , a) : res -= a C_ADDTO( res , a) : res += a * */ #ifdef FIXED_POINT #if (FIXED_POINT==32) # define FRACBITS 31 # define SAMPPROD int64_t #define SAMP_MAX 2147483647 #else # define FRACBITS 15 # define SAMPPROD int32_t #define SAMP_MAX 32767 #endif #define SAMP_MIN -SAMP_MAX #if defined(CHECK_OVERFLOW) # define CHECK_OVERFLOW_OP(a,op,b) \ if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \ fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); } #endif # define smul(a,b) ( (SAMPPROD)(a)*(b) ) # define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS ) # define S_MUL(a,b) sround( smul(a,b) ) # define C_MUL(m,a,b) \ do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0) # define DIVSCALAR(x,k) \ (x) = sround( smul( x, SAMP_MAX/k ) ) # define C_FIXDIV(c,div) \ do { DIVSCALAR( (c).r , div); \ DIVSCALAR( (c).i , div); }while (0) # define C_MULBYSCALAR( c, s ) \ do{ (c).r = sround( smul( (c).r , s ) ) ;\ (c).i = sround( smul( (c).i , s ) ) ; }while(0) #else /* not FIXED_POINT*/ # define S_MUL(a,b) ( (a)*(b) ) #define C_MUL(m,a,b) \ do{ (m).r = (a).r*(b).r - (a).i*(b).i;\ (m).i = (a).r*(b).i + (a).i*(b).r; }while(0) # define C_FIXDIV(c,div) /* NOOP */ # define C_MULBYSCALAR( c, s ) \ do{ (c).r *= (s);\ (c).i *= (s); }while(0) #endif #ifndef CHECK_OVERFLOW_OP # define CHECK_OVERFLOW_OP(a,op,b) /* noop */ #endif #define C_ADD( res, a,b)\ do { \ CHECK_OVERFLOW_OP((a).r,+,(b).r)\ CHECK_OVERFLOW_OP((a).i,+,(b).i)\ (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ }while(0) #define C_SUB( res, a,b)\ do { \ CHECK_OVERFLOW_OP((a).r,-,(b).r)\ CHECK_OVERFLOW_OP((a).i,-,(b).i)\ (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ }while(0) #define C_ADDTO( res , a)\ do { \ CHECK_OVERFLOW_OP((res).r,+,(a).r)\ CHECK_OVERFLOW_OP((res).i,+,(a).i)\ (res).r += (a).r; (res).i += (a).i;\ }while(0) #define C_SUBFROM( res , a)\ do {\ CHECK_OVERFLOW_OP((res).r,-,(a).r)\ CHECK_OVERFLOW_OP((res).i,-,(a).i)\ (res).r -= (a).r; (res).i -= (a).i; \ }while(0) #ifdef FIXED_POINT # define KISS_FFT_COS(phase) floor(.5+SAMP_MAX * cos (phase)) # define KISS_FFT_SIN(phase) floor(.5+SAMP_MAX * sin (phase)) # define HALF_OF(x) ((x)>>1) #elif defined(USE_SIMD) # define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) ) # define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) ) # define HALF_OF(x) ((x)*_mm_set1_ps(.5)) #else # define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase) # define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase) # define HALF_OF(x) ((x)*.5) #endif #define kf_cexp(x,phase) \ do{ \ (x)->r = KISS_FFT_COS(phase);\ (x)->i = KISS_FFT_SIN(phase);\ }while(0) /* a debugging function */ #define pcpx(c)\ fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) ) #ifdef KISS_FFT_USE_ALLOCA // define this to allow use of alloca instead of malloc for temporary buffers // Temporary buffers are used in two case: // 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5 // 2. "in-place" FFTs. Notice the quotes, since kissfft does not really do an in-place transform. #include #define KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes) #define KISS_FFT_TMP_FREE(ptr) #else #define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes) #define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr) #endif edfbrowser_157_source/third_party/kiss_fft/PaxHeaders.7921/kiss_fft.c0000644000000000000000000000012712646460742023007 xustar0029 mtime=1452958178.23324678 29 atime=1452958178.23324678 29 ctime=1452958178.23324678 edfbrowser_157_source/third_party/kiss_fft/kiss_fft.c0000644000175000001440000003056412646460742023354 0ustar00guvusers00000000000000/* Copyright (c) 2003-2010, Mark Borgerding All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "_kiss_fft_guts.h" /* The guts header contains all the multiplication and addition macros that are defined for fixed or floating point complex numbers. It also delares the kf_ internal functions. */ static void kf_bfly2( kiss_fft_cpx * Fout, const size_t fstride, const kiss_fft_cfg st, int m ) { kiss_fft_cpx * Fout2; kiss_fft_cpx * tw1 = st->twiddles; kiss_fft_cpx t; Fout2 = Fout + m; do{ C_FIXDIV(*Fout,2); C_FIXDIV(*Fout2,2); C_MUL (t, *Fout2 , *tw1); tw1 += fstride; C_SUB( *Fout2 , *Fout , t ); C_ADDTO( *Fout , t ); ++Fout2; ++Fout; }while (--m); } static void kf_bfly4( kiss_fft_cpx * Fout, const size_t fstride, const kiss_fft_cfg st, const size_t m ) { kiss_fft_cpx *tw1,*tw2,*tw3; kiss_fft_cpx scratch[6]; size_t k=m; const size_t m2=2*m; const size_t m3=3*m; tw3 = tw2 = tw1 = st->twiddles; do { C_FIXDIV(*Fout,4); C_FIXDIV(Fout[m],4); C_FIXDIV(Fout[m2],4); C_FIXDIV(Fout[m3],4); C_MUL(scratch[0],Fout[m] , *tw1 ); C_MUL(scratch[1],Fout[m2] , *tw2 ); C_MUL(scratch[2],Fout[m3] , *tw3 ); C_SUB( scratch[5] , *Fout, scratch[1] ); C_ADDTO(*Fout, scratch[1]); C_ADD( scratch[3] , scratch[0] , scratch[2] ); C_SUB( scratch[4] , scratch[0] , scratch[2] ); C_SUB( Fout[m2], *Fout, scratch[3] ); tw1 += fstride; tw2 += fstride*2; tw3 += fstride*3; C_ADDTO( *Fout , scratch[3] ); if(st->inverse) { Fout[m].r = scratch[5].r - scratch[4].i; Fout[m].i = scratch[5].i + scratch[4].r; Fout[m3].r = scratch[5].r + scratch[4].i; Fout[m3].i = scratch[5].i - scratch[4].r; }else{ Fout[m].r = scratch[5].r + scratch[4].i; Fout[m].i = scratch[5].i - scratch[4].r; Fout[m3].r = scratch[5].r - scratch[4].i; Fout[m3].i = scratch[5].i + scratch[4].r; } ++Fout; }while(--k); } static void kf_bfly3( kiss_fft_cpx * Fout, const size_t fstride, const kiss_fft_cfg st, size_t m ) { size_t k=m; const size_t m2 = 2*m; kiss_fft_cpx *tw1,*tw2; kiss_fft_cpx scratch[5]; kiss_fft_cpx epi3; epi3 = st->twiddles[fstride*m]; tw1=tw2=st->twiddles; do{ C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3); C_MUL(scratch[1],Fout[m] , *tw1); C_MUL(scratch[2],Fout[m2] , *tw2); C_ADD(scratch[3],scratch[1],scratch[2]); C_SUB(scratch[0],scratch[1],scratch[2]); tw1 += fstride; tw2 += fstride*2; Fout[m].r = Fout->r - HALF_OF(scratch[3].r); Fout[m].i = Fout->i - HALF_OF(scratch[3].i); C_MULBYSCALAR( scratch[0] , epi3.i ); C_ADDTO(*Fout,scratch[3]); Fout[m2].r = Fout[m].r + scratch[0].i; Fout[m2].i = Fout[m].i - scratch[0].r; Fout[m].r -= scratch[0].i; Fout[m].i += scratch[0].r; ++Fout; }while(--k); } static void kf_bfly5( kiss_fft_cpx * Fout, const size_t fstride, const kiss_fft_cfg st, int m ) { kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4; int u; kiss_fft_cpx scratch[13]; kiss_fft_cpx * twiddles = st->twiddles; kiss_fft_cpx *tw; kiss_fft_cpx ya,yb; ya = twiddles[fstride*m]; yb = twiddles[fstride*2*m]; Fout0=Fout; Fout1=Fout0+m; Fout2=Fout0+2*m; Fout3=Fout0+3*m; Fout4=Fout0+4*m; tw=st->twiddles; for ( u=0; ur += scratch[7].r + scratch[8].r; Fout0->i += scratch[7].i + scratch[8].i; scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r); scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r); scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i); scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i); C_SUB(*Fout1,scratch[5],scratch[6]); C_ADD(*Fout4,scratch[5],scratch[6]); scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r); scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r); scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i); scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i); C_ADD(*Fout2,scratch[11],scratch[12]); C_SUB(*Fout3,scratch[11],scratch[12]); ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4; } } /* perform the butterfly for one stage of a mixed radix FFT */ static void kf_bfly_generic( kiss_fft_cpx * Fout, const size_t fstride, const kiss_fft_cfg st, int m, int p ) { int u,k,q1,q; kiss_fft_cpx * twiddles = st->twiddles; kiss_fft_cpx t; int Norig = st->nfft; kiss_fft_cpx * scratch = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC(sizeof(kiss_fft_cpx)*p); for ( u=0; u=Norig) twidx-=Norig; C_MUL(t,scratch[q] , twiddles[twidx] ); C_ADDTO( Fout[ k ] ,t); } k += m; } } KISS_FFT_TMP_FREE(scratch); } static void kf_work( kiss_fft_cpx * Fout, const kiss_fft_cpx * f, const size_t fstride, int in_stride, int * factors, const kiss_fft_cfg st ) { kiss_fft_cpx * Fout_beg=Fout; const int p=*factors++; /* the radix */ const int m=*factors++; /* stage's fft length/p */ const kiss_fft_cpx * Fout_end = Fout + p*m; #ifdef _OPENMP // use openmp extensions at the // top-level (not recursive) if (fstride==1 && p<=5) { int k; // execute the p different work units in different threads # pragma omp parallel for for (k=0;k floor_sqrt) p = n; /* no more factors, skip to end */ } n /= p; *facbuf++ = p; *facbuf++ = n; } while (n > 1); } /* * * User-callable function to allocate all necessary storage space for the fft. * * The return value is a contiguous block of memory, allocated with malloc. As such, * It can be freed with free(), rather than a kiss_fft-specific function. * */ kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem ) { kiss_fft_cfg st=NULL; size_t memneeded = sizeof(struct kiss_fft_state) + sizeof(kiss_fft_cpx)*(nfft-1); /* twiddle factors*/ if ( lenmem==NULL ) { st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded ); }else{ if (mem != NULL && *lenmem >= memneeded) st = (kiss_fft_cfg)mem; *lenmem = memneeded; } if (st) { int i; st->nfft=nfft; st->inverse = inverse_fft; for (i=0;iinverse) phase *= -1; kf_cexp(st->twiddles+i, phase ); } kf_factor(nfft,st->factors); } return st; } void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride) { if (fin == fout) { //NOTE: this is not really an in-place FFT algorithm. //It just performs an out-of-place FFT into a temp buffer kiss_fft_cpx * tmpbuf = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC( sizeof(kiss_fft_cpx)*st->nfft); kf_work(tmpbuf,fin,1,in_stride, st->factors,st); memcpy(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft); KISS_FFT_TMP_FREE(tmpbuf); }else{ kf_work( fout, fin, 1,in_stride, st->factors,st ); } } void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout) { kiss_fft_stride(cfg,fin,fout,1); } void kiss_fft_cleanup(void) { // nothing needed any more } int kiss_fft_next_fast_size(int n) { while(1) { int m=n; while ( (m%2) == 0 ) m/=2; while ( (m%3) == 0 ) m/=3; while ( (m%5) == 0 ) m/=5; if (m<=1) break; /* n is completely factorable by twos, threes, and fives */ n++; } return n; } edfbrowser_157_source/third_party/kiss_fft/PaxHeaders.7921/kiss_fftr.c0000644000000000000000000000013212646460742023165 xustar0030 mtime=1452958178.234246777 30 atime=1452958178.234246777 30 ctime=1452958178.234246777 edfbrowser_157_source/third_party/kiss_fft/kiss_fftr.c0000644000175000001440000001347312646460742023536 0ustar00guvusers00000000000000/* Copyright (c) 2003-2004, Mark Borgerding All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "kiss_fftr.h" #include "_kiss_fft_guts.h" struct kiss_fftr_state{ kiss_fft_cfg substate; kiss_fft_cpx * tmpbuf; kiss_fft_cpx * super_twiddles; #ifdef USE_SIMD void * pad; #endif }; kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem) { int i; kiss_fftr_cfg st = NULL; size_t subsize, memneeded; if (nfft & 1) { fprintf(stderr,"Real FFT optimization must be even.\n"); return NULL; } nfft >>= 1; kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize); memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 3 / 2); if (lenmem == NULL) { st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded); } else { if (*lenmem >= memneeded) st = (kiss_fftr_cfg) mem; *lenmem = memneeded; } if (!st) return NULL; st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */ st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize); st->super_twiddles = st->tmpbuf + nfft; kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize); for (i = 0; i < nfft/2; ++i) { double phase = -3.14159265358979323846264338327 * ((double) (i+1) / nfft + .5); if (inverse_fft) phase *= -1; kf_cexp (st->super_twiddles+i,phase); } return st; } void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata) { /* input buffer timedata is stored row-wise */ int k,ncfft; kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc; if ( st->substate->inverse) { fprintf(stderr,"kiss fft usage error: improper alloc\n"); exit(1); } ncfft = st->substate->nfft; /*perform the parallel fft of two real signals packed in real,imag*/ kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf ); /* The real part of the DC element of the frequency spectrum in st->tmpbuf * contains the sum of the even-numbered elements of the input time sequence * The imag part is the sum of the odd-numbered elements * * The sum of tdc.r and tdc.i is the sum of the input time sequence. * yielding DC of input time sequence * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... * yielding Nyquist bin of input time sequence */ tdc.r = st->tmpbuf[0].r; tdc.i = st->tmpbuf[0].i; C_FIXDIV(tdc,2); CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i); CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i); freqdata[0].r = tdc.r + tdc.i; freqdata[ncfft].r = tdc.r - tdc.i; #ifdef USE_SIMD freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0); #else freqdata[ncfft].i = freqdata[0].i = 0; #endif for ( k=1;k <= ncfft/2 ; ++k ) { fpk = st->tmpbuf[k]; fpnk.r = st->tmpbuf[ncfft-k].r; fpnk.i = - st->tmpbuf[ncfft-k].i; C_FIXDIV(fpk,2); C_FIXDIV(fpnk,2); C_ADD( f1k, fpk , fpnk ); C_SUB( f2k, fpk , fpnk ); C_MUL( tw , f2k , st->super_twiddles[k-1]); freqdata[k].r = HALF_OF(f1k.r + tw.r); freqdata[k].i = HALF_OF(f1k.i + tw.i); freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r); freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i); } } void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata) { /* input buffer timedata is stored row-wise */ int k, ncfft; if (st->substate->inverse == 0) { fprintf (stderr, "kiss fft usage error: improper alloc\n"); exit (1); } ncfft = st->substate->nfft; st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r; st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r; C_FIXDIV(st->tmpbuf[0],2); for (k = 1; k <= ncfft / 2; ++k) { kiss_fft_cpx fk, fnkc, fek, fok, tmp; fk = freqdata[k]; fnkc.r = freqdata[ncfft - k].r; fnkc.i = -freqdata[ncfft - k].i; C_FIXDIV( fk , 2 ); C_FIXDIV( fnkc , 2 ); C_ADD (fek, fk, fnkc); C_SUB (tmp, fk, fnkc); C_MUL (fok, tmp, st->super_twiddles[k-1]); C_ADD (st->tmpbuf[k], fek, fok); C_SUB (st->tmpbuf[ncfft - k], fek, fok); #ifdef USE_SIMD st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0); #else st->tmpbuf[ncfft - k].i *= -1; #endif } kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata); } edfbrowser_157_source/third_party/PaxHeaders.7921/fidlib0000644000000000000000000000013212646460742020373 xustar0030 mtime=1452958178.234246777 30 atime=1452958178.234246777 30 ctime=1452958178.234246777 edfbrowser_157_source/third_party/fidlib/0000755000175000001440000000000012646460742021011 5ustar00guvusers00000000000000edfbrowser_157_source/third_party/fidlib/PaxHeaders.7921/fidmkf.h0000644000000000000000000000013212646460742022061 xustar0030 mtime=1452958178.234246777 30 atime=1452958178.234246777 30 ctime=1452958178.234246777 edfbrowser_157_source/third_party/fidlib/fidmkf.h0000644000175000001440000005214112646460742022425 0ustar00guvusers00000000000000// // mkfilter-derived code // --------------------- // // Copyright (c) 2002-2004 Jim Peters . This // file is released under the GNU Lesser General Public License // (LGPL) version 2.1 as published by the Free Software // Foundation. See the file COPYING_LIB for details, or visit // . // // This is all code derived from 'mkfilter' by Tony Fisher of the // University of York. I've rewritten it all in C, and given it // a thorough overhaul, so there is actually none of his code // here any more, but it is all still very strongly based on the // algorithms and techniques that he used in 'mkfilter'. // // For those who didn't hear, Tony Fisher died in February 2000 // at the age of 43. See his web-site for information and a // tribute: // // http://www-users.cs.york.ac.uk/~fisher/ // http://www-users.cs.york.ac.uk/~fisher/tribute.html // // The original C++ sources and the rest of the mkfilter tool-set // are still available from his site: // // http://www-users.cs.york.ac.uk/~fisher/mkfilter/ // // // I've made a number of improvements and changes whilst // rewriting the code in C. For example, I halved the // calculations required in designing the filters by storing only // one complex pole/zero out of each conjugate pair. This also // made it much easier to output the filter as a list of // sub-filters without lots of searching around to match up // conjugate pairs later on. Outputting as a list of subfilters // permits greater accuracy in calculation of the response, and // also in the execution of the final filter. Also, some FIR // coefficients can be marked as 'constant', allowing optimised // routines to be generated for whole classes of filters, with // just the variable coefficients filled in at run-time. // // On the down-side, complex numbers are not portably available // in C before C99, so complex calculations here are done on // double[] arrays with inline functions, which ends up looking // more like assembly language than C. Never mind. // // // LEGAL STUFF // ----------- // // Tony Fisher released his software on his University of York // pages for free use and free download. The software itself has // no licence terms attached, nor copyright messages, just the // author's name, E-mail address and date. Nor are there any // licence terms indicated on the website. I understand that // under the Berne convention copyright does not have to be // claimed explicitly, so these are in fact copyright files by // legal default. However, the intention was obviously that // these files should be used by others. // // None of this really helps, though, if we're going to try to be // 100% legally correct, so I wrote to Anthony Moulds who is the // contact name on Tony Fisher's pages now. I explained what I // planned to do with the code, and he answered as follows: // // (Note that I was planning to use it 'as-is' at that time, // rather than rewrite it as I have done now) // // > To: "Jim Peters" // > From: "Anthony Moulds" // > Subject: RE: mkfilter source // > Date: Tue, 29 Oct 2002 15:30:19 -0000 // > // > Hi Jim, // > // > Thanks for your email. // > // > The University will be happy to let you use Dr Fisher's mkfilter // > code since your intention is not to profit financially from his work. // > // > It would be nice if in some way you could acknowledge his contribution. // > // > Best wishes and good luck with your work, // > // > Anthony Moulds // > Senior Experimental Officer, // > Computer Science Department, University of York, // > York, England, UK. Tel: 44(0)1904 434758 Fax: 44(0)19042767 // > ============================================================ // > // > // > > -----Original Message----- // > > From: Jim Peters [mailto:jim@uazu.net] // > > Sent: Monday, October 28, 2002 12:36 PM // > > To: anthony@cs.york.ac.uk // > > Subject: mkfilter source // > > // > > // > > I'm very sorry to hear (rather late, I know) that Tony Fisher died -- // > > I've always gone straight to the filter page, rather than through his // > > home page. I hope his work remains available for the future. // > > // > > Anyway, the reason I'm writing is to clarify the status of the // > > mkfilter source code. Because copyright is not claimed on the web // > > page nor in the source distribution, I guess that Tony's intention was // > > that this code should be in the public domain. However, I would like // > > to check this now to avoid complications later. // > > // > > I am using his code, modified, to provide a library of filter-design // > > routines for a GPL'd filter design app, which is not yet released. // > > The library could also be used standalone, permitting apps to design // > > filters at run-time rather than using hard-coded compile-time filters. // > > My interest in filters is as a part of my work on the OpenEEG project // // So this looks pretty clear to me. I am not planning to profit // from the work, so everything is fine with the University. I // guess others might profit from the work, indirectly, as with // any free software release, but so long as I don't, we're fine. // // I hope this is watertight enough for Debian/etc. Otherwise // I'll have to go back to Anthony Moulds for clarification. // // Even though there is no code cut-and-pasted from 'mkfilter' // here, it is all very obviously based on that code, so it // probably counts as a derived work -- although as ever "I Am // Not A Lawyer". // #ifdef HUGE_VAL #define INF HUGE_VAL #else #define INF (1.0/0.0) #endif #define TWOPI (2*M_PI) // // Complex square root: aa= aa^0.5 // STATIC_INLINE double my_sqrt(double aa) { return aa <= 0.0 ? 0.0 : sqrt(aa); } // 'csqrt' clashes with builtin in GCC 4, so call it 'c_sqrt' STATIC_INLINE void c_sqrt(double *aa) { double mag= hypot(aa[0], aa[1]); double rr= my_sqrt((mag + aa[0]) * 0.5); double ii= my_sqrt((mag - aa[0]) * 0.5); if (aa[1] < 0.0) ii= -ii; aa[0]= rr; aa[1]= ii; } // // Complex imaginary exponent: aa= e^i.theta // STATIC_INLINE void cexpj(double *aa, double theta) { aa[0]= cos(theta); aa[1]= sin(theta); } // // Complex exponent: aa= e^aa // // 'cexp' clashes with builtin in GCC 4, so call it 'c_exp' STATIC_INLINE void c_exp(double *aa) { double mag= exp(aa[0]); aa[0]= mag * cos(aa[1]); aa[1]= mag * sin(aa[1]); } // // Global temp buffer for generating filters. *NOT THREAD SAFE* // // Note that the poles and zeros are stored in a strange way. // Rather than storing both a pole (or zero) and its complex // conjugate, I'm storing just one of the pair. Also, for real // poles, I'm not storing the imaginary part (which is zero). // This results in a list of numbers exactly half the length you // might otherwise expect. However, since some of these numbers // are in pairs, and some are single, we need a separate flag // array to indicate which is which. poltyp[] serves this // purpose. An entry is 1 if the corresponding offset is a real // pole, or 2 if it is the first of a pair of values making up a // complex pole. The second value of the pair has an entry of 0 // attached. (Similarly for zeros in zertyp[]) // #define MAXPZ 64 static int n_pol; // Number of poles static double pol[MAXPZ]; // Pole values (see above) static char poltyp[MAXPZ]; // Pole value types: 1 real, 2 first of complex pair, 0 second static int n_zer; // Same for zeros ... static double zer[MAXPZ]; static char zertyp[MAXPZ]; // // Pre-warp a frequency // STATIC_INLINE double prewarp(double val) { return tan(val * M_PI) / M_PI; } // // Bessel poles; final one is a real value for odd numbers of // poles // static double bessel_1[]= { -1.00000000000e+00 }; static double bessel_2[]= { -1.10160133059e+00, 6.36009824757e-01, }; static double bessel_3[]= { -1.04740916101e+00, 9.99264436281e-01, -1.32267579991e+00, }; static double bessel_4[]= { -9.95208764350e-01, 1.25710573945e+00, -1.37006783055e+00, 4.10249717494e-01, }; static double bessel_5[]= { -9.57676548563e-01, 1.47112432073e+00, -1.38087732586e+00, 7.17909587627e-01, -1.50231627145e+00, }; static double bessel_6[]= { -9.30656522947e-01, 1.66186326894e+00, -1.38185809760e+00, 9.71471890712e-01, -1.57149040362e+00, 3.20896374221e-01, }; static double bessel_7[]= { -9.09867780623e-01, 1.83645135304e+00, -1.37890321680e+00, 1.19156677780e+00, -1.61203876622e+00, 5.89244506931e-01, -1.68436817927e+00, }; static double bessel_8[]= { -8.92869718847e-01, 1.99832584364e+00, -1.37384121764e+00, 1.38835657588e+00, -1.63693941813e+00, 8.22795625139e-01, -1.75740840040e+00, 2.72867575103e-01, }; static double bessel_9[]= { -8.78399276161e-01, 2.14980052431e+00, -1.36758830979e+00, 1.56773371224e+00, -1.65239648458e+00, 1.03138956698e+00, -1.80717053496e+00, 5.12383730575e-01, -1.85660050123e+00, }; static double bessel_10[]= { -8.65756901707e-01, 2.29260483098e+00, -1.36069227838e+00, 1.73350574267e+00, -1.66181024140e+00, 1.22110021857e+00, -1.84219624443e+00, 7.27257597722e-01, -1.92761969145e+00, 2.41623471082e-01, }; static double *bessel_poles[10]= { bessel_1, bessel_2, bessel_3, bessel_4, bessel_5, bessel_6, bessel_7, bessel_8, bessel_9, bessel_10 }; // // Generate Bessel poles for the given order. // static void bessel(int order) { int a; if (order > 10) error("Maximum Bessel order is 10"); n_pol= order; memcpy(pol, bessel_poles[order-1], n_pol * sizeof(double)); for (a= 0; a MAXPZ) error("Maximum butterworth/chebyshev order is %d", MAXPZ); n_pol= order; for (a= 0; a= 0.0) error("Chebyshev ripple in dB should be -ve"); eps= sqrt(-1.0 + pow(10.0, -0.1 * ripple)); y= asinh(1.0 / eps) / order; if (y <= 0.0) error("Internal error; chebyshev y-value <= 0.0: %g", y); sh= sinh(y); ch= cosh(y); for (a= 0; a MAXPZ) error("Maximum order for bandpass filters is %d", MAXPZ/2); // Run through the list backwards, expanding as we go for (a= n_pol, b= n_pol*2; a>0; ) { // hba= pole * bw; // temp= c_sqrt(1.0 - square(w0 / hba)); // pole1= hba * (1.0 + temp); // pole2= hba * (1.0 - temp); if (poltyp[a-1] == 1) { double hba; a--; b -= 2; poltyp[b]= 2; poltyp[b+1]= 0; hba= pol[a] * bw; cassz(pol+b, 1.0 - (w0 / hba) * (w0 / hba), 0.0); c_sqrt(pol+b); caddz(pol+b, 1.0, 0.0); cmulr(pol+b, hba); } else { // Assume poltyp[] data is valid double hba[2]; a -= 2; b -= 4; poltyp[b]= 2; poltyp[b+1]= 0; poltyp[b+2]= 2; poltyp[b+3]= 0; cass(hba, pol+a); cmulr(hba, bw); cass(pol+b, hba); crecip(pol+b); cmulr(pol+b, w0); csqu(pol+b); cneg(pol+b); caddz(pol+b, 1.0, 0.0); c_sqrt(pol+b); cmul(pol+b, hba); cass(pol+b+2, pol+b); cneg(pol+b+2); cadd(pol+b, hba); cadd(pol+b+2, hba); } } n_pol *= 2; // Add zeros n_zer= n_pol; for (a= 0; a MAXPZ) error("Maximum order for bandstop filters is %d", MAXPZ/2); // Run through the list backwards, expanding as we go for (a= n_pol, b= n_pol*2; a>0; ) { // hba= bw / pole; // temp= c_sqrt(1.0 - square(w0 / hba)); // pole1= hba * (1.0 + temp); // pole2= hba * (1.0 - temp); if (poltyp[a-1] == 1) { double hba; a--; b -= 2; poltyp[b]= 2; poltyp[b+1]= 0; hba= bw / pol[a]; cassz(pol+b, 1.0 - (w0 / hba) * (w0 / hba), 0.0); c_sqrt(pol+b); caddz(pol+b, 1.0, 0.0); cmulr(pol+b, hba); } else { // Assume poltyp[] data is valid double hba[2]; a -= 2; b -= 4; poltyp[b]= 2; poltyp[b+1]= 0; poltyp[b+2]= 2; poltyp[b+3]= 0; cass(hba, pol+a); crecip(hba); cmulr(hba, bw); cass(pol+b, hba); crecip(pol+b); cmulr(pol+b, w0); csqu(pol+b); cneg(pol+b); caddz(pol+b, 1.0, 0.0); c_sqrt(pol+b); cmul(pol+b, hba); cass(pol+b+2, pol+b); cneg(pol+b+2); cadd(pol+b, hba); cadd(pol+b+2, hba); } } n_pol *= 2; // Add zeros n_zer= n_pol; for (a= 0; atyp= 'F'; ff->len= 1; ff->val[0]= gain; ff= FFNEXT(ff); // Output as much as possible as 2x2 IIR/FIR filters for (a= 0; a <= n_pol-2 && a <= n_zer-2; a += 2) { // Look for a pair of values for an IIR if (poltyp[a] == 1 && poltyp[a+1] == 1) { // Two real values ff->typ= 'I'; ff->len= 3; ff->val[0]= 1; ff->val[1]= -(pol[a] + pol[a+1]); ff->val[2]= pol[a] * pol[a+1]; ff= FFNEXT(ff); } else if (poltyp[a] == 2) { // A complex value and its conjugate pair ff->typ= 'I'; ff->len= 3; ff->val[0]= 1; ff->val[1]= -2 * pol[a]; ff->val[2]= pol[a] * pol[a] + pol[a+1] * pol[a+1]; ff= FFNEXT(ff); } else error("Internal error -- bad poltyp[] values for z2fidfilter()"); // Look for a pair of values for an FIR if (zertyp[a] == 1 && zertyp[a+1] == 1) { // Two real values // Skip if constant and 0/0 if (!cbm || zer[a] != 0.0 || zer[a+1] != 0.0) { ff->typ= 'F'; ff->cbm= cbm; ff->len= 3; ff->val[0]= 1; ff->val[1]= -(zer[a] + zer[a+1]); ff->val[2]= zer[a] * zer[a+1]; ff= FFNEXT(ff); } } else if (zertyp[a] == 2) { // A complex value and its conjugate pair // Skip if constant and 0/0 if (!cbm || zer[a] != 0.0 || zer[a+1] != 0.0) { ff->typ= 'F'; ff->cbm= cbm; ff->len= 3; ff->val[0]= 1; ff->val[1]= -2 * zer[a]; ff->val[2]= zer[a] * zer[a] + zer[a+1] * zer[a+1]; ff= FFNEXT(ff); } } else error("Internal error -- bad zertyp[] values"); } // Clear up any remaining bits and pieces. Should only be a 1x1 // IIR/FIR. if (n_pol-a == 0 && n_zer-a == 0) ; else if (n_pol-a == 1 && n_zer-a == 1) { if (poltyp[a] != 1 || zertyp[a] != 1) error("Internal error; bad poltyp or zertyp for final pole/zero"); ff->typ= 'I'; ff->len= 2; ff->val[0]= 1; ff->val[1]= -pol[a]; ff= FFNEXT(ff); // Skip FIR if it is constant and zero if (!cbm || zer[a] != 0.0) { ff->typ= 'F'; ff->cbm= cbm; ff->len= 2; ff->val[0]= 1; ff->val[1]= -zer[a]; ff= FFNEXT(ff); } } else error("Internal error: unexpected poles/zeros at end of list"); // End of list ff->typ= 0; ff->len= 0; ff= FFNEXT(ff); rv= realloc(rv, ((char*)ff)-((char*)rv)); if (!rv) error("Out of memory"); return rv; } // // Setup poles/zeros for a band-pass resonator. 'qfact' gives // the Q-factor; 0 is a special value indicating +infinity, // giving an oscillator. // static void bandpass_res(double freq, double qfact) { double mag; double th0, th1, th2; double theta= freq * TWOPI; double val[2]; double tmp1[2], tmp2[2], tmp3[2], tmp4[2]; int cnt; n_pol= 2; poltyp[0]= 2; poltyp[1]= 0; n_zer= 2; zertyp[0]= 1; zertyp[1]= 1; zer[0]= 1; zer[1]= -1; if (qfact == 0.0) { cexpj(pol, theta); return; } // Do a full binary search, rather than seeding it as Tony Fisher does cexpj(val, theta); mag= exp(-theta / (2.0 * qfact)); th0= 0; th2= M_PI; for (cnt= 60; cnt > 0; cnt--) { th1= 0.5 * (th0 + th2); cexpj(pol, th1); cmulr(pol, mag); // Evaluate response of filter for Z= val memcpy(tmp1, val, 2*sizeof(double)); memcpy(tmp2, val, 2*sizeof(double)); memcpy(tmp3, val, 2*sizeof(double)); memcpy(tmp4, val, 2*sizeof(double)); csubz(tmp1, 1, 0); csubz(tmp2, -1, 0); cmul(tmp1, tmp2); csub(tmp3, pol); cconj(pol); csub(tmp4, pol); cconj(pol); cmul(tmp3, tmp4); cdiv(tmp1, tmp3); if (fabs(tmp1[1] / tmp1[0]) < 1e-10) break; //printf("%-24.16g%-24.16g -> %-24.16g%-24.16g\n", th0, th2, tmp1[0], tmp1[1]); if (tmp1[1] > 0.0) th2= th1; else th0= th1; } if (cnt <= 0) fprintf(stderr, "Resonator binary search failed to converge"); } // // Setup poles/zeros for a bandstop resonator // static void bandstop_res(double freq, double qfact) { bandpass_res(freq, qfact); zertyp[0]= 2; zertyp[1]= 0; cexpj(zer, TWOPI * freq); } // // Setup poles/zeros for an allpass resonator // static void allpass_res(double freq, double qfact) { bandpass_res(freq, qfact); zertyp[0]= 2; zertyp[1]= 0; memcpy(zer, pol, 2*sizeof(double)); cmulr(zer, 1.0 / (zer[0]*zer[0] + zer[1]*zer[1])); } // // Setup poles/zeros for a proportional-integral filter // static void prop_integral(double freq) { n_pol= 1; poltyp[0]= 1; pol[0]= 0.0; n_zer= 1; zertyp[0]= 1; zer[0]= -TWOPI * freq; } // END // edfbrowser_157_source/third_party/fidlib/PaxHeaders.7921/fidlib.h0000644000000000000000000000013212646460742022052 xustar0030 mtime=1452958178.234246777 30 atime=1452958178.234246777 30 ctime=1452958178.234246777 edfbrowser_157_source/third_party/fidlib/fidlib.h0000644000175000001440000000545412646460742022423 0ustar00guvusers00000000000000// // fidlib include file // #ifndef FIDLIB_INCLUDED #define FIDLIB_INCLUDED typedef struct FidFilter FidFilter; struct FidFilter { short typ; // Type of filter element 'I' IIR, 'F' FIR, or 0 for end of list short cbm; // Constant bitmap. Bits 0..14, if set, indicate that val[0..14] // is a constant across changes in frequency for this filter type // Bit 15, if set, indicates that val[15..inf] are constant. int len; // Number of doubles stored in val[], or 0 for end of list double val[1]; }; // Lets you write: for (; ff->typ; ff= FFNEXT(ff)) { ... } #define FFNEXT(ff) ((FidFilter*)((ff)->val + (ff)->len)) // Size of a sub-filter with 'cnt' double values attached #define FFSIZE(cnt) (sizeof(FidFilter) + ((cnt)-1)*sizeof(double)) // Size required for the memory chunk to contain the given number // headers and values, plus termination #define FFCSIZE(n_head,n_val) ((sizeof(FidFilter)-sizeof(double))*((n_head)+1) + sizeof(double)*(n_val)) // Allocate the chunk of memory to hold a list of FidFilters, with // n_head FidFilters and n_val total double values in the whole list. // Includes space for the final termination, and zeros the memory. #define FFALLOC(n_head,n_val) (FidFilter*)Alloc(FFCSIZE(n_head, n_val)) // These are so you can use easier names to refer to running filters typedef void FidRun; typedef double (FidFunc)(void*, double); // // Prototypes // #ifdef __cplusplus extern "C" { #endif extern void fid_set_error_handler(void(*rout)(char *)); extern char *fid_version(); extern double fid_response_pha(FidFilter *filt, double freq, double *phase); extern double fid_response(FidFilter *filt, double freq); extern int fid_calc_delay(FidFilter *filt); extern FidFilter *fid_design(char *spec, double rate, double freq0, double freq1, int f_adj, char **descp); extern double fid_design_coef(double *coef, int n_coef, char *spec, double rate, double freq0, double freq1, int adj); extern void fid_list_filters(FILE *out); extern int fid_list_filters_buf(char *buf, char *bufend); extern FidFilter *fid_flatten(FidFilter *filt); extern void fid_rewrite_spec(char *spec, double freq0, double freq1, int adj, char **spec1p, char **spec2p, double *freq0p, double *freq1p, int *adjp); extern FidFilter *fid_cv_array(double *arr); extern FidFilter *fid_cat(int freeme, ...); extern char *fid_parse(double rate, char **pp, FidFilter **ffp); // // Filter running prototypes // extern void *fid_run_new(FidFilter *filt, double(**funcpp)(void *, double)); extern void *fid_run_newbuf(void *run); extern int fid_run_bufsize(void *run); extern void fid_run_initbuf(void *run, void *buf); extern void fid_run_zapbuf(void *buf); extern void fid_run_freebuf(void *runbuf); extern void fid_run_free(void *run); #ifdef __cplusplus } /* extern "C" */ #endif #endif edfbrowser_157_source/third_party/fidlib/PaxHeaders.7921/fidlib.c0000644000000000000000000000013212646460742022045 xustar0030 mtime=1452958178.234246777 30 atime=1452958178.234246777 30 ctime=1452958178.234246777 edfbrowser_157_source/third_party/fidlib/fidlib.c0000644000175000001440000017224312646460742022417 0ustar00guvusers00000000000000// // Fidlib digital filter designer code // ----------------------------------- // // Copyright (c) 2002-2004 Jim Peters . This // file is released under the GNU Lesser General Public License // (LGPL) version 2.1 as published by the Free Software // Foundation. See the file COPYING_LIB for details, or visit // . // // The code in this file was written to go with the Fiview app // (http://uazu.net/fiview/), but it may be used as a library for // other applications. The idea behind this library is to allow // filters to be designed at run-time, which gives much greater // flexibility to filtering applications. // // This file depends on the fidmkf.h file which provides the // filter types from Tony Fisher's 'mkfilter' package. See that // file for references and links used there. // // // Here are some of the sources I used whilst writing this code: // // Robert Bristow-Johnson's EQ cookbook formulae: // http://www.harmony-central.com/Computer/Programming/Audio-EQ-Cookbook.txt // #define VERSION "0.9.10" // // Filter specification string // --------------------------- // // The filter specification string can be used to completely // specify the filter, or it can be used with the frequency or // frequency range missing, in which case default values are // picked up from values passed directly to the routine. // // The spec consists of a series of letters usually followed by // the order of the filter and then by any other parameters // required, preceded by slashes. For example: // // LpBu4/20.4 Lowpass butterworth, 4th order, -3.01dB at 20.4Hz // BpBu2/3-4 Bandpass butterworth, 2nd order, from 3 to 4Hz // BpBu2/=3-4 Same filter, but adjusted exactly to the range given // BsRe/1000/10 Bandstop resonator, Q=1000, frequency 10Hz // // The routines fid_design() or fid_parse() are used to convert // this spec-string into filter coefficients and a description // (if required). // // // Typical usage: // ------------- // // FidFilter *filt, *filt2; // char *desc; // FidRun *run; // FidFunc *funcp; // void *fbuf1, *fbuf2; // int delay; // void my_error_func(char *err); // // // Design a filter, and optionally get its long description // filt= fid_design(spec, rate, freq0, freq1, adj, &desc); // // // List all the possible filter types // fid_list_filters(stdout); // okay= fid_list_filters_buf(buf, buf+sizeof(buf)); // // // Calculate the response of the filter at a given frequency // // (frequency is given as a proportion of the sampling rate, in // // the range 0 to 0.5). If phase is returned, then this is // // given in the range 0 to 1 (for 0 to 2*pi). // resp= fid_response(filt, freq); // resp= fid_response_pha(filt, freq, &phase); // // // Estimate the signal delay caused by a particular filter, in samples // delay= fid_calc_delay(filt); // // // Run a given filter (this will do JIT filter compilation if this is // // implemented for this processor / OS) // run= fid_run_new(filt, &funcp); // fbuf1= fid_run_newbuf(run); // fbuf2= fid_run_newbuf(run); // while (...) { // out_1= funcp(fbuf1, in_1); // out_2= funcp(fbuf2, in_2); // if (restart_required) fid_run_zapbuf(fbuf1); // ... // } // fid_run_freebuf(fbuf2); // fid_run_freebuf(fbuf1); // fid_run_free(run); // // // If you need to allocate your own buffers separately for some // // reason, then do it this way: // run= fid_run_new(filt, &funcp); // len= fid_run_bufsize(run); // fbuf1= Alloc(len); fid_run_initbuf(run, fbuf1); // fbuf2= Alloc(len); fid_run_initbuf(run, fbuf2); // while (...) { // out_1= funcp(fbuf1, in_1); // out_2= funcp(fbuf2, in_2); // if (restart_required) fid_run_zapbuf(fbuf1); // ... // } // free(fbuf2); // free(fbuf1); // fid_run_free(run); // // // Convert an arbitrary filter into a new filter which is a single // // IIR/FIR pair. This is done by convolving the coefficients. This // // flattened filter will give the same result, in theory. However, // // in practice this will be less accurate, especially in cases where // // the limits of the floating point format are being reached (e.g. // // subtracting numbers with small highly significant differences). // // The routine also ensures that the IIR first coefficient is 1.0. // filt2= fid_flatten(filt); // free(filt); // // // Parse an entire filter-spec string possibly containing several FIR, // // IIR and predefined filters and return it as a FidFilter at the given // // location. Stops at the first ,; or unmatched )]} character, or the end // // of the string. Returns a strdup'd error string on error, or else 0. // err= fid_parse(double rate, char **pp, FidFilter **ffp); // // // Set up your own fatal-error handler (default is to dump a message // // to STDERR and exit on fatal conditions) // fid_set_error_handler(&my_error_func); // // // Get the version number of the library as a string (e.g. "1.0.0") // txt= fid_version(); // // // Design a filter and reduce it to a list of all the non-const // // coefficients, which is returned in the given double[]. The number // // of coefficients expected must be provided (as a check). // #define N_COEF // double coef[N_COEF], gain; // gain= fid_design_coef(coef, N_COEF, spec, rate, freq0, freq1, adj); // // // Rewrite a filter spec in a full and/or separated-out form // char *full, *min; // double minf0, minf1; // int minadj; // fid_rewrite_spec(spec, freq0, freq1, adj, &full, &min, &minf0, &minf1, &minadj); // ... // free(full); free(min); // // // Create a FidFilter based on coefficients provided in the // // given double array. // static double array[]= { 'I', 3, 1.0, 0.55, 0.77, 'F', 3, 1, -2, 1, 0 }; // filt= fid_cv_array(array); // // // Join a number of filters into a single filter (and free them too, // // if the first argument is 1) // filt= fid_cat(0, filt1, filt2, filt3, filt4, 0); // // // // Format of returned filter // ------------------------- // // The filter returned is a single chunk of allocated memory in // which is stored a number of FidFilter instances. Each // instance has variable length according to the coefficients // contained in it. It is probably easier to think of this as a // stream of items in memory. Each sub-filter starts with its // type as a short -- either 'I' for IIR filters, or 'F' for FIR // filters. (Other types may be added later, e.g. AM modulation // elements, or whatever). This is followed by a short bitmap // which indicates which of the coefficients are constants, // aiding code-generation. Next comes the count of the following // coefficients, as an int. (These header fields normally takes 8 // bytes, the same as a double, but this might depend on the // platform). Then follow the coefficients, as doubles. The next // sub-filter follows on straight after that. The end of the list // is marked by 8 zero bytes, meaning typ==0, cbm==0 and len==0. // // The filter can be read with the aid of the FidFilter structure // (giving typ, cbm, len and val[] elements) and the FFNEXT() // macro: using ff= FFNEXT(ff) steps to the next FidFilter // structure along the chain. // // Note that within the sub-filters, coefficients are listed in // the order that they apply to data, from current-sample // backwards in time, i.e. most recent first (so an FIR val[] of // 0, 0, 1 represents a two-sample delay FIR filter). IIR // filters are *not* necessarily adjusted so that their first // coefficient is 1. // // Most filters have their gain pre-adjusted so that some // suitable part of the response is at gain==1.0. However, this // depends on the filter type. // // // Check that a target macro has been set. This macro selects // various fixes required on various platforms: // // T_LINUX Linux, or probably any UNIX-like platform with GCC // T_MINGW MinGW -- either building on Win32 or cross-compiling // T_MSVC Microsoft Visual C // // (On MSVC, add "T_MSVC" to the preprocessor definitions in the // project settings, or add /D "T_MSVC" to the compiler // command-line.) // #ifdef __MINGW32__ #define T_MINGW #else #define T_LINUX #endif #ifndef T_LINUX #ifndef T_MINGW #ifndef T_MSVC #error Please define one of the T_* target macros (e.g. -DT_LINUX); see fidlib.c #endif #endif #endif // // Select which method of filter execution is preferred. // RF_CMDLIST is recommended (and is the default). // // RF_COMBINED -- easy to understand code, lower accuracy // RF_CMDLIST -- faster pre-compiled code // RF_JIT -- fastest JIT run-time generated code (no longer supported) // #ifndef RF_COMBINED #ifndef RF_CMDLIST #ifndef RF_JIT #define RF_CMDLIST #endif #endif #endif // // Includes // #include #include #include #include #include #include #include "fidlib.h" #ifndef M_PI #define M_PI 3.14159265358979323846 #endif extern FidFilter *mkfilter(char *, ...); // // Target-specific fixes // // Macro for local inline routines that shouldn't be visible externally #ifdef T_MSVC #define STATIC_INLINE static __inline #else #define STATIC_INLINE static inline #endif // MinGW and MSVC fixes #if defined(T_MINGW) || defined(T_MSVC) #ifndef vsnprintf #define vsnprintf _vsnprintf #endif #ifndef snprintf #define snprintf _snprintf #endif // Not sure if we strictly need this still STATIC_INLINE double my_asinh(double val) { return log(val + sqrt(val*val + 1.0)); } #define asinh(xx) my_asinh(xx) #endif // // Support code // static void (*error_handler)(char *err)= 0; static void error(char *fmt, ...) { char buf[1024]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); // Ignore overflow buf[sizeof(buf)-1]= 0; if (error_handler) error_handler(buf); // If error handler routine returns, we dump to STDERR and exit anyway fprintf(stderr, "fidlib error: %s\n", buf); exit(1); } static char * strdupf(char *fmt, ...) { va_list ap; char buf[1024], *rv; int len; va_start(ap, fmt); len= vsnprintf(buf, sizeof(buf), fmt, ap); if (len < 0 || len >= sizeof(buf)-1) error("strdupf exceeded buffer"); rv= strdup(buf); if (!rv) error("Out of memory"); return rv; } static void * Alloc(int size) { void *vp= calloc(1, size); if (!vp) error("Out of memory"); return vp; } #define ALLOC(type) ((type*)Alloc(sizeof(type))) #define ALLOC_ARR(cnt, type) ((type*)Alloc((cnt) * sizeof(type))) // // Complex multiply: aa *= bb; // STATIC_INLINE void cmul(double *aa, double *bb) { double rr= aa[0] * bb[0] - aa[1] * bb[1]; double ii= aa[0] * bb[1] + aa[1] * bb[0]; aa[0]= rr; aa[1]= ii; } // // Complex square: aa *= aa; // STATIC_INLINE void csqu(double *aa) { double rr= aa[0] * aa[0] - aa[1] * aa[1]; double ii= 2 * aa[0] * aa[1]; aa[0]= rr; aa[1]= ii; } // // Complex multiply by real: aa *= bb; // STATIC_INLINE void cmulr(double *aa, double fact) { aa[0] *= fact; aa[1] *= fact; } // // Complex conjugate: aa= aa* // STATIC_INLINE void cconj(double *aa) { aa[1]= -aa[1]; } // // Complex divide: aa /= bb; // STATIC_INLINE void cdiv(double *aa, double *bb) { double rr= aa[0] * bb[0] + aa[1] * bb[1]; double ii= -aa[0] * bb[1] + aa[1] * bb[0]; double fact= 1.0 / (bb[0] * bb[0] + bb[1] * bb[1]); aa[0]= rr * fact; aa[1]= ii * fact; } // // Complex reciprocal: aa= 1/aa // STATIC_INLINE void crecip(double *aa) { double fact= 1.0 / (aa[0] * aa[0] + aa[1] * aa[1]); aa[0] *= fact; aa[1] *= -fact; } // // Complex assign: aa= bb // STATIC_INLINE void cass(double *aa, double *bb) { memcpy(aa, bb, 2*sizeof(double)); // Assigning doubles is really slow } // // Complex assign: aa= (rr + ii*j) // STATIC_INLINE void cassz(double *aa, double rr, double ii) { aa[0]= rr; aa[1]= ii; } // // Complex add: aa += bb // STATIC_INLINE void cadd(double *aa, double *bb) { aa[0] += bb[0]; aa[1] += bb[1]; } // // Complex add: aa += (rr + ii*j) // STATIC_INLINE void caddz(double *aa, double rr, double ii) { aa[0] += rr; aa[1] += ii; } // // Complex subtract: aa -= bb // STATIC_INLINE void csub(double *aa, double *bb) { aa[0] -= bb[0]; aa[1] -= bb[1]; } // // Complex subtract: aa -= (rr + ii*j) // STATIC_INLINE void csubz(double *aa, double rr, double ii) { aa[0] -= rr; aa[1] -= ii; } // // Complex negate: aa= -aa // STATIC_INLINE void cneg(double *aa) { aa[0]= -aa[0]; aa[1]= -aa[1]; } // // Evaluate a complex polynomial given the coefficients. // rv[0]+i*rv[1] is the result, in[0]+i*in[1] is the input value. // Coefficients are real values. // STATIC_INLINE void evaluate(double *rv, double *coef, int n_coef, double *in) { double pz[2]; // Powers of Z // Handle first iteration by hand rv[0]= *coef++; rv[1]= 0; if (--n_coef > 0) { // Handle second iteration by hand pz[0]= in[0]; pz[1]= in[1]; rv[0] += *coef * pz[0]; rv[1] += *coef * pz[1]; coef++; n_coef--; // Loop for remainder while (n_coef > 0) { cmul(pz, in); rv[0] += *coef * pz[0]; rv[1] += *coef * pz[1]; coef++; n_coef--; } } } // // Housekeeping // void fid_set_error_handler(void (*rout)(char*)) { error_handler= rout; } char * fid_version() { return VERSION; } // // Get the response and phase of a filter at the given frequency // (expressed as a proportion of the sampling rate, 0->0.5). // Phase is returned as a number from 0 to 1, representing a // phase between 0 and two-pi. // double fid_response_pha(FidFilter *filt, double freq, double *phase) { double top[2], bot[2]; double theta= freq * 2 * M_PI; double zz[2]; top[0]= 1; top[1]= 0; bot[0]= 1; bot[1]= 0; zz[0]= cos(theta); zz[1]= sin(theta); while (filt->len) { double resp[2]; int cnt= filt->len; evaluate(resp, filt->val, cnt, zz); if (filt->typ == 'I') cmul(bot, resp); else if (filt->typ == 'F') cmul(top, resp); else error("Unknown filter type %d in fid_response_pha()", filt->typ); filt= FFNEXT(filt); } cdiv(top, bot); if (phase) { double pha= atan2(top[1], top[0]) / (2 * M_PI); if (pha < 0) pha += 1.0; *phase= pha; } return hypot(top[1], top[0]); } // // Get the response of a filter at the given frequency (expressed // as a proportion of the sampling rate, 0->0.5). // // Code duplicate, as I didn't want the overhead of a function // call to fid_response_pha. Almost every call in this routine // can be inlined. // double fid_response(FidFilter *filt, double freq) { double top[2], bot[2]; double theta= freq * 2 * M_PI; double zz[2]; top[0]= 1; top[1]= 0; bot[0]= 1; bot[1]= 0; zz[0]= cos(theta); zz[1]= sin(theta); while (filt->len) { double resp[2]; int cnt= filt->len; evaluate(resp, filt->val, cnt, zz); if (filt->typ == 'I') cmul(bot, resp); else if (filt->typ == 'F') cmul(top, resp); else error("Unknown filter type %d in fid_response()", filt->typ); filt= FFNEXT(filt); } cdiv(top, bot); return hypot(top[1], top[0]); } // // Estimate the delay that a filter causes to the signal by // looking for the point at which 50% of the filter calculations // are complete. This involves running test impulses through the // filter several times. The estimated delay in samples is // returned. // // Delays longer than 8,000,000 samples are not handled well, as // the code drops out at this point rather than get stuck in an // endless loop. // int fid_calc_delay(FidFilter *filt) { FidRun *run; FidFunc *dostep; void *f1, *f2; double tot, tot100, tot50; int cnt; run= fid_run_new(filt, &dostep); // Run through to find at least the 99.9% point of filter; the r2 // (tot100) filter runs at 4x the speed of the other one to act as // a reference point much further ahead in the impulse response. f1= fid_run_newbuf(run); f2= fid_run_newbuf(run); tot= fabs(dostep(f1, 1.0)); tot100= fabs(dostep(f2, 1.0)); tot100 += fabs(dostep(f2, 0.0)); tot100 += fabs(dostep(f2, 0.0)); tot100 += fabs(dostep(f2, 0.0)); for (cnt= 1; cnt < 0x1000000; cnt++) { tot += fabs(dostep(f1, 0.0)); tot100 += fabs(dostep(f2, 0.0)); tot100 += fabs(dostep(f2, 0.0)); tot100 += fabs(dostep(f2, 0.0)); tot100 += fabs(dostep(f2, 0.0)); if (tot/tot100 >= 0.999) break; } fid_run_freebuf(f1); fid_run_freebuf(f2); // Now find the 50% point tot50= tot100/2; f1= fid_run_newbuf(run); tot= fabs(dostep(f1, 1.0)); for (cnt= 0; tot < tot50; cnt++) tot += fabs(dostep(f1, 0.0)); fid_run_freebuf(f1); // Clean up, return fid_run_free(run); return cnt; } // // 'mkfilter'-derived code // #include "fidmkf.h" // // Stack a number of identical filters, generating the required // FidFilter* return value // static FidFilter* stack_filter(int order, int n_head, int n_val, ...) { FidFilter *rv= FFALLOC(n_head * order, n_val * order); FidFilter *p, *q; va_list ap; int a, b, len; if (order == 0) return rv; // Copy from ap va_start(ap, n_val); p= q= rv; for (a= 0; atyp= va_arg(ap, int); p->cbm= va_arg(ap, int); p->len= va_arg(ap, int); for (b= 0; blen; b++) p->val[b]= va_arg(ap, double); p= FFNEXT(p); } order--; // Check length len= ((char*)p)-((char*)q); if (len != FFCSIZE(n_head-1, n_val)) error("Internal error; bad call to stack_filter(); length mismatch (%d,%d)", len, FFCSIZE(n_head-1, n_val)); // Make as many additional copies as necessary while (order-- > 0) { memcpy(p, q, len); p= (void*)(len + (char*)p); } // List is already terminated due to zeroed allocation return rv; } // // Search for a peak between two given frequencies. It is // assumed that the gradient goes upwards from 'f0' to the peak, // and then down again to 'f3'. If there are any other curves, // this routine will get confused and will come up with some // frequency, although probably not the right one. // // Returns the frequency of the peak. // static double search_peak(FidFilter *ff, double f0, double f3) { double f1, f2; double r1, r2; int a; // Binary search, modified, taking two intermediate points. Do 20 // subdivisions, which should give 1/2^20 == 1e-6 accuracy compared // to original range. for (a= 0; a<20; a++) { f1= 0.51 * f0 + 0.49 * f3; f2= 0.49 * f0 + 0.51 * f3; if (f1 == f2) break; // We're hitting FP limit r1= fid_response(ff, f1); r2= fid_response(ff, f2); if (r1 > r2) // Peak is either to the left, or between f1/f2 f3= f2; else // Peak is either to the right, or between f1/f2 f0= f1; } return (f0+f3)*0.5; } // // Handle the different 'back-ends' for Bessel, Butterworth and // Chebyshev filters. First argument selects between bilinear // (0) and matched-Z (non-0). The BL and MZ macros makes this a // bit more obvious in the code. // // Overall filter gain is adjusted to give the peak at 1.0. This // is easy for all types except for band-pass, where a search is // required to find the precise peak. This is much slower than // the other types. // #define BL 0 #define MZ 1 static FidFilter* do_lowpass(int mz, double freq) { FidFilter *rv; lowpass(prewarp(freq)); if (mz) s2z_matchedZ(); else s2z_bilinear(); rv= z2fidfilter(1.0, ~0); // FIR is constant rv->val[0]= 1.0 / fid_response(rv, 0.0); return rv; } static FidFilter* do_highpass(int mz, double freq) { FidFilter *rv; highpass(prewarp(freq)); if (mz) s2z_matchedZ(); else s2z_bilinear(); rv= z2fidfilter(1.0, ~0); // FIR is constant rv->val[0]= 1.0 / fid_response(rv, 0.5); return rv; } static FidFilter* do_bandpass(int mz, double f0, double f1) { FidFilter *rv; bandpass(prewarp(f0), prewarp(f1)); if (mz) s2z_matchedZ(); else s2z_bilinear(); rv= z2fidfilter(1.0, ~0); // FIR is constant rv->val[0]= 1.0 / fid_response(rv, search_peak(rv, f0, f1)); return rv; } static FidFilter* do_bandstop(int mz, double f0, double f1) { FidFilter *rv; bandstop(prewarp(f0), prewarp(f1)); if (mz) s2z_matchedZ(); else s2z_bilinear(); rv= z2fidfilter(1.0, 5); // FIR second coefficient is *non-const* for bandstop rv->val[0]= 1.0 / fid_response(rv, 0.0); // Use 0Hz response as reference return rv; } // // Information passed to individual filter design routines: // // double* rout(double rate, double f0, double f1, // int order, int n_arg, double *arg); // // 'rate' is the sampling rate, or 1 if not set // 'f0' and 'f1' give the frequency or frequency range as a // proportion of the sampling rate // 'order' is the order of the filter (the integer passed immediately // after the name) // 'n_arg' is the number of additional arguments for the filter // 'arg' gives the additional argument values: arg[n] // // Note that #O #o #F and #R are mapped to the f0/f1/order // arguments, and are not included in the arg[] array. // // See the previous description for the required meaning of the // return value FidFilter list. // // // Filter design routines and supporting code // static FidFilter* des_bpre(double rate, double f0, double f1, int order, int n_arg, double *arg) { bandpass_res(f0, arg[0]); return z2fidfilter(1.0, ~0); // FIR constant } static FidFilter* des_bsre(double rate, double f0, double f1, int order, int n_arg, double *arg) { bandstop_res(f0, arg[0]); return z2fidfilter(1.0, 0); // FIR not constant, depends on freq } static FidFilter* des_apre(double rate, double f0, double f1, int order, int n_arg, double *arg) { allpass_res(f0, arg[0]); return z2fidfilter(1.0, 0); // FIR not constant, depends on freq } static FidFilter* des_pi(double rate, double f0, double f1, int order, int n_arg, double *arg) { prop_integral(prewarp(f0)); s2z_bilinear(); return z2fidfilter(1.0, 0); // FIR not constant, depends on freq } static FidFilter* des_piz(double rate, double f0, double f1, int order, int n_arg, double *arg) { prop_integral(prewarp(f0)); s2z_matchedZ(); return z2fidfilter(1.0, 0); // FIR not constant, depends on freq } static FidFilter* des_lpbe(double rate, double f0, double f1, int order, int n_arg, double *arg) { bessel(order); return do_lowpass(BL, f0); } static FidFilter* des_hpbe(double rate, double f0, double f1, int order, int n_arg, double *arg) { bessel(order); return do_highpass(BL, f0); } static FidFilter* des_bpbe(double rate, double f0, double f1, int order, int n_arg, double *arg) { bessel(order); return do_bandpass(BL, f0, f1); } static FidFilter* des_bsbe(double rate, double f0, double f1, int order, int n_arg, double *arg) { bessel(order); return do_bandstop(BL, f0, f1); } static FidFilter* des_lpbez(double rate, double f0, double f1, int order, int n_arg, double *arg) { bessel(order); return do_lowpass(MZ, f0); } static FidFilter* des_hpbez(double rate, double f0, double f1, int order, int n_arg, double *arg) { bessel(order); return do_highpass(MZ, f0); } static FidFilter* des_bpbez(double rate, double f0, double f1, int order, int n_arg, double *arg) { bessel(order); return do_bandpass(MZ, f0, f1); } static FidFilter* des_bsbez(double rate, double f0, double f1, int order, int n_arg, double *arg) { bessel(order); return do_bandstop(MZ, f0, f1); } static FidFilter* // Butterworth-Bessel cross des_lpbube(double rate, double f0, double f1, int order, int n_arg, double *arg) { double tmp[MAXPZ]; int a; bessel(order); memcpy(tmp, pol, order * sizeof(double)); butterworth(order); for (a= 0; atyp= 'F'; ff->cbm= 0; ff->len= max*2+1; ff->val[max]= tot= 1.0; for (a= 1; a<=max; a++) { double val= 0.42 + 0.5 * cos(M_PI * a / wid) + 0.08 * cos(M_PI * 2.0 * a / wid); ff->val[max-a]= val; ff->val[max+a]= val; tot += val * 2.0; } adj= 1/tot; for (a= 0; a<=max*2; a++) ff->val[a] *= adj; return ff; } static FidFilter* des_lphm(double rate, double f0, double f1, int order, int n_arg, double *arg) { double wid= 0.3262096/f0; double tot, adj; int max= (int)floor(wid); int a; FidFilter *ff= Alloc(FFCSIZE(1, max*2+1)); ff->typ= 'F'; ff->cbm= 0; ff->len= max*2+1; ff->val[max]= tot= 1.0; for (a= 1; a<=max; a++) { double val= 0.54 + 0.46 * cos(M_PI * a / wid); ff->val[max-a]= val; ff->val[max+a]= val; tot += val * 2.0; } adj= 1/tot; for (a= 0; a<=max*2; a++) ff->val[a] *= adj; return ff; } static FidFilter* des_lphn(double rate, double f0, double f1, int order, int n_arg, double *arg) { double wid= 0.360144/f0; double tot, adj; int max= (int)floor(wid); int a; FidFilter *ff= Alloc(FFCSIZE(1, max*2+1)); ff->typ= 'F'; ff->cbm= 0; ff->len= max*2+1; ff->val[max]= tot= 1.0; for (a= 1; a<=max; a++) { double val= 0.5 + 0.5 * cos(M_PI * a / wid); ff->val[max-a]= val; ff->val[max+a]= val; tot += val * 2.0; } adj= 1/tot; for (a= 0; a<=max*2; a++) ff->val[a] *= adj; return ff; } static FidFilter* des_lpba(double rate, double f0, double f1, int order, int n_arg, double *arg) { double wid= 0.3189435/f0; double tot, adj; int max= (int)floor(wid); int a; FidFilter *ff= Alloc(FFCSIZE(1, max*2+1)); ff->typ= 'F'; ff->cbm= 0; ff->len= max*2+1; ff->val[max]= tot= 1.0; for (a= 1; a<=max; a++) { double val= 1.0 - a/wid; ff->val[max-a]= val; ff->val[max+a]= val; tot += val * 2.0; } adj= 1/tot; for (a= 0; a<=max*2; a++) ff->val[a] *= adj; return ff; } // // Filter table // static struct { FidFilter *(*rout)(double,double,double,int,int,double*); // Designer routine address char *fmt; // Format for spec-string char *txt; // Human-readable description of filter } filter[]= { { des_bpre, "BpRe/#V/#F", "Bandpass resonator, Q=#V (0 means Inf), frequency #F" }, { des_bsre, "BsRe/#V/#F", "Bandstop resonator, Q=#V (0 means Inf), frequency #F" }, { des_apre, "ApRe/#V/#F", "Allpass resonator, Q=#V (0 means Inf), frequency #F" }, { des_pi, "Pi/#F", "Proportional-integral filter, frequency #F" }, { des_piz, "PiZ/#F", "Proportional-integral filter, matched z-transform, frequency #F" }, { des_lpbe, "LpBe#O/#F", "Lowpass Bessel filter, order #O, -3.01dB frequency #F" }, { des_hpbe, "HpBe#O/#F", "Highpass Bessel filter, order #O, -3.01dB frequency #F" }, { des_bpbe, "BpBe#O/#R", "Bandpass Bessel filter, order #O, -3.01dB frequencies #R" }, { des_bsbe, "BsBe#O/#R", "Bandstop Bessel filter, order #O, -3.01dB frequencies #R" }, { des_lpbu, "LpBu#O/#F", "Lowpass Butterworth filter, order #O, -3.01dB frequency #F" }, { des_hpbu, "HpBu#O/#F", "Highpass Butterworth filter, order #O, -3.01dB frequency #F" }, { des_bpbu, "BpBu#O/#R", "Bandpass Butterworth filter, order #O, -3.01dB frequencies #R" }, { des_bsbu, "BsBu#O/#R", "Bandstop Butterworth filter, order #O, -3.01dB frequencies #R" }, { des_lpch, "LpCh#O/#V/#F", "Lowpass Chebyshev filter, order #O, passband ripple #VdB, -3.01dB frequency #F" }, { des_hpch, "HpCh#O/#V/#F", "Highpass Chebyshev filter, order #O, passband ripple #VdB, -3.01dB frequency #F" }, { des_bpch, "BpCh#O/#V/#R", "Bandpass Chebyshev filter, order #O, passband ripple #VdB, -3.01dB frequencies #R" }, { des_bsch, "BsCh#O/#V/#R", "Bandstop Chebyshev filter, order #O, passband ripple #VdB, -3.01dB frequencies #R" }, { des_lpbez, "LpBeZ#O/#F", "Lowpass Bessel filter, matched z-transform, order #O, -3.01dB frequency #F" }, { des_hpbez, "HpBeZ#O/#F", "Highpass Bessel filter, matched z-transform, order #O, -3.01dB frequency #F" }, { des_bpbez, "BpBeZ#O/#R", "Bandpass Bessel filter, matched z-transform, order #O, -3.01dB frequencies #R" }, { des_bsbez, "BsBeZ#O/#R", "Bandstop Bessel filter, matched z-transform, order #O, -3.01dB frequencies #R" }, { des_lpbuz, "LpBuZ#O/#F", "Lowpass Butterworth filter, matched z-transform, order #O, -3.01dB frequency #F" }, { des_hpbuz, "HpBuZ#O/#F", "Highpass Butterworth filter, matched z-transform, order #O, -3.01dB frequency #F" }, { des_bpbuz, "BpBuZ#O/#R", "Bandpass Butterworth filter, matched z-transform, order #O, -3.01dB frequencies #R" }, { des_bsbuz, "BsBuZ#O/#R", "Bandstop Butterworth filter, matched z-transform, order #O, -3.01dB frequencies #R" }, { des_lpchz, "LpChZ#O/#V/#F", "Lowpass Chebyshev filter, matched z-transform, order #O, " "passband ripple #VdB, -3.01dB frequency #F" }, { des_hpchz, "HpChZ#O/#V/#F", "Highpass Chebyshev filter, matched z-transform, order #O, " "passband ripple #VdB, -3.01dB frequency #F" }, { des_bpchz, "BpChZ#O/#V/#R", "Bandpass Chebyshev filter, matched z-transform, order #O, " "passband ripple #VdB, -3.01dB frequencies #R" }, { des_bschz, "BsChZ#O/#V/#R", "Bandstop Chebyshev filter, matched z-transform, order #O, " "passband ripple #VdB, -3.01dB frequencies #R" }, { des_lpbube, "LpBuBe#O/#V/#F", "Lowpass Butterworth-Bessel #V% cross, order #O, -3.01dB frequency #F" }, { des_lpbq, "LpBq#o/#V/#F", "Lowpass biquad filter, order #O, Q=#V, -3.01dB frequency #F" }, { des_hpbq, "HpBq#o/#V/#F", "Highpass biquad filter, order #O, Q=#V, -3.01dB frequency #F" }, { des_bpbq, "BpBq#o/#V/#F", "Bandpass biquad filter, order #O, Q=#V, centre frequency #F" }, { des_bsbq, "BsBq#o/#V/#F", "Bandstop biquad filter, order #O, Q=#V, centre frequency #F" }, { des_apbq, "ApBq#o/#V/#F", "Allpass biquad filter, order #O, Q=#V, centre frequency #F" }, { des_pkbq, "PkBq#o/#V/#V/#F", "Peaking biquad filter, order #O, Q=#V, dBgain=#V, frequency #F" }, { des_lsbq, "LsBq#o/#V/#V/#F", "Lowpass shelving biquad filter, S=#V, dBgain=#V, frequency #F" }, { des_hsbq, "HsBq#o/#V/#V/#F", "Highpass shelving biquad filter, S=#V, dBgain=#V, frequency #F" }, { des_lpbl, "LpBl/#F", "Lowpass Blackman window, -3.01dB frequency #F" }, { des_lphm, "LpHm/#F", "Lowpass Hamming window, -3.01dB frequency #F" }, { des_lphn, "LpHn/#F", "Lowpass Hann window, -3.01dB frequency #F" }, { des_lpba, "LpBa/#F", "Lowpass Bartlet (triangular) window, -3.01dB frequency #F" }, { 0, 0, 0 } }; // // Design a filter. Spec and range are passed as arguments. The // return value is a pointer to a FidFilter as documented earlier // in this file. This needs to be free()d once finished with. // // If 'f_adj' is set, then the frequencies fed to the design code // are adjusted automatically to get true sqrt(0.5) (-3.01dB) // values at the provided frequencies. (This is obviously a // slower operation) // // If 'descp' is non-0, then a long description of the filter is // generated and returned as a strdup'd string at the given // location. // // Any problem with the spec causes the program to die with an // error message. // // 'spec' gives the specification string. The 'rate' argument // gives the sampling rate for the data that will be passed to // the filter. This is only used to interpret the frequencies // given in the spec or given in 'freq0' and 'freq1'. Use 1.0 if // the frequencies are given as a proportion of the sampling // rate, in the range 0 to 0.5. 'freq0' and 'freq1' provide the // default frequency or frequency range if this is not included // in the specification string. These should be -ve if there is // no default range (causing an error if they are omitted from // the 'spec'). // typedef struct Spec Spec; static char* parse_spec(Spec*); static FidFilter *auto_adjust_single(Spec *sp, double rate, double f0); static FidFilter *auto_adjust_dual(Spec *sp, double rate, double f0, double f1); struct Spec { #define MAXARG 10 char *spec; double in_f0, in_f1; int in_adj; double argarr[MAXARG]; double f0, f1; int adj; int n_arg; int order; int minlen; // Minimum length of spec-string, assuming f0/f1 passed separately int n_freq; // Number of frequencies provided: 0,1,2 int fi; // Filter index (filter[fi]) }; FidFilter * fid_design(char *spec, double rate, double freq0, double freq1, int f_adj, char **descp) { FidFilter *rv; Spec sp; double f0, f1; char *err; // Parse the filter-spec sp.spec= spec; sp.in_f0= freq0; sp.in_f1= freq1; sp.in_adj= f_adj; err= parse_spec(&sp); if (err) error("%s", err); f0= sp.f0; f1= sp.f1; // Adjust frequencies to range 0-0.5, and check them f0 /= rate; if (f0 > 0.5) error("Frequency of %gHz out of range with sampling rate of %gHz", f0*rate, rate); f1 /= rate; if (f1 > 0.5) error("Frequency of %gHz out of range with sampling rate of %gHz", f1*rate, rate); // Okay we now have a successful spec-match to filter[sp.fi], and sp.n_arg // args are now in sp.argarr[] // Generate the filter if (!sp.adj) rv= filter[sp.fi].rout(rate, f0, f1, sp.order, sp.n_arg, sp.argarr); else if (strstr(filter[sp.fi].fmt, "#R")) rv= auto_adjust_dual(&sp, rate, f0, f1); else rv= auto_adjust_single(&sp, rate, f0); // Generate a long description if required if (descp) { char *fmt= filter[sp.fi].txt; int max= strlen(fmt) + 60 + sp.n_arg * 20; char *desc= Alloc(max); char *p= desc; char ch; double *arg= sp.argarr; int n_arg= sp.n_arg; while ((ch= *fmt++)) { if (ch != '#') { *p++= ch; continue; } switch (*fmt++) { case 'O': p += sprintf(p, "%d", sp.order); break; case 'F': p += sprintf(p, "%g", f0*rate); break; case 'R': p += sprintf(p, "%g-%g", f0*rate, f1*rate); break; case 'V': if (n_arg <= 0) error("Internal error -- disagreement between filter short-spec\n" " and long-description over number of arguments"); n_arg--; p += sprintf(p, "%g", *arg++); break; default: error("Internal error: unknown format in long description: #%c", fmt[-1]); } } *p++= 0; if (p-desc >= max) error("Internal error: exceeded estimated description buffer"); *descp= desc; } return rv; } // // Auto-adjust input frequency to give correct sqrt(0.5) // (~-3.01dB) point to 6 figures // #define M301DB (0.707106781186548) static FidFilter * auto_adjust_single(Spec *sp, double rate, double f0) { double a0, a1, a2; FidFilter *(*design)(double,double,double,int,int,double*)= filter[sp->fi].rout; FidFilter *rv= 0; double resp; double r0, r2; int incr; // Increasing (1) or decreasing (0) int a; #define DESIGN(aa) design(rate, aa, aa, sp->order, sp->n_arg, sp->argarr) #define TEST(aa) { if (rv) {free(rv);rv= 0;} rv= DESIGN(aa); resp= fid_response(rv, f0); } // Try and establish a range within which we can find the point a0= f0; TEST(a0); r0= resp; for (a= 2; 1; a*=2) { a2= f0/a; TEST(a2); r2= resp; if ((r0 < M301DB) != (r2 < M301DB)) break; a2= 0.5-((0.5-f0)/a); TEST(a2); r2= resp; if ((r0 < M301DB) != (r2 < M301DB)) break; if (a == 32) // No success error("auto_adjust_single internal error -- can't establish enclosing range"); } incr= r2 > r0; if (a0 > a2) { a1= a0; a0= a2; a2= a1; incr= !incr; } // Binary search while (1) { a1= 0.5 * (a0 + a2); if (a1 == a0 || a1 == a2) break; // Limit of double, sanity check TEST(a1); if (resp >= 0.9999995 * M301DB && resp < 1.0000005 * M301DB) break; if (incr == (resp > M301DB)) a2= a1; else a0= a1; } #undef TEST #undef DESIGN return rv; } // // Auto-adjust input frequencies to give response of sqrt(0.5) // (~-3.01dB) correct to 6sf at the given frequency-points // static FidFilter * auto_adjust_dual(Spec *sp, double rate, double f0, double f1) { double mid= 0.5 * (f0+f1); double wid= 0.5 * fabs(f1-f0); FidFilter *(*design)(double,double,double,int,int,double*)= filter[sp->fi].rout; FidFilter *rv= 0; int bpass= -1; double delta; double mid0, mid1; double wid0, wid1; double r0, r1, err0, err1; double perr; int cnt; int cnt_design= 0; #define DESIGN(mm,ww) { if (rv) {free(rv);rv= 0;} \ rv= design(rate, mm-ww, mm+ww, sp->order, sp->n_arg, sp->argarr); \ r0= fid_response(rv, f0); r1= fid_response(rv, f1); \ err0= fabs(M301DB-r0); err1= fabs(M301DB-r1); cnt_design++; } #define INC_WID ((r0+r1 < 1.0) == bpass) #define INC_MID ((r0 > r1) == bpass) #define MATCH (err0 < 0.000000499 && err1 < 0.000000499) #define PERR (err0+err1) DESIGN(mid, wid); bpass= (fid_response(rv, 0) < 0.5); delta= wid * 0.5; // Try delta changes until we get there for (cnt= 0; 1; cnt++, delta *= 0.51) { DESIGN(mid, wid); // I know -- this is redundant perr= PERR; mid0= mid; wid0= wid; mid1= mid + (INC_MID ? delta : -delta); wid1= wid + (INC_WID ? delta : -delta); if (mid0 - wid1 > 0.0 && mid0 + wid1 < 0.5) { DESIGN(mid0, wid1); if (MATCH) break; if (PERR < perr) { perr= PERR; mid= mid0; wid= wid1; } } if (mid1 - wid0 > 0.0 && mid1 + wid0 < 0.5) { DESIGN(mid1, wid0); if (MATCH) break; if (PERR < perr) { perr= PERR; mid= mid1; wid= wid0; } } if (mid1 - wid1 > 0.0 && mid1 + wid1 < 0.5) { DESIGN(mid1, wid1); if (MATCH) break; if (PERR < perr) { perr= PERR; mid= mid1; wid= wid1; } } if (cnt > 1000) error("auto_adjust_dual -- design not converging"); } #undef INC_WID #undef INC_MID #undef MATCH #undef PERR #undef DESIGN return rv; } // // Expand a specification string to the given buffer; if out of // space, drops dead // static void expand_spec(char *buf, char *bufend, char *str) { int ch; char *p= buf; while ((ch= *str++)) { if (p + 10 >= bufend) error("Buffer overflow in fidlib expand_spec()"); if (ch == '#') { switch (*str++) { case 'o': p += sprintf(p, ""); break; case 'O': p += sprintf(p, ""); break; case 'F': p += sprintf(p, ""); break; case 'R': p += sprintf(p, ""); break; case 'V': p += sprintf(p, ""); break; default: p += sprintf(p, "<%c>", str[-1]); break; } } else { *p++= ch; } } *p= 0; } // // Design a filter and reduce it to a list of all the non-const // coefficients. Arguments are as for fid_filter(). The // coefficients are written into the given double array. If the // number of coefficients doesn't match the array length given, // then a fatal error is generated. // // Note that all 1-element FIRs and IIR first-coefficients are // merged into a single gain coefficient, which is returned // rather than being included in the coefficient list. This is // to allow it to be merged with other gains within a stack of // filters. // // The algorithm used here (merging 1-element FIRs and adjusting // IIR first-coefficients) must match that used in the code- // generating code, or else the coefficients won't match up. The // 'n_coef' argument provides a partial safeguard. // double fid_design_coef(double *coef, int n_coef, char *spec, double rate, double freq0, double freq1, int adj) { FidFilter *filt= fid_design(spec, rate, freq0, freq1, adj, 0); FidFilter *ff= filt; int a, len; int cnt= 0; double gain= 1.0; double *iir, *fir, iir_adj; static double const_one= 1; int n_iir, n_fir; int iir_cbm, fir_cbm; while (ff->typ) { if (ff->typ == 'F' && ff->len == 1) { gain *= ff->val[0]; ff= FFNEXT(ff); continue; } if (ff->typ != 'I' && ff->typ != 'F') error("fid_design_coef can't handle FidFilter type: %c", ff->typ); // Initialise to safe defaults iir= fir= &const_one; n_iir= n_fir= 1; iir_cbm= fir_cbm= ~0; // See if we have an IIR filter if (ff->typ == 'I') { iir= ff->val; n_iir= ff->len; iir_cbm= ff->cbm; iir_adj= 1.0 / ff->val[0]; ff= FFNEXT(ff); gain *= iir_adj; } // See if we have an FIR filter if (ff->typ == 'F') { fir= ff->val; n_fir= ff->len; fir_cbm= ff->cbm; ff= FFNEXT(ff); } // Dump out all non-const coefficients in reverse order len= n_fir > n_iir ? n_fir : n_iir; for (a= len-1; a>=0; a--) { // Output IIR if present and non-const if (a < n_iir && a>0 && !(iir_cbm & (1<<(a<15?a:15)))) { if (cnt++ < n_coef) *coef++= iir_adj * iir[a]; } // Output FIR if present and non-const if (a < n_fir && !(fir_cbm & (1<<(a<15?a:15)))) { if (cnt++ < n_coef) *coef++= fir[a]; } } } if (cnt != n_coef) error("fid_design_coef called with the wrong number of coefficients.\n" " Given %d, expecting %d: (\"%s\",%g,%g,%g,%d)", n_coef, cnt, spec, rate, freq0, freq1, adj); free(filt); return gain; } // // List all the known filters to the given file handle // void fid_list_filters(FILE *out) { int a; for (a= 0; filter[a].fmt; a++) { char buf[4096]; expand_spec(buf, buf+sizeof(buf), filter[a].fmt); fprintf(out, "%s\n ", buf); expand_spec(buf, buf+sizeof(buf), filter[a].txt); fprintf(out, "%s\n", buf); } } // // List all the known filters to the given buffer; the buffer is // NUL-terminated; returns 1 okay, 0 not enough space // int fid_list_filters_buf(char *buf, char *bufend) { int a, cnt; char tmp[4096]; for (a= 0; filter[a].fmt; a++) { expand_spec(tmp, tmp+sizeof(tmp), filter[a].fmt); buf += (cnt= snprintf(buf, bufend-buf, "%s\n ", tmp)); if (cnt < 0 || buf >= bufend) return 0; expand_spec(tmp, tmp+sizeof(tmp), filter[a].txt); buf += (cnt= snprintf(buf, bufend-buf, "%s\n", tmp)); if (cnt < 0 || buf >= bufend) return 0; } return 1; } // // Do a convolution of parameters in place // STATIC_INLINE int convolve(double *dst, int n_dst, double *src, int n_src) { int len= n_dst + n_src - 1; int a, b; for (a= len-1; a>=0; a--) { double val= 0; for (b= 0; b= 0 && a-b < n_dst) val += src[b] * dst[a-b]; dst[a]= val; } return len; } // // Generate a combined filter -- merge all the IIR/FIR // sub-filters into a single IIR/FIR pair, and make sure the IIR // first coefficient is 1.0. // FidFilter * fid_flatten(FidFilter *filt) { int m_fir= 1; // Maximum values int m_iir= 1; int n_fir, n_iir; // Stored counts during convolution FidFilter *ff; FidFilter *rv; double *fir, *iir; double adj; int a; // Find the size of the output filter ff= filt; while (ff->len) { if (ff->typ == 'I') m_iir += ff->len-1; else if (ff->typ == 'F') m_fir += ff->len-1; else error("fid_flatten doesn't know about type %d", ff->typ); ff= FFNEXT(ff); } // Setup the output array rv= FFALLOC(2, m_iir + m_fir); rv->typ= 'I'; rv->len= m_iir; iir= rv->val; ff= FFNEXT(rv); ff->typ= 'F'; ff->len= m_fir; fir= ff->val; iir[0]= 1.0; n_iir= 1; fir[0]= 1.0; n_fir= 1; // Do the convolution ff= filt; while (ff->len) { if (ff->typ == 'I') n_iir= convolve(iir, n_iir, ff->val, ff->len); else n_fir= convolve(fir, n_fir, ff->val, ff->len); ff= FFNEXT(ff); } // Sanity check if (n_iir != m_iir || n_fir != m_fir) error("Internal error in fid_combine() -- array under/overflow"); // Fix iir[0] adj= 1.0/iir[0]; for (a= 0; aargarr; sp->n_arg= 0; sp->order= 0; sp->f0= 0; sp->f1= 0; sp->adj= 0; sp->minlen= -1; sp->n_freq= 0; for (a= 0; 1; a++) { char *fmt= filter[a].fmt; char *p= sp->spec; char ch, *q; if (!fmt) return strdupf("Spec-string \"%s\" matches no known format", sp->spec); while (*p && (ch= *fmt++)) { if (ch != '#') { if (ch == *p++) continue; p= 0; break; } if (isalpha(*p)) { p= 0; break; } // Handling a format character switch (ch= *fmt++) { default: return strdupf("Internal error: Unknown format #%c in format: %s", fmt[-1], filter[a].fmt); case 'o': case 'O': sp->order= (int)strtol(p, &q, 10); if (p == q) { if (ch == 'O') goto bad; sp->order= 1; } if (sp->order <= 0) return strdupf("Bad order %d in spec-string \"%s\"", sp->order, sp->spec); p= q; break; case 'V': sp->n_arg++; *arg++= strtod(p, &q); if (p == q) goto bad; p= q; break; case 'F': sp->minlen= p-1-sp->spec; sp->n_freq= 1; sp->adj= (p[0] == '='); if (sp->adj) p++; sp->f0= strtod(p, &q); sp->f1= 0; if (p == q) goto bad; p= q; break; case 'R': sp->minlen= p-1-sp->spec; sp->n_freq= 2; sp->adj= (p[0] == '='); if (sp->adj) p++; sp->f0= strtod(p, &q); if (p == q) goto bad; p= q; if (*p++ != '-') goto bad; sp->f1= strtod(p, &q); if (p == q) goto bad; if (sp->f0 > sp->f1) return strdupf("Backwards frequency range in spec-string \"%s\"", sp->spec); p= q; break; } } if (p == 0) continue; if (fmt[0] == '/' && fmt[1] == '#' && fmt[2] == 'F') { sp->minlen= p-sp->spec; sp->n_freq= 1; if (sp->in_f0 < 0.0) return strdupf("Frequency omitted from filter-spec, and no default provided"); sp->f0= sp->in_f0; sp->f1= 0; sp->adj= sp->in_adj; fmt += 3; } else if (fmt[0] == '/' && fmt[1] == '#' && fmt[2] == 'R') { sp->minlen= p-sp->spec; sp->n_freq= 2; if (sp->in_f0 < 0.0 || sp->in_f1 < 0.0) return strdupf("Frequency omitted from filter-spec, and no default provided"); sp->f0= sp->in_f0; sp->f1= sp->in_f1; sp->adj= sp->in_adj; fmt += 3; } // Check for trailing unmatched format characters if (*fmt) { bad: return strdupf("Bad match of spec-string \"%s\" to format \"%s\"", sp->spec, filter[a].fmt); } if (sp->n_arg > MAXARG) return strdupf("Internal error -- maximum arguments exceeded"); // Set the minlen to the whole string if unset if (sp->minlen < 0) sp->minlen= p-sp->spec; // Save values, return sp->fi= a; return 0; } return 0; } // // Parse a filter-spec and freq0/freq1 arguments and rewrite them // to give an all-in-one filter spec and/or a minimum spec plus // separate freq0/freq1 arguments. The all-in-one spec is // returned in *spec1p (strdup'd), and the minimum separated-out // spec is returned in *spec2p (strdup'd), *freq0p and *freq1p. // If either of spec1p or spec2p is 0, then that particular // spec-string is not generated. // void fid_rewrite_spec(char *spec, double freq0, double freq1, int adj, char **spec1p, char **spec2p, double *freq0p, double *freq1p, int *adjp) { Spec sp; char *err; sp.spec= spec; sp.in_f0= freq0; sp.in_f1= freq1; sp.in_adj= adj; err= parse_spec(&sp); if (err) error("%s", err); if (spec1p) { char buf[128]; int len; char *rv; switch (sp.n_freq) { case 1: sprintf(buf, "/%s%.15g", sp.adj ? "=" : "", sp.f0); break; case 2: sprintf(buf, "/%s%.15g-%.15g", sp.adj ? "=" : "", sp.f0, sp.f1); break; default: buf[0]= 0; } len= strlen(buf); rv= Alloc(sp.minlen + len + 1); memcpy(rv, spec, sp.minlen); strcpy(rv+sp.minlen, buf); *spec1p= rv; } if (spec2p) { char *rv= Alloc(sp.minlen + 1); memcpy(rv, spec, sp.minlen); *spec2p= rv; *freq0p= sp.f0; *freq1p= sp.f1; *adjp= sp.adj; } } // // Create a FidFilter from the given double array. The double[] // should contain one or more sections, each starting with the // filter type (either 'I' or 'F', as a double), then a count of // the number of coefficients following, then the coefficients // themselves. The end of the list is marked with a type of 0. // // This is really just a convenience function, allowing a filter // to be conveniently dumped to C source code and then // reconstructed. // // Note that for more general filter generation, FidFilter // instances can be created simply by allocating the memory and // filling them in (see fidlib.h). // FidFilter * fid_cv_array(double *arr) { double *dp; FidFilter *ff, *rv; int n_head= 0; int n_val= 0; // Scan through for sizes for (dp= arr; *dp; ) { int len, typ; typ= (int)(*dp++); if (typ != 'F' && typ != 'I') error("Bad type in array passed to fid_cv_array: %g", dp[-1]); len= (int)(*dp++); if (len < 1) error("Bad length in array passed to fid_cv_array: %g", dp[-1]); n_head++; n_val += len; dp += len; } rv= ff= Alloc(FFCSIZE(n_head, n_val)); // Scan through to fill in FidFilter for (dp= arr; *dp; ) { int len, typ; typ= (int)(*dp++); len= (int)(*dp++); ff->typ= typ; ff->cbm= ~0; ff->len= len; memcpy(ff->val, dp, len * sizeof(double)); dp += len; ff= FFNEXT(ff); } // Final element already zero'd thanks to allocation return rv; } // // Create a single filter from the given list of filters in // order. If 'freeme' is set, then all the listed filters are // free'd once read; otherwise they are left untouched. The // newly allocated resultant filter is returned, which should be // released with free() when finished with. // FidFilter * fid_cat(int freeme, ...) { va_list ap; FidFilter *rv, *ff, *ff0; int len= 0; int cnt; char *dst; // Find the memory required to store the combined filter va_start(ap, freeme); while ((ff0= va_arg(ap, FidFilter*))) { for (ff= ff0; ff->typ; ff= FFNEXT(ff)) ; len += ((char*)ff) - ((char*)ff0); } va_end(ap); rv= Alloc(FFCSIZE(0,0) + len); dst= (char*)rv; va_start(ap, freeme); while ((ff0= va_arg(ap, FidFilter*))) { for (ff= ff0; ff->typ; ff= FFNEXT(ff)) ; cnt= ((char*)ff) - ((char*)ff0); memcpy(dst, ff0, cnt); dst += cnt; if (freeme) free(ff0); } va_end(ap); // Final element already zero'd return rv; } // // Support for fid_parse // // Skip white space (including comments) static void skipWS(char **pp) { char *p= *pp; while (*p) { if (isspace(*p)) { p++; continue; } if (*p == '#') { while (*p && *p != '\n') p++; continue; } break; } *pp= p; } // Grab a word from the input into the given buffer. Returns 0: end // of file or error, else 1: success. Error is indicated when the // word doesn't fit in the buffer. static int grabWord(char **pp, char *buf, int buflen) { char *p, *q; int len; skipWS(pp); p= *pp; if (!*p) return 0; q= p; if (*q == ',' || *q == ';' || *q == ')' || *q == ']' || *q == '}') { q++; } else { while (*q && *q != '#' && !isspace(*q) && (*q != ',' && *q != ';' && *q != ')' && *q != ']' && *q != '}')) q++; } len= q-p; if (len >= buflen) return 0; memcpy(buf, p, len); buf[len]= 0; *pp= q; return 1; } // // Parse an entire filter specification, perhaps consisting of // several FIR, IIR and predefined filters. Stops at the first // ,; or unmatched )]}. Returns either 0 on success, or else a // strdup'd error string. // // This duplicates code from Fiview filter.c, I know, but this // may have to expand in the future to handle '+' operations, and // special filter types like tunable heterodyne filters. At that // point, the filter.c code will have to be modified to call a // version of this routine. // char * fid_parse(double rate, char **pp, FidFilter **ffp) { char buf[128]; char *p= *pp, *rew; #define INIT_LEN 128 char *rv= Alloc(INIT_LEN); char *rvend= rv + INIT_LEN; char *rvp= rv; char *tmp; #undef INIT_LEN FidFilter *curr; int xtra= FFCSIZE(0,0); int typ= -1; // First time through double val; char dmy; #define ERR(ptr, msg) { *pp= ptr; *ffp= 0; return msg; } #define INCBUF { tmp= realloc(rv, (rvend-rv) * 2); if (!tmp) error("Out of memory"); \ rvend= (rvend-rv) * 2 + tmp; rvp= (rvp-rv) + tmp; \ curr= (void*)(((char*)curr) - rv + tmp); rv= tmp; } while (1) { rew= p; if (!grabWord(&p, buf, sizeof(buf))) { if (*p) ERR(p, strdupf("Filter element unexpectedly long -- syntax error?")); buf[0]= 0; } if (!buf[0] || !buf[1]) switch (buf[0]) { default: break; case 0: case ',': case ';': case ')': case ']': case '}': // End of filter, return it tmp= realloc(rv, (rvp-rv) + xtra); if (!tmp) error("Out of memory"); curr= (void*)((rvp-rv) + tmp); curr->typ= 0; curr->cbm= 0; curr->len= 0; *pp= buf[0] ? (p-1) : p; *ffp= (FidFilter*)tmp; return 0; case '/': if (typ > 0) ERR(rew, strdupf("Filter syntax error; unexpected '/'")); typ= 'I'; continue; case 'x': if (typ > 0) ERR(rew, strdupf("Filter syntax error; unexpected 'x'")); typ= 'F'; continue; } if (typ < 0) typ= 'F'; // Assume 'x' if missing if (!typ) ERR(p, strdupf("Expecting a 'x' or '/' before this")); if (1 != sscanf(buf, "%lf %c", &val, &dmy)) { // Must be a predefined filter FidFilter *ff; FidFilter *ff1; Spec sp; double f0, f1; char *err; int len; if (typ != 'F') ERR(rew, strdupf("Predefined filters cannot be used with '/'")); // Parse the filter-spec memset(&sp, 0, sizeof(sp)); sp.spec= buf; sp.in_f0= sp.in_f1= -1; if ((err= parse_spec(&sp))) ERR(rew, err); f0= sp.f0; f1= sp.f1; // Adjust frequencies to range 0-0.5, and check them f0 /= rate; if (f0 > 0.5) ERR(rew, strdupf("Frequency of %gHz out of range with " "sampling rate of %gHz", f0*rate, rate)); f1 /= rate; if (f1 > 0.5) ERR(rew, strdupf("Frequency of %gHz out of range with " "sampling rate of %gHz", f1*rate, rate)); // Okay we now have a successful spec-match to filter[sp.fi], and sp.n_arg // args are now in sp.argarr[] // Generate the filter if (!sp.adj) ff= filter[sp.fi].rout(rate, f0, f1, sp.order, sp.n_arg, sp.argarr); else if (strstr(filter[sp.fi].fmt, "#R")) ff= auto_adjust_dual(&sp, rate, f0, f1); else ff= auto_adjust_single(&sp, rate, f0); // Append it to our FidFilter to return for (ff1= ff; ff1->typ; ff1= FFNEXT(ff1)) ; len= ((char*)ff1-(char*)ff); while (rvp + len + xtra >= rvend) INCBUF; memcpy(rvp, ff, len); rvp += len; free(ff); typ= 0; continue; } // Must be a list of coefficients curr= (void*)rvp; rvp += xtra; while (rvp + sizeof(double) >= rvend) INCBUF; curr->typ= typ; curr->cbm= ~0; curr->len= 1; *(double*)rvp= val; rvp += sizeof(double); // See how many more coefficients we can pick up while (1) { rew= p; if (!grabWord(&p, buf, sizeof(buf))) { if (*p) ERR(p, strdupf("Filter element unexpectedly long -- syntax error?")); buf[0]= 0; } if (1 != sscanf(buf, "%lf %c", &val, &dmy)) { p= rew; break; } while (rvp + sizeof(double) >= rvend) INCBUF; curr->len++; *(double*)rvp= val; rvp += sizeof(double); } typ= 0; continue; } #undef INCBUF #undef ERR return strdupf("Internal error, shouldn't reach here"); } // // Filter-running code // #ifdef RF_COMBINED #include "fidrf_combined.h" #endif #ifdef RF_CMDLIST #include "fidrf_cmdlist.h" #endif #ifdef RF_JIT #include "fidrf_jit.h" #endif // END // edfbrowser_157_source/third_party/fidlib/PaxHeaders.7921/fidrf_cmdlist.h0000644000000000000000000000013212646460742023432 xustar0030 mtime=1452958178.234246777 30 atime=1452958178.234246777 30 ctime=1452958178.234246777 edfbrowser_157_source/third_party/fidlib/fidrf_cmdlist.h0000644000175000001440000002756512646460742024012 0ustar00guvusers00000000000000// // Command-list based filter-running code. // // Copyright (c) 2002-2003 Jim Peters . This // file is released under the GNU Lesser General Public License // (LGPL) version 2.1 as published by the Free Software // Foundation. See the file COPYING_LIB for details, or visit // . // // This version of the filter-running code is based on getting // the filter to go as fast as possible with a pre-compiled // routine, but without flattening the filter structure. This // gives greater accuracy than the combined filter. The result // is mostly faster than the combined filter (tested on ix86 with // gcc -O6), except where the combined filter gets a big // advantage from flattening the filter list. This code is also // portable (unlike the JIT option). // typedef struct Run { int magic; // Magic: 0x64966325 int buf_size; // Length of working buffer required in doubles double *coef; // Coefficient list char *cmd; // Command list } Run; typedef struct RunBuf { double *coef; char *cmd; int mov_cnt; // Number of bytes to memmove double buf[0]; } RunBuf; // // Filter processing routine. This is designed to avoid too many // branches, and references are very localized in the code, // keeping the optimizer from trying to store and remember old // values. // // // Step commands: // 0 END // 1 IIR coefficient (1+0) // 2 2x IIR coefficient (2+0) // 3 3x IIR coefficient (3+0) // 4 4Nx IIR coefficient (4N+0) // 5 FIR coefficient (0+1) // 6 2x FIR coefficient (0+2) // 7 3x FIR coefficient (0+3) // 8 4Nx FIR coefficient (0+4N) // 9 IIR+FIR coefficients (1+1) // 10 2x IIR+FIR coefficients (2+2) // 11 3x IIR+FIR coefficients (3+3) // 12 4Nx IIR+FIR coefficients (4N+4N) // 13 End-stage, pure IIR, assume no FIR done at all (1+0) // 14 End-stage with just FIR coeff (0+2) // 15 End-stage with IIR+FIR coeff (1+2) // 16 IIR + pure-IIR endstage (2+0) // 17 FIR + FIR end-stage (0+3) // 18 IIR+FIR + IIR+FIR end-stage (2+3) // 19 Nx (IIR + pure-IIR endstage) (2+0) // 20 Nx (FIR + FIR end-stage) (0+3) // 21 Nx (IIR+FIR + IIR+FIR end-stage) (2+3) // 22 Gain coefficient (0+1) // // Most filters are made up of 2x2 IIR/FIR pairs, which means a // list of command 18 bytes. The other big job would be long FIR // filters. These have to be handled with a list of 7,6,5 // commands, plus a 13 command. // typedef unsigned char uchar; static double filter_step(void *fbuf, double iir) { double *coef= ((RunBuf*)fbuf)->coef; uchar *cmd= ((RunBuf*)fbuf)->cmd; double *buf= &((RunBuf*)fbuf)->buf[0]; uchar ch; double fir= 0; double tmp= buf[0]; int cnt; // Using a memmove first is faster on gcc -O6 / ix86 than moving // the values whilst working through the buffers. memmove(buf, buf+1, ((RunBuf*)fbuf)->mov_cnt); #define IIR \ iir -= *coef++ * tmp; \ tmp= *buf++; #define FIR \ fir += *coef++ * tmp; \ tmp= *buf++; #define BOTH \ iir -= *coef++ * tmp; \ fir += *coef++ * tmp; \ tmp= *buf++; #define ENDIIR \ iir -= *coef++ * tmp; \ tmp= *buf++; \ buf[-1]= iir; #define ENDFIR \ fir += *coef++ * tmp; \ tmp= *buf++; \ buf[-1]= iir; \ iir= fir + *coef++ * iir; \ fir= 0 #define ENDBOTH \ iir -= *coef++ * tmp; \ fir += *coef++ * tmp; \ tmp= *buf++; \ buf[-1]= iir; \ iir= fir + *coef++ * iir; \ fir= 0 #define GAIN \ iir *= *coef++ while ((ch= *cmd++)) switch (ch) { case 1: IIR; break; case 2: IIR; IIR; break; case 3: IIR; IIR; IIR; break; case 4: cnt= *cmd++; do { IIR; IIR; IIR; IIR; } while (--cnt > 0); break; case 5: FIR; break; case 6: FIR; FIR; break; case 7: FIR; FIR; FIR; break; case 8: cnt= *cmd++; do { FIR; FIR; FIR; FIR; } while (--cnt > 0); break; case 9: BOTH; break; case 10: BOTH; BOTH; break; case 11: BOTH; BOTH; BOTH; break; case 12: cnt= *cmd++; do { BOTH; BOTH; BOTH; BOTH; } while (--cnt > 0); break; case 13: ENDIIR; break; case 14: ENDFIR; break; case 15: ENDBOTH; break; case 16: IIR; ENDIIR; break; case 17: FIR; ENDFIR; break; case 18: BOTH; ENDBOTH; break; case 19: cnt= *cmd++; do { IIR; ENDIIR; } while (--cnt > 0); break; case 20: cnt= *cmd++; do { FIR; ENDFIR; } while (--cnt > 0); break; case 21: cnt= *cmd++; do { BOTH; ENDBOTH; } while (--cnt > 0); break; case 22: GAIN; break; } #undef IIR #undef FIR #undef BOTH #undef ENDIIR #undef ENDFIR #undef ENDBOTH #undef GAIN return iir; } // // Create an instance of a filter, ready to run. This returns a // void* handle, and a function to call to execute the filter. // Working buffers for the filter instances must be allocated // separately using fid_run_newbuf(). This allows many // simultaneous instances of the filter to be run. // // The sub-filters are executed in the precise order that they // are given. This may lead to some inefficiency. Normally when // an IIR filter is followed by an FIR filter, the buffers can be // shared. However, if the sub-filters are not in IIR/FIR pairs, // then extra memory accesses are required. // // In any case, factors are extracted from IIR filters (so that // the first coefficient is 1), and single-element FIR filters // are merged into the global gain factor, and are ignored. // // The returned handle must be released using fid_run_free(). // void * fid_run_new(FidFilter *filt, double (**funcpp)(void *,double)) { int buf_size= 0; uchar *cp, prev; FidFilter *ff; double *dp; double gain= 1.0; int a; double *coef_tmp; uchar *cmd_tmp; int coef_cnt, coef_max; int cmd_cnt, cmd_max; int filt_cnt= 0; Run *rr; for (ff= filt; ff->len; ff= FFNEXT(ff)) filt_cnt += ff->len; // Allocate worst-case sizes for temporary arrays coef_tmp= ALLOC_ARR(coef_max= filt_cnt + 1, double); cmd_tmp= ALLOC_ARR(cmd_max= filt_cnt + 4, char); dp= coef_tmp; cp= cmd_tmp; prev= 0; // Generate command and coefficient lists while (filt->len) { int n_iir, n_fir, cnt; double *iir, *fir; double adj; if (filt->typ == 'F' && filt->len == 1) { gain *= filt->val[0]; filt= FFNEXT(filt); continue; } if (filt->typ == 'F') { iir= 0; n_iir= 0; fir= filt->val; n_fir= filt->len; filt= FFNEXT(filt); } else if (filt->typ == 'I') { iir= filt->val; n_iir= filt->len; fir= 0; n_fir= 0; filt= FFNEXT(filt); while (filt->typ == 'F' && filt->len == 1) { gain *= filt->val[0]; filt= FFNEXT(filt); } if (filt->typ == 'F') { fir= filt->val; n_fir= filt->len; filt= FFNEXT(filt); } } else error("Internal error: fid_run_new can only handle IIR + FIR types"); // Okay, we now have an IIR/FIR pair to process, possibly with // n_iir or n_fir == 0 if one half is missing cnt= n_iir > n_fir ? n_iir : n_fir; buf_size += cnt-1; if (n_iir) { adj= 1.0 / iir[0]; gain *= adj; } if (n_fir == 3 && n_iir == 3) { if (prev == 18) { cp[-1]= prev= 21; *cp++= 2; } else if (prev == 21) { cp[-1]++; } else *cp++= prev= 18; *dp++= iir[2]*adj; *dp++= fir[2]; *dp++= iir[1]*adj; *dp++= fir[1]; *dp++= fir[0]; } else if (n_fir == 3 && n_iir == 0) { if (prev == 17) { cp[-1]= prev= 20; *cp++= 2; } else if (prev == 20) { cp[-1]++; } else *cp++= prev= 17; *dp++= fir[2]; *dp++= fir[1]; *dp++= fir[0]; } else if (n_fir == 0 && n_iir == 3) { if (prev == 16) { cp[-1]= prev= 19; *cp++= 2; } else if (prev == 19) { cp[-1]++; } else *cp++= prev= 16; *dp++= iir[2]*adj; *dp++= iir[1]*adj; } else { prev= 0; // Just cancel 'prev' as we only use it for 16-18,19-21 if (cnt > n_fir) { a= 0; while (cnt > n_fir && cnt > 2) { *dp++= iir[--cnt] * adj; a++; } while (a >= 4) { int nn= a/4; if (nn > 255) nn= 255; *cp++= 4; *cp++= nn; a -= nn*4; } if (a) *cp++= a; } if (cnt > n_iir) { a= 0; while (cnt > n_iir && cnt > 2) { *dp++= fir[--cnt]; a++; } while (a >= 4) { int nn= a/4; if (nn > 255) nn= 255; *cp++= 8; *cp++= nn; a -= nn*4; } if (a) *cp++= 4+a; } a= 0; while (cnt > 2) { cnt--; a++; *dp++= iir[cnt]*adj; *dp++= fir[cnt]; } while (a >= 4) { int nn= a/4; if (nn > 255) nn= 255; *cp++= 12; *cp++= nn; a -= nn*4; } if (a) *cp++= 8+a; if (!n_fir) { *cp++= 13; *dp++= iir[1]; } else if (!n_iir) { *cp++= 14; *dp++= fir[1]; *dp++= fir[0]; } else { *cp++= 15; *dp++= iir[1]; *dp++= fir[1]; *dp++= fir[0]; } } } if (gain != 1.0) { *cp++= 22; *dp++= gain; } *cp++= 0; // Sanity checks coef_cnt= dp-coef_tmp; cmd_cnt= cp-cmd_tmp; if (coef_cnt > coef_max || cmd_cnt > cmd_max) error("fid_run_new internal error; arrays exceeded"); // Allocate the final Run structure to return rr= (Run*)Alloc(sizeof(Run) + coef_cnt*sizeof(double) + cmd_cnt*sizeof(char)); rr->magic= 0x64966325; rr->buf_size= buf_size; rr->coef= (double*)(rr+1); rr->cmd= (char*)(rr->coef + coef_cnt); memcpy(rr->coef, coef_tmp, coef_cnt*sizeof(double)); memcpy(rr->cmd, cmd_tmp, cmd_cnt*sizeof(char)); //DEBUG { //DEBUG int a; //DEBUG for (cp= cmd_tmp; *cp; cp++) printf("%d ", *cp); //DEBUG printf("\n"); //DEBUG //for (a= 0; amagic != 0x64966325) error("Bad handle passed to fid_run_newbuf()"); siz= rr->buf_size ? rr->buf_size : 1; // Minimum one element to avoid problems rb= Alloc(sizeof(RunBuf) + siz * sizeof(double)); rb->coef= rr->coef; rb->cmd= rr->cmd; rb->mov_cnt= (siz-1) * sizeof(double); // rb->buf[] already zerod return rb; } // // Find the space required for a filter buffer // int fid_run_bufsize(void *run) { Run *rr= run; int siz; if (rr->magic != 0x64966325) error("Bad handle passed to fid_run_bufsize()"); siz= rr->buf_size ? rr->buf_size : 1; // Minimum one element to avoid problems return sizeof(RunBuf) + siz * sizeof(double); } // // Initialise a filter buffer allocated separately. Usually // fid_run_newbuf() is easier, but in the case where filter // buffers must be allocated as part of a larger structure, a // call to fid_run_newbuf can be replaced with a call to // fid_run_bufsize() to get the space required, and then a call // to fid_run_initbuf() once it has been allocated. // void fid_run_initbuf(void *run, void *buf) { Run *rr= run; RunBuf *rb= buf; int siz; if (rr->magic != 0x64966325) error("Bad handle passed to fid_run_initbuf()"); siz= rr->buf_size ? rr->buf_size : 1; // Minimum one element to avoid problems rb->coef= rr->coef; rb->cmd= rr->cmd; rb->mov_cnt= (siz-1) * sizeof(double); memset(rb->buf, 0, rb->mov_cnt + sizeof(double)); } // // Reinitialise an instance of the filter, allowing it to start // afresh. It assumes that the buffer was correctly initialised // previously, either through a call to fid_run_newbuf() or // fid_run_initbuf(). // void fid_run_zapbuf(void *buf) { RunBuf *rb= buf; memset(rb->buf, 0, rb->mov_cnt + sizeof(double)); } // // Delete an instance // void fid_run_freebuf(void *runbuf) { free(runbuf); } // // Delete the filter // void fid_run_free(void *run) { free(run); } // END // edfbrowser_157_source/PaxHeaders.7921/disclaimer.txt0000644000000000000000000000013212646460742017543 xustar0030 mtime=1452958178.258246696 30 atime=1452958178.258246696 30 ctime=1452958178.258246696 edfbrowser_157_source/disclaimer.txt0000644000175000001440000000051012646460742020100 0ustar00guvusers00000000000000 This is free software, it is experimental and available under the GPL License version 3. Despite this software is intend to be useful, there is no warranty, use this software at your own risk! This software is intend to be used for education and/or research. DO NOT USE THIS SOFTWARE FOR MEDICAL PURPOSES AND/OR DIAGNOSIS! edfbrowser_157_source/PaxHeaders.7921/print_to_edf.cpp0000644000000000000000000000012712646460742020052 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/print_to_edf.cpp0000644000175000001440000010442612646460742020416 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "print_to_edf.h" void print_screen_to_edf(UI_Mainwindow *mainwindow) { int i, j, k, p, n=0, records, records_written, signalcomps, duration_factor[MAXFILES], temp=0, edfplus=0, tallen, annotationlist_nr=0, annotations_left=1, add_one_sec=0, annot_smp_per_record=16, type, len; long long duration, smpls_written[MAXSIGNALS], s2, preamble=0LL, smpls_preamble[MAXSIGNALS], taltime=0LL, l_temp, referencetime, annot_difftime=0LL; char path[MAX_PATH_LENGTH], scratchpad[512], datrecduration[8], *viewbuf; double frequency, frequency2, dig_value; FILE *outputfile; struct signalcompblock **signalcomp; union { signed int one_signed; signed short two_signed[2]; unsigned char four[4]; } wr_var; union { signed short one_signed; unsigned char two[2]; } null_bytes[MAXSIGNALS]; struct annotationblock *annotations_pntr; struct date_time_struct date_time; ///////////////////////////////////////////////////////////////////////// signalcomps = mainwindow->signalcomps; signalcomp = mainwindow->signalcomp; viewbuf = mainwindow->viewbuf; annotations_pntr = mainwindow->annotationlist[0]; if((!mainwindow->files_open)||(!signalcomps)) { QMessageBox messagewindow(QMessageBox::Critical, "Print to EDF", "Put a signal on the screen and try again."); messagewindow.exec(); return; } for(i=0; ifiles_open; i++) { if(mainwindow->edfheaderlist[i]->bdf) { QMessageBox messagewindow(QMessageBox::Critical, "Print to EDF", "BDF files can not be printed to EDF."); messagewindow.exec(); return; } if(mainwindow->edfheaderlist[i]->discontinuous) { QMessageBox messagewindow(QMessageBox::Critical, "Print to EDF", "Sorry, discontinues EDF files can not be printed to EDF."); messagewindow.exec(); return; } if(mainwindow->edfheaderlist[i]->edfplus) { edfplus = 1; for(j=0; jedfheaderlist[i]->nr_annot_chns; j++) { if(mainwindow->edfheaderlist[i]->edfparam[mainwindow->edfheaderlist[i]->annot_ch[j]].smp_per_record>annot_smp_per_record) { annot_smp_per_record = mainwindow->edfheaderlist[i]->edfparam[mainwindow->edfheaderlist[i]->annot_ch[j]].smp_per_record; } } } } annot_smp_per_record += 16; taltime = mainwindow->edfheaderlist[mainwindow->sel_viewtime]->starttime_offset; duration = 0; for(i=0; iedfhdr->long_data_record_duration>duration) { duration = signalcomp[i]->edfhdr->long_data_record_duration; n = i; } } fseeko(signalcomp[n]->edfhdr->file_hdl, 244LL, SEEK_SET); if(fread(datrecduration, 8, 1, signalcomp[n]->edfhdr->file_hdl)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); return; } temp = 0; for(i=0; iedfhdr->long_data_record_duration) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "This combination of files can not be printed to EDF\n" "because the quotient of the datarecordblock durations is not an integer."); messagewindow.exec(); return; } duration_factor[signalcomp[i]->filenum] = duration / signalcomp[i]->edfhdr->long_data_record_duration; temp += signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record; } path[0] = 0; if(mainwindow->recent_savedir[0]!=0) { strcpy(path, mainwindow->recent_savedir); strcat(path, "/"); } len = strlen(path); get_filename_from_path(path + len, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename, MAX_PATH_LENGTH - len); remove_extension_from_filename(path); strcat(path, "_screenprint.edf"); strcpy(path, QFileDialog::getSaveFileName(0, "Print to EDF", QString::fromLocal8Bit(path), "EDF files (*.edf *.EDF)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(mainwindow->recent_savedir, path, MAX_PATH_LENGTH); if(mainwindow->file_is_opened(path)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, selected file is in use."); messagewindow.exec(); return; } outputfile = fopeno(path, "wb"); if(outputfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not create a file for writing."); messagewindow.exec(); return; } referencetime = mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime; if(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime<0) { if((-mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime) % TIME_DIMENSION) { preamble = TIME_DIMENSION - ((-mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime) % TIME_DIMENSION); referencetime--; add_one_sec = 1; } } else { preamble = mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime % TIME_DIMENSION; if(preamble) add_one_sec = 1; } for(i=0; iedfhdr->long_data_record_duration / signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record); } referencetime += (mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime / TIME_DIMENSION); utc_to_date_time(referencetime, &date_time); /************************* write EDF-header ***************************************/ rewind(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl); rewind(outputfile); if(edfplus) { if(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->edfplus) { if(fread(scratchpad, 88, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad, 88, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } else { fprintf(outputfile, "0 X X X X "); if(fread(scratchpad, 88, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad + 8, 72, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } fprintf(outputfile, "Startdate %02i-", date_time.day); switch(date_time.month) { case 1 : fprintf(outputfile, "JAN"); break; case 2 : fprintf(outputfile, "FEB"); break; case 3 : fprintf(outputfile, "MAR"); break; case 4 : fprintf(outputfile, "APR"); break; case 5 : fprintf(outputfile, "MAY"); break; case 6 : fprintf(outputfile, "JUN"); break; case 7 : fprintf(outputfile, "JUL"); break; case 8 : fprintf(outputfile, "AUG"); break; case 9 : fprintf(outputfile, "SEP"); break; case 10 : fprintf(outputfile, "OCT"); break; case 11 : fprintf(outputfile, "NOV"); break; case 12 : fprintf(outputfile, "DEC"); break; default : fprintf(outputfile, "ERR"); break; } fprintf(outputfile, "-%04i ", date_time.year); if(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->edfplus) { if(fread(scratchpad, 80, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); fclose(outputfile); return; } if(scratchpad[10]=='X') { if(fwrite(scratchpad + 12, 58, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } else { if(fwrite(scratchpad + 22, 58, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } } else { fprintf(outputfile, "X X X "); if(fread(scratchpad, 80, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad + 28, 52, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } } else { if(fread(scratchpad, 168, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad, 168, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } fprintf(outputfile, "%02i.%02i.%02i%02i.%02i.%02i", date_time.day, date_time.month, date_time.year % 100, date_time.hour, date_time.minute, date_time.second); fprintf(outputfile, "%-8i", (signalcomps + edfplus) * 256 + 256); if(edfplus) { fprintf(outputfile, "EDF+C"); for(i=0; i<39; i++) fputc(' ', outputfile); } else for(i=0; i<44; i++) fputc(' ', outputfile); records = (int)(mainwindow->pagetime / duration); if(add_one_sec) { records += TIME_DIMENSION / duration; } fprintf(outputfile, "%-8i", records); if(fwrite(datrecduration, 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } fprintf(outputfile, "%-4i", signalcomps + edfplus); for(i=0; isignallabel); strcat(scratchpad, " "); if(fwrite(scratchpad, 16, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } if(edfplus) { if(fwrite("EDF Annotations ", 16, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].transducer, 80, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } if(edfplus) { for(i=0; i<80; i++) fputc(' ', outputfile); } for(i=0; iphysdimension); strcat(scratchpad, " "); if(fwrite(scratchpad, 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } if(edfplus) { for(i=0; i<8; i++) fputc(' ', outputfile); } for(i=0; iecg_filter == NULL) && (signalcomp[i]->zratio_filter == NULL)) { fseeko(signalcomp[i]->edfhdr->file_hdl, (long long)((signalcomp[i]->edfsignal[0] * 8) + (104 * signalcomp[i]->edfhdr->edfsignals) + 256), SEEK_SET); if(fread(scratchpad, 8, 1, signalcomp[i]->edfhdr->file_hdl)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad, 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } if(signalcomp[i]->ecg_filter != NULL) { if(fwrite("0 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } if(signalcomp[i]->zratio_filter != NULL) { if(fwrite("-1 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } } if(edfplus) { if(fwrite("-1 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } for(i=0; iecg_filter == NULL) && (signalcomp[i]->zratio_filter == NULL)) { fseeko(signalcomp[i]->edfhdr->file_hdl, (long long)((signalcomp[i]->edfsignal[0] * 8) + (112 * signalcomp[i]->edfhdr->edfsignals) + 256), SEEK_SET); if(fread(scratchpad, 8, 1, signalcomp[i]->edfhdr->file_hdl)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad, 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } if(signalcomp[i]->ecg_filter != NULL) { if(fwrite("1000 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } if(signalcomp[i]->zratio_filter != NULL) { if(fwrite("1 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } } if(edfplus) { if(fwrite("1 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } for(i=0; iecg_filter == NULL) && (signalcomp[i]->zratio_filter == NULL)) { fprintf(outputfile, "%-8i", signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min); if(signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min<0) { null_bytes[i].one_signed = 0; } else { null_bytes[i].one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min; } } else { if(fwrite("-32768 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } null_bytes[i].one_signed = -32768; } } if(edfplus) { if(fwrite("-32768 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } for(i=0; iecg_filter == NULL) && (signalcomp[i]->zratio_filter == NULL)) { fprintf(outputfile, "%-8i", signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max); } else { if(fwrite("32767 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } } if(edfplus) { if(fwrite("32767 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].prefilter); strcat(scratchpad, " "); for(p = strlen(scratchpad) - 1; p>=0; p--) { if(scratchpad[p]!=' ') break; } p++; if(p) p++; if(signalcomp[i]->spike_filter) { p += sprintf(scratchpad + p, "Spike:%f", signalcomp[i]->spike_filter->velocity); 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(p>80) break; } for(j=0; jfilter_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; jfidfilter_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; jravg_filter_cnt; j++) { if(signalcomp[i]->ravg_filter_type[j] == 0) { p += sprintf(scratchpad + p, "HP:%iSmpls ", signalcomp[i]->ravg_filter[j]->size); } if(signalcomp[i]->ravg_filter_type[j] == 1) { p += sprintf(scratchpad + p, "LP:%iSmpls ", signalcomp[i]->ravg_filter[j]->size); } p = strlen(scratchpad); if(p>80) break; } if(signalcomp[i]->ecg_filter != NULL) { p += sprintf(scratchpad + p, "ECG:HR "); } 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) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } if(edfplus) { for(i=0; i<80; i++) fputc(' ', outputfile); } for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record * duration_factor[signalcomp[i]->filenum]); } if(edfplus) { fprintf(outputfile, "%-8i", annot_smp_per_record); } for(i=0; iprint_to_edf_active = 1; mainwindow->setup_viewbuf(); viewbuf = mainwindow->viewbuf; if(viewbuf==NULL) { fclose(outputfile); return; } QApplication::setOverrideCursor(Qt::WaitCursor); for(records_written=0; records_writtenprocessEvents(); for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record * duration_factor[signalcomp[i]->filenum]; k++) { if(smpls_preamble[i]) { smpls_preamble[i]--; fputc(null_bytes[i].two[0], outputfile); if(fputc(null_bytes[i].two[1], outputfile)==EOF) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } else { dig_value = 0; s2 = smpls_written[i] + signalcomp[i]->sample_timeoffset - signalcomp[i]->sample_start; for(j=0; jnum_of_signals; j++) { if((smpls_written[i]sample_stop)&&(s2>=0)) { if(signalcomp[i]->edfhdr->edf) { temp = *(((short *)( viewbuf + signalcomp[i]->viewbufoffset + (signalcomp[i]->edfhdr->recordsize * (s2 / signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record)) + signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].buf_offset)) + (s2 % signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record)); } temp += signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].offset; temp *= signalcomp[i]->factor[j]; temp -= signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].offset; } else { temp = 0; } dig_value += temp; } if(signalcomp[i]->spike_filter) { if(smpls_written[i]==signalcomp[i]->sample_start) { if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime<=0) { reset_spike_filter(signalcomp[i]->spike_filter); } else { spike_filter_restore_buf(signalcomp[i]->spike_filter); } } dig_value = run_spike_filter(dig_value, signalcomp[i]->spike_filter); } for(p=0; pfilter_cnt; p++) { if(smpls_written[i]==signalcomp[i]->sample_start) { if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime==0) { reset_filter(dig_value, signalcomp[i]->filter[p]); } else { signalcomp[i]->filter[p]->old_input = signalcomp[i]->filterpreset_a[p]; signalcomp[i]->filter[p]->old_output = signalcomp[i]->filterpreset_b[p]; } } dig_value = first_order_filter(dig_value, signalcomp[i]->filter[p]); } for(p=0; pravg_filter_cnt; p++) { if(smpls_written[i]==signalcomp[i]->sample_start) { if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime!=0) { ravg_filter_restore_buf(signalcomp[i]->ravg_filter[p]); } } dig_value = run_ravg_filter(dig_value, signalcomp[i]->ravg_filter[p]); } for(p=0; pfidfilter_cnt; p++) { if(smpls_written[i]==signalcomp[i]->sample_start) { if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime!=0) { memcpy(signalcomp[i]->fidbuf[p], signalcomp[i]->fidbuf2[p], fid_run_bufsize(signalcomp[i]->fid_run[p])); } } dig_value = signalcomp[i]->fidfuncp[p](signalcomp[i]->fidbuf[p], dig_value); } if(signalcomp[i]->ecg_filter != NULL) { if(smpls_written[i]==signalcomp[i]->sample_start) { if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime != 0) { ecg_filter_restore_buf(signalcomp[i]->ecg_filter); } } dig_value = run_ecg_filter(dig_value, signalcomp[i]->ecg_filter); dig_value = (dig_value * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue * 65.536) - 32768.0; } if(signalcomp[i]->zratio_filter != NULL) { if(smpls_written[i]==signalcomp[i]->sample_start) { if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime != 0) { zratio_filter_restore_buf(signalcomp[i]->zratio_filter); } } dig_value = run_zratio_filter(dig_value, signalcomp[i]->zratio_filter); dig_value = dig_value * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue * 32768.0; } if((smpls_written[i]>=signalcomp[i]->sample_start)&&(smpls_written[i]sample_stop)) { wr_var.one_signed = dig_value; if((signalcomp[i]->ecg_filter == NULL) && (signalcomp[i]->zratio_filter == NULL)) { if(wr_var.one_signed>signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max) { wr_var.one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max; } if(wr_var.one_signededfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min) { wr_var.one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min; } } else { if(wr_var.one_signed > 32767) { wr_var.one_signed = 32767; } if(wr_var.one_signed < -32768) { wr_var.one_signed = -32768; } } fputc(wr_var.four[0], outputfile); if(fputc(wr_var.four[1], outputfile)==EOF) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } else { fputc(null_bytes[i].two[0], outputfile); if(fputc(null_bytes[i].two[1], outputfile)==EOF) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } smpls_written[i]++; } } } if(edfplus) { tallen = fprintf(outputfile, "+%i.%07i", (int)(taltime / TIME_DIMENSION), (int)(taltime % TIME_DIMENSION)); fputc(20, outputfile); fputc(20, outputfile); fputc(0, outputfile); tallen += 3; if(annotations_left) { if(mainwindow->viewtime_sync==VIEWTIME_SYNCED_ABSOLUT) { annot_difftime = (referencetime - mainwindow->edfheaderlist[annotationlist_nr]->utc_starttime) * TIME_DIMENSION; } if(mainwindow->viewtime_sync==VIEWTIME_SYNCED_OFFSET) { annot_difftime = (referencetime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime) * TIME_DIMENSION; } if((mainwindow->viewtime_sync==VIEWTIME_UNSYNCED) || (mainwindow->viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { annot_difftime = (referencetime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime) * TIME_DIMENSION; annot_difftime += (mainwindow->edfheaderlist[annotationlist_nr]->viewtime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime); } if(annotationlist_nr != mainwindow->sel_viewtime) { annot_difftime -= mainwindow->edfheaderlist[mainwindow->sel_viewtime]->starttime_offset; annot_difftime += mainwindow->edfheaderlist[annotationlist_nr]->starttime_offset; } } while(annotations_left) { while(!annotations_pntr) { annotationlist_nr++; if(annotationlist_nr>=mainwindow->files_open) { annotations_left = 0; annotations_pntr = NULL; break; } annotations_pntr = mainwindow->annotationlist[annotationlist_nr]; if(mainwindow->viewtime_sync==VIEWTIME_SYNCED_ABSOLUT) { annot_difftime = (referencetime - mainwindow->edfheaderlist[annotationlist_nr]->utc_starttime) * TIME_DIMENSION; } if(mainwindow->viewtime_sync==VIEWTIME_SYNCED_OFFSET) { annot_difftime = (referencetime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime) * TIME_DIMENSION; } if((mainwindow->viewtime_sync==VIEWTIME_UNSYNCED) || (mainwindow->viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { annot_difftime = (referencetime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime) * TIME_DIMENSION; annot_difftime += (mainwindow->edfheaderlist[annotationlist_nr]->viewtime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime); } if(annotationlist_nr != mainwindow->sel_viewtime) { annot_difftime -= mainwindow->edfheaderlist[mainwindow->sel_viewtime]->starttime_offset; annot_difftime += mainwindow->edfheaderlist[annotationlist_nr]->starttime_offset; } } if(!annotations_left) break; if(annotations_pntr) { l_temp = annotations_pntr->onset - annot_difftime; if((l_temp >= 0LL) && (l_temp < (mainwindow->pagetime + TIME_DIMENSION))) { tallen += fprintf(outputfile, "%+i.%07i", (int)(l_temp / TIME_DIMENSION), (int)(l_temp % TIME_DIMENSION)); if(annotations_pntr->duration[0]!=0) { fputc(21, outputfile); tallen++; tallen += fprintf(outputfile, "%s", annotations_pntr->duration); } fputc(20, outputfile); tallen++; tallen += fprintf(outputfile, "%s", annotations_pntr->annotation); fputc(20, outputfile); fputc(0, outputfile); tallen += 2; annotations_pntr = annotations_pntr->next_annotation; break; } else { annotations_pntr = annotations_pntr->next_annotation; continue; } } } for(j=tallen; j<(annot_smp_per_record * 2); j++) { fputc(0, outputfile); } taltime += duration; } } QApplication::restoreOverrideCursor(); fclose(outputfile); } edfbrowser_157_source/PaxHeaders.7921/signal_chooser.cpp0000644000000000000000000000012712646460742020375 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/signal_chooser.cpp0000644000175000001440000002721112646460742020735 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "signal_chooser.h" UI_SignalChooser::UI_SignalChooser(QWidget *w_parent, int job, int *sgnl_nr) { task = job; signal_nr = sgnl_nr; mainwindow = (UI_Mainwindow *)w_parent; signalchooser_dialog = new QDialog(w_parent); if(task == 3) { signalchooser_dialog->setMinimumSize(265, 420); signalchooser_dialog->setMaximumSize(265, 420); signalchooser_dialog->setWindowTitle("Organize signals"); } else { signalchooser_dialog->setMinimumSize(200, 420); signalchooser_dialog->setMaximumSize(200, 420); signalchooser_dialog->setWindowTitle("Signals"); } signalchooser_dialog->setModal(true); signalchooser_dialog->setAttribute(Qt::WA_DeleteOnClose, true); list = new QListWidget(signalchooser_dialog); list->setGeometry(10, 10, 130, 365); list->setSelectionBehavior(QAbstractItemView::SelectRows); if(task == 3) { list->setSelectionMode(QAbstractItemView::ExtendedSelection); } else { list->setSelectionMode(QAbstractItemView::SingleSelection); } CloseButton = new QPushButton(signalchooser_dialog); CloseButton->setGeometry(10, 385, 130, 25); CloseButton->setText("Close"); if(task == 3) { UpButton = new QPushButton(signalchooser_dialog); UpButton->setGeometry(155, 180, 100, 25); UpButton->setText("Up"); DownButton = new QPushButton(signalchooser_dialog); DownButton->setGeometry(155, 220, 100, 25); DownButton->setText("Down"); InvertButton = new QPushButton(signalchooser_dialog); InvertButton->setGeometry(155, 260, 100, 25); InvertButton->setText("Invert"); DeleteButton = new QPushButton(signalchooser_dialog); DeleteButton->setGeometry(155, 300, 100, 25); DeleteButton->setText("Remove"); } load_signalcomps(); QObject::connect(CloseButton, SIGNAL(clicked()), signalchooser_dialog, SLOT(close())); if(task == 3) { if(list->count() > 0) { list->setCurrentRow(0); QObject::connect(UpButton, SIGNAL(clicked()), this, SLOT(signalUp())); QObject::connect(DownButton, SIGNAL(clicked()), this, SLOT(signalDown())); QObject::connect(InvertButton, SIGNAL(clicked()), this, SLOT(signalInvert())); QObject::connect(DeleteButton, SIGNAL(clicked()), this, SLOT(signalDelete())); } } else { QObject::connect(list, SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(call_sidemenu(QListWidgetItem *))); } signalchooser_dialog->exec(); } void UI_SignalChooser::load_signalcomps(void) { int i; QListWidgetItem *item; list->clear(); for(i=0; isignalcomps; i++) { item = new QListWidgetItem; item->setText(mainwindow->signalcomp[i]->signallabel); item->setData(Qt::UserRole, QVariant(i)); list->addItem(item); } } void UI_SignalChooser::call_sidemenu(QListWidgetItem *) { int i; if(task == 3) return; signalchooser_dialog->hide(); if(task == 0) { mainwindow->maincurve->exec_sidemenu(list->currentRow()); } if(task == 1) { for(i=0; ispectrumdock[i]->dock->isHidden()) break; } if(ispectrumdock[i]->init(list->currentRow()); } else { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The maximum number of docked Power Spectrum windows has been reached.\n" "Close one first."); messagewindow.exec(); } } if(task == 2) { AdjustFilterSettings filtersettings(mainwindow->signalcomp[list->currentRow()], mainwindow->maincurve); } if(task == 4) { if(signal_nr != NULL) { *signal_nr = list->currentRow(); } } signalchooser_dialog->close(); } void UI_SignalChooser::signalUp() { int i, n, size, sigcomp_nr, selected_signals[MAXSIGNALS]; struct signalcompblock *signalcomp; n = get_selectionlist(selected_signals); if(n < 1) { return; } size = list->count(); if(size < (n + 1)) { return; } if(selected_signals[0] < 1) { return; } for(i=0; isignalcomp[sigcomp_nr]; mainwindow->signalcomp[sigcomp_nr] = mainwindow->signalcomp[sigcomp_nr - 1]; mainwindow->signalcomp[sigcomp_nr - 1] = signalcomp; } load_signalcomps(); for(i=0; iitem(selected_signals[i] - 1)->setSelected(true); } mainwindow->setup_viewbuf(); } void UI_SignalChooser::signalDown() { int i, n, size, sigcomp_nr, selected_signals[MAXSIGNALS]; struct signalcompblock *signalcomp; n = get_selectionlist(selected_signals); if(n < 1) { return; } size = list->count(); if(size < (n + 1)) { return; } if(selected_signals[n-1] > (size - 2)) { return; } for(i=(n-1); i>=0; i--) { sigcomp_nr = selected_signals[i]; signalcomp = mainwindow->signalcomp[sigcomp_nr]; mainwindow->signalcomp[sigcomp_nr] = mainwindow->signalcomp[sigcomp_nr + 1]; mainwindow->signalcomp[sigcomp_nr + 1] = signalcomp; selected_signals[i] = sigcomp_nr; } load_signalcomps(); for(i=0; iitem(selected_signals[i] + 1)->setSelected(true); } mainwindow->setup_viewbuf(); } int UI_SignalChooser::get_selectionlist(int *slist) { int i, j, n, tmp; QListWidgetItem *item; QList selectedlist; selectedlist = list->selectedItems(); n = selectedlist.size(); if(n < 1) { return 0; } for(i=0; idata(Qt::UserRole).toInt(); for(j=i; j>0; j--) // Sort the list!! { if(slist[j] > slist[j-1]) { break; } tmp = slist[j]; slist[j] = slist[j-1]; slist[j-1] = tmp; } } return n; } void UI_SignalChooser::signalDelete() { int i, j, k, n, p, sigcomp_nr, selected_signr[MAXSIGNALS]; n = get_selectionlist(selected_signr); if(n < 1) { return; } for(k=0; kspectrumdock[i]->signalcomp == mainwindow->signalcomp[sigcomp_nr]) { mainwindow->spectrumdock[i]->clear(); mainwindow->spectrumdock[i]->dock->hide(); } } for(i=0; isignalcomp[sigcomp_nr]->spectr_dialog[i]; if(p != 0) { delete mainwindow->spectrumdialog[p - 1]; mainwindow->spectrumdialog[p - 1] = NULL; } } for(i=0; isignalcomp[sigcomp_nr]->avg_dialog[i]; if(p != 0) { delete mainwindow->averagecurvedialog[p - 1]; mainwindow->averagecurvedialog[p - 1] = NULL; } } for(i=0; isignalcomp[sigcomp_nr]->zscoredialog[i]; if(p != 0) { delete mainwindow->zscoredialog[p - 1]; mainwindow->zscoredialog[p - 1] = NULL; } } if(mainwindow->signalcomp[sigcomp_nr]->hascursor2) { mainwindow->maincurve->crosshair_2.active = 0; mainwindow->maincurve->crosshair_2.moving = 0; } if(mainwindow->signalcomp[sigcomp_nr]->hascursor1) { mainwindow->maincurve->crosshair_1.active = 0; mainwindow->maincurve->crosshair_2.active = 0; mainwindow->maincurve->crosshair_1.moving = 0; mainwindow->maincurve->crosshair_2.moving = 0; for(i=0; isignalcomps; i++) { mainwindow->signalcomp[i]->hascursor2 = 0; } } if(mainwindow->signalcomp[sigcomp_nr]->hasruler) { mainwindow->maincurve->ruler_active = 0; mainwindow->maincurve->ruler_moving = 0; } for(j=0; jsignalcomp[sigcomp_nr]->filter_cnt; j++) { free(mainwindow->signalcomp[sigcomp_nr]->filter[j]); } mainwindow->signalcomp[sigcomp_nr]->filter_cnt = 0; if(mainwindow->signalcomp[sigcomp_nr]->spike_filter != NULL) { free_spike_filter(mainwindow->signalcomp[sigcomp_nr]->spike_filter); } mainwindow->signalcomp[sigcomp_nr]->spike_filter = NULL; for(j=0; jsignalcomp[sigcomp_nr]->ravg_filter_cnt; j++) { free_ravg_filter(mainwindow->signalcomp[sigcomp_nr]->ravg_filter[j]); } mainwindow->signalcomp[sigcomp_nr]->ravg_filter_cnt = 0; if(mainwindow->signalcomp[sigcomp_nr]->ecg_filter != NULL) { free_ecg_filter(mainwindow->signalcomp[sigcomp_nr]->ecg_filter); mainwindow->signalcomp[sigcomp_nr]->ecg_filter = NULL; strcpy(mainwindow->signalcomp[sigcomp_nr]->signallabel, mainwindow->signalcomp[sigcomp_nr]->signallabel_bu); mainwindow->signalcomp[sigcomp_nr]->signallabellen = mainwindow->signalcomp[sigcomp_nr]->signallabellen_bu; strcpy(mainwindow->signalcomp[sigcomp_nr]->physdimension, mainwindow->signalcomp[sigcomp_nr]->physdimension_bu); } for(j=0; jsignalcomp[sigcomp_nr]->fidfilter_cnt; j++) { free(mainwindow->signalcomp[sigcomp_nr]->fidfilter[j]); fid_run_free(mainwindow->signalcomp[sigcomp_nr]->fid_run[j]); fid_run_freebuf(mainwindow->signalcomp[sigcomp_nr]->fidbuf[j]); fid_run_freebuf(mainwindow->signalcomp[sigcomp_nr]->fidbuf2[j]); } mainwindow->signalcomp[sigcomp_nr]->fidfilter_cnt = 0; free(mainwindow->signalcomp[sigcomp_nr]); for(i=sigcomp_nr; isignalcomps - 1; i++) { mainwindow->signalcomp[i] = mainwindow->signalcomp[i + 1]; } mainwindow->signalcomps--; } load_signalcomps(); mainwindow->setup_viewbuf(); } void UI_SignalChooser::signalInvert() { int i, n, selected_signals[MAXSIGNALS]; n = get_selectionlist(selected_signals); if(n < 1) { return; } for(i=0; isignalcomp[selected_signals[i]]->polarity *= -1; mainwindow->signalcomp[selected_signals[i]]->screen_offset *= -1; } load_signalcomps(); for(i=0; iitem(selected_signals[i])->setSelected(true); } mainwindow->setup_viewbuf(); } void UI_SignalChooser::strip_types_from_label(char *label) { int i, len; len = strlen(label); if(len<16) { return; } if((!(strncmp(label, "EEG ", 4))) ||(!(strncmp(label, "ECG ", 4))) ||(!(strncmp(label, "EOG ", 4))) ||(!(strncmp(label, "ERG ", 4))) ||(!(strncmp(label, "EMG ", 4))) ||(!(strncmp(label, "MEG ", 4))) ||(!(strncmp(label, "MCG ", 4)))) { if(label[4]!=' ') { for(i=0; i<(len-4); i++) { label[i] = label[i+4]; } for(; i. * *************************************************************************** */ #include "edf_compat.h" UI_EDFCompatwindow::UI_EDFCompatwindow(QWidget *w_parent) { int i; mainwindow = (UI_Mainwindow *)w_parent; EDFCompatDialog = new QDialog; EDFCompatDialog->setMinimumSize(800, 180); EDFCompatDialog->setMaximumSize(800, 180); EDFCompatDialog->setWindowTitle("Check EDF(+) / BDF(+) compatibility"); EDFCompatDialog->setModal(true); EDFCompatDialog->setAttribute(Qt::WA_DeleteOnClose, true); filelist = new QListWidget(EDFCompatDialog); filelist->setGeometry(10, 10, 780, 75); filelist->setSelectionBehavior(QAbstractItemView::SelectRows); filelist->setSelectionMode(QAbstractItemView::SingleSelection); for(i=0; ifiles_open; i++) { if((mainwindow->edfheaderlist[i]->edf)||(mainwindow->edfheaderlist[i]->bdf)) { new QListWidgetItem(QString::fromLocal8Bit(mainwindow->edfheaderlist[i]->filename), filelist); } } CheckButton = new QPushButton(EDFCompatDialog); CheckButton->setGeometry(10, 140, 100, 25); CheckButton->setText("Check"); CloseButton = new QPushButton(EDFCompatDialog); CloseButton->setGeometry(690, 140, 100, 25); CloseButton->setText("Close"); QObject::connect(CloseButton, SIGNAL(clicked()), EDFCompatDialog, SLOT(close())); QObject::connect(CheckButton, SIGNAL(clicked()), this, SLOT(CheckButtonClicked())); filelist->setCurrentRow(mainwindow->files_open - 1); EDFCompatDialog->exec(); } void UI_EDFCompatwindow::CheckButtonClicked() { int i, j, k, p, r=0, n, len, edfsignals, datarecords, recordsize, edfplus, discontinuous, bdf, bdfplus, *annot_ch, nr_annot_chns, max, onset, duration, duration_start, zero, max_tal_ln, error, temp, samplesize, annots_in_tal, progress_steps; char *scratchpad, *cnv_buf, txt_string[2048]; double data_record_duration, elapsedtime, time_tmp=0.0; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; FILE *inputfile; struct edfparamblock *edfparam; if(!mainwindow->files_open) { EDFCompatDialog->close(); return; } CheckButton->setEnabled(false); CloseButton->setEnabled(false); for(i=0; ifiles_open; i++) { if(!strcmp(mainwindow->edfheaderlist[i]->filename, filelist->item(filelist->currentRow())->text().toLocal8Bit().data())) { break; } } if(i==mainwindow->files_open) return; n = i; inputfile = mainwindow->edfheaderlist[n]->file_hdl; edfsignals = mainwindow->edfheaderlist[n]->edfsignals; recordsize = mainwindow->edfheaderlist[n]->recordsize; edfparam = mainwindow->edfheaderlist[n]->edfparam; nr_annot_chns = mainwindow->edfheaderlist[n]->nr_annot_chns; datarecords = mainwindow->edfheaderlist[n]->datarecords; data_record_duration = mainwindow->edfheaderlist[n]->data_record_duration; edfplus = mainwindow->edfheaderlist[n]->edfplus; bdfplus = mainwindow->edfheaderlist[n]->bdfplus; discontinuous = mainwindow->edfheaderlist[n]->discontinuous; annot_ch = mainwindow->edfheaderlist[n]->annot_ch; bdf = mainwindow->edfheaderlist[n]->bdf; if(bdf) samplesize = 3; else samplesize = 2; cnv_buf = (char *)calloc(1, recordsize); if(cnv_buf==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error. (cnv_buf)."); messagewindow.exec(); EDFCompatDialog->close(); return; } max_tal_ln = 0; for(i=0; iclose(); return; } if(fseeko(inputfile, (long long)((edfsignals + 1) * 256), SEEK_SET)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading inputfile."); messagewindow.exec(); free(cnv_buf); free(scratchpad); EDFCompatDialog->close(); return; } /***************** check the maximum and minimum of samples of all signals ******************************/ QProgressDialog progress("Checking...", "Abort", 0, datarecords, EDFCompatDialog); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); progress_steps = datarecords / 100; if(progress_steps < 1) { progress_steps = 1; } elapsedtime = 0.0; for(i=0; iprocessEvents(); if(progress.wasCanceled() == true) { free(cnv_buf); free(scratchpad); EDFCompatDialog->close(); return; } } if(fread(cnv_buf, recordsize, 1, inputfile)!=1) { progress.reset(); snprintf(txt_string, 2048, "An error occurred while reading inputfile at datarecord %i.", i + 1); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); free(cnv_buf); free(scratchpad); EDFCompatDialog->close(); return; } for(j=0; j edfparam[j].dig_max) { progress.reset(); snprintf(txt_string, 2048, "Error.\n\nIn datarecord %i -> signal %i -> sample %i is more than digital maximum.\n" "Digital maximum for this signal as written in header is %i but sample is %i.\n" "Offset from start of file: 0x%X\n", i + 1, j + 1, k + 1, edfparam[j].dig_max, temp, (i * recordsize) + edfparam[j].buf_offset + (k * samplesize) + (edfsignals * 256) + 256); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); free(scratchpad); free(cnv_buf); EDFCompatDialog->close(); return; } if(temp < edfparam[j].dig_min) { progress.reset(); snprintf(txt_string, 2048, "Error.\n\nIn datarecord %i -> signal %i -> sample %i is less than digital minimum.\n" "Digital minimum for this signal as written in header is %i but sample is %i.\n" "Offset from start of file: 0x%X\n", i + 1, j + 1, k + 1, edfparam[j].dig_min, temp, (i * recordsize) + edfparam[j].buf_offset + (k * samplesize) + (edfsignals * 256) + 256); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); free(cnv_buf); free(scratchpad); EDFCompatDialog->close(); return; } } } /************** process annotationsignals (if any) **************/ error = 0; for(r=0; r(data_record_duration+0.00000001))||((time_tmp-elapsedtime)<(data_record_duration-0.00000001))) { error = 3; goto END; } } } else { if(time_tmp>=1.0) { error = 2; goto END; } } elapsedtime = time_tmp; error = 0; break; } } } } for(k=0; k1) { error = 34; goto END; } zero = 0; if((scratchpad[n]==20)||(scratchpad[n]==21)) { if(scratchpad[n]==21) { if(duration||duration_start||onset||annots_in_tal) { /* it's not allowed to have multiple duration fields */ error = 35; /* in one TAL or to have a duration field which is */ goto END; /* not immediately behind the onsetfield */ } duration_start = 1; } if((scratchpad[n]==20)&&onset&&(!duration_start)) { annots_in_tal++; n = 0; continue; } if(!onset) { scratchpad[n] = 0; if(is_onset_number(scratchpad)) { error = 36; goto END; } onset = 1; n = 0; continue; } if(duration_start) { scratchpad[n] = 0; if(is_duration_number(scratchpad)) { error = 37; goto END; } duration = 1; duration_start = 0; n = 0; continue; } } n++; } END: /****************** end ************************/ if(error) { progress.reset(); if(error==1) { snprintf(txt_string, 1700, "Error.\n\nInvalid annotation in datarecord %i.\n", i + 1); } if(error==2) { snprintf(txt_string, 1700, "Error.\n\n" "Time keeping annotation in the first datarecord is %.12f\n" "expected <1.0\n", time_tmp); } if(error==3) { snprintf(txt_string, 1700, "Error.\n\n" "Datarecord duration is %.12f but timestep between\n" "datarecord %i and preceding datarecord is %.12f.\n", data_record_duration, i + 1, time_tmp - elapsedtime); } if(error==4) { snprintf(txt_string, 1700, "Error.\n\nDatarecords are not in chronological order,\n" "datarecord %i has timestamp %.12f and datarecord %i has timestamp %.12f.\n", i, elapsedtime, i + 1, time_tmp); } if(error==5) { snprintf(txt_string, 1700, "Error.\n\nInvalid annotation in datarecord %i,\n" "last byte is not a null-byte.\n", i + 1); } if(error==6) { snprintf(txt_string, 1700, "Error.\n\nInvalid annotation in datarecord %i,\n" "timekeeping TAL (the first annotation in the first annotations signal)\n" "should have two consecutive bytes with values 0x14 immediately after\n" "the number.\n", i + 1); } if(error==33) { snprintf(txt_string, 1700, "Error.\n\nInvalid annotation in datarecord %i,\n" "byte before the first null-byte should be equal to 0x14.\n", i + 1); } if(error==34) { snprintf(txt_string, 1700, "Error.\n\nInvalid annotation in datarecord %i,\n" "after two consecutive null-bytes all of the remaining bytes should be null-bytes as well.\n" "(it's not allowed to have two or more null-bytes between two TAL's)\n", i + 1); } if(error==35) { snprintf(txt_string, 1700, "Error.\n\nInvalid annotation in datarecord %i,\n" "it's not allowed to have multiple duration fields in one TAL or\n" "to have a duration field which is not immediately behind the onsetfield.\n", i + 1); } if(error==36) { snprintf(txt_string, 1700, "Error.\n\nInvalid annotation in datarecord %i,\n" "onset has an invalid number.\n", i + 1); } if(error==37) { snprintf(txt_string, 1700, "Error.\n\nInvalid annotation in datarecord %i,\n" "duration has an invalid number.\n", i + 1); } len = strlen(txt_string); p = (i * recordsize) + (edfsignals * 256) + 256 + (edfparam[annot_ch[r]].buf_offset); snprintf(txt_string + len, 348, "Offset from start of file: 0x%X\n\n" "Stopped at the first error, additional errors may be present.", p); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); free(cnv_buf); free(scratchpad); EDFCompatDialog->close(); return; } } } progress.reset(); if(bdf) { if(bdfplus) { QMessageBox messagewindow(QMessageBox::Information, "Result", "No errors found, file is BDF+ compliant."); messagewindow.setIconPixmap(QPixmap(":/images/ok.png")); messagewindow.exec(); } else { QMessageBox messagewindow(QMessageBox::Information, "Result", "No errors found, file is BDF compliant."); messagewindow.setIconPixmap(QPixmap(":/images/ok.png")); messagewindow.exec(); } } else { if(edfplus) { QMessageBox messagewindow(QMessageBox::Information, "Result", "No errors found, file is EDF+ compliant."); messagewindow.setIconPixmap(QPixmap(":/images/ok.png")); messagewindow.exec(); } else { QMessageBox messagewindow(QMessageBox::Information, "Result", "No errors found, file is EDF compliant."); messagewindow.setIconPixmap(QPixmap(":/images/ok.png")); messagewindow.exec(); } } free(cnv_buf); free(scratchpad); EDFCompatDialog->close(); } int UI_EDFCompatwindow::is_duration_number(char *str) { int i, l, hasdot = 0; l = strlen(str); if(!l) return(1); if((str[0] == '.')||(str[l-1] == '.')) return(1); for(i=0; i57)) return(1); } } return(0); } int UI_EDFCompatwindow::is_onset_number(char *str) { int i, l, hasdot = 0; l = strlen(str); if(l<2) return(1); if((str[0]!='+')&&(str[0]!='-')) return(1); if((str[1] == '.')||(str[l-1] == '.')) return(1); for(i=1; i57)) return(1); } } return(0); } int UI_EDFCompatwindow::is_integer_number(char *str) { int i=0, l, hasspace = 0, hassign=0, digit=0; l = strlen(str); if(!l) return(1); if((str[0]=='+')||(str[0]=='-')) { hassign++; i++; } for(; i57)) { return(1); } else { if(hasspace) { return(1); } digit++; } } } if(digit) return(0); else return(1); } int UI_EDFCompatwindow::is_number(char *str) { int i=0, l, hasspace = 0, hassign=0, digit=0, hasdot=0; l = strlen(str); if(!l) return(1); if((str[0]=='+')||(str[0]=='-')) { hassign++; i++; } if(str[l-1]=='.') { return(1); } for(; i57))&&str[i]!='.') { return(1); } else { if(hasspace) { return(1); } if(str[i]=='.') { if(hasdot||!i) return(1); if(hassign&&(i<2)) return(1); hasdot++; } else { digit++; } } } } if(digit) return(0); else return(1); } edfbrowser_157_source/PaxHeaders.7921/active_file_chooser.cpp0000644000000000000000000000013212646460742021366 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/active_file_chooser.cpp0000644000175000001440000000506012646460742021730 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "active_file_chooser.h" UI_activeFileChooserWindow::UI_activeFileChooserWindow(int *file_nr, QWidget *mainwndw) { int i; mainwindow = (UI_Mainwindow *)mainwndw; file_num = file_nr; *file_num = -1; chooserDialog = new QDialog; chooserDialog->setMinimumSize(800, 200); chooserDialog->setMaximumSize(800, 200); chooserDialog->setWindowTitle("Choose file"); chooserDialog->setModal(true); chooserDialog->setAttribute(Qt::WA_DeleteOnClose, true); filelist = new QListWidget(chooserDialog); filelist->setGeometry(10, 10, 780, 110); filelist->setSelectionBehavior(QAbstractItemView::SelectRows); filelist->setSelectionMode(QAbstractItemView::SingleSelection); for(i=0; ifiles_open; i++) { new QListWidgetItem(QString::fromLocal8Bit(mainwindow->edfheaderlist[i]->filename), filelist); } okButton = new QPushButton(chooserDialog); okButton->setGeometry(10, 140, 100, 25); okButton->setText("OK"); cancelButton = new QPushButton(chooserDialog); cancelButton->setGeometry(690, 140, 100, 25); cancelButton->setText("Cancel"); QObject::connect(cancelButton, SIGNAL(clicked()), chooserDialog, SLOT(close())); QObject::connect(okButton, SIGNAL(clicked()), this, SLOT(okButtonClicked())); filelist->setCurrentRow(mainwindow->files_open - 1); chooserDialog->exec(); } void UI_activeFileChooserWindow::okButtonClicked() { if(!mainwindow->files_open) { *file_num = -1; chooserDialog->close(); return; } *file_num = filelist->currentRow(); chooserDialog->close(); } edfbrowser_157_source/PaxHeaders.7921/images.qrc0000644000000000000000000000013212646460742016642 xustar0030 mtime=1452958178.256246703 30 atime=1452958178.256246703 30 ctime=1452958178.256246703 edfbrowser_157_source/images.qrc0000644000175000001440000000024412646460742017203 0ustar00guvusers00000000000000 images/edf.png images/splash.png images/ok.png edfbrowser_157_source/PaxHeaders.7921/edf_annot_list.c0000644000000000000000000000013212646460742020022 xustar0030 mtime=1452958178.243246747 30 atime=1452958178.243246747 30 ctime=1452958178.243246747 edfbrowser_157_source/edf_annot_list.c0000644000175000001440000002116312646460742020366 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "edf_annot_list.h" void edfplus_annotation_add_item(struct annotationblock **list, struct annotationblock *annotation) { struct annotationblock *annotlist; annotlist = *list; annotation->next_annotation = NULL; if(annotlist == NULL) { annotation->former_annotation = NULL; *list = annotation; return; } while(annotlist->next_annotation != NULL) { if(annotlist->next_annotation->onset > annotation->onset) { break; } annotlist = annotlist->next_annotation; } annotation->next_annotation = annotlist->next_annotation; if(annotation->next_annotation != NULL) { annotation->next_annotation->former_annotation = annotation; } annotlist->next_annotation = annotation; annotation->former_annotation = annotlist; } void edfplus_annotation_add_copy(struct annotationblock **list, struct annotationblock *annotation) { struct annotationblock *annotlist, *new_annot; annotlist = *list; new_annot = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); if(new_annot == NULL) { return; } memcpy(new_annot, annotation, sizeof(struct annotationblock)); new_annot->next_annotation = NULL; if(annotlist == NULL) { new_annot->former_annotation = NULL; *list = new_annot; return; } while(annotlist->next_annotation != NULL) { annotlist = annotlist->next_annotation; } annotlist->next_annotation = new_annot; new_annot->former_annotation = annotlist; } int edfplus_annotation_count(struct annotationblock **list) { int n=0; struct annotationblock *annotlist; annotlist = *list; while(annotlist != NULL) { annotlist = annotlist->next_annotation; n++; } return(n); } void edfplus_annotation_delete(struct annotationblock **list, int n) { struct annotationblock *annotlist; annotlist = *list; if(annotlist==NULL) { return; } while(n) { if(annotlist->next_annotation==NULL) { return; } annotlist = annotlist->next_annotation; n--; } if(annotlist->former_annotation!=NULL) { annotlist->former_annotation->next_annotation = annotlist->next_annotation; } if(annotlist->next_annotation!=NULL) { annotlist->next_annotation->former_annotation = annotlist->former_annotation; } if(annotlist->former_annotation==NULL) { *list = annotlist->next_annotation; } free(annotlist); } void edfplus_annotation_delete_list(struct annotationblock **list) { struct annotationblock *annotlist; annotlist = *list; if(annotlist == NULL) { return; } while(annotlist->next_annotation != NULL) { annotlist = annotlist->next_annotation; free(annotlist->former_annotation); } free(annotlist); *list = NULL; } struct annotationblock * edfplus_annotation_item(struct annotationblock **list, int n) { struct annotationblock *annotlist; annotlist = *list; if(annotlist == NULL) { return(NULL); } while(n) { if(annotlist->next_annotation == NULL) { return(NULL); } annotlist = annotlist->next_annotation; n--; } return(annotlist); } void edfplus_annotation_sort(struct annotationblock **list) // sort the annotationlist based on the onset time { struct annotationblock *p1, *p2, *p3, *pm, *p5; p1 = *list; while(p1 != NULL) { if(p1->next_annotation == NULL) { break; } if(p1->next_annotation->onset < p1->onset) { pm = p1; p2 = p1->next_annotation; // this one we take out p3 = p2->next_annotation; // take out p1->next_annotation = p3; if(p3 != NULL) { p3->former_annotation = p1; } // take out done while(1) // search backwards till we find the right place to put it { p5 = pm->former_annotation; if(p5 == NULL) { pm->former_annotation = p2; p2->next_annotation = pm; p2->former_annotation = NULL; *list = p2; break; } if(p5->onset <= p2->onset) // insert it here { pm->former_annotation = p2; p2->next_annotation = pm; p2->former_annotation = p5; p5->next_annotation = p2; break; } pm = p5; } } else { p1 = p1->next_annotation; // continue searching the list from where we stopped before } } } struct annotationblock * edfplus_annotation_copy_list(struct annotationblock **list) { struct annotationblock *annot, *annot2, *annot3; annot = *list; if(annot==NULL) { return(NULL); } annot2 = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); annot3 = annot2; memcpy(annot2, annot, sizeof(struct annotationblock)); annot = annot->next_annotation; while(annot!=NULL) { annot2->next_annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); memcpy(annot2->next_annotation, annot, sizeof(struct annotationblock)); annot2->next_annotation->former_annotation = annot2; annot2 = annot2->next_annotation; annot = annot->next_annotation; } return(annot3); } int get_tal_timestamp_digit_cnt(struct edfhdrblock *hdr) { int timestamp_digits; char scratchpad[256]; long long time; if(hdr==NULL) { return(-1); } time = (hdr->datarecords * hdr->long_data_record_duration) / TIME_DIMENSION; #ifdef _WIN32 timestamp_digits = __mingw_snprintf(scratchpad, 256, "%lli", time); #else timestamp_digits = snprintf(scratchpad, 256, "%lli", time); #endif return(timestamp_digits); } int get_tal_timestamp_decimal_cnt(struct edfhdrblock *hdr) { int i, j, timestamp_decimals; if(hdr==NULL) { return(-1); } j = 10; for(timestamp_decimals=7; timestamp_decimals>0; timestamp_decimals--) { if(hdr->long_data_record_duration % j) { break; } j *= 10; } if((hdr->edfplus==1)||(hdr->bdfplus==1)) { j = 10; for(i=7; i>0; i--) { if(hdr->starttime_offset % j) { break; } j *= 10; } if(i > timestamp_decimals) { timestamp_decimals = i; } } return(timestamp_decimals); } int get_max_annotation_strlen(struct annotationblock **list) { int j, len, annot_descr_len=0, annot_duration_len=0, timestamp_digits=0, timestamp_decimals=0; char scratchpad[256]; struct annotationblock *annot; annot = list[0]; if(annot==NULL) { return(0); } while(annot!=NULL) { #ifdef _WIN32 len = __mingw_snprintf(scratchpad, 256, "%lli", annot->onset / TIME_DIMENSION); #else len = snprintf(scratchpad, 256, "%lli", annot->onset / TIME_DIMENSION); #endif if(len > timestamp_digits) { timestamp_digits = len; } j = 10; for(len=7; len>0; len--) { if(annot->onset % j) { break; } j *= 10; } if(len > timestamp_decimals) { timestamp_decimals = len; } len = strlen(annot->annotation); if(len>annot_descr_len) { annot_descr_len = len; } len = strlen(annot->duration); if(len>annot_duration_len) { annot_duration_len = len; } annot = annot->next_annotation; } if(annot_duration_len) { annot_duration_len++; } if(timestamp_decimals) { timestamp_decimals++; } // printf("annot_descr_len is %i\n" // "annot_duration_len is %i\n" // "timestamp_digits is %i\n" // "timestamp_decimals is %i\n", // annot_descr_len, // annot_duration_len, // timestamp_digits, // timestamp_decimals); return(annot_descr_len + annot_duration_len + timestamp_digits + timestamp_decimals + 4); } edfbrowser_157_source/PaxHeaders.7921/spike_filter_dialog.cpp0000644000000000000000000000013212646460742021371 xustar0030 mtime=1452958178.249246726 30 atime=1452958178.249246726 30 ctime=1452958178.249246726 edfbrowser_157_source/spike_filter_dialog.cpp0000644000175000001440000001402312646460742021732 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2014, 2015, 2016 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 . * *************************************************************************** */ #include "spike_filter_dialog.h" UI_SpikeFilterDialog::UI_SpikeFilterDialog(QWidget *w_parent) { int i, n, s, sf=0; QListWidgetItem *item; QList selectedlist; mainwindow = (UI_Mainwindow *)w_parent; spikefilterdialog = new QDialog; spikefilterdialog->setMinimumSize(620, 365); spikefilterdialog->setMaximumSize(620, 365); spikefilterdialog->setWindowTitle("Add a spike filter"); spikefilterdialog->setModal(true); spikefilterdialog->setAttribute(Qt::WA_DeleteOnClose, true); velocityLabel = new QLabel(spikefilterdialog); velocityLabel->setGeometry(20, 45, 60, 25); velocityLabel->setText("Velocity"); velocitySpinBox = new QDoubleSpinBox(spikefilterdialog); velocitySpinBox->setGeometry(90, 45, 230, 25); velocitySpinBox->setDecimals(6); velocitySpinBox->setSuffix(" units/(0.5 mSec)"); velocitySpinBox->setMinimum(0.000001); velocitySpinBox->setMaximum(1E10); velocitySpinBox->setValue(1000.0); holdOffLabel = new QLabel(spikefilterdialog); holdOffLabel->setGeometry(20, 90, 60, 25); holdOffLabel->setText("Hold-off"); holdOffSpinBox = new QSpinBox(spikefilterdialog); holdOffSpinBox->setGeometry(90, 90, 230, 25); holdOffSpinBox->setSuffix(" milliSec"); holdOffSpinBox->setMinimum(10); holdOffSpinBox->setMaximum(1000); holdOffSpinBox->setValue(100); listlabel = new QLabel(spikefilterdialog); listlabel->setGeometry(440, 20, 100, 25); listlabel->setText("Select signals:"); list = new QListWidget(spikefilterdialog); list->setGeometry(440, 45, 160, 300); list->setSelectionBehavior(QAbstractItemView::SelectRows); list->setSelectionMode(QAbstractItemView::ExtendedSelection); CancelButton = new QPushButton(spikefilterdialog); CancelButton->setGeometry(300, 320, 100, 25); CancelButton->setText("&Close"); ApplyButton = new QPushButton(spikefilterdialog); ApplyButton->setGeometry(20, 320, 100, 25); ApplyButton->setText("&Apply"); ApplyButton->setVisible(false); for(i=0; isignalcomps; i++) { sf = ((long long)mainwindow->signalcomp[i]->edfhdr->edfparam[mainwindow->signalcomp[i]->edfsignal[0]].smp_per_record * TIME_DIMENSION) / mainwindow->signalcomp[i]->edfhdr->long_data_record_duration; if(sf < 4000) { continue; } item = new QListWidgetItem; if(mainwindow->signalcomp[i]->alias[0] != 0) { item->setText(mainwindow->signalcomp[i]->alias); } else { item->setText(mainwindow->signalcomp[i]->signallabel); } item->setData(Qt::UserRole, QVariant(i)); list->addItem(item); } n = list->count(); for(i=0; iitem(i); s = item->data(Qt::UserRole).toInt(); if(mainwindow->signalcomp[s]->spike_filter != NULL) { velocitySpinBox->setValue(mainwindow->signalcomp[s]->spike_filter_velocity); holdOffSpinBox->setValue(mainwindow->signalcomp[s]->spike_filter_holdoff); item->setSelected(true); } else { item->setSelected(false); } } QObject::connect(ApplyButton, SIGNAL(clicked()), this, SLOT(ApplyButtonClicked())); QObject::connect(CancelButton, SIGNAL(clicked()), spikefilterdialog, SLOT(close())); QObject::connect(list, SIGNAL(itemSelectionChanged()), this, SLOT(ApplyButtonClicked())); QObject::connect(velocitySpinBox, SIGNAL(valueChanged(double)), this, SLOT(ApplyButtonClicked())); QObject::connect(holdOffSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ApplyButtonClicked())); spikefilterdialog->exec(); } void UI_SpikeFilterDialog::ApplyButtonClicked() { int i, s, n, sf, holdoff; double velocity; QListWidgetItem *item; QList selectedlist; for(i=0; isignalcomps; i++) { if(mainwindow->signalcomp[i]->spike_filter) { free_spike_filter(mainwindow->signalcomp[i]->spike_filter); mainwindow->signalcomp[i]->spike_filter = NULL; } } selectedlist = list->selectedItems(); n = selectedlist.size(); for(i=0; idata(Qt::UserRole).toInt(); velocity = velocitySpinBox->value() / mainwindow->signalcomp[s]->edfhdr->edfparam[mainwindow->signalcomp[s]->edfsignal[0]].bitvalue; if(velocity < 0) velocity *= -1; holdoff = holdOffSpinBox->value(); sf = ((long long)mainwindow->signalcomp[s]->edfhdr->edfparam[mainwindow->signalcomp[s]->edfsignal[0]].smp_per_record * TIME_DIMENSION) / mainwindow->signalcomp[s]->edfhdr->long_data_record_duration; mainwindow->signalcomp[s]->spike_filter = create_spike_filter(sf, velocity, holdoff, NULL); if(mainwindow->signalcomp[s]->spike_filter == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while creating a spike filter."); messagewindow.exec(); } mainwindow->signalcomp[s]->spike_filter_velocity = velocitySpinBox->value(); mainwindow->signalcomp[s]->spike_filter_holdoff = holdOffSpinBox->value(); } mainwindow->setup_viewbuf(); } edfbrowser_157_source/PaxHeaders.7921/import_annotations.cpp0000644000000000000000000000013212646460742021321 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/import_annotations.cpp0000644000175000001440000016164112646460742021673 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "import_annotations.h" #define XML_FORMAT 0 #define ASCIICSV_FORMAT 1 #define DCEVENT_FORMAT 2 #define EDFPLUS_FORMAT 3 #define TAB_CNT 4 UI_ImportAnnotationswindow::UI_ImportAnnotationswindow(QWidget *w_parent) { int i; mainwindow = (UI_Mainwindow *)w_parent; if(mainwindow->files_open < 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not import annotations without opening an EDF/BDF-file first."); messagewindow.exec(); return; } ImportAnnotsDialog = new QDialog; ImportAnnotsDialog->setMinimumSize(490, 500); ImportAnnotsDialog->setMaximumSize(490, 500); ImportAnnotsDialog->setWindowTitle("Import annotations/events"); ImportAnnotsDialog->setModal(true); ImportAnnotsDialog->setAttribute(Qt::WA_DeleteOnClose, true); tabholder = new QTabWidget; tab_index_array[ASCIICSV_FORMAT] = 0; tab_index_array[DCEVENT_FORMAT] = 1; tab_index_array[XML_FORMAT] = 2; tab_index_array[EDFPLUS_FORMAT] = 3; for(i=0; isetText("Column separator"); SeparatorLabel->setMinimumSize(200, 25); OnsetColumnLabel = new QLabel(ImportAnnotsDialog); OnsetColumnLabel->setText("Onset column"); OnsetColumnLabel->setMinimumSize(200, 25); DatastartLabel = new QLabel(ImportAnnotsDialog); DatastartLabel->setText("Data starts at line"); DatastartLabel->setMinimumSize(200, 25); OnsetTimeLabel = new QLabel(ImportAnnotsDialog); OnsetTimeLabel->setText("Onset time coding is"); OnsetTimeLabel->setMinimumSize(200, 25); SeparatorLineEdit = new QLineEdit(ImportAnnotsDialog); SeparatorLineEdit->setMaxLength(3); SeparatorLineEdit->setText("tab"); SeparatorLineEdit->setMinimumSize(80, 25); DescriptionLineEdit = new QLineEdit(ImportAnnotsDialog); DescriptionLineEdit->setMaxLength(20); DescriptionLineEdit->setEnabled(false); DescriptionLineEdit->setMinimumSize(80, 25); OnsetColumnSpinBox = new QSpinBox(ImportAnnotsDialog); OnsetColumnSpinBox->setRange(1,256); OnsetColumnSpinBox->setValue(1); OnsetColumnSpinBox->setMinimumSize(80, 25); DurationColumnSpinBox = new QSpinBox(ImportAnnotsDialog); DurationColumnSpinBox->setRange(1,256); DurationColumnSpinBox->setValue(3); DurationColumnSpinBox->setMinimumSize(80, 25); DescriptionColumnSpinBox = new QSpinBox(ImportAnnotsDialog); DescriptionColumnSpinBox->setRange(1,256); DescriptionColumnSpinBox->setValue(2); DescriptionColumnSpinBox->setMinimumSize(80, 25); DatastartSpinbox = new QSpinBox(ImportAnnotsDialog); DatastartSpinbox->setRange(1,100); DatastartSpinbox->setValue(1); DatastartSpinbox->setMinimumSize(80, 25); RelativeTimeComboBox = new QComboBox(ImportAnnotsDialog); RelativeTimeComboBox->addItem("in seconds, relative to start of file"); RelativeTimeComboBox->addItem("hh:mm:ss"); RelativeTimeComboBox->addItem("hh:mm:ss.xxx"); RelativeTimeComboBox->addItem("yyyy-mm-ddThh:mm:ss"); RelativeTimeComboBox->addItem("yyyy-mm-ddThh:mm:ss.xxx"); RelativeTimeComboBox->setMinimumSize(200, 25); DescriptionColumnRadioButton = new QRadioButton("Description column"); DescriptionColumnRadioButton->setMinimumSize(198, 25); DescriptionColumnRadioButton->setChecked(true); UseManualDescriptionRadioButton = new QRadioButton("Manual description"); UseManualDescriptionRadioButton->setMinimumSize(198, 25); DurationCheckBox = new QCheckBox(" Duration column", ImportAnnotsDialog); DurationCheckBox->setTristate(false); DurationCheckBox->setCheckState(Qt::Unchecked); DurationCheckBox->setMinimumSize(198, 25); asciiSettingsHBoxLayout1 = new QHBoxLayout; asciiSettingsHBoxLayout1->addWidget(SeparatorLabel); asciiSettingsHBoxLayout1->addWidget(SeparatorLineEdit); asciiSettingsHBoxLayout1->addStretch(100); asciiSettingsHBoxLayout2 = new QHBoxLayout; asciiSettingsHBoxLayout2->addWidget(OnsetColumnLabel); asciiSettingsHBoxLayout2->addWidget(OnsetColumnSpinBox); asciiSettingsHBoxLayout2->addStretch(100); asciiSettingsHBoxLayout3 = new QHBoxLayout; asciiSettingsHBoxLayout3->addWidget(DescriptionColumnRadioButton); asciiSettingsHBoxLayout3->addWidget(DescriptionColumnSpinBox); asciiSettingsHBoxLayout3->addStretch(100); asciiSettingsHBoxLayout4 = new QHBoxLayout; asciiSettingsHBoxLayout4->addWidget(UseManualDescriptionRadioButton); asciiSettingsHBoxLayout4->addWidget(DescriptionLineEdit); asciiSettingsHBoxLayout4->addStretch(100); asciiSettingsHBoxLayout7 = new QHBoxLayout; asciiSettingsHBoxLayout7->addWidget(DurationCheckBox); asciiSettingsHBoxLayout7->addWidget(DurationColumnSpinBox); asciiSettingsHBoxLayout7->addStretch(100); asciiSettingsHBoxLayout5 = new QHBoxLayout; asciiSettingsHBoxLayout5->addWidget(DatastartLabel); asciiSettingsHBoxLayout5->addWidget(DatastartSpinbox); asciiSettingsHBoxLayout5->addStretch(100); asciiSettingsHBoxLayout6 = new QHBoxLayout; asciiSettingsHBoxLayout6->addWidget(OnsetTimeLabel); asciiSettingsHBoxLayout6->addWidget(RelativeTimeComboBox); asciiSettingsHBoxLayout6->addStretch(100); asciiSettingsVBoxLayout = new QVBoxLayout; asciiSettingsVBoxLayout->addLayout(asciiSettingsHBoxLayout1); asciiSettingsVBoxLayout->addLayout(asciiSettingsHBoxLayout2); asciiSettingsVBoxLayout->addLayout(asciiSettingsHBoxLayout3); asciiSettingsVBoxLayout->addLayout(asciiSettingsHBoxLayout4); asciiSettingsVBoxLayout->addLayout(asciiSettingsHBoxLayout7); asciiSettingsVBoxLayout->addLayout(asciiSettingsHBoxLayout5); asciiSettingsVBoxLayout->addLayout(asciiSettingsHBoxLayout6); tab[tab_index_array[ASCIICSV_FORMAT]]->setLayout(asciiSettingsVBoxLayout); DCEventSignalLabel = new QLabel(ImportAnnotsDialog); DCEventSignalLabel->setText("Signal"); DCEventSignalLabel->setMinimumSize(130, 25); DCEventBitTimeLabel = new QLabel(ImportAnnotsDialog); DCEventBitTimeLabel->setText("Bit Time"); DCEventBitTimeLabel->setMinimumSize(130, 25); DCEventTriggerLevelLabel = new QLabel(ImportAnnotsDialog); DCEventTriggerLevelLabel->setText("Trigger Level"); DCEventTriggerLevelLabel->setMinimumSize(130, 25); DCEventSignalComboBox = new QComboBox(ImportAnnotsDialog); for(i=0; isignalcomps; i++) { DCEventSignalComboBox->addItem(mainwindow->signalcomp[i]->signallabel); } DCEventSignalComboBox->setMinimumSize(130, 25); BitTimeSpinbox = new QSpinBox(ImportAnnotsDialog); BitTimeSpinbox->setRange(1,1000); BitTimeSpinbox->setSuffix(" mS"); BitTimeSpinbox->setValue(10); BitTimeSpinbox->setMinimumSize(130, 25); DCEventTriggerLevelSpinBox = new QDoubleSpinBox(ImportAnnotsDialog); DCEventTriggerLevelSpinBox->setDecimals(3); DCEventTriggerLevelSpinBox->setRange(-10000.0, 10000.0); DCEventTriggerLevelSpinBox->setValue(500.0); DCEventTriggerLevelSpinBox->setMinimumSize(130, 25); if(mainwindow->signalcomps) { DCEventSignalChanged(0); } DCEventHBoxLayout1 = new QHBoxLayout; DCEventHBoxLayout1->addWidget(DCEventSignalLabel); DCEventHBoxLayout1->addWidget(DCEventSignalComboBox); DCEventHBoxLayout1->addStretch(2); DCEventHBoxLayout2 = new QHBoxLayout; DCEventHBoxLayout2->addWidget(DCEventBitTimeLabel); DCEventHBoxLayout2->addWidget(BitTimeSpinbox); DCEventHBoxLayout2->addStretch(2); DCEventHBoxLayout3 = new QHBoxLayout; DCEventHBoxLayout3->addWidget(DCEventTriggerLevelLabel); DCEventHBoxLayout3->addWidget(DCEventTriggerLevelSpinBox); DCEventHBoxLayout3->addStretch(2); DCEventVBoxLayout = new QVBoxLayout; DCEventVBoxLayout->addStretch(10); DCEventVBoxLayout->addLayout(DCEventHBoxLayout1); DCEventVBoxLayout->addStretch(2); DCEventVBoxLayout->addLayout(DCEventHBoxLayout2); DCEventVBoxLayout->addStretch(2); DCEventVBoxLayout->addLayout(DCEventHBoxLayout3); DCEventVBoxLayout->addStretch(10); tab[tab_index_array[DCEVENT_FORMAT]]->setLayout(DCEventVBoxLayout); tabholder->addTab(tab[tab_index_array[ASCIICSV_FORMAT]], "ASCII / CSV"); tabholder->addTab(tab[tab_index_array[DCEVENT_FORMAT]], "DC-event (8-bit serial code)"); tabholder->addTab(tab[tab_index_array[XML_FORMAT]], "XML"); tabholder->addTab(tab[tab_index_array[EDFPLUS_FORMAT]], "EDF+ / BDF+"); IgnoreConsecutiveCheckBox = new QCheckBox(" Ignore consecutive events with the\n same description"); IgnoreConsecutiveCheckBox->setMinimumSize(300, 40); IgnoreConsecutiveCheckBox->setTristate(false); IgnoreConsecutiveCheckBox->setCheckState(Qt::Unchecked); ImportButton = new QPushButton(ImportAnnotsDialog); ImportButton->setMinimumSize(80, 25); ImportButton->setText("Import"); CloseButton = new QPushButton(ImportAnnotsDialog); CloseButton->setMinimumSize(80, 25); CloseButton->setText("Cancel"); horLayout = new QHBoxLayout; horLayout->addSpacing(30); horLayout->addWidget(ImportButton, 1); horLayout->addSpacing(300); horLayout->addWidget(CloseButton, 1); horLayout->addSpacing(30); mainLayout = new QVBoxLayout; mainLayout->addWidget(tabholder, 300); mainLayout->addSpacing(30); mainLayout->addWidget(IgnoreConsecutiveCheckBox, 30); mainLayout->addSpacing(30); mainLayout->addLayout(horLayout, 30); ImportAnnotsDialog->setLayout(mainLayout); SeparatorLineEdit->setText(mainwindow->import_annotations_var->separator); OnsetColumnSpinBox->setValue(mainwindow->import_annotations_var->onsetcolumn); DescriptionColumnSpinBox->setValue(mainwindow->import_annotations_var->descriptioncolumn); DescriptionLineEdit->setText(mainwindow->import_annotations_var->description); DurationColumnSpinBox->setValue(mainwindow->import_annotations_var->durationcolumn); DatastartSpinbox->setValue(mainwindow->import_annotations_var->datastartline); RelativeTimeComboBox->setCurrentIndex(mainwindow->import_annotations_var->onsettimeformat); BitTimeSpinbox->setValue(mainwindow->import_annotations_var->dceventbittime); DCEventTriggerLevelSpinBox->setValue(mainwindow->import_annotations_var->triggerlevel); if(mainwindow->import_annotations_var->manualdescription == 0) { DescriptionColumnRadioButton->setChecked(true); DescriptionColumnSpinBox->setEnabled(true); DescriptionLineEdit->setEnabled(false); } else { UseManualDescriptionRadioButton->setChecked(true); DescriptionColumnSpinBox->setEnabled(false); DescriptionLineEdit->setEnabled(true); if(mainwindow->import_annotations_var->format == ASCIICSV_FORMAT) { IgnoreConsecutiveCheckBox->setEnabled(false); } } if(mainwindow->import_annotations_var->useduration == 1) { DurationCheckBox->setCheckState(Qt::Checked); DurationColumnSpinBox->setEnabled(true); } else { DurationCheckBox->setCheckState(Qt::Unchecked); DurationColumnSpinBox->setEnabled(false); } if(mainwindow->import_annotations_var->ignoreconsecutive == 1) { IgnoreConsecutiveCheckBox->setCheckState(Qt::Checked); } else { IgnoreConsecutiveCheckBox->setCheckState(Qt::Unchecked); } if(mainwindow->import_annotations_var->format == EDFPLUS_FORMAT) { IgnoreConsecutiveCheckBox->setEnabled(false); } tabholder->setCurrentIndex(tab_index_array[mainwindow->import_annotations_var->format]); QObject::connect(CloseButton, SIGNAL(clicked()), ImportAnnotsDialog, SLOT(close())); QObject::connect(ImportButton, SIGNAL(clicked()), this, SLOT(ImportButtonClicked())); QObject::connect(DCEventSignalComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(DCEventSignalChanged(int))); QObject::connect(DescriptionColumnRadioButton, SIGNAL(toggled(bool)), this, SLOT(descriptionRadioButtonClicked(bool))); QObject::connect(UseManualDescriptionRadioButton, SIGNAL(toggled(bool)), this, SLOT(descriptionRadioButtonClicked(bool))); QObject::connect(DurationCheckBox, SIGNAL(stateChanged(int)), this, SLOT(DurationCheckBoxChanged(int))); QObject::connect(tabholder, SIGNAL(currentChanged(int)), this, SLOT(TabChanged(int))); ImportAnnotsDialog->exec(); } void UI_ImportAnnotationswindow::DurationCheckBoxChanged(int state) { if(state == Qt::Unchecked) { DurationColumnSpinBox->setEnabled(false); } else { DurationColumnSpinBox->setEnabled(true); } } void UI_ImportAnnotationswindow::descriptionRadioButtonClicked(bool) { if(DescriptionColumnRadioButton->isChecked() == true) { DescriptionColumnSpinBox->setEnabled(true); DescriptionLineEdit->setEnabled(false); IgnoreConsecutiveCheckBox->setEnabled(true); } if(UseManualDescriptionRadioButton->isChecked() == true) { DescriptionColumnSpinBox->setEnabled(false); DescriptionLineEdit->setEnabled(true); IgnoreConsecutiveCheckBox->setEnabled(false); } } void UI_ImportAnnotationswindow::TabChanged(int index) { if((index == tab_index_array[XML_FORMAT]) || (index == tab_index_array[DCEVENT_FORMAT])) { IgnoreConsecutiveCheckBox->setEnabled(true); } if(index == tab_index_array[EDFPLUS_FORMAT]) { IgnoreConsecutiveCheckBox->setEnabled(false); } if(index == tab_index_array[ASCIICSV_FORMAT]) { if(UseManualDescriptionRadioButton->isChecked() == true) { IgnoreConsecutiveCheckBox->setEnabled(false); } else { IgnoreConsecutiveCheckBox->setEnabled(true); } } } void UI_ImportAnnotationswindow::DCEventSignalChanged(int index) { char scratchpad[64]; if((index < 0) || (!mainwindow->signalcomps)) { DCEventTriggerLevelSpinBox->setSuffix(""); return; } strcpy(scratchpad, " "); strcat(scratchpad, mainwindow->signalcomp[index]->physdimension); DCEventTriggerLevelSpinBox->setSuffix(scratchpad); } void UI_ImportAnnotationswindow::ImportButtonClicked() { int i, input_format, error=0; ImportAnnotsDialog->setEnabled(false); i = tabholder->currentIndex(); for(input_format = 0; input_format < TAB_CNT; input_format++) { if(tab_index_array[input_format] == i) { break; } } if(input_format >= TAB_CNT) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Internal error (input_format >= TAB_CNT)."); messagewindow.exec(); ImportAnnotsDialog->setEnabled(true); return; } mainwindow->import_annotations_var->format = input_format; if(input_format == DCEVENT_FORMAT) { error = import_from_dcevent(); } if(input_format == EDFPLUS_FORMAT) { error = import_from_edfplus(); } if(input_format == XML_FORMAT) { error = import_from_xml(); } if(input_format == ASCIICSV_FORMAT) { error = import_from_ascii(); } if(mainwindow->annotations_dock[0] == NULL) { mainwindow->annotations_dock[0] = new UI_Annotationswindow(0, mainwindow); mainwindow->addDockWidget(Qt::RightDockWidgetArea, mainwindow->annotations_dock[0]->docklist, Qt::Vertical); if(!mainwindow->annotationlist[0]) { mainwindow->annotations_dock[0]->docklist->hide(); } } if(mainwindow->annotationlist[0]) { mainwindow->annotations_dock[0]->docklist->show(); mainwindow->annotations_edited = 1; mainwindow->annotations_dock[0]->updateList(); mainwindow->save_act->setEnabled(true); } mainwindow->maincurve->update(); if(!error) { QMessageBox messagewindow(QMessageBox::Information, "Ready", "Done."); messagewindow.setIconPixmap(QPixmap(":/images/ok.png")); messagewindow.exec(); } ImportAnnotsDialog->setEnabled(true); if(!error) { ImportAnnotsDialog->close(); } } int UI_ImportAnnotationswindow::import_from_xml(void) { int i, j, digits, ignore_consecutive=0; char path[MAX_PATH_LENGTH], last_description[256], result[XML_STRBUFLEN], duration[32]; long long onset=0LL, l_temp, utc_time=0LL; struct annotationblock *annotation; struct date_time_struct date_time; struct xml_handle *xml_hdl; duration[0] = 0; last_description[0] = 0; if(IgnoreConsecutiveCheckBox->checkState() == Qt::Checked) { ignore_consecutive = 1; } else { ignore_consecutive = 0; } strcpy(path, QFileDialog::getOpenFileName(0, "Open XML file", QString::fromLocal8Bit(mainwindow->recent_opendir), "XML files (*.xml *.XML)").toLocal8Bit().data()); if(!strcmp(path, "")) { return(1); } get_directory_from_path(mainwindow->recent_opendir, path, MAX_PATH_LENGTH); if(mainwindow->annotationlist_backup==NULL) { mainwindow->annotationlist_backup = edfplus_annotation_copy_list(&mainwindow->annotationlist[0]); } xml_hdl = xml_get_handle(path); if(xml_hdl==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); messagewindow.exec(); return(1); } if((xml_hdl->encoding != 1) && (xml_hdl->encoding != 2)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Encoding of XML-file must be UTF-8 or ISO-8859-1."); messagewindow.exec(); xml_close(xml_hdl); return(1); } if(strcmp(xml_hdl->elementname[xml_hdl->level], "annotationlist")) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find root element \"annotationlist\"."); messagewindow.exec(); xml_close(xml_hdl); return(1); } QApplication::setOverrideCursor(Qt::WaitCursor); for(j=0; j<10; j++) qApp->processEvents(); for(i=0; i<10000; i++) { if(xml_goto_nth_element_inside(xml_hdl, "annotation", i)) { if(i == 0) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find child element \"annotation\"."); messagewindow.exec(); xml_close(xml_hdl); return(1); } break; } if(xml_goto_nth_element_inside(xml_hdl, "onset", 0)) { xml_go_up(xml_hdl); continue; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not get content of element \"annotation\"."); messagewindow.exec(); xml_close(xml_hdl); return(1); } if(strlen(result) > 17) { if((result[4] == '-') && (result[7] == '-') && (result[10] == 'T') && (result[13] == ':') && (result[16] == ':')) { date_time.year = atoi(result); date_time.month = atoi(result + 5); date_time.day = atoi(result + 8); date_time.hour = atoi(result + 11); date_time.minute = atoi(result + 14); date_time.second = atoi(result + 17); date_time_to_utc(&utc_time, date_time); onset = utc_time - mainwindow->edfheaderlist[0]->utc_starttime; onset *= TIME_DIMENSION; if(strlen(result) > 19) { if(result[19] == '.') { for(digits=0; digits<32; digits++) { if((result[20 + digits] < '0') || (result[20 + digits] > '9')) { break; } } result[20 + digits] = 0; if(digits) { l_temp = (atoi(result + 20) * TIME_DIMENSION); for(; digits>0; digits--) { l_temp /= 10LL; } onset += l_temp; } } else { xml_go_up(xml_hdl); continue; } } } } else { xml_go_up(xml_hdl); continue; } xml_go_up(xml_hdl); if(!xml_goto_nth_element_inside(xml_hdl, "duration", 0)) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not get content of element \"duration\"."); messagewindow.exec(); xml_close(xml_hdl); return(1); } strncpy(duration, result, 16); duration[15] = 0; if((!(is_number(duration))) && (duration[0] != '-')) { remove_trailing_zeros(duration); } else { duration[0] = 0; } xml_go_up(xml_hdl); } if(xml_goto_nth_element_inside(xml_hdl, "description", 0)) { xml_go_up(xml_hdl); continue; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not get content of element \"description\"."); messagewindow.exec(); xml_close(xml_hdl); return(1); } if((!ignore_consecutive) || (strcmp(result, last_description))) { annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); if(annotation == NULL) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred (annotation)."); messagewindow.exec(); xml_close(xml_hdl); return(1); } annotation->onset = onset; strncpy(annotation->annotation, result, MAX_ANNOTATION_LEN); if(xml_hdl->encoding == 1) { latin1_to_utf8(annotation->annotation, MAX_ANNOTATION_LEN); } annotation->annotation[MAX_ANNOTATION_LEN] = 0; strcpy(annotation->duration, duration); edfplus_annotation_add_item(&mainwindow->annotationlist[0], annotation); strcpy(last_description, result); } xml_go_up(xml_hdl); xml_go_up(xml_hdl); } xml_close(xml_hdl); QApplication::restoreOverrideCursor(); return(0); } int UI_ImportAnnotationswindow::import_from_ascii(void) { int i, j, temp, column, column_end, str_start, line_nr, startline=1, onset_column=1, descr_column=2, duration_column=3, onset_is_set, descr_is_set, duration_is_set, max_descr_length, onsettime_coding=0, digits, days=0, ignore_consecutive=0, use_duration=0, manualdescription; char path[MAX_PATH_LENGTH], line[2048], scratchpad[256], str[2048], separator=',', description[256], last_description[256], duration[32]; long long onset=0LL, l_temp, last_onset=0LL, utc_time=0LL; FILE *inputfile=NULL; struct annotationblock *annotation; struct date_time_struct date_time; max_descr_length = 20; description[0] = 0; duration[0] = 0; last_description[0] = 0; if(UseManualDescriptionRadioButton->isChecked() == true) { manualdescription = 1; strcpy(description, DescriptionLineEdit->text().toLatin1().data()); } else { manualdescription = 0; } strcpy(str, SeparatorLineEdit->text().toLatin1().data()); if(!strcmp(str, "tab")) { separator = '\t'; } else { if(strlen(str)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Separator must be one character or \"tab\"."); messagewindow.exec(); return(1); } if((str[0]<32)||(str[0]>126)) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Separator character is not a valid ASCII character."); messagewindow.exec(); return(1); } if(str[0]=='.') { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Separator character can not be a dot."); messagewindow.exec(); return(1); } if((str[0]>47)&&(str[0]<58)) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Separator character can not be a number."); messagewindow.exec(); return(1); } separator = str[0]; } strcpy(mainwindow->import_annotations_var->separator, str); startline = DatastartSpinbox->value(); descr_column = DescriptionColumnSpinBox->value() - 1; onset_column = OnsetColumnSpinBox->value() - 1; duration_column = DurationColumnSpinBox->value() - 1; onsettime_coding = RelativeTimeComboBox->currentIndex(); if(DurationCheckBox->checkState() == Qt::Checked) { use_duration = 1; } else { use_duration = 0; } if((descr_column == onset_column) && (!manualdescription)) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Onset and Description can not be in the same column."); messagewindow.exec(); return(1); } if((duration_column == onset_column) && use_duration) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Onset and Duration can not be in the same column."); messagewindow.exec(); return(1); } if((descr_column == duration_column) && (!manualdescription) && use_duration) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Duration and Description can not be in the same column."); messagewindow.exec(); return(1); } mainwindow->import_annotations_var->onsettimeformat = onsettime_coding; mainwindow->import_annotations_var->onsetcolumn = onset_column + 1; mainwindow->import_annotations_var->descriptioncolumn = descr_column + 1; mainwindow->import_annotations_var->durationcolumn = duration_column + 1; mainwindow->import_annotations_var->useduration = use_duration; mainwindow->import_annotations_var->datastartline = startline; if(UseManualDescriptionRadioButton->isChecked() == true) { mainwindow->import_annotations_var->manualdescription = 1; } else { mainwindow->import_annotations_var->manualdescription = 0; } strcpy(mainwindow->import_annotations_var->description, DescriptionLineEdit->text().toLatin1().data()); if(IgnoreConsecutiveCheckBox->checkState() == Qt::Checked) { ignore_consecutive = 1; } else { ignore_consecutive = 0; } mainwindow->import_annotations_var->ignoreconsecutive = ignore_consecutive; strcpy(path, QFileDialog::getOpenFileName(0, "Open ASCII file", QString::fromLocal8Bit(mainwindow->recent_opendir), "ASCII files (*.txt *.TXT *.csv *.CSV)").toLocal8Bit().data()); if(!strcmp(path, "")) { return(1); } get_directory_from_path(mainwindow->recent_opendir, path, MAX_PATH_LENGTH); if(mainwindow->annotationlist_backup==NULL) { mainwindow->annotationlist_backup = edfplus_annotation_copy_list(&mainwindow->annotationlist[0]); } inputfile = fopeno(path, "rb"); if(inputfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); messagewindow.exec(); return(1); } rewind(inputfile); QApplication::setOverrideCursor(Qt::WaitCursor); for(j=0; j<10; j++) qApp->processEvents(); for(i=0; i<(startline-1);) { temp = fgetc(inputfile); if(temp==EOF) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "File does not contain enough lines."); messagewindow.exec(); fclose(inputfile); return(1); } if(temp=='\n') { i++; } } i = 0; column = 0; column_end = 1; str_start = 0; line_nr = startline; onset_is_set = 0; descr_is_set = 0; duration_is_set = 0; while(1) { temp = fgetc(inputfile); if(temp==EOF) { break; } line[i] = temp; if(line[i]=='\r') { continue; } if(separator!=',') { if(line[i]==',') { line[i] = '.'; } } if(line[i]==separator) { line[i] = 0; if(!column_end) { if(column == onset_column) { onset = 0LL; strncpy(scratchpad, line + str_start, 30); scratchpad[30] = 0; if(onsettime_coding == 0) { onset = atoll_x(scratchpad, TIME_DIMENSION); onset += mainwindow->edfheaderlist[0]->starttime_offset; onset_is_set = 1; } if(onsettime_coding == 1) { if(strlen(scratchpad) > 6) { if((scratchpad[2] == ':') && (scratchpad[5] == ':')) { scratchpad[8] = 0; onset = atoi(scratchpad) * 3600LL; onset += (atoi(scratchpad + 3) * 60LL); onset += (long long)(atoi(scratchpad + 6)); onset *= TIME_DIMENSION; onset -= mainwindow->edfheaderlist[0]->l_starttime; if(onset < last_onset) { last_onset = onset; days++; } onset_is_set = 1; } } if(strlen(scratchpad) > 5) { if((scratchpad[1] == ':') && (scratchpad[4] == ':')) { scratchpad[7] = 0; onset = atoi(scratchpad) * 3600LL; onset += (atoi(scratchpad + 2) * 60LL); onset += (long long)(atoi(scratchpad + 5)); onset *= TIME_DIMENSION; onset -= mainwindow->edfheaderlist[0]->l_starttime; if(onset < last_onset) { last_onset = onset; days++; } onset_is_set = 1; } } } if(onsettime_coding == 2) { if(strlen(scratchpad) > 8) { if((scratchpad[2] == ':') && (scratchpad[5] == ':') && ((scratchpad[8] == '.') || (scratchpad[8] == ','))) { for(digits=0; digits<32; digits++) { if((scratchpad[9 + digits] < '0') || (scratchpad[9 + digits] > '9')) { break; } } scratchpad[9 + digits] = 0; onset = atoi(scratchpad) * 3600LL; onset += (atoi(scratchpad + 3) * 60LL); onset += (long long)(atoi(scratchpad + 6)); onset *= TIME_DIMENSION; if(digits) { l_temp = (atoi(scratchpad + 9) * TIME_DIMENSION); for(; digits>0; digits--) { l_temp /= 10LL; } onset += l_temp; } onset -= mainwindow->edfheaderlist[0]->l_starttime; if(onset < last_onset) { last_onset = onset; days++; } onset_is_set = 1; } } if(strlen(scratchpad) > 7) { if((scratchpad[1] == ':') && (scratchpad[4] == ':') && ((scratchpad[7] == '.') || (scratchpad[7] == ','))) { for(digits=0; digits<32; digits++) { if((scratchpad[8 + digits] < '0') || (scratchpad[8 + digits] > '9')) { break; } } scratchpad[8 + digits] = 0; onset = atoi(scratchpad) * 3600LL; onset += (atoi(scratchpad + 2) * 60LL); onset += (long long)(atoi(scratchpad + 5)); onset *= TIME_DIMENSION; if(digits) { l_temp = (atoi(scratchpad + 8) * TIME_DIMENSION); for(; digits>0; digits--) { l_temp /= 10LL; } onset += l_temp; } onset -= mainwindow->edfheaderlist[0]->l_starttime; if(onset < last_onset) { last_onset = onset; days++; } onset_is_set = 1; } } } if(onsettime_coding == 3) { if(strlen(scratchpad) > 17) { if((scratchpad[4] == '-') && (scratchpad[7] == '-') && (scratchpad[13] == ':') && (scratchpad[16] == ':')) { scratchpad[19] = 0; date_time.year = atoi(scratchpad); date_time.month = atoi(scratchpad + 5); date_time.day = atoi(scratchpad + 8); date_time.hour = atoi(scratchpad + 11); date_time.minute = atoi(scratchpad + 14); date_time.second = atoi(scratchpad + 17); date_time_to_utc(&utc_time, date_time); onset = utc_time - mainwindow->edfheaderlist[0]->utc_starttime; onset *= TIME_DIMENSION; onset_is_set = 1; } } } if(onsettime_coding == 4) { if(strlen(scratchpad) > 19) { if((scratchpad[4] == '-') && (scratchpad[7] == '-') && (scratchpad[13] == ':') && (scratchpad[16] == ':') && ((scratchpad[19] == ',') || (scratchpad[19] == '.'))) { for(digits=0; digits<32; digits++) { if((scratchpad[20 + digits] < '0') || (scratchpad[20 + digits] > '9')) { break; } } scratchpad[20 + digits] = 0; date_time.year = atoi(scratchpad); date_time.month = atoi(scratchpad + 5); date_time.day = atoi(scratchpad + 8); date_time.hour = atoi(scratchpad + 11); date_time.minute = atoi(scratchpad + 14); date_time.second = atoi(scratchpad + 17); date_time_to_utc(&utc_time, date_time); onset = utc_time - mainwindow->edfheaderlist[0]->utc_starttime; onset *= TIME_DIMENSION; if(digits) { l_temp = (atoi(scratchpad + 20) * TIME_DIMENSION); for(; digits>0; digits--) { l_temp /= 10LL; } onset += l_temp; } onset_is_set = 1; } } } } if((!manualdescription) && (column == descr_column)) { strncpy(description, line + str_start, max_descr_length); description[max_descr_length] = 0; latin1_to_utf8(description, max_descr_length); descr_is_set = 1; } if((use_duration) && (column == duration_column)) { strncpy(duration, line + str_start, 16); duration[15] = 0; duration_is_set = 1; } column_end = 1; column++; } } else { if(line[i]!='\n') { if(column_end) { str_start = i; column_end = 0; } } } if(line[i]=='\n') { line[i] = 0; if(!column_end) { if(column == onset_column) { if((descr_is_set) || (manualdescription)) { onset = 0LL; strncpy(scratchpad, line + str_start, 30); scratchpad[30] = 0; if(onsettime_coding == 0) { onset = atoll_x(scratchpad, TIME_DIMENSION); onset += mainwindow->edfheaderlist[0]->starttime_offset; onset_is_set = 1; } if(onsettime_coding == 1) { if(strlen(scratchpad) > 6) { if((scratchpad[2] == ':') && (scratchpad[5] == ':')) { scratchpad[8] = 0; onset = atoi(scratchpad) * 3600LL; onset += (atoi(scratchpad + 3) * 60LL); onset += (long long)(atoi(scratchpad + 6)); onset *= TIME_DIMENSION; onset -= mainwindow->edfheaderlist[0]->l_starttime; if(onset < last_onset) { last_onset = onset; days++; } onset_is_set = 1; } } if(strlen(scratchpad) > 5) { if((scratchpad[1] == ':') && (scratchpad[4] == ':')) { scratchpad[7] = 0; onset = atoi(scratchpad) * 3600LL; onset += (atoi(scratchpad + 2) * 60LL); onset += (long long)(atoi(scratchpad + 5)); onset *= TIME_DIMENSION; onset -= mainwindow->edfheaderlist[0]->l_starttime; if(onset < last_onset) { last_onset = onset; days++; } onset_is_set = 1; } } } if(onsettime_coding == 2) { if(strlen(scratchpad) > 8) { if((scratchpad[2] == ':') && (scratchpad[5] == ':') && ((scratchpad[8] == '.') || (scratchpad[8] == ','))) { for(digits=0; digits<32; digits++) { if((scratchpad[9 + digits] < '0') || (scratchpad[9 + digits] > '9')) { break; } } scratchpad[9 + digits] = 0; onset = atoi(scratchpad) * 3600LL; onset += (atoi(scratchpad + 3) * 60LL); onset += (long long)(atoi(scratchpad + 6)); onset *= TIME_DIMENSION; if(digits) { l_temp = (atoi(scratchpad + 9) * TIME_DIMENSION); for(; digits>0; digits--) { l_temp /= 10LL; } onset += l_temp; } onset -= mainwindow->edfheaderlist[0]->l_starttime; if(onset < last_onset) { last_onset = onset; days++; } onset_is_set = 1; } } if(strlen(scratchpad) > 7) { if((scratchpad[1] == ':') && (scratchpad[4] == ':') && ((scratchpad[7] == '.') || (scratchpad[7] == ','))) { for(digits=0; digits<32; digits++) { if((scratchpad[8 + digits] < '0') || (scratchpad[8 + digits] > '9')) { break; } } scratchpad[8 + digits] = 0; onset = atoi(scratchpad) * 3600LL; onset += (atoi(scratchpad + 2) * 60LL); onset += (long long)(atoi(scratchpad + 5)); onset *= TIME_DIMENSION; if(digits) { l_temp = (atoi(scratchpad + 8) * TIME_DIMENSION); for(; digits>0; digits--) { l_temp /= 10LL; } onset += l_temp; } onset -= mainwindow->edfheaderlist[0]->l_starttime; if(onset < last_onset) { last_onset = onset; days++; } onset_is_set = 1; } } } if(onsettime_coding == 3) { if(strlen(scratchpad) > 17) { if((scratchpad[4] == '-') && (scratchpad[7] == '-') && (scratchpad[13] == ':') && (scratchpad[16] == ':')) { scratchpad[19] = 0; date_time.year = atoi(scratchpad); date_time.month = atoi(scratchpad + 5); date_time.day = atoi(scratchpad + 8); date_time.hour = atoi(scratchpad + 11); date_time.minute = atoi(scratchpad + 14); date_time.second = atoi(scratchpad + 17); date_time_to_utc(&utc_time, date_time); onset = utc_time - mainwindow->edfheaderlist[0]->utc_starttime; onset *= TIME_DIMENSION; onset_is_set = 1; } } } if(onsettime_coding == 4) { if(strlen(scratchpad) > 19) { if((scratchpad[4] == '-') && (scratchpad[7] == '-') && (scratchpad[13] == ':') && (scratchpad[16] == ':') && ((scratchpad[19] == ',') || (scratchpad[19] == '.'))) { for(digits=0; digits<32; digits++) { if((scratchpad[20 + digits] < '0') || (scratchpad[20 + digits] > '9')) { break; } } scratchpad[20 + digits] = 0; date_time.year = atoi(scratchpad); date_time.month = atoi(scratchpad + 5); date_time.day = atoi(scratchpad + 8); date_time.hour = atoi(scratchpad + 11); date_time.minute = atoi(scratchpad + 14); date_time.second = atoi(scratchpad + 17); date_time_to_utc(&utc_time, date_time); onset = utc_time - mainwindow->edfheaderlist[0]->utc_starttime; onset *= TIME_DIMENSION; if(digits) { l_temp = (atoi(scratchpad + 20) * TIME_DIMENSION); for(; digits>0; digits--) { l_temp /= 10LL; } onset += l_temp; } onset_is_set = 1; } } } } } if((!manualdescription) && (column == descr_column)) { if(onset_is_set) { strncpy(description, line + str_start, max_descr_length); description[max_descr_length] = 0; latin1_to_utf8(description, max_descr_length); descr_is_set = 1; } } if((use_duration) && (column == duration_column)) { strncpy(duration, line + str_start, 15); duration[15] = 0; duration_is_set = 1; } } if((!use_duration) || duration_is_set) { if(onset_is_set && descr_is_set && (!manualdescription)) { if((!ignore_consecutive) || strcmp(description, last_description)) { annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); if(annotation == NULL) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred (annotation)."); messagewindow.exec(); fclose(inputfile); return(1); } annotation->onset = onset + (86400LL * TIME_DIMENSION * days); strncpy(annotation->annotation, description, MAX_ANNOTATION_LEN); annotation->annotation[MAX_ANNOTATION_LEN] = 0; if(use_duration) { if((!(is_number(duration))) && (duration[0] != '-')) { remove_trailing_zeros(duration); if(duration[0] == '+') { strcpy(annotation->duration, duration + 1); } else { strcpy(annotation->duration, duration); } } } edfplus_annotation_add_item(&mainwindow->annotationlist[0], annotation); strcpy(last_description, description); } } if(onset_is_set && manualdescription) { annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); if(annotation == NULL) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred (annotation)."); messagewindow.exec(); fclose(inputfile); return(1); } annotation->onset = onset + (86400LL * TIME_DIMENSION * days); strncpy(annotation->annotation, description, MAX_ANNOTATION_LEN); annotation->annotation[MAX_ANNOTATION_LEN] = 0; if(use_duration) { if((!(is_number(duration))) && (duration[0] != '-')) { remove_trailing_zeros(duration); if(duration[0] == '+') { strcpy(annotation->duration, duration + 1); } else { strcpy(annotation->duration, duration); } } } edfplus_annotation_add_item(&mainwindow->annotationlist[0], annotation); } } line_nr++; str_start = 0; i = 0; column = 0; column_end = 1; onset_is_set = 0; descr_is_set = 0; duration_is_set = 0; qApp->processEvents(); continue; } i++; if(i>2046) { QApplication::restoreOverrideCursor(); snprintf(scratchpad, 256, "Error, line %i is too long.\n", line_nr); QMessageBox messagewindow(QMessageBox::Critical, "Error", scratchpad); messagewindow.exec(); fclose(inputfile); return(1); } } QApplication::restoreOverrideCursor(); if(fclose(inputfile)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while closing inputfile."); messagewindow.exec(); return(1); } return(0); } int UI_ImportAnnotationswindow::import_from_edfplus(void) { int i, annotlist_size; char path[MAX_PATH_LENGTH], str[2048]; long long starttime_diff; FILE *inputfile=NULL; struct edfhdrblock *edfhdr=NULL; struct annotationblock *annotlist[1]; struct annotationblock *annotation; strcpy(path, QFileDialog::getOpenFileName(0, "Open EDF+/BDF+ file", QString::fromLocal8Bit(mainwindow->recent_opendir), "EDF/BDF files (*.edf *.EDF *.bdf *.BDF )").toLocal8Bit().data()); if(!strcmp(path, "")) { return(1); } get_directory_from_path(mainwindow->recent_opendir, path, MAX_PATH_LENGTH); if(mainwindow->annotationlist_backup==NULL) { mainwindow->annotationlist_backup = edfplus_annotation_copy_list(&mainwindow->annotationlist[0]); } inputfile = fopeno(path, "rb"); if(inputfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); messagewindow.exec(); return(1); } rewind(inputfile); EDFfileCheck EDFfilechecker; str[0] = 0; annotlist[0] = NULL; edfhdr = EDFfilechecker.check_edf_file(inputfile, str, 0); if(edfhdr==NULL) { strcat(str, "\n File is not a valid EDF or BDF file."); QMessageBox messagewindow(QMessageBox::Critical, "Error", str); messagewindow.exec(); fclose(inputfile); return(1); } if(!(edfhdr->edfplus || edfhdr->bdfplus)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "File is not an EDF+ or BDF+ file."); messagewindow.exec(); free(edfhdr->edfparam); free(edfhdr); fclose(inputfile); return(1); } strcpy(edfhdr->filename, path); edfhdr->file_hdl = inputfile; EDF_annotations annotations; annotations.get_annotations(0, edfhdr, &annotlist[0], mainwindow->read_nk_trigger_signal); if(edfhdr->annots_not_read) { edfplus_annotation_delete_list(&annotlist[0]); free(edfhdr->edfparam); free(edfhdr); fclose(inputfile); return(1); } annotlist_size = edfplus_annotation_count(&annotlist[0]); if(annotlist_size == 0) { QMessageBox messagewindow(QMessageBox::Information, "Import annotations", "No annotations found."); messagewindow.exec(); free(edfhdr->edfparam); free(edfhdr); fclose(inputfile); return(1); } starttime_diff = edfhdr->utc_starttime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime; starttime_diff *= TIME_DIMENSION; QApplication::setOverrideCursor(Qt::WaitCursor); for(i=0; ionset += starttime_diff; edfplus_annotation_add_copy(&mainwindow->annotationlist[0], annotation); } edfplus_annotation_sort(&mainwindow->annotationlist[0]); edfplus_annotation_delete_list(&annotlist[0]); free(edfhdr->edfparam); free(edfhdr); fclose(inputfile); QApplication::restoreOverrideCursor(); return(0); } int UI_ImportAnnotationswindow::import_from_dcevent(void) { int i, ignore_consecutive=0, signal_nr, smpls_per_datrec, bytes_per_datrec, recsize, jumpbytes, bufoffset, triggervalue, bitwidth, bitposition, trigger_sample, next_sample, eventcode, tmp_value=0, edfformat, annotations_found=0; char scratchpad[256], last_description[256], *buf; long long datrecs, trigger_datrec, time_per_sample, progress_steps; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; FILE *inputfile=NULL; struct annotationblock *annotation; struct signalcompblock *signalcomp; last_description[0] = 0; if(IgnoreConsecutiveCheckBox->checkState() == Qt::Checked) { ignore_consecutive = 1; } else { ignore_consecutive = 0; } mainwindow->import_annotations_var->ignoreconsecutive = ignore_consecutive; signal_nr = DCEventSignalComboBox->currentIndex(); if(signal_nr < 0) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "You need to put at least one signal on the screen."); messagewindow.exec(); return(1); } if(mainwindow->signalcomp[signal_nr]->num_of_signals > 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The signal can not be a derivation of multiple signals."); messagewindow.exec(); return(1); } mainwindow->import_annotations_var->dceventbittime = BitTimeSpinbox->value(); mainwindow->import_annotations_var->triggerlevel = DCEventTriggerLevelSpinBox->value(); signalcomp = mainwindow->signalcomp[signal_nr]; smpls_per_datrec = signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record; recsize = signalcomp->edfhdr->recordsize; bufoffset = signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].buf_offset; time_per_sample = signalcomp->edfhdr->long_data_record_duration / smpls_per_datrec; if(signalcomp->edfhdr->edf) { edfformat = 1; bytes_per_datrec = smpls_per_datrec * 2; } else { bytes_per_datrec = smpls_per_datrec * 3; edfformat = 0; } jumpbytes = recsize - bytes_per_datrec; inputfile = signalcomp->edfhdr->file_hdl; bitwidth = ((long long)mainwindow->import_annotations_var->dceventbittime * 10000LL) / time_per_sample; if(bitwidth < 5) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Bit Time is set too low compared to the samplerate of the selected signal."); messagewindow.exec(); return(1); } triggervalue = mainwindow->import_annotations_var->triggerlevel / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue; triggervalue -= signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].offset; if(triggervalue >= signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].dig_max) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Trigger Level is equal or higher than physical maximum."); messagewindow.exec(); return(1); } if(triggervalue <= signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].dig_min) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Trigger Level is equal or lower than physical minimum."); messagewindow.exec(); return(1); } if(fseeko(inputfile, signalcomp->edfhdr->hdrsize + bufoffset, SEEK_SET)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading inputfile. (fseek)"); messagewindow.exec(); return(1); } buf = (char *)malloc(bytes_per_datrec); if(buf == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (buf)"); messagewindow.exec(); return(1); } annotations_found = 0; QProgressDialog progress("Scanning file for DC-events...", "Abort", 0, (int)signalcomp->edfhdr->datarecords); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); progress_steps = signalcomp->edfhdr->datarecords / 100LL; if(progress_steps < 1LL) { progress_steps = 1LL; } /* BITPOSITION: 0 nothing (idle) 1 rising edge of startbit found 2 middle of startbit found 3 middle of bit 0 found ........................ 10 middle of bit 7 found 11 middle of stopbit found */ bitposition = 0; eventcode = 0; next_sample = 0; trigger_sample = 0; trigger_datrec = 0LL; for(datrecs=0LL; datrecs < signalcomp->edfhdr->datarecords; datrecs++) { if(annotations_found > 10000) { progress.reset(); break; } if(!(datrecs % progress_steps)) { progress.setValue((int)datrecs); qApp->processEvents(); if(progress.wasCanceled() == true) { break; } } if(datrecs) { fseek(inputfile, jumpbytes, SEEK_CUR); } if(fread(buf, bytes_per_datrec, 1, inputfile) != 1) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading inputfile. (fread)"); messagewindow.exec(); free(buf); return(1); } for(i=0; i triggervalue) { eventcode += (1 << (bitposition - 2)); } } if(bitposition == 10) { if(tmp_value < triggervalue) { sprintf(scratchpad, "Trigger ID=%i", eventcode); if((!ignore_consecutive) || (strcmp(scratchpad, last_description))) { annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); if(annotation == NULL) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred (annotation)."); messagewindow.exec(); free(buf); return(1); } annotation->onset = ((trigger_datrec * signalcomp->edfhdr->long_data_record_duration) + (trigger_sample * time_per_sample)); annotation->onset += signalcomp->edfhdr->starttime_offset; annotation->file_num = signalcomp->edfhdr->file_num; strncpy(annotation->annotation, scratchpad, MAX_ANNOTATION_LEN); annotation->annotation[MAX_ANNOTATION_LEN] = 0; edfplus_annotation_add_item(&mainwindow->annotationlist[0], annotation); annotations_found++; strcpy(last_description, scratchpad); } } bitposition = 0; continue; } } next_sample = (i + bitwidth) % smpls_per_datrec; bitposition++; } } else { if(tmp_value > triggervalue) { trigger_sample = i; trigger_datrec = datrecs; bitposition = 1; next_sample = (i + (bitwidth / 2)) % smpls_per_datrec; eventcode = 0; } } } } free(buf); inputfile = NULL; progress.reset(); return(0); } edfbrowser_157_source/PaxHeaders.7921/annotations_dock.h0000644000000000000000000000013212646460742020374 xustar0030 mtime=1452958178.237246767 30 atime=1452958178.237246767 30 ctime=1452958178.237246767 edfbrowser_157_source/annotations_dock.h0000644000175000001440000000623112646460742020737 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef ANNOTATIONSFORM1_H #define ANNOTATIONSFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "edit_annotation_dock.h" #include "viewcurve.h" #include "utils.h" #include "averager_dialog.h" #include "edf_annot_list.h" class UI_Mainwindow; class UI_Annotationswindow : public QObject { Q_OBJECT public: UI_Annotationswindow(int, QWidget *parent); UI_Mainwindow *mainwindow; QDockWidget *docklist; QListWidget *list; void updateList(void); private: struct annotationblock *annotation; int file_num, relative, selected, invert_filter, hide_nk_triggers, hide_bs_triggers; QDialog *dialog1; QHBoxLayout *h_layout; QVBoxLayout *v_layout; QCheckBox *checkbox1, *checkbox2; QLabel *label1; QLineEdit *lineedit1; QAction *show_between_act, *average_annot_act, *hide_annot_act, *unhide_annot_act, *hide_same_annots_act, *unhide_same_annots_act, *unhide_all_annots_act, *hide_all_NK_triggers_act, *hide_all_BS_triggers_act, *unhide_all_NK_triggers_act, *unhide_all_BS_triggers_act; private slots: void annotation_selected(QListWidgetItem *, int centered=1); void hide_editdock(bool); void checkbox1_clicked(int); void checkbox2_clicked(int); void show_between(bool); void average_annot(bool); void hide_annot(bool); void unhide_annot(bool); void hide_same_annots(bool); void unhide_same_annots(bool); void unhide_all_annots(bool); void filter_edited(const QString); void hide_all_NK_triggers(bool); void hide_all_BS_triggers(bool); void unhide_all_NK_triggers(bool); void unhide_all_BS_triggers(bool); }; #endif // ANNOTATIONSFORM1_H edfbrowser_157_source/PaxHeaders.7921/special_button.cpp0000644000000000000000000000012712646460742020411 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/special_button.cpp0000644000175000001440000000460012646460742020746 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "special_button.h" SpecialButton::SpecialButton(QWidget *w_parent) : QWidget(w_parent) { ButtonColor = QColor(Qt::white); global_Color = Qt::white; buttonText[0] = 0; } void SpecialButton::paintEvent(QPaintEvent *) { int w, h; QPainter painter(this); #if QT_VERSION >= 0x050000 painter.setRenderHint(QPainter::Qt4CompatiblePainting, true); #endif painter.save(); w = width(); h = height(); painter.setRenderHint(QPainter::Antialiasing); painter.setPen(Qt::black); painter.drawRect(0, 0, w-1, h-1); painter.fillRect(1, 1, w-2, h-2, ButtonColor); if(buttonText[0]!=0) painter.drawText(5, h/2+5, buttonText); painter.restore(); } void SpecialButton::setColor(QColor newColor) { ButtonColor = newColor; update(); } QColor SpecialButton::color() { return(ButtonColor); } void SpecialButton::setGlobalColor(int newColor) { ButtonColor = (Qt::GlobalColor)newColor; global_Color = newColor; update(); } int SpecialButton::globalColor() { return(global_Color); } void SpecialButton::setText(const char *str) { strncpy(buttonText, str, 2047); buttonText[2047] = 0; update(); } void SpecialButton::mouseReleaseEvent(QMouseEvent *release_event) { if(release_event->button()==Qt::LeftButton) { emit clicked(this); } } edfbrowser_157_source/PaxHeaders.7921/emsa2edf.h0000644000000000000000000000013212646460742016525 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/emsa2edf.h0000644000175000001440000000375612646460742017101 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_EMSA2EDFFORM_H #define UI_EMSA2EDFFORM_H #include #include #include #include #include #include #include #include #include #if QT_VERSION < 0x050000 #include #include #endif #include #include #include #include #include #include #include "global.h" #include "utils.h" class UI_EMSA2EDFwindow : public QObject { Q_OBJECT public: UI_EMSA2EDFwindow(char *recent_dir=NULL, char *save_dir=NULL); private: QPushButton *pushButton1, *pushButton2; QTextEdit *textEdit1; QDialog *myobjectDialog; char *recent_opendir, *recent_savedir; struct event_struct{ int onset; int duration; char description[80]; } *logbuf; int get_string(char *, FILE *, int, int); private slots: void SelectFileButton(); }; #endif edfbrowser_157_source/PaxHeaders.7921/biox2edf.cpp0000644000000000000000000000013212646460742017074 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/biox2edf.cpp0000644000175000001440000002245512646460742017445 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2015, 2016 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 . * *************************************************************************** */ #include "biox2edf.h" #include #include #include #include #include "edflib.h" #define EDF_CHNS 3 #define MAX_POSSIBLE_SF 256 #define READ_BLOCK_SZ (256 * 4) UI_BIOX2EDFwindow::UI_BIOX2EDFwindow(char *recent_dir, char *save_dir) { char txt_string[2048]; recent_opendir = recent_dir; recent_savedir = save_dir; myobjectDialog = new QDialog; myobjectDialog->setMinimumSize(600, 480); myobjectDialog->setMaximumSize(600, 480); myobjectDialog->setWindowTitle("Biox CB-1305-C to EDF converter"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); 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"); textEdit1 = new QTextEdit(myobjectDialog); textEdit1->setGeometry(20, 20, 560, 380); textEdit1->setFrameStyle(QFrame::Panel | QFrame::Sunken); textEdit1->setReadOnly(true); textEdit1->setLineWrapMode(QTextEdit::NoWrap); sprintf(txt_string, "Biox CB-1305-C to EDF converter.\n"); textEdit1->append(txt_string); QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton())); QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close())); myobjectDialog->exec(); } void UI_BIOX2EDFwindow::SelectFileButton() { int i, j, hdl, chns=3, sf, wr_buf[MAX_POSSIBLE_SF * EDF_CHNS], blocks; char str[512], rd_buf[READ_BLOCK_SZ], txt_string[2048], edf_filename[MAX_PATH_LENGTH], data_filename[MAX_PATH_LENGTH]; unsigned char tmp_bits; FILE *inputfile=NULL; long long file_sz; pushButton1->setEnabled(false); strcpy(data_filename, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "Biox CB-1305-C data files (*.dat *.DAT)").toLocal8Bit().data()); if(!strcmp(data_filename, "")) { pushButton1->setEnabled(true); return; } get_directory_from_path(recent_opendir, data_filename, MAX_PATH_LENGTH); inputfile = fopeno(data_filename, "rb"); if(inputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for reading.\n", data_filename); textEdit1->append(QString::fromLocal8Bit(txt_string)); pushButton1->setEnabled(true); return; } snprintf(txt_string, 2048, "Read file: %s", data_filename); textEdit1->append(QString::fromLocal8Bit(txt_string)); fseeko(inputfile, 0x00, SEEK_END); file_sz = ftello(inputfile); if(file_sz < 2048) { textEdit1->append("File is smaller than 2048 bytes\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } fseeko(inputfile, 0x0100, SEEK_SET); if(fread(str, 17, 1, inputfile) != 1) { textEdit1->append("Can not read ID string from file\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } if(strncmp(str, "CB-1305-C SD-ECG3", 17)) { textEdit1->append("Wrong ID string in file\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } fseeko(inputfile, 0x0132, SEEK_SET); if(fread(str, 4, 1, inputfile) != 1) { textEdit1->append("Can not read parameter (samplefrequency) from file\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } #pragma GCC diagnostic ignored "-Wstrict-aliasing" sf = *((unsigned short *)str); #pragma GCC diagnostic warning "-Wstrict-aliasing" if((sf != 128) && (sf != 256)) { snprintf(txt_string, 2048, "Invalid parameter (samplefrequency) in file: %iHz\n", sf); textEdit1->append(QString::fromLocal8Bit(txt_string)); fclose(inputfile); pushButton1->setEnabled(true); return; } edf_filename[0] = 0; if(recent_savedir[0]!=0) { strcpy(edf_filename, recent_savedir); strcat(edf_filename, "/"); } strcat(edf_filename, "biox_ecg.edf"); strcpy(edf_filename, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(edf_filename), "EDF files (*.edf *.EDF)").toLocal8Bit().data()); if(!strcmp(edf_filename, "")) { fclose(inputfile); pushButton1->setEnabled(true); return; } get_directory_from_path(recent_savedir, edf_filename, MAX_PATH_LENGTH); hdl = edfopen_file_writeonly(edf_filename, EDFLIB_FILETYPE_EDFPLUS, chns); if(hdl < 0) { textEdit1->append("Error: can not open EDF file for writing\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } for(i=0; iappend("Error: edf_set_samplefrequency()\n"); edfclose_file(hdl); fclose(inputfile); pushButton1->setEnabled(true); return; } } for(i=0; iappend("Error: edf_set_digital_maximum()\n"); edfclose_file(hdl); fclose(inputfile); pushButton1->setEnabled(true); return; } } for(i=0; iappend("Error: edf_set_digital_minimum()\n"); edfclose_file(hdl); fclose(inputfile); pushButton1->setEnabled(true); return; } } for(i=0; iappend("Error: edf_set_physical_maximum()\n"); edfclose_file(hdl); fclose(inputfile); pushButton1->setEnabled(true); return; } } for(i=0; iappend("Error: edf_set_physical_minimum()\n"); edfclose_file(hdl); fclose(inputfile); pushButton1->setEnabled(true); return; } } for(i=0; iappend("Error: edf_set_physical_dimension()\n"); edfclose_file(hdl); fclose(inputfile); pushButton1->setEnabled(true); return; } } for(i=0; iappend("Error: edf_set_label()\n"); edfclose_file(hdl); fclose(inputfile); pushButton1->setEnabled(true); return; } } if(edf_set_equipment(hdl, "Biox CB-1305-C SD-ECG3")) { textEdit1->append("Error: edf_set_equipment()\n"); edfclose_file(hdl); fclose(inputfile); pushButton1->setEnabled(true); return; } fseeko(inputfile, 0x0200, SEEK_SET); file_sz -= 0x0200; file_sz /= READ_BLOCK_SZ; QProgressDialog progress("Converting ECG data ...", "Abort", 0, file_sz); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); j = 0; for(blocks=0; ; blocks++) { if(!(blocks % 10)) { progress.setValue(blocks); qApp->processEvents(); if(progress.wasCanceled() == true) { textEdit1->append("Conversion aborted by user.\n"); edfclose_file(hdl); fclose(inputfile); pushButton1->setEnabled(true); return; } } if(fread(rd_buf, READ_BLOCK_SZ, 1, inputfile) != 1) { break; } if(*((int *)(rd_buf + 1020)) == 0) { break; } for(i=0; i<(READ_BLOCK_SZ / 4); i++) { if((i == 127) || (i == 255)) continue; tmp_bits = rd_buf[i * 4 + 3]; rd_buf[i * 4] += 128; wr_buf[j] = rd_buf[i * 4]; wr_buf[j] <<= 2; rd_buf[i * 4 + 1] += 128; wr_buf[sf + j] = rd_buf[i * 4 + 1]; wr_buf[sf + j] <<= 2; rd_buf[i * 4 + 2] += 128; wr_buf[sf * 2 + j] = rd_buf[i * 4 + 2]; wr_buf[sf * 2 + j] <<= 2; wr_buf[j] += (tmp_bits >> 6) & 0b00000011; wr_buf[sf + j] += (tmp_bits >> 4) & 0b00000011; wr_buf[sf * 2 + j] += (tmp_bits >> 2) & 0b00000011; if(++j == sf) { j = 0; if(edf_blockwrite_digital_samples(hdl, wr_buf)) { progress.reset(); textEdit1->append("Error: a write error occurred during conversion\n"); edfclose_file(hdl); fclose(inputfile); pushButton1->setEnabled(true); return; } } } } progress.reset(); fclose(inputfile); edfclose_file(hdl); textEdit1->append("Ready.\n"); pushButton1->setEnabled(true); } edfbrowser_157_source/PaxHeaders.7921/print_to_edf.h0000644000000000000000000000012712646460742017517 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/print_to_edf.h0000644000175000001440000000275312646460742020063 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef PRINT_SCREEN_TO_EDF_H #define PRINT_SCREEN_TO_EDF_H #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "filter.h" #include "utc_date_time.h" #include "third_party/fidlib/fidlib.h" class UI_Mainwindow; void print_screen_to_edf(UI_Mainwindow *); #endif // PRINT_SCREEN_TO_EDF_H edfbrowser_157_source/PaxHeaders.7921/filter_dialog.h0000644000000000000000000000012712646460742017647 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/filter_dialog.h0000644000175000001440000000545512646460742020215 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef ADD_FILTERFORM1_H #define ADD_FILTERFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "filter.h" #include "filtercurve.h" #include "utils.h" #include "ravg_filter.h" #include "third_party/fidlib/fidlib.h" class UI_Mainwindow; class UI_FilterDialog : public QObject { Q_OBJECT public: UI_FilterDialog(QWidget *parent=0); UI_Mainwindow *mainwindow; private: QDialog *filterdialog; QPushButton *CancelButton, *ApplyButton; QListWidget *list; QComboBox *typebox, *modelbox; QDoubleSpinBox *freqbox, *ripplebox, *freq2box; QSpinBox *orderbox; QLabel *typeboxlabel, *freqboxlabel, *freqbox2label, *orderboxlabel, *modelboxlabel, *listlabel, *orderlabel, *ordervaluelabel; FilterCurve *curve1; double array[400], array_pha[400], last_ripple; int arraysize, last_order, last_qfactor, last_model, last_samples; void updatecurve(void); char *filter_spec, spec_str_1[256], spec_str_2[256]; private slots: void ApplyButtonClicked(); void frequencyboxvaluechanged(double); void orderboxvaluechanged(int); void filtertypeboxvaluechanged(int); void filtermodelboxvaluechanged(int); void rippleboxvaluechanged(double); void freq2boxvaluechanged(double); }; #endif // ADD_FILTERFORM1_H edfbrowser_157_source/PaxHeaders.7921/annotations_dock.cpp0000644000000000000000000000013212646460742020727 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/annotations_dock.cpp0000644000175000001440000005416712646460742021305 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "annotations_dock.h" UI_Annotationswindow::UI_Annotationswindow(int file_number, QWidget *w_parent) { QPalette palette; mainwindow = (UI_Mainwindow *)w_parent; file_num = file_number; docklist = new QDockWidget("Annotations", w_parent); docklist->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); docklist->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable); palette.setColor(QPalette::Text, mainwindow->maincurve->text_color); palette.setColor(QPalette::Base, mainwindow->maincurve->backgroundcolor); relative = 1; mainwindow->annotations_onset_relative = 1; selected = -1; invert_filter = 0; hide_nk_triggers = 0; hide_bs_triggers = 0; dialog1 = new QDialog; checkbox1 = new QCheckBox("Relative "); checkbox1->setGeometry(2, 2, 10, 10); checkbox1->setTristate(false); checkbox1->setCheckState(Qt::Checked); label1 = new QLabel; label1->setText(" Filter:"); lineedit1 = new QLineEdit; lineedit1->setMaxLength(16); checkbox2 = new QCheckBox("Inv."); checkbox2->setGeometry(2, 2, 10, 10); checkbox2->setTristate(false); checkbox2->setCheckState(Qt::Unchecked); list = new QListWidget(dialog1); list->setFont(*mainwindow->monofont); list->setAutoFillBackground(true); list->setPalette(palette); show_between_act = new QAction("Set timescale from here to next annotation", list); hide_annot_act = new QAction("Hide", list); unhide_annot_act = new QAction("Unhide", list); hide_same_annots_act = new QAction("Hide similar", list); unhide_same_annots_act = new QAction("Unhide similar", list); unhide_all_annots_act = new QAction("Unhide all", list); average_annot_act = new QAction("Average", list); hide_all_NK_triggers_act = new QAction("Hide all Nihon Kohden triggers", list); 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); list->setContextMenuPolicy(Qt::ActionsContextMenu); list->insertAction(NULL, show_between_act); list->insertAction(NULL, hide_annot_act); list->insertAction(NULL, hide_same_annots_act); list->insertAction(NULL, unhide_annot_act); list->insertAction(NULL, unhide_same_annots_act); list->insertAction(NULL, unhide_all_annots_act); list->insertAction(NULL, average_annot_act); list->insertAction(NULL, hide_all_NK_triggers_act); list->insertAction(NULL, unhide_all_NK_triggers_act); list->insertAction(NULL, hide_all_BS_triggers_act); list->insertAction(NULL, unhide_all_BS_triggers_act); h_layout = new QHBoxLayout; h_layout->addWidget(checkbox1); h_layout->addWidget(label1); h_layout->addWidget(lineedit1); h_layout->addWidget(checkbox2); v_layout = new QVBoxLayout(dialog1); v_layout->addLayout(h_layout); v_layout->addWidget(list); v_layout->setSpacing(1); docklist->setWidget(dialog1); updateList(); QObject::connect(list, SIGNAL(itemPressed(QListWidgetItem *)), this, SLOT(annotation_selected(QListWidgetItem *))); QObject::connect(docklist, SIGNAL(visibilityChanged(bool)), this, SLOT(hide_editdock(bool))); QObject::connect(checkbox1, SIGNAL(stateChanged(int)), this, SLOT(checkbox1_clicked(int))); QObject::connect(checkbox2, SIGNAL(stateChanged(int)), this, SLOT(checkbox2_clicked(int))); 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))); QObject::connect(unhide_same_annots_act, SIGNAL(triggered(bool)), this, SLOT(unhide_same_annots(bool))); QObject::connect(unhide_all_annots_act, SIGNAL(triggered(bool)), this, SLOT(unhide_all_annots(bool))); QObject::connect(average_annot_act, SIGNAL(triggered(bool)), this, SLOT(average_annot(bool))); QObject::connect(show_between_act, SIGNAL(triggered(bool)), this, SLOT(show_between(bool))); QObject::connect(hide_all_NK_triggers_act, SIGNAL(triggered(bool)), this, SLOT(hide_all_NK_triggers(bool))); 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(lineedit1, SIGNAL(textEdited(const QString)), this, SLOT(filter_edited(const QString))); } void UI_Annotationswindow::hide_all_NK_triggers(bool) { struct annotationblock *annot; annot = mainwindow->annotationlist[file_num]; hide_nk_triggers = 1; while(annot != NULL) { if(annot->ident & (1 << ANNOT_ID_NK_TRIGGER)) { annot->hided = 1; annot->hided_in_list = 1; } annot = annot->next_annotation; } updateList(); mainwindow->maincurve->update(); } void UI_Annotationswindow::hide_all_BS_triggers(bool) { struct annotationblock *annot; annot = mainwindow->annotationlist[file_num]; hide_bs_triggers = 1; while(annot != NULL) { if(annot->ident & (1 << ANNOT_ID_BS_TRIGGER)) { annot->hided = 1; annot->hided_in_list = 1; } annot = annot->next_annotation; } updateList(); mainwindow->maincurve->update(); } void UI_Annotationswindow::unhide_all_NK_triggers(bool) { struct annotationblock *annot; annot = mainwindow->annotationlist[file_num]; hide_nk_triggers = 0; while(annot != NULL) { if(annot->ident & (1 << ANNOT_ID_NK_TRIGGER)) { annot->hided = 0; annot->hided_in_list = 0; } annot = annot->next_annotation; } updateList(); mainwindow->maincurve->update(); } void UI_Annotationswindow::unhide_all_BS_triggers(bool) { struct annotationblock *annot; annot = mainwindow->annotationlist[file_num]; hide_bs_triggers = 0; while(annot != NULL) { if(annot->ident & (1 << ANNOT_ID_BS_TRIGGER)) { annot->hided = 0; annot->hided_in_list = 0; } annot = annot->next_annotation; } updateList(); mainwindow->maincurve->update(); } void UI_Annotationswindow::filter_edited(const QString text) { int i, cnt, n, len; char filter_str[32]; struct annotationblock *annot; annot = mainwindow->annotationlist[file_num]; cnt = edfplus_annotation_count(&annot); if(cnt < 1) { return; } if(text.length() < 1) { while(annot != NULL) { if(!(((annot->ident & (1 << ANNOT_ID_NK_TRIGGER)) && hide_nk_triggers) || ((annot->ident & (1 << ANNOT_ID_BS_TRIGGER)) && hide_bs_triggers))) { annot->hided_in_list = 0; annot->hided = 0; } annot = annot->next_annotation; } updateList(); mainwindow->maincurve->update(); return; } strcpy(filter_str, lineedit1->text().toUtf8().data()); len = strlen(filter_str); if(invert_filter == 0) { while(annot != NULL) { if(!(((annot->ident & (1 << ANNOT_ID_NK_TRIGGER)) && hide_nk_triggers) || ((annot->ident & (1 << ANNOT_ID_BS_TRIGGER)) && hide_bs_triggers))) { annot->hided_in_list = 1; n = strlen(annot->annotation) - len + 1; for(i=0; iannotation + i, len))) { annot->hided_in_list = 0; annot->hided = 0; break; } } } annot = annot->next_annotation; } } else { while(annot != NULL) { if(!(((annot->ident & (1 << ANNOT_ID_NK_TRIGGER)) && hide_nk_triggers) || ((annot->ident & (1 << ANNOT_ID_BS_TRIGGER)) && hide_bs_triggers))) { annot->hided_in_list = 0; n = strlen(annot->annotation) - len + 1; for(i=0; iannotation + i, len))) { annot->hided_in_list = 1; annot->hided = 1; break; } } } annot = annot->next_annotation; } } updateList(); mainwindow->maincurve->update(); } void UI_Annotationswindow::checkbox2_clicked(int state) { int cnt, changed=0; struct annotationblock *annot; annot = mainwindow->annotationlist[file_num]; cnt = edfplus_annotation_count(&annot); if(cnt < 1) { return; } if(state==Qt::Checked) { if(invert_filter == 0) changed = 1; invert_filter = 1; } if(state==Qt::Unchecked) { if(invert_filter == 1) changed = 1; invert_filter = 0; } if(changed == 0) return; filter_edited(lineedit1->text()); } void UI_Annotationswindow::show_between(bool) { int n; long long displaytime; struct annotationblock *annot; if(list->count() < 2) { return; } annot = mainwindow->annotationlist[file_num]; n = list->currentRow(); if(n >= (list->count() - 1)) { return; } while(n--) { annot = annot->next_annotation; } displaytime = annot->onset; annot = annot->next_annotation; displaytime -= annot->onset; if(displaytime < 0) { displaytime *= -1; } if(displaytime < 1000) { return; } mainwindow->pagetime = displaytime; annotation_selected(list->currentItem(), 0); } void UI_Annotationswindow::hide_annot(bool) { int n; struct annotationblock *annot; if(list->count() < 1) { return; } annot = mainwindow->annotationlist[file_num]; n = list->currentRow(); while(n--) { annot = annot->next_annotation; } annot->hided_in_list = 1; annot->hided = 1; mainwindow->maincurve->update(); } void UI_Annotationswindow::unhide_annot(bool) { int n; struct annotationblock *annot; if(list->count() < 1) { return; } annot = mainwindow->annotationlist[file_num]; n = list->currentRow(); while(n--) { annot = annot->next_annotation; } annot->hided_in_list = 0; annot->hided = 0; mainwindow->maincurve->update(); } void UI_Annotationswindow::hide_same_annots(bool) { int n; char str1[MAX_ANNOTATION_LEN], str2[MAX_ANNOTATION_LEN]; struct annotationblock *annot; if(list->count() < 1) { return; } annot = mainwindow->annotationlist[file_num]; n = list->currentRow(); while(n--) { annot = annot->next_annotation; } strcpy(str1, annot->annotation); remove_leading_spaces(str1); remove_trailing_spaces(str1); annot = mainwindow->annotationlist[file_num]; while(annot != NULL) { strcpy(str2, annot->annotation); remove_leading_spaces(str2); remove_trailing_spaces(str2); if(!strcmp(str1, str2)) { annot->hided_in_list = 1; annot->hided = 1; } annot = annot->next_annotation; } mainwindow->maincurve->update(); } void UI_Annotationswindow::unhide_same_annots(bool) { int n; char str1[MAX_ANNOTATION_LEN], str2[MAX_ANNOTATION_LEN]; struct annotationblock *annot; if(list->count() < 1) { return; } annot = mainwindow->annotationlist[file_num]; n = list->currentRow(); while(n--) { annot = annot->next_annotation; } strcpy(str1, annot->annotation); remove_leading_spaces(str1); remove_trailing_spaces(str1); annot = mainwindow->annotationlist[file_num]; while(annot != NULL) { strcpy(str2, annot->annotation); remove_leading_spaces(str2); remove_trailing_spaces(str2); if(!strcmp(str1, str2)) { annot->hided_in_list = 0; annot->hided = 0; } annot = annot->next_annotation; } mainwindow->maincurve->update(); } void UI_Annotationswindow::unhide_all_annots(bool) { struct annotationblock *annot; annot = mainwindow->annotationlist[file_num]; while(annot != NULL) { annot->hided = 0; annot->hided_in_list = 0; annot = annot->next_annotation; } mainwindow->maincurve->update(); } void UI_Annotationswindow::average_annot(bool) { if(mainwindow->files_open != 1) { return; } if(!mainwindow->signalcomps) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "First add a signal to the screen."); messagewindow.exec(); return; } if(mainwindow->annot_editor_active) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Close the annotation editor and try again."); messagewindow.exec(); return; } if(list->count() < 1) { return; } UI_AveragerWindow average_wndw(mainwindow, list->currentRow()); } void UI_Annotationswindow::checkbox1_clicked(int state) { if(state==Qt::Checked) { relative = 1; mainwindow->annotations_onset_relative = 1; } if(state==Qt::Unchecked) { relative = 0; mainwindow->annotations_onset_relative = 0; } updateList(); mainwindow->maincurve->update(); } void UI_Annotationswindow::hide_editdock(bool visible) { if(visible==false) { mainwindow->annotationEditDock->dockedit->hide(); } } void UI_Annotationswindow::updateList(void) { char str[MAX_ANNOTATION_LEN + 32], *str_tmp; int i, len, sequence_nr=0, jump=0, modified=0; QListWidgetItem *listitem; QString string; QByteArray ba; selected = -1; #ifdef Q_OS_WIN32 QFont specialfont("courier", 11, QFont::Normal, true); #else QFont specialfont("andale mono", 12, QFont::Normal, true); #endif specialfont.setPixelSize(12); list->clear(); edfplus_annotation_sort(&mainwindow->annotationlist[file_num]); annotation = mainwindow->annotationlist[file_num]; while(annotation != NULL) { if(annotation->hided_in_list) { annotation = annotation->next_annotation; sequence_nr++; continue; } string = QString::fromUtf8(annotation->annotation); ba = string.toUtf8(); str_tmp = ba.data(); len = 0; for(i=0; ; i++) { if(str_tmp[i]==0) break; if(((((unsigned char *)str_tmp)[i])&224)==192) len++; } for(i=0; ionset - mainwindow->edfheaderlist[file_num]->starttime_offset) < 0LL) { snprintf(str, (MAX_ANNOTATION_LEN + 32) / 2, " -%2i:%02i:%02i.%04i", (int)((-(annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION)/ 3600), (int)(((-(annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION) % 3600) / 60), (int)((-(annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION) % 60), (int)((-(annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) % TIME_DIMENSION) / 1000LL)); } else { snprintf(str, (MAX_ANNOTATION_LEN + 32) / 2, " %3i:%02i:%02i.%04i", (int)(((annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION)/ 3600), (int)((((annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION) % 3600) / 60), (int)(((annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION) % 60), (int)(((annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) % TIME_DIMENSION) / 1000LL)); } } else { snprintf(str, MAX_ANNOTATION_LEN + 32, " %3i:%02i:%02i.%04i", (int)((((annotation->onset + mainwindow->edfheaderlist[file_num]->l_starttime) / TIME_DIMENSION)/ 3600) % 24), (int)((((annotation->onset + mainwindow->edfheaderlist[file_num]->l_starttime) / TIME_DIMENSION) % 3600) / 60), (int)(((annotation->onset + mainwindow->edfheaderlist[file_num]->l_starttime) / TIME_DIMENSION) % 60), (int)(((annotation->onset + mainwindow->edfheaderlist[file_num]->l_starttime) % TIME_DIMENSION) / 1000LL)); } str[MAX_ANNOTATION_LEN + 31] = 0; remove_trailing_zeros(str); if(string.size() < 20) { string = string.leftJustified(20, ' '); } string.append(QString::fromLatin1(str)); listitem = new QListWidgetItem(string, list); listitem->setData(Qt::UserRole, QVariant(sequence_nr)); if(annotation->modified==1) { listitem->setFont(specialfont); listitem->setForeground(Qt::red); modified = 1; } if((annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) < 0LL) { snprintf(str, (MAX_ANNOTATION_LEN + 32) / 2, "onset: -%i:%02i:%02i.%04i", (int)((-(annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION)/ 3600), (int)(((-(annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION) % 3600) / 60), (int)((-(annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION) % 60), (int)((-(annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) % TIME_DIMENSION) / 1000LL)); } else { snprintf(str, (MAX_ANNOTATION_LEN + 32) / 2, "onset: %2i:%02i:%02i.%04i", (int)(((annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION)/ 3600), (int)((((annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION) % 3600) / 60), (int)(((annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION) % 60), (int)(((annotation->onset - mainwindow->edfheaderlist[file_num]->starttime_offset) % TIME_DIMENSION) / 1000LL)); } if(annotation->duration[0]!=0) { snprintf(str + strlen(str), (MAX_ANNOTATION_LEN + 32) / 2, "\nduration: %s",annotation->duration); } str[MAX_ANNOTATION_LEN + 31] = 0; remove_trailing_zeros(str); strcat(str, "\n\n"); string = QString::fromLatin1(str); string.append(QString::fromUtf8(annotation->annotation)); listitem->setToolTip(string); if(annotation->selected) { selected = sequence_nr; annotation->selected = 0; if(annotation->jump) { jump = 1; annotation->jump = 0; } } annotation = annotation->next_annotation; sequence_nr++; } if(mainwindow->annot_editor_active) { if(selected>=0) { list->setCurrentRow(selected, QItemSelectionModel::ClearAndSelect); mainwindow->annotationEditDock->set_selected_annotation(file_num, selected); if(jump) { jump = 0; annotation_selected(list->currentItem()); } selected = -1; } if(modified) { mainwindow->annotations_edited = 1; mainwindow->save_act->setEnabled(true); } } } void UI_Annotationswindow::annotation_selected(QListWidgetItem * item, int centered) { int i=0, n; long long temp; annotation = mainwindow->annotationlist[file_num]; n = item->data(Qt::UserRole).toInt(); if(mainwindow->annot_editor_active) { mainwindow->annotationEditDock->set_selected_annotation(file_num, n); } while(n--) { annotation = annotation->next_annotation; } if(mainwindow->video_player->status == VIDEO_STATUS_PLAYING) { mainwindow->video_player_seek((int)((annotation->onset - (mainwindow->pagetime / 2) - mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION)); return; } if(mainwindow->video_player->status == VIDEO_STATUS_PAUSED) { mainwindow->video_player_seek((int)((annotation->onset - (mainwindow->pagetime / 2) - mainwindow->edfheaderlist[file_num]->starttime_offset) / TIME_DIMENSION)); } if(mainwindow->viewtime_sync==VIEWTIME_SYNCED_OFFSET) { for(i=0; ifiles_open; i++) { mainwindow->edfheaderlist[i]->viewtime = annotation->onset; if(centered) { mainwindow->edfheaderlist[i]->viewtime -= (mainwindow->pagetime / 2); } mainwindow->edfheaderlist[i]->viewtime -= mainwindow->edfheaderlist[file_num]->starttime_offset; } } if(mainwindow->viewtime_sync==VIEWTIME_UNSYNCED) { mainwindow->edfheaderlist[file_num]->viewtime = annotation->onset; if(centered) { mainwindow->edfheaderlist[file_num]->viewtime -= (mainwindow->pagetime / 2); } mainwindow->edfheaderlist[file_num]->viewtime -= mainwindow->edfheaderlist[file_num]->starttime_offset; } if((mainwindow->viewtime_sync==VIEWTIME_SYNCED_ABSOLUT)||(mainwindow->viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { temp = annotation->onset - mainwindow->edfheaderlist[file_num]->viewtime; temp -= mainwindow->edfheaderlist[file_num]->starttime_offset; if(centered) { temp -= (mainwindow->pagetime / 2); } for(i=0; ifiles_open; i++) { mainwindow->edfheaderlist[i]->viewtime += temp; } } if(mainwindow->annotationEditDock->dockedit->isVisible()==true) { mainwindow->maincurve->setCrosshair_1_center(); } mainwindow->setup_viewbuf(); } edfbrowser_157_source/PaxHeaders.7921/spike_filter.cpp0000644000000000000000000000013212646460742020052 xustar0030 mtime=1452958178.249246726 30 atime=1452958178.249246726 30 ctime=1452958178.249246726 edfbrowser_157_source/spike_filter.cpp0000644000175000001440000001400312646460742020411 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2014, 2015, 2016 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 . * *************************************************************************** */ #include "spike_filter.h" struct spike_filter_settings * create_spike_filter(int sf, double sv, int ho, int *pace_detected) { struct spike_filter_settings *st; if((sf < 4000) || (sf > 128000)) return NULL; if((sv < 1E-10) || (sv > 1E13)) return NULL; if((ho < 10) || (ho > 1000)) return NULL; st = (struct spike_filter_settings *) calloc(1, sizeof(struct spike_filter_settings)); if(st==NULL) return(NULL); st->sf = sf; // samplefrequency st->n_max = sf / 2000; // Velocity is measured between sample n and sample n - n_max (tdiff is 0.5 mSec.) st->bufsz = (sf * 6) / 1000; // buffer length is 6 milli-Seconds st->flank_det_set = (sf * 3) / 1000; // accept only spikes with a maximum width of 3 milli-Seconds st->holdoff_set = (sf * ho) / 1000; // 100 milliSec. holdoff time (do not try to detect another spike during this time) st->velocity = (sv / (sf / 2000)) * st->n_max; st->pd_sig = pace_detected; st->spike_pos = -1; return(st); } void reset_spike_filter(struct spike_filter_settings *st) { st->cutoff = 0; st->cutoff_sav = 0; st->holdoff = 0; st->holdoff_sav = 0; st->flank_det = 0; st->flank_det_sav = 0; st->polarity = 0; st->polarity_sav = 0; for(int i=0; in_max; i++) st->array[i] = 0; st->idx = 0; st->idx_sav = 0; st->run_in = 0; st->run_in_sav = 0; st->spikewidth = 0; st->spikewidth_sav = 0; st->spike_pos = -1; st->spike_pos_sav = -1; if(st->pd_sig) *st->pd_sig = SPIKEFILTER_SPIKE_NO; } void spike_filter_save_buf(struct spike_filter_settings *st) { st->holdoff_sav = st->holdoff; st->cutoff_sav = st->cutoff; for(int i=0; in_max; i++) st->array_sav[i] = st->array[i]; st->idx_sav = st->idx; st->base_smpl_sav = st->base_smpl; st->polarity_sav = st->polarity; st->flank_det_sav = st->flank_det; st->run_in_sav = st->run_in; st->spikewidth_sav = st->spikewidth; st->spike_pos_sav = st->spike_pos; } void spike_filter_restore_buf(struct spike_filter_settings *st) { st->holdoff = st->holdoff_sav; st->cutoff = st->cutoff_sav; for(int i=0; in_max; i++) st->array[i] = st->array_sav[i]; st->idx = st->idx_sav; st->base_smpl = st->base_smpl_sav; st->polarity = st->polarity_sav; st->flank_det = st->flank_det_sav; st->run_in = st->run_in_sav; st->spikewidth = st->spikewidth_sav; st->spike_pos = st->spike_pos_sav; } double run_spike_filter(double val, struct spike_filter_settings *st) { int k, p_det=0, pol=1, tmp; if(st->run_in < st->bufsz) { st->run_in++; st->array[st->idx] = val; st->idx++; st->idx %= st->bufsz; if(st->pd_sig != NULL) { *st->pd_sig = SPIKEFILTER_SPIKE_NO; } return val; } if(st->flank_det) st->flank_det--; if(st->holdoff) st->holdoff--; if(st->cutoff) { st->cutoff--; st->array[st->idx] = val; st->idx++; st->idx %= st->bufsz; if(st->pd_sig != NULL) { *st->pd_sig = SPIKEFILTER_SPIKE_NO; } return st->base_smpl; // replace the sample with the baseline value because we are in the spike period } if(st->spike_pos == st->idx) { st->spike_pos = -1; st->cutoff = st->spikewidth; st->array[st->idx] = val; st->idx++; st->idx %= st->bufsz; if(st->pd_sig != NULL) { *st->pd_sig = SPIKEFILTER_SPIKE_ONSET; } return st->base_smpl; // replace the sample with the baseline value because we are in the spike period } if(!st->holdoff) { k = (st->idx + st->bufsz - st->n_max) % st->bufsz; tmp = val - st->array[k]; // check if there is a fast change between two samples if(tmp < 0) { tmp *= -1; // we want an absolute value pol = -1; } if(tmp > st->velocity) // change is fast enough to trigger a spike detect? { p_det = pol; } if(p_det) { if(st->flank_det) { if(pol != st->polarity) // we found the second flank of the spike { st->spikewidth = st->flank_det_set - st->flank_det + st->n_max; st->spike_pos = (st->idx + st->bufsz - st->spikewidth) % st->bufsz; st->spikewidth += (st->n_max * 2); st->holdoff = st->holdoff_set; // set the holdoff timer st->base_smpl = st->array[st->spike_pos]; st->flank_det = 0; } } else // we found the first flank of a new spike { st->polarity = pol; st->flank_det = st->flank_det_set; } } } st->array[st->idx] = val; st->idx++; st->idx %= st->bufsz; if(st->pd_sig != NULL) { *st->pd_sig = SPIKEFILTER_SPIKE_NO; } return st->array[st->idx]; } struct spike_filter_settings * create_spike_filter_copy(struct spike_filter_settings *src) { struct spike_filter_settings *settings; settings = (struct spike_filter_settings *) malloc(sizeof(struct spike_filter_settings)); if(settings==NULL) { return(NULL); } memcpy(settings, src, sizeof(struct spike_filter_settings)); return(settings); } void free_spike_filter(struct spike_filter_settings *st) { free(st); } edfbrowser_157_source/PaxHeaders.7921/jump_dialog.cpp0000644000000000000000000000013212646460742017664 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/jump_dialog.cpp0000644000175000001440000002562212646460742020234 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "jump_dialog.h" UI_JumpMenuDialog::UI_JumpMenuDialog(QWidget *w_parent) { mainwindow = (UI_Mainwindow *)w_parent; jump_dialog = new QDialog(w_parent); jump_dialog->setMinimumSize(435, 200); jump_dialog->setMaximumSize(435, 200); jump_dialog->setWindowTitle("Jump to"); jump_dialog->setModal(true); jump_dialog->setAttribute(Qt::WA_DeleteOnClose, true); label1 = new QLabel(jump_dialog); label1->setGeometry(10, 10, 155, 25); label1->setText(" dd hh:mm:ss.ms "); daybox1 = new QSpinBox(jump_dialog); daybox1->setGeometry(10, 45, 45, 25); daybox1->setRange(0, 30); daybox1->setEnabled(false); daybox2 = new QSpinBox(jump_dialog); daybox2->setGeometry(10, 80, 45, 25); daybox2->setRange(0, 30); daybox2->setEnabled(false); timeEdit1 = new QTimeEdit(jump_dialog); timeEdit1->setGeometry(65, 45, 110, 25); timeEdit1->setDisplayFormat("hh:mm:ss.zzz"); timeEdit1->setMinimumTime(QTime(0, 0, 0, 0)); timeEdit1->setEnabled(false); timeEdit2 = new QTimeEdit(jump_dialog); timeEdit2->setGeometry(65, 80, 110, 25); timeEdit2->setDisplayFormat("hh:mm:ss.zzz"); timeEdit2->setMinimumTime(QTime(0, 0, 0, 0)); timeEdit2->setEnabled(false); label2 = new QLabel("Offset from start of recording", jump_dialog); label2->setGeometry(185, 45, 250, 25); label3 = new QLabel("Absolute time", jump_dialog); label3->setGeometry(185, 80, 250, 25); jumpButton = new QPushButton(jump_dialog); jumpButton->setGeometry(10, 165, 100, 25); jumpButton->setText("Jump"); jumpButton->setEnabled(false); CloseButton = new QPushButton(jump_dialog); CloseButton->setGeometry(325, 165, 100, 25); CloseButton->setText("Cancel"); if(mainwindow->files_open) { daybox1->setEnabled(true); daybox2->setEnabled(true); timeEdit1->setEnabled(true); timeEdit2->setEnabled(true); starttime = mainwindow->edfheaderlist[mainwindow->sel_viewtime]->l_starttime + mainwindow->edfheaderlist[mainwindow->sel_viewtime]->starttime_offset; starttime /= 10000; time2.setHMS((int)((starttime / 3600000LL) % 24LL), (int)((starttime % 3600000LL) / 60000LL), (int)((starttime % 60000LL) / 1000LL), (int)(starttime % 1000LL)); timeEdit2->setMinimumTime(QTime((int)((starttime / 3600000LL) % 24LL), (int)((starttime % 3600000LL) / 60000LL), (int)((starttime % 60000LL) / 1000LL), (int)(starttime % 1000LL))); timeEdit2->setTime(time2); recording_duration = mainwindow->edfheaderlist[0]->datarecords * mainwindow->edfheaderlist[0]->long_data_record_duration; recording_duration /= (TIME_DIMENSION / 1000LL); jumpButton->setEnabled(true); } QObject::connect(CloseButton, SIGNAL(clicked()), jump_dialog, SLOT(close())); QObject::connect(jumpButton, SIGNAL(clicked()), this, SLOT(jumpbutton_pressed())); QObject::connect(timeEdit1, SIGNAL(timeChanged(const QTime &)), this, SLOT(offsettime_changed(const QTime &))); QObject::connect(timeEdit2, SIGNAL(timeChanged(const QTime &)), this, SLOT(absolutetime_changed(const QTime &))); QObject::connect(daybox1, SIGNAL(valueChanged(int)), this, SLOT(offsetday_changed(int))); QObject::connect(daybox2, SIGNAL(valueChanged(int)), this, SLOT(absoluteday_changed(int))); jump_dialog->exec(); } void UI_JumpMenuDialog::offsetday_changed(int days) { long long milliseconds; if(!mainwindow->files_open) return; QObject::disconnect(daybox2, SIGNAL(valueChanged(int)), this, SLOT(absoluteday_changed(int))); QObject::disconnect(timeEdit2, SIGNAL(timeChanged(const QTime &)), this, SLOT(absolutetime_changed(const QTime &))); milliseconds = (long long)(timeEdit1->time().hour()) * 3600000LL; milliseconds += (long long)(timeEdit1->time().minute()) * 60000LL; milliseconds += (long long)(timeEdit1->time().second()) * 1000LL; milliseconds += (long long)(timeEdit1->time().msec()); milliseconds += ((long long)days * 86400000LL); milliseconds += starttime; time2.setHMS((int)((milliseconds / 3600000LL) % 24LL), (int)((milliseconds % 3600000LL) / 60000LL), (int)((milliseconds % 60000LL) / 1000LL), (int)(milliseconds % 1000LL)); timeEdit2->setTime(time2); daybox2->setValue((int)(milliseconds / 86400000LL)); QObject::connect(daybox2, SIGNAL(valueChanged(int)), this, SLOT(absoluteday_changed(int))); QObject::connect(timeEdit2, SIGNAL(timeChanged(const QTime &)), this, SLOT(absolutetime_changed(const QTime &))); } void UI_JumpMenuDialog::absoluteday_changed(int days) { long long milliseconds; if(!mainwindow->files_open) return; QObject::disconnect(daybox1, SIGNAL(valueChanged(int)), this, SLOT(offsetday_changed(int))); QObject::disconnect(timeEdit1, SIGNAL(timeChanged(const QTime &)), this, SLOT(offsettime_changed(const QTime &))); milliseconds = (long long)(timeEdit2->time().hour()) * 3600000LL; milliseconds += (long long)(timeEdit2->time().minute()) * 60000LL; milliseconds += (long long)(timeEdit2->time().second()) * 1000LL; milliseconds += (long long)(timeEdit2->time().msec()); milliseconds += ((long long)days * 86400000LL); if(milliseconds<0) milliseconds = 0; milliseconds -= starttime; time1.setHMS((int)((milliseconds / 3600000LL) % 24LL), (int)((milliseconds % 3600000LL) / 60000LL), (int)((milliseconds % 60000LL) / 1000LL), (int)(milliseconds % 1000LL)); timeEdit1->setTime(time1); daybox1->setValue((int)(milliseconds / 86400000LL)); QObject::connect(daybox1, SIGNAL(valueChanged(int)), this, SLOT(offsetday_changed(int))); QObject::connect(timeEdit1, SIGNAL(timeChanged(const QTime &)), this, SLOT(offsettime_changed(const QTime &))); } void UI_JumpMenuDialog::offsettime_changed(const QTime &time_1) { long long milliseconds; if(!mainwindow->files_open) return; QObject::disconnect(daybox2, SIGNAL(valueChanged(int)), this, SLOT(absoluteday_changed(int))); QObject::disconnect(timeEdit2, SIGNAL(timeChanged(const QTime &)), this, SLOT(absolutetime_changed(const QTime &))); milliseconds = (long long)(time_1.hour()) * 3600000LL; milliseconds += (long long)(time_1.minute()) * 60000LL; milliseconds += (long long)(time_1.second()) * 1000LL; milliseconds += (long long)(time_1.msec()); milliseconds += ((long long)daybox1->value() * 86400000LL); milliseconds += starttime; time2.setHMS((int)((milliseconds / 3600000LL) % 24LL), (int)((milliseconds % 3600000LL) / 60000LL), (int)((milliseconds % 60000LL) / 1000LL), (int)(milliseconds % 1000LL)); timeEdit2->setTime(time2); daybox2->setValue((int)(milliseconds / 86400000LL)); QObject::connect(daybox2, SIGNAL(valueChanged(int)), this, SLOT(absoluteday_changed(int))); QObject::connect(timeEdit2, SIGNAL(timeChanged(const QTime &)), this, SLOT(absolutetime_changed(const QTime &))); } void UI_JumpMenuDialog::absolutetime_changed(const QTime &time_2) { long long milliseconds; if(!mainwindow->files_open) return; QObject::disconnect(daybox1, SIGNAL(valueChanged(int)), this, SLOT(offsetday_changed(int))); QObject::disconnect(timeEdit1, SIGNAL(timeChanged(const QTime &)), this, SLOT(offsettime_changed(const QTime &))); milliseconds = (long long)(time_2.hour()) * 3600000LL; milliseconds += (long long)(time_2.minute()) * 60000LL; milliseconds += (long long)(time_2.second()) * 1000LL; milliseconds += (long long)(time_2.msec()); milliseconds += ((long long)daybox2->value() * 86400000LL); if(milliseconds<0) milliseconds = 0; milliseconds -= starttime; time1.setHMS((int)((milliseconds / 3600000LL) % 24LL), (int)((milliseconds % 3600000LL) / 60000LL), (int)((milliseconds % 60000LL) / 1000LL), (int)(milliseconds % 1000LL)); timeEdit1->setTime(time1); daybox1->setValue((int)(milliseconds / 86400000LL)); QObject::connect(daybox1, SIGNAL(valueChanged(int)), this, SLOT(offsetday_changed(int))); QObject::connect(timeEdit1, SIGNAL(timeChanged(const QTime &)), this, SLOT(offsettime_changed(const QTime &))); } void UI_JumpMenuDialog::jumpbutton_pressed() { int i; long long milliseconds; if(!mainwindow->files_open) return; milliseconds = (long long)(timeEdit1->time().hour()) * 3600000LL; milliseconds += (long long)(timeEdit1->time().minute()) * 60000LL; milliseconds += (long long)(timeEdit1->time().second()) * 1000LL; milliseconds += (long long)(timeEdit1->time().msec()); milliseconds += ((long long)daybox1->value() * 86400000LL); if(mainwindow->viewtime_sync==VIEWTIME_SYNCED_OFFSET) { for(i=0; ifiles_open; i++) { mainwindow->edfheaderlist[i]->viewtime = milliseconds * (TIME_DIMENSION / 1000); } } if(mainwindow->viewtime_sync==VIEWTIME_UNSYNCED) { mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime = milliseconds * (TIME_DIMENSION / 1000); } if(mainwindow->viewtime_sync==VIEWTIME_SYNCED_ABSOLUT) { mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime = milliseconds * (TIME_DIMENSION / 1000); for(i=0; ifiles_open; i++) { if(i!=mainwindow->sel_viewtime) { mainwindow->edfheaderlist[i]->viewtime = mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime - ((mainwindow->edfheaderlist[i]->utc_starttime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime) * TIME_DIMENSION); } } } if(mainwindow->viewtime_sync==VIEWTIME_USER_DEF_SYNCED) { for(i=0; ifiles_open; i++) { if(i!=mainwindow->sel_viewtime) { mainwindow->edfheaderlist[i]->viewtime -= (mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime - milliseconds * (TIME_DIMENSION / 1000)); } } mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime = milliseconds * (TIME_DIMENSION / 1000); } mainwindow->setup_viewbuf(); jump_dialog->close(); } edfbrowser_157_source/PaxHeaders.7921/load_montage_dialog.cpp0000644000000000000000000000013212646460742021342 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/load_montage_dialog.cpp0000644000175000001440000016706512646460742021722 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "load_montage_dialog.h" UI_LoadMontagewindow::UI_LoadMontagewindow(QWidget *w_parent, char *path) { int i; mainwindow = (UI_Mainwindow *)w_parent; mtg_path[0] = 0; if(path!=NULL) { strcpy(mtg_path, path); } if(mainwindow->files_open==1) { LoadMontageDialog = NULL; LoadButtonClicked(); return; } LoadMontageDialog = new QDialog; LoadMontageDialog->setMinimumSize(800, 180); LoadMontageDialog->setMaximumSize(800, 180); LoadMontageDialog->setWindowTitle("Load montage"); LoadMontageDialog->setModal(true); LoadMontageDialog->setAttribute(Qt::WA_DeleteOnClose, true); label1 = new QLabel(LoadMontageDialog); label1->setGeometry(10, 10, 780, 25); label1->setText("Choose to which file you want to apply the montage:"); filelist = new QListWidget(LoadMontageDialog); filelist->setGeometry(10, 35, 780, 75); filelist->setSelectionBehavior(QAbstractItemView::SelectRows); filelist->setSelectionMode(QAbstractItemView::SingleSelection); for(i=0; ifiles_open; i++) { new QListWidgetItem(QString::fromLocal8Bit(mainwindow->edfheaderlist[i]->filename), filelist); } LoadButton = new QPushButton(LoadMontageDialog); LoadButton->setGeometry(10, 140, 100, 25); LoadButton->setText("Load"); CloseButton = new QPushButton(LoadMontageDialog); CloseButton->setGeometry(690, 140, 100, 25); CloseButton->setText("Close"); QObject::connect(CloseButton, SIGNAL(clicked()), LoadMontageDialog, SLOT(close())); QObject::connect(LoadButton, SIGNAL(clicked()), this, SLOT(LoadButtonClicked())); filelist->setCurrentRow(mainwindow->files_open - 1); LoadMontageDialog->exec(); } void UI_LoadMontagewindow::LoadButtonClicked() { int i, k, n, p, tmp, skip, found, signalcomps_read=0, signals_read, signal_cnt, filters_read, spike_filter_cnt=0, filter_cnt=0, ravg_filter_cnt=0, fidfilter_cnt=0, len, order=1, type=0, model=0, size=0, amp_cat[3], f_ruler_cnt=0, holdoff=100; char result[XML_STRBUFLEN], scratchpad[2048], str[128], *err, *filter_spec, spec_str[256]; double frequency=1.0, frequency2=2.0, ripple=1.0, velocity=1.0; struct xml_handle *xml_hdl; struct signalcompblock *newsignalcomp; if(mainwindow->files_open==1) n = 0; else n = filelist->currentRow(); if(mtg_path[0]==0) { strcpy(mtg_path, QFileDialog::getOpenFileName(0, "Load montage", QString::fromLocal8Bit(mainwindow->recent_montagedir), "Montage files (*.mtg *.MTG)").toLocal8Bit().data()); if(!strcmp(mtg_path, "")) { return; } get_directory_from_path(mainwindow->recent_montagedir, mtg_path, MAX_PATH_LENGTH); } xml_hdl = xml_get_handle(mtg_path); if(xml_hdl==NULL) { sprintf(scratchpad, "Can not open montage file:\n%s", mtg_path); QMessageBox messagewindow(QMessageBox::Critical, "Error", QString::fromLocal8Bit(scratchpad)); messagewindow.exec(); mainwindow->remove_recent_file_mtg_path(mtg_path); return; } if(strcmp(xml_hdl->elementname[xml_hdl->level], PROGRAM_NAME "_montage")) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } //////////////////////////////////////////// for(k=0; ksignalcomps; ) { if(mainwindow->signalcomp[k]->filenum==n) { for(i=0; ispectrumdock[i]->signalcomp == mainwindow->signalcomp[k]) { mainwindow->spectrumdock[i]->clear(); mainwindow->spectrumdock[i]->dock->hide(); } } for(i=0; isignalcomp[k]->spectr_dialog[i]; if(p != 0) { delete mainwindow->spectrumdialog[p - 1]; mainwindow->spectrumdialog[p - 1] = NULL; } } for(i=0; isignalcomp[k]->avg_dialog[i]; if(p != 0) { delete mainwindow->averagecurvedialog[p - 1]; mainwindow->averagecurvedialog[p - 1] = NULL; } } if(mainwindow->signalcomp[k]->hascursor2) { /* crosshair_2_active = 0; crosshair_2_moving = 0;*/ } if(mainwindow->signalcomp[k]->hascursor1) { // crosshair_1_active = 0; // crosshair_2_active = 0; // crosshair_1_moving = 0; // crosshair_2_moving = 0; for(i=0; isignalcomps; i++) { mainwindow->signalcomp[i]->hascursor2 = 0; } } if(mainwindow->signalcomp[k]->spike_filter) { free_spike_filter(mainwindow->signalcomp[k]->spike_filter); mainwindow->signalcomp[k]->spike_filter = NULL; } for(i=0; isignalcomp[k]->filter_cnt; i++) { free(mainwindow->signalcomp[k]->filter[i]); } mainwindow->signalcomp[k]->filter_cnt = 0; for(i=0; isignalcomp[k]->ravg_filter_cnt; i++) { free_ravg_filter(mainwindow->signalcomp[k]->ravg_filter[i]); } mainwindow->signalcomp[k]->ravg_filter_cnt = 0; for(i=0; isignalcomp[k]->fidfilter_cnt; i++) { free(mainwindow->signalcomp[k]->fidfilter[i]); fid_run_free(mainwindow->signalcomp[k]->fid_run[i]); fid_run_freebuf(mainwindow->signalcomp[k]->fidbuf[i]); fid_run_freebuf(mainwindow->signalcomp[k]->fidbuf2[i]); } mainwindow->signalcomp[k]->fidfilter_cnt = 0; if(mainwindow->signalcomp[k]->ecg_filter != NULL) { free_ecg_filter(mainwindow->signalcomp[k]->ecg_filter); mainwindow->signalcomp[k]->ecg_filter = NULL; strcpy(mainwindow->signalcomp[k]->signallabel, mainwindow->signalcomp[k]->signallabel_bu); mainwindow->signalcomp[k]->signallabellen = mainwindow->signalcomp[k]->signallabellen_bu; } free(mainwindow->signalcomp[k]); for(i=k; isignalcomps - 1; i++) { mainwindow->signalcomp[i] = mainwindow->signalcomp[i + 1]; } mainwindow->signalcomps--; k = 0; } else { k++; } } //////////////////////////////////////////// while(1) { skip = 0; xml_goto_root(xml_hdl); signals_read = 0; if(xml_goto_nth_element_inside(xml_hdl, "signalcomposition", signalcomps_read)) { break; } newsignalcomp = (struct signalcompblock *)calloc(1, sizeof(struct signalcompblock)); if(newsignalcomp==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Internal error: Memory allocation error:\n\"new signal composition\""); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_goto_nth_element_inside(xml_hdl, "num_of_signals", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } signal_cnt = atoi(result); if((signal_cnt<1)||(signal_cnt>MAXSIGNALS)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } newsignalcomp->edfhdr = mainwindow->edfheaderlist[n]; newsignalcomp->filenum = n; newsignalcomp->num_of_signals = signal_cnt; newsignalcomp->hascursor1 = 0; newsignalcomp->hascursor2 = 0; newsignalcomp->hasoffsettracking = 0; newsignalcomp->hasgaintracking = 0; newsignalcomp->screen_offset = 0; newsignalcomp->filter_cnt = 0; newsignalcomp->ravg_filter_cnt = 0; newsignalcomp->ecg_filter = NULL; newsignalcomp->fidfilter_cnt = 0; newsignalcomp->hasruler = 0; newsignalcomp->polarity = 1; xml_go_up(xml_hdl); if(!(xml_goto_nth_element_inside(xml_hdl, "alias", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(result[0] != 0) { strncpy(newsignalcomp->alias, result, 16); newsignalcomp->alias[16] = 0; latin1_to_ascii(newsignalcomp->alias, 16); remove_trailing_spaces(newsignalcomp->alias); remove_leading_spaces(newsignalcomp->alias); } xml_go_up(xml_hdl); } if(xml_goto_nth_element_inside(xml_hdl, "voltpercm", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } newsignalcomp->voltpercm = atof(result); if(newsignalcomp->voltpercm==0.0) newsignalcomp->voltpercm = 0.000000001; xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "screen_offset", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } newsignalcomp->screen_offset = atof(result); xml_go_up(xml_hdl); if(!(xml_goto_nth_element_inside(xml_hdl, "polarity", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } newsignalcomp->polarity = atoi(result); if(newsignalcomp->polarity != -1) { newsignalcomp->polarity = 1; } xml_go_up(xml_hdl); } if(xml_goto_nth_element_inside(xml_hdl, "color", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } newsignalcomp->color = atoi(result); if((newsignalcomp->color < 2) || (newsignalcomp->color > 18)) { newsignalcomp->color = 2; } xml_go_up(xml_hdl); if(!(xml_goto_nth_element_inside(xml_hdl, "filter_cnt", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } filter_cnt = atoi(result); if(filter_cnt < 0) filter_cnt = 0; if(filter_cnt > MAXFILTERS) filter_cnt = MAXFILTERS; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "spike_filter_cnt", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } spike_filter_cnt = atoi(result); if(spike_filter_cnt < 0) filter_cnt = 0; if(spike_filter_cnt > 1) spike_filter_cnt = 1; xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "ravg_filter_cnt", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } ravg_filter_cnt = atoi(result); if(ravg_filter_cnt < 0) filter_cnt = 0; if(ravg_filter_cnt > MAXFILTERS) ravg_filter_cnt = MAXFILTERS; xml_go_up(xml_hdl); } if(filter_cnt) { fidfilter_cnt = 0; } else { if(!(xml_goto_nth_element_inside(xml_hdl, "fidfilter_cnt", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } fidfilter_cnt = atoi(result); if(fidfilter_cnt < 0) fidfilter_cnt = 0; if(fidfilter_cnt > MAXFILTERS) fidfilter_cnt = MAXFILTERS; xml_go_up(xml_hdl); } } for(signals_read=0; signals_readfactor[signals_read] = atoi(result); if(newsignalcomp->factor[signals_read] < -128) { newsignalcomp->factor[signals_read] = -128; } if(newsignalcomp->factor[signals_read] > 128) { newsignalcomp->factor[signals_read] = 128; } if(newsignalcomp->factor[signals_read] == 0) { newsignalcomp->factor[signals_read] = 1; } xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "edfindex", 0)) { if(xml_goto_nth_element_inside(xml_hdl, "label", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } remove_trailing_spaces(result); found = 0; for(i=0; iedfhdr->edfsignals; i++) { strcpy(scratchpad, newsignalcomp->edfhdr->edfparam[i].label); remove_trailing_spaces(scratchpad); if(!strcmp(scratchpad, result)) { newsignalcomp->edfsignal[signals_read] = i; if(newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[signals_read]].annotation) { found = 0; } else { found = 1; } break; } } } else { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } newsignalcomp->edfsignal[signals_read] = atoi(result); if((newsignalcomp->edfsignal[signals_read] < 0) || (newsignalcomp->edfsignal[signals_read] >= newsignalcomp->edfhdr->edfsignals)) { found = 0; } else { if(newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[signals_read]].annotation) { found = 0; } else { found = 1; } } } if(!found) { free(newsignalcomp); skip = 1; signalcomps_read++; xml_go_up(xml_hdl); xml_go_up(xml_hdl); break; } if(signals_read) { if(newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[signals_read]].smp_per_record != newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].smp_per_record) { free(newsignalcomp); skip = 1; signalcomps_read++; xml_go_up(xml_hdl); xml_go_up(xml_hdl); break; } } newsignalcomp->sensitivity[signals_read] = newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[signals_read]].bitvalue / (newsignalcomp->voltpercm * mainwindow->pixelsizefactor); if(!signals_read) { newsignalcomp->signallabel[0] = 0; } if(signal_cnt>1) { if(newsignalcomp->factor[signals_read]<0) { strcat(newsignalcomp->signallabel, "- "); } else { if(signals_read) { strcat(newsignalcomp->signallabel, "+ "); } } } strcpy(str, newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[signals_read]].label); strip_types_from_label(str); strcat(newsignalcomp->signallabel, str); strcat(newsignalcomp->signallabel, " "); len = strlen(newsignalcomp->signallabel); for(k=(len-1); k>0; k--) { if(newsignalcomp->signallabel[k]!=' ') break; } newsignalcomp->signallabel[k+2] = 0; newsignalcomp->file_duration = newsignalcomp->edfhdr->long_data_record_duration * newsignalcomp->edfhdr->datarecords; newsignalcomp->signallabellen = strlen(newsignalcomp->signallabel); xml_go_up(xml_hdl); xml_go_up(xml_hdl); } if(skip) continue; strcpy(newsignalcomp->physdimension, newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].physdimension); remove_trailing_spaces(newsignalcomp->physdimension); if(spike_filter_cnt) { if(xml_goto_nth_element_inside(xml_hdl, "spike_filter", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(xml_goto_nth_element_inside(xml_hdl, "velocity", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } velocity = atof(result); if(velocity < 0.0001) velocity = 0.0001; if(velocity > 10E9) velocity = 10E9; xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "holdoff", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } holdoff = atoi(result); if(holdoff < 10) holdoff = 10; if(holdoff > 1000) holdoff = 1000; newsignalcomp->spike_filter = create_spike_filter( (double)(newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].smp_per_record) / newsignalcomp->edfhdr->data_record_duration, velocity / newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].bitvalue, holdoff, NULL); if(newsignalcomp->spike_filter == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred when creating a spike filter."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } newsignalcomp->spike_filter_velocity = velocity; newsignalcomp->spike_filter_holdoff = holdoff; xml_go_up(xml_hdl); xml_go_up(xml_hdl); } for(filters_read=0; filters_read 1) || (frequency < 0.0001)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file. (filter values)"); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(frequency >= ((newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].smp_per_record / newsignalcomp->edfhdr->data_record_duration) / 2.0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The frequency of the filter(s) must be less than: samplerate / 2"); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(type == 0) { sprintf(spec_str, "HpBu1/%f", frequency); } if(type == 1) { sprintf(spec_str, "LpBu1/%f", frequency); } filter_spec = spec_str; err = fid_parse(((double)(newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].smp_per_record)) / newsignalcomp->edfhdr->data_record_duration, &filter_spec, &newsignalcomp->fidfilter[filters_read]); if(err != NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", err); messagewindow.exec(); free(err); free(newsignalcomp); xml_close(xml_hdl); return; } newsignalcomp->fid_run[filters_read] = fid_run_new(newsignalcomp->fidfilter[filters_read], &newsignalcomp->fidfuncp[filters_read]); newsignalcomp->fidbuf[filters_read] = fid_run_newbuf(newsignalcomp->fid_run[filters_read]); newsignalcomp->fidbuf2[filters_read] = fid_run_newbuf(newsignalcomp->fid_run[filters_read]); newsignalcomp->fidfilter_freq[filters_read] = frequency; newsignalcomp->fidfilter_freq2[filters_read] = frequency * 1.12; newsignalcomp->fidfilter_ripple[filters_read] = -1.0; newsignalcomp->fidfilter_order[filters_read] = 1; newsignalcomp->fidfilter_type[filters_read] = type; newsignalcomp->fidfilter_model[filters_read] = 0; newsignalcomp->fidfilter_setup[filters_read] = 1; newsignalcomp->fidfilter_cnt = filters_read + 1; xml_go_up(xml_hdl); xml_go_up(xml_hdl); } for(filters_read=0; filters_read 1) || (size < 2) || (size > 10000)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file. (ravg_filter values)"); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } newsignalcomp->ravg_filter[filters_read] = create_ravg_filter(type, size); if(newsignalcomp->ravg_filter[filters_read] == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred when creating an ravg filter."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } newsignalcomp->ravg_filter_size[filters_read] = size; newsignalcomp->ravg_filter_type[filters_read] = type; newsignalcomp->ravg_filter_cnt = filters_read + 1; xml_go_up(xml_hdl); xml_go_up(xml_hdl); } for(filters_read=0; filters_read 2) || (order < 1) || (order > 100) || (type < 0) || (type > 4) || (ripple < (-6.0)) || (ripple > (-0.1)) || (frequency < 0.0001) || (frequency2 < 0.0001)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file. (fidfilter values)"); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(frequency >= ((newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].smp_per_record / newsignalcomp->edfhdr->data_record_duration) / 2.0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The frequency of the filter(s) must be less than: samplerate / 2"); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(type > 2) { if(frequency2 >= ((newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].smp_per_record / newsignalcomp->edfhdr->data_record_duration) / 2.0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The frequency of the filter(s) must be less than: samplerate / 2"); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } } if((type == 0) || (type == 1)) { if(order > 8) { order = 8; } } if(type == 0) { if(model == 0) { sprintf(spec_str, "HpBu%i/%f", order, frequency); } if(model == 1) { sprintf(spec_str, "HpCh%i/%f/%f", order, ripple, frequency); } if(model == 2) { sprintf(spec_str, "HpBe%i/%f", order, frequency); } } if(type == 1) { if(model == 0) { sprintf(spec_str, "LpBu%i/%f", order, frequency); } if(model == 1) { sprintf(spec_str, "LpCh%i/%f/%f", order, ripple, frequency); } if(model == 2) { sprintf(spec_str, "LpBe%i/%f", order, frequency); } } if(type == 2) { if(order > 100) { order = 100; } if(order < 3) { order = 3; } if(model == 0) { sprintf(spec_str, "BsRe/%i/%f", order, frequency); } } if((type == 3) || (type == 4)) { if(order < 2) { order = 2; } if(order % 2) { order++; } if(order > 16) { order = 16; } } if(type == 3) { if(model == 0) { sprintf(spec_str, "BpBu%i/%f-%f", order, frequency, frequency2); } if(model == 1) { sprintf(spec_str, "BpCh%i/%f/%f-%f", order, ripple, frequency, frequency2); } if(model == 2) { sprintf(spec_str, "BpBe%i/%f-%f", order, frequency, frequency2); } } if(type == 4) { if(model == 0) { sprintf(spec_str, "BsBu%i/%f-%f", order, frequency, frequency2); } if(model == 1) { sprintf(spec_str, "BsCh%i/%f/%f-%f", order, ripple, frequency, frequency2); } if(model == 2) { sprintf(spec_str, "BsBe%i/%f-%f", order, frequency, frequency2); } } filter_spec = spec_str; err = fid_parse(((double)(newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].smp_per_record)) / newsignalcomp->edfhdr->data_record_duration, &filter_spec, &newsignalcomp->fidfilter[filters_read]); if(err != NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", err); messagewindow.exec(); free(err); free(newsignalcomp); xml_close(xml_hdl); return; } newsignalcomp->fid_run[filters_read] = fid_run_new(newsignalcomp->fidfilter[filters_read], &newsignalcomp->fidfuncp[filters_read]); newsignalcomp->fidbuf[filters_read] = fid_run_newbuf(newsignalcomp->fid_run[filters_read]); newsignalcomp->fidbuf2[filters_read] = fid_run_newbuf(newsignalcomp->fid_run[filters_read]); newsignalcomp->fidfilter_freq[filters_read] = frequency; newsignalcomp->fidfilter_freq2[filters_read] = frequency2; newsignalcomp->fidfilter_ripple[filters_read] = ripple; newsignalcomp->fidfilter_order[filters_read] = order; newsignalcomp->fidfilter_type[filters_read] = type; newsignalcomp->fidfilter_model[filters_read] = model; newsignalcomp->fidfilter_setup[filters_read] = 1; newsignalcomp->fidfilter_cnt = filters_read + 1; xml_go_up(xml_hdl); xml_go_up(xml_hdl); } if(!xml_goto_nth_element_inside(xml_hdl, "ecg_filter", 0)) { if(xml_goto_nth_element_inside(xml_hdl, "type", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } type = atoi(result); if(type == 1) { newsignalcomp->ecg_filter = create_ecg_filter(newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].smp_per_record / newsignalcomp->edfhdr->data_record_duration, newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].bitvalue, mainwindow->powerlinefreq); if(newsignalcomp->ecg_filter == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred when creating an ECG filter."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } strcpy(newsignalcomp->signallabel_bu, newsignalcomp->signallabel); newsignalcomp->signallabellen_bu = newsignalcomp->signallabellen; strcpy(newsignalcomp->signallabel, "HR"); newsignalcomp->signallabellen = strlen(newsignalcomp->signallabel); strcpy(newsignalcomp->physdimension_bu, newsignalcomp->physdimension); strcpy(newsignalcomp->physdimension, "bpm"); } xml_go_up(xml_hdl); xml_go_up(xml_hdl); } if(newsignalcomp->ecg_filter == NULL) { if(!xml_goto_nth_element_inside(xml_hdl, "zratio_filter", 0)) { if(xml_goto_nth_element_inside(xml_hdl, "type", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } type = atoi(result); xml_go_up(xml_hdl); if(type == 1) { if(xml_goto_nth_element_inside(xml_hdl, "crossoverfreq", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } newsignalcomp->zratio_crossoverfreq = atof(result); if((newsignalcomp->zratio_crossoverfreq < 5.0) || (newsignalcomp->zratio_crossoverfreq > 9.5)) { newsignalcomp->zratio_crossoverfreq = 7.5; } newsignalcomp->zratio_filter = create_zratio_filter(newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].smp_per_record, newsignalcomp->edfhdr->long_data_record_duration, newsignalcomp->zratio_crossoverfreq, newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].bitvalue); if(newsignalcomp->zratio_filter == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred when creating a Z-ratio filter."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } strcpy(newsignalcomp->signallabel_bu, newsignalcomp->signallabel); newsignalcomp->signallabellen_bu = newsignalcomp->signallabellen; strcpy(newsignalcomp->signallabel, "Z-ratio "); strcat(newsignalcomp->signallabel, newsignalcomp->signallabel_bu); newsignalcomp->signallabellen = strlen(newsignalcomp->signallabel); strcpy(newsignalcomp->physdimension_bu, newsignalcomp->physdimension); strcpy(newsignalcomp->physdimension, ""); xml_go_up(xml_hdl); } xml_go_up(xml_hdl); } } if(f_ruler_cnt == 0) { if(!xml_goto_nth_element_inside(xml_hdl, "floating_ruler", 0)) { if(xml_goto_nth_element_inside(xml_hdl, "hasruler", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } tmp = atoi(result); xml_go_up(xml_hdl); if(tmp == 1) { f_ruler_cnt = 1; mainwindow->maincurve->ruler_x_position = 200; mainwindow->maincurve->ruler_y_position = 200; mainwindow->maincurve->floating_ruler_value = 0; if(!xml_goto_nth_element_inside(xml_hdl, "ruler_x_position", 0)) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } tmp = atoi(result); if((tmp >= 0) && (tmp < 5000)) { mainwindow->maincurve->ruler_x_position = tmp; } xml_go_up(xml_hdl); } if(!xml_goto_nth_element_inside(xml_hdl, "ruler_y_position", 0)) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } tmp = atoi(result); if((tmp >= 0) && (tmp < 5000)) { mainwindow->maincurve->ruler_y_position = tmp; } xml_go_up(xml_hdl); } if(!xml_goto_nth_element_inside(xml_hdl, "floating_ruler_value", 0)) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); free(newsignalcomp); xml_close(xml_hdl); return; } tmp = atoi(result); if((tmp >= 0) && (tmp < 2)) { mainwindow->maincurve->floating_ruler_value = tmp; } xml_go_up(xml_hdl); } newsignalcomp->hasruler = 1; } xml_go_up(xml_hdl); } } mainwindow->signalcomp[mainwindow->signalcomps] = newsignalcomp; mainwindow->signalcomps++; signalcomps_read++; } xml_goto_root(xml_hdl); if(!(xml_goto_nth_element_inside(xml_hdl, "pagetime", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this montage file."); messagewindow.exec(); xml_close(xml_hdl); return; } mainwindow->pagetime = atoll(result); if(mainwindow->pagetime < 10000LL) { mainwindow->pagetime = 10000LL; } } xml_goto_root(xml_hdl); struct spectrumdocksettings settings[MAXSPECTRUMDOCKS]; for(i=0; iclose(); mainwindow->setMainwindowTitle(mainwindow->edfheaderlist[mainwindow->sel_viewtime]); if(mainwindow->files_open == 1) { strcpy(&mainwindow->recent_file_mtg_path[0][0], mtg_path); } mainwindow->timescale_doubler = round_125_cat(mainwindow->pagetime); for(i=0; i<3; i++) { amp_cat[i] = 0; } for(i=0; isignalcomps; i++) { tmp = round_125_cat(mainwindow->signalcomp[i]->voltpercm); switch(tmp) { case 10 : amp_cat[0]++; break; case 20 : amp_cat[1]++; break; case 50 : amp_cat[2]++; break; } } mainwindow->amplitude_doubler = 10; if((amp_cat[1] > amp_cat[0]) && (amp_cat[1] >= amp_cat[2])) { mainwindow->amplitude_doubler = 20; } if((amp_cat[2] > amp_cat[0]) && (amp_cat[2] > amp_cat[1])) { mainwindow->amplitude_doubler = 50; } if(f_ruler_cnt == 1) { mainwindow->maincurve->ruler_active = 1; } for(i=0; i= 0) { if(mainwindow->spectrumdock[i]->dock->isVisible()) { mainwindow->spectrumdock[i]->clear(); mainwindow->spectrumdock[i]->dock->hide(); } } } mainwindow->setup_viewbuf(); for(i=0; i= 0) && (settings[i].signalnr < MAXSIGNALS) && (settings[i].signalnr < mainwindow->signalcomps)) { mainwindow->spectrumdock[i]->init(settings[i].signalnr); mainwindow->spectrumdock[i]->setsettings(settings[i]); } } } void UI_LoadMontagewindow::strip_types_from_label(char *label) { int i, len; len = strlen(label); if(len<16) { return; } if((!(strncmp(label, "EEG ", 4))) ||(!(strncmp(label, "ECG ", 4))) ||(!(strncmp(label, "EOG ", 4))) ||(!(strncmp(label, "ERG ", 4))) ||(!(strncmp(label, "EMG ", 4))) ||(!(strncmp(label, "MEG ", 4))) ||(!(strncmp(label, "MCG ", 4)))) { if(label[4]!=' ') { for(i=0; i<(len-4); i++) { label[i] = label[i+4]; } for(; i. * *************************************************************************** */ #ifndef EDFBROWSER_GLOBAL_H #define EDFBROWSER_GLOBAL_H #include #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) #define fopeno fopen #else #define fseeko fseeko64 #define ftello ftello64 #define fopeno fopen64 #endif #define PROGRAM_NAME "EDFbrowser" #define PROGRAM_VERSION "1.57" #define MINIMUM_QT_VERSION 0x040701 #define MAXFILES 32 #define MAXSIGNALS 512 #define MAXFILTERS 16 #define TIME_DIMENSION (10000000LL) #define MAX_ANNOTATION_LEN 512 #define VIEWTIME_SYNCED_OFFSET 0 #define VIEWTIME_SYNCED_ABSOLUT 1 #define VIEWTIME_UNSYNCED 2 #define VIEWTIME_USER_DEF_SYNCED 3 #define MAX_PATH_LENGTH 1024 #define MAX_RECENTFILES 32 #define MAX_ACTIVE_ANNOT_MARKERS 64 #define MAXSPECTRUMDIALOGS 32 #define MAXSPECTRUMDOCKS 8 #define MAXPREDEFINEDMONTAGES 12 #define MAXAVERAGECURVEDIALOGS 32 #define MAXZSCOREDIALOGS 32 #define ANNOT_ID_NK_TRIGGER 0 #define ANNOT_ID_BS_TRIGGER 1 #define VIDEO_STATUS_STOPPED 0 #define VIDEO_STATUS_STARTUP_1 1 #define VIDEO_STATUS_STARTUP_2 2 #define VIDEO_STATUS_STARTUP_3 3 #define VIDEO_STATUS_STARTUP_4 4 #define VIDEO_STATUS_STARTUP_5 5 #define VIDEO_STATUS_PLAYING 16 #define VIDEO_STATUS_PAUSED 17 #define VIDEO_STATUS_ENDED 18 #include "filter.h" #include "third_party/fidlib/fidlib.h" #include "ravg_filter.h" #include "spike_filter.h" #include "ecg_filter.h" #include "z_ratio_filter.h" struct edfparamblock{ char label[17]; char transducer[81]; char physdimension[9]; double phys_min; double phys_max; int dig_min; int dig_max; char prefilter[81]; int smp_per_record; char reserved[33]; double offset; int buf_offset; double bitvalue; int annotation; }; struct edfhdrblock{ FILE *file_hdl; int file_num; char version[32]; char filename[MAX_PATH_LENGTH]; char patient[81]; char recording[81]; char plus_patientcode[81]; char plus_gender[16]; char plus_birthdate[16]; char plus_patient_name[81]; char plus_patient_additional[81]; char plus_startdate[16]; char plus_admincode[81]; char plus_technician[81]; char plus_equipment[81]; char plus_recording_additional[81]; long long l_starttime; long long utc_starttime; char reserved[45]; int hdrsize; int edfsignals; long long datarecords; int recordsize; int annot_ch[256]; int nr_annot_chns; int edf; int edfplus; int bdf; int bdfplus; int discontinuous; int genuine_nk; int nk_triggers_read; int genuine_biosemi; double data_record_duration; long long long_data_record_duration; long long viewtime; long long starttime_offset; long long prefiltertime; int annots_not_read; int recording_len_sec; struct edfparamblock *edfparam; }; struct signalcompblock{ int filenum; struct edfhdrblock *edfhdr; int num_of_signals; int viewbufsize; int viewbufoffset; long long records_in_viewbuf; long long samples_in_viewbuf; long long samples_on_screen; long long sample_start; long long sample_stop; int timeoffset; int sample_timeoffset; int pixels_shift; double sample_timeoffset_part; double sample_pixel_ratio; int edfsignal[MAXSIGNALS]; int factor[MAXSIGNALS]; int polarity; double sensitivity[MAXSIGNALS]; int oldvalue; long long oldsmplnr; long long file_duration; char signallabel[512]; char alias[17]; int signallabellen; char signallabel_bu[512]; int signallabellen_bu; int hascursor1; int hascursor2; int hasoffsettracking; int hasgaintracking; int hasruler; double screen_offset; double voltpercm; char physdimension[9]; char physdimension_bu[9]; int color; int filter_cnt; int samples_in_prefilterbuf; long long prefilter_starttime; int prefilter_reset_sample; double filterpreset_a[MAXFILTERS]; double filterpreset_b[MAXFILTERS]; struct filter_settings *filter[MAXFILTERS]; int max_dig_value; int min_dig_value; int fidfilter_cnt; int fidfilter_type[MAXFILTERS]; double fidfilter_freq[MAXFILTERS]; double fidfilter_freq2[MAXFILTERS]; double fidfilter_ripple[MAXFILTERS]; int fidfilter_order[MAXFILTERS]; int fidfilter_model[MAXFILTERS]; FidFilter *fidfilter[MAXFILTERS]; FidRun *fid_run[MAXFILTERS]; FidFunc *fidfuncp[MAXFILTERS]; void *fidbuf[MAXFILTERS]; void *fidbuf2[MAXFILTERS]; int fidfilter_setup[MAXFILTERS]; int stat_cnt; int stat_zero_crossing_cnt; double stat_sum; double stat_sum_sqr; double stat_sum_rectified; int ravg_filter_cnt; int ravg_filter_type[MAXFILTERS]; int ravg_filter_size[MAXFILTERS]; int ravg_filter_setup[MAXFILTERS]; struct ravg_filter_settings *ravg_filter[MAXFILTERS]; struct ecg_filter_settings *ecg_filter; double spike_filter_velocity; int spike_filter_holdoff; struct spike_filter_settings *spike_filter; struct zratio_filter_settings *zratio_filter; double zratio_crossoverfreq; int spectr_dialog[MAXSPECTRUMDIALOGS]; int avg_dialog[MAXAVERAGECURVEDIALOGS]; int zscoredialog[MAXZSCOREDIALOGS]; }; struct zoomhistoryblock{ int pntr; int history_size_tail; int history_size_front; long long viewtime[64][MAXFILES]; long long pagetime[64]; double voltpercm[64][MAXSIGNALS]; double sensitivity[64][MAXSIGNALS][MAXSIGNALS]; double screen_offset[64][MAXSIGNALS]; }; struct annotationblock{ int file_num; long long onset; char duration[16]; char annotation[MAX_ANNOTATION_LEN + 1]; struct annotationblock *former_annotation; struct annotationblock *next_annotation; int modified; int x_pos; int selected; int jump; int hided; int hided_in_list; unsigned int ident; }; struct active_markersblock{ int file_num; struct annotationblock *list[MAX_ACTIVE_ANNOT_MARKERS]; int count; int selected; }; struct graphicLineStruct{ int x1; int y1; int x2; int y2; }; struct graphicBufStruct{ struct graphicLineStruct graphicLine[MAXSIGNALS]; }; struct crossHairStruct{ int color; int file_num; int active; int moving; int position; int x_position; int y_position; int y_value; double value; long long time; long long time_relative; }; struct video_player_struct{ int status; int cntdwn_timer; int poll_timer; long long utc_starttime; int starttime_diff; int stop_det_counter; int fpos; }; #endif edfbrowser_157_source/PaxHeaders.7921/show_edf_hdr.cpp0000644000000000000000000000012712646460742020031 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/show_edf_hdr.cpp0000644000175000001440000003460712646460742020400 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "show_edf_hdr.h" UI_EDFhdrwindow::UI_EDFhdrwindow(QWidget *w_parent) { int i; edfplus_layout = 0; mainwindow = (UI_Mainwindow *)w_parent; EDFhdrDialog = new QDialog; EDFhdrDialog->setMinimumSize(690, 480); EDFhdrDialog->setMaximumSize(690, 480); EDFhdrDialog->setWindowTitle("File Info"); EDFhdrDialog->setModal(true); EDFhdrDialog->setAttribute(Qt::WA_DeleteOnClose, true); filelist = new QListWidget(EDFhdrDialog); filelist->setGeometry(10, 10, 670, 75); for(i=0; ifiles_open; i++) { new QListWidgetItem(QString::fromLocal8Bit(mainwindow->edfheaderlist[i]->filename), filelist); } label1 = new QLabel(EDFhdrDialog); label1->setGeometry(10, 120, 80, 25); label1->setText("Subject"); label1a = new SpecialButton(EDFhdrDialog); label1a->setGeometry(100, 120, 580, 25); label1a->setColor(Qt::white); label2 = new QLabel(EDFhdrDialog); label2->setGeometry(10, 155, 80, 25); label2->setText("Recording"); label2a = new SpecialButton(EDFhdrDialog); label2a->setGeometry(100, 155, 580, 25); label2a->setColor(Qt::white); label3 = new QLabel(EDFhdrDialog); label3->setGeometry(10, 190, 80, 25); label3->setText("Start"); label3a = new SpecialButton(EDFhdrDialog); label3a->setGeometry(100, 190, 180, 25); label3a->setColor(Qt::white); label4 = new QLabel(EDFhdrDialog); label4->setGeometry(410, 190, 80, 25); label4->setText("Duration"); label4a = new SpecialButton(EDFhdrDialog); label4a->setGeometry(500, 190, 180, 25); label4a->setColor(Qt::white); label5 = new QLabel(EDFhdrDialog); label5->setGeometry(10, 225, 80, 25); label5->setText("Reserved"); label5a = new SpecialButton(EDFhdrDialog); label5a->setGeometry(100, 225, 350, 25); label5a->setColor(Qt::white); label6 = new QLabel(EDFhdrDialog); label6->setGeometry(10, 190, 130, 25); label6->setText("Birthdate"); label6->setVisible(false); label6a = new SpecialButton(EDFhdrDialog); label6a->setGeometry(150, 190, 530, 25); label6a->setColor(Qt::white); label6a->setVisible(false); label7 = new QLabel(EDFhdrDialog); label7->setGeometry(10, 225, 130, 25); label7->setText("Subject name"); label7->setVisible(false); label7a = new SpecialButton(EDFhdrDialog); label7a->setGeometry(150, 225, 530, 25); label7a->setColor(Qt::white); label7a->setVisible(false); label8 = new QLabel(EDFhdrDialog); label8->setGeometry(10, 260, 130, 25); label8->setText("Additional info"); label8->setVisible(false); label8a = new SpecialButton(EDFhdrDialog); label8a->setGeometry(150, 260, 530, 25); label8a->setColor(Qt::white); label8a->setVisible(false); label9 = new QLabel(EDFhdrDialog); label9->setGeometry(10, 290, 130, 25); label9->setText("Startdate"); label9->setVisible(false); label9a = new SpecialButton(EDFhdrDialog); label9a->setGeometry(150, 290, 530, 25); label9a->setColor(Qt::white); label9a->setVisible(false); label10 = new QLabel(EDFhdrDialog); label10->setGeometry(10, 325, 130, 25); label10->setText("Administr. code"); label10->setVisible(false); label10a = new SpecialButton(EDFhdrDialog); label10a->setGeometry(150, 325, 530, 25); label10a->setColor(Qt::white); label10a->setVisible(false); label11 = new QLabel(EDFhdrDialog); label11->setGeometry(10, 360, 130, 25); label11->setText("Technician"); label11->setVisible(false); label11a = new SpecialButton(EDFhdrDialog); label11a->setGeometry(150, 360, 530, 25); label11a->setColor(Qt::white); label11a->setVisible(false); label12 = new QLabel(EDFhdrDialog); label12->setGeometry(10, 395, 130, 25); label12->setText("Device"); label12->setVisible(false); label12a = new SpecialButton(EDFhdrDialog); label12a->setGeometry(150, 395, 530, 25); label12a->setColor(Qt::white); label12a->setVisible(false); label13 = new QLabel(EDFhdrDialog); label13->setGeometry(10, 430, 130, 25); label13->setText("Additional info"); label13->setVisible(false); label13a = new SpecialButton(EDFhdrDialog); label13a->setGeometry(150, 430, 530, 25); label13a->setColor(Qt::white); label13a->setVisible(false); label20 = new QLabel(EDFhdrDialog); label20->setGeometry(10, 260, 130, 25); label20->setText("Datarecord duration"); label20a = new SpecialButton(EDFhdrDialog); label20a->setGeometry(150, 260, 100, 25); label20a->setColor(Qt::white); label21 = new QLabel(EDFhdrDialog); label21->setGeometry(410, 260, 80, 25); label21->setText("Version"); label21a = new SpecialButton(EDFhdrDialog); label21a->setGeometry(500, 260, 180, 25); label21a->setColor(Qt::white); signallist = new QTableWidget(EDFhdrDialog); signallist->setGeometry(10, 295, 670, 100); signallist->setSelectionMode(QAbstractItemView::NoSelection); signallist->setEditTriggers(QAbstractItemView::NoEditTriggers); pushButton1 = new QPushButton(EDFhdrDialog); pushButton1->setGeometry(580, 445, 100, 25); pushButton1->setText("Close"); QObject::connect(pushButton1, SIGNAL(clicked()), EDFhdrDialog, SLOT(close())); QObject::connect(filelist, SIGNAL(currentRowChanged(int)), this, SLOT(show_params(int))); filelist->setCurrentRow(mainwindow->files_open - 1); EDFhdrDialog->exec(); } void UI_EDFhdrwindow::show_params(int row) { int i, signal_cnt; char str[512]; long long file_duration; struct date_time_struct date_time; if(row<0) return; if(mainwindow->edfheaderlist[row]->edfplus || mainwindow->edfheaderlist[row]->bdfplus) { edfplus_layout = 1; EDFhdrDialog->setMinimumSize(690, 765); EDFhdrDialog->setMaximumSize(690, 765); pushButton1->setGeometry(580, 730, 100, 25); signallist->setGeometry(10, 580, 670, 100); label20a->setGeometry(150, 545, 100, 25); label20->setGeometry(10, 545, 130, 25); label21->setGeometry(410, 545, 80, 25); label21a->setGeometry(500, 545, 180, 25); label5a->setGeometry(150, 500, 350, 25); label5->setGeometry(10, 500, 80, 25); label4a->setGeometry(500, 465, 180, 25); label4->setGeometry(410, 465, 80, 25); label3a->setGeometry(150, 465, 180, 25); label3->setGeometry(10, 465, 80, 25); label1a->setGeometry(150, 120, 530, 25); label1a->setText(mainwindow->edfheaderlist[row]->plus_patientcode); label1->setGeometry(10, 120, 130, 25); label1->setText("Subject code"); label2a->setGeometry(150, 155, 530, 25); label2a->setText(mainwindow->edfheaderlist[row]->plus_gender); label2->setGeometry(10, 155, 130, 25); label2->setText("Sex"); label6->setVisible(true); label6a->setVisible(true); label6a->setText(mainwindow->edfheaderlist[row]->plus_birthdate); label7->setVisible(true); label7a->setVisible(true); label7a->setText(mainwindow->edfheaderlist[row]->plus_patient_name); label8->setVisible(true); label8a->setVisible(true); label8a->setText(mainwindow->edfheaderlist[row]->plus_patient_additional); label9->setVisible(true); label9a->setVisible(true); label9a->setText(mainwindow->edfheaderlist[row]->plus_startdate); label10->setVisible(true); label10a->setVisible(true); label10a->setText(mainwindow->edfheaderlist[row]->plus_admincode); label11->setVisible(true); label11a->setVisible(true); label11a->setText(mainwindow->edfheaderlist[row]->plus_technician); label12->setVisible(true); label12a->setVisible(true); label12a->setText(mainwindow->edfheaderlist[row]->plus_equipment); label13->setVisible(true); label13a->setVisible(true); label13a->setText(mainwindow->edfheaderlist[row]->plus_recording_additional); } else { label6->setVisible(false); label6a->setVisible(false); label7->setVisible(false); label7a->setVisible(false); label8->setVisible(false); label8a->setVisible(false); label9->setVisible(false); label9a->setVisible(false); label10->setVisible(false); label10a->setVisible(false); label11->setVisible(false); label11a->setVisible(false); label12->setVisible(false); label12a->setVisible(false); label13->setVisible(false); label13a->setVisible(false); EDFhdrDialog->setMinimumSize(690, 480); EDFhdrDialog->setMaximumSize(690, 480); label1->setGeometry(10, 120, 80, 25); label1->setText("Subject"); label1a->setGeometry(100, 120, 580, 25); label1a->setText(mainwindow->edfheaderlist[row]->patient); label2->setGeometry(10, 155, 80, 25); label2->setText("Recording"); label2a->setGeometry(100, 155, 580, 25); label2a->setText(mainwindow->edfheaderlist[row]->recording); label3a->setGeometry(100, 190, 180, 25); label3->setGeometry(10, 190, 80, 25); label4a->setGeometry(500, 190, 180, 25); label4->setGeometry(410, 190, 80, 25); label5a->setGeometry(100, 225, 350, 25); label5->setGeometry(10, 225, 80, 25); label20->setGeometry(10, 260, 130, 25); label20a->setGeometry(150, 260, 100, 25); label21->setGeometry(410, 260, 80, 25); label21a->setGeometry(500, 260, 180, 25); signallist->setGeometry(10, 295, 670, 100); pushButton1->setGeometry(580, 445, 100, 25); } utc_to_date_time(mainwindow->edfheaderlist[row]->utc_starttime, &date_time); date_time.month_str[0] += 32; date_time.month_str[1] += 32; date_time.month_str[2] += 32; snprintf(str, 400, "%i %s %i %2i:%02i:%02i", date_time.day, date_time.month_str, date_time.year, date_time.hour, date_time.minute, date_time.second); if(mainwindow->edfheaderlist[row]->starttime_offset != 0LL) { #ifdef Q_OS_WIN32 __mingw_snprintf(str + strlen(str), 100, ".%07lli", mainwindow->edfheaderlist[row]->starttime_offset); #else snprintf(str + strlen(str), 100, ".%07lli", mainwindow->edfheaderlist[row]->starttime_offset); #endif remove_trailing_zeros(str); } label3a->setText(str); file_duration = mainwindow->edfheaderlist[row]->long_data_record_duration * mainwindow->edfheaderlist[row]->datarecords; if((file_duration / TIME_DIMENSION) / 10) { snprintf(str, 512, "%2i:%02i:%02i", (int)((file_duration / TIME_DIMENSION)/ 3600LL), (int)(((file_duration / TIME_DIMENSION) % 3600LL) / 60LL), (int)((file_duration / TIME_DIMENSION) % 60LL)); } else { snprintf(str, 512, "%2i:%02i:%02i.%06i", (int)((file_duration / TIME_DIMENSION)/ 3600LL), (int)(((file_duration / TIME_DIMENSION) % 3600LL) / 60LL), (int)((file_duration / TIME_DIMENSION) % 60LL), (int)((file_duration % TIME_DIMENSION) / 10LL)); } label4a->setText(str); label5a->setText(mainwindow->edfheaderlist[row]->reserved); snprintf(str, 512, "%.12f", mainwindow->edfheaderlist[row]->data_record_duration); remove_trailing_zeros(str); label20a->setText(str); label21a->setText(mainwindow->edfheaderlist[row]->version); signal_cnt = mainwindow->edfheaderlist[row]->edfsignals; signallist->setColumnCount(10); signallist->setRowCount(signal_cnt); signallist->setSelectionMode(QAbstractItemView::NoSelection); signallist->setColumnWidth(0, 180); signallist->setColumnWidth(1, 120); signallist->setColumnWidth(2, 120); signallist->setColumnWidth(3, 120); signallist->setColumnWidth(4, 120); signallist->setColumnWidth(5, 120); signallist->setColumnWidth(6, 120); signallist->setColumnWidth(7, 120); signallist->setColumnWidth(8, 520); signallist->setColumnWidth(9, 520); QStringList horizontallabels; horizontallabels += "Label"; horizontallabels += "Samplefrequency"; horizontallabels += "Physical maximum"; horizontallabels += "Physical minimum"; horizontallabels += "Physical dimension"; horizontallabels += "Digital maximum"; horizontallabels += "Digital minimum"; horizontallabels += "Samples per record"; horizontallabels += "Prefilter"; horizontallabels += "Transducer"; signallist->setHorizontalHeaderLabels(horizontallabels); for(i=0; isetRowHeight(i, 25); signallist->setCellWidget(i, 0, new QLabel(mainwindow->edfheaderlist[row]->edfparam[i].label)); convert_to_metric_suffix(str, (double)mainwindow->edfheaderlist[row]->edfparam[i].smp_per_record / mainwindow->edfheaderlist[row]->data_record_duration, 3); strcat(str, "Hz"); remove_trailing_zeros(str); signallist->setCellWidget(i, 1, new QLabel(str)); snprintf(str, 512, "%+f", mainwindow->edfheaderlist[row]->edfparam[i].phys_max); remove_trailing_zeros(str); signallist->setCellWidget(i, 2, new QLabel(str)); snprintf(str, 512, "%+f", mainwindow->edfheaderlist[row]->edfparam[i].phys_min); remove_trailing_zeros(str); signallist->setCellWidget(i, 3, new QLabel(str)); signallist->setCellWidget(i, 4, new QLabel(mainwindow->edfheaderlist[row]->edfparam[i].physdimension)); snprintf(str, 512, "%+i", mainwindow->edfheaderlist[row]->edfparam[i].dig_max); signallist->setCellWidget(i, 5, new QLabel(str)); snprintf(str, 512, "%+i", mainwindow->edfheaderlist[row]->edfparam[i].dig_min); signallist->setCellWidget(i, 6, new QLabel(str)); snprintf(str, 512, "%i", mainwindow->edfheaderlist[row]->edfparam[i].smp_per_record); signallist->setCellWidget(i, 7, new QLabel(str)); signallist->setCellWidget(i, 8, new QLabel(mainwindow->edfheaderlist[row]->edfparam[i].prefilter)); signallist->setCellWidget(i, 9, new QLabel(mainwindow->edfheaderlist[row]->edfparam[i].transducer)); } } edfbrowser_157_source/PaxHeaders.7921/z_score_dialog.h0000644000000000000000000000013212646460742020022 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/z_score_dialog.h0000644000175000001440000000710512646460742020366 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef ZSCORE_FORM1_H #define ZSCORE_FORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "edf_annot_list.h" #include "utils.h" #include "filteredblockread.h" #include "signalcurve.h" #include "annotations_dock.h" #include "filter.h" #include "spike_filter.h" #include "ravg_filter.h" #include "third_party/kiss_fft/kiss_fftr.h" class UI_Mainwindow; class UI_ZScoreWindow : public QObject { Q_OBJECT public: UI_ZScoreWindow(QWidget *, UI_ZScoreWindow **, int, int); ~UI_ZScoreWindow(); UI_Mainwindow *mainwindow; QDialog *zscore_dialog; private: QHBoxLayout *hlayout1, *hlayout2, *hlayout3, *hlayout4, *hlayout5; QVBoxLayout *vlayout2, *vlayout3; QLabel *crossoverbinLabel, *thresholdLabel, *pagelenLabel, *hysteresisLabel; // *errordetectionLabel; QPushButton *CloseButton, *StartButton, *get_annotButton, *defaultButton, *jumpButton, *addTraceButton; QSpinBox *pagelenSpinbox; // *errordetectionSpinbox; QDoubleSpinBox *thresholdSpinbox, *crossoverSpinbox, *hysteresisSpinbox; QRadioButton *epochRadioButton, *pageRadioButton, *wakesleepRadioButton; SignalCurve *curve1; UI_ZScoreWindow **zscoredialog; QAction *shift_page_right_Act, *shift_page_left_Act; int signalnr, zscore_page_len, avg_majority, epoch_cntr, zscore_pages, zscore_wake, *zscore_sleepstage_buf, *zscore_error_buf, plot_type, zscore_dialog_is_destroyed, zscore_dialognumber, zscore_error_detection; double *zscore_epoch_buf, *zscore_page_buf, crossoverfreq, z_threshold, z_hysteresis; private slots: void startButtonClicked(); void get_annotationsButtonClicked(); void jumpButtonClicked(); void ZscoreDialogDestroyed(QObject *); void RadioButtonsClicked(bool); void defaultButtonClicked(); void markersMoved(); void addTraceButtonClicked(); void shift_page_right(); void shift_page_left(); }; #endif // ZSCORE_FORM1_H edfbrowser_157_source/PaxHeaders.7921/edf_compat.h0000644000000000000000000000013212646460742017140 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/edf_compat.h0000644000175000001440000000363112646460742017504 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef EDFCOMPATFORM1_H #define EDFCOMPATFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" class UI_Mainwindow; class UI_EDFCompatwindow : public QObject { Q_OBJECT public: UI_EDFCompatwindow(QWidget *parent); UI_Mainwindow *mainwindow; private: QDialog *EDFCompatDialog; QListWidget *filelist; QPushButton *CloseButton, *CheckButton; int is_duration_number(char *); int is_onset_number(char *); int is_integer_number(char *); int is_number(char *); private slots: void CheckButtonClicked(); }; #endif // EDFCOMPATFORM1_H edfbrowser_157_source/PaxHeaders.7921/bdf2edf.h0000644000000000000000000000013212646460742016333 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/bdf2edf.h0000644000175000001440000000533612646460742016703 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_BDF2EDFFORM_H #define UI_BDF2EDFFORM_H #include #include #include #include #include #include #include #include #include #include #include #if QT_VERSION < 0x050000 #include #include #endif #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "check_edf_file.h" #include "filter.h" #include "utils.h" class UI_Mainwindow; class UI_BDF2EDFwindow : public QObject { Q_OBJECT public: UI_BDF2EDFwindow(QWidget *parent); UI_Mainwindow *mainwindow; private: QLabel *label1, *label2, *label3; QPushButton *pushButton1, *pushButton2, *pushButton3, *pushButton4, *pushButton5; QDoubleSpinBox *spinBox1, *spinBox2; QTableWidget *SignalsTablewidget; QDialog *myobjectDialog; int signalslist[MAXSIGNALS], annotlist[MAXSIGNALS]; char inputpath[MAX_PATH_LENGTH], outputpath[MAX_PATH_LENGTH], *recent_opendir, *recent_savedir; double dividerlist[MAXSIGNALS]; FILE *inputfile, *outputfile; struct edfhdrblock *edfhdr; struct filter_settings *filterlist[MAXSIGNALS]; void showpopupmessage(const char *, const char *); private slots: void SelectFileButton(); void StartConversion(); void spinbox1_changed(double); void spinbox2_changed(double); void Select_all_signals(); void Deselect_all_signals(); void free_edfheader(); }; #endif edfbrowser_157_source/PaxHeaders.7921/edflib.c0000644000000000000000000000013212646460742016257 xustar0030 mtime=1452958178.243246747 30 atime=1452958178.243246747 30 ctime=1452958178.243246747 edfbrowser_157_source/edflib.c0000644000175000001440000037172312646460742016635 0ustar00guvusers00000000000000/* ***************************************************************************** * * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Teunis van Beelen * All rights reserved. * * email: teuniz@gmail.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY Teunis van Beelen ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL Teunis van Beelen BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************** */ /* compile with options "-D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE" */ #include "edflib.h" #define EDFLIB_VERSION 111 #define EDFLIB_MAXFILES 64 #if defined(__APPLE__) || defined(__MACH__) || defined(__APPLE_CC__) #define fopeno fopen #else #define fseeko fseeko64 #define ftello ftello64 #define fopeno fopen64 #endif #ifdef _WIN32 #ifndef __MINGW32__ /* needed for visual c */ #undef fseeko #define fseeko _fseeki64 #undef ftello #define ftello _ftelli64 #undef fopeno #define fopeno fopen #endif #endif /* max size of annotationtext */ #define EDFLIB_WRITE_MAX_ANNOTATION_LEN 40 /* bytes in datarecord for EDF annotations, must be a multiple of three and two */ #define EDFLIB_ANNOTATION_BYTES 114 #define EDFLIB_ANNOT_MEMBLOCKSZ 1000 struct edfparamblock{ char label[17]; char transducer[81]; char physdimension[9]; double phys_min; double phys_max; int dig_min; int dig_max; char prefilter[81]; int smp_per_record; char reserved[33]; double offset; int buf_offset; double bitvalue; int annotation; long long sample_pntr; }; struct edfhdrblock{ FILE *file_hdl; char path[1024]; int writemode; char version[32]; char patient[81]; char recording[81]; char plus_patientcode[81]; char plus_gender[16]; char plus_birthdate[16]; char plus_patient_name[81]; char plus_patient_additional[81]; char plus_startdate[16]; char plus_admincode[81]; char plus_technician[81]; char plus_equipment[81]; char plus_recording_additional[81]; long long l_starttime; int startdate_day; int startdate_month; int startdate_year; int starttime_second; int starttime_minute; int starttime_hour; char reserved[45]; int hdrsize; int edfsignals; long long datarecords; int recordsize; int annot_ch[EDFLIB_MAXSIGNALS]; int nr_annot_chns; int mapped_signals[EDFLIB_MAXSIGNALS]; int edf; int edfplus; int bdf; int bdfplus; int discontinuous; int signal_write_sequence_pos; long long starttime_offset; double data_record_duration; long long long_data_record_duration; int annots_in_file; int annotlist_sz; int total_annot_bytes; int eq_sf; struct edfparamblock *edfparam; }; static struct edf_annotationblock{ long long onset; char duration[16]; char annotation[EDFLIB_MAX_ANNOTATION_LEN + 1]; } *annotationslist[EDFLIB_MAXFILES]; static struct edf_write_annotationblock{ long long onset; long long duration; char annotation[EDFLIB_WRITE_MAX_ANNOTATION_LEN + 1]; } *write_annotationslist[EDFLIB_MAXFILES]; static int edf_files_open=0; static struct edfhdrblock *hdrlist[EDFLIB_MAXFILES]; static struct edfhdrblock * edflib_check_edf_file(FILE *, int *); static int edflib_is_integer_number(char *); static int edflib_is_number(char *); static long long edflib_get_long_duration(char *); static int edflib_get_annotations(struct edfhdrblock *, int, int); static int edflib_is_duration_number(char *); static int edflib_is_onset_number(char *); static long long edflib_get_long_time(char *); static int edflib_write_edf_header(struct edfhdrblock *); static void edflib_latin1_to_ascii(char *, int); static void edflib_latin12utf8(char *, int); static void edflib_remove_padding_trailing_spaces(char *); static int edflib_atoi_nonlocalized(const char *); static double edflib_atof_nonlocalized(const char *); static int edflib_sprint_number_nonlocalized(char *, double); /* static int edflib_sprint_int_number_nonlocalized(char *, int, int, int); */ static int edflib_sprint_ll_number_nonlocalized(char *, long long, int, int); static int edflib_fprint_int_number_nonlocalized(FILE *, int, int, int); static int edflib_fprint_ll_number_nonlocalized(FILE *, long long, int, int); int edflib_is_file_used(const char *path) { int i, file_used=0; for(i=0; ipath))) { file_used = 1; break; } } } return(file_used); } int edflib_get_number_of_open_files() { return(edf_files_open); } int edflib_get_handle(int file_number) { int i, file_count=0; for(i=0; ifiletype = EDFLIB_INVALID_READ_ANNOTS_VALUE; return(-1); } if(read_annotations>2) { edfhdr->filetype = EDFLIB_INVALID_READ_ANNOTS_VALUE; return(-1); } memset(edfhdr, 0, sizeof(struct edf_hdr_struct)); if(edf_files_open>=EDFLIB_MAXFILES) { edfhdr->filetype = EDFLIB_MAXFILES_REACHED; return(-1); } for(i=0; ipath))) { edfhdr->filetype = EDFLIB_FILE_ALREADY_OPENED; return(-1); } } } file = fopeno(path, "rb"); if(file==NULL) { edfhdr->filetype = EDFLIB_NO_SUCH_FILE_OR_DIRECTORY; return(-1); } hdr = edflib_check_edf_file(file, &edf_error); if(hdr==NULL) { edfhdr->filetype = edf_error; fclose(file); return(-1); } if(hdr->discontinuous) { edfhdr->filetype = EDFLIB_FILE_IS_DISCONTINUOUS; free(hdr->edfparam); free(hdr); fclose(file); return(-1); } hdr->writemode = 0; for(i=0; ihandle = i; break; } } if((hdr->edf)&&(!(hdr->edfplus))) { edfhdr->filetype = EDFLIB_FILETYPE_EDF; } if(hdr->edfplus) { edfhdr->filetype = EDFLIB_FILETYPE_EDFPLUS; } if((hdr->bdf)&&(!(hdr->bdfplus))) { edfhdr->filetype = EDFLIB_FILETYPE_BDF; } if(hdr->bdfplus) { edfhdr->filetype = EDFLIB_FILETYPE_BDFPLUS; } edfhdr->edfsignals = hdr->edfsignals - hdr->nr_annot_chns; edfhdr->file_duration = hdr->long_data_record_duration * hdr->datarecords; edfhdr->startdate_day = hdr->startdate_day; edfhdr->startdate_month = hdr->startdate_month; edfhdr->startdate_year = hdr->startdate_year; edfhdr->starttime_hour = hdr->starttime_hour; edfhdr->starttime_second = hdr->starttime_second; edfhdr->starttime_minute = hdr->starttime_minute; edfhdr->starttime_subsecond = hdr->starttime_offset; edfhdr->datarecords_in_file = hdr->datarecords; edfhdr->datarecord_duration = hdr->long_data_record_duration; annotationslist[edfhdr->handle] = NULL; hdr->annotlist_sz = 0; hdr->annots_in_file = 0; edfhdr->annotations_in_file = 0LL; if((!(hdr->edfplus))&&(!(hdr->bdfplus))) { strcpy(edfhdr->patient, hdr->patient); strcpy(edfhdr->recording, hdr->recording); edfhdr->patientcode[0] = 0; edfhdr->gender[0] = 0; edfhdr->birthdate[0] = 0; edfhdr->patient_name[0] = 0; edfhdr->patient_additional[0] = 0; edfhdr->admincode[0] = 0; edfhdr->technician[0] = 0; edfhdr->equipment[0] = 0; edfhdr->recording_additional[0] = 0; } else { edfhdr->patient[0] = 0; edfhdr->recording[0] = 0; strcpy(edfhdr->patientcode, hdr->plus_patientcode); strcpy(edfhdr->gender, hdr->plus_gender); strcpy(edfhdr->birthdate, hdr->plus_birthdate); strcpy(edfhdr->patient_name, hdr->plus_patient_name); strcpy(edfhdr->patient_additional, hdr->plus_patient_additional); strcpy(edfhdr->admincode, hdr->plus_admincode); strcpy(edfhdr->technician, hdr->plus_technician); strcpy(edfhdr->equipment, hdr->plus_equipment); strcpy(edfhdr->recording_additional, hdr->plus_recording_additional); if((read_annotations==EDFLIB_READ_ANNOTATIONS)||(read_annotations==EDFLIB_READ_ALL_ANNOTATIONS)) { if(edflib_get_annotations(hdr, edfhdr->handle, read_annotations)) { edfhdr->filetype = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; fclose(file); free(hdr->edfparam); free(hdr); return(-1); } } edfhdr->annotations_in_file = hdr->annots_in_file; } strcpy(hdr->path, path); edf_files_open++; j = 0; for(i=0; iedfsignals; i++) { if(!(hdr->edfparam[i].annotation)) { hdr->mapped_signals[j++] = i; } } for(i=0; iedfsignals; i++) { channel = hdr->mapped_signals[i]; strcpy(edfhdr->signalparam[i].label, hdr->edfparam[channel].label); strcpy(edfhdr->signalparam[i].transducer, hdr->edfparam[channel].transducer); strcpy(edfhdr->signalparam[i].physdimension, hdr->edfparam[channel].physdimension); strcpy(edfhdr->signalparam[i].prefilter, hdr->edfparam[channel].prefilter); edfhdr->signalparam[i].smp_in_file = hdr->edfparam[channel].smp_per_record * hdr->datarecords; edfhdr->signalparam[i].phys_max = hdr->edfparam[channel].phys_max; edfhdr->signalparam[i].phys_min = hdr->edfparam[channel].phys_min; edfhdr->signalparam[i].dig_max = hdr->edfparam[channel].dig_max; edfhdr->signalparam[i].dig_min = hdr->edfparam[channel].dig_min; edfhdr->signalparam[i].smp_in_datarecord = hdr->edfparam[channel].smp_per_record; } return(0); } int edfclose_file(int handle) { struct edf_write_annotationblock *annot2; int i, j, k, n, p, datrecsize, nmemb; long long offset, datarecords; char str[EDFLIB_ANNOTATION_BYTES * 2]; struct edfhdrblock *hdr; if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } hdr = hdrlist[handle]; if(hdr->writemode) { if(hdr->datarecords == 0LL) { if(edflib_write_edf_header(hdr)) { return(-1); } for(k=0; kannots_in_file; k++) { annot2 = write_annotationslist[handle] + k; p = edflib_fprint_ll_number_nonlocalized(hdr->file_hdl, (hdr->datarecords * hdr->long_data_record_duration) / EDFLIB_TIME_DIMENSION, 0, 1); if(hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) { fputc('.', hdr->file_hdl); p++; p += edflib_fprint_ll_number_nonlocalized(hdr->file_hdl, (hdr->datarecords * hdr->long_data_record_duration) % EDFLIB_TIME_DIMENSION, 7, 0); } fputc(20, hdr->file_hdl); fputc(20, hdr->file_hdl); p += 2; for(; ptotal_annot_bytes; p++) { fputc(0, hdr->file_hdl); } hdr->datarecords++; } } if(hdr->datarecords<100000000LL) { fseeko(hdr->file_hdl, 236LL, SEEK_SET); p = edflib_fprint_int_number_nonlocalized(hdr->file_hdl, (int)(hdr->datarecords), 0, 0); if(p < 2) { fputc(' ', hdr->file_hdl); } } datarecords = 0LL; offset = (long long)((hdr->edfsignals + hdr->nr_annot_chns + 1) * 256); datrecsize = hdr->total_annot_bytes; for(i=0; iedfsignals; i++) { if(hdr->edf) { offset += (long long)(hdr->edfparam[i].smp_per_record * 2); datrecsize += (hdr->edfparam[i].smp_per_record * 2); } else { offset += (long long)(hdr->edfparam[i].smp_per_record * 3); datrecsize += (hdr->edfparam[i].smp_per_record * 3); } } j = 0; for(k=0; kannots_in_file; k++) { annot2 = write_annotationslist[handle] + k; p = 0; if(j==0) // first annotation signal { if(fseeko(hdr->file_hdl, offset, SEEK_SET)) { break; } p += edflib_sprint_ll_number_nonlocalized(str, (datarecords * hdr->long_data_record_duration) / EDFLIB_TIME_DIMENSION, 0, 1); if(hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) { str[p++] = '.'; n = edflib_sprint_ll_number_nonlocalized(str + p, (datarecords * hdr->long_data_record_duration) % EDFLIB_TIME_DIMENSION, 7, 0); p += n; } str[p++] = 20; str[p++] = 20; str[p++] = 0; } n = edflib_sprint_ll_number_nonlocalized(str + p, annot2->onset / 10000LL, 0, 1); p += n; if(annot2->onset % 10000LL) { str[p++] = '.'; n = edflib_sprint_ll_number_nonlocalized(str + p, annot2->onset % 10000LL, 4, 0); p += n; } if(annot2->duration>=0LL) { str[p++] = 21; n = edflib_sprint_ll_number_nonlocalized(str + p, annot2->duration / 10000LL, 0, 0); p += n; if(annot2->duration % 10000LL) { str[p++] = '.'; n = edflib_sprint_ll_number_nonlocalized(str + p, annot2->duration % 10000LL, 4, 0); p += n; } } str[p++] = 20; for(i=0; iannotation[i]==0) { break; } str[p++] = annot2->annotation[i]; } str[p++] = 20; for(; pfile_hdl); if(nmemb != 1) { break; } j++; if(j >= hdr->nr_annot_chns) { j = 0; offset += datrecsize; datarecords++; if(datarecords>=hdr->datarecords) { break; } } } free(write_annotationslist[handle]); } else { free(annotationslist[handle]); } fclose(hdr->file_hdl); free(hdr->edfparam); free(hdr); hdrlist[handle] = NULL; edf_files_open--; return(0); } long long edfseek(int handle, int edfsignal, long long offset, int whence) { long long smp_in_file; int channel; if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(edfsignal<0) { return(-1); } if(hdrlist[handle]->writemode) { return(-1); } if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) { return(-1); } channel = hdrlist[handle]->mapped_signals[edfsignal]; smp_in_file = hdrlist[handle]->edfparam[channel].smp_per_record * hdrlist[handle]->datarecords; if(whence==EDFSEEK_SET) { hdrlist[handle]->edfparam[channel].sample_pntr = offset; } if(whence==EDFSEEK_CUR) { hdrlist[handle]->edfparam[channel].sample_pntr += offset; } if(whence==EDFSEEK_END) { hdrlist[handle]->edfparam[channel].sample_pntr = (hdrlist[handle]->edfparam[channel].smp_per_record * hdrlist[handle]->datarecords) + offset; } if(hdrlist[handle]->edfparam[channel].sample_pntr > smp_in_file) { hdrlist[handle]->edfparam[channel].sample_pntr = smp_in_file; } if(hdrlist[handle]->edfparam[channel].sample_pntr < 0LL) { hdrlist[handle]->edfparam[channel].sample_pntr = 0LL; } return(hdrlist[handle]->edfparam[channel].sample_pntr); } long long edftell(int handle, int edfsignal) { int channel; if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(edfsignal<0) { return(-1); } if(hdrlist[handle]->writemode) { return(-1); } if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) { return(-1); } channel = hdrlist[handle]->mapped_signals[edfsignal]; return(hdrlist[handle]->edfparam[channel].sample_pntr); } void edfrewind(int handle, int edfsignal) { int channel; if(handle<0) { return; } if(handle>=EDFLIB_MAXFILES) { return; } if(hdrlist[handle]==NULL) { return; } if(edfsignal<0) { return; } if(hdrlist[handle]->writemode) { return; } if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) { return; } channel = hdrlist[handle]->mapped_signals[edfsignal]; hdrlist[handle]->edfparam[channel].sample_pntr = 0LL; } int edfread_physical_samples(int handle, int edfsignal, int n, double *buf) { int bytes_per_smpl=2, tmp, i, channel; double phys_bitvalue, phys_offset; long long smp_in_file, offset, sample_pntr, smp_per_record, jump; struct edfhdrblock *hdr; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; FILE *file; if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(edfsignal<0) { return(-1); } if(hdrlist[handle]->writemode) { return(-1); } if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) { return(-1); } channel = hdrlist[handle]->mapped_signals[edfsignal]; if(n<0LL) { return(-1); } if(n==0LL) { return(0LL); } hdr = hdrlist[handle]; if(hdr->edf) { bytes_per_smpl = 2; } if(hdr->bdf) { bytes_per_smpl = 3; } smp_in_file = hdr->edfparam[channel].smp_per_record * hdr->datarecords; if((hdr->edfparam[channel].sample_pntr + n) > smp_in_file) { n = smp_in_file - hdr->edfparam[channel].sample_pntr; if(n==0) { return(0LL); } if(n<0) { return(-1); } } file = hdr->file_hdl; offset = hdr->hdrsize; offset += (hdr->edfparam[channel].sample_pntr / hdr->edfparam[channel].smp_per_record) * hdr->recordsize; offset += hdr->edfparam[channel].buf_offset; offset += ((hdr->edfparam[channel].sample_pntr % hdr->edfparam[channel].smp_per_record) * bytes_per_smpl); fseeko(file, offset, SEEK_SET); sample_pntr = hdr->edfparam[channel].sample_pntr; smp_per_record = hdr->edfparam[channel].smp_per_record; jump = hdr->recordsize - (smp_per_record * bytes_per_smpl); phys_bitvalue = hdr->edfparam[channel].bitvalue; phys_offset = hdr->edfparam[channel].offset; if(hdr->edf) { for(i=0; ibdf) { for(i=0; iedfparam[channel].sample_pntr = sample_pntr; return(n); } int edfread_digital_samples(int handle, int edfsignal, int n, int *buf) { int bytes_per_smpl=2, tmp, i, channel; long long smp_in_file, offset, sample_pntr, smp_per_record, jump; struct edfhdrblock *hdr; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; FILE *file; if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(edfsignal<0) { return(-1); } if(hdrlist[handle]->writemode) { return(-1); } if(edfsignal>=(hdrlist[handle]->edfsignals - hdrlist[handle]->nr_annot_chns)) { return(-1); } channel = hdrlist[handle]->mapped_signals[edfsignal]; if(n<0LL) { return(-1); } if(n==0LL) { return(0LL); } hdr = hdrlist[handle]; if(hdr->edf) { bytes_per_smpl = 2; } if(hdr->bdf) { bytes_per_smpl = 3; } smp_in_file = hdr->edfparam[channel].smp_per_record * hdr->datarecords; if((hdr->edfparam[channel].sample_pntr + n) > smp_in_file) { n = smp_in_file - hdr->edfparam[channel].sample_pntr; if(n==0) { return(0LL); } if(n<0) { return(-1); } } file = hdr->file_hdl; offset = hdr->hdrsize; offset += (hdr->edfparam[channel].sample_pntr / hdr->edfparam[channel].smp_per_record) * hdr->recordsize; offset += hdr->edfparam[channel].buf_offset; offset += ((hdr->edfparam[channel].sample_pntr % hdr->edfparam[channel].smp_per_record) * bytes_per_smpl); fseeko(file, offset, SEEK_SET); sample_pntr = hdr->edfparam[channel].sample_pntr; smp_per_record = hdr->edfparam[channel].smp_per_record; jump = hdr->recordsize - (smp_per_record * bytes_per_smpl); if(hdr->edf) { for(i=0; ibdf) { for(i=0; iedfparam[channel].sample_pntr = sample_pntr; return(n); } int edf_get_annotation(int handle, int n, struct edf_annotation_struct *annot) { memset(annot, 0, sizeof(struct edf_annotation_struct)); if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(hdrlist[handle]->writemode) { return(-1); } if(n<0) { return(-1); } if(n>=hdrlist[handle]->annots_in_file) { return(-1); } annot->onset = (annotationslist[handle] + n)->onset; strcpy(annot->duration, (annotationslist[handle] + n)->duration); strcpy(annot->annotation, (annotationslist[handle] + n)->annotation); return(0); } static struct edfhdrblock * edflib_check_edf_file(FILE *inputfile, int *edf_error) { int i, j, p, r=0, n, dotposition, error; char *edf_hdr, scratchpad[128], scratchpad2[64]; struct edfhdrblock *edfhdr; /***************** check header ******************************/ edf_hdr = (char *)calloc(1, 256); if(edf_hdr==NULL) { *edf_error = EDFLIB_MALLOC_ERROR; return(NULL); } edfhdr = (struct edfhdrblock *)calloc(1, sizeof(struct edfhdrblock)); if(edfhdr==NULL) { free(edf_hdr); *edf_error = EDFLIB_MALLOC_ERROR; return(NULL); } rewind(inputfile); if(fread(edf_hdr, 256, 1, inputfile)!=1) { *edf_error = EDFLIB_FILE_READ_ERROR; free(edf_hdr); free(edfhdr); return(NULL); } /**************************** VERSION ***************************************/ strncpy(scratchpad, edf_hdr, 8); scratchpad[8] = 0; if(((signed char *)scratchpad)[0]==-1) /* BDF-file */ { for(i=1; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } } if(strcmp(scratchpad + 1, "BIOSEMI")) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } edfhdr->bdf = 1; } else /* EDF-file */ { for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } } if(strcmp(scratchpad, "0 ")) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } edfhdr->edf = 1; } strncpy(edfhdr->version, edf_hdr, 8); edfhdr->version[8] = 0; if(edfhdr->bdf) edfhdr->version[0] = '.'; /********************* PATIENTNAME *********************************************/ strncpy(scratchpad, edf_hdr + 8, 80); scratchpad[80] = 0; for(i=0; i<80; i++) { if((((unsigned char *)scratchpad)[i]<32)||(((unsigned char *)scratchpad)[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } } strncpy(edfhdr->patient, edf_hdr + 8, 80); edfhdr->patient[80] = 0; /********************* RECORDING *********************************************/ strncpy(scratchpad, edf_hdr + 88, 80); scratchpad[80] = 0; for(i=0; i<80; i++) { if((((unsigned char *)scratchpad)[i]<32)||(((unsigned char *)scratchpad)[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } } strncpy(edfhdr->recording, edf_hdr + 88, 80); edfhdr->recording[80] = 0; /********************* STARTDATE *********************************************/ strncpy(scratchpad, edf_hdr + 168, 8); scratchpad[8] = 0; for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } } error = 0; if((edf_hdr[170]!='.')||(edf_hdr[173]!='.')) error = 1; if((edf_hdr[168]<48)||(edf_hdr[168]>57)) error = 1; if((edf_hdr[169]<48)||(edf_hdr[169]>57)) error = 1; if((edf_hdr[171]<48)||(edf_hdr[171]>57)) error = 1; if((edf_hdr[172]<48)||(edf_hdr[172]>57)) error = 1; if((edf_hdr[174]<48)||(edf_hdr[174]>57)) error = 1; if((edf_hdr[175]<48)||(edf_hdr[175]>57)) error = 1; strncpy(scratchpad, edf_hdr + 168, 8); if(error) { scratchpad[8] = 0; *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } scratchpad[2] = 0; scratchpad[5] = 0; scratchpad[8] = 0; if((edflib_atof_nonlocalized(scratchpad)<1)||(edflib_atof_nonlocalized(scratchpad)>31)) { strncpy(scratchpad, edf_hdr + 168, 8); scratchpad[8] = 0; *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } if((edflib_atof_nonlocalized(scratchpad+3)<1)||(edflib_atof_nonlocalized(scratchpad+3)>12)) { strncpy(scratchpad, edf_hdr + 168, 8); scratchpad[8] = 0; *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } edfhdr->startdate_day = edflib_atof_nonlocalized(scratchpad); edfhdr->startdate_month = edflib_atof_nonlocalized(scratchpad + 3); edfhdr->startdate_year = edflib_atof_nonlocalized(scratchpad + 6); if(edfhdr->startdate_year>84) { edfhdr->startdate_year += 1900; } else { edfhdr->startdate_year += 2000; } /********************* STARTTIME *********************************************/ strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } } error = 0; if((edf_hdr[178]!='.')||(edf_hdr[181]!='.')) error = 1; if((edf_hdr[176]<48)||(edf_hdr[176]>57)) error = 1; if((edf_hdr[177]<48)||(edf_hdr[177]>57)) error = 1; if((edf_hdr[179]<48)||(edf_hdr[179]>57)) error = 1; if((edf_hdr[180]<48)||(edf_hdr[180]>57)) error = 1; if((edf_hdr[182]<48)||(edf_hdr[182]>57)) error = 1; if((edf_hdr[183]<48)||(edf_hdr[183]>57)) error = 1; strncpy(scratchpad, edf_hdr + 176, 8); if(error) { strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } scratchpad[2] = 0; scratchpad[5] = 0; scratchpad[8] = 0; if(edflib_atof_nonlocalized(scratchpad)>23) { strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } if(edflib_atof_nonlocalized(scratchpad+3)>59) { strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } if(edflib_atof_nonlocalized(scratchpad+6)>59) { strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } edfhdr->starttime_hour = edflib_atof_nonlocalized(scratchpad); edfhdr->starttime_minute = edflib_atof_nonlocalized(scratchpad + 3); edfhdr->starttime_second = edflib_atof_nonlocalized(scratchpad + 6); edfhdr->l_starttime = 3600 * edflib_atof_nonlocalized(scratchpad); edfhdr->l_starttime += 60 * edflib_atof_nonlocalized(scratchpad + 3); edfhdr->l_starttime += edflib_atof_nonlocalized(scratchpad + 6); edfhdr->l_starttime *= EDFLIB_TIME_DIMENSION; /***************** NUMBER OF SIGNALS IN HEADER *******************************/ strncpy(scratchpad, edf_hdr + 252, 4); scratchpad[4] = 0; for(i=0; i<4; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } } if(edflib_is_integer_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } edfhdr->edfsignals = edflib_atof_nonlocalized(scratchpad); if(edfhdr->edfsignals<1) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } if(edfhdr->edfsignals>EDFLIB_MAXSIGNALS) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } /***************** NUMBER OF BYTES IN HEADER *******************************/ strncpy(scratchpad, edf_hdr + 184, 8); scratchpad[8] = 0; for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } } if(edflib_is_integer_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } n = edflib_atof_nonlocalized(scratchpad); if((edfhdr->edfsignals * 256 + 256)!=n) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } /********************* RESERVED FIELD *************************************/ edfhdr->edfplus = 0; edfhdr->discontinuous = 0; strncpy(scratchpad, edf_hdr + 192, 44); scratchpad[44] = 0; for(i=0; i<44; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } } if(edfhdr->edf) { if(!strncmp(scratchpad, "EDF+C", 5)) { edfhdr->edfplus = 1; } if(!strncmp(scratchpad, "EDF+D", 5)) { edfhdr->edfplus = 1; edfhdr->discontinuous = 1; } } if(edfhdr->bdf) { if(!strncmp(scratchpad, "BDF+C", 5)) { edfhdr->bdfplus = 1; } if(!strncmp(scratchpad, "BDF+D", 5)) { edfhdr->bdfplus = 1; edfhdr->discontinuous = 1; } } strncpy(edfhdr->reserved, edf_hdr + 192, 44); edfhdr->reserved[44] = 0; /********************* NUMBER OF DATARECORDS *************************************/ strncpy(scratchpad, edf_hdr + 236, 8); scratchpad[8] = 0; for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } } if(edflib_is_integer_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } edfhdr->datarecords = edflib_atof_nonlocalized(scratchpad); if(edfhdr->datarecords<1) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } /********************* DATARECORD DURATION *************************************/ strncpy(scratchpad, edf_hdr + 244, 8); scratchpad[8] = 0; for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } } if(edflib_is_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } edfhdr->data_record_duration = edflib_atof_nonlocalized(scratchpad); if(edfhdr->data_record_duration < -0.000001) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr); return(NULL); } edfhdr->long_data_record_duration = edflib_get_long_duration(scratchpad); free(edf_hdr); /********************* START WITH THE SIGNALS IN THE HEADER *********************/ edf_hdr = (char *)calloc(1, (edfhdr->edfsignals + 1) * 256); if(edf_hdr==NULL) { *edf_error = EDFLIB_MALLOC_ERROR; free(edfhdr); return(NULL); } rewind(inputfile); if(fread(edf_hdr, (edfhdr->edfsignals + 1) * 256, 1, inputfile)!=1) { *edf_error = EDFLIB_FILE_READ_ERROR; free(edf_hdr); free(edfhdr); return(NULL); } edfhdr->edfparam = (struct edfparamblock *)calloc(1, sizeof(struct edfparamblock) * edfhdr->edfsignals); if(edfhdr->edfparam==NULL) { *edf_error = EDFLIB_MALLOC_ERROR; free(edf_hdr); free(edfhdr); return(NULL); } /**************************** LABELS *************************************/ edfhdr->nr_annot_chns = 0; for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (i * 16), 16); for(j=0; j<16; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } if(edfhdr->edfplus) { if(!strncmp(scratchpad, "EDF Annotations ", 16)) { edfhdr->annot_ch[edfhdr->nr_annot_chns] = i; edfhdr->nr_annot_chns++; edfhdr->edfparam[i].annotation = 1; } } if(edfhdr->bdfplus) { if(!strncmp(scratchpad, "BDF Annotations ", 16)) { edfhdr->annot_ch[edfhdr->nr_annot_chns] = i; edfhdr->nr_annot_chns++; edfhdr->edfparam[i].annotation = 1; } } strncpy(edfhdr->edfparam[i].label, edf_hdr + 256 + (i * 16), 16); edfhdr->edfparam[i].label[16] = 0; } if(edfhdr->edfplus&&(!edfhdr->nr_annot_chns)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } if(edfhdr->bdfplus&&(!edfhdr->nr_annot_chns)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } if((edfhdr->edfsignals!=edfhdr->nr_annot_chns)||((!edfhdr->edfplus)&&(!edfhdr->bdfplus))) { if(edfhdr->data_record_duration<0.0000001) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } /**************************** TRANSDUCER TYPES *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 16) + (i * 80), 80); for(j=0; j<80; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } strncpy(edfhdr->edfparam[i].transducer, edf_hdr + 256 + (edfhdr->edfsignals * 16) + (i * 80), 80); edfhdr->edfparam[i].transducer[80] = 0; if((edfhdr->edfplus) || (edfhdr->bdfplus)) { if(edfhdr->edfparam[i].annotation) { for(j=0; j<80; j++) { if(edfhdr->edfparam[i].transducer[j]!=' ') { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } } } } /**************************** PHYSICAL DIMENSIONS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 96) + (i * 8), 8); for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } strncpy(edfhdr->edfparam[i].physdimension, edf_hdr + 256 + (edfhdr->edfsignals * 96) + (i * 8), 8); edfhdr->edfparam[i].physdimension[8] = 0; } /**************************** PHYSICAL MINIMUMS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 104) + (i * 8), 8); scratchpad[8] = 0; for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } if(edflib_is_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } edfhdr->edfparam[i].phys_min = edflib_atof_nonlocalized(scratchpad); } /**************************** PHYSICAL MAXIMUMS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 112) + (i * 8), 8); scratchpad[8] = 0; for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } if(edflib_is_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } edfhdr->edfparam[i].phys_max = edflib_atof_nonlocalized(scratchpad); if(edfhdr->edfparam[i].phys_max==edfhdr->edfparam[i].phys_min) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } /**************************** DIGITAL MINIMUMS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 120) + (i * 8), 8); scratchpad[8] = 0; for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } if(edflib_is_integer_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } n = edflib_atof_nonlocalized(scratchpad); if(edfhdr->edfplus) { if(edfhdr->edfparam[i].annotation) { if(n!=-32768) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } } if(edfhdr->bdfplus) { if(edfhdr->edfparam[i].annotation) { if(n!=-8388608) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } } if(edfhdr->edf) { if((n>32767)||(n<-32768)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } if(edfhdr->bdf) { if((n>8388607)||(n<-8388608)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } edfhdr->edfparam[i].dig_min = n; } /**************************** DIGITAL MAXIMUMS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 128) + (i * 8), 8); scratchpad[8] = 0; for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } if(edflib_is_integer_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } n = edflib_atof_nonlocalized(scratchpad); if(edfhdr->edfplus) { if(edfhdr->edfparam[i].annotation) { if(n!=32767) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } } if(edfhdr->bdfplus) { if(edfhdr->edfparam[i].annotation) { if(n!=8388607) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } } if(edfhdr->edf) { if((n>32767)||(n<-32768)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } else { if((n>8388607)||(n<-8388608)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } edfhdr->edfparam[i].dig_max = n; if(edfhdr->edfparam[i].dig_max<(edfhdr->edfparam[i].dig_min + 1)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } /**************************** PREFILTER FIELDS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 136) + (i * 80), 80); for(j=0; j<80; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } strncpy(edfhdr->edfparam[i].prefilter, edf_hdr + 256 + (edfhdr->edfsignals * 136) + (i * 80), 80); edfhdr->edfparam[i].prefilter[80] = 0; if((edfhdr->edfplus) || (edfhdr->bdfplus)) { if(edfhdr->edfparam[i].annotation) { for(j=0; j<80; j++) { if(edfhdr->edfparam[i].prefilter[j]!=' ') { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } } } } /*********************** NR OF SAMPLES IN EACH DATARECORD ********************/ edfhdr->recordsize = 0; for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 216) + (i * 8), 8); scratchpad[8] = 0; for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } if(edflib_is_integer_number(scratchpad)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } n = edflib_atof_nonlocalized(scratchpad); if(n<1) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } edfhdr->edfparam[i].smp_per_record = n; edfhdr->recordsize += n; } if(edfhdr->bdf) { edfhdr->recordsize *= 3; if(edfhdr->recordsize > 15728640) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } else { edfhdr->recordsize *= 2; if(edfhdr->recordsize > 10485760) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } /**************************** RESERVED FIELDS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 224) + (i * 32), 32); for(j=0; j<32; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } strncpy(edfhdr->edfparam[i].reserved, edf_hdr + 256 + (edfhdr->edfsignals * 224) + (i * 32), 32); edfhdr->edfparam[i].reserved[32] = 0; } /********************* EDF+ PATIENTNAME *********************************************/ if(edfhdr->edfplus || edfhdr->bdfplus) { error = 0; dotposition = 0; strncpy(scratchpad, edf_hdr + 8, 80); scratchpad[80] = 0; for(i=0; i<80; i++) { if(scratchpad[i]==' ') { dotposition = i; break; } } dotposition++; if((dotposition>73)||(dotposition<2)) error = 1; if(scratchpad[dotposition + 2]!='X') { if(dotposition>65) error = 1; } if((scratchpad[dotposition]!='M')&&(scratchpad[dotposition]!='F')&&(scratchpad[dotposition]!='X')) error = 1; dotposition++; if(scratchpad[dotposition]!=' ') error = 1; if(scratchpad[dotposition + 1]=='X') { if(scratchpad[dotposition + 2]!=' ') error = 1; if(scratchpad[dotposition + 3]==' ') error = 1; } else { if(scratchpad[dotposition + 12]!=' ') error = 1; if(scratchpad[dotposition + 13]==' ') error = 1; dotposition++; strncpy(scratchpad2, scratchpad + dotposition, 11); scratchpad2[11] = 0; if((scratchpad2[2]!='-')||(scratchpad2[6]!='-')) error = 1; scratchpad2[2] = 0; scratchpad2[6] = 0; if((scratchpad2[0]<48)||(scratchpad2[0]>57)) error = 1; if((scratchpad2[1]<48)||(scratchpad2[1]>57)) error = 1; if((scratchpad2[7]<48)||(scratchpad2[7]>57)) error = 1; if((scratchpad2[8]<48)||(scratchpad2[8]>57)) error = 1; if((scratchpad2[9]<48)||(scratchpad2[9]>57)) error = 1; if((scratchpad2[10]<48)||(scratchpad2[10]>57)) error = 1; if((edflib_atof_nonlocalized(scratchpad2)<1)||(edflib_atof_nonlocalized(scratchpad2)>31)) error = 1; if(strcmp(scratchpad2 + 3, "JAN")) if(strcmp(scratchpad2 + 3, "FEB")) if(strcmp(scratchpad2 + 3, "MAR")) if(strcmp(scratchpad2 + 3, "APR")) if(strcmp(scratchpad2 + 3, "MAY")) if(strcmp(scratchpad2 + 3, "JUN")) if(strcmp(scratchpad2 + 3, "JUL")) if(strcmp(scratchpad2 + 3, "AUG")) if(strcmp(scratchpad2 + 3, "SEP")) if(strcmp(scratchpad2 + 3, "OCT")) if(strcmp(scratchpad2 + 3, "NOV")) if(strcmp(scratchpad2 + 3, "DEC")) error = 1; } if(error) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } p = 0; if(edfhdr->patient[p]=='X') { edfhdr->plus_patientcode[0] = 0; p += 2; } else { for(i=0; i<(80-p); i++) { if(edfhdr->patient[i+p]==' ') { break; } edfhdr->plus_patientcode[i] = edfhdr->patient[i+p]; if(edfhdr->plus_patientcode[i]=='_') edfhdr->plus_patientcode[i] = ' '; } edfhdr->plus_patientcode[i] = 0; p += i + 1; } if(edfhdr->patient[p]=='M') { strcpy(edfhdr->plus_gender, "Male"); } if(edfhdr->patient[p]=='F') { strcpy(edfhdr->plus_gender, "Female"); } if(edfhdr->patient[p]=='X') { edfhdr->plus_gender[0] = 0; } for(i=0; i<(80-p);i++) { if(edfhdr->patient[i+p]==' ') { break; } } p += i + 1; if(edfhdr->patient[p]=='X') { edfhdr->plus_birthdate[0] = 0; p += 2; } else { for(i=0; i<(80-p); i++) { if(edfhdr->patient[i+p]==' ') { break; } edfhdr->plus_birthdate[i] = edfhdr->patient[i+p]; } edfhdr->plus_birthdate[2] = ' '; edfhdr->plus_birthdate[3] += 32; edfhdr->plus_birthdate[4] += 32; edfhdr->plus_birthdate[5] += 32; edfhdr->plus_birthdate[6] = ' '; edfhdr->plus_birthdate[11] = 0; p += i + 1; } for(i=0; i<(80-p);i++) { if(edfhdr->patient[i+p]==' ') { break; } edfhdr->plus_patient_name[i] = edfhdr->patient[i+p]; if(edfhdr->plus_patient_name[i]=='_') edfhdr->plus_patient_name[i] = ' '; } edfhdr->plus_patient_name[i] = 0; p += i + 1; for(i=0; i<(80-p);i++) { edfhdr->plus_patient_additional[i] = edfhdr->patient[i+p]; } edfhdr->plus_patient_additional[i] = 0; p += i + 1; } /********************* EDF+ RECORDINGFIELD *********************************************/ if(edfhdr->edfplus || edfhdr->bdfplus) { error = 0; strncpy(scratchpad, edf_hdr + 88, 80); scratchpad[80] = 0; if(strncmp(scratchpad, "Startdate ", 10)) error = 1; if(scratchpad[10]=='X') { if(scratchpad[11]!=' ') error = 1; if(scratchpad[12]==' ') error = 1; p = 12; } else { if(scratchpad[21]!=' ') error = 1; if(scratchpad[22]==' ') error = 1; p = 22; strncpy(scratchpad2, scratchpad + 10, 11); scratchpad2[11] = 0; if((scratchpad2[2]!='-')||(scratchpad2[6]!='-')) error = 1; scratchpad2[2] = 0; scratchpad2[6] = 0; if((scratchpad2[0]<48)||(scratchpad2[0]>57)) error = 1; if((scratchpad2[1]<48)||(scratchpad2[1]>57)) error = 1; if((scratchpad2[7]<48)||(scratchpad2[7]>57)) error = 1; if((scratchpad2[8]<48)||(scratchpad2[8]>57)) error = 1; if((scratchpad2[9]<48)||(scratchpad2[9]>57)) error = 1; if((scratchpad2[10]<48)||(scratchpad2[10]>57)) error = 1; if((edflib_atof_nonlocalized(scratchpad2)<1)||(edflib_atof_nonlocalized(scratchpad2)>31)) error = 1; r = 0; if(!strcmp(scratchpad2 + 3, "JAN")) r = 1; else if(!strcmp(scratchpad2 + 3, "FEB")) r = 2; else if(!strcmp(scratchpad2 + 3, "MAR")) r = 3; else if(!strcmp(scratchpad2 + 3, "APR")) r = 4; else if(!strcmp(scratchpad2 + 3, "MAY")) r = 5; else if(!strcmp(scratchpad2 + 3, "JUN")) r = 6; else if(!strcmp(scratchpad2 + 3, "JUL")) r = 7; else if(!strcmp(scratchpad2 + 3, "AUG")) r = 8; else if(!strcmp(scratchpad2 + 3, "SEP")) r = 9; else if(!strcmp(scratchpad2 + 3, "OCT")) r = 10; else if(!strcmp(scratchpad2 + 3, "NOV")) r = 11; else if(!strcmp(scratchpad2 + 3, "DEC")) r = 12; else error = 1; } n = 0; for(i=p; i<80; i++) { if(i>78) { error = 1; break; } if(scratchpad[i]==' ') { n++; if(scratchpad[i + 1]==' ') { error = 1; break; } } if(n>1) break; } if(error) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } if(edf_hdr[98]!='X') { error = 0; strncpy(scratchpad, edf_hdr + 168, 8); scratchpad[2] = 0; scratchpad[5] = 0; scratchpad[8] = 0; if(edflib_atof_nonlocalized(scratchpad)!=edflib_atof_nonlocalized(scratchpad2)) error = 1; if(edflib_atof_nonlocalized(scratchpad+3)!=r) error = 1; if(edflib_atof_nonlocalized(scratchpad+6)!=edflib_atof_nonlocalized(scratchpad2+9)) error = 1; if(error) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } edfhdr->startdate_year = edflib_atof_nonlocalized(scratchpad2 + 7); if(edfhdr->startdate_year<1970) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } p = 10; for(i=0; i<(80-p); i++) { if(edfhdr->recording[i+p]==' ') { break; } edfhdr->plus_startdate[i] = edfhdr->recording[i+p]; } edfhdr->plus_startdate[2] = ' '; edfhdr->plus_startdate[3] += 32; edfhdr->plus_startdate[4] += 32; edfhdr->plus_startdate[5] += 32; edfhdr->plus_startdate[6] = ' '; edfhdr->plus_startdate[11] = 0; p += i + 1; if(edfhdr->recording[p]=='X') { edfhdr->plus_admincode[0] = 0; p += 2; } else { for(i=0; i<(80-p); i++) { if(edfhdr->recording[i+p]==' ') { break; } edfhdr->plus_admincode[i] = edfhdr->recording[i+p]; if(edfhdr->plus_admincode[i]=='_') edfhdr->plus_admincode[i] = ' '; } edfhdr->plus_admincode[i] = 0; p += i + 1; } if(edfhdr->recording[p]=='X') { edfhdr->plus_technician[0] = 0; p += 2; } else { for(i=0; i<(80-p); i++) { if(edfhdr->recording[i+p]==' ') { break; } edfhdr->plus_technician[i] = edfhdr->recording[i+p]; if(edfhdr->plus_technician[i]=='_') edfhdr->plus_technician[i] = ' '; } edfhdr->plus_technician[i] = 0; p += i + 1; } if(edfhdr->recording[p]=='X') { edfhdr->plus_equipment[0] = 0; p += 2; } else { for(i=0; i<(80-p); i++) { if(edfhdr->recording[i+p]==' ') { break; } edfhdr->plus_equipment[i] = edfhdr->recording[i+p]; if(edfhdr->plus_equipment[i]=='_') edfhdr->plus_equipment[i] = ' '; } edfhdr->plus_equipment[i] = 0; p += i + 1; } for(i=0; i<(80-p);i++) { edfhdr->plus_recording_additional[i] = edfhdr->recording[i+p]; } edfhdr->plus_recording_additional[i] = 0; p += i + 1; } /********************* FILESIZE *********************************************/ edfhdr->hdrsize = edfhdr->edfsignals * 256 + 256; fseeko(inputfile, 0LL, SEEK_END); if(ftello(inputfile)!=(edfhdr->recordsize * edfhdr->datarecords + edfhdr->hdrsize)) { *edf_error = EDFLIB_FILE_CONTAINS_FORMAT_ERRORS; free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } n = 0; for(i=0; iedfsignals; i++) { edfhdr->edfparam[i].buf_offset = n; if(edfhdr->bdf) n += edfhdr->edfparam[i].smp_per_record * 3; else n += edfhdr->edfparam[i].smp_per_record * 2; edfhdr->edfparam[i].bitvalue = (edfhdr->edfparam[i].phys_max - edfhdr->edfparam[i].phys_min) / (edfhdr->edfparam[i].dig_max - edfhdr->edfparam[i].dig_min); edfhdr->edfparam[i].offset = edfhdr->edfparam[i].phys_max / edfhdr->edfparam[i].bitvalue - edfhdr->edfparam[i].dig_max; } edfhdr->file_hdl = inputfile; free(edf_hdr); return(edfhdr); } static int edflib_is_integer_number(char *str) { int i=0, l, hasspace = 0, hassign=0, digit=0; l = strlen(str); if(!l) return(1); if((str[0]=='+')||(str[0]=='-')) { hassign++; i++; } for(; i57)) { return(1); } else { if(hasspace) { return(1); } digit++; } } } if(digit) return(0); else return(1); } static int edflib_is_number(char *str) { int i=0, l, hasspace = 0, hassign=0, digit=0, hasdot=0, hasexp=0; l = strlen(str); if(!l) return(1); if((str[0]=='+')||(str[0]=='-')) { hassign++; i++; } for(; i57))&&str[i]!='.') { return(1); } else { if(hasspace) { return(1); } if(str[i]=='.') { if(hasdot) return(1); hasdot++; } else { digit++; } } } } if(hasexp) { if(++i==l) { return(1); } if((str[i]=='+')||(str[i]=='-')) { hassign++; i++; } for(; i57)) { return(1); } else { if(hasspace) { return(1); } digit++; } } } } if(digit) return(0); else return(1); } static long long edflib_get_long_duration(char *str) { int i, len=8, hasdot=0, dotposition=0; long long value=0, radix; for(i=0; i<8; i++) { if(str[i]==' ') { len = i; break; } } for(i=0; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } radix = EDFLIB_TIME_DIMENSION / 10; for(i=dotposition+1; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } } return(value); } int edflib_version(void) { return(EDFLIB_VERSION); } static int edflib_get_annotations(struct edfhdrblock *edfhdr, int hdl, int read_annotations) { int i, j, k, p, r=0, n, edfsignals, datarecords, recordsize, discontinuous, *annot_ch, nr_annot_chns, max, onset, duration, duration_start, zero, max_tal_ln, error, annots_in_record, annots_in_tal, samplesize=2; char *scratchpad, *cnv_buf, *time_in_txt, *duration_in_txt; long long data_record_duration, elapsedtime, time_tmp=0; FILE *inputfile; struct edfparamblock *edfparam; struct edf_annotationblock *new_annotation=NULL, *malloc_list; inputfile = edfhdr->file_hdl; edfsignals = edfhdr->edfsignals; recordsize = edfhdr->recordsize; edfparam = edfhdr->edfparam; nr_annot_chns = edfhdr->nr_annot_chns; datarecords = edfhdr->datarecords; data_record_duration = edfhdr->long_data_record_duration; discontinuous = edfhdr->discontinuous; annot_ch = edfhdr->annot_ch; if(edfhdr->edfplus) { samplesize = 2; } if(edfhdr->bdfplus) { samplesize = 3; } cnv_buf = (char *)calloc(1, recordsize); if(cnv_buf==NULL) { return(1); } max_tal_ln = 0; for(i=0; i=EDFLIB_TIME_DIMENSION) { error = 2; goto END; } else { edfhdr->starttime_offset = time_tmp; } } elapsedtime = time_tmp; error = 0; break; } } } } for(k=0; k1) { error = 34; goto END; } zero = 0; if((scratchpad[n]==20)||(scratchpad[n]==21)) { if(scratchpad[n]==21) { if(duration||duration_start||onset||annots_in_tal) { /* it's not allowed to have multiple duration fields */ error = 35; /* in one TAL or to have a duration field which is */ goto END; /* not immediately behind the onsetfield */ } duration_start = 1; } if((scratchpad[n]==20)&&onset&&(!duration_start)) { if(r||annots_in_record) { if(n >= 0) { if(edfhdr->annots_in_file >= edfhdr->annotlist_sz) { malloc_list = (struct edf_annotationblock *)realloc(annotationslist[hdl], sizeof(struct edf_annotationblock) * (edfhdr->annotlist_sz + EDFLIB_ANNOT_MEMBLOCKSZ)); if(malloc_list==NULL) { free(cnv_buf); free(scratchpad); free(time_in_txt); free(duration_in_txt); return(-1); } annotationslist[hdl] = malloc_list; edfhdr->annotlist_sz += EDFLIB_ANNOT_MEMBLOCKSZ; } new_annotation = annotationslist[hdl] + edfhdr->annots_in_file; new_annotation->annotation[0] = 0; if(duration) strcpy(new_annotation->duration, duration_in_txt); else new_annotation->duration[0] = 0; for(j=0; jannotation[j] = scratchpad[j]; } new_annotation->annotation[j] = 0; new_annotation->onset = edflib_get_long_time(time_in_txt); edfhdr->annots_in_file++; if(read_annotations==EDFLIB_READ_ANNOTATIONS) { if(!(strncmp(new_annotation->annotation, "Recording ends", 14))) { if(nr_annot_chns==1) { goto END; } } } } } annots_in_tal++; annots_in_record++; n = 0; continue; } if(!onset) { scratchpad[n] = 0; if(edflib_is_onset_number(scratchpad)) { error = 36; goto END; } onset = 1; n = 0; strcpy(time_in_txt, scratchpad); continue; } if(duration_start) { scratchpad[n] = 0; if(edflib_is_duration_number(scratchpad)) { error = 37; goto END; } for(j=0; j126)) { duration_in_txt[j] = '.'; } } duration_in_txt[j] = 0; duration = 1; duration_start = 0; n = 0; continue; } } n++; } END: /****************** end ************************/ if(error) { free(cnv_buf); free(scratchpad); free(time_in_txt); free(duration_in_txt); return(9); } } } free(cnv_buf); free(scratchpad); free(time_in_txt); free(duration_in_txt); return(0); } static int edflib_is_duration_number(char *str) { int i, l, hasdot = 0; l = strlen(str); if(!l) return(1); if((str[0] == '.')||(str[l-1] == '.')) return(1); for(i=0; i57)) return(1); } } return(0); } static int edflib_is_onset_number(char *str) { int i, l, hasdot = 0; l = strlen(str); if(l<2) return(1); if((str[0]!='+')&&(str[0]!='-')) return(1); if((str[1] == '.')||(str[l-1] == '.')) return(1); for(i=1; i57)) return(1); } } return(0); } static long long edflib_get_long_time(char *str) { int i, len, hasdot=0, dotposition=0; long long value=0, radix; str = str + 1; len = strlen(str); for(i=0; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } radix = EDFLIB_TIME_DIMENSION / 10; for(i=dotposition+1; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } } if(str[-1]=='-') value = -value; return(value); } static void edflib_latin1_to_ascii(char *str, int len) { int i, value; for(i=0; i31)&&(value<127)) { continue; } switch(value) { case 128 : str[i] = 'E'; break; case 130 : str[i] = ','; break; case 131 : str[i] = 'F'; break; case 132 : str[i] = '\"'; break; case 133 : str[i] = '.'; break; case 134 : str[i] = '+'; break; case 135 : str[i] = '+'; break; case 136 : str[i] = '^'; break; case 137 : str[i] = 'm'; break; case 138 : str[i] = 'S'; break; case 139 : str[i] = '<'; break; case 140 : str[i] = 'E'; break; case 142 : str[i] = 'Z'; break; case 145 : str[i] = '`'; break; case 146 : str[i] = '\''; break; case 147 : str[i] = '\"'; break; case 148 : str[i] = '\"'; break; case 149 : str[i] = '.'; break; case 150 : str[i] = '-'; break; case 151 : str[i] = '-'; break; case 152 : str[i] = '~'; break; case 154 : str[i] = 's'; break; case 155 : str[i] = '>'; break; case 156 : str[i] = 'e'; break; case 158 : str[i] = 'z'; break; case 159 : str[i] = 'Y'; break; case 171 : str[i] = '<'; break; case 180 : str[i] = '\''; break; case 181 : str[i] = 'u'; break; case 187 : str[i] = '>'; break; case 191 : str[i] = '\?'; break; case 192 : str[i] = 'A'; break; case 193 : str[i] = 'A'; break; case 194 : str[i] = 'A'; break; case 195 : str[i] = 'A'; break; case 196 : str[i] = 'A'; break; case 197 : str[i] = 'A'; break; case 198 : str[i] = 'E'; break; case 199 : str[i] = 'C'; break; case 200 : str[i] = 'E'; break; case 201 : str[i] = 'E'; break; case 202 : str[i] = 'E'; break; case 203 : str[i] = 'E'; break; case 204 : str[i] = 'I'; break; case 205 : str[i] = 'I'; break; case 206 : str[i] = 'I'; break; case 207 : str[i] = 'I'; break; case 208 : str[i] = 'D'; break; case 209 : str[i] = 'N'; break; case 210 : str[i] = 'O'; break; case 211 : str[i] = 'O'; break; case 212 : str[i] = 'O'; break; case 213 : str[i] = 'O'; break; case 214 : str[i] = 'O'; break; case 215 : str[i] = 'x'; break; case 216 : str[i] = 'O'; break; case 217 : str[i] = 'U'; break; case 218 : str[i] = 'U'; break; case 219 : str[i] = 'U'; break; case 220 : str[i] = 'U'; break; case 221 : str[i] = 'Y'; break; case 222 : str[i] = 'I'; break; case 223 : str[i] = 's'; break; case 224 : str[i] = 'a'; break; case 225 : str[i] = 'a'; break; case 226 : str[i] = 'a'; break; case 227 : str[i] = 'a'; break; case 228 : str[i] = 'a'; break; case 229 : str[i] = 'a'; break; case 230 : str[i] = 'e'; break; case 231 : str[i] = 'c'; break; case 232 : str[i] = 'e'; break; case 233 : str[i] = 'e'; break; case 234 : str[i] = 'e'; break; case 235 : str[i] = 'e'; break; case 236 : str[i] = 'i'; break; case 237 : str[i] = 'i'; break; case 238 : str[i] = 'i'; break; case 239 : str[i] = 'i'; break; case 240 : str[i] = 'd'; break; case 241 : str[i] = 'n'; break; case 242 : str[i] = 'o'; break; case 243 : str[i] = 'o'; break; case 244 : str[i] = 'o'; break; case 245 : str[i] = 'o'; break; case 246 : str[i] = 'o'; break; case 247 : str[i] = '-'; break; case 248 : str[i] = '0'; break; case 249 : str[i] = 'u'; break; case 250 : str[i] = 'u'; break; case 251 : str[i] = 'u'; break; case 252 : str[i] = 'u'; break; case 253 : str[i] = 'y'; break; case 254 : str[i] = 't'; break; case 255 : str[i] = 'y'; break; default : str[i] = ' '; break; } } } static void edflib_latin12utf8(char *latin1_str, int len) { int i, j; unsigned char *str, tmp_str[512]; str = (unsigned char *)latin1_str; j = 0; for(i=0; i126)&&(str[i]<160)) tmp_str[j] = '.'; if(str[i]>159) { if((len-j)<2) { tmp_str[j] = ' '; } else { tmp_str[j] = 192 + (str[i]>>6); j++; tmp_str[j] = 128 + (str[i]&63); } } j++; if(j>=len) break; } for(i=0; i=EDFLIB_MAXFILES) { return(EDFLIB_MAXFILES_REACHED); } for(i=0; ipath))) { return(EDFLIB_FILE_ALREADY_OPENED); } } } if(number_of_signals<0) { return(EDFLIB_NUMBER_OF_SIGNALS_INVALID); } if(number_of_signals>EDFLIB_MAXSIGNALS) { return(EDFLIB_NUMBER_OF_SIGNALS_INVALID); } hdr = (struct edfhdrblock *)calloc(1, sizeof(struct edfhdrblock)); if(hdr==NULL) { return(EDFLIB_MALLOC_ERROR); } hdr->edfparam = (struct edfparamblock *)calloc(1, sizeof(struct edfparamblock) * number_of_signals); if(hdr->edfparam==NULL) { free(hdr); return(EDFLIB_MALLOC_ERROR); } hdr->writemode = 1; hdr->edfsignals = number_of_signals; handle = -1; for(i=0; iedfparam); free(hdr); return(EDFLIB_MAXFILES_REACHED); } write_annotationslist[handle] = NULL; hdr->annotlist_sz = 0; hdr->annots_in_file = 0; file = fopeno(path, "wb"); if(file==NULL) { free(hdr->edfparam); free(hdr); return(EDFLIB_NO_SUCH_FILE_OR_DIRECTORY); } hdr->file_hdl = file; strcpy(hdr->path, path); edf_files_open++; if(filetype==EDFLIB_FILETYPE_EDFPLUS) { hdr->edf = 1; hdr->edfplus = 1; } if(filetype==EDFLIB_FILETYPE_BDFPLUS) { hdr->bdf = 1; hdr->bdfplus = 1; } hdr->long_data_record_duration = EDFLIB_TIME_DIMENSION; hdr->data_record_duration = 1.0; hdr->nr_annot_chns = 1; return(handle); } int edf_set_samplefrequency(int handle, int edfsignal, int samplefrequency) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(edfsignal<0) { return(-1); } if(edfsignal>=hdrlist[handle]->edfsignals) { return(-1); } if(samplefrequency<1) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } hdrlist[handle]->edfparam[edfsignal].smp_per_record = samplefrequency; return(0); } int edf_set_number_of_annotation_signals(int handle, int annot_signals) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } if((annot_signals < 1) || (annot_signals > 64)) { return(-1); } hdrlist[handle]->nr_annot_chns = annot_signals; return(0); } int edf_set_datarecord_duration(int handle, int duration) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } if((duration < 100) || (duration > 6000000)) { return(-1); } hdrlist[handle]->long_data_record_duration = (long long)duration * 100LL; if(hdrlist[handle]->long_data_record_duration < (EDFLIB_TIME_DIMENSION * 10LL)) { hdrlist[handle]->long_data_record_duration /= 10LL; hdrlist[handle]->long_data_record_duration *= 10LL; } else { hdrlist[handle]->long_data_record_duration /= 100LL; hdrlist[handle]->long_data_record_duration *= 100LL; } hdrlist[handle]->data_record_duration = ((double)(hdrlist[handle]->long_data_record_duration)) / EDFLIB_TIME_DIMENSION; return(0); } int edfwrite_digital_short_samples(int handle, short *buf) { int i, p, error, sf, digmax, digmin, edfsignal, value; FILE *file; struct edfhdrblock *hdr; if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->edfsignals == 0) { return(-1); } if(hdrlist[handle]->bdf == 1) { return(-1); } hdr = hdrlist[handle]; file = hdr->file_hdl; edfsignal = hdr->signal_write_sequence_pos; if(!hdr->datarecords) { if(!edfsignal) { error = edflib_write_edf_header(hdr); if(error) { return(error); } } } sf = hdr->edfparam[edfsignal].smp_per_record; digmax = hdr->edfparam[edfsignal].dig_max; digmin = hdr->edfparam[edfsignal].dig_min; for(i=0; idigmax) { value = digmax; } if(value>8)&0xff, file)==EOF) { return(-1); } if(hdr->bdf) { fputc((value>>16)&0xff, file); } } hdr->signal_write_sequence_pos++; if(hdr->signal_write_sequence_pos == hdr->edfsignals) { hdr->signal_write_sequence_pos = 0; p = edflib_fprint_ll_number_nonlocalized(file, (hdr->datarecords * hdr->long_data_record_duration) / EDFLIB_TIME_DIMENSION, 0, 1); if(hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) { fputc('.', file); p++; p += edflib_fprint_ll_number_nonlocalized(file, (hdr->datarecords * hdr->long_data_record_duration) % EDFLIB_TIME_DIMENSION, 7, 0); } fputc(20, file); fputc(20, file); p += 2; for(; ptotal_annot_bytes; p++) { fputc(0, file); } hdr->datarecords++; fflush(file); } return(0); } int edfwrite_digital_samples(int handle, int *buf) { int i, p, error, sf, digmax, digmin, edfsignal, value; FILE *file; struct edfhdrblock *hdr; if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->edfsignals == 0) { return(-1); } hdr = hdrlist[handle]; file = hdr->file_hdl; edfsignal = hdr->signal_write_sequence_pos; if(!hdr->datarecords) { if(!edfsignal) { error = edflib_write_edf_header(hdr); if(error) { return(error); } } } sf = hdr->edfparam[edfsignal].smp_per_record; digmax = hdr->edfparam[edfsignal].dig_max; digmin = hdr->edfparam[edfsignal].dig_min; for(i=0; idigmax) { value = digmax; } if(value>8)&0xff, file)==EOF) { return(-1); } if(hdr->bdf) { fputc((value>>16)&0xff, file); } } hdr->signal_write_sequence_pos++; if(hdr->signal_write_sequence_pos == hdr->edfsignals) { hdr->signal_write_sequence_pos = 0; p = edflib_fprint_ll_number_nonlocalized(file, (hdr->datarecords * hdr->long_data_record_duration) / EDFLIB_TIME_DIMENSION, 0, 1); if(hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) { fputc('.', file); p++; p += edflib_fprint_ll_number_nonlocalized(file, (hdr->datarecords * hdr->long_data_record_duration) % EDFLIB_TIME_DIMENSION, 7, 0); } fputc(20, file); fputc(20, file); p += 2; for(; ptotal_annot_bytes; p++) { fputc(0, file); } hdr->datarecords++; fflush(file); } return(0); } int edf_blockwrite_digital_samples(int handle, int *buf) { int i, j, p, error, sf, digmax, digmin, edfsignals, buf_offset, value; FILE *file; struct edfhdrblock *hdr; if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->signal_write_sequence_pos) { return(-1); } if(hdrlist[handle]->edfsignals == 0) { return(-1); } hdr = hdrlist[handle]; file = hdr->file_hdl; edfsignals = hdr->edfsignals; if(!hdr->datarecords) { error = edflib_write_edf_header(hdr); if(error) { return(error); } } buf_offset = 0; for(j=0; jedfparam[j].smp_per_record; digmax = hdr->edfparam[j].dig_max; digmin = hdr->edfparam[j].dig_min; for(i=0; idigmax) { value = digmax; } if(value>8)&0xff, file)==EOF) { return(-1); } if(hdr->bdf) { fputc((value>>16)&0xff, file); } } buf_offset += sf; } p = edflib_fprint_ll_number_nonlocalized(file, (hdr->datarecords * hdr->long_data_record_duration) / EDFLIB_TIME_DIMENSION, 0, 1); if(hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) { fputc('.', file); p++; p += edflib_fprint_ll_number_nonlocalized(file, (hdr->datarecords * hdr->long_data_record_duration) % EDFLIB_TIME_DIMENSION, 7, 0); } fputc(20, file); fputc(20, file); p += 2; for(; ptotal_annot_bytes; p++) { fputc(0, file); } hdr->datarecords++; fflush(file); return(0); } int edf_blockwrite_digital_short_samples(int handle, short *buf) { int i, j, p, error, sf, digmax, digmin, edfsignals, buf_offset, value; FILE *file; struct edfhdrblock *hdr; if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->signal_write_sequence_pos) { return(-1); } if(hdrlist[handle]->edfsignals == 0) { return(-1); } if(hdrlist[handle]->bdf == 1) { return(-1); } hdr = hdrlist[handle]; file = hdr->file_hdl; edfsignals = hdr->edfsignals; if(!hdr->datarecords) { error = edflib_write_edf_header(hdr); if(error) { return(error); } } buf_offset = 0; for(j=0; jedfparam[j].smp_per_record; digmax = hdr->edfparam[j].dig_max; digmin = hdr->edfparam[j].dig_min; for(i=0; idigmax) { value = digmax; } if(value>8)&0xff, file)==EOF) { return(-1); } if(hdr->bdf) { fputc((value>>16)&0xff, file); } } buf_offset += sf; } p = edflib_fprint_ll_number_nonlocalized(file, (hdr->datarecords * hdr->long_data_record_duration) / EDFLIB_TIME_DIMENSION, 0, 1); if(hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) { fputc('.', file); p++; p += edflib_fprint_ll_number_nonlocalized(file, (hdr->datarecords * hdr->long_data_record_duration) % EDFLIB_TIME_DIMENSION, 7, 0); } fputc(20, file); fputc(20, file); p += 2; for(; ptotal_annot_bytes; p++) { fputc(0, file); } hdr->datarecords++; fflush(file); return(0); } int edf_blockwrite_digital_3byte_samples(int handle, void *buf) { int j, p, error, edfsignals, total_samples=0; FILE *file; struct edfhdrblock *hdr; if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->signal_write_sequence_pos) { return(-1); } if(hdrlist[handle]->edfsignals == 0) { return(-1); } if(hdrlist[handle]->bdf != 1) { return(-1); } hdr = hdrlist[handle]; file = hdr->file_hdl; edfsignals = hdr->edfsignals; if(!hdr->datarecords) { error = edflib_write_edf_header(hdr); if(error) { return(error); } } for(j=0; jedfparam[j].smp_per_record; } if(fwrite(buf, total_samples * 3, 1, file) != 1) { return(-1); } p = edflib_fprint_ll_number_nonlocalized(file, (hdr->datarecords * hdr->long_data_record_duration) / EDFLIB_TIME_DIMENSION, 0, 1); if(hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) { fputc('.', file); p++; p += edflib_fprint_ll_number_nonlocalized(file, (hdr->datarecords * hdr->long_data_record_duration) % EDFLIB_TIME_DIMENSION, 7, 0); } fputc(20, file); fputc(20, file); p += 2; for(; ptotal_annot_bytes; p++) { fputc(0, file); } hdr->datarecords++; fflush(file); return(0); } int edfwrite_physical_samples(int handle, double *buf) { int i, p, error, sf, digmax, digmin, value, edfsignal; double bitvalue, phys_offset; FILE *file; struct edfhdrblock *hdr; if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->edfsignals == 0) { return(-1); } hdr = hdrlist[handle]; file = hdr->file_hdl; edfsignal = hdr->signal_write_sequence_pos; if(!hdr->datarecords) { if(!edfsignal) { error = edflib_write_edf_header(hdr); if(error) { return(error); } } } sf = hdr->edfparam[edfsignal].smp_per_record; digmax = hdr->edfparam[edfsignal].dig_max; digmin = hdr->edfparam[edfsignal].dig_min; bitvalue = hdr->edfparam[edfsignal].bitvalue; phys_offset = hdr->edfparam[edfsignal].offset; for(i=0; idigmax) { value = digmax; } if(value>8)&0xff, file)==EOF) { return(-1); } if(hdr->bdf) { fputc((value>>16)&0xff, file); } } hdr->signal_write_sequence_pos++; if(hdr->signal_write_sequence_pos == hdr->edfsignals) { hdr->signal_write_sequence_pos = 0; p = edflib_fprint_ll_number_nonlocalized(file, (hdr->datarecords * hdr->long_data_record_duration) / EDFLIB_TIME_DIMENSION, 0, 1); if(hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) { fputc('.', file); p++; p += edflib_fprint_ll_number_nonlocalized(file, (hdr->datarecords * hdr->long_data_record_duration) % EDFLIB_TIME_DIMENSION, 7, 0); } fputc(20, file); fputc(20, file); p += 2; for(; ptotal_annot_bytes; p++) { fputc(0, file); } hdr->datarecords++; fflush(file); } return(0); } int edf_blockwrite_physical_samples(int handle, double *buf) { int i, j, p, error, sf, digmax, digmin, edfsignals, buf_offset, value; double bitvalue, phys_offset; FILE *file; struct edfhdrblock *hdr; if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->signal_write_sequence_pos) { return(-1); } if(hdrlist[handle]->edfsignals == 0) { return(-1); } hdr = hdrlist[handle]; file = hdr->file_hdl; edfsignals = hdr->edfsignals; if(!hdr->datarecords) { error = edflib_write_edf_header(hdr); if(error) { return(error); } } buf_offset = 0; for(j=0; jedfparam[j].smp_per_record; digmax = hdr->edfparam[j].dig_max; digmin = hdr->edfparam[j].dig_min; bitvalue = hdr->edfparam[j].bitvalue; phys_offset = hdr->edfparam[j].offset; for(i=0; idigmax) { value = digmax; } if(value>8)&0xff, file)==EOF) { return(-1); } if(hdr->bdf) { fputc((value>>16)&0xff, file); } } buf_offset += sf; } p = edflib_fprint_ll_number_nonlocalized(file, (hdr->datarecords * hdr->long_data_record_duration) / EDFLIB_TIME_DIMENSION, 0, 1); if(hdr->long_data_record_duration % EDFLIB_TIME_DIMENSION) { fputc('.', file); p++; p += edflib_fprint_ll_number_nonlocalized(file, (hdr->datarecords * hdr->long_data_record_duration) % EDFLIB_TIME_DIMENSION, 7, 0); } fputc(20, file); fputc(20, file); p += 2; for(; ptotal_annot_bytes; p++) { fputc(0, file); } hdr->datarecords++; fflush(file); return(0); } static int edflib_write_edf_header(struct edfhdrblock *hdr) { int i, j, p, q, len, rest, edfsignals; char str[128]; struct tm *date_time; time_t elapsed_time; FILE *file; file = hdr->file_hdl; edfsignals = hdr->edfsignals; if(edfsignals<0) { return(-20); } if(edfsignals>EDFLIB_MAXSIGNALS) { return(-21); } hdr->eq_sf = 1; for(i=0; iedfparam[i].smp_per_record<1) { return(-22); } if(hdr->edfparam[i].dig_max==hdr->edfparam[i].dig_min) { return(-23); } if(hdr->edfparam[i].dig_maxedfparam[i].dig_min) { return(-24); } if(hdr->edfparam[i].phys_max==hdr->edfparam[i].phys_min) { return(-25); } if(i > 0) { if(hdr->edfparam[i].smp_per_record != hdr->edfparam[i-1].smp_per_record) { hdr->eq_sf = 0; } } } for(i=0; iedfparam[i].bitvalue = (hdr->edfparam[i].phys_max - hdr->edfparam[i].phys_min) / (hdr->edfparam[i].dig_max - hdr->edfparam[i].dig_min); hdr->edfparam[i].offset = hdr->edfparam[i].phys_max / hdr->edfparam[i].bitvalue - hdr->edfparam[i].dig_max; } rewind(file); if(hdr->edf) { fprintf(file, "0 "); } else { fputc(255, file); fprintf(file, "BIOSEMI"); } p = 0; if(hdr->plus_birthdate[0]==0) { rest = 72; } else { rest = 62; } len = strlen(hdr->plus_patientcode); if(len && rest) { if(len>rest) { len = rest; rest = 0; } else { rest -= len; } strcpy(str, hdr->plus_patientcode); edflib_latin1_to_ascii(str, len); str[len] = 0; for(i=0; iplus_gender[0]=='M') { fputc('M', file); } else { if(hdr->plus_gender[0]=='F') { fputc('F', file); } else { fputc('X', file); } } fputc(' ', file); p +=2; if(hdr->plus_birthdate[0]==0) { fputc('X', file); fputc(' ', file); p +=2; } else { fputc(hdr->plus_birthdate[0], file); fputc(hdr->plus_birthdate[1], file); fputc('-', file); q = edflib_atof_nonlocalized(&(hdr->plus_birthdate[3])); switch(q) { case 1: fprintf(file, "JAN"); break; case 2: fprintf(file, "FEB"); break; case 3: fprintf(file, "MAR"); break; case 4: fprintf(file, "APR"); break; case 5: fprintf(file, "MAY"); break; case 6: fprintf(file, "JUN"); break; case 7: fprintf(file, "JUL"); break; case 8: fprintf(file, "AUG"); break; case 9: fprintf(file, "SEP"); break; case 10: fprintf(file, "OCT"); break; case 11: fprintf(file, "NOV"); break; case 12: fprintf(file, "DEC"); break; } fputc('-', file); fputc(hdr->plus_birthdate[6], file); fputc(hdr->plus_birthdate[7], file); fputc(hdr->plus_birthdate[8], file); fputc(hdr->plus_birthdate[9], file); fputc(' ', file); p += 12; } len = strlen(hdr->plus_patient_name); if(len && rest) { if(len>rest) { len = rest; rest = 0; } else { rest -= len; } strcpy(str, hdr->plus_patient_name); edflib_latin1_to_ascii(str, len); str[len] = 0; for(i=0; iplus_patient_additional); if(len && rest) { if(len>rest) { len = rest; } strcpy(str, hdr->plus_patient_additional); edflib_latin1_to_ascii(str, len); str[len] = 0; p += fprintf(file, "%s", str); } for(; p<80; p++) { fputc(' ', file); } if(!hdr->startdate_year) { elapsed_time = time(NULL); date_time = localtime(&elapsed_time); hdr->startdate_year = date_time->tm_year + 1900; hdr->startdate_month = date_time->tm_mon + 1; hdr->startdate_day = date_time->tm_mday; hdr->starttime_hour = date_time->tm_hour; hdr->starttime_minute = date_time->tm_min; hdr->starttime_second = date_time->tm_sec % 60; } p = 0; p += fprintf(file, "Startdate %02u-", hdr->startdate_day); switch(hdr->startdate_month) { case 1 : fprintf(file, "JAN"); break; case 2 : fprintf(file, "FEB"); break; case 3 : fprintf(file, "MAR"); break; case 4 : fprintf(file, "APR"); break; case 5 : fprintf(file, "MAY"); break; case 6 : fprintf(file, "JUN"); break; case 7 : fprintf(file, "JUL"); break; case 8 : fprintf(file, "AUG"); break; case 9 : fprintf(file, "SEP"); break; case 10 : fprintf(file, "OCT"); break; case 11 : fprintf(file, "NOV"); break; case 12 : fprintf(file, "DEC"); break; } p += 3; fputc('-', file); p++; p += edflib_fprint_int_number_nonlocalized(file, hdr->startdate_year, 4, 0); fputc(' ', file); p++; rest = 42; len = strlen(hdr->plus_admincode); if(len && rest) { if(len>rest) { len = rest; rest = 0; } else { rest -= len; } strcpy(str, hdr->plus_admincode); edflib_latin1_to_ascii(str, len); str[len] = 0; for(i=0; iplus_technician); if(len && rest) { if(len>rest) { len = rest; rest = 0; } else { rest -= len; } strcpy(str, hdr->plus_technician); edflib_latin1_to_ascii(str, len); str[len] = 0; for(i=0; iplus_equipment); if(len && rest) { if(len>rest) { len = rest; rest = 0; } else { rest -= len; } strcpy(str, hdr->plus_equipment); edflib_latin1_to_ascii(str, len); str[len] = 0; for(i=0; iplus_recording_additional); if(len && rest) { if(len>rest) { len = rest; } strcpy(str, hdr->plus_recording_additional); edflib_latin1_to_ascii(str, len); str[len] = 0; p += fprintf(file, "%s", str); } for(; p<80; p++) { fputc(' ', file); } fprintf(file, "%02u.%02u.%02u", hdr->startdate_day, hdr->startdate_month, (hdr->startdate_year % 100)); fprintf(file, "%02u.%02u.%02u", hdr->starttime_hour, hdr->starttime_minute, hdr->starttime_second); p = edflib_fprint_int_number_nonlocalized(file, (edfsignals + hdr->nr_annot_chns + 1) * 256, 0, 0); for(; p<8; p++) { fputc(' ', file); } if(hdr->edf) { fprintf(file, "EDF+C"); } else { fprintf(file, "BDF+C"); } for(i=0; i<39; i++) { fputc(' ', file); } fprintf(file, "-1 "); if(hdr->long_data_record_duration == EDFLIB_TIME_DIMENSION) { fprintf(file, "1 "); } else { edflib_sprint_number_nonlocalized(str, hdr->data_record_duration); strcat(str, " "); str[8] = 0; fprintf(file, "%s", str); } p = edflib_fprint_int_number_nonlocalized(file, edfsignals + hdr->nr_annot_chns, 0, 0); for(; p<4; p++) { fputc(' ', file); } for(i=0; iedfparam[i].label); edflib_latin1_to_ascii(hdr->edfparam[i].label, len); for(j=0; jedfparam[i].label[j], file); } for(; j<16; j++) { fputc(' ', file); } } for(j=0; jnr_annot_chns; j++) { if(hdr->edf) { fprintf(file, "EDF Annotations "); } else { fprintf(file, "BDF Annotations "); } } for(i=0; iedfparam[i].transducer); edflib_latin1_to_ascii(hdr->edfparam[i].transducer, len); for(j=0; jedfparam[i].transducer[j], file); } for(; j<80; j++) { fputc(' ', file); } } for(j=0; jnr_annot_chns; j++) { for(i=0; i<80; i++) { fputc(' ', file); } } for(i=0; iedfparam[i].physdimension); edflib_latin1_to_ascii(hdr->edfparam[i].physdimension, len); for(j=0; jedfparam[i].physdimension[j], file); } for(; j<8; j++) { fputc(' ', file); } } for(j=0; jnr_annot_chns; j++) { fprintf(file, " "); } for(i=0; iedfparam[i].phys_min); for(; p<8; p++) { str[p] = ' '; } str[8] = 0; fprintf(file, "%s", str); } for(j=0; jnr_annot_chns; j++) { fprintf(file, "-1 "); } for(i=0; iedfparam[i].phys_max); for(; p<8; p++) { str[p] = ' '; } str[8] = 0; fprintf(file, "%s", str); } for(j=0; jnr_annot_chns; j++) { fprintf(file, "1 "); } for(i=0; iedfparam[i].dig_min, 0, 0); for(; p<8; p++) { fputc(' ', file); } } for(j=0; jnr_annot_chns; j++) { if(hdr->edf) { fprintf(file, "-32768 "); } else { fprintf(file, "-8388608"); } } for(i=0; iedfparam[i].dig_max, 0, 0); for(; p<8; p++) { fputc(' ', file); } } for(j=0; jnr_annot_chns; j++) { if(hdr->edf) { fprintf(file, "32767 "); } else { fprintf(file, "8388607 "); } } for(i=0; iedfparam[i].prefilter); edflib_latin1_to_ascii(hdr->edfparam[i].prefilter, len); for(j=0; jedfparam[i].prefilter[j], file); } for(; j<80; j++) { fputc(' ', file); } } for(i=0; inr_annot_chns; i++) { for(j=0; j<80; j++) { fputc(' ', file); } } for(i=0; iedfparam[i].smp_per_record, 0, 0); for(; p<8; p++) { fputc(' ', file); } } for(j=0; jnr_annot_chns; j++) { if(hdr->edf) { p = edflib_fprint_int_number_nonlocalized(file, EDFLIB_ANNOTATION_BYTES / 2, 0, 0); for(; p<8; p++) { fputc(' ', file); } } else { p = edflib_fprint_int_number_nonlocalized(file, EDFLIB_ANNOTATION_BYTES / 3, 0, 0); for(; p<8; p++) { fputc(' ', file); } } } for(i=0; i<(edfsignals * 32); i++) { fputc(' ', file); } for(i=0; i<(hdr->nr_annot_chns * 32); i++) { fputc(' ', file); } hdr->total_annot_bytes = EDFLIB_ANNOTATION_BYTES * hdr->nr_annot_chns; return(0); } int edf_set_label(int handle, int edfsignal, const char *label) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(edfsignal<0) { return(-1); } if(edfsignal>=hdrlist[handle]->edfsignals) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } strncpy(hdrlist[handle]->edfparam[edfsignal].label, label, 16); hdrlist[handle]->edfparam[edfsignal].label[16] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->edfparam[edfsignal].label); return(0); } int edf_set_physical_dimension(int handle, int edfsignal, const char *phys_dim) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(edfsignal<0) { return(-1); } if(edfsignal>=hdrlist[handle]->edfsignals) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } strncpy(hdrlist[handle]->edfparam[edfsignal].physdimension, phys_dim, 8); hdrlist[handle]->edfparam[edfsignal].physdimension[8] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->edfparam[edfsignal].physdimension); return(0); } int edf_set_physical_maximum(int handle, int edfsignal, double phys_max) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(edfsignal<0) { return(-1); } if(edfsignal>=hdrlist[handle]->edfsignals) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } hdrlist[handle]->edfparam[edfsignal].phys_max = phys_max; return(0); } int edf_set_physical_minimum(int handle, int edfsignal, double phys_min) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(edfsignal<0) { return(-1); } if(edfsignal>=hdrlist[handle]->edfsignals) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } hdrlist[handle]->edfparam[edfsignal].phys_min = phys_min; return(0); } int edf_set_digital_maximum(int handle, int edfsignal, int dig_max) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(edfsignal<0) { return(-1); } if(edfsignal>=hdrlist[handle]->edfsignals) { return(-1); } if(hdrlist[handle]->edf) { if(dig_max > 32767) { return(-1); } } else { if(dig_max > 8388607) { return(-1); } } if(hdrlist[handle]->datarecords) { return(-1); } hdrlist[handle]->edfparam[edfsignal].dig_max = dig_max; return(0); } int edf_set_digital_minimum(int handle, int edfsignal, int dig_min) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(edfsignal<0) { return(-1); } if(edfsignal>=hdrlist[handle]->edfsignals) { return(-1); } if(hdrlist[handle]->edf) { if(dig_min < (-32768)) { return(-1); } } else { if(dig_min < (-8388608)) { return(-1); } } if(hdrlist[handle]->datarecords) { return(-1); } hdrlist[handle]->edfparam[edfsignal].dig_min = dig_min; return(0); } int edf_set_patientname(int handle, const char *patientname) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } strncpy(hdrlist[handle]->plus_patient_name, patientname, 80); hdrlist[handle]->plus_patient_name[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_patient_name); return(0); } int edf_set_patientcode(int handle, const char *patientcode) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } strncpy(hdrlist[handle]->plus_patientcode, patientcode, 80); hdrlist[handle]->plus_patientcode[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_patientcode); return(0); } int edf_set_gender(int handle, int gender) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } if((gender<0)||(gender>1)) { return(-1); } if(gender) { hdrlist[handle]->plus_gender[0] = 'M'; } else { hdrlist[handle]->plus_gender[0] = 'F'; } hdrlist[handle]->plus_gender[1] = 0; return(0); } int edf_set_birthdate(int handle, int birthdate_year, int birthdate_month, int birthdate_day) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } if((birthdate_year<1800) || (birthdate_year>3000) || (birthdate_month<1) || (birthdate_month>12) || (birthdate_day<1) || (birthdate_day>31)) { return(-1); } sprintf(hdrlist[handle]->plus_birthdate, "%02i.%02i.%02i%02i", birthdate_day, birthdate_month, birthdate_year / 100, birthdate_year % 100); hdrlist[handle]->plus_birthdate[10] = 0; return(0); } int edf_set_patient_additional(int handle, const char *patient_additional) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } strncpy(hdrlist[handle]->plus_patient_additional, patient_additional, 80); hdrlist[handle]->plus_patient_additional[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_patient_additional); return(0); } int edf_set_admincode(int handle, const char *admincode) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } strncpy(hdrlist[handle]->plus_admincode, admincode, 80); hdrlist[handle]->plus_admincode[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_admincode); return(0); } int edf_set_technician(int handle, const char *technician) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } strncpy(hdrlist[handle]->plus_technician, technician, 80); hdrlist[handle]->plus_technician[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_technician); return(0); } int edf_set_equipment(int handle, const char *equipment) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } strncpy(hdrlist[handle]->plus_equipment, equipment, 80); hdrlist[handle]->plus_equipment[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_equipment); return(0); } int edf_set_recording_additional(int handle, const char *recording_additional) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } strncpy(hdrlist[handle]->plus_recording_additional, recording_additional, 80); hdrlist[handle]->plus_recording_additional[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->plus_recording_additional); return(0); } int edf_set_startdatetime(int handle, int startdate_year, int startdate_month, int startdate_day, int starttime_hour, int starttime_minute, int starttime_second) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } if((startdate_year<1970) || (startdate_year>3000) || (startdate_month<1) || (startdate_month>12) || (startdate_day<1) || (startdate_day>31) || (starttime_hour<0) || (starttime_hour>23) || (starttime_minute<0) || (starttime_minute>59) || (starttime_second<0) || (starttime_second>59)) { return(-1); } hdrlist[handle]->startdate_year = startdate_year; hdrlist[handle]->startdate_month = startdate_month; hdrlist[handle]->startdate_day = startdate_day; hdrlist[handle]->starttime_hour = starttime_hour; hdrlist[handle]->starttime_minute = starttime_minute; hdrlist[handle]->starttime_second = starttime_second; return(0); } int edfwrite_annotation_utf8(int handle, long long onset, long long duration, const char *description) { int i; struct edf_write_annotationblock *list_annot, *malloc_list; if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(onset<0LL) { return(-1); } if(hdrlist[handle]->annots_in_file >= hdrlist[handle]->annotlist_sz) { malloc_list = (struct edf_write_annotationblock *)realloc(write_annotationslist[handle], sizeof(struct edf_write_annotationblock) * (hdrlist[handle]->annotlist_sz + EDFLIB_ANNOT_MEMBLOCKSZ)); if(malloc_list==NULL) { return(-1); } write_annotationslist[handle] = malloc_list; hdrlist[handle]->annotlist_sz += EDFLIB_ANNOT_MEMBLOCKSZ; } list_annot = write_annotationslist[handle] + hdrlist[handle]->annots_in_file; list_annot->onset = onset; list_annot->duration = duration; strncpy(list_annot->annotation, description, EDFLIB_WRITE_MAX_ANNOTATION_LEN); list_annot->annotation[EDFLIB_WRITE_MAX_ANNOTATION_LEN] = 0; for(i=0; ; i++) { if(list_annot->annotation[i] == 0) { break; } if(list_annot->annotation[i] < 32) { list_annot->annotation[i] = '.'; } } hdrlist[handle]->annots_in_file++; return(0); } int edfwrite_annotation_latin1(int handle, long long onset, long long duration, const char *description) { struct edf_write_annotationblock *list_annot, *malloc_list; char str[EDFLIB_WRITE_MAX_ANNOTATION_LEN + 1]; if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(onset<0LL) { return(-1); } if(hdrlist[handle]->annots_in_file >= hdrlist[handle]->annotlist_sz) { malloc_list = (struct edf_write_annotationblock *)realloc(write_annotationslist[handle], sizeof(struct edf_write_annotationblock) * (hdrlist[handle]->annotlist_sz + EDFLIB_ANNOT_MEMBLOCKSZ)); if(malloc_list==NULL) { return(-1); } write_annotationslist[handle] = malloc_list; hdrlist[handle]->annotlist_sz += EDFLIB_ANNOT_MEMBLOCKSZ; } list_annot = write_annotationslist[handle] + hdrlist[handle]->annots_in_file; list_annot->onset = onset; list_annot->duration = duration; strncpy(str, description, EDFLIB_WRITE_MAX_ANNOTATION_LEN); str[EDFLIB_WRITE_MAX_ANNOTATION_LEN] = 0; edflib_latin12utf8(str, strlen(str)); strncpy(list_annot->annotation, str, EDFLIB_WRITE_MAX_ANNOTATION_LEN); list_annot->annotation[EDFLIB_WRITE_MAX_ANNOTATION_LEN] = 0; hdrlist[handle]->annots_in_file++; return(0); } static void edflib_remove_padding_trailing_spaces(char *str) { int i; while(str[0]==' ') { for(i=0; ; i++) { if(str[i]==0) { break; } str[i] = str[i+1]; } } for(i = strlen(str); i>0; i--) { if(str[i-1]==' ') { str[i-1] = 0; } else { break; } } } int edf_set_prefilter(int handle, int edfsignal, const char *prefilter) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(edfsignal<0) { return(-1); } if(edfsignal>=hdrlist[handle]->edfsignals) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } strncpy(hdrlist[handle]->edfparam[edfsignal].prefilter, prefilter, 80); hdrlist[handle]->edfparam[edfsignal].prefilter[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->edfparam[edfsignal].prefilter); return(0); } int edf_set_transducer(int handle, int edfsignal, const char *transducer) { if(handle<0) { return(-1); } if(handle>=EDFLIB_MAXFILES) { return(-1); } if(hdrlist[handle]==NULL) { return(-1); } if(!(hdrlist[handle]->writemode)) { return(-1); } if(edfsignal<0) { return(-1); } if(edfsignal>=hdrlist[handle]->edfsignals) { return(-1); } if(hdrlist[handle]->datarecords) { return(-1); } strncpy(hdrlist[handle]->edfparam[edfsignal].transducer, transducer, 80); hdrlist[handle]->edfparam[edfsignal].transducer[80] = 0; edflib_remove_padding_trailing_spaces(hdrlist[handle]->edfparam[edfsignal].transducer); return(0); } /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */ /* if sign is zero, only negative numbers will have the sign '-' character */ /* if sign is one, the sign '+' or '-' character will always be printed */ /* returns the amount of characters printed */ static int edflib_fprint_int_number_nonlocalized(FILE *file, int q, int minimum, int sign) { int flag=0, z, i, j=0, base = 1000000000; if(minimum < 0) { minimum = 0; } if(minimum > 9) { flag = 1; } if(q < 0) { fputc('-', file); j++; q = -q; } else { if(sign) { fputc('+', file); j++; } } for(i=10; i; i--) { if(minimum == i) { flag = 1; } z = q / base; q %= base; if(z || flag) { fputc('0' + z, file); j++; flag = 1; } base /= 10; } if(!flag) { fputc('0', file); j++; } return(j); } /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */ /* if sign is zero, only negative numbers will have the sign '-' character */ /* if sign is one, the sign '+' or '-' character will always be printed */ /* returns the amount of characters printed */ static int edflib_fprint_ll_number_nonlocalized(FILE *file, long long q, int minimum, int sign) { int flag=0, z, i, j=0; long long base = 1000000000000000000LL; if(minimum < 0) { minimum = 0; } if(minimum > 18) { flag = 1; } if(q < 0LL) { fputc('-', file); j++; q = -q; } else { if(sign) { fputc('+', file); j++; } } for(i=19; i; i--) { if(minimum == i) { flag = 1; } z = q / base; q %= base; if(z || flag) { fputc('0' + z, file); j++; flag = 1; } base /= 10LL; } if(!flag) { fputc('0', file); j++; } return(j); } /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */ /* if sign is zero, only negative numbers will have the sign '-' character */ /* if sign is one, the sign '+' or '-' character will always be printed */ /* returns the amount of characters printed */ /* static int edflib_sprint_int_number_nonlocalized(char *str, int q, int minimum, int sign) { int flag=0, z, i, j=0, base = 1000000000; if(minimum < 0) { minimum = 0; } if(minimum > 9) { flag = 1; } if(q < 0) { str[j++] = '-'; q = -q; } else { if(sign) { str[j++] = '+'; } } for(i=10; i; i--) { if(minimum == i) { flag = 1; } z = q / base; q %= base; if(z || flag) { str[j++] = '0' + z; flag = 1; } base /= 10; } if(!flag) { str[j++] = '0'; } str[j] = 0; return(j); } */ /* minimum is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */ /* if sign is zero, only negative numbers will have the sign '-' character */ /* if sign is one, the sign '+' or '-' character will always be printed */ /* returns the amount of characters printed */ static int edflib_sprint_ll_number_nonlocalized(char *str, long long q, int minimum, int sign) { int flag=0, z, i, j=0; long long base = 1000000000000000000LL; if(minimum < 0) { minimum = 0; } if(minimum > 18) { flag = 1; } if(q < 0LL) { str[j++] = '-'; q = -q; } else { if(sign) { str[j++] = '+'; } } for(i=19; i; i--) { if(minimum == i) { flag = 1; } z = q / base; q %= base; if(z || flag) { str[j++] = '0' + z; flag = 1; } base /= 10LL; } if(!flag) { str[j++] = '0'; } str[j] = 0; return(j); } static int edflib_sprint_number_nonlocalized(char *str, double nr) { int flag=0, z, i, j=0, q, base = 1000000000; double var; q = (int)nr; var = nr - q; if(nr < 0.0) { str[j++] = '-'; if(q < 0) { q = -q; } } for(i=10; i; i--) { z = q / base; q %= base; if(z || flag) { str[j++] = '0' + z; flag = 1; } base /= 10; } if(!flag) { str[j++] = '0'; } base = 100000000; var *= (base * 10); q = (int)var; if(q < 0) { q = -q; } if(!q) { str[j] = 0; return(j); } str[j++] = '.'; for(i=9; i; i--) { z = q / base; q %= base; str[j++] = '0' + z; base /= 10; } str[j] = 0; j--; for(; j>0; j--) { if(str[j] == '0') { str[j] = 0; } else { j++; break; } } return(j); } static double edflib_atof_nonlocalized(const char *str) { int i=0, dot_pos=-1, decimals=0, sign=1; double value, value2=0.0; value = edflib_atoi_nonlocalized(str); while(str[i] == ' ') { i++; } if((str[i] == '+') || (str[i] == '-')) { if(str[i] == '-') { sign = -1; } i++; } for(; ; i++) { if(str[i] == 0) { break; } if(((str[i] < '0') || (str[i] > '9')) && (str[i] != '.')) { break; } if(dot_pos >= 0) { if((str[i] >= '0') && (str[i] <= '9')) { decimals++; } else { break; } } if(str[i] == '.') { if(dot_pos < 0) { dot_pos = i; } } } if(decimals) { value2 = edflib_atoi_nonlocalized(str + dot_pos + 1) * sign; i = 1; while(decimals--) { i *= 10; } value2 /= i; } return(value + value2); } static int edflib_atoi_nonlocalized(const char *str) { int i=0, value=0, sign=1; while(str[i] == ' ') { i++; } if((str[i] == '+') || (str[i] == '-')) { if(str[i] == '-') { sign = -1; } i++; } for( ; ; i++) { if(str[i] == 0) { break; } if((str[i] < '0') || (str[i] > '9')) { break; } value *= 10; value += (str[i] - '0'); } return(value * sign); } edfbrowser_157_source/PaxHeaders.7921/show_actual_montage_dialog.h0000644000000000000000000000013212646460742022401 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/show_actual_montage_dialog.h0000644000175000001440000000341112646460742022741 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef SHOWACTUALMONTAGEFORM1_H #define SHOWACTUALMONTAGEFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "utils.h" class UI_Mainwindow; class UI_ShowActualMontagewindow : public QObject { Q_OBJECT public: UI_ShowActualMontagewindow(QWidget *parent); UI_Mainwindow *mainwindow; private: QDialog *ShowMontageDialog; QPushButton *CloseButton; QBoxLayout *box; QTreeView *tree; QStandardItemModel *t_model; }; #endif // SHOWACTUALMONTAGEFORM1_H edfbrowser_157_source/PaxHeaders.7921/popup_save_cancelwindow.cpp0000644000000000000000000000012712646460742022314 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/popup_save_cancelwindow.cpp0000644000175000001440000000547712646460742022666 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "popup_save_cancelwindow.h" UI_CancelSavewindow::UI_CancelSavewindow(const char *title, const char *str, const char *button1txt, const char *button2txt, int *button_nr) { int i, len, max=0, labelwidth = 0, labelheight = 25; buttonnr = button_nr; len = strlen(str); for(i=0; ilabelwidth) labelwidth = max; max = 0; } else { max++; } } if(max>labelwidth) labelwidth = max; labelwidth *= 6; labelwidth += 10; if(labelwidth<260) labelwidth = 260; MessageDialog = new QDialog; MessageDialog->setMinimumSize(labelwidth + 40, labelheight + 85); MessageDialog->setMaximumSize(labelwidth + 40, labelheight + 85); MessageDialog->setWindowTitle(title); MessageDialog->setModal(true); MessageDialog->setAttribute(Qt::WA_DeleteOnClose, true); Label1 = new QLabel(MessageDialog); Label1->setGeometry(20, 20, labelwidth, labelheight); Label1->setAlignment(Qt::AlignLeft | Qt::AlignTop); Label1->setText(str); pushButton1 = new QPushButton(MessageDialog); pushButton1->setGeometry(20, labelheight + 40, 100, 25); pushButton1->setText(button1txt); pushButton2 = new QPushButton(MessageDialog); pushButton2->setGeometry(140, labelheight + 40, 100, 25); pushButton2->setText(button2txt); QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(button1Clicked())); QObject::connect(pushButton2, SIGNAL(clicked()), this, SLOT(button2Clicked())); MessageDialog->exec(); } void UI_CancelSavewindow::button1Clicked() { *buttonnr = 0; MessageDialog->close(); } void UI_CancelSavewindow::button2Clicked() { *buttonnr = 1; MessageDialog->close(); } edfbrowser_157_source/PaxHeaders.7921/ecg_export.cpp0000644000000000000000000000013212646460742017531 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/ecg_export.cpp0000644000175000001440000002651112646460742020077 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "ecg_export.h" UI_ECGExport::UI_ECGExport(QWidget *w_parent) { mainwindow = (UI_Mainwindow *)w_parent; myobjectDialog = new QDialog(w_parent); myobjectDialog->setMinimumSize(400, 445); myobjectDialog->setMaximumSize(400, 445); myobjectDialog->setWindowTitle("Export RR-intervals"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); list = new QListWidget(myobjectDialog); list->setGeometry(20, 20, 130, 350); list->setSelectionBehavior(QAbstractItemView::SelectRows); list->setSelectionMode(QAbstractItemView::SingleSelection); groupBox1 = new QGroupBox(myobjectDialog); groupBox1->setGeometry(170, 20, 210, 120); groupBox1->setTitle("Output format"); radioButton1 = new QRadioButton("RR interval"); radioButton2 = new QRadioButton("R Onset + RR interval"); radioButton3 = new QRadioButton("R Onset"); radioButton2->setChecked(true); checkBox1 = new QCheckBox("Whole recording", myobjectDialog); checkBox1->setGeometry(170, 160, 210, 25); checkBox1->setTristate(false); checkBox2 = new QCheckBox("Don't write to file,\n" "import as annotations instead", myobjectDialog); checkBox2->setGeometry(170, 200, 210, 40); checkBox2->setTristate(false); vbox1 = new QVBoxLayout; vbox1->addWidget(radioButton1); vbox1->addWidget(radioButton2); vbox1->addWidget(radioButton3); groupBox1->setLayout(vbox1); startButton = new QPushButton(myobjectDialog); startButton->setGeometry(20, 400, 150, 25); startButton->setText("Import/Export"); cancelButton = new QPushButton(myobjectDialog); cancelButton->setGeometry(280, 400, 100, 25); cancelButton->setText("Cancel"); load_signalcomps(); QObject::connect(cancelButton, SIGNAL(clicked()), myobjectDialog, SLOT(close())); QObject::connect(startButton, SIGNAL(clicked()), this, SLOT(Export_RR_intervals())); myobjectDialog->exec(); } void UI_ECGExport::Export_RR_intervals() { int i, len, signal_nr, type=-1, beat_cnt, samples_cnt, progress_steps, datarecords, whole_recording=0, import_as_annots=0, filenum=0; char path[MAX_PATH_LENGTH], str[2048]; double *beat_interval_list, *buf; long long *beat_onset_list, datrecs, smpls_left, l_time=0LL; struct signalcompblock *signalcomp; FILE *outputfile; QList selectedlist; struct annotationblock *annotation; selectedlist = list->selectedItems(); if(selectedlist.size() < 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Select a signal first."); messagewindow.exec(); return; } signal_nr = selectedlist.at(0)->data(Qt::UserRole).toInt(); if((signal_nr < 0) || (signal_nr >= mainwindow->signalcomps)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Invalid signalcomp number"); messagewindow.exec(); return; } signalcomp = mainwindow->signalcomp[signal_nr]; if(signalcomp->ecg_filter == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Heart Rate detection is not activated for the selected signal."); messagewindow.exec(); return; } if(checkBox2->checkState() == Qt::Checked) { import_as_annots = 1; } if(checkBox1->checkState() == Qt::Checked) { whole_recording = 1; class FilteredBlockReadClass blockrd; buf = blockrd.init_signalcomp(signalcomp, 1, 0); if(buf == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, can not initialize FilteredBlockReadClass."); messagewindow.exec(); return; } samples_cnt = blockrd.samples_in_buf(); if(samples_cnt < 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, samples_cnt is < 1."); messagewindow.exec(); return; } filenum = signalcomp->filenum; reset_ecg_filter(signalcomp->ecg_filter); datarecords = signalcomp->edfhdr->datarecords; QProgressDialog progress("Processing file...", "Abort", 0, datarecords); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); progress_steps = datarecords / 100; if(progress_steps < 1) { progress_steps = 1; } for(i=0; iedfhdr->datarecords; i++) { if(!(i%progress_steps)) { progress.setValue(i); qApp->processEvents(); if(progress.wasCanceled() == true) { return; } } if(blockrd.process_signalcomp(i) != 0) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error while reading file."); messagewindow.exec(); return; } } progress.reset(); } beat_cnt = ecg_filter_get_beat_cnt(signalcomp->ecg_filter); beat_onset_list = ecg_filter_get_onset_beatlist(signalcomp->ecg_filter); beat_interval_list = ecg_filter_get_interval_beatlist(signalcomp->ecg_filter); if(beat_cnt < 4) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, not enough beats."); messagewindow.exec(); return; } if(import_as_annots) { for(i=0; iedfhdr->viewtime; } if(l_time < 0LL) { l_time = 0LL; } datrecs = beat_onset_list[i] / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record; smpls_left = beat_onset_list[i] % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record; l_time += (datrecs * signalcomp->edfhdr->long_data_record_duration); l_time += ((smpls_left * signalcomp->edfhdr->long_data_record_duration) / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record); if(!whole_recording) { l_time += (mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime - signalcomp->edfhdr->viewtime); } annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); if(annotation == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred (annotation)."); messagewindow.exec(); return; } annotation->onset = l_time; strncpy(annotation->annotation, "R-onset", MAX_ANNOTATION_LEN); annotation->annotation[MAX_ANNOTATION_LEN] = 0; edfplus_annotation_add_item(&mainwindow->annotationlist[filenum], annotation); } if(mainwindow->annotations_dock[signalcomp->filenum] == NULL) { mainwindow->annotations_dock[filenum] = new UI_Annotationswindow(filenum, mainwindow); mainwindow->addDockWidget(Qt::RightDockWidgetArea, mainwindow->annotations_dock[filenum]->docklist, Qt::Vertical); if(!mainwindow->annotationlist[filenum]) { mainwindow->annotations_dock[filenum]->docklist->hide(); } } if(mainwindow->annotationlist[filenum]) { mainwindow->annotations_dock[filenum]->docklist->show(); mainwindow->annotations_edited = 1; mainwindow->annotations_dock[filenum]->updateList(); mainwindow->save_act->setEnabled(true); } } else { path[0] = 0; if(mainwindow->recent_savedir[0]!=0) { strcpy(path, mainwindow->recent_savedir); strcat(path, "/"); } len = strlen(path); get_filename_from_path(path + len, signalcomp->edfhdr->filename, MAX_PATH_LENGTH - len); remove_extension_from_filename(path); strcat(path, "_RR_interval.txt"); strcpy(path, QFileDialog::getSaveFileName(0, "Export RR-interval to ASCII", QString::fromLocal8Bit(path), "Text files (*.txt *.TXT)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(mainwindow->recent_savedir, path, MAX_PATH_LENGTH); outputfile = fopeno(path, "wb"); if(outputfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, can not open outputfile for writing."); messagewindow.exec(); return; } if(radioButton1->isChecked() == true) { type = 1; } if(radioButton2->isChecked() == true) { type = 2; } if(radioButton3->isChecked() == true) { type = 3; } if(type == 1) { for(i=0; iedfhdr->viewtime; } if(l_time < 0LL) { l_time = 0LL; } datrecs = beat_onset_list[i] / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record; smpls_left = beat_onset_list[i] % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record; l_time += (datrecs * signalcomp->edfhdr->long_data_record_duration); l_time += ((smpls_left * signalcomp->edfhdr->long_data_record_duration) / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record); if(!whole_recording) { l_time += (mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime - signalcomp->edfhdr->viewtime); } if(type == 2) { fprintf(outputfile, "%.4f\t%.4f\n", ((double)l_time) / TIME_DIMENSION, beat_interval_list[i]); } if(type == 3) { fprintf(outputfile, "%.4f\n", ((double)l_time) / TIME_DIMENSION); } } } fclose(outputfile); } myobjectDialog->close(); if(!import_as_annots) { sprintf(str, "Done. The R-onsets and/or RR-intervals are exported to:\n\n%s", path); QMessageBox messagewindow(QMessageBox::Information, "Ready", QString::fromLocal8Bit(str)); messagewindow.setIconPixmap(QPixmap(":/images/ok.png")); messagewindow.exec(); } reset_ecg_filter(signalcomp->ecg_filter); mainwindow->setup_viewbuf(); } void UI_ECGExport::load_signalcomps(void) { int i; QListWidgetItem *item; list->clear(); for(i=0; isignalcomps; i++) { item = new QListWidgetItem; item->setText(mainwindow->signalcomp[i]->signallabel); item->setData(Qt::UserRole, QVariant(i)); list->addItem(item); } } edfbrowser_157_source/PaxHeaders.7921/flywheel.h0000644000000000000000000000012712646460742016662 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/flywheel.h0000644000175000001440000000435612646460742017227 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef FLYWHEELBUTTON_H #define FLYWHEELBUTTON_H #include #include #include #include #include #include #include #include #include #include class UI_Flywheel: public QWidget { Q_OBJECT public: UI_Flywheel(QWidget *parent=0); ~UI_Flywheel(); QSize sizeHint() const {return minimumSizeHint(); } QSize minimumSizeHint() const {return QSize(10,30); } private slots: void wheel_rotate(void); void t2_time_out(void); protected: void paintEvent(QPaintEvent *); void mousePressEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *); private: QTimer *t1, *t2; int mouse_y, mouse_old_y, mouse_delta_y, use_move_events, time_old, time_new, dial_speed, dial_speed_arr[4], dial_speed_ptr, spinning, holdoff, knobs, cursor_above_object; double wheel_position; struct timeval tv; QColor *bordercolor_up, *bordercolor_down; QLinearGradient *linearGrad; signals: void dialMoved(int); }; #endif edfbrowser_157_source/PaxHeaders.7921/manscan2edf.h0000644000000000000000000000012712646460742017224 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/manscan2edf.h0000644000175000001440000000476012646460742017570 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_MANSCAN2EDFFORM_H #define UI_MANSCAN2EDFFORM_H #include #include #include #include #include #include #include #include #include #if QT_VERSION < 0x050000 #include #include #endif #include #include #include #include #include #include #include "global.h" #include "utils.h" #include "edflib.h" #include "utc_date_time.h" class UI_MANSCAN2EDFwindow : public QObject { Q_OBJECT public: UI_MANSCAN2EDFwindow(char *recent_dir=NULL, char *save_dir=NULL); private: QPushButton *pushButton1, *pushButton2; QTextEdit *textEdit1; QDialog *myobjectDialog; char *recent_opendir, *recent_savedir; int get_worddatafile(struct segment_prop_struct *, int, FILE *); int get_channel_gain(struct segment_prop_struct *, int, FILE *); int get_start_date(struct segment_prop_struct *, int, FILE *); int get_sample_rate(struct segment_prop_struct *, int, FILE *); int get_filter_settings(struct segment_prop_struct *, int, FILE *); int get_recorder_version(struct segment_prop_struct *, int, FILE *); int get_starttime_offset(struct segment_prop_struct *, int, FILE *); int get_events(struct segment_prop_struct *, int, FILE *); int get_number_of_segments(FILE *); char * fgetline(char *, int, FILE *); long long get_long_time(const char *); private slots: void SelectFileButton(); }; #endif edfbrowser_157_source/PaxHeaders.7921/nk2edf.h0000644000000000000000000000012712646460742016214 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/nk2edf.h0000644000175000001440000000400412646460742016547 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_NK2EDFFORM_H #define UI_NK2EDFFORM_H #include #include #include #include #include #include #include #include #include #include #if QT_VERSION < 0x050000 #include #include #endif #include #include #include #include #include #include #include "global.h" #include "utils.h" class UI_NK2EDFwindow : public QObject { Q_OBJECT public: UI_NK2EDFwindow(char *recent_dir=NULL); private: QPushButton *pushButton1, *pushButton2; QTextEdit *textEdit1; QDialog *myobjectDialog; QCheckBox *checkBox1; int total_elapsed_time; char *recent_opendir, labels[256][17]; int check_device(char *); int read_21e_file(char *); private slots: void SelectFileButton(); int convert_nk2edf(FILE *, FILE *, FILE *, int, int, int, char *, int); }; #endif edfbrowser_157_source/PaxHeaders.7921/filter.h0000644000000000000000000000012712646460742016330 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/filter.h0000644000175000001440000000337212646460742016672 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef filter_INCLUDED #define filter_INCLUDED #include #include #include struct filter_settings{ double old_input; double old_output; double factor; double sample_frequency; double cutoff_frequency; int is_LPF; int first_sample; }; struct filter_settings * create_filter(int, double, double); void reset_filter(int, struct filter_settings *); int first_order_filter(int, struct filter_settings *); double get_filter_factor(double, double); struct filter_settings * create_filter_copy(struct filter_settings *); #endif edfbrowser_157_source/PaxHeaders.7921/wav2edf.cpp0000644000000000000000000000013212646460742016730 xustar0030 mtime=1452958178.249246726 30 atime=1452958178.249246726 30 ctime=1452958178.249246726 edfbrowser_157_source/wav2edf.cpp0000644000175000001440000004173312646460742017301 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "wav2edf.h" UI_WAV2EDFwindow::UI_WAV2EDFwindow(char *recent_dir, char *save_dir) { recent_opendir = recent_dir; recent_savedir = save_dir; myobjectDialog = new QDialog; myobjectDialog->setMinimumSize(600, 300); myobjectDialog->setMaximumSize(600, 300); myobjectDialog->setWindowTitle("Wave to EDF converter"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); PatientnameLabel = new QLabel(myobjectDialog); PatientnameLabel->setGeometry(20, 20, 140, 25); PatientnameLabel->setText("Subject"); RecordingLabel = new QLabel(myobjectDialog); RecordingLabel->setGeometry(20, 55, 140, 25); RecordingLabel->setText("Recording"); DatetimeLabel = new QLabel(myobjectDialog); DatetimeLabel->setGeometry(20, 90, 140, 25); DatetimeLabel->setText("Startdate and time"); PhysDimLabel = new QLabel(myobjectDialog); PhysDimLabel->setGeometry(20, 125, 140, 25); PhysDimLabel->setText("Physical dimension"); PhysMaxLabel = new QLabel(myobjectDialog); PhysMaxLabel->setGeometry(20, 160, 140, 25); PhysMaxLabel->setText("Physical maximum"); PatientnameLineEdit = new QLineEdit(myobjectDialog); PatientnameLineEdit->setGeometry(160, 20, 420, 25); PatientnameLineEdit->setMaxLength(80); RecordingLineEdit = new QLineEdit(myobjectDialog); RecordingLineEdit->setGeometry(160, 55, 420, 25); RecordingLineEdit->setMaxLength(80); StartDatetimeedit = new QDateTimeEdit(myobjectDialog); StartDatetimeedit->setGeometry(160, 90, 140, 25); StartDatetimeedit->setDisplayFormat("dd/MM/yyyy hh:mm:ss"); StartDatetimeedit->setDateTime(QDateTime::currentDateTime()); PhysDimLineEdit = new QLineEdit(myobjectDialog); PhysDimLineEdit->setGeometry(160, 125, 140, 25); PhysDimLineEdit->setMaxLength(8); PhysDimLineEdit->setText("mV"); PhysMaxSpinBox = new QDoubleSpinBox(myobjectDialog); PhysMaxSpinBox->setGeometry(160, 160, 140, 25); PhysMaxSpinBox->setDecimals(5); PhysMaxSpinBox->setRange(1.0, 1000000.0); PhysMaxSpinBox->setValue(2000.0); pushButton1 = new QPushButton(myobjectDialog); pushButton1->setGeometry(20, 250, 100, 25); pushButton1->setText("Select File"); pushButton2 = new QPushButton(myobjectDialog); pushButton2->setGeometry(480, 250, 100, 25); pushButton2->setText("Close"); QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton())); QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close())); myobjectDialog->exec(); } void UI_WAV2EDFwindow::SelectFileButton() { FILE *inputfile=NULL; int i, j, edfsignals, sf, resolution, edf_hdl, readbufsize, *writebuf, bytes_per_sample, sf_divider; unsigned int fmt_chunk_offset, data_chunk_offset, tmp; char path[MAX_PATH_LENGTH], outputfilename[MAX_PATH_LENGTH], scratchpad[512], *readbuf; long long blocks, leftover, progress_steps, k; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; enable_widgets(false); if(!(strlen(PatientnameLineEdit->text().toLatin1().data()))) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a subject name."); messagewindow.exec(); enable_widgets(true); return; } if(!(strlen(RecordingLineEdit->text().toLatin1().data()))) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a recording description."); messagewindow.exec(); enable_widgets(true); return; } strcpy(path, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "Text files (*.wav *.WAV)").toLocal8Bit().data()); if(!strcmp(path, "")) { enable_widgets(true); return; } get_directory_from_path(recent_opendir, path, MAX_PATH_LENGTH); inputfile = fopeno(path, "rb"); if(inputfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); messagewindow.exec(); enable_widgets(true); return; } /***************** check if the wavefile is valid ******************************/ rewind(inputfile); if(fread(scratchpad, 256, 1, inputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if((strncmp(scratchpad, "RIFF", 4)) || (strncmp(scratchpad + 8, "WAVE", 4))) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "File is not a Wave file."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } fmt_chunk_offset = 12; while(1) { fseeko(inputfile, (long long)fmt_chunk_offset, SEEK_SET); if(fread(scratchpad, 256, 1, inputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find fmt chunk."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(strncmp(scratchpad, "fmt ", 4) == 0) { break; } tmp = *((unsigned int *)(scratchpad + 4)); if(tmp < 2) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find fmt chunk."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(tmp & 1) { tmp++; } fmt_chunk_offset += (tmp + 8); } if(*((signed short *)(scratchpad + 8)) != 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "File contains compressed data.\nCan not convert compressed data."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } edfsignals = *((unsigned short *)(scratchpad + 10)); if(edfsignals < 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Channels < 1"); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(edfsignals > MAXSIGNALS) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Channels > MAXSIGNALS"); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } sf = *((unsigned int *)(scratchpad + 12)); if(sf < 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Samplefrequency < 1"); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(sf > 500000) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Samplefrequency > 500000"); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } resolution = *((unsigned short *)(scratchpad + 22)); if(resolution < 8) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Resolution < 8 bit"); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(resolution > 24) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Resolution > 24"); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if((resolution != 8) && (resolution != 16) && (resolution != 24)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Resolution (bitdepth) must be 8, 16 or 24 bit."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } bytes_per_sample = 2; if(resolution > 16) { bytes_per_sample = 3; } if(resolution < 9) { bytes_per_sample = 1; } /////////////////////////////////////////////////////////////////////////////// data_chunk_offset = 12; while(1) { fseeko(inputfile, (long long)data_chunk_offset, SEEK_SET); if(fread(scratchpad, 256, 1, inputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find data chunk."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(strncmp(scratchpad, "data", 4) == 0) { break; } tmp = *((unsigned int *)(scratchpad + 4)); if(tmp < 2) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find data chunk."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(tmp & 1) { tmp++; } data_chunk_offset += (tmp + 8); } /////////////////////////////////////////////////////////////////////////////// sf_divider = 1; if((sf % 10) == 0) { sf_divider = 10; sf /= 10; } blocks = (long long)(*((int *)(scratchpad + 4))); blocks /= (sf * edfsignals * bytes_per_sample); fseeko(inputfile, 0LL, SEEK_END); leftover = ftello(inputfile) - (long long)data_chunk_offset - 8LL; leftover /= (sf * edfsignals * bytes_per_sample); if(blocks > leftover) { blocks = leftover; } if(blocks < 1LL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Not enough data in file."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } readbufsize = bytes_per_sample * sf * edfsignals; readbuf = (char *)malloc(readbufsize); if(readbuf == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (readbuf)."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } writebuf = (int *)malloc(sf * edfsignals * sizeof(int)); if(writebuf == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (writebuf)."); messagewindow.exec(); free(readbuf); fclose(inputfile); enable_widgets(true); return; } // printf("resolution is %i edfsignals is %i sf is %i blocks is %lli\n", resolution, edfsignals, sf, blocks); /***************** create a new EDF file *****************************************/ get_filename_from_path(outputfilename, path, MAX_PATH_LENGTH); remove_extension_from_filename(outputfilename); if(resolution > 16) { strcat(outputfilename, ".bdf"); } else { strcat(outputfilename, ".edf"); } path[0] = 0; if(recent_savedir[0]!=0) { strcpy(path, recent_savedir); strcat(path, "/"); } strcat(path, outputfilename); if(resolution > 16) { strcpy(path, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(path), "BDF files (*.bdf *.BDF)").toLocal8Bit().data()); } else { strcpy(path, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(path), "EDF files (*.edf *.EDF)").toLocal8Bit().data()); } if(!strcmp(path, "")) { enable_widgets(true); fclose(inputfile); return; } get_directory_from_path(recent_savedir, path, MAX_PATH_LENGTH); if(resolution > 16) { edf_hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_BDFPLUS, edfsignals); } else { edf_hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_EDFPLUS, edfsignals); } if(edf_hdl < 0) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open output file for writing."); messagewindow.exec(); fclose(inputfile); free(readbuf); free(writebuf); enable_widgets(true); return; } for(i=0; i 16) { edf_set_digital_maximum(edf_hdl, i, 8388607); } else { if(resolution < 9) { edf_set_digital_maximum(edf_hdl, i, 127); } else { edf_set_digital_maximum(edf_hdl, i, 32767); } } } for(i=0; i 16) { edf_set_digital_minimum(edf_hdl, i, -8388608); } else { if(resolution < 9) { edf_set_digital_minimum(edf_hdl, i, -128); } else { edf_set_digital_minimum(edf_hdl, i, -32768); } } } for(i=0; ivalue()); } for(i=0; ivalue() * -1.0); } for(i=0; itext().toLatin1().data()); } for(i=0; itext().toLatin1().data()); edf_set_recording_additional(edf_hdl, RecordingLineEdit->text().toLatin1().data()); edf_set_startdatetime(edf_hdl, StartDatetimeedit->date().year(), StartDatetimeedit->date().month(), StartDatetimeedit->date().day(), StartDatetimeedit->time().hour(), StartDatetimeedit->time().minute(), StartDatetimeedit->time().second()); edfwrite_annotation_latin1(edf_hdl, 0LL, -1, "Recording starts"); /***************** start conversion **************************************/ fseeko(inputfile, (long long)data_chunk_offset + 8LL, SEEK_SET); QProgressDialog progress("Converting a Wave file ...", "Abort", 0, (int)blocks, myobjectDialog); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); progress_steps = blocks / 100LL; if(progress_steps < 1LL) { progress_steps = 1LL; } for(k=0LL; kprocessEvents(); if(progress.wasCanceled() == true) { edfclose_file(edf_hdl); fclose(inputfile); free(readbuf); free(writebuf); enable_widgets(true); return; } } if(fread(readbuf, readbufsize, 1, inputfile)!=1) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read error occurred during conversion."); messagewindow.exec(); edfclose_file(edf_hdl); fclose(inputfile); free(readbuf); free(writebuf); enable_widgets(true); return; } if(bytes_per_sample == 1) { for(i=0; isetEnabled(toggle); PatientnameLineEdit->setEnabled(toggle); RecordingLineEdit->setEnabled(toggle); pushButton1->setEnabled(toggle); pushButton2->setEnabled(toggle); } edfbrowser_157_source/PaxHeaders.7921/ravg_filter.h0000644000000000000000000000012712646460742017347 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/ravg_filter.h0000644000175000001440000000375312646460742017714 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef ravg_filter_INCLUDED #define ravg_filter_INCLUDED #include #include #include struct ravg_filter_settings{ int size; int type; int first_sample; double *buf; double *buf2; int buf_pntr; int buf_pntr2; double mean; double mean2; }; struct ravg_filter_settings * create_ravg_filter(int, int); void reset_ravg_filter(double, struct ravg_filter_settings *); double run_ravg_filter(double, struct ravg_filter_settings *); void free_ravg_filter(struct ravg_filter_settings *); void ravg_filter_restore_buf(struct ravg_filter_settings *); void ravg_filter_save_buf(struct ravg_filter_settings *); double ravg_filter_response(int, int, double); struct ravg_filter_settings * create_ravg_filter_copy(struct ravg_filter_settings *); #endif edfbrowser_157_source/PaxHeaders.7921/utc_date_time.c0000644000000000000000000000013212646460742017640 xustar0030 mtime=1452958178.243246747 30 atime=1452958178.243246747 30 ctime=1452958178.243246747 edfbrowser_157_source/utc_date_time.c0000644000175000001440000002007612646460742020206 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "utc_date_time.h" void date_time_to_utc(long long *seconds, struct date_time_struct date_time) { *seconds = (date_time.day - 1) * 86400LL; if(date_time.month>1) { *seconds += 2678400LL; } if(date_time.month>2) { if(date_time.year%4) { *seconds += 2419200LL; } else { *seconds += 2505600LL; } } if(date_time.month>3) { *seconds += 2678400LL; } if(date_time.month>4) { *seconds += 2592000LL; } if(date_time.month>5) { *seconds += 2678400LL; } if(date_time.month>6) { *seconds += 2592000LL; } if(date_time.month>7) { *seconds += 2678400LL; } if(date_time.month>8) { *seconds += 2678400LL; } if(date_time.month>9) { *seconds += 2592000LL; } if(date_time.month>10) { *seconds += 2678400LL; } if(date_time.month>11) { *seconds += 2592000LL; } *seconds += (date_time.year - 1970) * 31536000LL; *seconds += ((date_time.year - 1970 + 1) / 4) * 86400LL; *seconds += date_time.hour * 3600; *seconds += date_time.minute * 60; *seconds += date_time.second; switch(date_time.month) { case 1 : strcpy(date_time.month_str, "JAN"); break; case 2 : strcpy(date_time.month_str, "FEB"); break; case 3 : strcpy(date_time.month_str, "MAR"); break; case 4 : strcpy(date_time.month_str, "APR"); break; case 5 : strcpy(date_time.month_str, "MAY"); break; case 6 : strcpy(date_time.month_str, "JUN"); break; case 7 : strcpy(date_time.month_str, "JUL"); break; case 8 : strcpy(date_time.month_str, "AUG"); break; case 9 : strcpy(date_time.month_str, "SEP"); break; case 10 : strcpy(date_time.month_str, "OCT"); break; case 11 : strcpy(date_time.month_str, "NOV"); break; case 12 : strcpy(date_time.month_str, "DEC"); break; default : strcpy(date_time.month_str, "ERR"); break; } } void utc_to_date_time(long long seconds, struct date_time_struct *date_time) { date_time->year = 1970; while(1) { if(date_time->year%4) { if(seconds>=31536000) { date_time->year++; seconds -= 31536000; } else { break; } } else { if(seconds>=31622400) { date_time->year++; seconds -= 31622400; } else { break; } } } date_time->month = 1; if(seconds>=2678400) { date_time->month++; seconds -= 2678400; if(date_time->year%4) { if(seconds>=2419200) { date_time->month++; seconds -= 2419200; if(seconds>=2678400) { date_time->month++; seconds -= 2678400; if(seconds>=2592000) { date_time->month++; seconds -= 2592000; if(seconds>=2678400) { date_time->month++; seconds -= 2678400; if(seconds>=2592000) { date_time->month++; seconds -= 2592000; if(seconds>=2678400) { date_time->month++; seconds -= 2678400; if(seconds>=2678400) { date_time->month++; seconds -= 2678400; if(seconds>=2592000) { date_time->month++; seconds -= 2592000; if(seconds>=2678400) { date_time->month++; seconds -= 2678400; if(seconds>=2592000) { date_time->month++; seconds -= 2592000; if(seconds>=2678400) { date_time->month++; seconds -= 2678400; } } } } } } } } } } } } else { if(seconds>=2505600) { date_time->month++; seconds -= 2505600; if(seconds>=2678400) { date_time->month++; seconds -= 2678400; if(seconds>=2592000) { date_time->month++; seconds -= 2592000; if(seconds>=2678400) { date_time->month++; seconds -= 2678400; if(seconds>=2592000) { date_time->month++; seconds -= 2592000; if(seconds>=2678400) { date_time->month++; seconds -= 2678400; if(seconds>=2678400) { date_time->month++; seconds -= 2678400; if(seconds>=2592000) { date_time->month++; seconds -= 2592000; if(seconds>=2678400) { date_time->month++; seconds -= 2678400; if(seconds>=2592000) { date_time->month++; seconds -= 2592000; if(seconds>=2678400) { date_time->month++; seconds -= 2678400; } } } } } } } } } } } } } date_time->day = (seconds / 86400) + 1; seconds %= 86400; date_time->hour = seconds / 3600; seconds %= 3600; date_time->minute = seconds / 60; seconds %= 60; date_time->second = seconds; switch(date_time->month) { case 1 : strcpy(date_time->month_str, "JAN"); break; case 2 : strcpy(date_time->month_str, "FEB"); break; case 3 : strcpy(date_time->month_str, "MAR"); break; case 4 : strcpy(date_time->month_str, "APR"); break; case 5 : strcpy(date_time->month_str, "MAY"); break; case 6 : strcpy(date_time->month_str, "JUN"); break; case 7 : strcpy(date_time->month_str, "JUL"); break; case 8 : strcpy(date_time->month_str, "AUG"); break; case 9 : strcpy(date_time->month_str, "SEP"); break; case 10 : strcpy(date_time->month_str, "OCT"); break; case 11 : strcpy(date_time->month_str, "NOV"); break; case 12 : strcpy(date_time->month_str, "DEC"); break; default : strcpy(date_time->month_str, "ERR"); break; } } edfbrowser_157_source/PaxHeaders.7921/biosemi2bdfplus.h0000644000000000000000000000013212646460742020130 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/biosemi2bdfplus.h0000644000175000001440000000422512646460742020474 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_BIOSEMI2BDFFORM_H #define UI_BIOSEMI2BDFFORM_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "edflib.h" #include "edf_annot_list.h" class UI_Mainwindow; class UI_BIOSEMI2BDFPLUSwindow : public QObject { Q_OBJECT public: UI_BIOSEMI2BDFPLUSwindow(QWidget *parent); UI_Mainwindow *mainwindow; private: QLabel *label1[16], *label2, *label3, *label4; QLineEdit *lineEdit1[16]; QRadioButton *radioButton1, *radioButton2; QCheckBox *checkBox1; QPushButton *selectButton, *closeButton; QDialog *myobjectDialog; char inputpath[MAX_PATH_LENGTH], outputpath[MAX_PATH_LENGTH], *recent_opendir, *recent_savedir; private slots: void SelectFileButton(); }; #endif edfbrowser_157_source/PaxHeaders.7921/spectrumanalyzer.cpp0000644000000000000000000000013112646460742021001 xustar0030 mtime=1452958178.249246726 29 atime=1452958178.24824673 30 ctime=1452958178.249246726 edfbrowser_157_source/spectrumanalyzer.cpp0000644000175000001440000006607412646460742021360 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "spectrumanalyzer.h" #define SPECT_LOG_MINIMUM (0.000001) #define SPECT_LOG_MINIMUM_LOG (-5) UI_FreqSpectrumWindow::UI_FreqSpectrumWindow(struct signalcompblock *signal_comp, char *view_buf, UI_FreqSpectrumWindow **spectrdialog, int number, QWidget *w_parent) { int i; char str[1024]; long long l_temp; buf1 = NULL; buf2 = NULL; buf3 = NULL; buf4 = NULL; buf5 = NULL; busy = 0; spectrumdialog_is_destroyed = 0; class_is_deleted = 0; flywheel_value = 1050; spectrumdialog = spectrdialog; spectrumdialognumber = number; mainwindow = (UI_Mainwindow *)w_parent; viewbuf = view_buf; signalcomp = signal_comp; for(i=strlen(signalcomp->edfhdr->filename); i>0; i--) { if((signalcomp->edfhdr->filename[i-1]=='/')||(signalcomp->edfhdr->filename[i-1]=='\\')) break; } if((signalcomp->edfhdr->viewtime + signalcomp->edfhdr->starttime_offset)>=0LL) { if(signalcomp->alias[0] != 0) { snprintf(signallabel, 512, " %s %i:%02i:%02i.%04i %s", signalcomp->alias, (int)((signalcomp->edfhdr->viewtime / TIME_DIMENSION)/ 3600LL), (int)(((signalcomp->edfhdr->viewtime / TIME_DIMENSION) % 3600LL) / 60LL), (int)((signalcomp->edfhdr->viewtime / TIME_DIMENSION) % 60LL), (int)((signalcomp->edfhdr->viewtime % TIME_DIMENSION) / 1000LL), signalcomp->edfhdr->filename + i); } else { snprintf(signallabel, 512, " %s %i:%02i:%02i.%04i %s", signalcomp->signallabel, (int)((signalcomp->edfhdr->viewtime / TIME_DIMENSION)/ 3600LL), (int)(((signalcomp->edfhdr->viewtime / TIME_DIMENSION) % 3600LL) / 60LL), (int)((signalcomp->edfhdr->viewtime / TIME_DIMENSION) % 60LL), (int)((signalcomp->edfhdr->viewtime % TIME_DIMENSION) / 1000LL), signalcomp->edfhdr->filename + i); } } else { l_temp = signalcomp->edfhdr->l_starttime + ((signalcomp->edfhdr->viewtime + signalcomp->edfhdr->starttime_offset) % (86400LL * TIME_DIMENSION)); if(l_temp<=0) { l_temp = (86400LL * TIME_DIMENSION) + l_temp; } l_temp = -signalcomp->edfhdr->viewtime; if(signalcomp->alias[0] != 0) { snprintf(signallabel, 512, " %s -%i:%02i:%02i.%04i %s", signalcomp->alias, (int)((l_temp / TIME_DIMENSION)/ 3600LL), (int)(((l_temp / TIME_DIMENSION) % 3600LL) / 60LL), (int)((l_temp / TIME_DIMENSION) % 60LL), (int)((l_temp % TIME_DIMENSION) / 1000LL), signalcomp->edfhdr->filename + i); } else { snprintf(signallabel, 512, " %s -%i:%02i:%02i.%04i %s", signalcomp->signallabel, (int)((l_temp / TIME_DIMENSION)/ 3600LL), (int)(((l_temp / TIME_DIMENSION) % 3600LL) / 60LL), (int)((l_temp / TIME_DIMENSION) % 60LL), (int)((l_temp % TIME_DIMENSION) / 1000LL), signalcomp->edfhdr->filename + i); } } remove_trailing_zeros(signallabel); strcpy(physdimension, signalcomp->physdimension); SpectrumDialog = new QDialog(); SpectrumDialog->setAttribute(Qt::WA_DeleteOnClose, true); SpectrumDialog->setMinimumSize(650, 480); SpectrumDialog->setSizeGripEnabled(true); SpectrumDialog->setModal(false); SpectrumDialog->setWindowFlags(Qt::Window | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); if(mainwindow->spectrum_sqrt) { snprintf(str, 512, "Amplitude Spectrum %s", signallabel); } else { snprintf(str, 512, "Power Spectral Density %s", signallabel); } SpectrumDialog->setWindowTitle(str); SpectrumDialog->setWindowIcon(QIcon(":/images/edf.png")); curve1 = new SignalCurve; curve1->setSignalColor(Qt::green); curve1->setBackgroundColor(Qt::black); curve1->setRasterColor(Qt::gray); curve1->setTraceWidth(0); curve1->setH_label("Hz"); curve1->setLowerLabel("Frequency"); if(mainwindow->spectrum_sqrt) { if(mainwindow->spectrum_vlog) { sprintf(str, "log10(%s)", physdimension); curve1->setV_label(str); } else { curve1->setV_label(physdimension); } } else { if(mainwindow->spectrum_vlog) { sprintf(str, "log10((%s)^2/Hz)", physdimension); } else { sprintf(str, "(%s)^2/Hz", physdimension); } curve1->setV_label(str); } curve1->create_button("to Text"); curve1->setDashBoardEnabled(false); flywheel1 = new UI_Flywheel; flywheel1->setMinimumSize(20, 85); amplitudeSlider = new QSlider; amplitudeSlider->setOrientation(Qt::Vertical); amplitudeSlider->setMinimum(1); amplitudeSlider->setMaximum(2000); amplitudeSlider->setValue(1000); amplitudeSlider->setInvertedAppearance(true); amplitudeSlider->setMinimumSize(15, 280); log_minslider = new QSlider; log_minslider->setOrientation(Qt::Vertical); log_minslider->setMinimum(1); log_minslider->setMaximum(2000); log_minslider->setValue(1000); log_minslider->setInvertedAppearance(false); log_minslider->setMinimumSize(15, 280); amplitudeLabel = new QLabel; amplitudeLabel->setText("Amplitude"); amplitudeLabel->setMinimumSize(100, 15); amplitudeLabel->setAlignment(Qt::AlignHCenter); sqrtCheckBox = new QCheckBox("Amplitude"); sqrtCheckBox->setMinimumSize(70, 25); sqrtCheckBox->setTristate(false); if(mainwindow->spectrum_sqrt) { sqrtCheckBox->setCheckState(Qt::Checked); } else { sqrtCheckBox->setCheckState(Qt::Unchecked); } VlogCheckBox = new QCheckBox("Log"); VlogCheckBox->setMinimumSize(70, 25); VlogCheckBox->setTristate(false); if(mainwindow->spectrum_vlog) { VlogCheckBox->setCheckState(Qt::Checked); log_minslider->setVisible(true); } else { VlogCheckBox->setCheckState(Qt::Unchecked); log_minslider->setVisible(false); } BWCheckBox = new QCheckBox("B/W"); BWCheckBox->setMinimumSize(70, 25); BWCheckBox->setTristate(false); if(mainwindow->spectrum_bw == 1) { BWCheckBox->setCheckState(Qt::Checked); } else { BWCheckBox->setCheckState(Qt::Unchecked); } vlayout3 = new QVBoxLayout; vlayout3->addStretch(100); vlayout3->addWidget(flywheel1, 100); vlayout3->addStretch(100); hlayout4 = new QHBoxLayout; hlayout4->addStretch(100); hlayout4->addLayout(vlayout3, 100); hlayout4->addStretch(100); hlayout4->addWidget(amplitudeSlider, 300); hlayout4->addWidget(log_minslider, 300); vlayout2 = new QVBoxLayout; vlayout2->setSpacing(10); vlayout2->addStretch(100); vlayout2->addWidget(amplitudeLabel, 0, Qt::AlignHCenter); vlayout2->addLayout(hlayout4, 200); vlayout2->addWidget(sqrtCheckBox); vlayout2->addWidget(VlogCheckBox); vlayout2->addWidget(BWCheckBox); spanSlider = new QSlider; spanSlider->setOrientation(Qt::Horizontal); spanSlider->setMinimum(1); spanSlider->setMaximum(1000); spanSlider->setValue(1000); spanSlider->setMinimumSize(500, 15); spanLabel = new QLabel; spanLabel->setText("Span"); spanLabel->setMinimumSize(110, 15); spanLabel->setAlignment(Qt::AlignHCenter); centerSlider = new QSlider; centerSlider->setOrientation(Qt::Horizontal); centerSlider->setMinimum(0); centerSlider->setMaximum(1000); centerSlider->setValue(0); centerSlider->setMinimumSize(500, 15); centerLabel = new QLabel; centerLabel->setText("Center"); centerLabel->setMinimumSize(110, 15); centerLabel->setAlignment(Qt::AlignHCenter); hlayout1 = new QHBoxLayout; hlayout1->setSpacing(20); hlayout1->addLayout(vlayout2); hlayout1->addWidget(curve1, 100); hlayout2 = new QHBoxLayout; hlayout2->setSpacing(20); hlayout2->addWidget(spanLabel); hlayout2->addWidget(spanSlider); hlayout2->addStretch(100); hlayout3 = new QHBoxLayout; hlayout3->setSpacing(20); hlayout3->addWidget(centerLabel); hlayout3->addWidget(centerSlider); hlayout3->addStretch(100); vlayout1 = new QVBoxLayout; vlayout1->setSpacing(20); vlayout1->addLayout(hlayout1); vlayout1->addLayout(hlayout2); vlayout1->addLayout(hlayout3); SpectrumDialog->setLayout(vlayout1); t1 = new QTimer(this); t1->setSingleShot(true); #if QT_VERSION >= 0x050000 t1->setTimerType(Qt::PreciseTimer); #endif t1->start(10); QObject::connect(t1, SIGNAL(timeout()), this, SLOT(update_curve())); QObject::connect(amplitudeSlider, SIGNAL(valueChanged(int)), this, SLOT(sliderMoved(int))); QObject::connect(log_minslider, SIGNAL(valueChanged(int)), this, SLOT(sliderMoved(int))); QObject::connect(spanSlider, SIGNAL(valueChanged(int)), this, SLOT(sliderMoved(int))); QObject::connect(centerSlider, SIGNAL(valueChanged(int)), this, SLOT(sliderMoved(int))); QObject::connect(sqrtCheckBox, SIGNAL(stateChanged(int)), this, SLOT(sliderMoved(int))); QObject::connect(VlogCheckBox, SIGNAL(stateChanged(int)), this, SLOT(sliderMoved(int))); QObject::connect(BWCheckBox, SIGNAL(stateChanged(int)), this, SLOT(sliderMoved(int))); QObject::connect(SpectrumDialog, SIGNAL(destroyed(QObject *)), this, SLOT(SpectrumDialogDestroyed(QObject *))); QObject::connect(curve1, SIGNAL(extra_button_clicked()), this, SLOT(print_to_txt())); QObject::connect(flywheel1, SIGNAL(dialMoved(int)), this, SLOT(update_flywheel(int))); QObject::connect(this, SIGNAL(finished()), this, SLOT(thr_finished_func())); SpectrumDialog->show(); } void UI_FreqSpectrumWindow::update_flywheel(int new_value) { flywheel_value += new_value; if(flywheel_value < 10) { flywheel_value = 10; } if(flywheel_value > 100000) { flywheel_value = 100000; } sliderMoved(0); } void UI_FreqSpectrumWindow::print_to_txt() { int i; char str[1024], path[MAX_PATH_LENGTH]; FILE *outputfile; path[0] = 0; if(mainwindow->recent_savedir[0]!=0) { strcpy(path, mainwindow->recent_savedir); strcat(path, "/"); } strcat(path, "spectrum.txt"); strcpy(path, QFileDialog::getSaveFileName(0, "Export to text (ASCII)", QString::fromLocal8Bit(path), "Text files (*.txt *.TXT)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(mainwindow->recent_savedir, path, MAX_PATH_LENGTH); outputfile = fopen(path, "wb"); if(outputfile == NULL) { snprintf(str, 1024, "Can not open file %s for writing.", path); QMessageBox messagewindow(QMessageBox::Critical, "Error", QString::fromLocal8Bit(str)); messagewindow.exec(); return; } sprintf(str, "FFT Power Spectral Density log10(Power/%fHz)\n", freqstep); remove_trailing_zeros(str); fprintf(outputfile, "%s", str); if(signalcomp->alias[0] != 0) { fprintf(outputfile, "Signal: %s\n", signalcomp->alias); } else { fprintf(outputfile, "Signal: %s\n", signalcomp->signallabel); } sprintf(str, "FFT blocksize: %i\n", mainwindow->maxdftblocksize); sprintf(str + strlen(str), "FFT resolution: %f Hz\n", freqstep); sprintf(str + strlen(str), "Data Samples: %i\n", samples); sprintf(str + strlen(str), "Power Samples: %i\n", steps); sprintf(str + strlen(str), "Samplefrequency: %f Hz\n", (double)signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record / ((double)signalcomp->edfhdr->long_data_record_duration / TIME_DIMENSION)); remove_trailing_zeros(str); fprintf(outputfile, "%s", str); for(i=0; icheckState() == Qt::Checked) { mainwindow->spectrum_vlog = 1; log_minslider->setVisible(true); } else { mainwindow->spectrum_vlog = 0; log_minslider->setVisible(false); } if(sqrtCheckBox->checkState() == Qt::Checked) { mainwindow->spectrum_sqrt = 1; sprintf(str, "Amplitude Spectrum %s", signallabel); SpectrumDialog->setWindowTitle(str); if(mainwindow->spectrum_vlog) { sprintf(str, "log10(%s)", physdimension); curve1->setV_label(str); } else { curve1->setV_label(physdimension); } } else { mainwindow->spectrum_sqrt = 0; sprintf(str, "Power Spectral Density %s", signallabel); SpectrumDialog->setWindowTitle(str); if(mainwindow->spectrum_vlog) { sprintf(str, "log10((%s)^2/Hz)", physdimension); } else { sprintf(str, "(%s)^2/Hz", physdimension); } curve1->setV_label(str); } if(BWCheckBox->isChecked() == true) { curve1->setSignalColor(Qt::black); curve1->setBackgroundColor(Qt::white); curve1->setRasterColor(Qt::black); curve1->setMarker1Color(Qt::black); curve1->setBorderColor(Qt::white); curve1->setTextColor(Qt::black); curve1->setCrosshairColor(Qt::black); mainwindow->spectrum_bw = 1; } else { curve1->setSignalColor(Qt::green); curve1->setBackgroundColor(Qt::black); curve1->setRasterColor(Qt::gray); curve1->setMarker1Color(Qt::yellow); curve1->setBorderColor(Qt::lightGray); curve1->setTextColor(Qt::black); curve1->setCrosshairColor(Qt::red); mainwindow->spectrum_bw = 0; } spanstep = (long long)spanSlider->value() * (long long)steps / 1000LL; startstep = (long long)centerSlider->value() * ((long long)steps - spanstep) / 1000LL; stopstep = startstep + spanstep; if(mainwindow->spectrum_sqrt) { if(mainwindow->spectrum_vlog) { curve1->drawCurve(buf5 + startstep, stopstep - startstep, (maxvalue_sqrt_vlog * ((double)flywheel_value / 1000.0) * (double)amplitudeSlider->value()) / 1000.0, minvalue_sqrt_vlog * (double)log_minslider->value() / 1000.0); } else { curve1->drawCurve(buf3 + startstep, stopstep - startstep, (maxvalue_sqrt * ((double)flywheel_value / 1000.0) * (double)amplitudeSlider->value()) / 1000.0, 0.0); } } else { if(mainwindow->spectrum_vlog) { curve1->drawCurve(buf4 + startstep, stopstep - startstep, (maxvalue_vlog * ((double)flywheel_value / 1000.0) * (double)amplitudeSlider->value()) / 1000.0, minvalue_vlog * (double)log_minslider->value() / 1000.0); } else { curve1->drawCurve(buf2 + startstep, stopstep - startstep, (maxvalue * ((double)flywheel_value / 1000.0) * (double)amplitudeSlider->value()) / 1000.0, 0.0); } } max_freq = ((double)samplefreq / 2.0) * stopstep / steps; start_freq = ((double)samplefreq / 2.0) * startstep / steps; // printf("steps: %i\n" // "startstep: %lli\n" // "stopstep: %lli\n" // "spanstep: %lli\n" // "samplefreq: %f\n" // "max_freq: %f\n" // "start_freq: %f\n", // steps, // startstep, // stopstep, // spanstep, // samplefreq, // max_freq, // start_freq); curve1->setH_RulerValues(start_freq, max_freq); strcpy(str, "Center "); convert_to_metric_suffix(str + strlen(str), start_freq + ((max_freq - start_freq) / 2.0), 3); remove_trailing_zeros(str); strcat(str, "Hz"); centerLabel->setText(str); strcpy(str, "Span "); convert_to_metric_suffix(str + strlen(str), max_freq - start_freq, 3); remove_trailing_zeros(str); strcat(str, "Hz"); spanLabel->setText(str); } void UI_FreqSpectrumWindow::run() { int i, j, k, samplesleft, fft_outputbufsize; long long s, s2; double dig_value=0.0, f_tmp=0.0; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; if(buf1 != NULL) { free(buf1); } buf1 = (double *)malloc(sizeof(double) * signalcomp->samples_on_screen); if(buf1 == NULL) { malloc_err = 1; return; } samples = 0; for(s=signalcomp->sample_start; ssamples_on_screen; s++) { if(s>signalcomp->sample_stop) break; dig_value = 0.0; s2 = s + signalcomp->sample_timeoffset - signalcomp->sample_start; for(j=0; jnum_of_signals; j++) { if(signalcomp->edfhdr->bdf) { var.two[0] = *((unsigned short *)( viewbuf + signalcomp->viewbufoffset + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)) + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset + ((s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record) * 3))); var.four[2] = *((unsigned char *)( viewbuf + signalcomp->viewbufoffset + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)) + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset + ((s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record) * 3) + 2)); if(var.four[2]&0x80) { var.four[3] = 0xff; } else { var.four[3] = 0x00; } f_tmp = var.one_signed; } if(signalcomp->edfhdr->edf) { f_tmp = *(((short *)( viewbuf + signalcomp->viewbufoffset + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)) + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset)) + (s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)); } f_tmp += signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].offset; f_tmp *= signalcomp->factor[j]; dig_value += f_tmp; } if(signalcomp->spike_filter) { if(s==signalcomp->sample_start) { spike_filter_restore_buf(signalcomp->spike_filter); } dig_value = run_spike_filter(dig_value, signalcomp->spike_filter); } for(k=0; kfilter_cnt; k++) { dig_value = first_order_filter(dig_value, signalcomp->filter[k]); } for(k=0; kravg_filter_cnt; k++) { if(s==signalcomp->sample_start) { ravg_filter_restore_buf(signalcomp->ravg_filter[k]); } dig_value = run_ravg_filter(dig_value, signalcomp->ravg_filter[k]); } for(k=0; kfidfilter_cnt; k++) { if(s==signalcomp->sample_start) { memcpy(signalcomp->fidbuf[k], signalcomp->fidbuf2[k], fid_run_bufsize(signalcomp->fid_run[k])); } dig_value = signalcomp->fidfuncp[k](signalcomp->fidbuf[k], dig_value); } if(signalcomp->ecg_filter != NULL) { if(s==signalcomp->sample_start) { ecg_filter_restore_buf(signalcomp->ecg_filter); } dig_value = run_ecg_filter(dig_value, signalcomp->ecg_filter); } if(s>=signalcomp->sample_start) { buf1[samples++] = dig_value * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue; } } samplefreq = (double)signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record / ((double)signalcomp->edfhdr->long_data_record_duration / TIME_DIMENSION); dftblocksize = mainwindow->maxdftblocksize; if(dftblocksize & 1) { dftblocksize--; } dftblocks = 1; if(dftblocksize < samples) { dftblocks = samples / dftblocksize; } else { dftblocksize = samples; } if(dftblocksize & 1) { dftblocksize--; } samplesleft = samples % dftblocksize; if(samplesleft & 1) { samplesleft--; } freqstep = samplefreq / (double)dftblocksize; fft_outputbufsize = dftblocksize / 2; steps = fft_outputbufsize; if(buf2 != NULL) { free(buf2); } buf2 = (double *)calloc(1, sizeof(double) * fft_outputbufsize); if(buf2 == NULL) { malloc_err = 1; free(buf1); buf1 = NULL; return; } if(buf3 != NULL) { free(buf3); } buf3 = (double *)malloc(sizeof(double) * fft_outputbufsize); if(buf3 == NULL) { malloc_err = 1; free(buf1); free(buf2); buf1 = NULL; buf2 = NULL; return; } if(buf4 != NULL) { free(buf4); } buf4 = (double *)malloc(sizeof(double) * fft_outputbufsize); if(buf4 == NULL) { malloc_err = 1; free(buf1); free(buf2); free(buf3); buf1 = NULL; buf2 = NULL; buf3 = NULL; return; } if(buf5 != NULL) { free(buf5); } buf5 = (double *)malloc(sizeof(double) * fft_outputbufsize); if(buf5 == NULL) { malloc_err = 1; free(buf1); free(buf2); free(buf3); free(buf4); buf1 = NULL; buf2 = NULL; buf3 = NULL; buf4 = NULL; return; } maxvalue = 0.000001; maxvalue_sqrt = 0.000001; maxvalue_vlog = 0.000001; maxvalue_sqrt_vlog = 0.000001; minvalue_vlog = 0.0; minvalue_sqrt_vlog = 0.0; #ifdef CHECK_POWERSPECTRUM printf("samples is %i dftblocksize is %i dftblocks is %i samplesleft is %i fft_outputbufsize is %i steps is %i\n", samples, dftblocksize, dftblocks, samplesleft, fft_outputbufsize, steps); double power1=0.0, power2=0.0; for(i=0; iecg_filter == NULL) { buf2[0] /= 2.0; // DC! } else { buf2[0] = 0.0; // Remove DC because heart rate is always a positive value } free(cfg); free(kiss_fftbuf); for(i=0; i maxvalue) { maxvalue = buf2[i]; } if(buf3[i] > maxvalue_sqrt) { maxvalue_sqrt = buf3[i]; } if(buf4[i] > maxvalue_vlog) { maxvalue_vlog = buf4[i]; } if(buf5[i] > maxvalue_sqrt_vlog) { maxvalue_sqrt_vlog = buf5[i]; } if((buf4[i] < minvalue_vlog) && (buf4[i] >= SPECT_LOG_MINIMUM_LOG)) { minvalue_vlog = buf4[i]; } if((buf5[i] < minvalue_sqrt_vlog) && (buf5[i] >= SPECT_LOG_MINIMUM_LOG)) { minvalue_sqrt_vlog = buf5[i]; } } } if(minvalue_vlog < SPECT_LOG_MINIMUM_LOG) minvalue_vlog = SPECT_LOG_MINIMUM_LOG; if(minvalue_sqrt_vlog < SPECT_LOG_MINIMUM_LOG) minvalue_sqrt_vlog = SPECT_LOG_MINIMUM_LOG; if(samplesleft) { dftblocks++; } #ifdef CHECK_POWERSPECTRUM power1 /= samples; power2 *= freqstep; printf("\n power1 is %f\n power2 is %f\n\n", power1, power2); #endif if(buf1 != NULL) { free(buf1); buf1 = NULL; } } void UI_FreqSpectrumWindow::update_curve() { if(signalcomp == NULL) { return; } if(busy) { return; } viewbuf = mainwindow->viewbuf; if(viewbuf == NULL) { return; } samples = signalcomp->samples_on_screen; if(signalcomp->samples_on_screen > signalcomp->sample_stop) { samples = signalcomp->sample_stop; } samples -= signalcomp->sample_start; if((samples < 10) || (viewbuf == NULL)) { curve1->clear(); return; } busy = 1; malloc_err = 0; curve1->setUpdatesEnabled(false); QApplication::setOverrideCursor(Qt::WaitCursor); start(); } void UI_FreqSpectrumWindow::thr_finished_func() { char str[1024]; if(spectrumdialog_is_destroyed) { return; } if(malloc_err) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); messagewindow.exec(); curve1->clear(); busy = 0; return; } strcpy(str, "FFT resolution: "); convert_to_metric_suffix(str + strlen(str), freqstep, 3); remove_trailing_zeros(str); sprintf(str + strlen(str), "Hz %i blocks of %i samples", dftblocks, dftblocksize); curve1->setUpperLabel1(str); curve1->setUpperLabel2(signallabel); sliderMoved(0); curve1->setUpdatesEnabled(true); busy = 0; QApplication::restoreOverrideCursor(); } void UI_FreqSpectrumWindow::SpectrumDialogDestroyed(QObject *) { spectrumdialog_is_destroyed = 1; QObject::disconnect(this, SIGNAL(finished()), this, SLOT(thr_finished_func())); if(isRunning()) { wait(ULONG_MAX); QApplication::restoreOverrideCursor(); } spectrumdialog[spectrumdialognumber] = NULL; if(!class_is_deleted) { delete this; } } UI_FreqSpectrumWindow::~UI_FreqSpectrumWindow() { int i; class_is_deleted = 1; if(!spectrumdialog_is_destroyed) { SpectrumDialog->close(); } if(buf2 != NULL) { free(buf2); } if(buf3 != NULL) { free(buf3); } if(buf4 != NULL) { free(buf4); } if(buf5 != NULL) { free(buf5); } spectrumdialog[spectrumdialognumber] = NULL; for(i=0; ispectr_dialog[i] == spectrumdialognumber + 1) { signalcomp->spectr_dialog[i] = 0; break; } } } edfbrowser_157_source/PaxHeaders.7921/check_for_updates.cpp0000644000000000000000000000013212646460742021042 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/check_for_updates.cpp0000644000175000001440000000640412646460742021407 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "check_for_updates.h" Check_for_updates::Check_for_updates() { QNetworkRequest request; QNetworkReply *reply; manager = new QNetworkAccessManager(this); request.setUrl(QUrl("http://www.teuniz.net/edfbrowser/latest_version.txt")); request.setRawHeader("User-Agent", PROGRAM_NAME " " PROGRAM_VERSION " OS_UNKNOWN"); #ifdef Q_OS_LINUX request.setRawHeader("User-Agent", PROGRAM_NAME " " PROGRAM_VERSION " Q_OS_LINUX"); #elif defined (Q_OS_MAC) request.setRawHeader("User-Agent", PROGRAM_NAME " " PROGRAM_VERSION " Q_OS_MAC"); #elif defined (Q_OS_WIN32) request.setRawHeader("User-Agent", PROGRAM_NAME " " PROGRAM_VERSION " Q_OS_WIN32"); #else request.setRawHeader("User-Agent", PROGRAM_NAME " " PROGRAM_VERSION " Q_OS_OTHER"); #endif request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork); reply = manager->get(request); connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); } void Check_for_updates::replyFinished() { long long int n; char buf[128]; int this_version, latest_version; QNetworkReply *reply = qobject_cast(sender()); if(reply->error() != QNetworkReply::NoError) { reply->deleteLater(); return; } if(reply->bytesAvailable() < 31) { reply->deleteLater(); return; } n = reply->read(buf, 100); if(n < 31) { reply->deleteLater(); return; } reply->deleteLater(); buf[30] = 0; if(strncmp(buf, "EDFbrowser latest version: ", 27)) { return; } if(is_integer_number(buf + 27)) { return; } latest_version = atoi(buf + 27); if((latest_version < 1) || (latest_version > 1000000)) { return; } sprintf(buf, PROGRAM_VERSION); buf[1] = buf[0]; this_version = atoi(buf + 1); if(this_version >= latest_version) { return; } QMessageBox messagewindow(QMessageBox::Information, "New version available", "A newer version of EDFbrowser is available.\n" "Do you want to download the new version now?", QMessageBox::Yes | QMessageBox::No); if(messagewindow.exec() != QMessageBox::Yes) { return; } QDesktopServices::openUrl(QUrl("http://www.teuniz.net/edfbrowser/")); } edfbrowser_157_source/PaxHeaders.7921/ravg_filter.cpp0000644000000000000000000000012712646460742017702 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/ravg_filter.cpp0000644000175000001440000001154512646460742020245 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "ravg_filter.h" struct ravg_filter_settings * create_ravg_filter(int type, int size) { struct ravg_filter_settings *settings; if((size < 2) || (size > 10000)) return(NULL); if((type < 0) || (type > 1)) return(NULL); settings = (struct ravg_filter_settings *) calloc(1, sizeof(struct ravg_filter_settings)); if(settings==NULL) return(NULL); settings->size = size; settings->type = type; settings->first_sample = 1; settings->buf_pntr = 0; settings->buf_pntr2 = 0; settings->mean = 0.0; settings->mean2 = 0.0; settings->buf = (double *)calloc(1, sizeof(double) * size); if(settings->buf == NULL) { free(settings); return(NULL); } settings->buf2 = (double *)calloc(1, sizeof(double) * size); if(settings->buf2 == NULL) { free(settings->buf); free(settings); return(NULL); } return(settings); } struct ravg_filter_settings * create_ravg_filter_copy(struct ravg_filter_settings *src) { struct ravg_filter_settings *settings; settings = (struct ravg_filter_settings *) calloc(1, sizeof(struct ravg_filter_settings)); if(settings==NULL) { return(NULL); } memcpy(settings, src, sizeof(struct ravg_filter_settings)); settings->buf = (double *)calloc(1, sizeof(double) * settings->size); if(settings->buf == NULL) { free(settings); return(NULL); } memcpy(settings->buf, src->buf, settings->size); settings->buf2 = (double *)calloc(1, sizeof(double) * settings->size); if(settings->buf2 == NULL) { free(settings->buf); free(settings); return(NULL); } memcpy(settings->buf2, src->buf2, settings->size); return(settings); } void reset_ravg_filter(double offset, struct ravg_filter_settings *settings) { int i; for(i=0; isize; i++) { settings->buf[i] = offset; } memcpy(settings->buf2, settings->buf, settings->size * sizeof(double)); settings->mean = offset; settings->mean2 = offset; settings->buf_pntr = 0; settings->buf_pntr2 = 0; } void ravg_filter_restore_buf(struct ravg_filter_settings *settings) { memcpy(settings->buf, settings->buf2, settings->size * sizeof(double)); settings->mean = settings->mean2; settings->buf_pntr = settings->buf_pntr2; } void ravg_filter_save_buf(struct ravg_filter_settings *settings) { memcpy(settings->buf2, settings->buf, settings->size * sizeof(double)); settings->mean2 = settings->mean; settings->buf_pntr2 = settings->buf_pntr; } double run_ravg_filter(double new_input, struct ravg_filter_settings *settings) { int i; if(settings->first_sample) { settings->first_sample = 0; for(i=0; isize; i++) { settings->buf[i] = new_input; } settings->mean = new_input; return(new_input); } settings->mean -= (settings->buf[settings->buf_pntr] / settings->size); settings->buf[settings->buf_pntr] = new_input; settings->buf_pntr++; if(settings->buf_pntr >= settings->size) { settings->buf_pntr = 0; } settings->mean += (new_input / settings->size); if(settings->type == 0) /* highpass */ { return(settings->buf[(settings->buf_pntr + (settings->size / 2)) % settings->size] - settings->mean); } if(settings->type == 1) /* lowpass */ { return(settings->mean); } return(0.0); } void free_ravg_filter(struct ravg_filter_settings *settings) { if(settings == NULL) { return; } free(settings->buf); free(settings->buf2); free(settings); } double ravg_filter_response(int type, int size, double freq) { if((type < 0) || (type > 1) || (size < 2) || (freq > 0.5)) { return(1.0); } if(type) { if(freq < 0.000001) { return(1.0); } return(fabs((sin(M_PI * freq * (double)size)) / ((double)size * sin(M_PI * freq)))); } if(freq < 0.000001) { return(0.0); } return(1.0 - fabs((sin(M_PI * freq * (double)size)) / ((double)size * sin(M_PI * freq)))); } edfbrowser_157_source/PaxHeaders.7921/edit_predefined_mtg.cpp0000644000000000000000000000013212646460742021353 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/edit_predefined_mtg.cpp0000644000175000001440000001053212646460742021715 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "edit_predefined_mtg.h" UI_edit_predefined_mtg_window::UI_edit_predefined_mtg_window(QWidget *w_parent) { int i; char str[1200]; mainwindow = (UI_Mainwindow *)w_parent; edit_predefined_mtg_Dialog = new QDialog; edit_predefined_mtg_Dialog->setMinimumSize(800, 265); edit_predefined_mtg_Dialog->setMaximumSize(800, 265); edit_predefined_mtg_Dialog->setWindowTitle("Edit key-bindings for montages"); edit_predefined_mtg_Dialog->setModal(true); edit_predefined_mtg_Dialog->setAttribute(Qt::WA_DeleteOnClose, true); mtg_path_list = new QListWidget(edit_predefined_mtg_Dialog); mtg_path_list->setGeometry(10, 10, 780, 210); mtg_path_list->setSelectionBehavior(QAbstractItemView::SelectRows); mtg_path_list->setSelectionMode(QAbstractItemView::SingleSelection); mtg_path_list->setSpacing(1); for(i=0; i < MAXPREDEFINEDMONTAGES; i++) { sprintf(str, "F%i : ", i + 1); if(mainwindow->predefined_mtg_path[i][0] != 0) { strcat(str, &(mainwindow->predefined_mtg_path[i][0])); } new QListWidgetItem(str, mtg_path_list); } CloseButton = new QPushButton(edit_predefined_mtg_Dialog); CloseButton->setGeometry(690, 230, 100, 25); CloseButton->setText("Close"); QObject::connect(CloseButton, SIGNAL(clicked()), edit_predefined_mtg_Dialog, SLOT(close())); QObject::connect(mtg_path_list, SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(rowClicked(QListWidgetItem *))); edit_predefined_mtg_Dialog->exec(); } void UI_edit_predefined_mtg_window::rowClicked(QListWidgetItem *item) { row = mtg_path_list->row(item); listItem = item; dialog = new QDialog(edit_predefined_mtg_Dialog); dialog->setMinimumSize(140, 135); dialog->setMaximumSize(140, 135); dialog->setWindowTitle("Entry"); dialog->setModal(true); dialog->setAttribute(Qt::WA_DeleteOnClose, true); button1 = new QPushButton(dialog); button1->setGeometry(20, 20, 100, 25); button1->setText("Edit"); button2 = new QPushButton(dialog); button2->setGeometry(20, 55, 100, 25); button2->setText("Remove"); button3 = new QPushButton(dialog); button3->setGeometry(20, 90, 100, 25); button3->setText("Cancel"); QObject::connect(button1, SIGNAL(clicked()), this, SLOT(adEntry())); QObject::connect(button2, SIGNAL(clicked()), this, SLOT(removeEntry())); QObject::connect(button3, SIGNAL(clicked()), dialog, SLOT(close())); dialog->exec(); } void UI_edit_predefined_mtg_window::adEntry() { char str[1200], path[MAX_PATH_LENGTH]; dialog->close(); strcpy(path, QFileDialog::getOpenFileName(0, "Select montage", QString::fromLocal8Bit(mainwindow->recent_montagedir), "MTG files (*.mtg *.MTG)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(mainwindow->recent_montagedir, path, MAX_PATH_LENGTH); strcpy(&(mainwindow->predefined_mtg_path[row][0]), path); mainwindow->load_predefined_mtg_act[row]->setText(QString::fromLocal8Bit(mainwindow->predefined_mtg_path[row])); sprintf(str, "F%i : ", row + 1); strcat(str, path); listItem->setText(str); } void UI_edit_predefined_mtg_window::removeEntry() { char str[32]; dialog->close(); mainwindow->predefined_mtg_path[row][0] = 0; mainwindow->load_predefined_mtg_act[row]->setText("Empty"); sprintf(str, "F%i :", row + 1); listItem->setText(str); } edfbrowser_157_source/PaxHeaders.7921/emsa2edf.cpp0000644000000000000000000000013212646460742017060 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/emsa2edf.cpp0000644000175000001440000005576012646460742017436 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "emsa2edf.h" UI_EMSA2EDFwindow::UI_EMSA2EDFwindow(char *recent_dir, char *save_dir) { char txt_string[2048]; recent_opendir = recent_dir; recent_savedir = save_dir; myobjectDialog = new QDialog; myobjectDialog->setMinimumSize(600, 480); myobjectDialog->setMaximumSize(600, 480); myobjectDialog->setWindowTitle("Emsa to EDF+ converter"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); 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"); textEdit1 = new QTextEdit(myobjectDialog); textEdit1->setGeometry(20, 20, 560, 380); textEdit1->setFrameStyle(QFrame::Panel | QFrame::Sunken); textEdit1->setReadOnly(true); textEdit1->setLineWrapMode(QTextEdit::NoWrap); sprintf(txt_string, "Emsa to EDF+ converter.\n"); textEdit1->append(txt_string); QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton())); QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close())); myobjectDialog->exec(); } void UI_EMSA2EDFwindow::SelectFileButton() { FILE *inputfile=NULL, *outputfile=NULL, *logfile=NULL; int i, j, k, channels, record_size, samplefrequency, hdrsize, samples_in_record, bufsize, max_buf_records, raster, data_records, records_in_buf, error, len, seq_nr, year, b_year, b_date, seconds, deci_seconds, datrecduris1, gender, tallen=0, annot_cnt=0, patientcode=0, annots_written=0, time_on, time_off, duration_present=0; long long filesize; char path[MAX_PATH_LENGTH], scratchpad[256], *buf, date[9], time[9], month[4], patientname[128], b_month[4], *p, equipment[41], handedness[16], weight[16], birthdate[16], txt_string[2048], outputfilename[MAX_PATH_LENGTH]; union{ int number; char str[4]; } var; pushButton1->setEnabled(false); strcpy(path, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "PLG files (*.plg *.PLG)").toLocal8Bit().data()); if(!strcmp(path, "")) { pushButton1->setEnabled(true); return; } get_directory_from_path(recent_opendir, path, MAX_PATH_LENGTH); /***************** check header ******************************/ inputfile = fopeno(path, "rb"); if(inputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for reading.\n", path); textEdit1->append(QString::fromLocal8Bit(txt_string)); pushButton1->setEnabled(true); return; } fseeko(inputfile, 0LL, SEEK_END); filesize = ftello(inputfile); if(filesize<1538) { textEdit1->append("Error, filesize is too small.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } rewind(inputfile); if(fread(scratchpad, 3, 1, inputfile)!=1) { textEdit1->append("Read error.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } if((strncmp(scratchpad, "PBJ", 3))&&(strncmp(scratchpad, "BPC", 3))) { textEdit1->append("Error, file id does not match.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } fseeko(inputfile, 3LL, SEEK_SET); channels = fgetc(inputfile); if(channels==EOF) { textEdit1->append("Read error.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } if(!channels) { textEdit1->append("Error, number of channels is 0.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } hdrsize = 1024 + (512 * channels); if(filesize<(hdrsize + (2 * channels))) { textEdit1->append("Error, filesize is too small.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } fseeko(inputfile, 10LL, SEEK_SET); samplefrequency = 256 * fgetc(inputfile); fseeko(inputfile, 9LL, SEEK_SET); samplefrequency += fgetc(inputfile); if(!samplefrequency) { textEdit1->append("Error, samplefrequency is 0 Hz.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } if(filesize<(hdrsize + (2 * channels * samplefrequency))) { textEdit1->append("Error, filesize is too small.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } if(get_string(scratchpad, inputfile, 205, 32)!=8) { textEdit1->append("Error, can not read startdate.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } error = 0; if((scratchpad[0]<'0')||(scratchpad[0]>'9')) error = 1; if((scratchpad[1]<'0')||(scratchpad[1]>'9')) error = 1; date[6] = scratchpad[2]; date[7] = scratchpad[3]; date[3] = scratchpad[4]; date[4] = scratchpad[5]; date[0] = scratchpad[6]; date[1] = scratchpad[7]; date[2] = 0; date[5] = 0; date[8] = 0; if((date[0]<'0')||(date[0]>'9')) error = 1; if((date[1]<'0')||(date[1]>'9')) error = 1; if((date[3]<'0')||(date[3]>'9')) error = 1; if((date[4]<'0')||(date[4]>'9')) error = 1; if((date[6]<'0')||(date[6]>'9')) error = 1; if((date[7]<'0')||(date[7]>'9')) error = 1; scratchpad[4] = 0; year = atoi(scratchpad); if(get_string(scratchpad, inputfile, 214, 32)!=8) { textEdit1->append("Error, can not read starttime.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } strcpy(time, scratchpad); if(time[2] != ':') error = 1; if(time[5] != ':') error = 1; time[2] = 0; time[5] = 0; time[8] = 0; if((time[0]<'0')||(time[0]>'9')) error = 1; if((time[1]<'0')||(time[1]>'9')) error = 1; if((time[3]<'0')||(time[3]>'9')) error = 1; if((time[4]<'0')||(time[4]>'9')) error = 1; if((time[6]<'0')||(time[6]>'9')) error = 1; if((time[7]<'0')||(time[7]>'9')) error = 1; if((atoi(date)<1)||(atoi(date)>31)) error = 1; if((atoi(date+3)<1)||(atoi(date+3)>12)) error = 1; if(atoi(time)>23) error = 1; if(atoi(time+3)>59) error = 1; if(atoi(time+6)>59) error = 1; if(error) { textEdit1->append("Error, can not read startdate or starttime.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } date[2] = '.'; date[5] = '.'; time[2] = '.'; time[5] = '.'; i = atoi(date+3); switch(i) { case 1 : strcpy(month, "JAN"); break; case 2 : strcpy(month, "FEB"); break; case 3 : strcpy(month, "MAR"); break; case 4 : strcpy(month, "APR"); break; case 5 : strcpy(month, "MAY"); break; case 6 : strcpy(month, "JUN"); break; case 7 : strcpy(month, "JUL"); break; case 8 : strcpy(month, "AUG"); break; case 9 : strcpy(month, "SEP"); break; case 10 : strcpy(month, "OCT"); break; case 11 : strcpy(month, "NOV"); break; case 12 : strcpy(month, "DEC"); break; default : strcpy(month, "ERR"); break; } if(get_string(scratchpad, inputfile, 169, 32)!=8) { strcpy(birthdate, "X"); } else { error = 0; for(i=0; i<8; i++) { if((scratchpad[i]<'0')||(scratchpad[i]>'9')) error = 1; } scratchpad[8] = 0; b_date = atoi(scratchpad+6); if((b_date<1)||(b_date>31)) error = 1; scratchpad[6] = 0; i = atoi(scratchpad+4); if((i<1)||(i>12)) error = 1; switch(i) { case 1 : strcpy(b_month, "JAN"); break; case 2 : strcpy(b_month, "FEB"); break; case 3 : strcpy(b_month, "MAR"); break; case 4 : strcpy(b_month, "APR"); break; case 5 : strcpy(b_month, "MAY"); break; case 6 : strcpy(b_month, "JUN"); break; case 7 : strcpy(b_month, "JUL"); break; case 8 : strcpy(b_month, "AUG"); break; case 9 : strcpy(b_month, "SEP"); break; case 10 : strcpy(b_month, "OCT"); break; case 11 : strcpy(b_month, "NOV"); break; case 12 : strcpy(b_month, "DEC"); break; default : strcpy(b_month, "ERR"); break; } scratchpad[4] = 0; b_year = atoi(scratchpad); if(error) { strcpy(birthdate, "X"); } else { sprintf(birthdate, "%02i-%s-%04i", b_date, b_month, b_year); } } len = get_string(patientname, inputfile, 11, 30); if(len) { latin1_to_ascii(patientname, len); for(i=0; iappend("Read error.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } fseeko(inputfile, 8LL, SEEK_SET); seq_nr = fgetc(inputfile); if(seq_nr==EOF) { textEdit1->append("Read error.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } fseeko(inputfile, 203LL, SEEK_SET); gender = fgetc(inputfile); if((gender!='M')&&(gender!='F')) { gender = 'X'; } len = fgetc(inputfile); switch(len) { case 'E' : strcpy(handedness, " lefthanded"); break; case 'D' : strcpy(handedness, " righthanded"); break; default : handedness[0] = 0; break; } len = get_string(weight + 1, inputfile, 351, 6); if(len) { latin1_to_ascii(weight + 1, len); weight[0] = ' '; strcat(weight, " Kg"); } else { weight[0] = 0; } len = get_string(equipment, inputfile, 309, 40); if(len) { latin1_to_ascii(equipment, len); for(i=0; iappend("Malloc error. (logbuf)\n"); fclose(inputfile); fclose(logfile); pushButton1->setEnabled(true); return; } for(i=0; iappend("Error, can not read event starttime in .LBK file.\n"); fclose(inputfile); fclose(logfile); free(logbuf); return; } if(scratchpad[2] != ':') error = 1; if(scratchpad[5] != ':') error = 1; scratchpad[2] = 0; scratchpad[5] = 0; scratchpad[8] = 0; if((scratchpad[0]<'0')||(scratchpad[0]>'9')) error = 1; if((scratchpad[1]<'0')||(scratchpad[1]>'9')) error = 1; if((scratchpad[3]<'0')||(scratchpad[3]>'9')) error = 1; if((scratchpad[4]<'0')||(scratchpad[4]>'9')) error = 1; if((scratchpad[6]<'0')||(scratchpad[6]>'9')) error = 1; if((scratchpad[7]<'0')||(scratchpad[7]>'9')) error = 1; if(atoi(scratchpad)>23) error = 1; if(atoi(scratchpad+3)>59) error = 1; if(atoi(scratchpad+6)>59) error = 1; if(error) { textEdit1->append("Error, can not read event starttime in .LBK file.\n"); fclose(inputfile); fclose(logfile); free(logbuf); return; } time_on = atoi(scratchpad) * 3600; time_on += atoi(scratchpad+3) * 60; time_on += atoi(scratchpad+6); if(get_string(scratchpad, logfile, i * 69 + 9, 10)!=8) { textEdit1->append("Error, can not read event stoptime in .LBK file.\n"); fclose(inputfile); fclose(logfile); free(logbuf); return; } if(scratchpad[2] != ':') error = 1; if(scratchpad[5] != ':') error = 1; scratchpad[2] = 0; scratchpad[5] = 0; scratchpad[8] = 0; if((scratchpad[0]<'0')||(scratchpad[0]>'9')) error = 1; if((scratchpad[1]<'0')||(scratchpad[1]>'9')) error = 1; if((scratchpad[3]<'0')||(scratchpad[3]>'9')) error = 1; if((scratchpad[4]<'0')||(scratchpad[4]>'9')) error = 1; if((scratchpad[6]<'0')||(scratchpad[6]>'9')) error = 1; if((scratchpad[7]<'0')||(scratchpad[7]>'9')) error = 1; if(atoi(scratchpad)>23) error = 1; if(atoi(scratchpad+3)>59) error = 1; if(atoi(scratchpad+6)>59) error = 1; if(error) { textEdit1->append("Error, can not read event stoptime in .LBK file.\n"); fclose(inputfile); fclose(logfile); free(logbuf); return; } time_off = atoi(scratchpad) * 3600; time_off += atoi(scratchpad+3) * 60; time_off += atoi(scratchpad+6); logbuf[i].duration = time_off - time_on; if(logbuf[i].duration<0) { textEdit1->append("Error, event duration in .LBK file is < 0.\n"); fclose(inputfile); fclose(logfile); free(logbuf); return; } if(logbuf[i].duration) { duration_present = 1; } k = (atoi(time) * 3600); k += (atoi(time+3) * 60); k += atoi(time+6); logbuf[i].onset = time_on - k; if(logbuf[i].onset < 0) { logbuf[i].onset += 86400; } len = get_string(logbuf[i].description, logfile, i * 69 + 18, 40); if(len>2) { for(j=len-1; j>0; j--) { if(logbuf[i].description[j]==' ') { logbuf[i].description[j] = 0; len--; } else break; } } latin1_to_utf8(logbuf[i].description, 80); len = strlen(logbuf[i].description); if(len>tallen) { tallen = len; } } } fclose(logfile); } else { textEdit1->append("Can not open LBK file, will continue without events."); } tallen += 14; if(annot_cnt) { tallen += 14; } if(duration_present) { tallen += 14; } if(tallen%2) { tallen++; } /***************** write header *****************************************/ get_filename_from_path(outputfilename, path, MAX_PATH_LENGTH); remove_extension_from_filename(outputfilename); strcat(outputfilename, ".edf"); path[0] = 0; if(recent_savedir[0]!=0) { strcpy(path, recent_savedir); strcat(path, "/"); } strcat(path, outputfilename); strcpy(path, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(path), "EDF files (*.edf *.EDF)").toLocal8Bit().data()); if(!strcmp(path, "")) { fclose(inputfile); free(logbuf); pushButton1->setEnabled(true); return; } get_directory_from_path(recent_savedir, path, MAX_PATH_LENGTH); outputfile = fopen(path, "wb"); if(outputfile==NULL) { snprintf(txt_string, 2048, "Error, can not open file %s for writing.\n", path); textEdit1->append(QString::fromLocal8Bit(txt_string)); fclose(inputfile); free(logbuf); pushButton1->setEnabled(true); return; } fprintf(outputfile, "0 "); i = fprintf(outputfile, "%05i %c %s %s%s%s", patientcode, gender, birthdate, patientname, handedness, weight); for(; i<80; i++) { fputc(' ', outputfile); } i = fprintf(outputfile, "Startdate %02i-%s-%04i %05i%02i X %s", atoi(date), month, year, patientcode, seq_nr, equipment); for(; i<80; i++) { fputc(' ', outputfile); } if(fwrite(date, 8, 1, outputfile)!=1) { textEdit1->append("Write error.\n"); fclose(inputfile); fclose(outputfile); free(logbuf); pushButton1->setEnabled(true); return; } if(fwrite(time, 8, 1, outputfile)!=1) { textEdit1->append("Write error.\n"); fclose(inputfile); fclose(outputfile); free(logbuf); pushButton1->setEnabled(true); return; } fprintf(outputfile, "%-8i", (256 * (channels + 2))); fprintf(outputfile, "EDF+C "); fprintf(outputfile, "%-8u", data_records); if(samplefrequency%10) { fprintf(outputfile, "1 "); } else { fprintf(outputfile, "0.1 "); } fprintf(outputfile, "%-4i", channels + 1); for(i=0; iappend("Write error.\n"); fclose(inputfile); fclose(outputfile); free(logbuf); pushButton1->setEnabled(true); return; } } else { if(fwrite(scratchpad, 16, 1, outputfile)!=1) { textEdit1->append("Write error.\n"); fclose(inputfile); fclose(outputfile); free(logbuf); pushButton1->setEnabled(true); return; } } } if(fwrite("EDF Annotations ", 16, 1, outputfile)!=1) { textEdit1->append("Write error.\n"); fclose(inputfile); fclose(outputfile); free(logbuf); pushButton1->setEnabled(true); return; } for(i=0; i<(80*(channels+1)); i++) { fputc(' ', outputfile); } for(i=0; ibufsize) { bufsize = record_size; } buf = (char *)calloc(1, bufsize); if(buf==NULL) { textEdit1->append("Malloc error. (buf)\n"); fclose(inputfile); fclose(outputfile); free(logbuf); pushButton1->setEnabled(true); return; } max_buf_records = bufsize / record_size; fseeko(inputfile, (long long)(hdrsize), SEEK_SET); while(data_records) { if(data_records>max_buf_records) records_in_buf = max_buf_records; else records_in_buf = data_records; for(i=0; i9) { deci_seconds = 0; seconds++; } } p[len++] = 20; p[len++] = 20; if(annots_writtenappend("Write error.\n"); fclose(inputfile); fclose(outputfile); free(buf); free(logbuf); pushButton1->setEnabled(true); return; } data_records -= records_in_buf; } free(logbuf); free(buf); fclose(inputfile); fclose(outputfile); snprintf(txt_string, 2048, "Done, your EDF+ file is %s\n", path); textEdit1->append(QString::fromLocal8Bit(txt_string)); pushButton1->setEnabled(true); } int UI_EMSA2EDFwindow::get_string(char *str, FILE *file, int offset, int maxlen) { int len; if(maxlen<1) { str[0] = 0; return(0); } fseeko(file, (long long)(offset), SEEK_SET); len = fgetc(file); if(len==EOF) { str[0] = 0; return(0); } if(len>maxlen) { len = maxlen; } if(fread(str, len, 1, file)!=1) { str[0] = 0; return(0); } str[len] = 0; return(len); } edfbrowser_157_source/PaxHeaders.7921/check_for_updates.h0000644000000000000000000000013212646460742020507 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/check_for_updates.h0000644000175000001440000000277712646460742021065 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef CHECKFORUPDATES_H #define CHECKFORUPDATES_H #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "utils.h" class Check_for_updates : public QObject { Q_OBJECT public: Check_for_updates(); private: QNetworkAccessManager *manager; private slots: void replyFinished(); }; #endif edfbrowser_157_source/PaxHeaders.7921/edf_annotations_new.cpp0000644000000000000000000000013212646460742021416 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.246246736 30 ctime=1452958178.247246733 edfbrowser_157_source/edf_annotations_new.cpp0000644000175000001440000004730112646460742021764 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "edf_annotations.h" int EDF_annotations::get_annotations(int file_num, struct edfhdrblock *edf_hdr, struct annotationblock **annotslist, int read_nk_trigger_signal) { int i, j, k, p, r=0, n, edfsignals, datarecords, recordsize, discontinuous, *annot_ch, nr_annot_chns, max, onset, duration, duration_start, zero, max_tal_ln, error, annots_in_record, annots_in_tal, samplesize=2, nk_triggers_smpls=0, nk_triggers_bufoffset=0, nk_triggers_enabled=0, nk_triggers_channel=0, nk_triggers_cnt=0, sf, progress_steps, annotlist_sz=0, annots_in_file=0; unsigned short nk_triggerfields=0, nk_old_triggerfields=0; char *scratchpad, *cnv_buf, *time_in_txt, *duration_in_txt, nk_triggerlabel[16][32]; long long data_record_duration, elapsedtime, time_tmp=0LL, nk_trigger_sample_duration=0LL; FILE *inputfile; struct edfparamblock *edfparam; struct annotationblock *new_annotation=NULL, *temp_annotation, *malloc_list; inputfile = edf_hdr->file_hdl; edfsignals = edf_hdr->edfsignals; recordsize = edf_hdr->recordsize; edfparam = edf_hdr->edfparam; nr_annot_chns = edf_hdr->nr_annot_chns; datarecords = edf_hdr->datarecords; data_record_duration = edf_hdr->long_data_record_duration; discontinuous = edf_hdr->discontinuous; annot_ch = edf_hdr->annot_ch; if(edf_hdr->edfplus) { samplesize = 2; } if(edf_hdr->bdfplus) { samplesize = 3; } if((edf_hdr->edfplus) && (read_nk_trigger_signal)) { if(data_record_duration == 1000000LL) { if(check_device(edf_hdr->plus_equipment) == 0) { for(i=0; iedfparam[i].smp_per_record; error = 1; switch(sf) { case 10 : error = 0; break; case 20 : error = 0; break; case 50 : error = 0; break; case 100 : error = 0; break; } for(j=0; jedfparam[j].smp_per_record != sf) { if(!edf_hdr->edfparam[j].annotation) { error = 1; } } } if(edf_hdr->nr_annot_chns != 1) error = 1; if(!error) { nk_triggers_channel = i; nk_triggers_bufoffset = edfparam[nk_triggers_channel].buf_offset; nk_triggers_smpls = edfparam[nk_triggers_channel].smp_per_record; nk_trigger_sample_duration = data_record_duration / (long long)nk_triggers_smpls; strcpy(nk_triggerlabel[0], "CAL mode"); strcpy(nk_triggerlabel[1], "RESET condition"); strcpy(nk_triggerlabel[2], "External mark"); strcpy(nk_triggerlabel[3], "Photo/HV mark"); strcpy(nk_triggerlabel[4], "Remote mark"); strcpy(nk_triggerlabel[5], "HV mark"); strcpy(nk_triggerlabel[6], "DC trigger 9"); strcpy(nk_triggerlabel[7], "DC trigger 10"); strcpy(nk_triggerlabel[8], "DC trigger 11"); strcpy(nk_triggerlabel[9], "DC trigger 12"); strcpy(nk_triggerlabel[10], "DC trigger 13"); strcpy(nk_triggerlabel[11], "DC trigger 14"); strcpy(nk_triggerlabel[12], "DC trigger 15"); strcpy(nk_triggerlabel[13], "DC trigger 16"); strcpy(nk_triggerlabel[14], ""); strcpy(nk_triggerlabel[15], ""); nk_triggers_enabled = 1; edf_hdr->genuine_nk = 1; break; } } } } } } cnv_buf = (char *)calloc(1, recordsize); if(cnv_buf==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Memory allocation error occurred when trying to read annotations.\n(cnv_buf)"); messagewindow.exec(); return(1); } max_tal_ln = 0; for(i=0; iprocessEvents(); if(progress.wasCanceled() == true) { edf_hdr->annots_not_read = 1; free(cnv_buf); free(scratchpad); free(time_in_txt); free(duration_in_txt); return(11); } } if(fread(cnv_buf, recordsize, 1, inputfile)!=1) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading inputfile annotations. (fread())"); messagewindow.exec(); free(cnv_buf); free(scratchpad); free(time_in_txt); free(duration_in_txt); return(2); } /************** process annotationsignals (if any) **************/ error = 0; for(r=0; r=TIME_DIMENSION) { error = 2; goto END; } else { edf_hdr->starttime_offset = time_tmp; } } elapsedtime = time_tmp; error = 0; break; } } } } for(k=0; k1) { error = 34; goto END; } zero = 0; if((scratchpad[n]==20)||(scratchpad[n]==21)) { if(scratchpad[n]==21) { if(duration||duration_start||onset||annots_in_tal) { /* it's not allowed to have multiple duration fields */ error = 35; /* in one TAL or to have a duration field which is */ goto END; /* not immediately behind the onsetfield */ } duration_start = 1; } if((scratchpad[n]==20)&&onset&&(!duration_start)) { if(r||annots_in_record) { if(n >= 0) { if(annots_in_file >= annotlist_sz) { malloc_list = (struct annotationblock *)realloc(*annotslist, sizeof(struct annotationblock) * (annotlist_sz + EDF_ANNOTS_MEMBLOCKSZ)); if(malloc_list == NULL) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred while reading annotations."); messagewindow.exec(); free(cnv_buf); free(scratchpad); free(time_in_txt); free(duration_in_txt); return(1); } memset(malloc_list + (sizeof(struct annotationblock) * annotlist_sz), 0, EDF_ANNOTS_MEMBLOCKSZ); annotlist_sz += EDF_ANNOTS_MEMBLOCKSZ; *annotslist = malloc_list; } ((*annotslist) + annots_in_file)->next_annotation = NULL; ((*annotslist) + annots_in_file)->file_num = file_num; ((*annotslist) + annots_in_file)->annotation[0] = 0; if(duration) strcpy(((*annotslist) + annots_in_file)->duration, duration_in_txt); else ((*annotslist) + annots_in_file)->duration[0] = 0; for(j=0; jannotation[j] = scratchpad[j]; } ((*annotslist) + annots_in_file)->annotation[j] = 0; ((*annotslist) + annots_in_file)->file_num = edf_hdr->file_num; ((*annotslist) + annots_in_file)->onset = get_long_time(time_in_txt); if(annots_in_file > 0) { ((*annotslist) + annots_in_file)->former_annotation = (*annotslist) + annots_in_file - 1; ((*annotslist) + annots_in_file - 1)->next_annotation = (*annotslist) + 1; } else { ((*annotslist) + annots_in_file)->former_annotation = NULL; } annots_in_file++; } } annots_in_tal++; annots_in_record++; n = 0; continue; } if(!onset) { scratchpad[n] = 0; if(is_onset_number(scratchpad)) { error = 36; goto END; } onset = 1; n = 0; strcpy(time_in_txt, scratchpad); continue; } if(duration_start) { scratchpad[n] = 0; if(is_duration_number(scratchpad)) { error = 37; goto END; } for(j=0; j126)) { duration_in_txt[j] = '.'; } } duration_in_txt[j] = 0; duration = 1; duration_start = 0; n = 0; continue; } } n++; } END: /****************** end ************************/ if(error) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not read annotations because there is an EDF or BDF incompatibility in this file.\n" "For more information, run the EDF/BDF compatibility checker in the Tools menu."); messagewindow.exec(); free(cnv_buf); free(scratchpad); free(time_in_txt); free(duration_in_txt); return(9); } } /************** process NK triggers ****************/ if(nk_triggers_enabled) { if(nk_triggers_cnt < 100000) { for(k=0; kfile_num = edf_hdr->file_num; new_annotation->next_annotation = NULL; new_annotation->file_num = file_num; strcpy(new_annotation->annotation, nk_triggerlabel[j]); new_annotation->onset = ((long long)i * data_record_duration) + ((long long)k * nk_trigger_sample_duration); new_annotation->onset += edf_hdr->starttime_offset; new_annotation->ident = (1 << ANNOT_ID_NK_TRIGGER); if(*annotslist!=NULL) { temp_annotation = *annotslist; while(temp_annotation->next_annotation) temp_annotation = temp_annotation->next_annotation; new_annotation->former_annotation = temp_annotation; temp_annotation->next_annotation = new_annotation; } else { new_annotation->former_annotation = NULL; *annotslist = new_annotation; } } } nk_old_triggerfields = nk_triggerfields; } } edf_hdr->nk_triggers_read = 1; } } edfplus_annotation_sort(&annotslist[file_num]); progress.reset(); free(cnv_buf); free(scratchpad); free(time_in_txt); free(duration_in_txt); return(0); } int EDF_annotations::is_duration_number(char *str) { int i, l, hasdot = 0; l = strlen(str); if(!l) return(1); if((str[0] == '.')||(str[l-1] == '.')) return(1); for(i=0; i57)) return(1); } } return(0); } int EDF_annotations::is_onset_number(char *str) { int i, l, hasdot = 0; l = strlen(str); if(l<2) return(1); if((str[0]!='+')&&(str[0]!='-')) return(1); if((str[1] == '.')||(str[l-1] == '.')) return(1); for(i=1; i57)) return(1); } } return(0); } long long EDF_annotations::get_long_time(char *str) { int i, len, hasdot=0, dotposition=0; long long value=0, radix; str = str + 1; len = strlen(str); for(i=0; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } radix = TIME_DIMENSION / 10; for(i=dotposition+1; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } } if(str[-1]=='-') value = -value; return(value); } int EDF_annotations::check_device(char *str) { int error = 1; if(strlen(str) < 29) return(1); if(!strncmp(str, "Nihon Kohden EEG-1100A V01.00", 29)) error = 0; if(!strncmp(str, "Nihon Kohden EEG-1100B V01.00", 29)) error = 0; if(!strncmp(str, "Nihon Kohden EEG-1100C V01.00", 29)) error = 0; if(!strncmp(str, "Nihon Kohden QI-403A V01.00", 29)) error = 0; if(!strncmp(str, "Nihon Kohden QI-403A V02.00", 29)) error = 0; if(!strncmp(str, "Nihon Kohden EEG-2100 V01.00", 29)) error = 0; if(!strncmp(str, "Nihon Kohden EEG-2100 V02.00", 29)) error = 0; if(!strncmp(str, "Nihon Kohden DAE-2100D V01.30", 29)) error = 0; if(!strncmp(str, "Nihon Kohden DAE-2100D V02.00", 29)) error = 0; // if(!strncmp(str, "Nihon Kohden EEG-1200A V01.00", 29)) error = 0; return(error); } edfbrowser_157_source/PaxHeaders.7921/z_score_dialog.cpp0000644000000000000000000000013212646460742020355 xustar0030 mtime=1452958178.249246726 30 atime=1452958178.249246726 30 ctime=1452958178.249246726 edfbrowser_157_source/z_score_dialog.cpp0000644000175000001440000011120412646460742020715 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "z_score_dialog.h" #define ZSCORE_EPOCH_LEN 2 #define ZSCORE_F1 3.0 #define ZSCORE_F3 12.0 #define ZSCORE_F4 25.0 #define ZSCORE_ERRORLEVEL 5.0 UI_ZScoreWindow::UI_ZScoreWindow(QWidget *w_parent, UI_ZScoreWindow **w_zscoredialog, int w_zscore_dialognumber, int w_signalnr) { zscore_epoch_buf = NULL; zscore_page_buf = NULL; zscore_sleepstage_buf = NULL; crossoverfreq = 7.0; z_threshold = 0.0; zscore_page_len = 15; zscore_pages = 0; epoch_cntr = 0; zscore_wake = 1; mainwindow = (UI_Mainwindow *)w_parent; zscore_dialognumber = w_zscore_dialognumber; signalnr = w_signalnr; zscoredialog = w_zscoredialog; zscore_dialog_is_destroyed = 0; zscore_dialog = new QDialog(); zscore_dialog->setMinimumSize(600, 550); zscore_dialog->setWindowTitle("Z-EEG"); zscore_dialog->setModal(false); zscore_dialog->setAttribute(Qt::WA_DeleteOnClose, true); zscore_dialog->setWindowIcon(QIcon(":/images/edf.png")); zscore_dialog->setSizeGripEnabled(true); zscore_dialog->setWindowFlags(Qt::Window | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); crossoverbinLabel = new QLabel; crossoverbinLabel->setMinimumSize(100, 25); crossoverbinLabel->setMaximumSize(100, 25); crossoverbinLabel->setText("Cross-over"); crossoverSpinbox = new QDoubleSpinBox; crossoverSpinbox->setMinimumSize(100, 25); crossoverSpinbox->setMaximumSize(100, 25); crossoverSpinbox->setRange(5.0, 9.5); crossoverSpinbox->setDecimals(1); crossoverSpinbox->setSingleStep(0.5); crossoverSpinbox->setSuffix(" Hz"); crossoverSpinbox->setValue(mainwindow->z_score_var.crossoverfreq); crossoverSpinbox->setToolTip("Threshold between low-frequency and high-frequency"); thresholdLabel = new QLabel; thresholdLabel->setMinimumSize(100, 25); thresholdLabel->setMaximumSize(100, 25); thresholdLabel->setText("Z-threshold"); thresholdSpinbox = new QDoubleSpinBox; thresholdSpinbox->setMinimumSize(100, 25); thresholdSpinbox->setMaximumSize(100, 25); thresholdSpinbox->setRange(-0.5, 0.5); thresholdSpinbox->setDecimals(2); thresholdSpinbox->setSingleStep(0.05); thresholdSpinbox->setValue(mainwindow->z_score_var.z_threshold); pagelenLabel = new QLabel; pagelenLabel->setMinimumSize(100, 25); pagelenLabel->setMaximumSize(100, 25); pagelenLabel->setText("Z-page"); pagelenSpinbox = new QSpinBox; pagelenSpinbox->setMinimumSize(100, 25); pagelenSpinbox->setMaximumSize(100, 25); pagelenSpinbox->setRange(10, 60); pagelenSpinbox->setSingleStep(2); pagelenSpinbox->setSuffix(" sec"); pagelenSpinbox->setValue(mainwindow->z_score_var.zscore_page_len); // errordetectionLabel = new QLabel; // errordetectionLabel->setMinimumSize(100, 25); // errordetectionLabel->setMaximumSize(100, 25); // errordetectionLabel->setText("Error detection"); // // errordetectionSpinbox = new QSpinBox; // errordetectionSpinbox->setMinimumSize(100, 25); // errordetectionSpinbox->setMaximumSize(100, 25); // errordetectionSpinbox->setRange(50, 100); // errordetectionSpinbox->setSingleStep(1); // errordetectionSpinbox->setSuffix(" \%"); // errordetectionSpinbox->setValue(mainwindow->z_score_var.zscore_error_detection); // errordetectionSpinbox->setToolTip("Enter value of \% total power when any of the four\n" // "standard bandwidths: delta, theta, alpha, beta\n" // "exceeds this percent of total power.\n" // "This value will be evaluated when annotating."); hysteresisLabel = new QLabel; hysteresisLabel->setMinimumSize(100, 25); hysteresisLabel->setMaximumSize(100, 25); hysteresisLabel->setText("Sleep/Wake\ndifferentiation"); hysteresisSpinbox = new QDoubleSpinBox; hysteresisSpinbox->setMinimumSize(100, 25); hysteresisSpinbox->setMaximumSize(100, 25); hysteresisSpinbox->setDecimals(2); hysteresisSpinbox->setRange(0.0, 0.25); hysteresisSpinbox->setSingleStep(0.01); hysteresisSpinbox->setValue(mainwindow->z_score_var.z_hysteresis); hysteresisSpinbox->setToolTip("Hysteresis applied to the z-threshold."); curve1 = new SignalCurve; curve1->setSignalColor(Qt::green); curve1->setBackgroundColor(Qt::black); curve1->setRasterColor(Qt::gray); curve1->setCrosshairColor(Qt::red); curve1->setTraceWidth(0); curve1->setDashBoardEnabled(false); curve1->setUpsidedownEnabled(true); StartButton = new QPushButton; StartButton->setMinimumSize(100, 25); StartButton->setMaximumSize(100, 25); StartButton->setText("Calculate"); StartButton->setToolTip("Plot the Z-ratio / Z-pages"); jumpButton = new QPushButton; jumpButton->setMinimumSize(100, 25); jumpButton->setMaximumSize(100, 25); jumpButton->setText("Jump"); jumpButton->setToolTip("Jump to cursor-position"); get_annotButton = new QPushButton; get_annotButton->setMinimumSize(100, 25); get_annotButton->setMaximumSize(100, 25); get_annotButton->setText("Annotate"); get_annotButton->setToolTip("Create annotations from the Z-EEG"); defaultButton = new QPushButton; defaultButton->setMinimumSize(100, 25); defaultButton->setMaximumSize(100, 25); defaultButton->setText("Default"); defaultButton->setToolTip("Set parameters to default values"); CloseButton = new QPushButton; CloseButton->setMinimumSize(100, 25); CloseButton->setMaximumSize(100, 25); CloseButton->setText("Close"); CloseButton->setToolTip("Close this window"); addTraceButton = new QPushButton; addTraceButton->setMinimumSize(100, 25); addTraceButton->setMaximumSize(100, 25); addTraceButton->setText("Add Trace"); addTraceButton->setToolTip("Add this Z-ratio trace to the mainwindow"); epochRadioButton = new QRadioButton; epochRadioButton->setMinimumSize(100, 25); epochRadioButton->setMaximumSize(100, 25); epochRadioButton->setText("Epochs"); pageRadioButton = new QRadioButton; pageRadioButton->setMinimumSize(100, 25); pageRadioButton->setMaximumSize(100, 25); pageRadioButton->setText("Pages"); wakesleepRadioButton = new QRadioButton; wakesleepRadioButton->setMinimumSize(100, 25); wakesleepRadioButton->setMaximumSize(100, 25); wakesleepRadioButton->setText("Sleep/Wake"); pageRadioButton->setChecked(true); plot_type = 1; hlayout1 = new QHBoxLayout; hlayout1->setSpacing(20); hlayout1->addWidget(crossoverbinLabel); hlayout1->addWidget(crossoverSpinbox); hlayout1->addStretch(100); hlayout1->addWidget(epochRadioButton); hlayout1->addStretch(100); hlayout1->addWidget(StartButton); hlayout2 = new QHBoxLayout; hlayout2->setSpacing(20); hlayout2->addWidget(thresholdLabel); hlayout2->addWidget(thresholdSpinbox); hlayout2->addStretch(100); hlayout2->addWidget(pageRadioButton); hlayout2->addStretch(100); hlayout2->addWidget(jumpButton); hlayout3 = new QHBoxLayout; hlayout3->setSpacing(20); hlayout3->addWidget(pagelenLabel); hlayout3->addWidget(pagelenSpinbox); hlayout3->addStretch(100); hlayout3->addWidget(wakesleepRadioButton); hlayout3->addStretch(100); hlayout3->addWidget(get_annotButton); // hlayout4 = new QHBoxLayout; // hlayout4->setSpacing(20); // hlayout4->addWidget(errordetectionLabel); // hlayout4->addWidget(errordetectionSpinbox); // hlayout4->addStretch(100); hlayout4 = new QHBoxLayout; hlayout4->setSpacing(20); hlayout4->addStretch(100); hlayout4->addWidget(addTraceButton); hlayout5 = new QHBoxLayout; hlayout5->setSpacing(20); hlayout5->addWidget(hysteresisLabel); hlayout5->addWidget(hysteresisSpinbox); hlayout5->addStretch(100); hlayout5->addWidget(defaultButton); hlayout5->addStretch(100); hlayout5->addWidget(CloseButton); vlayout2 = new QVBoxLayout; vlayout2->setSpacing(20); vlayout2->addLayout(hlayout1); vlayout2->addLayout(hlayout2); vlayout2->addLayout(hlayout3); vlayout2->addLayout(hlayout4); vlayout2->addLayout(hlayout5); vlayout3 = new QVBoxLayout; vlayout3->setSpacing(20); vlayout3->setContentsMargins(20, 20, 20, 20); vlayout3->addWidget(curve1); vlayout3->addLayout(vlayout2); zscore_dialog->setLayout(vlayout3); shift_page_left_Act = new QAction(this); shift_page_left_Act->setShortcut(QKeySequence::MoveToPreviousChar); connect(shift_page_left_Act, SIGNAL(triggered()), this, SLOT(shift_page_left())); zscore_dialog->addAction(shift_page_left_Act); shift_page_right_Act = new QAction(this); shift_page_right_Act->setShortcut(QKeySequence::MoveToNextChar); connect(shift_page_right_Act, SIGNAL(triggered()), this, SLOT(shift_page_right())); zscore_dialog->addAction(shift_page_right_Act); QObject::connect(CloseButton, SIGNAL(clicked()), zscore_dialog, SLOT(close())); QObject::connect(StartButton, SIGNAL(clicked()), this, SLOT(startButtonClicked())); QObject::connect(get_annotButton, SIGNAL(clicked()), this, SLOT(get_annotationsButtonClicked())); QObject::connect(jumpButton, SIGNAL(clicked()), this, SLOT(jumpButtonClicked())); QObject::connect(zscore_dialog, SIGNAL(destroyed(QObject *)), this, SLOT(ZscoreDialogDestroyed(QObject *))); QObject::connect(epochRadioButton, SIGNAL(clicked(bool)), this, SLOT(RadioButtonsClicked(bool))); QObject::connect(pageRadioButton, SIGNAL(clicked(bool)), this, SLOT(RadioButtonsClicked(bool))); QObject::connect(wakesleepRadioButton, SIGNAL(clicked(bool)), this, SLOT(RadioButtonsClicked(bool))); QObject::connect(defaultButton, SIGNAL(clicked()), this, SLOT(defaultButtonClicked())); QObject::connect(curve1, SIGNAL(markerHasMoved()), this, SLOT(markersMoved())); QObject::connect(addTraceButton, SIGNAL(clicked()), this, SLOT(addTraceButtonClicked())); zscore_dialog->show(); } UI_ZScoreWindow::~UI_ZScoreWindow() { if(!zscore_dialog_is_destroyed) { zscore_dialog->close(); } if(zscore_epoch_buf != NULL) { free(zscore_epoch_buf); } if(zscore_page_buf != NULL) { free(zscore_page_buf); } if(zscore_sleepstage_buf != NULL) { free(zscore_sleepstage_buf); } zscoredialog[zscore_dialognumber] = NULL; } void UI_ZScoreWindow::ZscoreDialogDestroyed(QObject *) { zscore_dialog_is_destroyed = 1; zscoredialog[zscore_dialognumber] = NULL; delete this; } void UI_ZScoreWindow::addTraceButtonClicked() { int i; struct edfhdrblock *hdr; struct signalcompblock *signalcomp, *original_signalcomp; original_signalcomp = mainwindow->signalcomp[signalnr]; hdr = original_signalcomp->edfhdr; if(original_signalcomp->ecg_filter != NULL) { return; } if(original_signalcomp->zratio_filter != NULL) { return; } signalcomp = mainwindow->create_signalcomp_copy(original_signalcomp); if(signalcomp == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Internal error: can not create a signalcomp copy."); messagewindow.exec(); return; } signalcomp->zratio_filter = create_zratio_filter(hdr->edfparam[signalcomp->edfsignal[0]].smp_per_record, hdr->long_data_record_duration, crossoverSpinbox->value(), signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue); if(signalcomp->zratio_filter == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not create a Z-ratio-filter, malloc() error?"); messagewindow.exec(); free(signalcomp); return; } strcpy(signalcomp->signallabel_bu, signalcomp->signallabel); signalcomp->signallabellen_bu = signalcomp->signallabellen; strcpy(signalcomp->signallabel, "Z-ratio "); strcat(signalcomp->signallabel, signalcomp->signallabel_bu); signalcomp->signallabellen = strlen(signalcomp->signallabel); strcpy(signalcomp->physdimension_bu, signalcomp->physdimension); strcpy(signalcomp->physdimension, ""); signalcomp->polarity = -1; if(signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue < 0.0) { for(i=0; inum_of_signals; i++) { signalcomp->sensitivity[i] = signalcomp->edfhdr->edfparam[signalcomp->edfsignal[i]].bitvalue / -1.0 / mainwindow->pixelsizefactor; } signalcomp->voltpercm = -1.0; } else { for(i=0; inum_of_signals; i++) { signalcomp->sensitivity[i] = signalcomp->edfhdr->edfparam[signalcomp->edfsignal[i]].bitvalue / 1.0 / mainwindow->pixelsizefactor; } signalcomp->voltpercm = 1.0; } signalcomp->zratio_crossoverfreq = crossoverSpinbox->value(); signalcomp->screen_offset = 0.0; mainwindow->setup_viewbuf(); } void UI_ZScoreWindow::defaultButtonClicked() { pagelenSpinbox->setValue(30); // errordetectionSpinbox->setValue(80); thresholdSpinbox->setValue(0.0); crossoverSpinbox->setValue(7.5); hysteresisSpinbox->setValue(0.0); } void UI_ZScoreWindow::startButtonClicked() { int i, datrec_offset, total_datrecs, smpls, smp_per_record, smpls_in_epoch, dftblocksize, fft_outputbufsize, smpls_in_inputbuf, smpls_copied, epochs, f1, f2, f3, f4, power_neg_cnt, power_pos_cnt, progress_steps; double *buf, *fft_inputbuf, *fft_outputbuf, samplefreq, freqstep, power_delta, power_theta, power_alpha, power_beta, power_total, power_neg, power_pos; struct edfhdrblock *hdr; struct signalcompblock *signalcomp; crossoverfreq = crossoverSpinbox->value(); mainwindow->z_score_var.crossoverfreq = crossoverfreq; z_threshold = thresholdSpinbox->value(); mainwindow->z_score_var.z_threshold = z_threshold; zscore_page_len = pagelenSpinbox->value() / 2; mainwindow->z_score_var.zscore_page_len = zscore_page_len * 2; // zscore_error_detection = errordetectionSpinbox->value(); // mainwindow->z_score_var.zscore_error_detection = zscore_error_detection; z_hysteresis = hysteresisSpinbox->value(); mainwindow->z_score_var.z_hysteresis = z_hysteresis; z_hysteresis /= 2.0; signalcomp = mainwindow->signalcomp[signalnr]; hdr = signalcomp->edfhdr; total_datrecs = hdr->datarecords; smp_per_record = hdr->edfparam[signalcomp->edfsignal[0]].smp_per_record; dftblocksize = ((long long)smp_per_record * (ZSCORE_EPOCH_LEN * TIME_DIMENSION)) / hdr->long_data_record_duration; if(dftblocksize < (ZSCORE_EPOCH_LEN * 100)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Samplerate of selected signal is too low"); messagewindow.exec(); curve1->clear(); return; } smpls_in_epoch = dftblocksize; epochs = (hdr->datarecords * (long long)smp_per_record) / (long long)smpls_in_epoch; samplefreq = (double)smp_per_record / ((double)hdr->long_data_record_duration / TIME_DIMENSION); if(samplefreq < 99.9999999) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Samplefrequency of the selected signal must be at least 100 Hz."); messagewindow.exec(); curve1->clear(); return; } fft_outputbufsize = dftblocksize / 2; freqstep = samplefreq / (double)dftblocksize; if(freqstep > 1.0001) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Frequency bin of FFT is more than 1 Hz."); messagewindow.exec(); curve1->clear(); return; } f2 = crossoverfreq / freqstep; f1 = ZSCORE_F1 / freqstep; f3 = ZSCORE_F3 / freqstep; f4 = ZSCORE_F4 / freqstep; fft_inputbuf = (double *)malloc(sizeof(double) * dftblocksize); if(fft_inputbuf == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); messagewindow.exec(); curve1->clear(); return; } fft_outputbuf = (double *)calloc(1, sizeof(double) * fft_outputbufsize); if(fft_outputbuf == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); messagewindow.exec(); curve1->clear(); free(fft_inputbuf); return; } if(zscore_epoch_buf != NULL) { free(zscore_epoch_buf); } zscore_epoch_buf = (double *)calloc(1, sizeof(double) * epochs); if(zscore_epoch_buf == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); messagewindow.exec(); curve1->clear(); free(fft_inputbuf); free(fft_outputbuf); return; } if(zscore_page_buf != NULL) { free(zscore_page_buf); } zscore_page_buf = (double *)calloc(1, sizeof(double) * ((epochs / zscore_page_len) + 1)); if(zscore_page_buf == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); messagewindow.exec(); curve1->clear(); free(fft_inputbuf); free(fft_outputbuf); return; } if(zscore_sleepstage_buf != NULL) { free(zscore_sleepstage_buf); } zscore_sleepstage_buf = (int *)calloc(1, sizeof(int) * ((epochs / zscore_page_len) + 1)); if(zscore_sleepstage_buf == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); messagewindow.exec(); curve1->clear(); free(fft_inputbuf); free(fft_outputbuf); return; } // printf("epochs / zscore_page_len is %i\n", // epochs / zscore_page_len); kiss_fftr_cfg cfg; kiss_fft_cpx *kiss_fftbuf; kiss_fftbuf = (kiss_fft_cpx *)malloc((fft_outputbufsize + 1) * sizeof(kiss_fft_cpx)); if(kiss_fftbuf == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); messagewindow.exec(); curve1->clear(); free(fft_inputbuf); free(fft_outputbuf); return; } cfg = kiss_fftr_alloc(dftblocksize, 0, NULL, NULL); FilteredBlockReadClass blockread; buf = blockread.init_signalcomp(signalcomp, 1, 0); if(buf == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Internal error: init_signalcomp()"); messagewindow.exec(); curve1->clear(); free(fft_inputbuf); free(fft_outputbuf); free(cfg); free(kiss_fftbuf); return; } QProgressDialog progress("Processing ...", "Abort", 0, (int)hdr->datarecords, zscore_dialog); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); progress_steps = total_datrecs / 100; if(progress_steps < 1) { progress_steps = 1; } if(progress_steps > 50) { progress_steps = 50; } // printf("total_datrecs is %i\n" // "smp_per_record is %i\n" // "dftblocksize is %i\n" // "smpls_in_epoch is %i\n" // "epochs is %i\n" // "samplefreq is %f\n" // "fft_outputbufsize is %i\n" // "freqstep is %f\n" // "f1 is %i\n" // "f2 is %i\n" // "f3 is %i\n" // "f4 is %i\n" // "z_hysteresis is %f\n", // total_datrecs, // smp_per_record, // dftblocksize, // smpls_in_epoch, // epochs, // samplefreq, // fft_outputbufsize, // freqstep, // f1, // f2, // f3, // f4, // z_hysteresis); epoch_cntr = 0; smpls_in_inputbuf = 0; // FILE *test_file1 = fopen("testfile1.dat", "wb"); // if(test_file1 == NULL) // { // printf("error opening file\n"); // return; // } // // FILE *test_file2 = fopen("testfile2.dat", "wb"); // if(test_file2 == NULL) // { // printf("error opening file\n"); // return; // } for(datrec_offset=0; datrec_offset < total_datrecs; datrec_offset++) // for(datrec_offset=0; datrec_offset < 2; datrec_offset++) { // printf("\ndatrec_offset is %i\n", datrec_offset); // printf("smpls_in_inputbuf is %i\n", smpls_in_inputbuf); if(!(datrec_offset % progress_steps)) { progress.setValue(datrec_offset); qApp->processEvents(); if(progress.wasCanceled() == true) { break; } } if(blockread.process_signalcomp(datrec_offset)) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read-error occurred."); messagewindow.exec(); curve1->clear(); free(fft_inputbuf); free(fft_outputbuf); free(cfg); free(kiss_fftbuf); return; } smpls = blockread.samples_in_buf(); // fwrite(buf, smpls * sizeof(double), 1, test_file1); // printf("smpls is %i\n", smpls); // for(k=0; k 0) { // printf("while(smpls > 0)\n"); if(smpls < (dftblocksize - smpls_in_inputbuf)) { memcpy(fft_inputbuf + smpls_in_inputbuf, buf, smpls * sizeof(double)); // for(j=0; j 0) && (i < f1)) { power_delta += fft_outputbuf[i]; } if((i >= f1) && (i < f2)) { power_theta += fft_outputbuf[i]; } if((i >= f2) && (i < f3)) { power_alpha += fft_outputbuf[i]; } if((i >= f3) && (i <= f4)) { power_beta += fft_outputbuf[i]; } power_total += fft_outputbuf[i]; } if(power_total <= 0.0) { zscore_epoch_buf[epoch_cntr++] = 0.0; } else { zscore_epoch_buf[epoch_cntr++] = ((power_delta + power_theta) - (power_alpha + power_beta)) / power_total; } // if(epoch_cntr < 3) // { // printf("zscore_epoch_buf[%i] is %f\n", epoch_cntr - 1, zscore_epoch_buf[epoch_cntr - 1]); // printf("power_delta is %f\n" // "power_theta is %f\n" // "power_alpha is %f\n" // "power_beta is %f\n" // "power_total is %f\n\n", // power_delta, power_theta, power_alpha, power_beta, power_total); // } if(epoch_cntr >= epochs) { break; } } if(epoch_cntr >= epochs) { break; } } power_pos = 0.0; power_neg = 0.0; power_pos_cnt = 0; power_neg_cnt = 0; zscore_pages = 0; for(i=0; i= power_pos_cnt) { zscore_page_buf[zscore_pages] = power_neg; zscore_sleepstage_buf[zscore_pages] = 0; } else { zscore_page_buf[zscore_pages] = power_pos; zscore_sleepstage_buf[zscore_pages] = 1; } zscore_pages++; power_pos = 0.0; power_neg = 0.0; power_pos_cnt = 0; power_neg_cnt = 0; } if(zscore_epoch_buf[i] < ZSCORE_ERRORLEVEL) { if(zscore_pages > 0) { if(zscore_sleepstage_buf[zscore_pages - 1] == 0) { // printf("if(zscore_sleepstage_buf[zscore_pages - 1] == 0) : %f < %f + %f\n", // zscore_epoch_buf[i], z_threshold, z_hysteresis); if(zscore_epoch_buf[i] < (z_threshold + z_hysteresis)) { power_neg += zscore_epoch_buf[i]; power_neg_cnt++; } else { power_pos += zscore_epoch_buf[i]; power_pos_cnt++; } } else { // printf("else : %f < %f + %f\n", // zscore_epoch_buf[i], z_threshold, z_hysteresis); if(zscore_epoch_buf[i] < (z_threshold - z_hysteresis)) { power_neg += zscore_epoch_buf[i]; power_neg_cnt++; } else { power_pos += zscore_epoch_buf[i]; power_pos_cnt++; } } } else { if(zscore_epoch_buf[i] < z_threshold) { power_neg += zscore_epoch_buf[i]; power_neg_cnt++; } else { power_pos += zscore_epoch_buf[i]; power_pos_cnt++; } } } } // printf("epoch_cntr is %i zscore_pages is %i\n", // epoch_cntr, zscore_pages); // Delta: 0.5 - 2.0 Hz // Theta: 2.5 - 7.0 Hz // Alpha: 7.5 - 11.5 Hz // Beta: 12.0 - 25.0 Hz // Stage Z ratio (mean +-SD) // ---------------------------- // Wake -0.181 +- .055 // REM 0.156 +- .043 // 1 0.066 +- .101 // 2 0.207 +- .067 // 3 0.443 +- .034 // 4 0.527 +- .039 // ZRatio = ((Delta + Theta) - (Alpha + Beta)) / (Delta + Theta + Alpha + Beta) progress.reset(); RadioButtonsClicked(true); free(fft_inputbuf); free(fft_outputbuf); free(cfg); free(kiss_fftbuf); mainwindow->setup_viewbuf(); // printf("epoch_cntr is %i epochs is %i\n", epoch_cntr, epochs); // fclose(test_file1); // fclose(test_file2); } void UI_ZScoreWindow::get_annotationsButtonClicked() { int i, awake = 1, filenum, marker_start, marker_end; struct annotationblock *annotation; if((epoch_cntr < 2) || (zscore_pages < 1)) { return; } marker_start = curve1->getMarker1Position() * zscore_pages; if(marker_start < 0) { marker_start = 0; } marker_end = curve1->getMarker2Position() * zscore_pages; if(marker_end > zscore_pages) { marker_end = zscore_pages; } filenum = mainwindow->signalcomp[signalnr]->edfhdr->file_num; for(i=0; i= marker_start) { annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); if(annotation == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred (annotation)."); messagewindow.exec(); return; } annotation->onset = i * zscore_page_len * 2LL * TIME_DIMENSION; if(awake) { strcpy(annotation->annotation, "Wake"); } else { strcpy(annotation->annotation, "Sleep"); } edfplus_annotation_add_item(&mainwindow->annotationlist[filenum], annotation); } } } if(mainwindow->annotations_dock[filenum] == NULL) { mainwindow->annotations_dock[filenum] = new UI_Annotationswindow(filenum, mainwindow); mainwindow->addDockWidget(Qt::RightDockWidgetArea, mainwindow->annotations_dock[filenum]->docklist, Qt::Vertical); if(!mainwindow->annotationlist[filenum]) { mainwindow->annotations_dock[filenum]->docklist->hide(); } } if(mainwindow->annotationlist[filenum]) { mainwindow->annotations_dock[filenum]->docklist->show(); mainwindow->annotations_edited = 1; mainwindow->annotations_dock[filenum]->updateList(); mainwindow->save_act->setEnabled(true); } mainwindow->maincurve->update(); } void UI_ZScoreWindow::RadioButtonsClicked(bool) { int i, marker_start, marker_end, regression_samples, sleep_cnt, sleep_pct; double b0, b1, sum_xy=0.0, sum_x2=0.0, avg_x=0.0, avg_y=0.0, shiftfactor=2.0; char str[1024]; if(epochRadioButton->isChecked() == true) { plot_type = 0; if((epoch_cntr < 2) || (zscore_pages < 1)) { return; } marker_start = curve1->getMarker1Position() * epoch_cntr; if(marker_start < 0) { marker_start = 0; } marker_end = curve1->getMarker2Position() * epoch_cntr; if(marker_end > epoch_cntr) { marker_end = epoch_cntr; } regression_samples = marker_end - marker_start; if(regression_samples < 60) { return; } for(i=0; isignalcomp[signalnr]->signallabel, b1, b0); curve1->drawCurve(zscore_epoch_buf, epoch_cntr, 1.0, -1.0); curve1->setH_RulerValues(0, epoch_cntr); curve1->setLowerLabel("Epochs"); curve1->setV_label("Z ratio"); curve1->setUpperLabel1(str); curve1->drawLine(marker_start, b0 + b1, marker_end, b0 + (b1 * regression_samples), Qt::yellow); curve1->setMarker1Enabled(true); curve1->setMarker1MovableEnabled(true); curve1->setMarker2Enabled(true); curve1->setMarker2MovableEnabled(true); } if(pageRadioButton->isChecked() == true) { plot_type = 1; if((epoch_cntr < 2) || (zscore_pages < 1)) { return; } marker_start = curve1->getMarker1Position() * zscore_pages; if(marker_start < 0) { marker_start = 0; } marker_end = curve1->getMarker2Position() * zscore_pages; if(marker_end > zscore_pages) { marker_end = zscore_pages; } regression_samples = marker_end - marker_start; if(regression_samples < 2) { return; } for(i=0; isignalcomp[signalnr]->signallabel, b1, b0); curve1->drawCurve(zscore_page_buf, zscore_pages, 1.0, -1.0); curve1->setH_RulerValues(0, zscore_pages); curve1->setLowerLabel("Pages"); curve1->setV_label("Z ratio"); curve1->setUpperLabel1(str); curve1->drawLine(marker_start, b0 + b1, marker_end, b0 + (b1 * regression_samples), Qt::yellow); curve1->setMarker1Enabled(true); curve1->setMarker1MovableEnabled(true); curve1->setMarker2Enabled(true); curve1->setMarker2MovableEnabled(true); } if(wakesleepRadioButton->isChecked() == true) { plot_type = 2; if((epoch_cntr < 2) || (zscore_pages < 1)) { return; } marker_start = curve1->getMarker1Position() * zscore_pages; if(marker_start < 0) { marker_start = 0; } marker_end = curve1->getMarker2Position() * zscore_pages; if(marker_end > zscore_pages) { marker_end = zscore_pages; } regression_samples = marker_end - marker_start; if(regression_samples < 2) { return; } sleep_cnt = 0; for(i=marker_start; isignalcomp[signalnr]->signallabel, sleep_pct); curve1->drawCurve(zscore_sleepstage_buf, zscore_pages, 3.0, -3.0); curve1->setH_RulerValues(0, zscore_pages); curve1->setLowerLabel("Pages"); curve1->setV_label("Sleep/Wake"); curve1->setUpperLabel1(str); curve1->setLineEnabled(false); curve1->setMarker1Enabled(true); curve1->setMarker1MovableEnabled(true); curve1->setMarker2Enabled(true); curve1->setMarker2MovableEnabled(true); } } void UI_ZScoreWindow::markersMoved() { RadioButtonsClicked(true); } void UI_ZScoreWindow::jumpButtonClicked() { int i, file_num; long long onset, temp; double position; if((epoch_cntr < 2) || (zscore_pages < 1)) { return; } if(curve1->isCursorActive() == false) { return; } position = curve1->getCursorPosition(); if(plot_type) { onset = position * zscore_page_len * 2 * TIME_DIMENSION; } else { onset = position * ZSCORE_EPOCH_LEN * TIME_DIMENSION; } file_num = mainwindow->signalcomp[signalnr]->edfhdr->file_num; if(mainwindow->viewtime_sync==VIEWTIME_SYNCED_OFFSET) { for(i=0; ifiles_open; i++) { mainwindow->edfheaderlist[i]->viewtime = onset; mainwindow->edfheaderlist[i]->viewtime -= (mainwindow->pagetime / 2); mainwindow->edfheaderlist[i]->viewtime -= mainwindow->edfheaderlist[file_num]->starttime_offset; } } if(mainwindow->viewtime_sync==VIEWTIME_UNSYNCED) { mainwindow->edfheaderlist[file_num]->viewtime = onset; mainwindow->edfheaderlist[file_num]->viewtime -= (mainwindow->pagetime / 2); mainwindow->edfheaderlist[file_num]->viewtime -= mainwindow->edfheaderlist[file_num]->starttime_offset; } if((mainwindow->viewtime_sync==VIEWTIME_SYNCED_ABSOLUT)||(mainwindow->viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { temp = onset - mainwindow->edfheaderlist[file_num]->viewtime; temp -= mainwindow->edfheaderlist[file_num]->starttime_offset; temp -= (mainwindow->pagetime / 2); for(i=0; ifiles_open; i++) { mainwindow->edfheaderlist[i]->viewtime += temp; } } mainwindow->setup_viewbuf(); } void UI_ZScoreWindow::shift_page_right() { if((epoch_cntr < 2) || (zscore_pages < 1)) { return; } if(curve1->isCursorActive() == false) { return; } curve1->shiftCursorIndexRight(1); } void UI_ZScoreWindow::shift_page_left() { if((epoch_cntr < 2) || (zscore_pages < 1)) { return; } if(curve1->isCursorActive() == false) { return; } curve1->shiftCursorIndexLeft(1); } edfbrowser_157_source/PaxHeaders.7921/viewcurve.h0000644000000000000000000000013212646460742017056 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/viewcurve.h0000644000175000001440000001462612646460742017430 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef VIEWCURVE_H #define VIEWCURVE_H #include #include #include #include #include #include #include #include #include #include #if QT_VERSION < 0x050000 #include #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "colordialog.h" #include "filter.h" #include "spectrumanalyzer.h" #include "utils.h" #include "adjustfiltersettings.h" #include "spike_filter.h" #include "ravg_filter.h" #include "ecg_filter.h" #include "statistics_dialog.h" #include "z_score_dialog.h" #include "z_ratio_filter.h" #include "third_party/fidlib/fidlib.h" class UI_Mainwindow; class drawCurve_stage_1_thread : public QThread { public: void init_vars(UI_Mainwindow *, struct signalcompblock **, int, int, char *, int, int, int *, int, struct graphicBufStruct *, double, double, struct crossHairStruct *, struct crossHairStruct *, int, int); private: int i, h, w, signalcomps, *screensamples, *screensamples_b, printing, cpu_cnt, linear_interpol; char *viewbuf; double printsize_x_factor, printsize_y_factor; UI_Mainwindow *mainwindow; struct signalcompblock *signalcomp, **signalcomp_b; struct graphicBufStruct *graphicBuf; struct crossHairStruct *crosshair_1, *crosshair_2; void run(); }; class ViewCurve : public QWidget { Q_OBJECT public: ViewCurve(QWidget *parent=0); ~ViewCurve(); UI_Mainwindow *mainwindow; int use_move_events, mouse_x, mouse_y, mouse_old_x, mouse_old_y, sidemenu_active, signal_nr, mouse_press_coordinate_x, mouse_press_coordinate_y, draw_zoom_rectangle, signal_color, floating_ruler_color, ruler_active, ruler_moving, ruler_x_position, ruler_y_position, *screensamples, graphicBufWidth, blackwhite_printing, backup_color_10[MAXSIGNALS], backup_color_11, backup_color_12, backup_color_14, annot_marker_moving, pressed_on_label, label_press_y_position, cpu_cnt, floating_ruler_value, linear_interpol; double original_screen_offset; struct graphicBufStruct *graphicBuf, *printBuf; struct active_markersblock *active_markers; struct crossHairStruct crosshair_1, crosshair_2; QColor backgroundcolor, small_ruler_color, big_ruler_color, mouse_rect_color, baseline_color, text_color, annot_marker_color, backup_color_1, backup_color_2, backup_color_3, backup_color_4, backup_color_5, backup_color_13, backup_color_15; QFont *printfont; void drawCurve_stage_1(QPainter *painter=NULL, int w_width=0, int w_height=0, int print_linewidth=0); void setCrosshair_1_center(void); public slots: void exec_sidemenu(int); #if QT_VERSION < 0x050000 void print_to_postscript(); #endif void print_to_pdf(); void print_to_image(int, int); void print_to_printer(); private: QDialog *sidemenu; QPushButton *sidemenuButton1, *sidemenuButton2, *sidemenuButton3, *sidemenuButton4, *sidemenuButton5, *sidemenuButton6, *sidemenuButton7, *sidemenuButton8, *sidemenuButton9, *sidemenuButton10, *sidemenuButton11, *sidemenuButton12, *sidemenuButton13; QDoubleSpinBox *ScaleBox, *ScaleBox2; QLabel *SidemenuLabel, *AmpLabel, *AliasLabel, *OffsetLabel; QLineEdit *AliasLineEdit; QPrinter *printer; QPen *special_pen, *annot_marker_pen, *signal_pen, *ruler_pen; int printing, w, h; double *original_sensitivity, painter_pixelsizefactor, printsize_x_factor, printsize_y_factor; drawCurve_stage_1_thread *thr[MAXSIGNALS]; inline void floating_ruler(QPainter *, int, int, struct signalcompblock *, int); void backup_colors_for_printing(void); void restore_colors_after_printing(void); protected slots: void RulerButton(); void FittopaneButton(); void ScaleBoxChanged(double); void ScaleBox2Changed(double); void RemovefilterButton(); void RemovesignalButton(); void ColorButton(); void CrosshairButton(); void FreqSpecButton(); void Z_scoringButton(); void AdjustFilterButton(); void StatisticsButton(); void ECGdetectButton(); void signalInvert(); void strip_types_from_label(char *); void sidemenu_close(); protected: void paintEvent(QPaintEvent *); void resizeEvent(QResizeEvent *); void drawCurve_stage_2(QPainter *painter, int w_width=0, int w_height=0, int print_linewidth=0); void mousePressEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *); void wheelEvent(QWheelEvent *); }; #endif edfbrowser_157_source/PaxHeaders.7921/wav2edf.h0000644000000000000000000000013212646460742016375 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/wav2edf.h0000644000175000001440000000424112646460742016737 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_WAV2EDFFORM_H #define UI_WAV2EDFFORM_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "utils.h" #include "edflib.h" class UI_WAV2EDFwindow : public QObject { Q_OBJECT public: UI_WAV2EDFwindow(char *recent_dir=NULL, char *save_dir=NULL); private: QDialog *myobjectDialog; QPushButton *pushButton1, *pushButton2; QLabel *PatientnameLabel, *RecordingLabel, *DatetimeLabel, *PhysDimLabel, *PhysMaxLabel; QLineEdit *PatientnameLineEdit, *RecordingLineEdit, *PhysDimLineEdit; QDateTimeEdit *StartDatetimeedit; QDoubleSpinBox *PhysMaxSpinBox; char *recent_opendir, *recent_savedir; void enable_widgets(bool); private slots: void SelectFileButton(); }; #endif edfbrowser_157_source/PaxHeaders.7921/fma_ecg2edf.cpp0000644000000000000000000000013212646460742017514 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/fma_ecg2edf.cpp0000644000175000001440000004771512646460742020073 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2015, 2016 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 . * *************************************************************************** */ /* *************************************************************************** * * This is an FM decoder using up-sampling and zero-crossing detection. * It expects the source signal to be sampled at the traditional samplerates * used for pc sound cards: 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200 or 96000 Hz * with 16-bit resolution. * * The carrier centerfrequency of the FM signal is 1900Hz. * Frequency deviation is 100Hz per milli-Volt. * This technic is used to upload an ECG recording via POTS (Plain Old Telephone Service). * *************************************************************************** */ #include "fma_ecg2edf.h" UI_FMaudio2EDFwindow::UI_FMaudio2EDFwindow(char *recent_dir, char *save_dir) { recent_opendir = recent_dir; recent_savedir = save_dir; myobjectDialog = new QDialog; myobjectDialog->setMinimumSize(600, 300); myobjectDialog->setMaximumSize(600, 300); myobjectDialog->setWindowTitle("FM Audio ECG to EDF converter"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); PatientnameLabel = new QLabel(myobjectDialog); PatientnameLabel->setGeometry(20, 20, 140, 25); PatientnameLabel->setText("Subject"); RecordingLabel = new QLabel(myobjectDialog); RecordingLabel->setGeometry(20, 55, 140, 25); RecordingLabel->setText("Recording"); DatetimeLabel = new QLabel(myobjectDialog); DatetimeLabel->setGeometry(20, 90, 140, 25); DatetimeLabel->setText("Startdate and time"); PatientnameLineEdit = new QLineEdit(myobjectDialog); PatientnameLineEdit->setGeometry(160, 20, 420, 25); PatientnameLineEdit->setMaxLength(80); RecordingLineEdit = new QLineEdit(myobjectDialog); RecordingLineEdit->setGeometry(160, 55, 420, 25); RecordingLineEdit->setMaxLength(80); StartDatetimeedit = new QDateTimeEdit(myobjectDialog); StartDatetimeedit->setGeometry(160, 90, 140, 25); StartDatetimeedit->setDisplayFormat("dd/MM/yyyy hh:mm:ss"); StartDatetimeedit->setDateTime(QDateTime::currentDateTime()); pushButton1 = new QPushButton(myobjectDialog); pushButton1->setGeometry(20, 250, 100, 25); pushButton1->setText("Select File"); pushButton2 = new QPushButton(myobjectDialog); pushButton2->setGeometry(480, 250, 100, 25); pushButton2->setText("Close"); QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton())); QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close())); myobjectDialog->exec(); } void UI_FMaudio2EDFwindow::SelectFileButton() { FILE *inputfile=NULL; int i, edfsignals, resolution, sf, df, uf, dsf, usf, hdl_out, readbufsize, *buf2=NULL, *buf3=NULL, pos=0, smpls=0, freq=608000, freq_min=448000, freq_max=768000; unsigned int fmt_chunk_offset, data_chunk_offset, tmp; char path[MAX_PATH_LENGTH], outputfilename[MAX_PATH_LENGTH], scratchpad[512], *buf1=NULL; long long blocks, leftover, progress_steps, k; hpf44=NULL; lpf9a=NULL; lpf9b=NULL; lpf9c=NULL; lpf9d=NULL; lpf9e=NULL; lpf200a=NULL; lpf200b=NULL; lpf200c=NULL; lpf200d=NULL; lpf200e=NULL; enable_widgets(false); if(!(strlen(PatientnameLineEdit->text().toLatin1().data()))) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a subject name."); messagewindow.exec(); enable_widgets(true); return; } if(!(strlen(RecordingLineEdit->text().toLatin1().data()))) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a recording description."); messagewindow.exec(); enable_widgets(true); return; } strcpy(path, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "Text files (*.wav *.WAV)").toLocal8Bit().data()); if(!strcmp(path, "")) { enable_widgets(true); return; } get_directory_from_path(recent_opendir, path, MAX_PATH_LENGTH); inputfile = fopeno(path, "rb"); if(inputfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); messagewindow.exec(); enable_widgets(true); return; } /***************** check if the wavefile is valid ******************************/ rewind(inputfile); if(fread(scratchpad, 256, 1, inputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if((strncmp(scratchpad, "RIFF", 4)) || (strncmp(scratchpad + 8, "WAVE", 4))) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "File is not a Wave file."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } fmt_chunk_offset = 12; while(1) { fseeko(inputfile, (long long)fmt_chunk_offset, SEEK_SET); if(fread(scratchpad, 256, 1, inputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find fmt chunk."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(strncmp(scratchpad, "fmt ", 4) == 0) { break; } tmp = *((unsigned int *)(scratchpad + 4)); if(tmp < 2) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find fmt chunk."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(tmp & 1) { tmp++; } fmt_chunk_offset += (tmp + 8); } if(*((signed short *)(scratchpad + 8)) != 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "File contains compressed data.\nCan not convert compressed data."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } edfsignals = *((unsigned short *)(scratchpad + 10)); if(edfsignals < 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Number of channels in wave file is < 1"); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(edfsignals > 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Number of channels in wave file is > 1\n" "Can only handle mono recordings."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } sf = *((unsigned int *)(scratchpad + 12)); switch(sf) { case 96000 : dsf = 384; usf = 2; break; case 88200 : dsf = 882; usf = 5; break; case 48000 : dsf = 384; usf = 4; break; case 44100 : dsf = 441; usf = 5; break; case 32000 : dsf = 384; usf = 6; break; case 22050 : dsf = 441; usf = 10; break; case 16000 : dsf = 384; usf = 12; break; case 11025 : dsf = 441; usf = 20; break; case 8000 : dsf = 384; usf = 24; break; default : dsf = 0; usf = 1; break; } if(!dsf) { sprintf(scratchpad, "error: samplefrequency is %iHz.\n" "expected: 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200 or 96000 Hz\n", sf); QMessageBox messagewindow(QMessageBox::Critical, "Error", scratchpad); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } // usf *= 2; // Select 1000Hz instead of 500Hz for the new EDF file, // not used because it doesn't improve signal quality // sf: samplefrequency of the source file uf = sf * usf; // uf: upsampling frequency (192KHz or 220.5KHz) // usf: upsampling factor df = uf / dsf; // df: downsampling frequency (500Hz, samplefrequency of the new EDF file) // dsf: downsampling factor resolution = *((unsigned short *)(scratchpad + 22)); if(resolution != 16) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Resolution (bitdepth) must be 16 bit."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } /////////////////////////////////////////////////////////////////////////////// data_chunk_offset = 12; while(1) { fseeko(inputfile, (long long)data_chunk_offset, SEEK_SET); if(fread(scratchpad, 256, 1, inputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find data chunk."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(strncmp(scratchpad, "data", 4) == 0) { break; } tmp = *((unsigned int *)(scratchpad + 4)); if(tmp < 2) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not find data chunk."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(tmp & 1) { tmp++; } data_chunk_offset += (tmp + 8); } /////////////////////////////////////////////////////////////////////////////// blocks = (long long)(*((int *)(scratchpad + 4))); blocks /= (sf * edfsignals * 2); fseeko(inputfile, 0LL, SEEK_END); leftover = ftello(inputfile) - (long long)data_chunk_offset - 8LL; leftover /= (sf * edfsignals * 2); if(blocks > leftover) { blocks = leftover; } if(blocks < 1LL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Not enough data in file."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } readbufsize = 2 * sf * edfsignals; buf1 = (char *)malloc(readbufsize); if(buf1 == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (buf1)."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } buf2 = (int *)malloc(uf * sizeof(int)); if(buf2 == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (buf2)."); messagewindow.exec(); fclose(inputfile); free(buf1); enable_widgets(true); return; } buf3 = (int *)malloc(df * sizeof(int)); if(buf3 == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (buf3)."); messagewindow.exec(); fclose(inputfile); free(buf1); free(buf2); enable_widgets(true); return; } if(allocateFilters(uf, usf, dsf) == false) { fclose(inputfile); free(buf1); free(buf2); free(buf3); deleteFilters(); enable_widgets(true); return; } /***************** create a new EDF file *****************************************/ get_filename_from_path(outputfilename, path, MAX_PATH_LENGTH); remove_extension_from_filename(outputfilename); strcat(outputfilename, ".edf"); path[0] = 0; if(recent_savedir[0]!=0) { strcpy(path, recent_savedir); strcat(path, "/"); } strcat(path, outputfilename); strcpy(path, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(path), "EDF files (*.edf *.EDF)").toLocal8Bit().data()); if(!strcmp(path, "")) { fclose(inputfile); free(buf1); free(buf2); free(buf3); deleteFilters(); enable_widgets(true); return; } get_directory_from_path(recent_savedir, path, MAX_PATH_LENGTH); hdl_out = edfopen_file_writeonly(path, EDFLIB_FILETYPE_EDFPLUS, edfsignals); if(hdl_out < 0) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open output file for writing."); messagewindow.exec(); fclose(inputfile); free(buf1); free(buf2); free(buf3); deleteFilters(); enable_widgets(true); return; } edf_set_samplefrequency(hdl_out, 0, df); edf_set_physical_maximum(hdl_out, 0, 8192); edf_set_physical_minimum(hdl_out, 0, -8192); edf_set_digital_maximum(hdl_out, 0, 32767); edf_set_digital_minimum(hdl_out, 0, -32768); edf_set_label(hdl_out, 0, "ECG"); edf_set_physical_dimension(hdl_out, 0, "uV"); edf_set_patientname(hdl_out, PatientnameLineEdit->text().toLatin1().data()); edf_set_recording_additional(hdl_out, RecordingLineEdit->text().toLatin1().data()); edf_set_startdatetime(hdl_out, StartDatetimeedit->date().year(), StartDatetimeedit->date().month(), StartDatetimeedit->date().day(), StartDatetimeedit->time().hour(), StartDatetimeedit->time().minute(), StartDatetimeedit->time().second()); edfwrite_annotation_latin1(hdl_out, 0LL, -1, "Recording starts"); /***************** start conversion **************************************/ fseeko(inputfile, (long long)data_chunk_offset + 8LL, SEEK_SET); QProgressDialog progress("Converting a Wave file ...", "Abort", 0, (int)blocks, myobjectDialog); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(0); progress_steps = blocks / 100LL; if(progress_steps < 1LL) { progress_steps = 1LL; } for(k=0LL; kprocessEvents(); if(progress.wasCanceled() == true) { edfclose_file(hdl_out); fclose(inputfile); free(buf1); free(buf2); free(buf3); deleteFilters(); enable_widgets(true); return; } } if(fread(buf1, readbufsize, 1, inputfile) != 1) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read error occurred during conversion."); messagewindow.exec(); edfclose_file(hdl_out); fclose(inputfile); free(buf1); free(buf2); free(buf3); deleteFilters(); enable_widgets(true); return; } for(i=0; i= 0) && (!pos)) { pos = 1; freq = (uf * 320) / smpls; if(freq < freq_min) { freq = freq_min; } else if(freq > freq_max) { freq = freq_max; } smpls = 0; } else if((buf2[i] < 0) && pos) { pos = 0; } buf2[i] = freq - 608000; buf2[i] = run_ravg_filter(buf2[i], lpf200a); buf2[i] = run_ravg_filter(buf2[i], lpf200b); buf2[i] = run_ravg_filter(buf2[i], lpf200c); buf2[i] = run_ravg_filter(buf2[i], lpf200d); buf2[i] = run_ravg_filter(buf2[i], lpf200e); if(!(i % dsf)) { buf3[i / dsf] = buf2[i] / 8; } } if(edf_blockwrite_digital_samples(hdl_out, buf3)) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "A write error occurred during conversion."); messagewindow.exec(); edfclose_file(hdl_out); fclose(inputfile); free(buf1); free(buf2); free(buf3); deleteFilters(); enable_widgets(true); return; } } progress.reset(); edfwrite_annotation_latin1(hdl_out, blocks * 10000LL, -1, "Recording ends"); edfclose_file(hdl_out); fclose(inputfile); free(buf1); free(buf2); free(buf3); deleteFilters(); QMessageBox messagewindow(QMessageBox::Information, "Ready", "Done."); messagewindow.setIconPixmap(QPixmap(":/images/ok.png")); messagewindow.exec(); enable_widgets(true); } void UI_FMaudio2EDFwindow::enable_widgets(bool toggle) { StartDatetimeedit->setEnabled(toggle); PatientnameLineEdit->setEnabled(toggle); RecordingLineEdit->setEnabled(toggle); pushButton1->setEnabled(toggle); pushButton2->setEnabled(toggle); } void UI_FMaudio2EDFwindow::deleteFilters(void) { free_ravg_filter(lpf9a); free_ravg_filter(lpf9b); free_ravg_filter(lpf9c); free_ravg_filter(lpf9d); free_ravg_filter(lpf9e); free_ravg_filter(hpf44); free_ravg_filter(lpf200a); free_ravg_filter(lpf200b); free_ravg_filter(lpf200c); free_ravg_filter(lpf200d); free_ravg_filter(lpf200e); } bool UI_FMaudio2EDFwindow::allocateFilters(int uf, int usf, int dsf) { lpf9a = create_ravg_filter(1, usf * 2); if(lpf9a == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (ravg filter)."); messagewindow.exec(); return false; } lpf9b = create_ravg_filter(1, usf * 2); if(lpf9b == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (ravg filter)."); messagewindow.exec(); return false; } lpf9c = create_ravg_filter(1, usf * 2); if(lpf9c == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (ravg filter)."); messagewindow.exec(); return false; } lpf9d = create_ravg_filter(1, usf * 2); if(lpf9d == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (ravg filter)."); messagewindow.exec(); return false; } lpf9e = create_ravg_filter(1, usf * 2); if(lpf9e == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (ravg filter)."); messagewindow.exec(); return false; } hpf44 = create_ravg_filter(0, uf / 700); if(hpf44 == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (ravg filter)."); messagewindow.exec(); return false; } lpf200a = create_ravg_filter(1, dsf * 2); if(lpf200a == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (ravg filter)."); messagewindow.exec(); return false; } lpf200b = create_ravg_filter(1, dsf * 2); if(lpf200b == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (ravg filter)."); messagewindow.exec(); return false; } lpf200c = create_ravg_filter(1, dsf * 2); if(lpf200c == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (ravg filter)."); messagewindow.exec(); return false; } lpf200d = create_ravg_filter(1, dsf * 2); if(lpf200d == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (ravg filter)."); messagewindow.exec(); return false; } lpf200e = create_ravg_filter(1, dsf * 2); if(lpf200e == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (ravg filter)."); messagewindow.exec(); return false; } return true; } edfbrowser_157_source/PaxHeaders.7921/xml.cpp0000644000000000000000000000013212646460742016172 xustar0030 mtime=1452958178.249246726 30 atime=1452958178.249246726 30 ctime=1452958178.249246726 edfbrowser_157_source/xml.cpp0000644000175000001440000005403612646460742016543 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "xml.h" static int xml_attribute(const char *, const char *, char *, int); static int xml_process_tag(const char *, struct xml_handle *); inline static int xml_next_tag(int, struct xml_handle *); int xml_character_encoding_type(struct xml_handle *handle_p) { if(handle_p==NULL) return(-1); return(handle_p->encoding); } void xml_fwrite_encode_entity(FILE *file, const char *str) { for(; *str; str++) { switch(*str) { case '<' : fwrite("<", 4, 1, file); break; case '>' : fwrite(">", 4, 1, file); break; case '&' : fwrite("&", 5, 1, file); break; case '\'' : fwrite("'", 6, 1, file); break; case '\"' : fwrite(""", 6, 1, file); break; default : fputc(*str, file); break; } } } void xml_fnwrite_encode_entity(FILE *file, const char *str, int n) { int i; for(i=0; i' : fwrite(">", 4, 1, file); break; case '&' : fwrite("&", 5, 1, file); break; case '\'' : fwrite("'", 6, 1, file); break; case '\"' : fwrite(""", 6, 1, file); break; default : fputc(str[i], file); break; } } } void xml_strcpy_encode_entity(char *dest, const char *src) { *dest = 0; for(; *src; src++) { switch(*src) { case '<' : strcpy(dest, "<"); dest += 4; break; case '>' : strcpy(dest, ">"); dest += 4; break; case '&' : strcpy(dest, "&"); dest += 5; break; case '\'' : strcpy(dest, "'"); dest += 6; break; case '\"' : strcpy(dest, """); dest += 6; break; default : *dest = *src; *(++dest) = 0; break; } } } int xml_strncpy_encode_entity(char *dest, const char *src, int n) { int i=0; if(n < 1) { return(0); } *dest = 0; for(; *src; src++) { if((n - i) < 7) { break; } if(*src == '<') { strcpy(dest + i, "<"); i += 4; continue; } if(*src == '>') { strcpy(dest + i, ">"); i += 4; continue; } if(*src == '&') { strcpy(dest + i, "&"); i += 5; continue; } if(*src == '\'') { strcpy(dest + i, "'"); i += 6; continue; } if(*src == '\"') { strcpy(dest + i, """); i += 6; continue; } dest[i++] = *src; } dest[i] = 0; return(i); } void xml_strcpy_decode_entity(char *dest, const char *src) { int i, len, p=0; len = strlen(src); for(i=0; i= (n - 1)) { i++; break; } } return(i); } int xml_get_name_of_element(struct xml_handle *handle_p, char *buf, int sz) { if(handle_p == NULL) return XML_ERROR_INV_HDL; if(sz < 2) return XML_ERROR_GEN; strncpy(buf, handle_p->elementname[handle_p->level], sz); buf[sz-1] = 0; return 0; } int xml_get_attribute_of_element(struct xml_handle *handle_p, const char *attr_name, char *str_buf, int content_len) { if(handle_p == NULL) return XML_ERROR_INV_HDL; if(strlen(attr_name) < 1) return XML_ERROR_GEN; if(content_len < 1) return XML_ERROR_GEN; return xml_attribute(handle_p->attributes[handle_p->level], attr_name, str_buf, content_len); } static int xml_attribute(const char *data, const char *item, char *result, int result_len) { int i, j, data_len, item_len, quote=0; if(data == NULL) return XML_ERROR_GEN; data_len = strlen(data); item_len = strlen(item); if((data_len < 4) || (item_len >= (data_len - 4))) { return XML_ERROR_GEN; } for(i=0; i<(data_len - item_len); i++) { if(data[i] == '\"') { if(quote) { quote--; } else { quote++; } } if(quote) continue; if(!strncmp(data + i, item, item_len)) { if((i + item_len) < (data_len - 3)) { if(!strncmp(data + i + item_len, "=\"", 2)) { i += (item_len + 2); for(j=i; jfile = fopen(filename, "rb"); if(handle_p->file==NULL) { xml_close(handle_p); return NULL; } handle_p->offset[handle_p->level] = xml_next_tag(0, handle_p); if(handle_p->offset[handle_p->level] < 0) { xml_close(handle_p); return NULL; } if(strlen(handle_p->tag_search_result) < 3) { xml_close(handle_p); return NULL; } if((handle_p->tag_search_result[0] == '?') && (handle_p->tag_search_result[strlen(handle_p->tag_search_result) - 1] == '?')) { if(xml_attribute(handle_p->tag_search_result, "encoding", scratchpad, 512) < 0) { handle_p->encoding = 0; // attribute encoding not present } else { if((!strcmp(scratchpad, "ISO-8859-1")) || (!strcmp(scratchpad, "iso-8859-1"))) { handle_p->encoding = 1; } else if((!strcmp(scratchpad, "UTF-8")) || (!strcmp(scratchpad, "utf-8"))) { handle_p->encoding = 2; } else { handle_p->encoding = 99999; // unknown encoding } } } while((handle_p->tag_search_result[0]=='!') || (handle_p->tag_search_result[0]=='?')) { handle_p->offset[handle_p->level] = xml_next_tag(handle_p->offset[handle_p->level], handle_p); if(handle_p->offset[handle_p->level] < 0) { xml_close(handle_p); return NULL; } } err = xml_process_tag(handle_p->tag_search_result , handle_p); if(err) { xml_close(handle_p); return NULL; } return handle_p; } int xml_get_content_of_element(struct xml_handle *handle_p, char *buf, int sz) { int i, j, offset, len, deep=0, cdata=0; if(handle_p==NULL) return(XML_ERROR_INV_HDL); offset = handle_p->offset[handle_p->level]; len = strlen(handle_p->elementname[handle_p->level]); while(1) { offset = xml_next_tag(offset, handle_p); if(offset < 0) return offset; if((handle_p->tag_search_result[0]=='!') || (handle_p->tag_search_result[0]=='?')) { continue; } if(handle_p->tag_search_result[0]=='/') { if(deep) deep--; else break; } else { deep++; } } offset -= (len + 3); if(offset < handle_p->offset[handle_p->level]) return XML_ERROR_GEN; fseek(handle_p->file, handle_p->offset[handle_p->level], SEEK_SET); if(offset - handle_p->offset[handle_p->level] + 1 >= XML_STRBUFLEN) { return XML_ERROR_STRLEN; } if(offset > handle_p->offset[handle_p->level]) { if(fread(handle_p->content[handle_p->level], offset - handle_p->offset[handle_p->level], 1, handle_p->file) != 1) { return XML_ERROR_GEN; } } len = offset - handle_p->offset[handle_p->level]; handle_p->content[handle_p->level][len] = 0; if(len > 11) // cdata? { if(!(strncmp(handle_p->content[handle_p->level], "content[handle_p->level][j] = handle_p->content[handle_p->level][j+9]; } len -= 3; handle_p->content[handle_p->level][len] = 0; } } if(cdata == 0) { for(i=0; handle_p->content[handle_p->level][i]!=0; i++) { if(handle_p->content[handle_p->level][i]=='&') { if(i <= (len - 3)) { if(!strncmp(handle_p->content[handle_p->level] + i + 1, "lt;", 3)) { handle_p->content[handle_p->level][i] = '<'; for(j=i+1; handle_p->content[handle_p->level][j-1]!=0; j++) { handle_p->content[handle_p->level][j] = handle_p->content[handle_p->level][j+3]; } } if(!strncmp(handle_p->content[handle_p->level] + i + 1, "gt;", 3)) { handle_p->content[handle_p->level][i] = '>'; for(j=i+1; handle_p->content[handle_p->level][j-1]!=0; j++) { handle_p->content[handle_p->level][j] = handle_p->content[handle_p->level][j+3]; } } } if(i <= (len - 5)) { if(!strncmp(handle_p->content[handle_p->level] + i + 1, "apos;", 5)) { handle_p->content[handle_p->level][i] = '\''; for(j=i+1; handle_p->content[handle_p->level][j-1]!=0; j++) { handle_p->content[handle_p->level][j] = handle_p->content[handle_p->level][j+5]; } } if(!strncmp(handle_p->content[handle_p->level] + i + 1, "quot;", 5)) { handle_p->content[handle_p->level][i] = '\"'; for(j=i+1; handle_p->content[handle_p->level][j-1]!=0; j++) { handle_p->content[handle_p->level][j] = handle_p->content[handle_p->level][j+5]; } } } if(i <= (len - 4)) { if(!strncmp(handle_p->content[handle_p->level] + i + 1, "amp;", 4)) { for(j=i+1; handle_p->content[handle_p->level][j-1]!=0; j++) { handle_p->content[handle_p->level][j] = handle_p->content[handle_p->level][j+4]; } } } } } } if(sz < 2) return XML_ERROR_GEN; strncpy(buf, handle_p->content[handle_p->level], sz); buf[sz-1] = 0; return 0; } int xml_goto_nth_element_inside(struct xml_handle *handle_p, const char *name, int n) { int len, offset, deep=0, cnt=0, ts_len, has_endslash, err; if(handle_p==NULL) return XML_ERROR_INV_HDL; if(handle_p->level >= (XML_MAX_ED - 2)) return XML_ERROR_MEMBUFSZ; len = strlen(name); offset = handle_p->offset[handle_p->level]; while(1) { while(1) { offset = xml_next_tag(offset, handle_p); if(offset < 0) return offset; if((handle_p->tag_search_result[0]=='!') || (handle_p->tag_search_result[0]=='?')) { continue; } if(handle_p->tag_search_result[0]=='/') { if(deep) deep--; else return XML_ERROR_GEN; } else { ts_len = strlen(handle_p->tag_search_result); if(handle_p->tag_search_result[ts_len - 1] == '/') { has_endslash = 1; } else { has_endslash = 0; deep++; } break; } } if((deep + has_endslash) == 1) { if((int)strlen(handle_p->tag_search_result) >= len) { if(!strncmp(handle_p->tag_search_result, name, len)) { if((handle_p->tag_search_result[len]==' ')||(handle_p->tag_search_result[len]==0)) { if(cnt==n) { handle_p->level++; handle_p->offset[handle_p->level] = offset; handle_p->one_tag[handle_p->level] = 0; handle_p->elementname[handle_p->level][0] = 0; handle_p->attributes[handle_p->level][0] = 0; err = xml_process_tag(handle_p->tag_search_result, handle_p); if(err) return err; return 0; } cnt++; } } } } } return XML_ERROR_GEN; } int xml_goto_next_element_with_same_name(struct xml_handle *handle_p) { int len, offset, deep=0, err, ts_len, has_endslash; if(handle_p==NULL) return XML_ERROR_INV_HDL; len = strlen(handle_p->elementname[handle_p->level]); offset = handle_p->offset[handle_p->level]; if(handle_p->one_tag[handle_p->level] == 0) { while(1) { offset = xml_next_tag(offset, handle_p); if(offset < 0) return XML_ERROR_GEN; if((handle_p->tag_search_result[0]=='!') || (handle_p->tag_search_result[0]=='?')) { continue; } if(handle_p->tag_search_result[0]=='/') { if(deep) deep--; else break; } else { ts_len = strlen(handle_p->tag_search_result); if(handle_p->tag_search_result[ts_len - 1] != '/') { deep++; } } } } while(1) { while(1) { offset = xml_next_tag(offset, handle_p); if(offset < 0) return offset; if((handle_p->tag_search_result[0]=='!') || (handle_p->tag_search_result[0]=='?')) { continue; } if(handle_p->tag_search_result[0]=='/') { if(deep) deep--; else return XML_ERROR_GEN; } else { ts_len = strlen(handle_p->tag_search_result); if(handle_p->tag_search_result[ts_len - 1] == '/') { has_endslash = 1; } else { has_endslash = 0; deep++; } break; } } if((deep + has_endslash) == 1) { if((int)strlen(handle_p->tag_search_result) >= len) { if(!strncmp(handle_p->tag_search_result, handle_p->elementname[handle_p->level], len)) { if((handle_p->tag_search_result[len]==' ')||(handle_p->tag_search_result[len]==0)) { handle_p->offset[handle_p->level] = offset; handle_p->one_tag[handle_p->level] = 0; handle_p->elementname[handle_p->level][0] = 0; handle_p->attributes[handle_p->level][0] = 0; err = xml_process_tag(handle_p->tag_search_result, handle_p); if(err) return err; return 0; } } } } } return XML_ERROR_GEN; } int xml_goto_next_element_at_same_level(struct xml_handle *handle_p) { int offset, deep=0, ts_len, err; if(handle_p==NULL) return XML_ERROR_INV_HDL; offset = handle_p->offset[handle_p->level]; while(1) { offset = xml_next_tag(offset, handle_p); if(offset < 0) return offset; if((handle_p->tag_search_result[0]=='!') || (handle_p->tag_search_result[0]=='?')) { continue; } if(handle_p->tag_search_result[0]=='/') { if(deep) deep--; else break; } else { ts_len = strlen(handle_p->tag_search_result); if(handle_p->tag_search_result[ts_len - 1] != '/') { deep++; } } } offset = xml_next_tag(offset, handle_p); if(offset < 0) return offset; while((handle_p->tag_search_result[0]=='!') || (handle_p->tag_search_result[0]=='?')) { offset = xml_next_tag(offset, handle_p); if(offset < 0) return offset; if(handle_p->tag_search_result==NULL) { return XML_ERROR_GEN; } } if(handle_p->tag_search_result[0]=='/') { return XML_ERROR_GEN; } err = xml_process_tag(handle_p->tag_search_result, handle_p); if(err) return err; handle_p->offset[handle_p->level] = offset; return 0; } /* Read the element name and copy it into the field of the structure */ /* Read the attributes and copy them into the field of the structure */ /* Check if the element has one or two tags */ static int xml_process_tag(const char *str, struct xml_handle *handle_p) { int len, i, p; if(handle_p==NULL) return XML_ERROR_INV_HDL; len = strlen(str); if(!len) return XML_ERROR_GEN; if((str[0]==' ')||(str[0]=='>')) return XML_ERROR_GEN; for(i=0; i')) break; } if((i + 1) > XML_STRBUFLEN) { return XML_ERROR_STRLEN; } strncpy(handle_p->elementname[handle_p->level], str, i); handle_p->elementname[handle_p->level][i] = 0; if(str[i]!=' ') return 0; i++; p = i; for(; i') break; } if(str[i-1] == '/') { i--; handle_p->one_tag[handle_p->level] = 1; } else { handle_p->one_tag[handle_p->level] = 0; } len = i - p; if(len < 2) return 0; if(str[len] == '/') len--; if((len + 1) > XML_STRBUFLEN) return XML_ERROR_STRLEN; strncpy(handle_p->attributes[handle_p->level], str + p, len); handle_p->attributes[handle_p->level][len] = 0; return 0; } void xml_close(struct xml_handle *handle_p) /* delete everything and close the file */ { if(handle_p==NULL) return; if(handle_p->file != NULL) fclose(handle_p->file); free(handle_p); } void xml_goto_root(struct xml_handle *handle_p) /* go to rootlevel and delete everything beneath */ { if(handle_p==NULL) return; handle_p->level = 0; } void xml_go_up(struct xml_handle *handle_p) /* go one level up and delete everything beneath */ { if(handle_p==NULL) return; if(handle_p->level > 0) handle_p->level--; return; } inline static int xml_next_tag(int offset, struct xml_handle *handle_p) /* returns offset after '>' */ { int temp, fp1=0, fp2=0, tagstart=0, tag_char_cnt=0, comment=0, cdata=0; char circ_buf[16]; handle_p->tag_search_result[0] = 0; fseek(handle_p->file, offset, SEEK_SET); while(1) { temp = fgetc(handle_p->file); if(temp==EOF) { return XML_ERROR_GEN; } if(tagstart) { circ_buf[tag_char_cnt % 16] = temp; tag_char_cnt++; if(tag_char_cnt == 3) { if(!strncmp(circ_buf, "!--", 3)) // start of comment { comment = 1; } } if(tag_char_cnt == 8) { if(!strncmp(circ_buf, "![CDATA[", 8)) // start of cdata { cdata = 1; } } } if(!comment) { if(!cdata) { if(temp=='<') { if(tagstart) { return XML_ERROR_GEN; } tagstart = 1; fp1 = ftell(handle_p->file); } if(temp=='>') { if(!tagstart) return XML_ERROR_GEN; offset = ftell(handle_p->file); fp2 = offset - 1; break; } } else // cdata { if((temp=='>') && (tag_char_cnt > 10)) { if((circ_buf[(tag_char_cnt - 2) % 16] == ']') && (circ_buf[(tag_char_cnt - 3) % 16] == ']')) { // end of cdata cdata = 0; tagstart = 0; fp1 = 0; fp2 = 0; tag_char_cnt = 0; } } } } else // comment { if((temp=='>') && (tag_char_cnt > 5)) { if((circ_buf[(tag_char_cnt - 2) % 16] == '-') && (circ_buf[(tag_char_cnt - 3) % 16] == '-')) { // end of comment comment = 0; tagstart = 0; fp1 = 0; fp2 = 0; tag_char_cnt = 0; } } } } if(!fp2) return XML_ERROR_GEN; fseek(handle_p->file, fp1, SEEK_SET); if((fp2 - fp1 + 1) > XML_STRBUFLEN) return XML_ERROR_STRLEN; if(fread(handle_p->tag_search_result, fp2 - fp1, 1, handle_p->file) != 1) { handle_p->tag_search_result[0] = 0; return XML_ERROR_GEN; } handle_p->tag_search_result[fp2 - fp1] = 0; return offset; } edfbrowser_157_source/PaxHeaders.7921/filter_dialog.cpp0000644000000000000000000000013212646460742020176 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/filter_dialog.cpp0000644000175000001440000006246712646460742020556 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ /* type: 0 : highpass 1 : lowpass 2 : notch 3 : bandpass 4 : bandstop model: 0 : Butterworth 1 : Chebyshev 2 : Bessel 3 : moving average 0 : resonator */ #define FILTERTYPE_HIGHPASS 0 #define FILTERTYPE_LOWPASS 1 #define FILTERTYPE_NOTCH 2 #define FILTERTYPE_BANDPASS 3 #define FILTERTYPE_BANDSTOP 4 #define FILTERMODEL_BUTTERWORTH 0 #define FILTERMODEL_CHEBYSHEV 1 #define FILTERMODEL_BESSEL 2 #define FILTERMODEL_MOVINGAVERAGE 3 #include "filter_dialog.h" UI_FilterDialog::UI_FilterDialog(QWidget *w_parent) { int i; QListWidgetItem *item; arraysize = 400; last_order = 1; last_samples = 16; last_qfactor = 20; last_model = 0; last_ripple = -1.0; mainwindow = (UI_Mainwindow *)w_parent; filterdialog = new QDialog; filterdialog->setMinimumSize(620, 365); filterdialog->setMaximumSize(620, 365); filterdialog->setWindowTitle("Add a filter"); filterdialog->setModal(true); filterdialog->setAttribute(Qt::WA_DeleteOnClose, true); typeboxlabel = new QLabel(filterdialog); typeboxlabel->setGeometry(20, 20, 120, 25); typeboxlabel->setText("Type"); freqboxlabel = new QLabel(filterdialog); freqboxlabel->setGeometry(160, 20, 120, 25); freqboxlabel->setText("Frequency"); freqbox2label = new QLabel(filterdialog); freqbox2label->setGeometry(300, 20, 120, 25); freqbox2label->setText("Frequency 2"); freqbox2label->setVisible(false); orderboxlabel = new QLabel(filterdialog); orderboxlabel->setGeometry(160, 80, 120, 25); orderboxlabel->setText("Order"); modelboxlabel = new QLabel(filterdialog); modelboxlabel->setGeometry(20, 80, 120, 25); modelboxlabel->setText("Model"); orderlabel = new QLabel(filterdialog); orderlabel->setGeometry(300, 80, 120, 25); orderlabel->setText("Slope roll-off:"); ordervaluelabel = new QLabel(filterdialog); ordervaluelabel->setGeometry(300, 105, 120, 25); ordervaluelabel->setText("6 dB / octave"); typebox = new QComboBox(filterdialog); typebox->setGeometry(20, 45, 120, 25); typebox->addItem("Highpass"); typebox->addItem("Lowpass"); typebox->addItem("Notch"); typebox->addItem("Bandpass"); typebox->addItem("Bandstop"); freqbox = new QDoubleSpinBox(filterdialog); freqbox->setGeometry(160, 45, 120, 25); freqbox->setDecimals(6); freqbox->setSuffix(" Hz"); freqbox->setMinimum(0.0001); freqbox->setMaximum(100000000.0); freqbox->setValue(1.0); freq2box = new QDoubleSpinBox(filterdialog); freq2box->setGeometry(300, 45, 120, 25); freq2box->setDecimals(6); freq2box->setSuffix(" Hz"); freq2box->setMinimum(0.0001); freq2box->setMaximum(100000000.0); freq2box->setValue(2.0); freq2box->setVisible(false); orderbox = new QSpinBox(filterdialog); orderbox->setGeometry(160, 105, 120, 25); orderbox->setMinimum(1); orderbox->setMaximum(8); orderbox->setSingleStep(1); orderbox->setValue(1); modelbox = new QComboBox(filterdialog); modelbox->setGeometry(20, 105, 120, 25); modelbox->addItem("Butterworth"); modelbox->addItem("Chebyshev"); modelbox->addItem("Bessel"); modelbox->addItem("Moving Average"); ripplebox = new QDoubleSpinBox(filterdialog); ripplebox->setGeometry(300, 105, 120, 25); ripplebox->setDecimals(6); ripplebox->setSuffix(" dB"); ripplebox->setMinimum(0.1); ripplebox->setMaximum(6.0); ripplebox->setValue(1.0); ripplebox->setVisible(false); listlabel = new QLabel(filterdialog); listlabel->setGeometry(440, 20, 100, 25); listlabel->setText("Select signals:"); list = new QListWidget(filterdialog); list->setGeometry(440, 45, 160, 300); list->setSelectionBehavior(QAbstractItemView::SelectRows); list->setSelectionMode(QAbstractItemView::ExtendedSelection); CancelButton = new QPushButton(filterdialog); CancelButton->setGeometry(300, 320, 100, 25); CancelButton->setText("&Cancel"); ApplyButton = new QPushButton(filterdialog); ApplyButton->setGeometry(20, 320, 100, 25); ApplyButton->setText("&Apply"); curve1 = new FilterCurve(filterdialog); curve1->setGeometry(20, 145, 400, 150); curve1->setH_RasterSize(10); curve1->setV_RasterSize(14); for(i=0; isignalcomps; i++) { item = new QListWidgetItem; if(mainwindow->signalcomp[i]->alias[0] != 0) { item->setText(mainwindow->signalcomp[i]->alias); } else { item->setText(mainwindow->signalcomp[i]->signallabel); } item->setData(Qt::UserRole, QVariant(i)); list->addItem(item); } list->setCurrentRow(0); QObject::connect(ApplyButton, SIGNAL(clicked()), this, SLOT(ApplyButtonClicked())); QObject::connect(CancelButton, SIGNAL(clicked()), filterdialog, SLOT(close())); QObject::connect(freqbox, SIGNAL(valueChanged(double)), this, SLOT(frequencyboxvaluechanged(double))); QObject::connect(typebox, SIGNAL(currentIndexChanged(int)), this, SLOT(filtertypeboxvaluechanged(int))); QObject::connect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); QObject::connect(modelbox, SIGNAL(currentIndexChanged(int)), this, SLOT(filtermodelboxvaluechanged(int))); QObject::connect(ripplebox, SIGNAL(valueChanged(double)), this, SLOT(rippleboxvaluechanged(double))); QObject::connect(freq2box, SIGNAL(valueChanged(double)), this, SLOT(freq2boxvaluechanged(double))); updatecurve(); filterdialog->exec(); } void UI_FilterDialog::updatecurve(void) { int i, type=0, rate=3200, order=1, model=0; double frequency=150.0, ripple=1.0, frequency2=200.0; char *err; FidFilter *ff; order = orderbox->value(); type = typebox->currentIndex(); model = modelbox->currentIndex(); if(model == FILTERMODEL_MOVINGAVERAGE) { for(i=0; idrawCurve(array, arraysize, 1.4, 0.0); return; } ripple = -(ripplebox->value()); if((type == FILTERTYPE_BANDPASS) || (type == FILTERTYPE_BANDSTOP)) { frequency = frequency2 * (freqbox->value() / freq2box->value()); } spec_str_1[0] = 0; if(type == FILTERTYPE_HIGHPASS) { if(model == FILTERMODEL_BUTTERWORTH) { sprintf(spec_str_1, "HpBu%i/%f", order, frequency); } if(model == FILTERMODEL_CHEBYSHEV) { sprintf(spec_str_1, "HpCh%i/%f/%f", order, ripple, frequency); } if(model == FILTERMODEL_BESSEL) { sprintf(spec_str_1, "HpBe%i/%f", order, frequency); } } if(type == FILTERTYPE_LOWPASS) { if(model == FILTERMODEL_BUTTERWORTH) { sprintf(spec_str_1, "LpBu%i/%f", order, frequency); } if(model == FILTERMODEL_CHEBYSHEV) { sprintf(spec_str_1, "LpCh%i/%f/%f", order, ripple, frequency); } if(model == FILTERMODEL_BESSEL) { sprintf(spec_str_1, "LpBe%i/%f", order, frequency); } } if(type == FILTERTYPE_NOTCH) { sprintf(spec_str_1, "BsRe/%i/%f", order, frequency); } if(type == FILTERTYPE_BANDPASS) { if(model == FILTERMODEL_BUTTERWORTH) { sprintf(spec_str_1, "BpBu%i/%f-%f", order, frequency, frequency2); } if(model == FILTERMODEL_CHEBYSHEV) { sprintf(spec_str_1, "BpCh%i/%f/%f-%f", order, ripple, frequency, frequency2); } if(model == FILTERMODEL_BESSEL) { sprintf(spec_str_1, "BpBe%i/%f-%f", order, frequency, frequency2); } } if(type == FILTERTYPE_BANDSTOP) { if(model == FILTERMODEL_BUTTERWORTH) { sprintf(spec_str_1, "BsBu%i/%f-%f", order, frequency, frequency2); } if(model == FILTERMODEL_CHEBYSHEV) { sprintf(spec_str_1, "BsCh%i/%f/%f-%f", order, ripple, frequency, frequency2); } if(model == FILTERMODEL_BESSEL) { sprintf(spec_str_1, "BsBe%i/%f-%f", order, frequency, frequency2); } } strcpy(spec_str_2, spec_str_1); filter_spec = spec_str_2; err = fid_parse(rate, &filter_spec, &ff); if(err != NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", err); messagewindow.exec(); free(err); return; } for(i=0; idrawCurve(array, arraysize, 1.4, 0.0, array_pha, arraysize, 0.0, 1.0, frequency, frequency2); } else { curve1->drawCurve(array, arraysize, 1.4, 0.0, array_pha, arraysize, 0.0, 1.0, frequency); } free(ff); } void UI_FilterDialog::rippleboxvaluechanged(double value) { last_ripple = value; updatecurve(); } void UI_FilterDialog::filtermodelboxvaluechanged(int model) { int type; QObject::disconnect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); QObject::disconnect(modelbox, SIGNAL(currentIndexChanged(int)), this, SLOT(filtermodelboxvaluechanged(int))); type = typebox->currentIndex(); last_model = model; freqboxlabel->setText("Frequency"); freqbox->setVisible(true); if(type != FILTERTYPE_NOTCH) { orderboxlabel->setText("Order"); orderboxlabel->setVisible(true); if((type == FILTERTYPE_BANDPASS) || (type == FILTERTYPE_BANDSTOP)) { if(model == FILTERMODEL_BESSEL) { orderbox->setMaximum(10); } else { orderbox->setMaximum(16); } } else { orderbox->setMaximum(8); } orderbox->setSingleStep(1); orderbox->setMinimum(1); orderbox->setValue(last_order); orderbox->setVisible(true); } if(model == FILTERMODEL_BUTTERWORTH) { ripplebox->setVisible(false); orderlabel->setText("Slope roll-off:"); orderlabel->setVisible(true); ordervaluelabel->setText(QString::number(6 * orderbox->value(), 'f', 0).append(" dB / octave")); ordervaluelabel->setVisible(true); } if(model == FILTERMODEL_CHEBYSHEV) { orderlabel->setText("passband ripple"); orderlabel->setVisible(true); ordervaluelabel->setVisible(false); ripplebox->setVisible(true); } if(model == FILTERMODEL_BESSEL) { ripplebox->setVisible(false); ordervaluelabel->setVisible(false); orderlabel->setVisible(false); } if(model == FILTERMODEL_MOVINGAVERAGE) { orderlabel->setVisible(false); ordervaluelabel->setVisible(false); freqboxlabel->setVisible(false); freqbox2label->setVisible(false); freqbox->setVisible(false); ripplebox->setVisible(false); orderboxlabel->setText("Samples"); orderbox->setMaximum(10000); orderbox->setSingleStep(1); orderbox->setMinimum(2); orderbox->setValue(last_samples); } updatecurve(); QObject::connect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); QObject::connect(modelbox, SIGNAL(currentIndexChanged(int)), this, SLOT(filtermodelboxvaluechanged(int))); } void UI_FilterDialog::orderboxvaluechanged(int order) { int type, model; char str[256]; type = typebox->currentIndex(); model = modelbox->currentIndex(); if(type == FILTERTYPE_NOTCH) { sprintf(str,"%f Hz", freqbox->value() / orderbox->value()); remove_trailing_zeros(str); ordervaluelabel->setText(str); ordervaluelabel->setVisible(true); last_qfactor = order; } else { if((type == FILTERTYPE_BANDPASS) || (type == FILTERTYPE_BANDSTOP)) { last_order = order / 2; } else { if(model == FILTERMODEL_MOVINGAVERAGE) { last_samples = order; } else { last_order = order; } } if(model == FILTERMODEL_BUTTERWORTH) { orderlabel->setText("Slope roll-off:"); orderlabel->setVisible(true); ordervaluelabel->setText(QString::number(6 * last_order, 'f', 0).append(" dB / octave")); ordervaluelabel->setVisible(true); } if(model == FILTERMODEL_CHEBYSHEV) { orderlabel->setText("passband ripple"); orderlabel->setVisible(true); ordervaluelabel->setVisible(false); } if(model == FILTERMODEL_BESSEL) { ripplebox->setVisible(false); orderlabel->setVisible(false); ordervaluelabel->setVisible(false); } if(model == FILTERMODEL_MOVINGAVERAGE) { orderlabel->setVisible(false); ordervaluelabel->setVisible(false); freqboxlabel->setVisible(false); } } updatecurve(); } void UI_FilterDialog::filtertypeboxvaluechanged(int type) { char str[256]; QObject::disconnect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); QObject::disconnect(modelbox, SIGNAL(currentIndexChanged(int)), this, SLOT(filtermodelboxvaluechanged(int))); if(type == FILTERTYPE_NOTCH) { ripplebox->setVisible(false); orderboxlabel->setText("Notch Q-factor"); orderboxlabel->setVisible(true); orderbox->setMaximum(100); orderbox->setSingleStep(1); orderbox->setMinimum(3); orderbox->setValue(last_qfactor); orderbox->setVisible(true); orderlabel->setText("-3 dB bandwidth:"); sprintf(str,"%f Hz", freqbox->value() / orderbox->value()); remove_trailing_zeros(str); ordervaluelabel->setText(str); ordervaluelabel->setVisible(true); modelbox->clear(); modelbox->addItem("Resonator"); modelbox->setVisible(true); } else { orderboxlabel->setText("Order"); orderboxlabel->setVisible(true); if((type == FILTERTYPE_BANDPASS) || (type == FILTERTYPE_BANDSTOP)) { if(last_model == FILTERMODEL_BESSEL) { orderbox->setMaximum(10); } else { orderbox->setMaximum(16); } orderbox->setSingleStep(2); orderbox->setMinimum(2); orderbox->setValue(last_order * 2); orderbox->setVisible(true); } else { orderbox->setMaximum(8); orderbox->setSingleStep(1); orderbox->setMinimum(1); orderbox->setValue(last_order); orderbox->setVisible(true); } if(last_model == FILTERMODEL_MOVINGAVERAGE) { if((type == FILTERTYPE_HIGHPASS) || (type == FILTERTYPE_LOWPASS)) { ripplebox->setVisible(false); ordervaluelabel->setVisible(false); orderlabel->setVisible(false); ordervaluelabel->setVisible(false); orderboxlabel->setText("Samples"); orderboxlabel->setVisible(true); orderbox->setMaximum(10000); orderbox->setSingleStep(1); orderbox->setMinimum(2); orderbox->setValue(last_samples); orderbox->setVisible(true); } else { last_model = FILTERMODEL_BUTTERWORTH; } } if(last_model == FILTERMODEL_BUTTERWORTH) { ripplebox->setVisible(false); orderlabel->setText("Slope roll-off:"); orderlabel->setVisible(true); ordervaluelabel->setText(QString::number(6 * last_order, 'f', 0).append(" dB / octave")); ordervaluelabel->setVisible(true); } if(last_model == FILTERMODEL_CHEBYSHEV) { ordervaluelabel->setVisible(false); ripplebox->setVisible(true); orderlabel->setText("passband ripple"); orderlabel->setVisible(true); } if(last_model == FILTERMODEL_BESSEL) { ripplebox->setVisible(false); orderlabel->setVisible(false); ordervaluelabel->setVisible(false); } modelbox->clear(); modelbox->addItem("Butterworth"); modelbox->addItem("Chebyshev"); modelbox->addItem("Bessel"); if((type == FILTERTYPE_HIGHPASS) || (type == FILTERTYPE_LOWPASS)) { modelbox->addItem("Moving Average"); } modelbox->setCurrentIndex(last_model); } if((type == FILTERTYPE_BANDPASS) || (type == FILTERTYPE_BANDSTOP)) { freqboxlabel->setText("Frequency 1"); freqboxlabel->setVisible(true); freqbox2label->setText("Frequency 2"); freqbox2label->setVisible(true); freqbox->setVisible(true); freq2box->setVisible(true); } else { freqbox2label->setVisible(false); freq2box->setVisible(false); if(last_model == FILTERMODEL_MOVINGAVERAGE) { orderlabel->setVisible(false); ordervaluelabel->setVisible(false); freqboxlabel->setVisible(false); } else { freqboxlabel->setText("Frequency"); freqboxlabel->setVisible(true); } } QObject::connect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); QObject::connect(modelbox, SIGNAL(currentIndexChanged(int)), this, SLOT(filtermodelboxvaluechanged(int))); updatecurve(); } void UI_FilterDialog::frequencyboxvaluechanged(double value) { char str[256]; if(freq2box->value() < (value * 1.12)) { freq2box->setValue(value * 1.12); } if(typebox->currentIndex() == FILTERTYPE_NOTCH) { sprintf(str,"%f Hz", freqbox->value() / orderbox->value()); remove_trailing_zeros(str); ordervaluelabel->setText(str); } updatecurve(); } void UI_FilterDialog::freq2boxvaluechanged(double value) { QObject::disconnect(freqbox, SIGNAL(valueChanged(double)), this, SLOT(frequencyboxvaluechanged(double))); if(freqbox->value() > (value * 0.9)) { freqbox->setValue(value * 0.9); } QObject::connect(freqbox, SIGNAL(valueChanged(double)), this, SLOT(frequencyboxvaluechanged(double))); updatecurve(); } void UI_FilterDialog::ApplyButtonClicked() { int i, s, n, type, model, order; double frequency, frequency2, ripple; char *err; QListWidgetItem *item; QList selectedlist; selectedlist = list->selectedItems(); n = selectedlist.size(); if(!n) { filterdialog->close(); return; } frequency = freqbox->value(); frequency2 = freq2box->value(); order = orderbox->value(); type = typebox->currentIndex(); model = modelbox->currentIndex(); ripple = -(ripplebox->value()); for(i=0; idata(Qt::UserRole).toInt(); if((mainwindow->signalcomp[s]->filter_cnt + mainwindow->signalcomp[s]->fidfilter_cnt) > MAXFILTERS - 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The maximum amount of filters per signal has been reached.\n" "Remove some filters first."); messagewindow.exec(); return; } } if((model == FILTERMODEL_BUTTERWORTH) || (model == FILTERMODEL_CHEBYSHEV) || (model == FILTERMODEL_BESSEL)) { for(i=0; irow(item); if((type == FILTERTYPE_HIGHPASS) || (type == FILTERTYPE_LOWPASS) || (type == FILTERTYPE_NOTCH)) { if(frequency >= ((mainwindow->signalcomp[s]->edfhdr->edfparam[mainwindow->signalcomp[s]->edfsignal[0]].smp_per_record / mainwindow->signalcomp[s]->edfhdr->data_record_duration) / 2.0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The frequency of the filter(s) must be less than: samplerate / 2"); messagewindow.exec(); return; } } else { if(frequency2 >= ((mainwindow->signalcomp[s]->edfhdr->edfparam[mainwindow->signalcomp[s]->edfsignal[0]].smp_per_record / mainwindow->signalcomp[s]->edfhdr->data_record_duration) / 2.0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The frequency of the filter(s) must be less than: samplerate / 2"); messagewindow.exec(); return; } } } spec_str_1[0] = 0; if(type == FILTERTYPE_HIGHPASS) { if(model == FILTERMODEL_BUTTERWORTH) { sprintf(spec_str_1, "HpBu%i/%f", order, frequency); } if(model == FILTERMODEL_CHEBYSHEV) { sprintf(spec_str_1, "HpCh%i/%f/%f", order, ripple, frequency); } if(model == FILTERMODEL_BESSEL) { sprintf(spec_str_1, "HpBe%i/%f", order, frequency); } } if(type == FILTERTYPE_LOWPASS) { if(model == FILTERMODEL_BUTTERWORTH) { sprintf(spec_str_1, "LpBu%i/%f", order, frequency); } if(model == FILTERMODEL_CHEBYSHEV) { sprintf(spec_str_1, "LpCh%i/%f/%f", order, ripple, frequency); } if(model == FILTERMODEL_BESSEL) { sprintf(spec_str_1, "LpBe%i/%f", order, frequency); } } if(type == FILTERTYPE_NOTCH) { sprintf(spec_str_1, "BsRe/%i/%f", order, frequency); } if(type == FILTERTYPE_BANDPASS) { if(model == FILTERMODEL_BUTTERWORTH) { sprintf(spec_str_1, "BpBu%i/%f-%f", order, frequency, frequency2); } if(model == FILTERMODEL_CHEBYSHEV) { sprintf(spec_str_1, "BpCh%i/%f/%f-%f", order, ripple, frequency, frequency2); } if(model == FILTERMODEL_BESSEL) { sprintf(spec_str_1, "BpBe%i/%f-%f", order, frequency, frequency2); } } if(type == FILTERTYPE_BANDSTOP) { if(model == FILTERMODEL_BUTTERWORTH) { sprintf(spec_str_1, "BsBu%i/%f-%f", order, frequency, frequency2); } if(model == FILTERMODEL_CHEBYSHEV) { sprintf(spec_str_1, "BsCh%i/%f/%f-%f", order, ripple, frequency, frequency2); } if(model == FILTERMODEL_BESSEL) { sprintf(spec_str_1, "BsBe%i/%f-%f", order, frequency, frequency2); } } for(i=0; irow(item); strcpy(spec_str_2, spec_str_1); filter_spec = spec_str_2; err = fid_parse(((double)(mainwindow->signalcomp[s]->edfhdr->edfparam[mainwindow->signalcomp[s]->edfsignal[0]].smp_per_record)) / mainwindow->signalcomp[s]->edfhdr->data_record_duration, &filter_spec, &mainwindow->signalcomp[s]->fidfilter[mainwindow->signalcomp[s]->fidfilter_cnt]); if(err != NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", err); messagewindow.exec(); free(err); filterdialog->close(); return; } mainwindow->signalcomp[s]->fid_run[mainwindow->signalcomp[s]->fidfilter_cnt] = fid_run_new(mainwindow->signalcomp[s]->fidfilter[mainwindow->signalcomp[s]->fidfilter_cnt], &mainwindow->signalcomp[s]->fidfuncp[mainwindow->signalcomp[s]->fidfilter_cnt]); mainwindow->signalcomp[s]->fidbuf[mainwindow->signalcomp[s]->fidfilter_cnt] = fid_run_newbuf(mainwindow->signalcomp[s]->fid_run[mainwindow->signalcomp[s]->fidfilter_cnt]); mainwindow->signalcomp[s]->fidbuf2[mainwindow->signalcomp[s]->fidfilter_cnt] = fid_run_newbuf(mainwindow->signalcomp[s]->fid_run[mainwindow->signalcomp[s]->fidfilter_cnt]); mainwindow->signalcomp[s]->fidfilter_freq[mainwindow->signalcomp[s]->fidfilter_cnt] = frequency; mainwindow->signalcomp[s]->fidfilter_freq2[mainwindow->signalcomp[s]->fidfilter_cnt] = frequency2; mainwindow->signalcomp[s]->fidfilter_ripple[mainwindow->signalcomp[s]->fidfilter_cnt] = ripple; mainwindow->signalcomp[s]->fidfilter_order[mainwindow->signalcomp[s]->fidfilter_cnt] = order; mainwindow->signalcomp[s]->fidfilter_model[mainwindow->signalcomp[s]->fidfilter_cnt] = model; mainwindow->signalcomp[s]->fidfilter_type[mainwindow->signalcomp[s]->fidfilter_cnt] = type; mainwindow->signalcomp[s]->fidfilter_setup[mainwindow->signalcomp[s]->fidfilter_cnt] = 1; mainwindow->signalcomp[s]->fidfilter_cnt++; } } if(model == FILTERMODEL_MOVINGAVERAGE) { for(i=0; irow(item); mainwindow->signalcomp[s]->ravg_filter[mainwindow->signalcomp[s]->ravg_filter_cnt] = create_ravg_filter(type, order); if(mainwindow->signalcomp[s]->ravg_filter[mainwindow->signalcomp[s]->ravg_filter_cnt] == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while creating a moving average filter."); messagewindow.exec(); filterdialog->close(); return; } mainwindow->signalcomp[s]->ravg_filter_type[mainwindow->signalcomp[s]->ravg_filter_cnt] = type; mainwindow->signalcomp[s]->ravg_filter_size[mainwindow->signalcomp[s]->ravg_filter_cnt] = order; mainwindow->signalcomp[s]->ravg_filter_setup[mainwindow->signalcomp[s]->ravg_filter_cnt] = 1; mainwindow->signalcomp[s]->ravg_filter_cnt++; } } filterdialog->close(); mainwindow->setup_viewbuf(); } edfbrowser_157_source/PaxHeaders.7921/edit_predefined_mtg.h0000644000000000000000000000013212646460742021020 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/edit_predefined_mtg.h0000644000175000001440000000366212646460742021370 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef EDITPREDEFINEDMTGFORM1_H #define EDITPREDEFINEDMTGFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" class UI_Mainwindow; class UI_edit_predefined_mtg_window : public QObject { Q_OBJECT public: UI_edit_predefined_mtg_window(QWidget *parent); UI_Mainwindow *mainwindow; private: QDialog *edit_predefined_mtg_Dialog, *dialog; QListWidget *mtg_path_list; QPushButton *CloseButton, *button1, *button2, *button3; QListWidgetItem *listItem; int row; private slots: void rowClicked(QListWidgetItem *); void adEntry(); void removeEntry(); }; #endif edfbrowser_157_source/PaxHeaders.7921/bdf_triggers.h0000644000000000000000000000013212646460742017500 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/bdf_triggers.h0000644000175000001440000000267012646460742020046 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef BDF_TRIGGERS_H #define BDF_TRIGGERS_H #include #include #include #include #include #include #include #include #include "global.h" #include "edf_annot_list.h" class BDF_triggers { public: int get_triggers(struct edfhdrblock *, struct annotationblock **); private: struct edfhdrblock *edfhdr; }; #endif // BDF_TRIGGERS_H edfbrowser_157_source/PaxHeaders.7921/bdf2edf.cpp0000644000000000000000000000013212646460742016666 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/bdf2edf.cpp0000644000175000001440000004654012646460742017240 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "bdf2edf.h" UI_BDF2EDFwindow::UI_BDF2EDFwindow(QWidget *w_parent) { mainwindow = (UI_Mainwindow *)w_parent; recent_opendir = mainwindow->recent_opendir; recent_savedir = mainwindow->recent_savedir; myobjectDialog = new QDialog; myobjectDialog->setMinimumSize(600, 526); myobjectDialog->setMaximumSize(600, 526); myobjectDialog->setWindowTitle("BDF+ to EDF+ converter"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); label1 = new QLabel(myobjectDialog); label1->setGeometry(20, 20, 560, 25); label2 = new QLabel(myobjectDialog); label2->setGeometry(440, 196, 100, 25); label2->setText("High-pass filter"); label3 = new QLabel(myobjectDialog); label3->setGeometry(440, 300, 100, 25); label3->setText("Divider"); SignalsTablewidget = new QTableWidget(myobjectDialog); SignalsTablewidget->setGeometry(20, 66, 400, 380); SignalsTablewidget->setSelectionMode(QAbstractItemView::NoSelection); SignalsTablewidget->setColumnCount(3); SignalsTablewidget->setColumnWidth(0, 140); SignalsTablewidget->setColumnWidth(1, 100); SignalsTablewidget->setColumnWidth(2, 100); QStringList horizontallabels; horizontallabels += "Label"; horizontallabels += "HighPassFilter"; horizontallabels += "Divider"; SignalsTablewidget->setHorizontalHeaderLabels(horizontallabels); spinBox1 = new QDoubleSpinBox(myobjectDialog); spinBox1->setGeometry(440, 232, 100, 25); spinBox1->setDecimals(3); spinBox1->setSuffix(" Hz"); spinBox1->setRange(0.001, 100.0); spinBox1->setValue(0.1); spinBox2 = new QDoubleSpinBox(myobjectDialog); spinBox2->setGeometry(440, 336, 100, 25); spinBox2->setDecimals(3); spinBox2->setRange(1.0, 256.0); spinBox2->setValue(1.0); pushButton1 = new QPushButton(myobjectDialog); pushButton1->setGeometry(20, 476, 100, 25); pushButton1->setText("Select File"); pushButton2 = new QPushButton(myobjectDialog); pushButton2->setGeometry(480, 476, 100, 25); pushButton2->setText("Close"); pushButton3 = new QPushButton(myobjectDialog); pushButton3->setGeometry(200, 476, 100, 25); pushButton3->setText("Convert"); pushButton3->setEnabled(false); pushButton4 = new QPushButton(myobjectDialog); pushButton4->setGeometry(440, 66, 140, 25); pushButton4->setText("Select all signals"); pushButton4->setEnabled(false); pushButton5 = new QPushButton(myobjectDialog); pushButton5->setGeometry(440, 118, 140, 25); pushButton5->setText("Deselect all signals"); pushButton5->setEnabled(false); 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(spinBox1, SIGNAL(valueChanged(double)), this, SLOT(spinbox1_changed(double))); QObject::connect(spinBox2, SIGNAL(valueChanged(double)), this, SLOT(spinbox2_changed(double))); QObject::connect(myobjectDialog, SIGNAL(destroyed()), this, SLOT(free_edfheader())); edfhdr = NULL; inputfile = NULL; outputfile = NULL; inputpath[0] = 0; myobjectDialog->exec(); } void UI_BDF2EDFwindow::free_edfheader() { if(edfhdr != NULL) { free(edfhdr->edfparam); free(edfhdr); edfhdr = NULL; } } void UI_BDF2EDFwindow::Select_all_signals() { int i; if(edfhdr==NULL) { return; } for(i=0; iedfsignals; i++) { if(!edfhdr->edfparam[i].annotation) { ((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->setCheckState(Qt::Checked); } } } void UI_BDF2EDFwindow::Deselect_all_signals() { int i; if(edfhdr==NULL) { return; } for(i=0; iedfsignals; i++) { if(!edfhdr->edfparam[i].annotation) { ((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->setCheckState(Qt::Unchecked); } } } void UI_BDF2EDFwindow::spinbox1_changed(double value) { int i; if(edfhdr==NULL) { return; } for(i=0; iedfsignals; i++) { if(!edfhdr->edfparam[i].annotation) { ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 1)))->setValue(value); } } } void UI_BDF2EDFwindow::spinbox2_changed(double value) { int i; if(edfhdr==NULL) { return; } for(i=0; iedfsignals; i++) { if(!edfhdr->edfparam[i].annotation) { ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 2)))->setValue(value); } } } void UI_BDF2EDFwindow::SelectFileButton() { int i; char txt_string[2048]; if(edfhdr!=NULL) { label1->setText(""); SignalsTablewidget->setRowCount(0); free_edfheader(); inputfile = NULL; outputfile = NULL; inputpath[0] = 0; pushButton3->setEnabled(false); pushButton4->setEnabled(false); pushButton5->setEnabled(false); } strcpy(inputpath, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "BDF files (*.bdf *.BDF)").toLocal8Bit().data()); if(!strcmp(inputpath, "")) { return; } get_directory_from_path(recent_opendir, inputpath, MAX_PATH_LENGTH); inputfile = fopeno(inputpath, "rb"); if(inputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for reading.", inputpath); QMessageBox messagewindow(QMessageBox::Critical, "Error", QString::fromLocal8Bit(txt_string)); messagewindow.exec(); return; } /***************** check if the file is valid ******************************/ EDFfileCheck EDFfilechecker; edfhdr = EDFfilechecker.check_edf_file(inputfile, txt_string); if(edfhdr==NULL) { fclose(inputfile); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); return; } if(!edfhdr->bdf) { fclose(inputfile); QMessageBox messagewindow(QMessageBox::Critical, "Error", "File is not a BDF file."); messagewindow.exec(); free_edfheader(); return; } /***************** load signalproperties ******************************/ label1->setText(QString::fromLocal8Bit(inputpath)); SignalsTablewidget->setRowCount(edfhdr->edfsignals); for(i=0; iedfsignals; 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) { SignalsTablewidget->setCellWidget(i, 1, new QDoubleSpinBox); ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 1)))->setDecimals(3); ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 1)))->setSuffix(" Hz"); ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 1)))->setRange(0.001, 100.0); ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 1)))->setValue(spinBox1->value()); SignalsTablewidget->setCellWidget(i, 2, new QDoubleSpinBox); ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 2)))->setDecimals(3); ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 2)))->setRange(1.0, 256.0); ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 2)))->setValue(spinBox2->value()); } else { ((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->setEnabled(false); } } pushButton3->setEnabled(true); pushButton4->setEnabled(true); pushButton5->setEnabled(true); } void UI_BDF2EDFwindow::StartConversion() { int i, j, k, datrecs, new_edfsignals, datarecords, len, progress_steps; char *readbuf, scratchpad[256]; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; union { signed short one_short; unsigned char two_bytes[2]; } var2; pushButton3->setEnabled(false); pushButton4->setEnabled(false); pushButton5->setEnabled(false); if(edfhdr==NULL) { return; } if(edfhdr->edfsignals>MAXSIGNALS) { return; } new_edfsignals = 0; for(i=0; iedfsignals; i++) { if(!edfhdr->edfparam[i].annotation) { if(((QCheckBox *)(SignalsTablewidget->cellWidget(i, 0)))->checkState()==Qt::Checked) { signalslist[new_edfsignals] = i; annotlist[new_edfsignals] = 0; filterlist[new_edfsignals] = create_filter(0, ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 1)))->value(), 1.0 / (edfhdr->data_record_duration / edfhdr->edfparam[i].smp_per_record)); dividerlist[new_edfsignals] = ((QDoubleSpinBox *)(SignalsTablewidget->cellWidget(i, 2)))->value(); new_edfsignals++; } } else { signalslist[new_edfsignals] = i; annotlist[new_edfsignals] = 1; filterlist[new_edfsignals] = create_filter(0, 0.01, 1.0 / (edfhdr->data_record_duration / edfhdr->edfparam[i].smp_per_record)); dividerlist[new_edfsignals] = 1.0; new_edfsignals++; } } datarecords = edfhdr->datarecords; QProgressDialog progress("Converting...", "Abort", 0, datarecords, myobjectDialog); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); progress.reset(); if(!new_edfsignals) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "You must select at least one signal."); messagewindow.exec(); goto END_1; } readbuf = (char *)malloc(edfhdr->recordsize); if(readbuf==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error, (readbuf)."); messagewindow.exec(); goto END_2; } /////////////////////////// write header //////////////////////////////////////// outputpath[0] = 0; if(recent_savedir[0]!=0) { strcpy(outputpath, recent_savedir); strcat(outputpath, "/"); } len = strlen(outputpath); get_filename_from_path(outputpath + len, inputpath, MAX_PATH_LENGTH - len); remove_extension_from_filename(outputpath); strcat(outputpath, ".edf"); strcpy(outputpath, QFileDialog::getSaveFileName(0, "Select outputfile", QString::fromLocal8Bit(outputpath), "EDF files (*.edf *.EDF)").toLocal8Bit().data()); if(!strcmp(outputpath, "")) { goto END_2; } get_directory_from_path(recent_savedir, outputpath, MAX_PATH_LENGTH); if(mainwindow->file_is_opened(outputpath)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, selected file is in use."); messagewindow.exec(); goto END_2; } outputfile = fopeno(outputpath, "wb"); if(outputfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open outputfile for writing."); messagewindow.exec(); goto END_2; } fprintf(outputfile, "0 "); fseeko(inputfile, 8LL, SEEK_SET); if(fread(scratchpad, 176, 1, inputfile)!=1) { showpopupmessage("Error", "Read error (1)."); QMessageBox messagewindow(QMessageBox::Critical, "Error", "Read error (1)."); messagewindow.exec(); goto END_3; } if(fwrite(scratchpad, 176, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Write error (1)."); messagewindow.exec(); goto END_3; } fprintf(outputfile, "%-8i", new_edfsignals * 256 + 256); if(edfhdr->bdfplus) { if(edfhdr->discontinuous) { fprintf(outputfile, "EDF+D"); } else { fprintf(outputfile, "EDF+C"); } for(i=0; i<39; i++) { fputc(' ', outputfile); } } else { for(i=0; i<44; i++) { fputc(' ', outputfile); } } fprintf(outputfile, "%-8i", datarecords); snprintf(scratchpad, 256, "%f", edfhdr->data_record_duration); convert_trailing_zeros_to_spaces(scratchpad); if(scratchpad[7]=='.') { scratchpad[7] = ' '; } scratchpad[8] = 0; fprintf(outputfile, "%s", scratchpad); fprintf(outputfile, "%-4i", new_edfsignals); for(i=0; iedfparam[signalslist[i]].label); } } for(i=0; iedfparam[signalslist[i]].transducer); } for(i=0; iedfparam[signalslist[i]].physdimension); } for(i=0; iedfparam[signalslist[i]].bitvalue * -32768.0 * dividerlist[i]); convert_trailing_zeros_to_spaces(scratchpad); if(scratchpad[7]=='.') { scratchpad[7] = ' '; } scratchpad[8] = 0; fprintf(outputfile, "%s", scratchpad); } } for(i=0; iedfparam[signalslist[i]].bitvalue * 32767.0 * dividerlist[i]); convert_trailing_zeros_to_spaces(scratchpad); if(scratchpad[7]=='.') { scratchpad[7] = ' '; } scratchpad[8] = 0; fprintf(outputfile, "%s", scratchpad); } } for(i=0; icellWidget(signalslist[i], 1)))->value()); remove_trailing_zeros(scratchpad); strcat(scratchpad, "Hz "); strcat(scratchpad, edfhdr->edfparam[signalslist[i]].prefilter); for(j=strlen(scratchpad); j<200; j++) { scratchpad[j] = ' '; } scratchpad[200] = 0; for(j=0; j<80; j++) { if(!strncmp(scratchpad + j, "No filtering", 12)) { for(k=j; k<(j+12); k++) { scratchpad[k] = ' '; } } } for(j=0; j<80; j++) { if(!strncmp(scratchpad + j, "None", 4)) { for(k=j; k<(j+4); k++) { scratchpad[k] = ' '; } } } for(j=0; j<80; j++) { if(!strncmp(scratchpad + j, "HP: DC;", 7)) { for(k=j; k<(j+7); k++) { scratchpad[k] = ' '; } } } scratchpad[80] = 0; fprintf(outputfile, "%s", scratchpad); } } for(i=0; iedfparam[signalslist[i]].smp_per_record % 2) { fprintf(outputfile, "%-8i", ((edfhdr->edfparam[signalslist[i]].smp_per_record * 15) / 10) + 1); } else { fprintf(outputfile, "%-8i", (edfhdr->edfparam[signalslist[i]].smp_per_record * 15) / 10); } } else { fprintf(outputfile, "%-8i", edfhdr->edfparam[signalslist[i]].smp_per_record); } } for(i=0; i<(new_edfsignals * 32); i++) { fputc(' ', outputfile); } ///////////////////////////// start conversion ////////////////////////////////////// progress_steps = datarecords / 100; if(progress_steps < 1) { progress_steps = 1; } fseeko(inputfile, (long long)(edfhdr->hdrsize), SEEK_SET); for(datrecs=0; datrecsprocessEvents(); if(progress.wasCanceled() == true) { goto END_3; } } if(fread(readbuf, edfhdr->recordsize, 1, inputfile) != 1) { progress.reset(); showpopupmessage("Error", "Read error (2)."); goto END_3; } for(i=0; iedfparam[signalslist[i]].buf_offset, edfhdr->edfparam[signalslist[i]].smp_per_record * 3, 1, outputfile)!=1) { progress.reset(); showpopupmessage("Error", "Write error (2)."); goto END_3; } if(edfhdr->edfparam[signalslist[i]].smp_per_record % 2) { if(fputc(0, outputfile)==EOF) { progress.reset(); showpopupmessage("Error", "Write error (3)."); goto END_3; } } } else { for(j=0; jedfparam[signalslist[i]].smp_per_record; j++) { var.two[0] = *((unsigned short *)(readbuf + edfhdr->edfparam[signalslist[i]].buf_offset + (j * 3))); var.four[2] = *((unsigned char *)(readbuf + edfhdr->edfparam[signalslist[i]].buf_offset + (j * 3) + 2)); if(var.four[2]&0x80) { var.four[3] = 0xff; } else { var.four[3] = 0x00; } var.one_signed += edfhdr->edfparam[signalslist[i]].offset; var.one_signed = first_order_filter(var.one_signed, filterlist[i]); var.one_signed /= dividerlist[i]; if(var.one_signed>32767) var.one_signed = 32767; if(var.one_signed<-32768) var.one_signed = -32768; var2.one_short = var.one_signed; fputc(var2.two_bytes[0], outputfile); if(fputc(var2.two_bytes[1], outputfile)==EOF) { progress.reset(); showpopupmessage("Error", "Write error (4)."); goto END_3; } } } } } progress.reset(); showpopupmessage("Ready", "Done."); END_3: fclose(outputfile); outputfile = NULL; END_2: free(readbuf); END_1: for(i=0; isetText(""); SignalsTablewidget->setRowCount(0); } void UI_BDF2EDFwindow::showpopupmessage(const char *str1, const char *str2) { QMessageBox messagewindow(QMessageBox::NoIcon, str1, str2); messagewindow.exec(); } edfbrowser_157_source/PaxHeaders.7921/edfbrowser.rc0000644000000000000000000000013212646460742017356 xustar0030 mtime=1452958178.254246709 30 atime=1452958178.254246709 30 ctime=1452958178.254246709 edfbrowser_157_source/edfbrowser.rc0000644000175000001440000000010112646460742017707 0ustar00guvusers00000000000000IDI_ICON1 ICON DISCARDABLE "images/edf.ico" edfbrowser_157_source/PaxHeaders.7921/print_to_bdf.cpp0000644000000000000000000000012712646460742020047 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/print_to_bdf.cpp0000644000175000001440000011003712646460742020406 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "print_to_bdf.h" void print_screen_to_bdf(UI_Mainwindow *mainwindow) { int i, j, k, p, n=0, records, records_written, signalcomps, duration_factor[MAXFILES], temp=0, bdfplus=0, tallen, annotationlist_nr=0, annotations_left=1, add_one_sec=0, annot_smp_per_record=16, type, len; long long duration, smpls_written[MAXSIGNALS], s2, preamble=0LL, smpls_preamble[MAXSIGNALS], taltime=0LL, l_temp, referencetime, annot_difftime=0LL; char path[MAX_PATH_LENGTH], scratchpad[512], datrecduration[8], *viewbuf; double frequency, frequency2, dig_value; FILE *outputfile; struct signalcompblock **signalcomp; union { signed int one_signed; signed short two_signed[2]; unsigned char four[4]; } wr_var; union { signed int one_signed; signed short two_signed[2]; unsigned char four[4]; } null_bytes[MAXSIGNALS]; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; struct annotationblock *annotations_pntr; struct date_time_struct date_time; ///////////////////////////////////////////////////////////////////////// signalcomps = mainwindow->signalcomps; signalcomp = mainwindow->signalcomp; viewbuf = mainwindow->viewbuf; annotations_pntr = mainwindow->annotationlist[0]; if((!mainwindow->files_open)||(!signalcomps)) { QMessageBox messagewindow(QMessageBox::Critical, "Print to BDF", "Put a signal on the screen and try again."); messagewindow.exec(); return; } for(i=0; ifiles_open; i++) { if(mainwindow->edfheaderlist[i]->discontinuous) { QMessageBox messagewindow(QMessageBox::Critical, "Print to BDF", "Sorry, discontinues BDF/EDF files can not be printed to BDF.\n"); messagewindow.exec(); return; } if(mainwindow->edfheaderlist[i]->edfplus || mainwindow->edfheaderlist[i]->bdfplus) { bdfplus = 1; for(j=0; jedfheaderlist[i]->nr_annot_chns; j++) { if(mainwindow->edfheaderlist[i]->edfparam[mainwindow->edfheaderlist[i]->annot_ch[j]].smp_per_record>annot_smp_per_record) { annot_smp_per_record = mainwindow->edfheaderlist[i]->edfparam[mainwindow->edfheaderlist[i]->annot_ch[j]].smp_per_record; } } } } annot_smp_per_record += 11; taltime = mainwindow->edfheaderlist[mainwindow->sel_viewtime]->starttime_offset; duration = 0; for(i=0; iedfhdr->long_data_record_duration>duration) { duration = signalcomp[i]->edfhdr->long_data_record_duration; n = i; } } fseeko(signalcomp[n]->edfhdr->file_hdl, 244LL, SEEK_SET); if(fread(datrecduration, 8, 1, signalcomp[n]->edfhdr->file_hdl)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); return; } temp = 0; for(i=0; iedfhdr->long_data_record_duration) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "This combination of files can not be printed to EDF\n" "because the quotient of the datarecordblock durations is not an integer."); messagewindow.exec(); return; } duration_factor[signalcomp[i]->filenum] = duration / signalcomp[i]->edfhdr->long_data_record_duration; temp += signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record; } path[0] = 0; if(mainwindow->recent_savedir[0]!=0) { strcpy(path, mainwindow->recent_savedir); strcat(path, "/"); } len = strlen(path); get_filename_from_path(path + len, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename, MAX_PATH_LENGTH - len); remove_extension_from_filename(path); strcat(path, "_screenprint.bdf"); strcpy(path, QFileDialog::getSaveFileName(0, "Print to BDF", QString::fromLocal8Bit(path), "BDF files (*.bdf *.BDF)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(mainwindow->recent_savedir, path, MAX_PATH_LENGTH); if(mainwindow->file_is_opened(path)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, selected file is in use."); messagewindow.exec(); return; } outputfile = fopeno(path, "wb"); if(outputfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not create a file for writing."); messagewindow.exec(); return; } referencetime = mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime; if(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime<0) { if((-mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime) % TIME_DIMENSION) { preamble = TIME_DIMENSION - ((-mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime) % TIME_DIMENSION); referencetime--; add_one_sec = 1; } } else { preamble = mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime % TIME_DIMENSION; if(preamble) add_one_sec = 1; } referencetime += (mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime / TIME_DIMENSION); utc_to_date_time(referencetime, &date_time); /************************* write BDF-header ***************************************/ fseeko(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl, 8LL, SEEK_SET); rewind(outputfile); if(bdfplus) { fputc(255, outputfile); fprintf(outputfile, "BIOSEMI"); if(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->edfplus || mainwindow->edfheaderlist[mainwindow->sel_viewtime]->bdfplus) { if(fread(scratchpad, 80, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad, 80, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } else { fprintf(outputfile, "X X X X "); if(fread(scratchpad, 80, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad, 72, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } fprintf(outputfile, "Startdate %02i-", date_time.day); switch(date_time.month) { case 1 : fprintf(outputfile, "JAN"); break; case 2 : fprintf(outputfile, "FEB"); break; case 3 : fprintf(outputfile, "MAR"); break; case 4 : fprintf(outputfile, "APR"); break; case 5 : fprintf(outputfile, "MAY"); break; case 6 : fprintf(outputfile, "JUN"); break; case 7 : fprintf(outputfile, "JUL"); break; case 8 : fprintf(outputfile, "AUG"); break; case 9 : fprintf(outputfile, "SEP"); break; case 10 : fprintf(outputfile, "OCT"); break; case 11 : fprintf(outputfile, "NOV"); break; case 12 : fprintf(outputfile, "DEC"); break; default : fprintf(outputfile, "ERR"); break; } fprintf(outputfile, "-%04i ", date_time.year); if(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->edfplus || mainwindow->edfheaderlist[mainwindow->sel_viewtime]->bdfplus) { if(fread(scratchpad, 80, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); fclose(outputfile); return; } if(scratchpad[10]=='X') { if(fwrite(scratchpad + 12, 58, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } else { if(fwrite(scratchpad + 22, 58, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } } else { fprintf(outputfile, "X X X "); if(fread(scratchpad, 80, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad + 28, 52, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } } else { if(fread(scratchpad, 160, 1, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->file_hdl)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); fclose(outputfile); return; } fputc(255, outputfile); fprintf(outputfile, "BIOSEMI"); if(fwrite(scratchpad, 160, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } fprintf(outputfile, "%02i.%02i.%02i%02i.%02i.%02i", date_time.day, date_time.month, date_time.year % 100, date_time.hour, date_time.minute, date_time.second); fprintf(outputfile, "%-8i", (signalcomps + bdfplus) * 256 + 256); if(bdfplus) { fprintf(outputfile, "BDF+C"); for(i=0; i<39; i++) fputc(' ', outputfile); } else { for(i=0; i<44; i++) fputc(' ', outputfile); } records = (int)(mainwindow->pagetime / duration); if(add_one_sec) { records += TIME_DIMENSION / duration; } fprintf(outputfile, "%-8i", records); if(fwrite(datrecduration, 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } fprintf(outputfile, "%-4i", signalcomps + bdfplus); for(i=0; isignallabel); strcat(scratchpad, " "); if(fwrite(scratchpad, 16, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } if(bdfplus) { if(fwrite("BDF Annotations ", 16, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].transducer, 80, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } if(bdfplus) { for(i=0; i<80; i++) fputc(' ', outputfile); } for(i=0; iphysdimension); strcat(scratchpad, " "); if(fwrite(scratchpad, 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } if(bdfplus) { for(i=0; i<8; i++) fputc(' ', outputfile); } for(i=0; iecg_filter == NULL) && (signalcomp[i]->zratio_filter == NULL)) { fseeko(signalcomp[i]->edfhdr->file_hdl, (long long)((signalcomp[i]->edfsignal[0] * 8) + (104 * signalcomp[i]->edfhdr->edfsignals) + 256), SEEK_SET); if(fread(scratchpad, 8, 1, signalcomp[i]->edfhdr->file_hdl)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad, 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } if(signalcomp[i]->ecg_filter != NULL) { if(fwrite("0 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } if(signalcomp[i]->zratio_filter != NULL) { if(fwrite("-1 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } } if(bdfplus) { if(fwrite("-1 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } for(i=0; iecg_filter == NULL) && (signalcomp[i]->zratio_filter == NULL)) { fseeko(signalcomp[i]->edfhdr->file_hdl, (long long)((signalcomp[i]->edfsignal[0] * 8) + (112 * signalcomp[i]->edfhdr->edfsignals) + 256), SEEK_SET); if(fread(scratchpad, 8, 1, signalcomp[i]->edfhdr->file_hdl)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading from inputfile."); messagewindow.exec(); fclose(outputfile); return; } if(fwrite(scratchpad, 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } if(signalcomp[i]->ecg_filter != NULL) { if(fwrite("1000 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } if(signalcomp[i]->zratio_filter != NULL) { if(fwrite("1 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } } if(bdfplus) { if(fwrite("1 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } for(i=0; iecg_filter == NULL) && (signalcomp[i]->zratio_filter == NULL)) { fprintf(outputfile, "%-8i", signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min); if(signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min<0) { null_bytes[i].one_signed = 0; } else { null_bytes[i].one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min; } } else { if(fwrite("-8388608", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } null_bytes[i].one_signed = -8388608; } } if(bdfplus) { if(fwrite("-8388608", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } for(i=0; iecg_filter == NULL) && (signalcomp[i]->zratio_filter == NULL)) { fprintf(outputfile, "%-8i", signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max); } else { if(fwrite("8388607 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } } if(bdfplus) { if(fwrite("8388607 ", 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].prefilter); strcat(scratchpad, " "); for(p = strlen(scratchpad) - 1; p>=0; p--) { if(scratchpad[p]!=' ') break; } p++; if(p) p++; if(signalcomp[i]->spike_filter) { p += sprintf(scratchpad + p, "Spike:%f", signalcomp[i]->spike_filter->velocity); 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(p>80) break; } for(j=0; jfilter_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; jfidfilter_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; jravg_filter_cnt; j++) { if(signalcomp[i]->ravg_filter_type[j] == 0) { p += sprintf(scratchpad + p, "HP:%iSmpls ", signalcomp[i]->ravg_filter[j]->size); } if(signalcomp[i]->ravg_filter_type[j] == 1) { p += sprintf(scratchpad + p, "LP:%iSmpls ", signalcomp[i]->ravg_filter[j]->size); } p = strlen(scratchpad); if(p>80) break; } if(signalcomp[i]->ecg_filter != NULL) { p += sprintf(scratchpad + p, "ECG:HR "); } 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) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } if(bdfplus) { for(i=0; i<80; i++) fputc(' ', outputfile); } for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record * duration_factor[signalcomp[i]->filenum]); } if(bdfplus) { fprintf(outputfile, "%-8i", annot_smp_per_record); } for(i=0; iprint_to_edf_active = 1; mainwindow->setup_viewbuf(); viewbuf = mainwindow->viewbuf; if(viewbuf==NULL) { fclose(outputfile); return; } for(i=0; iedfhdr->long_data_record_duration / signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record); } QApplication::setOverrideCursor(Qt::WaitCursor); for(records_written=0; records_writtenprocessEvents(); for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record * duration_factor[signalcomp[i]->filenum]; k++) { if(smpls_preamble[i]) { smpls_preamble[i]--; fputc(null_bytes[i].four[0], outputfile); fputc(null_bytes[i].four[1], outputfile); if(fputc(null_bytes[i].four[2], outputfile)==EOF) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } else { dig_value = 0; s2 = smpls_written[i] + signalcomp[i]->sample_timeoffset - signalcomp[i]->sample_start; for(j=0; jnum_of_signals; j++) { if((smpls_written[i]sample_stop)&&(s2>=0)) { if(signalcomp[i]->edfhdr->bdf) { var.two[0] = *((unsigned short *)( viewbuf + signalcomp[i]->viewbufoffset + (signalcomp[i]->edfhdr->recordsize * (s2 / signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record)) + signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].buf_offset + ((s2 % signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record) * 3))); var.four[2] = *((unsigned char *)( viewbuf + signalcomp[i]->viewbufoffset + (signalcomp[i]->edfhdr->recordsize * (s2 / signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record)) + signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].buf_offset + ((s2 % signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record) * 3) + 2)); if(var.four[2]&0x80) { var.four[3] = 0xff; } else { var.four[3] = 0x00; } temp = var.one_signed; } if(signalcomp[i]->edfhdr->edf) { temp = *(((short *)( viewbuf + signalcomp[i]->viewbufoffset + (signalcomp[i]->edfhdr->recordsize * (s2 / signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record)) + signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].buf_offset)) + (s2 % signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record)); } temp += signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].offset; temp *= signalcomp[i]->factor[j]; temp -= signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].offset; } else { temp = 0; } dig_value += temp; } if(signalcomp[i]->spike_filter) { if(smpls_written[i]==signalcomp[i]->sample_start) { if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime<=0) { reset_spike_filter(signalcomp[i]->spike_filter); } else { spike_filter_restore_buf(signalcomp[i]->spike_filter); } } dig_value = run_spike_filter(dig_value, signalcomp[i]->spike_filter); } for(p=0; pfilter_cnt; p++) { if(smpls_written[i]==signalcomp[i]->sample_start) { if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime==0) { reset_filter(dig_value, signalcomp[i]->filter[p]); } else { signalcomp[i]->filter[p]->old_input = signalcomp[i]->filterpreset_a[p]; signalcomp[i]->filter[p]->old_output = signalcomp[i]->filterpreset_b[p]; } } dig_value = first_order_filter(dig_value, signalcomp[i]->filter[p]); } for(p=0; pravg_filter_cnt; p++) { if(smpls_written[i]==signalcomp[i]->sample_start) { if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime!=0) { ravg_filter_restore_buf(signalcomp[i]->ravg_filter[p]); } } dig_value = run_ravg_filter(dig_value, signalcomp[i]->ravg_filter[p]); } for(p=0; pfidfilter_cnt; p++) { if(smpls_written[i]==signalcomp[i]->sample_start) { if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime!=0) { memcpy(signalcomp[i]->fidbuf[p], signalcomp[i]->fidbuf2[p], fid_run_bufsize(signalcomp[i]->fid_run[p])); } } dig_value = signalcomp[i]->fidfuncp[p](signalcomp[i]->fidbuf[p], dig_value); } if(signalcomp[i]->ecg_filter != NULL) { if(smpls_written[i]==signalcomp[i]->sample_start) { if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime != 0) { ecg_filter_restore_buf(signalcomp[i]->ecg_filter); } } dig_value = run_ecg_filter(dig_value, signalcomp[i]->ecg_filter); dig_value = (dig_value * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue * 16777.216) - 8388608.0; } if(signalcomp[i]->zratio_filter != NULL) { if(smpls_written[i]==signalcomp[i]->sample_start) { if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime != 0) { zratio_filter_restore_buf(signalcomp[i]->zratio_filter); } } dig_value = run_zratio_filter(dig_value, signalcomp[i]->zratio_filter); dig_value = dig_value * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue * 8388608.0; } if((smpls_written[i]>=signalcomp[i]->sample_start)&&(smpls_written[i]sample_stop)) { wr_var.one_signed = dig_value; if((signalcomp[i]->ecg_filter == NULL) && (signalcomp[i]->zratio_filter == NULL)) { if(wr_var.one_signed>signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max) { wr_var.one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_max; } if(wr_var.one_signededfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min) { wr_var.one_signed = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].dig_min; } } else { if(wr_var.one_signed > 8388607) { wr_var.one_signed = 8388607; } if(wr_var.one_signed < -8388608) { wr_var.one_signed = -8388608; } } fputc(wr_var.four[0], outputfile); fputc(wr_var.four[1], outputfile); if(fputc(wr_var.four[2], outputfile)==EOF) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } else { fputc(null_bytes[i].four[0], outputfile); fputc(null_bytes[i].four[1], outputfile); if(fputc(null_bytes[i].four[2], outputfile)==EOF) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while writing to outputfile."); messagewindow.exec(); fclose(outputfile); return; } } smpls_written[i]++; } } } if(bdfplus) { tallen = fprintf(outputfile, "+%i.%07i", (int)(taltime / TIME_DIMENSION), (int)(taltime % TIME_DIMENSION)); fputc(20, outputfile); fputc(20, outputfile); fputc(0, outputfile); tallen += 3; if(annotations_left) { if(mainwindow->viewtime_sync==VIEWTIME_SYNCED_ABSOLUT) { annot_difftime = (referencetime - mainwindow->edfheaderlist[annotationlist_nr]->utc_starttime) * TIME_DIMENSION; } if(mainwindow->viewtime_sync==VIEWTIME_SYNCED_OFFSET) { annot_difftime = (referencetime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime) * TIME_DIMENSION; } if((mainwindow->viewtime_sync==VIEWTIME_UNSYNCED) || (mainwindow->viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { annot_difftime = (referencetime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime) * TIME_DIMENSION; annot_difftime += (mainwindow->edfheaderlist[annotationlist_nr]->viewtime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime); } if(annotationlist_nr != mainwindow->sel_viewtime) { annot_difftime -= mainwindow->edfheaderlist[mainwindow->sel_viewtime]->starttime_offset; annot_difftime += mainwindow->edfheaderlist[annotationlist_nr]->starttime_offset; } } while(annotations_left) { while(!annotations_pntr) { annotationlist_nr++; if(annotationlist_nr>=mainwindow->files_open) { annotations_left = 0; annotations_pntr = NULL; break; } annotations_pntr = mainwindow->annotationlist[annotationlist_nr]; if(mainwindow->viewtime_sync==VIEWTIME_SYNCED_ABSOLUT) { annot_difftime = (referencetime - mainwindow->edfheaderlist[annotationlist_nr]->utc_starttime) * TIME_DIMENSION; } if(mainwindow->viewtime_sync==VIEWTIME_SYNCED_OFFSET) { annot_difftime = (referencetime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime) * TIME_DIMENSION; } if((mainwindow->viewtime_sync==VIEWTIME_UNSYNCED) || (mainwindow->viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { annot_difftime = (referencetime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime) * TIME_DIMENSION; annot_difftime += (mainwindow->edfheaderlist[annotationlist_nr]->viewtime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime); } if(annotationlist_nr != mainwindow->sel_viewtime) { annot_difftime -= mainwindow->edfheaderlist[mainwindow->sel_viewtime]->starttime_offset; annot_difftime += mainwindow->edfheaderlist[annotationlist_nr]->starttime_offset; } } if(!annotations_left) break; if(annotations_pntr) { l_temp = annotations_pntr->onset - annot_difftime; if((l_temp >= 0LL) && (l_temp < (mainwindow->pagetime + TIME_DIMENSION))) { tallen += fprintf(outputfile, "%+i.%07i", (int)(l_temp / TIME_DIMENSION), (int)(l_temp % TIME_DIMENSION)); if(annotations_pntr->duration[0]!=0) { fputc(21, outputfile); tallen++; tallen += fprintf(outputfile, "%s", annotations_pntr->duration); } fputc(20, outputfile); tallen++; tallen += fprintf(outputfile, "%s", annotations_pntr->annotation); fputc(20, outputfile); fputc(0, outputfile); tallen += 2; annotations_pntr = annotations_pntr->next_annotation; break; } else { annotations_pntr = annotations_pntr->next_annotation; continue; } } } for(j=tallen; j<(annot_smp_per_record * 3); j++) { fputc(0, outputfile); } taltime += duration; } } QApplication::restoreOverrideCursor(); fclose(outputfile); } edfbrowser_157_source/PaxHeaders.7921/ascii_export.cpp0000644000000000000000000000013212646460742020063 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/ascii_export.cpp0000644000175000001440000006122112646460742020426 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "ascii_export.h" UI_AsciiExportwindow::UI_AsciiExportwindow(QWidget *w_parent) { int i; mainwindow = (UI_Mainwindow *)w_parent; AsciiExportDialog = new QDialog; AsciiExportDialog->setMinimumSize(800, 180); AsciiExportDialog->setMaximumSize(800, 180); AsciiExportDialog->setWindowTitle("Export to ASCII"); AsciiExportDialog->setModal(true); AsciiExportDialog->setAttribute(Qt::WA_DeleteOnClose, true); filelist = new QListWidget(AsciiExportDialog); filelist->setGeometry(10, 10, 780, 75); filelist->setSelectionBehavior(QAbstractItemView::SelectRows); filelist->setSelectionMode(QAbstractItemView::SingleSelection); for(i=0; ifiles_open; i++) { if((mainwindow->edfheaderlist[i]->edf)||(mainwindow->edfheaderlist[i]->bdf)) { new QListWidgetItem(QString::fromLocal8Bit(mainwindow->edfheaderlist[i]->filename), filelist); } } ExportButton = new QPushButton(AsciiExportDialog); ExportButton->setGeometry(10, 140, 100, 25); ExportButton->setText("Export"); CloseButton = new QPushButton(AsciiExportDialog); CloseButton->setGeometry(690, 140, 100, 25); CloseButton->setText("Close"); QObject::connect(CloseButton, SIGNAL(clicked()), AsciiExportDialog, SLOT(close())); QObject::connect(ExportButton, SIGNAL(clicked()), this, SLOT(ExportButtonClicked())); filelist->setCurrentRow(mainwindow->files_open - 1); AsciiExportDialog->exec(); } void UI_AsciiExportwindow::ExportButtonClicked() { int i, j, k, m, p, r, n, edfsignals, datarecords, datarecordswritten, recordsize, recordfull, edfplus, bdf, bdfplus=0, samplesize, annot_ch[256], nr_annot_chns=0, skip, max, onset, duration, zero, max_tal_ln, len, progress_steps; char path[MAX_PATH_LENGTH], ascii_path[MAX_PATH_LENGTH], *edf_hdr, *scratchpad, *cnv_buf, *time_in_txt, *duration_in_txt, str[1024]; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; FILE *inputfile, *outputfile, *annotationfile; double data_record_duration, elapsedtime, time_tmp, d_tmp, value_tmp; if(!mainwindow->files_open) { AsciiExportDialog->close(); return; } ExportButton->setEnabled(false); CloseButton->setEnabled(false); for(i=0; ifiles_open; i++) { if(!strcmp(mainwindow->edfheaderlist[i]->filename, filelist->item(filelist->currentRow())->text().toLocal8Bit().data())) { break; } } if(i==mainwindow->files_open) return; n = i; inputfile = mainwindow->edfheaderlist[n]->file_hdl; path[0] = 0; if(mainwindow->recent_savedir[0]!=0) { strcpy(path, mainwindow->recent_savedir); strcat(path, "/"); } len = strlen(path); get_filename_from_path(path + len, mainwindow->edfheaderlist[n]->filename, MAX_PATH_LENGTH - len); remove_extension_from_filename(path); strcat(path, "_data.txt"); strcpy(path, QFileDialog::getSaveFileName(0, "Export to ASCII", QString::fromLocal8Bit(path), "Text files (*.txt *.TXT)").toLocal8Bit().data()); if(!strcmp(path, "")) { AsciiExportDialog->close(); return; } get_directory_from_path(mainwindow->recent_savedir, path, MAX_PATH_LENGTH); if(mainwindow->file_is_opened(path)) { QMessageBox messagewindow(QMessageBox::Critical, "Save file", "Error, selected file is in use."); messagewindow.exec(); AsciiExportDialog->close(); return; } if(!(strcmp(path + strlen(path) - 9, "_data.txt"))) { path[strlen(path) - 9] = 0; } scratchpad = (char *)calloc(1, 128); if(scratchpad==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error! (scratchpad)."); messagewindow.exec(); AsciiExportDialog->close(); return; } if(fseeko(inputfile, 0xfcLL, SEEK_SET)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "File read error."); messagewindow.exec(); AsciiExportDialog->close(); return; } if(fread(scratchpad, 4, 1, inputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "File read error."); messagewindow.exec(); AsciiExportDialog->close(); return; } scratchpad[4] = 0; edfsignals = atoi(scratchpad); edf_hdr = (char *)calloc(1, (edfsignals + 1) * 256); if(edf_hdr==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error! (edf_hdr)"); messagewindow.exec(); AsciiExportDialog->close(); return; } rewind(inputfile); if(fread(edf_hdr, (edfsignals + 1) * 256, 1, inputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "File read error."); messagewindow.exec(); free(edf_hdr); AsciiExportDialog->close(); return; } for(i=0; i<((edfsignals+1)*256); i++) { if(edf_hdr[i]==',') edf_hdr[i] = '\''; /* replace all comma's in header by single quotes because they */ } /* interfere with the comma-separated txt-files */ strncpy(scratchpad, edf_hdr + 0xec, 8); scratchpad[8] = 0; datarecords = atoi(scratchpad); strncpy(scratchpad, edf_hdr + 0xf4, 8); scratchpad[8] = 0; data_record_duration = atof(scratchpad); nr_annot_chns = 0; if(((signed char *)edf_hdr)[0]==-1) { bdf = 1; samplesize = 3; edfplus = 0; if((strncmp(edf_hdr + 0xc0, "BDF+C ", 10))&&(strncmp(edf_hdr + 0xc0, "BDF+D ", 10))) { bdfplus = 0; } else { bdfplus = 1; for(i=0; i255) break; } } } } else { bdf = 0; samplesize = 2; if((strncmp(edf_hdr + 0xc0, "EDF+C ", 10))&&(strncmp(edf_hdr + 0xc0, "EDF+D ", 10))) { edfplus = 0; } else { edfplus = 1; for(i=0; i255) break; } } } } edfparamascii = (struct asciiedfparamblock *)calloc(1, sizeof(struct asciiedfparamblock[edfsignals])); if(edfparamascii==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error! (edfparam)"); messagewindow.exec(); free(edf_hdr); AsciiExportDialog->close(); return; } recordsize = 0; for(i=0; iclose(); return; } free(scratchpad); max_tal_ln = 0; for(r=0; rclose(); return; } duration_in_txt = (char *)calloc(1, max_tal_ln + 3); if(duration_in_txt==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error! (duration_in_txt)"); messagewindow.exec(); free(scratchpad); free(cnv_buf); free(edf_hdr); free(edfparamascii); AsciiExportDialog->close(); return; } time_in_txt = (char *)calloc(1, max_tal_ln + 3); if(time_in_txt==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error! (time_in_txt)"); messagewindow.exec(); free(duration_in_txt); free(scratchpad); free(cnv_buf); free(edf_hdr); free(edfparamascii); AsciiExportDialog->close(); return; } /***************** write header ******************************/ strcpy(ascii_path, path); remove_extension_from_filename(ascii_path); strcat(ascii_path, "_header.txt"); outputfile = fopeno(ascii_path, "wb"); if(outputfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, can not open headerfile for writing."); messagewindow.exec(); free(edf_hdr); free(edfparamascii); free(cnv_buf); free(time_in_txt); free(duration_in_txt); free(scratchpad); AsciiExportDialog->close(); return; } fprintf(outputfile, "Version,Subject,Recording,Startdate,Startime,Bytes,Reserved,NumRec,Duration,NumSig\n"); if(bdf) { fprintf(outputfile, ".%.7s,", edf_hdr + 1); } else { fprintf(outputfile, "%.8s,", edf_hdr); } fprintf(outputfile, "%.80s,", edf_hdr + 8); fprintf(outputfile, "%.80s,", edf_hdr + 88); fprintf(outputfile, "%.8s,", edf_hdr + 168); fprintf(outputfile, "%.8s,", edf_hdr + 176); fprintf(outputfile, "%.8s,", edf_hdr + 184); fprintf(outputfile, "%.44s,", edf_hdr + 192); fprintf(outputfile, "%i,", datarecords); fprintf(outputfile, "%.8s,", edf_hdr + 244); snprintf(scratchpad, 128, "%.4s", edf_hdr + 252); fprintf(outputfile, "%i\n", atoi(scratchpad) - nr_annot_chns); fclose(outputfile); /***************** write signals ******************************/ strcpy(ascii_path, path); remove_extension_from_filename(ascii_path); strcat(ascii_path, "_signals.txt"); outputfile = fopeno(ascii_path, "wb"); if(outputfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, can not open signalfile for writing."); messagewindow.exec(); free(edf_hdr); free(edfparamascii); free(cnv_buf); free(time_in_txt); free(duration_in_txt); free(scratchpad); AsciiExportDialog->close(); return; } fprintf(outputfile, "Signal,Label,Transducer,Units,Min,Max,Dmin,Dmax,PreFilter,Smp/Rec,Reserved\n"); for(i=0; iclose(); return; } fprintf(annotationfile, "Onset,Duration,Annotation\n"); /***************** write data ******************************/ strcpy(ascii_path, path); remove_extension_from_filename(ascii_path); strcat(ascii_path, "_data.txt"); outputfile = fopeno(ascii_path, "wb"); if(outputfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Error, can not open datafile for writing."); messagewindow.exec(); fclose(annotationfile); free(edf_hdr); free(edfparamascii); free(cnv_buf); free(time_in_txt); free(duration_in_txt); free(scratchpad); AsciiExportDialog->close(); return; } fprintf(outputfile, "Time"); for(i=0; i<(edfsignals-nr_annot_chns); i++) { fprintf(outputfile, ",%i", i + 1); } if(fputc('\n', outputfile)==EOF) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when writing to outputfile."); messagewindow.exec(); fclose(annotationfile); fclose(outputfile); free(edf_hdr); free(edfparamascii); free(cnv_buf); free(time_in_txt); free(duration_in_txt); free(scratchpad); AsciiExportDialog->close(); return; } if(fseeko(inputfile, (long long)((edfsignals + 1) * 256), SEEK_SET)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when reading from inputfile."); messagewindow.exec(); fclose(annotationfile); fclose(outputfile); free(edf_hdr); free(edfparamascii); free(cnv_buf); free(time_in_txt); free(duration_in_txt); free(scratchpad); AsciiExportDialog->close(); return; } /***************** start data conversion ******************************/ QProgressDialog progress("Writing file...", "Abort", 0, datarecords); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); progress_steps = datarecords / 100; if(progress_steps < 1) { progress_steps = 1; } datarecordswritten = 0; for(i=0; iprocessEvents(); if(progress.wasCanceled() == true) { break; } } for(j=0; jclose(); return; } if(edfplus || bdfplus) { max = edfparamascii[annot_ch[0]].smp_per_record * samplesize; p = edfparamascii[annot_ch[0]].buf_offset * samplesize; /* extract time from datarecord */ for(k=0; kmax_tal_ln) { progress.reset(); snprintf(str, 256, "Error, TAL in record %i exceeds my buffer.", datarecordswritten + 1); QMessageBox messagewindow(QMessageBox::Critical, "Error", str); messagewindow.exec(); fclose(annotationfile); fclose(outputfile); free(edf_hdr); free(edfparamascii); free(cnv_buf); free(time_in_txt); free(duration_in_txt); free(scratchpad); AsciiExportDialog->close(); return; } scratchpad[k] = cnv_buf[p + k]; if(scratchpad[k]==20) break; } scratchpad[k] = 0; elapsedtime = atof(scratchpad); /* process annotations */ for(r=0; rmax_tal_ln) { progress.reset(); snprintf(str, 256, "Error, TAL in record %i exceeds my buffer.", datarecordswritten + 1); QMessageBox messagewindow(QMessageBox::Critical, "Error", str); messagewindow.exec(); fclose(annotationfile); fclose(outputfile); free(edf_hdr); free(edfparamascii); free(cnv_buf); free(time_in_txt); free(duration_in_txt); free(scratchpad); AsciiExportDialog->close(); return; } scratchpad[n] = cnv_buf[p + k]; if(scratchpad[n]==0) { n = 0; onset = 0; duration = 0; time_in_txt[0] = 0; duration_in_txt[0] = 0; scratchpad[0] = 0; zero++; continue; } else zero = 0; if(zero>1) break; if(scratchpad[n]==20) { if(duration) { scratchpad[n] = 0; strcpy(duration_in_txt, scratchpad); n = 0; duration = 0; scratchpad[0] = 0; continue; } else if(onset) { scratchpad[n] = 0; if(n) { utf8_to_latin1(scratchpad); for(m=0; mmax_tal_ln) { progress.reset(); snprintf(str, 256, "Error, TAL in record %i exceeds my buffer.", datarecordswritten + 1); QMessageBox messagewindow(QMessageBox::Critical, "Error", str); messagewindow.exec(); fclose(annotationfile); fclose(outputfile); free(edf_hdr); free(edfparamascii); free(cnv_buf); free(time_in_txt); free(duration_in_txt); free(scratchpad); AsciiExportDialog->close(); return; } } } } else elapsedtime = datarecordswritten * data_record_duration; /* done with timekeeping and annotations, continue with the data */ do { time_tmp = 10000000000.0; for(j=0; j(time_tmp-0.00000000000001))&&(edfparamascii[j].smp_writtenclose(); return; } recordfull = 1; for(j=0; jclose(); } edfbrowser_157_source/PaxHeaders.7921/edf_annotations.cpp0000644000000000000000000000013212646460742020545 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/edf_annotations.cpp0000644000175000001440000004625612646460742021123 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "edf_annotations.h" int EDF_annotations::get_annotations(int file_num, struct edfhdrblock *edf_hdr, struct annotationblock **annotslist, int read_nk_trigger_signal) { int i, j, k, p, r=0, n, edfsignals, datarecords, recordsize, discontinuous, *annot_ch, nr_annot_chns, max, onset, duration, duration_start, zero, max_tal_ln, error, annots_in_record, annots_in_tal, samplesize=2, nk_triggers_smpls=0, nk_triggers_bufoffset=0, nk_triggers_enabled=0, nk_triggers_channel=0, nk_triggers_cnt=0, sf, progress_steps; unsigned short nk_triggerfields=0, nk_old_triggerfields=0; char *scratchpad, *cnv_buf, *time_in_txt, *duration_in_txt, nk_triggerlabel[16][32]; long long data_record_duration, elapsedtime, time_tmp=0LL, nk_trigger_sample_duration=0LL; FILE *inputfile; struct edfparamblock *edfparam; struct annotationblock *new_annotation=NULL, *temp_annotation; inputfile = edf_hdr->file_hdl; edfsignals = edf_hdr->edfsignals; recordsize = edf_hdr->recordsize; edfparam = edf_hdr->edfparam; nr_annot_chns = edf_hdr->nr_annot_chns; datarecords = edf_hdr->datarecords; data_record_duration = edf_hdr->long_data_record_duration; discontinuous = edf_hdr->discontinuous; annot_ch = edf_hdr->annot_ch; if(edf_hdr->edfplus) { samplesize = 2; } if(edf_hdr->bdfplus) { samplesize = 3; } if((edf_hdr->edfplus) && (read_nk_trigger_signal)) { if(data_record_duration == 1000000LL) { if(check_device(edf_hdr->plus_equipment) == 0) { for(i=0; iedfparam[i].smp_per_record; error = 1; switch(sf) { case 10 : error = 0; break; case 20 : error = 0; break; case 50 : error = 0; break; case 100 : error = 0; break; } for(j=0; jedfparam[j].smp_per_record != sf) { if(!edf_hdr->edfparam[j].annotation) { error = 1; } } } if(edf_hdr->nr_annot_chns != 1) error = 1; if(!error) { nk_triggers_channel = i; nk_triggers_bufoffset = edfparam[nk_triggers_channel].buf_offset; nk_triggers_smpls = edfparam[nk_triggers_channel].smp_per_record; nk_trigger_sample_duration = data_record_duration / (long long)nk_triggers_smpls; strcpy(nk_triggerlabel[0], "CAL mode"); strcpy(nk_triggerlabel[1], "RESET condition"); strcpy(nk_triggerlabel[2], "External mark"); strcpy(nk_triggerlabel[3], "Photo/HV mark"); strcpy(nk_triggerlabel[4], "Remote mark"); strcpy(nk_triggerlabel[5], "HV mark"); strcpy(nk_triggerlabel[6], "DC trigger 9"); strcpy(nk_triggerlabel[7], "DC trigger 10"); strcpy(nk_triggerlabel[8], "DC trigger 11"); strcpy(nk_triggerlabel[9], "DC trigger 12"); strcpy(nk_triggerlabel[10], "DC trigger 13"); strcpy(nk_triggerlabel[11], "DC trigger 14"); strcpy(nk_triggerlabel[12], "DC trigger 15"); strcpy(nk_triggerlabel[13], "DC trigger 16"); strcpy(nk_triggerlabel[14], ""); strcpy(nk_triggerlabel[15], ""); nk_triggers_enabled = 1; edf_hdr->genuine_nk = 1; break; } } } } } } cnv_buf = (char *)calloc(1, recordsize); if(cnv_buf==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Memory allocation error occurred when trying to read annotations.\n(cnv_buf)"); messagewindow.exec(); return(1); } max_tal_ln = 0; for(i=0; iprocessEvents(); if(progress.wasCanceled() == true) { edf_hdr->annots_not_read = 1; free(cnv_buf); free(scratchpad); free(time_in_txt); free(duration_in_txt); return(11); } } if(fread(cnv_buf, recordsize, 1, inputfile)!=1) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred while reading inputfile annotations. (fread())"); messagewindow.exec(); free(cnv_buf); free(scratchpad); free(time_in_txt); free(duration_in_txt); return(2); } /************** process annotationsignals (if any) **************/ error = 0; for(r=0; r=TIME_DIMENSION) { error = 2; goto END; } else { edf_hdr->starttime_offset = time_tmp; } } elapsedtime = time_tmp; error = 0; break; } } } } for(k=0; k1) { error = 34; goto END; } zero = 0; if((scratchpad[n]==20)||(scratchpad[n]==21)) { if(scratchpad[n]==21) { if(duration||duration_start||onset||annots_in_tal) { /* it's not allowed to have multiple duration fields */ error = 35; /* in one TAL or to have a duration field which is */ goto END; /* not immediately behind the onsetfield */ } duration_start = 1; } if((scratchpad[n]==20)&&onset&&(!duration_start)) { if(r||annots_in_record) { if(n >= 0) { new_annotation = (struct annotationblock *)calloc(1, sizeof(struct annotationblock)); if(new_annotation==NULL) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred while reading annotations."); messagewindow.exec(); free(cnv_buf); free(scratchpad); free(time_in_txt); free(duration_in_txt); return(1); } new_annotation->next_annotation = NULL; new_annotation->file_num = file_num; new_annotation->annotation[0] = 0; if(duration) strcpy(new_annotation->duration, duration_in_txt); else new_annotation->duration[0] = 0; for(j=0; jannotation[j] = scratchpad[j]; } new_annotation->annotation[j] = 0; new_annotation->file_num = edf_hdr->file_num; new_annotation->onset = get_long_time(time_in_txt); if(*annotslist!=NULL) { temp_annotation = *annotslist; while(temp_annotation->next_annotation) temp_annotation = temp_annotation->next_annotation; new_annotation->former_annotation = temp_annotation; temp_annotation->next_annotation = new_annotation; } else { new_annotation->former_annotation = NULL; *annotslist = new_annotation; } } } annots_in_tal++; annots_in_record++; n = 0; continue; } if(!onset) { scratchpad[n] = 0; if(is_onset_number(scratchpad)) { error = 36; goto END; } onset = 1; n = 0; strcpy(time_in_txt, scratchpad); continue; } if(duration_start) { scratchpad[n] = 0; if(is_duration_number(scratchpad)) { error = 37; goto END; } for(j=0; j126)) { duration_in_txt[j] = '.'; } } duration_in_txt[j] = 0; duration = 1; duration_start = 0; n = 0; continue; } } n++; } END: /****************** end ************************/ if(error) { progress.reset(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not read annotations because there is an EDF or BDF incompatibility in this file.\n" "For more information, run the EDF/BDF compatibility checker in the Tools menu."); messagewindow.exec(); free(cnv_buf); free(scratchpad); free(time_in_txt); free(duration_in_txt); return(9); } } /************** process NK triggers ****************/ if(nk_triggers_enabled) { if(nk_triggers_cnt < 100000) { for(k=0; kfile_num = edf_hdr->file_num; new_annotation->next_annotation = NULL; new_annotation->file_num = file_num; strcpy(new_annotation->annotation, nk_triggerlabel[j]); new_annotation->onset = ((long long)i * data_record_duration) + ((long long)k * nk_trigger_sample_duration); new_annotation->onset += edf_hdr->starttime_offset; new_annotation->ident = (1 << ANNOT_ID_NK_TRIGGER); if(*annotslist!=NULL) { temp_annotation = *annotslist; while(temp_annotation->next_annotation) temp_annotation = temp_annotation->next_annotation; new_annotation->former_annotation = temp_annotation; temp_annotation->next_annotation = new_annotation; } else { new_annotation->former_annotation = NULL; *annotslist = new_annotation; } } } nk_old_triggerfields = nk_triggerfields; } } edf_hdr->nk_triggers_read = 1; } } edfplus_annotation_sort(&annotslist[file_num]); progress.reset(); free(cnv_buf); free(scratchpad); free(time_in_txt); free(duration_in_txt); return(0); } int EDF_annotations::is_duration_number(char *str) { int i, l, hasdot = 0; l = strlen(str); if(!l) return(1); if((str[0] == '.')||(str[l-1] == '.')) return(1); for(i=0; i57)) return(1); } } return(0); } int EDF_annotations::is_onset_number(char *str) { int i, l, hasdot = 0; l = strlen(str); if(l<2) return(1); if((str[0]!='+')&&(str[0]!='-')) return(1); if((str[1] == '.')||(str[l-1] == '.')) return(1); for(i=1; i57)) return(1); } } return(0); } long long EDF_annotations::get_long_time(char *str) { int i, len, hasdot=0, dotposition=0; long long value=0, radix; str = str + 1; len = strlen(str); for(i=0; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } radix = TIME_DIMENSION / 10; for(i=dotposition+1; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } } if(str[-1]=='-') value = -value; return(value); } int EDF_annotations::check_device(char *str) { int error = 1; if(strlen(str) < 29) return(1); if(!strncmp(str, "Nihon Kohden EEG-1100A V01.00", 29)) error = 0; if(!strncmp(str, "Nihon Kohden EEG-1100B V01.00", 29)) error = 0; if(!strncmp(str, "Nihon Kohden EEG-1100C V01.00", 29)) error = 0; if(!strncmp(str, "Nihon Kohden QI-403A V01.00", 29)) error = 0; if(!strncmp(str, "Nihon Kohden QI-403A V02.00", 29)) error = 0; if(!strncmp(str, "Nihon Kohden EEG-2100 V01.00", 29)) error = 0; if(!strncmp(str, "Nihon Kohden EEG-2100 V02.00", 29)) error = 0; if(!strncmp(str, "Nihon Kohden DAE-2100D V01.30", 29)) error = 0; if(!strncmp(str, "Nihon Kohden DAE-2100D V02.00", 29)) error = 0; // if(!strncmp(str, "Nihon Kohden EEG-1200A V01.00", 29)) error = 0; return(error); } edfbrowser_157_source/PaxHeaders.7921/ascii2edf.cpp0000644000000000000000000000013212646460742017223 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/ascii2edf.cpp0000644000175000001440000013442412646460742017574 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "ascii2edf.h" UI_ASCII2EDFapp::UI_ASCII2EDFapp(char *recent_dir, char *save_dir) { recent_opendir = recent_dir; recent_savedir = save_dir; autoPhysicalMaximum = 1; edf_format = 1; ascii2edfDialog = new QDialog; ascii2edfDialog->setMinimumSize(720, 520); ascii2edfDialog->setMaximumSize(720, 520); ascii2edfDialog->setWindowTitle("ASCII to EDF/BDF converter"); ascii2edfDialog->setModal(true); ascii2edfDialog->setAttribute(Qt::WA_DeleteOnClose, true); SeparatorLabel = new QLabel(ascii2edfDialog); SeparatorLabel->setGeometry(20, 20, 140, 25); SeparatorLabel->setText("Column separator"); NumsignalsLabel = new QLabel(ascii2edfDialog); NumsignalsLabel->setGeometry(20, 55, 140, 25); NumsignalsLabel->setText("Number of columns"); DatastartLabel = new QLabel(ascii2edfDialog); DatastartLabel->setGeometry(20, 90, 140, 25); DatastartLabel->setText("Data starts at line"); SamplefreqLabel = new QLabel(ascii2edfDialog); SamplefreqLabel->setGeometry(20, 125, 140, 25); SamplefreqLabel->setText("Samplefrequency"); PatientnameLabel = new QLabel(ascii2edfDialog); PatientnameLabel->setGeometry(20, 160, 140, 25); PatientnameLabel->setText("Subject name"); RecordingLabel = new QLabel(ascii2edfDialog); RecordingLabel->setGeometry(20, 195, 140, 25); RecordingLabel->setText("Recording"); DatetimeLabel = new QLabel(ascii2edfDialog); DatetimeLabel->setGeometry(20, 230, 140, 25); DatetimeLabel->setText("Startdate and time"); autoPhysicalMaximumLabel = new QLabel(ascii2edfDialog); autoPhysicalMaximumLabel->setGeometry(360, 265, 180, 25); autoPhysicalMaximumLabel->setText("Auto detect physical maximum"); SignalsLabel = new QLabel(ascii2edfDialog); SignalsLabel->setGeometry(20, 300, 140, 25); SignalsLabel->setText("Signals"); groupbox1 = new QGroupBox(ascii2edfDialog); groupbox1->setGeometry(530, 20, 160, 90); groupbox1->setTitle("Output format"); edfButton = new QRadioButton("EDF (16-bit)"); bdfButton = new QRadioButton("BDF (24-bit)"); edfButton->setChecked(true); vbox1 = new QVBoxLayout; vbox1->addWidget(edfButton); vbox1->addStretch(1); vbox1->addWidget(bdfButton); vbox1->addStretch(1); groupbox1->setLayout(vbox1); SeparatorLineEdit = new QLineEdit(ascii2edfDialog); SeparatorLineEdit->setGeometry(160, 20, 30, 25); SeparatorLineEdit->setMaxLength(3); SeparatorLineEdit->setText("tab"); NumcolumnsSpinbox = new QSpinBox(ascii2edfDialog); NumcolumnsSpinbox->setGeometry(160, 55, 70, 25); NumcolumnsSpinbox->setRange(1,256); NumcolumnsSpinbox->setValue(1); DatastartSpinbox = new QSpinBox(ascii2edfDialog); DatastartSpinbox->setGeometry(160, 90, 70, 25); DatastartSpinbox->setRange(1,100); DatastartSpinbox->setValue(1); SamplefreqSpinbox = new QDoubleSpinBox(ascii2edfDialog); SamplefreqSpinbox->setGeometry(160, 125, 140, 25); SamplefreqSpinbox->setDecimals(7); SamplefreqSpinbox->setRange(0.0000001,1000000.0); SamplefreqSpinbox->setSuffix(" Hz"); SamplefreqSpinbox->setValue(1.0); PatientnameLineEdit = new QLineEdit(ascii2edfDialog); PatientnameLineEdit->setGeometry(160, 160, 540, 25); PatientnameLineEdit->setMaxLength(80); RecordingLineEdit = new QLineEdit(ascii2edfDialog); RecordingLineEdit->setGeometry(160, 195, 540, 25); RecordingLineEdit->setMaxLength(80); StartDatetimeedit = new QDateTimeEdit(ascii2edfDialog); StartDatetimeedit->setGeometry(160, 230, 140, 25); StartDatetimeedit->setDisplayFormat("dd/MM/yyyy hh:mm:ss"); StartDatetimeedit->setDateTime(QDateTime::currentDateTime()); autoPhysicalMaximumCheckbox = new QCheckBox(ascii2edfDialog); autoPhysicalMaximumCheckbox->setGeometry(560, 265, 20, 25); autoPhysicalMaximumCheckbox->setTristate(false); autoPhysicalMaximumCheckbox->setCheckState(Qt::Checked); SignalsTablewidget = new QTableWidget(ascii2edfDialog); SignalsTablewidget->setGeometry(160, 300, 540, 140); SignalsTablewidget->setSelectionMode(QAbstractItemView::NoSelection); SignalsTablewidget->setColumnCount(5); SignalsTablewidget->setColumnWidth(0, 20); SignalsTablewidget->setColumnWidth(1, 120); SignalsTablewidget->setColumnWidth(2, 120); SignalsTablewidget->setColumnWidth(3, 120); SignalsTablewidget->setColumnWidth(4, 120); SignalsTablewidget->setRowCount(1); SignalsTablewidget->setRowHeight(0, 25); SignalsTablewidget->setCellWidget(0, 0, new QCheckBox); ((QCheckBox *)SignalsTablewidget->cellWidget(0, 0))->setCheckState(Qt::Checked); SignalsTablewidget->setCellWidget(0, 1, new QLineEdit); ((QLineEdit *)SignalsTablewidget->cellWidget(0, 1))->setMaxLength(16); SignalsTablewidget->setCellWidget(0, 2, new QLineEdit); ((QLineEdit *)SignalsTablewidget->cellWidget(0, 2))->setMaxLength(7); ((QLineEdit *)SignalsTablewidget->cellWidget(0, 2))->setEnabled(false); SignalsTablewidget->setCellWidget(0, 3, new QLineEdit); ((QLineEdit *)SignalsTablewidget->cellWidget(0, 3))->setMaxLength(8); SignalsTablewidget->setCellWidget(0, 4, new QDoubleSpinBox); ((QDoubleSpinBox *)SignalsTablewidget->cellWidget(0, 4))->setDecimals(4); ((QDoubleSpinBox *)SignalsTablewidget->cellWidget(0, 4))->setRange(0.0001,1000000.0); ((QDoubleSpinBox *)SignalsTablewidget->cellWidget(0, 4))->setValue(1.0); QStringList horizontallabels; horizontallabels += ""; horizontallabels += "Label"; horizontallabels += "Physical maximum"; horizontallabels += "Physical dimension"; horizontallabels += "Multiplier"; SignalsTablewidget->setHorizontalHeaderLabels(horizontallabels); GoButton = new QPushButton(ascii2edfDialog); GoButton->setGeometry(20, 480, 75, 25); GoButton->setText("Start"); CloseButton = new QPushButton(ascii2edfDialog); CloseButton->setGeometry(160, 480, 75, 25); CloseButton->setText("Cancel"); SaveButton = new QPushButton(ascii2edfDialog); SaveButton->setGeometry(485, 480, 75, 25); SaveButton->setText("Save"); SaveButton->setToolTip("Save settings as a template"); LoadButton = new QPushButton(ascii2edfDialog); LoadButton->setGeometry(625, 480, 75, 25); LoadButton->setText("Load"); LoadButton->setToolTip("Load settings from a template"); columns = 1; edfsignals = 1; QObject::connect(NumcolumnsSpinbox, SIGNAL(valueChanged(int)), this, SLOT(numofcolumnschanged(int))); QObject::connect(GoButton, SIGNAL(clicked()), this, SLOT(gobuttonpressed())); QObject::connect(CloseButton, SIGNAL(clicked()), ascii2edfDialog, SLOT(close())); QObject::connect(SaveButton, SIGNAL(clicked()), this, SLOT(savebuttonpressed())); QObject::connect(LoadButton, SIGNAL(clicked()), this, SLOT(loadbuttonpressed())); QObject::connect(autoPhysicalMaximumCheckbox, SIGNAL(stateChanged(int)), this, SLOT(autoPhysicalMaximumCheckboxChanged(int))); ascii2edfDialog->exec(); } void UI_ASCII2EDFapp::autoPhysicalMaximumCheckboxChanged(int state) { int i; if(state == Qt::Checked) { autoPhysicalMaximum = 1; for(i=0; i< columns; i++) { ((QLineEdit *)SignalsTablewidget->cellWidget(i, 2))->setEnabled(false); } } else { autoPhysicalMaximum = 0; for(i=0; i< columns; i++) { ((QLineEdit *)SignalsTablewidget->cellWidget(i, 2))->setEnabled(true); } } } void UI_ASCII2EDFapp::numofcolumnschanged(int cnt) { int i; if(cnt>columns) { SignalsTablewidget->setRowCount(cnt); for(i=columns; isetRowHeight(i, 20); SignalsTablewidget->setCellWidget(i, 0, new QCheckBox); ((QCheckBox *)SignalsTablewidget->cellWidget(i, 0))->setCheckState(Qt::Checked); SignalsTablewidget->setCellWidget(i, 1, new QLineEdit); ((QLineEdit *)SignalsTablewidget->cellWidget(i, 1))->setMaxLength(16); SignalsTablewidget->setCellWidget(i, 2, new QLineEdit); ((QLineEdit *)SignalsTablewidget->cellWidget(i, 2))->setMaxLength(7); if(autoPhysicalMaximum) { ((QLineEdit *)SignalsTablewidget->cellWidget(i, 2))->setEnabled(false); } else { ((QLineEdit *)SignalsTablewidget->cellWidget(i, 2))->setEnabled(true); } SignalsTablewidget->setCellWidget(i, 3, new QLineEdit); ((QLineEdit *)SignalsTablewidget->cellWidget(i, 3))->setMaxLength(8); SignalsTablewidget->setCellWidget(i, 4, new QDoubleSpinBox); ((QDoubleSpinBox *)SignalsTablewidget->cellWidget(i, 4))->setDecimals(4); ((QDoubleSpinBox *)SignalsTablewidget->cellWidget(i, 4))->setRange(0.0001,1000000.0); ((QDoubleSpinBox *)SignalsTablewidget->cellWidget(i, 4))->setValue(1.0); edfsignals++; } } if(cnt=cnt; i--) { delete SignalsTablewidget->cellWidget(i, 0); delete SignalsTablewidget->cellWidget(i, 1); delete SignalsTablewidget->cellWidget(i, 2); delete SignalsTablewidget->cellWidget(i, 3); delete SignalsTablewidget->cellWidget(i, 4); SignalsTablewidget->removeRow(i); edfsignals--; } } columns = cnt; } void UI_ASCII2EDFapp::gobuttonpressed() { int i, j, k, p, column, column_end, headersize, temp, datarecords, str_start, line_nr, smpls_per_block=0, bufsize=0, edf_signal, len; char path[MAX_PATH_LENGTH], txt_string[ASCII_MAX_LINE_LEN], str[256], line[ASCII_MAX_LINE_LEN], *buf, scratchpad[128], outputfilename[MAX_PATH_LENGTH]; FILE *inputfile, *outputfile; ascii2edfDialog->setEnabled(false); if(edfButton->isChecked() == true) { edf_format = 1; } else { edf_format = 0; } if(check_input()) { ascii2edfDialog->setEnabled(true); return; } if(!(strlen(PatientnameLineEdit->text().toLatin1().data()))) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a subjectname."); messagewindow.exec(); ascii2edfDialog->setEnabled(true); return; } if(!(strlen(RecordingLineEdit->text().toLatin1().data()))) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a recording description."); messagewindow.exec(); ascii2edfDialog->setEnabled(true); return; } strcpy(path, QFileDialog::getOpenFileName(0, "Open ASCII file", QString::fromLocal8Bit(recent_opendir), "ASCII files (*.txt *.TXT *.csv *.CSV)").toLocal8Bit().data()); if(!strcmp(path, "")) { ascii2edfDialog->setEnabled(true); return; } get_directory_from_path(recent_opendir, path, MAX_PATH_LENGTH); inputfile = fopeno(path, "rb"); if(inputfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); messagewindow.exec(); ascii2edfDialog->setEnabled(true); return; } /********************** check file *************************/ rewind(inputfile); temp = 0; for(i=0; i<(startline-1);) { temp = fgetc(inputfile); if(temp==EOF) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "File does not contain enough lines."); messagewindow.exec(); fclose(inputfile); ascii2edfDialog->setEnabled(true); return; } if(temp=='\n') { i++; } } headersize = ftello(inputfile); columns = NumcolumnsSpinbox->value(); column_end = 1; column = 0; for(i=0; i<(ASCII_MAX_LINE_LEN - 2); i++) { temp = fgetc(inputfile); if(temp==EOF) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "File does not contain enough lines."); messagewindow.exec(); fclose(inputfile); ascii2edfDialog->setEnabled(true); return; } if(temp=='\r') { continue; } if(temp==separator) { if(!column_end) { column++; column_end = 1; } } else { if(temp=='\n') { if(!column_end) { column++; } if(column!=columns) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Number of columns does not match."); messagewindow.exec(); fclose(inputfile); ascii2edfDialog->setEnabled(true); return; } break; } column_end = 0; } } if(i>ASCII_MAX_LINE_LEN) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Too many characters in a line."); messagewindow.exec(); fclose(inputfile); ascii2edfDialog->setEnabled(true); return; } /***************** find highest physical maximums ***********************/ if(autoPhysicalMaximum) { QApplication::setOverrideCursor(Qt::WaitCursor); for(j=0; j<10; j++) qApp->processEvents(); for(i=0; isetEnabled(true); return; } line_nr++; for(j=0; jprocessEvents(); continue; } i++; if(i>(ASCII_MAX_LINE_LEN - 2)) { QApplication::restoreOverrideCursor(); snprintf(txt_string, ASCII_MAX_LINE_LEN, "Error, line %i is too long.\n", line_nr); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); fclose(inputfile); ascii2edfDialog->setEnabled(true); return; } } columns = NumcolumnsSpinbox->value(); edf_signal = 0; for(i=0; icellWidget(i, 4))->value(); if(physmax[edf_signal] > 9999999.0) { physmax[edf_signal] = 9999999.0; } if(edf_format) { sensitivity[edf_signal] = 32767.0 / physmax[edf_signal]; } else { sensitivity[edf_signal] = 8388607.0 / physmax[edf_signal]; } sensitivity[edf_signal++] *= ((QDoubleSpinBox *)SignalsTablewidget->cellWidget(i, 4))->value(); } } QApplication::restoreOverrideCursor(); } /***************** write header *****************************************/ outputfilename[0] = 0; if(recent_savedir[0]!=0) { strcpy(outputfilename, recent_savedir); strcat(outputfilename, "/"); } len = strlen(outputfilename); get_filename_from_path(outputfilename + len, path, MAX_PATH_LENGTH - len); remove_extension_from_filename(outputfilename); if(edf_format) { strcat(outputfilename, ".edf"); strcpy(outputfilename, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(outputfilename), "EDF files (*.edf *.EDF)").toLocal8Bit().data()); } else { strcat(outputfilename, ".bdf"); strcpy(outputfilename, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(outputfilename), "BDF files (*.bdf *.BDF)").toLocal8Bit().data()); } if(!strcmp(outputfilename, "")) { fclose(inputfile); ascii2edfDialog->setEnabled(true); return; } get_directory_from_path(recent_savedir, outputfilename, MAX_PATH_LENGTH); outputfile = fopeno(outputfilename, "wb"); if(outputfile==NULL) { snprintf(txt_string, ASCII_MAX_LINE_LEN, "Can not open file %s for writing.", outputfilename); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); fclose(inputfile); ascii2edfDialog->setEnabled(true); return; } if(edf_format) { fprintf(outputfile, "0 "); } else { fputc(255, outputfile); fprintf(outputfile, "BIOSEMI"); } p = snprintf(scratchpad, 128, "%s", PatientnameLineEdit->text().toLatin1().data()); for( ; p<80; p++) { scratchpad[p] = ' '; } latin1_to_ascii(scratchpad, 80); scratchpad[80] = 0; fprintf(outputfile, "%s", scratchpad); p = snprintf(scratchpad, 128, "%s", RecordingLineEdit->text().toLatin1().data()); for( ; p<80; p++) { scratchpad[p] = ' '; } latin1_to_ascii(scratchpad, 80); scratchpad[80] = 0; fprintf(outputfile, "%s", scratchpad); fprintf(outputfile, "%02i.%02i.%02i%02i.%02i.%02i", StartDatetimeedit->date().day(), StartDatetimeedit->date().month(), StartDatetimeedit->date().year() % 100, StartDatetimeedit->time().hour(), StartDatetimeedit->time().minute(), StartDatetimeedit->time().second()); fprintf(outputfile, "%-8i", 256 * edfsignals + 256); fprintf(outputfile, " "); fprintf(outputfile, "-1 "); if(samplefrequency<1.0) { datrecduration = 1.0 / samplefrequency; snprintf(str, 256, "%.8f", datrecduration); if(fwrite(str, 8, 1, outputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A write error occurred."); messagewindow.exec(); fclose(inputfile); fclose(outputfile); ascii2edfDialog->setEnabled(true); return; } } else { if(((int)samplefrequency)%10) { datrecduration = 1.0; fprintf(outputfile, "1 "); } else { datrecduration = 0.1; fprintf(outputfile, "0.1 "); } } fprintf(outputfile, "%-4i", edfsignals); for(i=0; icellWidget(i, 1))->text().toLatin1().data()); for(j=p; j<16; j++) { fputc(' ', outputfile); } } } for(i=0; i<(80*edfsignals); i++) { fputc(' ', outputfile); } for(i=0; icellWidget(i, 3))->text().toLatin1().data()); for(j=p; j<8; j++) { fputc(' ', outputfile); } } } edf_signal = 0; for(i=0; icellWidget(i, 2))->text().toLatin1().data()); for(j=p; j<7; j++) { fputc(' ', outputfile); } } } } edf_signal = 0; for(i=0; icellWidget(i, 2))->text().toLatin1().data()); for(j=p; j<8; j++) { fputc(' ', outputfile); } if(edf_format) { sensitivity[edf_signal] = 32767.0 / atof(((QLineEdit *)SignalsTablewidget->cellWidget(i, 2))->text().toLatin1().data()); } else { sensitivity[edf_signal] = 8388607.0 / atof(((QLineEdit *)SignalsTablewidget->cellWidget(i, 2))->text().toLatin1().data()); } sensitivity[edf_signal++] *= ((QDoubleSpinBox *)SignalsTablewidget->cellWidget(i, 4))->value(); } } } for(i=0; iprocessEvents(); if(edf_format) { bufsize = smpls_per_block * 2 * edfsignals; } else { bufsize = smpls_per_block * 3 * edfsignals; } buf = (char *)calloc(1, bufsize); if(buf==NULL) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "Malloc error (buf)"); messagewindow.exec(); fclose(inputfile); fclose(outputfile); ascii2edfDialog->setEnabled(true); return; } fseeko(inputfile, (long long)headersize, SEEK_SET); i = 0; k = 0; column = 0; column_end = 1; datarecords = 0; str_start = 0; edf_signal = 0; line_nr = startline; while(1) { temp = fgetc(inputfile); if(temp==EOF) { break; } line[i] = temp; if(line[i]=='\r') { continue; } if(separator!=',') { if(line[i]==',') { line[i] = '.'; } } if(line[i]==separator) { if(!column_end) { if(column_enabled[column]) { value[edf_signal] = atof(line + str_start); edf_signal++; } column_end = 1; column++; } } else { if(line[i]!='\n') { if(column_end) { str_start = i; column_end = 0; } } } if(line[i]=='\n') { if(!column_end) { if(column_enabled[column]) { value[edf_signal] = atof(line + str_start); edf_signal++; } column++; column_end = 1; } if(column!=columns) { for(j=0; jsetEnabled(true); return; } line_nr++; for(j=0; j32767) temp = 32767; if(temp<-32768) temp = -32768; *(((short *)buf) + k + (j * smpls_per_block)) = (short)temp; } else { if(temp>8388607) temp = 8388607; if(temp<-8388608) temp = -8388608; p = (k + (j * smpls_per_block)) * 3; buf[p++] = temp & 0xff; buf[p++] = (temp>>8) & 0xff; buf[p] = (temp>>16) & 0xff; } } k++; if(k>=smpls_per_block) { if(fwrite(buf, bufsize, 1, outputfile)!=1) { QApplication::restoreOverrideCursor(); QMessageBox messagewindow(QMessageBox::Critical, "Error", "Write error during conversion."); messagewindow.exec(); fclose(inputfile); fclose(outputfile); free(buf); ascii2edfDialog->setEnabled(true); return; } datarecords++; k = 0; } str_start = 0; i = 0; column = 0; column_end = 1; edf_signal = 0; qApp->processEvents(); continue; } i++; if(i>(ASCII_MAX_LINE_LEN - 2)) { QApplication::restoreOverrideCursor(); snprintf(txt_string, ASCII_MAX_LINE_LEN, "Error, line %i is too long.\n", line_nr); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); fclose(inputfile); fclose(outputfile); free(buf); ascii2edfDialog->setEnabled(true); return; } } QApplication::restoreOverrideCursor(); fseeko(outputfile, 236LL, SEEK_SET); fprintf(outputfile, "%-8i", datarecords); free(buf); if(fclose(outputfile)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when closing outputfile."); messagewindow.exec(); fclose(inputfile); ascii2edfDialog->setEnabled(true); return; } if(fclose(inputfile)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred when closing inputfile."); messagewindow.exec(); ascii2edfDialog->setEnabled(true); return; } snprintf(txt_string, ASCII_MAX_LINE_LEN, "Done. EDF file is located at %s\n", outputfilename); QMessageBox messagewindow(QMessageBox::Information, "Ready", txt_string); messagewindow.setIconPixmap(QPixmap(":/images/ok.png")); messagewindow.exec(); ascii2edfDialog->setEnabled(true); } void UI_ASCII2EDFapp::savebuttonpressed() { int i, j, len; char path[MAX_PATH_LENGTH], str[128]; FILE *outputfile; ascii2edfDialog->setEnabled(false); if(check_input()) { ascii2edfDialog->setEnabled(true); return; } path[0] = 0; if(recent_savedir[0]!=0) { strcpy(path, recent_savedir); strcat(path, "/"); } strcat(path, "ascii_to_edf.template"); strcpy(path, QFileDialog::getSaveFileName(0, "Save parameters", QString::fromLocal8Bit(path), "Template files (*.template *.TEMPLATE)").toLocal8Bit().data()); if(!strcmp(path, "")) { ascii2edfDialog->setEnabled(true); return; } get_directory_from_path(recent_savedir, path, MAX_PATH_LENGTH); outputfile = fopeno(path, "wb"); if(outputfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for writing."); messagewindow.exec(); ascii2edfDialog->setEnabled(true); return; } fprintf(outputfile, "\n<" PROGRAM_NAME "_ascii2edf_template>\n"); fprintf(outputfile, " %s\n", SeparatorLineEdit->text().toLatin1().data()); fprintf(outputfile, " %i\n", columns); fprintf(outputfile, " %i\n", startline); fprintf(outputfile, " %.10f\n", samplefrequency); fprintf(outputfile, " %i\n", autoPhysicalMaximum); if(edfButton->isChecked() == true) { fprintf(outputfile, " 1\n"); } else { fprintf(outputfile, " 0\n"); } for(i=0; i\n"); if(((QCheckBox *)SignalsTablewidget->cellWidget(i, 0))->checkState()==Qt::Checked) { fprintf(outputfile, " 1\n"); } else { fprintf(outputfile, " 0\n"); } strcpy(str, ((QLineEdit *)SignalsTablewidget->cellWidget(i, 1))->text().toLatin1().data()); len = strlen(str); for(j=len-1; j>0; j--) { if(str[j]!=' ') break; } str[j+1] = 0; fprintf(outputfile, " \n", str); strcpy(str, ((QLineEdit *)SignalsTablewidget->cellWidget(i, 2))->text().toLatin1().data()); len = strlen(str); for(j=len-1; j>0; j--) { if(str[j]!=' ') break; } str[j+1] = 0; fprintf(outputfile, " %s\n", str); strcpy(str, ((QLineEdit *)SignalsTablewidget->cellWidget(i, 3))->text().toLatin1().data()); len = strlen(str); for(j=len-1; j>0; j--) { if(str[j]!=' ') break; } str[j+1] = 0; fprintf(outputfile, " %s\n", str); fprintf(outputfile, " %f\n", ((QDoubleSpinBox *)SignalsTablewidget->cellWidget(i, 4))->value()); fprintf(outputfile, " \n"); } fprintf(outputfile, "\n"); fclose(outputfile); ascii2edfDialog->setEnabled(true); } void UI_ASCII2EDFapp::loadbuttonpressed() { int i, temp; char path[MAX_PATH_LENGTH], result[XML_STRBUFLEN]; double f_temp; struct xml_handle *xml_hdl; strcpy(path, QFileDialog::getOpenFileName(0, "Load parameters", QString::fromLocal8Bit(recent_opendir), "Template files (*.template *.TEMPLATE)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(recent_opendir, path, MAX_PATH_LENGTH); xml_hdl = xml_get_handle(path); if(xml_hdl==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for reading."); messagewindow.exec(); return; } if(strcmp(xml_hdl->elementname[xml_hdl->level], PROGRAM_NAME "_ascii2edf_template")) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_goto_nth_element_inside(xml_hdl, "separator", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } if(!strcmp(result, "tab")) { SeparatorLineEdit->setText("tab"); } else { if(strlen(result)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } else { if((result[0]<32)||(result[0]>126)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } SeparatorLineEdit->setText(result); } } xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "columns", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } temp = atoi(result); if((temp<1)||(temp>256)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } NumcolumnsSpinbox->setValue(temp); columns = temp; SignalsTablewidget->setRowCount(columns); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "startline", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } temp = atoi(result); if((temp<1)||(temp>100)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } DatastartSpinbox->setValue(temp); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "samplefrequency", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } f_temp = atof(result); if((f_temp<0.0000001)||(f_temp>1000000.0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } SamplefreqSpinbox->setValue(f_temp); xml_go_up(xml_hdl); if(!(xml_goto_nth_element_inside(xml_hdl, "autophysicalmaximum", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } autoPhysicalMaximum = atoi(result); if((autoPhysicalMaximum<0)||(autoPhysicalMaximum>1)) { autoPhysicalMaximum = 1; } if(autoPhysicalMaximum) { autoPhysicalMaximumCheckbox->setCheckState(Qt::Checked); } else { autoPhysicalMaximumCheckbox->setCheckState(Qt::Unchecked); } xml_go_up(xml_hdl); } if(!(xml_goto_nth_element_inside(xml_hdl, "edf_format", 0))) { if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } edf_format = atoi(result); if((edf_format<0)||(edf_format>1)) { edf_format = 0; } if(edf_format) { edfButton->setChecked(true); } else { bdfButton->setChecked(true); } xml_go_up(xml_hdl); } for(i=0; icellWidget(i, 0))->setCheckState(Qt::Unchecked); } xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "label", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } ((QLineEdit *)SignalsTablewidget->cellWidget(i, 1))->setText(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "physical_maximum", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } ((QLineEdit *)SignalsTablewidget->cellWidget(i, 2))->setText(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "physical_dimension", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } ((QLineEdit *)SignalsTablewidget->cellWidget(i, 3))->setText(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "multiplier", 0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this template."); messagewindow.exec(); xml_close(xml_hdl); return; } ((QDoubleSpinBox *)SignalsTablewidget->cellWidget(i, 4))->setValue(atof(result)); xml_go_up(xml_hdl); xml_go_up(xml_hdl); } xml_close(xml_hdl); } int UI_ASCII2EDFapp::check_input(void) { int i, j, k, len, dot; char str[128], big_str[ASCII_MAX_LINE_LEN]; const char *columnname[]={"", "Label", "Physical maximum", "Physical dimension"}; strcpy(str, SeparatorLineEdit->text().toLatin1().data()); if(!strcmp(str, "tab")) { separator = '\t'; } else { if(strlen(str)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Separator must be one character or tab."); messagewindow.exec(); return(1); } if((str[0]<32)||(str[0]>126)) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Separator character is not a valid ASCII character."); messagewindow.exec(); return(1); } if(str[0]=='.') { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Separator character can not be a dot."); messagewindow.exec(); return(1); } if((str[0]>47)&&(str[0]<58)) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Separator character can not be a number."); messagewindow.exec(); return(1); } separator = str[0]; } startline = DatastartSpinbox->value(); samplefrequency = SamplefreqSpinbox->value(); if(samplefrequency>=1.0) { if(samplefrequency>((double)((int)samplefrequency))) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Only samplefrequencies below 1 Hz can have a decimal fraction."); messagewindow.exec(); return(1); } } edfsignals = 0; for(i=0; icellWidget(i, 0))->checkState()==Qt::Checked) { for(j=1; j<4; j++) { if((j == 2) && autoPhysicalMaximum) { continue; } dot = 0; strcpy(str, ((QLineEdit *)SignalsTablewidget->cellWidget(i, j))->text().toLatin1().data()); len = strlen(str); if(!len) { snprintf(big_str, ASCII_MAX_LINE_LEN, "%s field of row %i is empty.", columnname[j], i + 1); QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", big_str); messagewindow.exec(); return(1); } for(k=0; k126)) { snprintf(big_str, ASCII_MAX_LINE_LEN, "Character %i in %s field of row %i is not a valid ASCII character.", k + 1, columnname[j], i + 1); QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", big_str); messagewindow.exec(); return(1); } if(str[k]==' ') { if(k==0) { snprintf(big_str, ASCII_MAX_LINE_LEN, "Text in %s field of row %i is not valid.\nField must not be empty and left-aligned (no spaces in front of the text).", columnname[j], i + 1); QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", big_str); messagewindow.exec(); return(1); } } if(j==2) { if(str[len-1]=='.') { snprintf(big_str, ASCII_MAX_LINE_LEN, "Text in %s field of row %i is not valid.\n" "Last character can not be a dot.", columnname[j], i + 1); QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", big_str); messagewindow.exec(); return(1); } if((str[k]<48)||(str[k]>57)) { if(str[k]=='.') { if(dot) { snprintf(big_str, ASCII_MAX_LINE_LEN, "Text in %s field of row %i is not valid.\n" "Only one dot is allowed as a decimal separator.", columnname[j], i + 1); QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", big_str); messagewindow.exec(); return(1); } else { if(k==0) { snprintf(big_str, ASCII_MAX_LINE_LEN, "Text in %s field of row %i is not valid.\n" "First character can not be a dot.", columnname[j], i + 1); QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", big_str); messagewindow.exec(); return(1); } dot = 1; } } else { snprintf(big_str, ASCII_MAX_LINE_LEN, "Text in %s field of row %i is not valid.\n" "Field must contain a number and no spaces.", columnname[j], i + 1); QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", big_str); messagewindow.exec(); return(1); } } } } if(j==2) { if(atof(str)<1.0) { snprintf(big_str, ASCII_MAX_LINE_LEN, "Value in %s field of row %i is not valid.\n" "Value must be 1 or more.", columnname[j], i + 1); QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", big_str); messagewindow.exec(); return(1); } } } edfsignals++; column_enabled[i] = 1; } else { column_enabled[i] = 0; } } if(edfsignals<1) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "At least one row needs to be checked."); messagewindow.exec(); return(1); } return(0); } edfbrowser_157_source/PaxHeaders.7921/edf_annot_list.h0000644000000000000000000000013212646460742020027 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/edf_annot_list.h0000644000175000001440000000370112646460742020371 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef EDFPLUS_ANNOT_LIST_H #define EDFPLUS_ANNOT_LIST_H #include #include #include "global.h" #ifdef __cplusplus extern "C" { #endif void edfplus_annotation_add_item(struct annotationblock **, struct annotationblock *); void edfplus_annotation_add_copy(struct annotationblock **, struct annotationblock *); int edfplus_annotation_count(struct annotationblock **); void edfplus_annotation_delete(struct annotationblock **, int); void edfplus_annotation_delete_list(struct annotationblock **); struct annotationblock * edfplus_annotation_item(struct annotationblock **, int); void edfplus_annotation_sort(struct annotationblock **); struct annotationblock * edfplus_annotation_copy_list(struct annotationblock **); int get_tal_timestamp_digit_cnt(struct edfhdrblock *); int get_tal_timestamp_decimal_cnt(struct edfhdrblock *); int get_max_annotation_strlen(struct annotationblock **); #ifdef __cplusplus } /* extern "C" */ #endif #endif edfbrowser_157_source/PaxHeaders.7921/active_file_chooser.h0000644000000000000000000000013212646460742021033 xustar0030 mtime=1452958178.237246767 30 atime=1452958178.237246767 30 ctime=1452958178.237246767 edfbrowser_157_source/active_file_chooser.h0000644000175000001440000000314212646460742021374 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef ACTIVEFILESAVERFORM1_H #define ACTIVEFILESAVERFORM1_H #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" class UI_Mainwindow; class UI_activeFileChooserWindow : public QObject { Q_OBJECT public: UI_activeFileChooserWindow(int *, QWidget *); private: QDialog *chooserDialog; QPushButton *okButton, *cancelButton; QListWidget *filelist; int *file_num; UI_Mainwindow *mainwindow; private slots: void okButtonClicked(); }; #endif edfbrowser_157_source/PaxHeaders.7921/averager_dialog.h0000644000000000000000000000013212646460742020152 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/averager_dialog.h0000644000175000001440000000451212646460742020515 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef AVERAGER_FORM1_H #define AVERAGER_FORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "edf_annot_list.h" #include "averager_curve_wnd.h" #include "utils.h" class UI_Mainwindow; class UI_AveragerWindow : public QObject { Q_OBJECT public: UI_AveragerWindow(QWidget *, int); ~UI_AveragerWindow(); UI_Mainwindow *mainwindow; private: QDialog *averager_dialog; QLabel *annotLabel, *annotNameLabel, *signalLabel, *ratioLabel, *bufsizeLabel, *time1Label, *time2Label; QPushButton *CloseButton, *StartButton; QListWidget *list; QComboBox *ratioBox; QTimeEdit *timeEdit1, *timeEdit2; QTime time1, time2; QDoubleSpinBox *avg_periodspinbox; char annot_str[MAX_ANNOTATION_LEN + 1]; int signal_nr; double *avgbuf; void process_avg(struct signalcompblock *); private slots: void startButtonClicked(); }; #endif // AVERAGER_FORM1_H edfbrowser_157_source/PaxHeaders.7921/images0000644000000000000000000000012712646460742016062 xustar0029 mtime=1452958178.23024679 29 atime=1452958178.23024679 29 ctime=1452958178.23024679 edfbrowser_157_source/images/0000755000175000001440000000000012646460742016474 5ustar00guvusers00000000000000edfbrowser_157_source/images/PaxHeaders.7921/edf.ico0000644000000000000000000000012712646460742017371 xustar0029 mtime=1452958178.23024679 29 atime=1452958178.23024679 29 ctime=1452958178.23024679 edfbrowser_157_source/images/edf.ico0000644000175000001440000000727612646460742017742 0ustar00guvusers0000000000000000¨(0` XXX+ƒÿedfbrowser_157_source/images/PaxHeaders.7921/edf.png0000644000000000000000000000012712646460742017403 xustar0029 mtime=1452958178.23024679 29 atime=1452958178.23024679 29 ctime=1452958178.23024679 edfbrowser_157_source/images/edf.png0000644000175000001440000000124112646460742017736 0ustar00guvusers00000000000000‰PNG  IHDR00Wù‡ pHYs  šœ†zTXtCommentxœsI-Î.É/Ð-άJMQÈLÎÏã²E\\Éš F& ^‰Ù¥I êY™¹¹‰Éê Á%©™y©E: \%%Vúú ½ÜÒâÌäŒÄœ½ä*.®ä¢ÔÄ’Ô…òÌ’ …’ŒTwOߘ–òòr½ôÌܽü¢tè,>#þÝèÁIDAThíZKnƒ0}X‘…rŽî¢ž±B½KÓMQ¯R±Bœ¥JWQÏX@•‹ÝŒÁøƒKÄÛâ™y3oüAI Ø00¼žbÇa…ä|‹„+v±q ¦å•üqžçx?}ØË§òŽsŽöùAyv|û"ídYökÇ$ƘÆÉ8æœ+„ÒòŠ´¼Þ˜³ã RBmÛ.6$º<ºE´÷ÙPU*i\…•n›¦Á±Ç>õèš8M GvN}ÙÑ”Pß÷^„I ëºÅ†ÄÒëS& %Ä9G]×`•JDë”>¡ö5öÃ\Dìbc' O’[eýö…ûðS…9ýG™W Tð®vº*PWEð‘”Ù „ Þ‡Ýrþ:1éÈvmmŠ9Ú „ʼȱÑ_%N%Æ´ Ô§í¥^GB8³!é2O“÷̶GæV@qml0üÒìOe]†U¦4K½3 ^Ì˺Œ g!—åÖ4pošÚ3B®jÖ0ÉòûHðãth›¿8õÀZ:ŸÂæ+°ˆ}bõR˜$v ÅÆæ $Øøßm¾8Ô»•‘ÉÔIEND®B`‚edfbrowser_157_source/images/PaxHeaders.7921/ok.png0000644000000000000000000000012712646460742017256 xustar0029 mtime=1452958178.23024679 29 atime=1452958178.23024679 29 ctime=1452958178.23024679 edfbrowser_157_source/images/ok.png0000644000175000001440000000475312646460742017624 0ustar00guvusers00000000000000‰PNG  IHDR00Wù‡tEXtSoftwareAdobe ImageReadyqÉe< IDATxÚìZ[lGþfwÏÅ>Çvl'q“¦IêVMšD¡Ê-•¨ } q“*Ê @êˆ"ñ„Bž ¥žR¤Š6…B…ˆT*MÛÈ…¤IHÇI|͉ÏmÏewg˜ëîì9§¶)¤¬5™=»³3ÿ÷ßæÿÿ aŒáÿù"7Üð_ð _IÍ×£™‹õhøþ­?þ·ÖwÞ&èy2ºeuËY÷¿ÍX‡3€üÇ$°ë{;qçm“õVýOµº¿¿\ñsQ½#ª1rò¯üQh¿7t¯àÇ޿k¹\›ºybcvç¶ l†ëºœåü¶‹ž¨žÿ9DõJ,º'b1£C,î)cªÿ2Ó'c®—«˜](áÕœcãƒ#?zñ˯<Æ·Œê­ À~~`i÷ä-ã“Û·Xú¢DKÂÞ3Ž£AH¢5Ž©%É„KOPÌÐħðý6ž;rœù/úw;|ùŒñVc¥Zß±u4bhÔÚ¢j I´Cˆ¨gª%%ÉeM$å ’g®ÇçË:( çÏe°cëM¤ðÙü£À#|š€7jh\ÀØÈŸ8â,k”ÛÝDwÜ’¨!Z^± %*b¸LøÜDôLŒTÏù‚œI aò9ä F‡ Ⱥ™;…iðV5RX@Æó$÷Àvï:Jm\þ›èÞ€0¤´˜@rZ0†P8¢×¤n %t¨¼Òë‹5=.þ2¯i^Í>´š$ÄÇDO,0F…, 6áF…ñ„PÞ … FÏ ñ^¯/¿£r€ÛéúW W“4êaˆKR0"°ADBu4ñU’е– Ñû ÓFï §·ñVóÇŒiÏã¤[/ Hb ÐjÄ”źï%Nâ•c%qs¸`e ý`R’jË&ŠËBMRD»¶D53ª”’€ö2ó—Kp2.²¼œï ’Å8¢šä½[g(‘lR’0M¤ ‹› òøf—qÝžý¥³ópkì:ˆ°¡å)5Tó'nÙ §Ö§Bf75®Òx"nFÖ{Ë iâjÓ¤xð=ŸÁþíïÅûêà…ÓOáÂÒ) ŽäÕüBÙ!±Ø¬•›Uhú»DíYlFm: [´Ø,>{rÛGvc϶òÙæÂ6<|Ï×1]}Ï\ü "n‚xÂŒ#°6DŽÉñBCÚ éЉ2»­‹:q¡6¡Nv¿xe¬Mð±{æÏ2©U¶v&Þ+µìõ‰Ð—ì°Œ¦­Áòó¤„í™ä³ÄˆË×ê8°ã>LlØÖµÎѹ§S!H¼Ðd;.Y‡ Ä¢´U)Ž>-$Þì´GÒÞù3W¶‡û÷~BÙ†uÍ5.àÍêÉ8¾Š×ÐÀÅ}È7‚ZTú–@ƒú(·—1èù@3Çʽ#v 8 (Ÿ‚÷ïý ¹áÔü ðòµßÆó˜¹Å]›¿«‡54Ã:Êá5ÍVÿÚQC™ 8W;6€b¶(ÛSäéT>^ìÂéY yã`yccCß<sô©KüÛ1¸õ¾®ù/Ö§°Ôº"ǶYˆjTE­]“­Ô°9·ïz764®áÕæ1¬Ë MöàŽâ~”›K˜kÍ ,`6œF!Ä`f™®VJøÒÁ/`rón»øk\ånqp9˜¦âãw=Ä÷lj^?*ãùÅ_`©½?ðQêÈÓ"FÝM˜ÞÍ¥>Št¹9¥×ÞÒÛ¬ àù¹§¤w7cb` vöq©àƒs‰^Ç™×ßä^ävÜ}˽rüGw}g˯á™+ã/ÁÞ⽘œØÓ5ï±ëÏ¢”0D†±%·ƒ¹"jD¹]Æ©êóJ5½$¡à.”­k#_-¶æQ à6ĦEËæ$Vàk|75þŽ‘»ñèÈ“øKñ÷¸}l—Û\j_Ɖåpµ©ð9§ƒi´Â"¶G<|a4KyB_°^œµ‘ŸBL€pÂËaáHSµ?÷üòàö`Sqk×óÃK?ÅB0kÁjamë°Yo©Â‹Ê’e±þc!ó± Ä’{‘©‰¤¤°1‡CW€ïüósx½v¼çNn_güW0U9®RHªSJ}ßk˯W6çõB"Ñ‹ úgfýi<9ý-<1óM̵§{NÓânùÙ¹Çåx»fH)P;ñI"8q¿`I)DL,ˆ•¾^m04R‘–fý½ü7¿áƒãŸÄƒ›>¬“ß½´üÌøçÁ‘"šÒ4j@Z]K“z£«H€t$fÖäöâ‘Õh¨ŒðÈÂÓxì̧q¬tXα,âðìÏÔ{{¼„ÑD±=˜`¤Sל‘- -©>©Ê'Uƒ¸g’!°¨’R-ªàÐ¥âèâs˜Ü‹z«'ô]R ¶ ÒNGÅC&¹Y_> ƒ*ÊhRéQ²Ü!i€‰­§«çdÓɹ¥óiI¦ÀˆÔ“ÅØ:óÛHK ŠVÚ]nSÄk#WÜW_'P»*a;‚N ¤ZÏw*ßì€.dÄ3ý¡ÖÞ “~C<³£I¦Ä…!í’a¹án›ŠË(Æb²6?Ç:itߦÓ͵Dò‘Ñ^×!!ÿ«×šÜø¯7¬~ýK€úˆ#¸Ø"ÁIEND®B`‚edfbrowser_157_source/images/PaxHeaders.7921/splash.png0000644000000000000000000000012712646460742020137 xustar0029 mtime=1452958178.23024679 29 atime=1452958178.23024679 29 ctime=1452958178.23024679 edfbrowser_157_source/images/splash.png0000644000175000001440000002176012646460742020502 0ustar00guvusers00000000000000‰PNG  IHDR©æº ‹bKGDÿÿÿ ½§“ pHYs  šœtIMEàsæ~ !iTXtCommentCreated with The GIMPm°— IDATxíœU½Çÿ›Ýl6›^6=!½Ð*Z@ ”Ð"" ("Ôç|"">òÁÂ""b("( &½BIL!=Ùô¶i»É–÷ÿßÝÙ;wnÉfÏùþ?ŸåÞ9sæÌÿ|ÿÃýåœùÏ™‚ºÇÖ @p@}Â%@€@‚"Å…@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î@¤œ ŽA€"Å5@Î(rÖ3k"pí'Mß?‹o?Ý'óYšãO]Hmuý_Õ6‘›E*V‰¬_$²â#‘…¯×—e>sö½Íñ-{«©5²1J=‚@ ©f@ãf(()l[ÿ×¶½HÇž"eÃD†}±¾±Ú‘ù/‹¼5MdÙÍ8‡@Q$Àt_£š}jS(2êh‘ ™öŸ!&€Hµ0PškcO¹øQ‘îƒ[ 1š€ò™"•ÏÑ‹²ï]û‰œÿ{‘žC£ÜKúd!À=©,€œÝíÚû\ü),)Ò¿Òn"ôž” Рë§ùÚuLEm÷­Î¾]ä¾/‹TV¤îϵ$ßrm‹z€ÀgJ€‘ÔgŠ;æ'«Ù)RµUdã2‘åš1ó1‘'(rÛD‘×ï©«MÔ}ȤRË)bA‘ŠE˜ïdÕ‘—~%òÇ‹EvnOuv´Š˜—˜º—@ ©7ﺶ䑇¾)R³+Õõ£¿“ZF  yˆTäCœg\ö¾È ¿Huº÷h‘½Æ§–SDš"éðæiçÞÑg¥VÍIu~¿ÓRË("M‘Štxó¸s¯ü&ÕùD ô¡_ ˆ D*6¡Î³ŽÚI¶¾ŸßÚwé—e]A}¾CyO‘ÊûF´uº–ß‚×R;×oßÔ2J È@¤"ÚtlŇ©è;&µŒ@ ²©È†6[§¯ñZ—þÁ¶!`Y¤| nk½7É¥%„leŠ uî,ɾÝR¬\b“½×Ô€@$0’ŠD#Ú‰úrÄ •t –° D˜"áàæ}×–H²&b€@l R± uv4ly¤Bf¨ó0’¸ f@¤šŽ[@Q»ÔSTëJê ü³4_C‡›øÅ¥©ÑÙµ#µ,[IXecÀ~ä)FRy¸X¸Ý±,µ›Û6¤–QD–"ÙÐF c]¤vbËêÔ2J È@¤"Út¬÷¨ÔN¬[˜ZF  YˆTdCŽíuPj'V‡¼Â#µ%€@D R däºQÒYdÀ¸Ôn-‘ZF  YˆTdC›çÛ÷d‘Â¶ÉØ°T$l©¤äZlA"€HE(˜‘éJ}2âóS»3û™Ô2J H@¤"Þ<íœ T×Àjçuµ"3ÏÓá6 Ð\ˆTsÉq\ë°—NøvjÛó^Ù´<µœ@ ÒXq"ÒáͳÎí5^äŒ_ˆ';^«oéýçíÉeºUð£YIeu7ŽMÚfȈTþÇ0ÿ{`)¾ñ_Uå Ü¿ý‘µóó¿ŸôØmˆÔn#ã€f°„ˆ¶%"¥ÝDºô)!2ä‘áGˆ´) ovÉ»"/ý:|¥€@ä Rùâ–zÛlºþï­á¥œ?z•Hmu:/)‡"N dn%â=¦{ùA`ùL‘ûÏÙ±9?üÅK@ U0’j¬4Úlö¾¨wÔD‰ÛDÂ^zØì†9ÈGˆT>F-Š>o]'2ûY‘·¦‰T¬Šbé Ð ˆT3 qH3 ØÈhçv‘ªm"Ûõ½PëhÖžþÙÔÞ²´Ñºf6Ìa€@T RùÙÝMbhí>¹æ¿¿êÛ‹ ·Ê]ïn”7—n—5Ûj¤gi¡Œ)k'“÷î,çë"Ú¥É$lh'ìù«O×WÉUO¯Ò¶U`ÕFö,–“Fv’›&ön8*ù£º¦N›]!|²YÞ]Q)+·¨@«õéX$h/gŽí,gí"E…ÉêÖÃo–)/o,?Të¿ù¡Ûa_ªªk¥ìæ¹²eg­´Õ;Ík®-]ÛgîçAw.å•Í=Ú,o(ǹëvʦÊ)jS ½;ÉØÞídâ°Žrî~]¤L·sµºº:ùûÜ­ògíãÛ˶ˊ-ÕR]['e¥E²¿9]ctîçºH‰u"ƒµDŒ24Ï.‡ä~u9ä4®@ Œ€ ÷þ¶R~7ccÒnû!´¿çU`nzy­Ü1©¯œ¦?†¹š Ì÷,–•[›² ?\U%»Àmhð-ýñýÚ_V$~؃çXVQ-Ëfo‘¿èßO^Z+8c@B´üõNÙQJŠ ¤²º~dùöò²J}èÓ)ü|vì³ó·&ʾïÒ¤ÿW…\x€¦ú§±å›w% T{=߉*ºf;´KþZ.ª@Íe‰kOÏÛ*×<·Z®9¢§\;¡LÚ¨€e²9k«ä¼G—Ë{>aôêÛ•Úžµi\î›ÜOŽQÌÕv7F¹¶K½?Ìÿ\ù÷û‡È™ÀÅúèàÁå*Vgüy™<0sSpWÚíKŸ(O(¯âߨÃ+{BÅa½‹CÊ«ã}ÎÑÑÉ÷.’Ìßâ%>;êHïK#š~ Mªþ67¹NÒºa£6¿=üqò¶Ÿ}bNòþT;·‘Z¡I, ¨`¶mBzý‹kå›O® ÛÝXfÂ}è] Cª±R×¥*€Çß¿DþôaëÄ(x>¶Ý&ÀHÊíøàÝn¸¿Ax†vk+?Ói¸ã†wÔé)‘×–l—>·Ff®ªŸÚÒßáÄHáàþíe´Nf3›žܵ­Ü}j?™0¸TL覽¿INS?òðŽŸµºRÎÑiº:¢ól\Ÿù鱽䰽JÅÆ¯&|Y-­®JT±ù³þ¼\f\6T§›|±éÀ¿þ«I˜žÐï—ÔÝk6és—žïÉ9Mumç :å¹a{µt×i´0³öüfç3»ã òâ¢ú)MÛîZÒ&á¿MmöïÜVjÞlýï[ä÷4‰ˆýãà«:•zÄàvX’Ù(ç”?.•ÍU:Äk°SFw’ï|¡‡¨S|m dÖšJùí;m=Cxáãå &iœ²Y®1ÊÖûÝ#ÀHʽ˜àÑ0Q˜qÙ0™²oé¦÷dìþÓ úûÖ7†ÈÑCš~@«ôWðʧ2ÿëßs£Xïýãü½d¢Š^±ªÞànÅrÃ1½Rîm]¡ííh˜¢³cRš8ïI£:I—’Bé¬öým½¿t„Š–g[õ>Òå:Mé·“µ^;ßýªtªr›Ö ³çlÕûEõû¼ ·ú)¿d!òŽÝ¬÷–þé"›Zœ¤ç3»70UúÐÙäòCz$úÜVý±{Eôk/ÓNï/—œXßÛößòÊ‚Ÿ~¡°}v;_: I~_¬^Ðûáõ[ð>’í³d‘'¦úl4q£ŽR<{IGKë¶5%{xåþiD+ó¦úì{i «î¡4BgumDi+Ï{å?eÅIöÈ'bÓ«ž]ùùÞ×´ŸÁ„ÇS“a棰ã(sŸ"å~Œð0G§IþQ;ì$MðÛëš^Íöï«‹âf±7–6‚¬jð³{jGí Ï~ZÿC¿~GXÈŸ<ê Z꺙cÉ fëHæÒƒ›.,)¢Â—À0Q§ßljѳëŽ*“gTļäÓ¥iš a6…y¬Ö?YEÍ)zé3_Ù,8}ØCŸåÚ][°!™KØñ¹Ä(ì8ÊÜ'ÀHÊýáaŽzuhú±MwHY ÎýáÏf}÷±ÒÕõF3Þþ2}€8›ë¬÷%xÇž©üú͛ڳ2KÜ7R:aDýˆÈ+«c k|Ïw¥Ë곺f–ñˆÞ×ëÜ.õ§Á¶©·‹4ë®ï-såðß-’ÛÞ\/«}í×·ÒôßLûšjeþ¶±…b”ù,ìu•@ê•誧ø,‚÷SªëTÚœX+Ìòª^åËê³íöþy:+±`{P6h§iš»ÎÈ5š=‡åÙk:=¸ZWÔ0³ù1½êSØÒ‘–—”a#!ï*[íÁŸªn.Ú”bÐNѲ¹W—ïÖCW—[sÕÎ¥®Â1pê\ùÖ“å²µ*UðýÙŽÁóäºCˆ$—åz>ê¹E ûxÝ-ñi XZyû,‚Lã¶)µ–0»·cç÷ÌVm°‡r3YЗ hÙ±=uÉ¡ šaç=»´pã.ùDŸÇ²iËGu*ϳ|ÿZö ­Öà ’-³tÙøîº<ÓŽÄ3^Þ1Ç í˜HÓ÷¶ýŸ¶ºÅ-Ç÷‘›õy³Wo×g¶*ä)} xž?h–î~§¦ŸÛʯ\<$‘RîÕ±e”¼©C+«¸vtc&¡W‡Od"ÀH*öåà”[˜óÁé§9LË…µ, N#úŸ Öõ¶ƒ¾Øƒav¦f-úí]:Èìï¾U(¼%¼z“F5%ˆ¼¢÷±L4íW¿Ûõïó¾Ûå(½Çõë“úʧß)ó¯.·Oê#–JÌ®e¥ÜøÏµÞ¡‰Ï`Ÿ–éjv‡"µ;´¨ë4y9<óä­:áud\ŸìÙf^ÝLŸ#{ÔOµyu>jXÝÂÛûü8´1TSºÃÌ]õ_ÕŒ¹-:µ¶hSý¾=fÉ~³Äo–Цæ–hÝç>m)›JÜ]®ý´‡{ŸýÚ`Yü½‘rLà¼Ág³FôHîÓ;:Ú °;©Ý¡E]§ ØsAÙ,øŒÐµŒHÛ±…R³ÙSúP­ßÒ¥g÷Ö,ºÃ5­Pñº¦»û³æl©¦Ò@rG?]ÂÈŸ–=SG96Ýç™=¤Û#dɤAzÉV÷þÊ+Ò|l™¤Îìï5™ø\¨ÿEŸßVÁ»?–tÈ@‘ʇ]ùEàž÷6ʦ ™`6Òò?tk÷‘ÎY$¶9½¶ÑŽßì™~àm_pÔá^Éß–}÷OÍYF¢?õÜ–} 3[‚ɳûÞߘXÏÛ>+0…蕟“ >gåÕó> uÝ=¿…Ïÿ °Õ3ñ~ß·²†ÿXï»ÝûòDÒ>O}p©·‹Ï@¤bô¨vÙ2Ý.ÐOÃ:5ñš2}yRrÃWõ]H¹<ë“ ¯ý5uÛF4žÙz|ç=ºB³þR³­ÌömÛÕ”haïŒ:d`Óñ^;Þ§‰ _ü‹»úSνúöé¿/õ¼.å™e Ú»µÂìüý»&Û=¦%›Ò?§tëëë’ê§ÿŒ‹¿Ì¦m^{õH˜Ù+D.ÓLA¿]6>y@ÿ>¾GŸ"ýǦ‡öãkmGÞ»(qÿ¥BR5q²ì¶õþûQý;ÉÔã{·(›Û'õM¼ÊkÔ2ò½kQ"+Î|±ûHOë(Áʼl=«k ¼ÞyJ_ï°ÐO›ZóOzI"ÃtÅwÿêéþƒm•w/…¼IEW*/Mû¢Âc5+Ð/¶öÒÈñ¿](¿y{CB¬l¦í*Àïê½%[‰â–×Ö7žÒøÿ°žÛÞãâ¥Ä[Ù<}hù€ß,ùZòˆµi w¼½^ìEŒöÎ-ÏlåŽ/5<ÿå•ñ/¤ Ç+Þ‘îíMúJŒ«õ•o,Û!ÇéûˆÒY7}ýÄ_¾20ík,Ò—­ÜÒ¨k¯$13¡ºüï+õ/±™ö?¿<±ì²ê‡½eú”rÆCËG²ö’ÃKô=]òDÚæd_}ûïÊ‹7FRñޤzo«r_­úú´¶_Ÿv‰gyìÕ­a§«¼xá`±wZe³1eÅòò׋“‹ïïØ1þç£ÂÚð^Ááí³,ÁÓ÷nºWå•û?‡h–¡=ïôùÖÙ³ãl´6]_éqÅ¡éµûc¯\çC„ƒ€âK‘Šoìé9 ç R·!Ä—"ߨÓs@Î@¤œBˆ/D*¾±§ç€œ'€H9"„ _ˆT|cOÏ!8O‘r>D8@ ¾©øÆžžCpž"å|ˆp€@| Rñ==‡ à<DÊùá  ø@¤â{z@Àyˆ”ó!ÂA@ñ%€HÅ7öô€€ó)çC„ƒ€âK‘Šoìé9 ç R·!Ä—"ߨÓs@Î@¤œBˆ/D*¾±§ç€œ'€H9"„ _ˆT|cOÏ!8O‘r>D8@ ¾©øÆžžCpž"å|ˆp€@| Rñ==‡ à<DÊùá  ø@¤â{z@Àyˆ”ó!ÂA@ñ%€HÅ7öô€€ó)çC„ƒ€âK‘Šoìé9 ç R·!Ä—"ߨÓs@Î@¤œBˆ/D*¾±§ç€œ'€H9"„ _ˆT|cOÏ!8O‘r>D8@ ¾©øÆžžCpž"å|ˆp€@| Rñ==‡ à<DÊùá  ø@¤â{z@Àyˆ”ó!ÂA@ñ%€HÅ7öô€€ó)çC„ƒ€âK‘Šoìé9 ç R·!Ä—"ߨÓs@Î@¤œBˆ/D*¾±§ç€œ'€H9"„ _ˆT|cOÏ!8O‘r>D8@ ¾©øÆžžCpž"å|ˆp€@| Rñ==‡ à<DÊùá  ø@¤â{z@Àyˆ”ó!ÂA@ñ%€HÅ7öô€€ó)çC„ƒ€âK‘Šoìé9 ç R·!Ä—"ߨÓs@Î@¤œBˆ/D*¾±§ç€œ'€H9"„ _ˆT|cOÏ!8O‘r>D8@ ¾©øÆžžCpž"å|ˆp€@| Rñ==‡ à<DÊùá  ø@¤â{z@Àyˆ”ó!ÂA@ñ%€HÅ7öô€€ó)çC„ƒ€âK‘Šoìé9 ç R·!Ä—"ߨÓs@Î@¤œBˆ/D*¾±§ç€œ'€H9"„ _ˆT|cOÏ!8O‘r>D8@ ¾©øÆžžCpž"å|ˆp€@| Rñ==‡ à<DÊùá  ø@¤â{z@Àyˆ”ó!ÂA@ñ%€HÅ7öô€€ó)çC„ƒ€âK (¾]§ç€€‹ ~4KênÛª®mÛY+{ßö©,ùÏ‘ÏS^±KúO—RÇóÏ| Z›‘šŸ´®ÿÁsFy‘Šrtéò€'­åzEeL™¾\–nÞ•õ3Ê+åô½;Écç ­ôõñÙòòâm¡u)l¦ûšÇ£  ¶WKÿ[æÊ–ªš¤þnÕí±:©®©K”ÿøÅ5Rvóéû?såêÿ[ÝXn;m´ñªþp÷ùù9òÞE‰úöc^|ý,i«ãîø4±?±£¡¾÷½¶¶N®{aM¢ÝÒfË1÷-–%›vz»mßýîrë<)¼nV¢Mk;“Müý™ú¥Þ™ª4î›Q¾Cß«Cãv¦/;«k¾þø¨^™ª±o7 R» Œêˆî¥ErˆŽr×»“º}÷{e²Ž0Š ä™›¤OÇ"YªSg{˜ŒìQ,÷ÌH­¿à»#å3$Ú™2}™LŸ2P*¯ß[®P&=^žÔ¾·ñË7ÖK·’6²à;#dÝ5£å„‘å†×z»Ÿ}´Yž½`/©¾aïD›Öv&»ñØ^²Oï’LU÷™H=5wKB€û©ÿèùÕR£ÂfÓ>Ø”ð¯kû°ݔ5“"ÕLp¸¸âÐbbQ¥#³]:zºíÍ réAÝÛw¼½AÎù\iß¶ôìÙ¯ñqDIDATP$ØM¬Ìo×U&ŠÛÈÀ.mÅ]J ¥BGc…zçÌ}ºÈ|¡0³þóÆu•R=ÖþÎ×ï/.LžN»}R_Ù³¨pv–]õn†5—(;nxÇ´û‚;f¬¨Tÿ:Ëòï”yW —î*@S_[¬–ؾó rÑõLB+PØ,Ü“j6‚@|ì×·D†u/–ûU0.=¸»üé£M:i'ƒº' Ì]W%]o𓤤H³|6¸¡®W4mr9ùÁ¥rëëëeò˜ÎrŠ˜ VÐ>]¿Sºª yf"±z[µ·™ø¡#·Ö²òŒjlºþZ^¨"tÐ äê#ÊËíËÇ«*Û£ËÚ%•³±ç©=gH ˆ<+í.×车¯ë(iêkëåç›îéÔèÈeÇuc¤DGRé̦ý6it'ùèòa²\³çnzymbTõËûú«$¾· ˆ]m]ìl¸æU..J^¯NK}vj×FVnMIkû™ù[eâ°ÜGh-åOÚù좚ô%`£Êê:¹ý­ šDQ+'ê½!φëHfM`tãíËô¹oŸ½‡ÓIn;©¯üJ§Ãl¸Žà6i6žg›*k¥mȈËÛßÒŸ§Î••[š²7쨑°‘ÛK·Ë•¶ôéiO R\€@V6ºl|wù‘fÚ]¢÷¢Úø„âw“?Ü,–ñ·NÅêg:2:vÚâŒmZfàÃoNd.Ù´K…'¼ú¥Ú¶%fl×çšìïú}TÏÖ›Þ zñ½×f÷ß,»Ñž­ºGFì]Ð>Y])c{1ÕäÒÛi.–hš6 (0Á°¼¶¯Ø5©[—è`…Ž®ß:_†üb¾¼µl»fñõOªܸwr?ùÙ+k¥ýOfë3Kõ™~Á:¶mm—oÑ4xÑ Ð¿÷V쿞þÌRØñÍ)ó? ûã£{%FrC¬ošæ¾K3ûlÊ3hæc¿ÎõI!Á}lï}-<ŸrÏÚåh@€À`$µÇi€Z‹"ÕZdi€ö˜"µÇi€Z‹"ÕZdi€ö˜ÀÿÔ±¬éë?¬HIEND®B`‚edfbrowser_157_source/PaxHeaders.7921/nexfin2edf.h0000644000000000000000000000012712646460742017073 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/nexfin2edf.h0000644000175000001440000000432212646460742017431 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_NEXFIN2EDFFORM_H #define UI_NEXFIN2EDFFORM_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "utils.h" #define MAX_SIGNALS 32 class UI_NEXFIN2EDFwindow : public QObject { Q_OBJECT public: UI_NEXFIN2EDFwindow(char *recent_dir=NULL, char *save_dir=NULL); private: QDialog *myobjectDialog; QPushButton *pushButton1, *pushButton2; QLabel *PatientnameLabel, *RecordingLabel, *DatetimeLabel; QLineEdit *PatientnameLineEdit, *RecordingLineEdit; QDateTimeEdit *StartDatetimeedit; QRadioButton *radio100button, *radio103button, *radio032button; QComboBox *analoginputscombobox; int file_type; char *recent_opendir, *recent_savedir; void enable_widgets(bool); private slots: void SelectFileButton(); void radiobuttonchecked(bool); }; #endif edfbrowser_157_source/PaxHeaders.7921/spectrum_dock.h0000644000000000000000000000013212646460742017701 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/spectrum_dock.h0000644000175000001440000001027712646460742020251 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef SPECTRUMANALYZERDOCK_H #define SPECTRUMANALYZERDOCK_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "signalcurve.h" #include "utils.h" #include "filter.h" #include "spike_filter.h" #include "ravg_filter.h" #include "flywheel.h" #include "third_party/fidlib/fidlib.h" #include "third_party/kiss_fft/kiss_fftr.h" class UI_Mainwindow; struct spectrumdocksettings{ int signalnr; int span; int center; int amp; int log_min_sl; int wheel; int log; int sqrt; int colorbar; double maxvalue; double maxvalue_sqrt; double maxvalue_vlog; double maxvalue_sqrt_vlog; double minvalue_vlog; double minvalue_sqrt_vlog; }; class UI_SpectrumDockWindow : public QObject { Q_OBJECT public: UI_SpectrumDockWindow(QWidget *parent); ~UI_SpectrumDockWindow(); UI_Mainwindow *mainwindow; QDialog *SpectrumDialog; QDockWidget *dock; struct signalcompblock *signalcomp; struct spectrum_markersblock *spectrum_color; void rescan(); void init(int); void clear(); void getsettings(struct spectrumdocksettings *); void setsettings(struct spectrumdocksettings); private: QWidget *parentwindow; QHBoxLayout *hlayout1, *hlayout2, *hlayout3, *hlayout4; QVBoxLayout *vlayout1, *vlayout2, *vlayout3; SignalCurve *curve1; QTimer *t1; QSlider *amplitudeSlider, *spanSlider, *centerSlider, *log_minslider; QLabel *spanLabel, *centerLabel, *amplitudeLabel; QCheckBox *sqrtButton, *vlogButton, *colorBarButton; UI_Flywheel *flywheel1; int samples, steps, spectrumdock_sqrt, spectrumdock_vlog, dashboard, flywheel_value, init_maxvalue, signal_nr, set_settings; volatile int busy; double samplefreq, freqstep, maxvalue, maxvalue_sqrt, maxvalue_vlog, maxvalue_sqrt_vlog, minvalue_vlog, minvalue_sqrt_vlog, *buf1, *buf2, *buf3, *buf4, *buf5; char *viewbuf, signallabel[512], physdimension[9]; struct spectrumdocksettings settings; private slots: void update_curve(); void sliderMoved(int); void sqrtButtonClicked(bool); void vlogButtonClicked(bool); void colorBarButtonClicked(bool); void print_to_txt(); void setdashboard(); void update_flywheel(int); }; #endif edfbrowser_157_source/PaxHeaders.7921/mit2edf.cpp0000644000000000000000000000012712646460742016730 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/mit2edf.cpp0000644000175000001440000005725112646460742017277 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2014, 2015, 2016 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 . * *************************************************************************** */ #include "mit2edf.h" #define NOTQRS 0 /* not-QRS (not a getann/putann code) */ #define NORMAL 1 /* normal beat */ #define LBBB 2 /* left bundle branch block beat */ #define RBBB 3 /* right bundle branch block beat */ #define ABERR 4 /* aberrated atrial premature beat */ #define PVC 5 /* premature ventricular contraction */ #define FUSION 6 /* fusion of ventricular and normal beat */ #define NPC 7 /* nodal (junctional) premature beat */ #define APC 8 /* atrial premature contraction */ #define SVPB 9 /* premature or ectopic supraventricular beat */ #define VESC 10 /* ventricular escape beat */ #define NESC 11 /* nodal (junctional) escape beat */ #define PACE 12 /* paced beat */ #define UNKNOWN 13 /* unclassifiable beat */ #define NOISE 14 /* signal quality change */ #define ARFCT 16 /* isolated QRS-like artifact */ #define STCH 18 /* ST change */ #define TCH 19 /* T-wave change */ #define SYSTOLE 20 /* systole */ #define DIASTOLE 21 /* diastole */ #define NOTE 22 /* comment annotation */ #define MEASURE 23 /* measurement annotation */ #define PWAVE 24 /* P-wave peak */ #define BBB 25 /* left or right bundle branch block */ #define PACESP 26 /* non-conducted pacer spike */ #define TWAVE 27 /* T-wave peak */ #define RHYTHM 28 /* rhythm change */ #define UWAVE 29 /* U-wave peak */ #define LEARN 30 /* learning */ #define FLWAV 31 /* ventricular flutter wave */ #define VFON 32 /* start of ventricular flutter/fibrillation */ #define VFOFF 33 /* end of ventricular flutter/fibrillation */ #define AESC 34 /* atrial escape beat */ #define SVESC 35 /* supraventricular escape beat */ #define LINK 36 /* link to external data (aux contains URL) */ #define NAPC 37 /* non-conducted P-wave (blocked APB) */ #define PFUS 38 /* fusion of paced and normal beat */ #define WFON 39 /* waveform onset */ #define PQ WFON /* PQ junction (beginning of QRS) */ #define WFOFF 40 /* waveform end */ #define JPT WFOFF /* J point (end of QRS) */ #define RONT 41 /* R-on-T premature ventricular contraction */ /* ... annotation codes between RONT+1 and ACMAX inclusive are user-defined */ #define ACMAX 49 /* value of largest valid annot code (must be < 50) */ char annotdescrlist[42][48]={"not-QRS","normal beat", "left bundle branch block beat", "right bundle branch block beat", "aberrated atrial premature beat", "premature ventricular contraction", "fusion of ventricular and normal beat", "nodal (junctional) premature beat", "atrial premature contraction", "premature or ectopic supraventricular beat", "ventricular escape beat", "nodal (junctional) escape beat", "paced beat", "unclassifiable beat", "signal quality change", "isolated QRS-like artifact", "ST change", "T-wave change", "systole", "diastole", "comment annotation", "measurement annotation", "P-wave peak", "left or right bundle branch block", "non-conducted pacer spike", "T-wave peak", "rhythm change", "U-wave peak", "learning", "ventricular flutter wave", "start of ventricular flutter/fibrillation", "end of ventricular flutter/fibrillation", "atrial escape beat", "supraventricular escape beat", "link to external data (aux contains URL)", "non-conducted P-wave (blocked APB)", "fusion of paced and normal beat", "waveform onset", "waveform end", "R-on-T premature ventricular contraction"}; UI_MIT2EDFwindow::UI_MIT2EDFwindow(char *recent_dir, char *save_dir) { char txt_string[2048]; recent_opendir = recent_dir; recent_savedir = save_dir; myobjectDialog = new QDialog; myobjectDialog->setMinimumSize(600, 480); myobjectDialog->setMaximumSize(600, 480); myobjectDialog->setWindowTitle("MIT to EDF+ converter"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); 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"); textEdit1 = new QTextEdit(myobjectDialog); textEdit1->setGeometry(20, 20, 560, 380); textEdit1->setFrameStyle(QFrame::Panel | QFrame::Sunken); textEdit1->setReadOnly(true); textEdit1->setLineWrapMode(QTextEdit::NoWrap); sprintf(txt_string, "MIT to EDF+ converter.\n"); textEdit1->append(txt_string); QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton())); QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close())); myobjectDialog->exec(); } void UI_MIT2EDFwindow::SelectFileButton() { FILE *header_inputfile=NULL, *data_inputfile=NULL, *annot_inputfile=NULL; int i, j, p, len, hdl, *buf; char header_filename[MAX_PATH_LENGTH], txt_string[2048], edf_filename[MAX_PATH_LENGTH], data_filename[MAX_PATH_LENGTH], annot_filename[MAX_PATH_LENGTH], filename_x[MAX_PATH_LENGTH], scratchpad[4096], *charpntr; unsigned char a_buf[128]; long long filesize; pushButton1->setEnabled(false); strcpy(header_filename, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "MIT header files (*.hea *.HEA)").toLocal8Bit().data()); if(!strcmp(header_filename, "")) { pushButton1->setEnabled(true); return; } get_directory_from_path(recent_opendir, header_filename, MAX_PATH_LENGTH); header_inputfile = fopeno(header_filename, "rb"); if(header_inputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for reading.\n", header_filename); textEdit1->append(QString::fromLocal8Bit(txt_string)); pushButton1->setEnabled(true); return; } get_filename_from_path(filename_x, header_filename, MAX_PATH_LENGTH); snprintf(txt_string, 2048, "Read file: %s", filename_x); textEdit1->append(QString::fromLocal8Bit(txt_string)); remove_extension_from_filename(filename_x); charpntr = fgets(scratchpad, 4095, header_inputfile); if(charpntr == NULL) { textEdit1->append("Can not read header file. (error 1)\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } len = strlen(charpntr); if(len < 6) { textEdit1->append("Can not read header file. (error 2)\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } for(i=0; iappend("Can not read header file. (error 3)\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } if(strcmp(charpntr, filename_x)) { textEdit1->append("Can not read header file. (error 4)\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } p = ++i; for(; iappend("Can not read header file. (error 5)\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } mit_hdr.chns = atoi(charpntr + p); if(mit_hdr.chns < 1) { textEdit1->append("Error, number of signals is less than one. (error 6)\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } if(mit_hdr.chns > MAXSIGNALS) { textEdit1->append("Error, Too many signals in header. (error 7)\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } p = ++i; for(; iappend("Can not read header file. (error 8)\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } mit_hdr.sf = atoi(charpntr + p); if(mit_hdr.sf < 1) { textEdit1->append("Error, samplefrequency is less than 1 Hz. (error 9)\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } if(mit_hdr.sf > 100000) { textEdit1->append("Error, samplefrequency is more than 100000 Hz. (error 10)\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } mit_hdr.smp_period = 1000000000LL / mit_hdr.sf; strcat(filename_x, ".dat"); for(j=0; jappend("Can not read header file. (error 11)\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } len = strlen(charpntr); if(len < 6) { textEdit1->append("Can not read header file. (error 12)\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } for(i=0; iappend("Can not read header file. (error 13)\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } if(strcmp(charpntr, filename_x)) { textEdit1->append("Error, filenames are different. (error 14)\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } p = ++i; for(; iappend("Can not read header file. (error 15)\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } mit_hdr.format[j] = atoi(charpntr + p); if((mit_hdr.format[j] != 212) && (mit_hdr.format[j] != 16)) { snprintf(txt_string, 2048, "Error, unsupported format: %i (error 16)\n", mit_hdr.format[j]); textEdit1->append(txt_string); fclose(header_inputfile); pushButton1->setEnabled(true); return; } if(j>0) { if(mit_hdr.format[j] != mit_hdr.format[0]) { textEdit1->append("Error, different formats in the same file. (error 17)\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } } p = ++i; for(; iappend(QString::fromLocal8Bit(txt_string)); pushButton1->setEnabled(true); return; } fseeko(data_inputfile, 0LL, SEEK_END); filesize = ftello(data_inputfile); if(filesize < (mit_hdr.chns * mit_hdr.sf * 45 / 10)) { textEdit1->append("Error, .dat filesize is too small.\n"); fclose(data_inputfile); pushButton1->setEnabled(true); return; } mit_hdr.sf_div = 1; mit_hdr.sf_block = mit_hdr.sf; if(!(mit_hdr.sf % 10)) { mit_hdr.sf_div = 10; mit_hdr.sf_block /= mit_hdr.sf_div; } else if(!(mit_hdr.sf % 8)) { mit_hdr.sf_div = 8; mit_hdr.sf_block /= mit_hdr.sf_div; } else if(!(mit_hdr.sf % 4)) { mit_hdr.sf_div = 4; mit_hdr.sf_block /= mit_hdr.sf_div; } else if(!(mit_hdr.sf % 2)) { mit_hdr.sf_div = 2; mit_hdr.sf_block /= mit_hdr.sf_div; } hdl = edfopen_file_writeonly(edf_filename, EDFLIB_FILETYPE_EDFPLUS, mit_hdr.chns); if(hdl<0) { snprintf(txt_string, 2048, "Can not open file %s for writing.\n", edf_filename); textEdit1->append(QString::fromLocal8Bit(txt_string)); fclose(data_inputfile); pushButton1->setEnabled(true); return; } for(i=0; iappend("Error: edf_set_samplefrequency()\n"); fclose(data_inputfile); edfclose_file(hdl); pushButton1->setEnabled(true); return; } } for(i=0; iappend("Error: edf_set_digital_minimum()\n"); fclose(data_inputfile); edfclose_file(hdl); pushButton1->setEnabled(true); return; } } for(i=0; iappend("Error: edf_set_digital_maximum()\n"); fclose(data_inputfile); edfclose_file(hdl); pushButton1->setEnabled(true); return; } } for(i=0; iappend("Error: edf_set_label()\n"); fclose(data_inputfile); edfclose_file(hdl); pushButton1->setEnabled(true); return; } } for(i=0; iappend("Error: edf_set_physical_dimension()\n"); fclose(data_inputfile); edfclose_file(hdl); pushButton1->setEnabled(true); return; } if(edf_set_physical_maximum(hdl, i, (double)((32767 - mit_hdr.adc_zero[i]) * 1000) / mit_hdr.adc_gain[i])) { textEdit1->append("Error: edf_set_physical_maximum()\n"); fclose(data_inputfile); edfclose_file(hdl); pushButton1->setEnabled(true); return; } if(edf_set_physical_minimum(hdl, i, (double)((-32768 - mit_hdr.adc_zero[i]) * 1000) / mit_hdr.adc_gain[i])) { textEdit1->append("Error: edf_set_physical_minimum()\n"); fclose(data_inputfile); edfclose_file(hdl); pushButton1->setEnabled(true); return; } } if(edf_set_datarecord_duration(hdl, 100000 / mit_hdr.sf_div)) { textEdit1->append("Error: edf_set_datarecord_duration()\n"); fclose(data_inputfile); edfclose_file(hdl); pushButton1->setEnabled(true); return; } buf = (int *)malloc(mit_hdr.sf_block * mit_hdr.chns * sizeof(int)); if(buf == NULL) { textEdit1->append("Malloc() error (buf)\n"); fclose(data_inputfile); edfclose_file(hdl); pushButton1->setEnabled(true); return; } /////////////////// Start conversion ////////////////////////////////////////// int k, blocks, tmp1, tmp2; fseeko(data_inputfile, 0LL, SEEK_SET); blocks = filesize / (mit_hdr.sf_block * mit_hdr.chns); QProgressDialog progress("Converting digitized signals ...", "Abort", 0, blocks); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); if(mit_hdr.format[0] == 212) { blocks *= 10; blocks /= 15; progress.setMaximum(blocks); for(k=0; kprocessEvents(); if(progress.wasCanceled() == true) { textEdit1->append("Conversion aborted by user.\n"); fclose(data_inputfile); edfclose_file(hdl); free(buf); pushButton1->setEnabled(true); return; } } for(i=0; iappend("A write error occurred during conversion.\n"); fclose(data_inputfile); edfclose_file(hdl); free(buf); pushButton1->setEnabled(true); return; } } } if(mit_hdr.format[0] == 16) { blocks /= 2; progress.setMaximum(blocks); for(k=0; kprocessEvents(); if(progress.wasCanceled() == true) { textEdit1->append("Conversion aborted by user.\n"); fclose(data_inputfile); edfclose_file(hdl); free(buf); pushButton1->setEnabled(true); return; } } for(i=0; iappend("A write error occurred during conversion.\n"); fclose(data_inputfile); edfclose_file(hdl); free(buf); pushButton1->setEnabled(true); return; } } } OUT: progress.reset(); qApp->processEvents(); /////////////////// End conversion ////////////////////////////////////////// fclose(data_inputfile); free(buf); int annot_code, tc=0, skip; long long bytes_read; get_filename_from_path(filename_x, annot_filename, MAX_PATH_LENGTH); annot_inputfile = fopeno(annot_filename, "rb"); if(annot_inputfile==NULL) { remove_extension_from_filename(annot_filename); strcat(annot_filename, ".ari"); annot_inputfile = fopeno(annot_filename, "rb"); } if(annot_inputfile==NULL) { remove_extension_from_filename(annot_filename); strcat(annot_filename, ".ecg"); annot_inputfile = fopeno(annot_filename, "rb"); } if(annot_inputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for reading.\n" "Annotations can not be included.", filename_x); textEdit1->append(QString::fromLocal8Bit(txt_string)); } else { snprintf(txt_string, 2048, "Read file: %s", filename_x); textEdit1->append(QString::fromLocal8Bit(txt_string)); fseeko(annot_inputfile, 0LL, SEEK_END); filesize = ftello(annot_inputfile); progress.setLabelText("Converting annotations ..."); progress.setMinimum(0); progress.setMaximum(filesize); fseeko(annot_inputfile, 0LL, SEEK_SET); for(bytes_read=0LL; bytes_read < filesize; bytes_read += 2LL) { if(!(bytes_read % 100)) { progress.setValue(bytes_read); qApp->processEvents(); if(progress.wasCanceled() == true) { textEdit1->append("Conversion aborted by user.\n"); break; } } skip = 0; if(fread(a_buf, 2, 1, annot_inputfile) != 1) { break; } #pragma GCC diagnostic ignored "-Wstrict-aliasing" if(*((unsigned short *)a_buf) == 0) // end of file { break; } annot_code = a_buf[1] >> 2; if(annot_code == 59) { if(fread(a_buf, 4, 1, annot_inputfile) != 1) { break; } tc += (*((unsigned short *)a_buf) << 16); tc += *((unsigned short *)(a_buf + 2)); } else if(annot_code == 63) { skip = *((unsigned short *)a_buf) & 0x3ff; if(skip % 2) skip++; } else if((annot_code >= 0) && (annot_code <= ACMAX)) { tc += *((unsigned short *)a_buf) & 0x3ff; #pragma GCC diagnostic warning "-Wstrict-aliasing" if(annot_code < 42) { edfwrite_annotation_latin1(hdl, ((long long)tc * mit_hdr.smp_period) / 100000LL, -1, annotdescrlist[annot_code]); } else { edfwrite_annotation_latin1(hdl, ((long long)tc * mit_hdr.smp_period) / 100000LL, -1, "user-defined"); } } if(skip) { if(fseek(annot_inputfile, skip, SEEK_CUR) < 0) { break; } bytes_read += skip; } } fclose(annot_inputfile); } progress.reset(); edfclose_file(hdl); textEdit1->append("Ready.\n"); pushButton1->setEnabled(true); } edfbrowser_157_source/PaxHeaders.7921/pagetime_dialog.cpp0000644000000000000000000000012712646460742020510 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/pagetime_dialog.cpp0000644000175000001440000000556112646460742021054 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "pagetime_dialog.h" UI_Userdefined_timepage_Dialog::UI_Userdefined_timepage_Dialog(QWidget *w_parent) { mainwindow = (UI_Mainwindow *)w_parent; set_diplaytime_dialog = new QDialog(w_parent); set_diplaytime_dialog->setMinimumSize(335, 200); set_diplaytime_dialog->setMaximumSize(335, 200); set_diplaytime_dialog->setWindowTitle("Set timescale"); set_diplaytime_dialog->setModal(true); set_diplaytime_dialog->setAttribute(Qt::WA_DeleteOnClose, true); label1 = new QLabel(set_diplaytime_dialog); label1->setGeometry(70, 25, 110, 25); label1->setText("hh:mm:ss:mmm"); timeEdit1 = new QTimeEdit(set_diplaytime_dialog); timeEdit1->setGeometry(65, 50, 110, 25); timeEdit1->setDisplayFormat("hh:mm:ss.zzz"); timeEdit1->setMinimumTime(QTime(0, 0, 0, 0)); OKButton = new QPushButton(set_diplaytime_dialog); OKButton->setGeometry(10, 165, 100, 25); OKButton->setText("OK"); CloseButton = new QPushButton(set_diplaytime_dialog); CloseButton->setGeometry(225, 165, 100, 25); CloseButton->setText("Cancel"); QObject::connect(CloseButton, SIGNAL(clicked()), set_diplaytime_dialog, SLOT(close())); QObject::connect(OKButton, SIGNAL(clicked()), this, SLOT(okbutton_pressed())); set_diplaytime_dialog->exec(); } void UI_Userdefined_timepage_Dialog::okbutton_pressed() { long long milliseconds; if(!mainwindow->files_open) { set_diplaytime_dialog->close(); return; } milliseconds = (long long)(timeEdit1->time().hour()) * 3600000LL; milliseconds += (long long)(timeEdit1->time().minute()) * 60000LL; milliseconds += (long long)(timeEdit1->time().second()) * 1000LL; milliseconds += (long long)(timeEdit1->time().msec()); if(!milliseconds) { return; } mainwindow->pagetime = milliseconds * (TIME_DIMENSION / 1000); mainwindow->setup_viewbuf(); set_diplaytime_dialog->close(); } edfbrowser_157_source/PaxHeaders.7921/mainwindow.h0000644000000000000000000000012712646460742017217 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/mainwindow.h0000644000175000001440000003400212646460742017553 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_VIEW_MAINFORM_H #define UI_VIEW_MAINFORM_H #include #include #include #include #include #include #include #include #include #include #if QT_VERSION < 0x050000 #include #include #include #ifdef Q_OS_MAC #include #endif #else #include #endif #ifdef Q_OS_WIN32 #include #include #ifndef CSIDL_COMMON_APPDATA #define CSIDL_COMMON_APPDATA 0x0023 // All Users\Application Data #endif #ifndef CSIDL_APPDATA #define CSIDL_APPDATA 0x001a // \Application Data #endif #ifndef CSIDL_PROGRAM_FILES #define CSIDL_PROGRAM_FILES 0x0026 // C:\Program Files #endif #if QT_VERSION >= 0x050000 #define QT_WA(unicode, ansi) unicode #endif #else #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "viewcurve.h" #include "check_edf_file.h" #include "show_edf_hdr.h" #include "signals_dialog.h" #include "signal_chooser.h" #include "ascii_export.h" #include "edf_compat.h" #include "filter.h" #include "filter_dialog.h" #include "jump_dialog.h" #include "about_dialog.h" #include "edf_annotations.h" #include "annotations_dock.h" #include "options_dialog.h" #include "nk2edf.h" #include "xml.h" #include "save_montage_dialog.h" #include "load_montage_dialog.h" #include "view_montage_dialog.h" #include "show_actual_montage_dialog.h" #include "print_to_edf.h" #include "pagetime_dialog.h" #include "print_to_bdf.h" #include "ascii2edf.h" #include "fino2edf.h" #include "nexfin2edf.h" #include "edfplusd_cnv.h" #include "emsa2edf.h" #include "bdf2edf.h" #include "edit_annotation_dock.h" #include "popup_save_cancelwindow.h" #include "save_annots.h" #include "utils.h" #include "spectrumanalyzer.h" #include "bi9800.h" #include "export_annotations.h" #include "edit_predefined_mtg.h" #include "spectrum_dock.h" #include "signalcurve.h" #include "edf_annot_list.h" #include "reduce_signals.h" #include "header_editor.h" #include "biosemi2bdfplus.h" #include "bdf_triggers.h" #include "import_annotations.h" #include "ravg_filter.h" #include "wav2edf.h" #include "fma_ecg2edf.h" #include "averager_curve_wnd.h" #include "ecg_filter.h" #include "ecg_export.h" #include "z_score_dialog.h" #include "z_ratio_filter.h" #include "raw2edf.h" #include "check_for_updates.h" #include "manscan2edf.h" #include "scp_ecg2edf.h" #include "unisens2edf.h" #include "date_time_stamp_parser.h" #include "spike_filter.h" #include "spike_filter_dialog.h" #include "mit2edf.h" #include "biox2edf.h" #include "third_party/fidlib/fidlib.h" class ViewCurve; class UI_Signalswindow; class UI_Annotationswindow; class UI_AnnotationEditwindow; class UI_SpectrumDockWindow; class UI_FreqSpectrumWindow; class UI_AverageCurveWindow; class UI_ZScoreWindow; class UI_Mainwindow : public QMainWindow { Q_OBJECT public: UI_Mainwindow(); ~UI_Mainwindow(); int files_open, signalcomps, totalviewbufsize, sel_viewtime, viewtime_sync, print_to_edf_active, annot_editor_active, show_annot_markers, show_baselines, annotations_edited, annotations_onset_relative, exit_in_progress, maxdftblocksize, dpix, dpiy, auto_dpi, clip_to_pane, auto_reload_mtg, read_biosemi_status_signal, read_nk_trigger_signal, live_stream_active, playback_realtime_active, live_stream_update_interval, signal_averaging_active, powerlinefreq, mousewheelsens, average_ratio, average_upsidedown, average_bw, spectrum_bw, spectrum_sqrt, spectrum_vlog, spectrumdock_sqrt, spectrumdock_vlog, use_threads, check_for_updates, amplitude_doubler, timescale_doubler, viewtime_indicator_type, mainwindow_title_type, linear_interpol; long long pagetime, maxfilesize_to_readin_annotations; char *viewbuf, viewtime_string[128], pagetime_string[64], recent_montagedir[MAX_PATH_LENGTH], recent_savedir[MAX_PATH_LENGTH], recent_opendir[MAX_PATH_LENGTH], predefined_mtg_path[MAXPREDEFINEDMONTAGES][MAX_PATH_LENGTH], recent_file_mtg_path[MAX_RECENTFILES][MAX_PATH_LENGTH], recent_colordir[MAX_PATH_LENGTH], cfg_app_version[17]; double pixelsizefactor, x_pixelsizefactor, average_period, default_amplitude; struct{ double crossoverfreq; double z_threshold; double z_hysteresis; int zscore_page_len; int zscore_error_detection; } z_score_var; struct raw2edf_var_struct raw2edf_var; struct edfhdrblock *edfheaderlist[MAXFILES]; struct signalcompblock *signalcomp[MAXSIGNALS]; struct zoomhistoryblock *zoomhistory; struct annotationblock *annotationlist[MAXFILES]; struct annotationblock *annotationlist_backup; struct spectrum_markersblock *spectrum_colorbar; struct import_annotations_var_block *import_annotations_var; struct export_annotations_var_block *export_annotations_var; struct video_player_struct *video_player; UI_Annotationswindow *annotations_dock[MAXFILES]; UI_AnnotationEditwindow *annotationEditDock; UI_FreqSpectrumWindow *spectrumdialog[MAXSPECTRUMDIALOGS]; UI_SpectrumDockWindow *spectrumdock[MAXSPECTRUMDOCKS]; UI_AverageCurveWindow *averagecurvedialog[MAXAVERAGECURVEDIALOGS]; UI_ZScoreWindow *zscoredialog[MAXZSCOREDIALOGS]; void setup_viewbuf(); void setMainwindowTitle(struct edfhdrblock *); int file_is_opened(const char *); void remove_recent_file_mtg_path(const char *); void get_rgbcolor_settings(struct xml_handle *, const char *, int, QColor *); struct signalcompblock * create_signalcomp_copy(struct signalcompblock *); ViewCurve *maincurve; QFont *myfont, *monofont; QAction *save_act, *load_predefined_mtg_act[MAXPREDEFINEDMONTAGES], *Escape_act, *video_act, *video_pause_act, *video_stop_act; QActionGroup *timelock_act_group, *sel_viewtime_act_group; private: QMenuBar *menubar; QMenu *filemenu, *signalmenu, *displaymenu, *amplitudemenu, *toolsmenu, *helpmenu, *printmenu, *filtermenu, // *math_func_menu, *timemenu, *windowmenu, *recent_filesmenu, *close_filemenu, *montagemenu, *patternmenu, *print_img_menu; char path[MAX_PATH_LENGTH], videopath[MAX_PATH_LENGTH], montagepath[MAX_PATH_LENGTH], recent_file_path[MAX_RECENTFILES][MAX_PATH_LENGTH], option_str[MAX_PATH_LENGTH]; QAction *former_page_Act, *shift_page_left_Act, *shift_page_right_Act, *playback_realtime_Act, *next_page_Act, *shift_page_up_Act, *shift_page_down_Act, *page_div2, *page_mult2, *page_10u, *page_20u, *page_50u, *page_100u, *page_200u, *page_500u, *page_1m, *page_2m, *page_5m, *page_10m, *page_20m, *page_50m, *page_100m, *page_200m, *page_500m, *page_1, *page_2, *page_5, *page_10, *page_15, *page_20, *page_30, *page_60, *page_300, *page_1200, *page_3600, *page_user_defined, *page_whole_rec, *fit_to_pane, *fit_to_dc, *amp_00001, *amp_00002, *amp_00005, *amp_0001, *amp_0002, *amp_0005, *amp_001, *amp_002, *amp_005, *amp_01, *amp_02, *amp_05, *amp_1, *amp_2, *amp_5, *amp_10, *amp_20, *amp_50, *amp_100, *amp_200, *amp_500, *amp_1000, *amp_2000, *amp_5000, *amp_10000, *amp_20000, *amp_50000, *amp_plus, *amp_minus, *zoomback_Act, *zoomforward_Act, *recent_file[MAX_RECENTFILES], *offset_timesync_act, *absolut_timesync_act, *no_timesync_act, *user_def_sync_act, *sel_viewtime_act[MAXFILES]; QActionGroup *AmplitudeGroup, *DisplayGroup, *load_predefined_mtg_group; QTimer *live_stream_timer, *video_poll_timer, *playback_realtime_timer; QTime *playback_realtime_time; QSplashScreen *splash; QPixmap *pixmap; QToolBar *slidertoolbar; QSlider *positionslider; QProcess *video_process; int cmdlineargument, cmdlineoption, oldwindowheight; Check_for_updates *update_checker; void read_color_settings(); void read_recent_file_settings(); void read_general_settings(); void write_settings(); #ifdef Q_OS_WIN32 QString specialFolder(int); #endif long long check_edf_file_datarecords(struct edfhdrblock *); inline void mpr_write(const char *); inline int mpr_read(char *, int); public slots: void remove_all_signals(); void edfplus_annotation_remove_duplicates(); void video_player_seek(int); void video_player_toggle_pause(); private slots: void open_new_file(); void show_file_info(); void close_file_action_func(QAction *); void close_all_files(); void exit_program(); void signalproperties_dialog(); void filterproperties_dialog(); void add_signals_dialog(); void show_about_dialog(); void set_display_time(QAction *); void set_page_div2(); void set_page_mult2(); void set_display_time_whole_rec(); void set_amplitude(QAction *); void set_amplitude_div2(); void set_amplitude_mult2(); void fit_signals_to_pane(); void fit_signals_dc_offset(); void former_page(); void shift_page_left(); void shift_page_right(); void playback_realtime(); void next_page(); void shift_page_up(); void shift_page_down(); void zoomback(); void forward(); void show_splashscreen(); void export_to_ascii(); void check_edf_compatibility(); void add_new_filter(); void add_spike_filter(); void remove_all_filters(); void remove_all_spike_filters(); // void add_new_math_func(); // void remove_all_math_funcs(); void jump_to_dialog(); void jump_to_start(); void jump_to_end(); void jump_to_time_millisec(long long); void show_annotations(); void show_options_dialog(); long long get_long_time(char *); void nk2edf_converter(); void set_timesync(QAction *); void set_timesync_reference(QAction *); void recent_file_action_func(QAction *); void sync_by_crosshairs(); void save_montage(); void load_montage(); void view_montage(); void show_this_montage(); void show_help(); void show_kb_shortcuts(); void print_to_edf(); void set_user_defined_display_time(); void print_to_bdf(); void print_to_img_640x480(); void print_to_img_800x600(); void print_to_img_1024x768(); void print_to_img_1280x1024(); void print_to_img_1600x1200(); void convert_ascii_to_edf(); void convert_fino_to_edf(); void convert_wave_to_edf(); void convert_fm_audio_to_edf(); void convert_nexfin_to_edf(); void edfd_converter(); void slider_moved(int); void convert_emsa_to_edf(); void bdf2edf_converter(); void set_dc_offset_to_zero(); void annotation_editor(); void save_file(); void unisens2edf_converter(); void BI98002edf_converter(); void export_annotations(); void load_predefined_mtg(QAction *); void edit_predefined_montages(); void show_spectrum_dock(); void page_3cmsec(); void reduce_signals(); void edit_header(); void biosemi2bdfplus_converter(); void import_annotations(); void open_stream(); void start_stop_video(); void stop_video_generic(); void live_stream_timer_func(); void video_poll_timer_func(); void playback_realtime_timer_func(); void stop_playback_realtime(); void organize_signals(); void Escape_fun(); void export_ecg_rr_interval_to_ascii(); void convert_binary_to_edf(); void convert_manscan_to_edf(); void convert_scpecg_to_edf(); void convert_mit_to_edf(); void convert_biox_to_edf(); void video_process_error(QProcess::ProcessError); // void search_pattern(); protected: void closeEvent(QCloseEvent *); }; #endif edfbrowser_157_source/PaxHeaders.7921/export_annotations.h0000644000000000000000000000012712646460742021001 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/export_annotations.h0000644000175000001440000000556212646460742021346 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef EXPORTANNOTATIONSFORM1_H #define EXPORTANNOTATIONSFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "edflib.h" #include "utc_date_time.h" #include "edf_annot_list.h" class UI_Mainwindow; struct export_annotations_var_block { int separator; int format; int duration; }; class UI_ExportAnnotationswindow : public QObject { Q_OBJECT public: UI_ExportAnnotationswindow(QWidget *parent); UI_Mainwindow *mainwindow; private: QDialog *ExportAnnotsDialog; QListWidget *filelist; QPushButton *CloseButton, *ExportButton; QRadioButton *CSVRadioButton, *EDFplusRadioButton, *XMLRadioButton, *mergeRadioButton, *selectRadioButton, *asciiSecondsRadioButton, *asciiISOtimeRadioButton, *asciiISOtimedateRadioButton, *asciiISOtimeFractionRadioButton, *asciiISOtimedateFractionRadioButton; QGroupBox *formatGroupBox, *fileGroupBox, *asciiSettingsGroupBox; QVBoxLayout *formatVBoxLayout, *fileVBoxLayout, *asciiSettingsVBoxLayout; QHBoxLayout *asciiSettingsHBoxLayout; QComboBox *separatorBox; QLabel *separatorLabel; QCheckBox *durationCheckBox; private slots: void ExportButtonClicked(); void outputformatRadioButtonClicked(bool); }; #endif edfbrowser_157_source/PaxHeaders.7921/show_edf_hdr.h0000644000000000000000000000013212646460742017472 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/show_edf_hdr.h0000644000175000001440000000472612646460742020044 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef SHOWEDFHDRFORM1_H #define SHOWEDFHDRFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "utc_date_time.h" #include "special_button.h" #include "utils.h" class UI_Mainwindow; class UI_EDFhdrwindow : public QObject { Q_OBJECT public: UI_EDFhdrwindow(QWidget *parent); UI_Mainwindow *mainwindow; private: QDialog *EDFhdrDialog; QListWidget *filelist; QTableWidget *signallist; QLabel *label1, *label2, *label6, *label7, *label8, *label9, *label10, *label11, *label12, *label13, *label3, *label4, *label5, *label20, *label21; SpecialButton *label1a, *label2a, *label6a, *label7a, *label8a, *label9a, *label10a, *label11a, *label12a, *label13a, *label3a, *label4a, *label5a, *label20a, *label21a; QPushButton *pushButton1; int edfplus_layout; private slots: void show_params(int); }; #endif // SHOWEDFHDRORM1_H edfbrowser_157_source/PaxHeaders.7921/spectrum_dock.cpp0000644000000000000000000000013212646460742020234 xustar0030 mtime=1452958178.249246726 30 atime=1452958178.249246726 30 ctime=1452958178.249246726 edfbrowser_157_source/spectrum_dock.cpp0000644000175000001440000007466512646460742020617 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "spectrum_dock.h" #define SPECT_LOG_MINIMUM 0.000001 #define SPECT_LOG_MINIMUM_LOG (-5) UI_SpectrumDockWindow::UI_SpectrumDockWindow(QWidget *w_parent) { char str[600]; buf1 = NULL; buf2 = NULL; buf3 = NULL; buf4 = NULL; buf5 = NULL; busy = 0; dashboard = 0; signalcomp = NULL; signal_nr = -1; set_settings = 0; mainwindow = (UI_Mainwindow *)w_parent; spectrum_color = mainwindow->spectrum_colorbar; SpectrumDialog = new QDialog; flywheel_value = 1050; init_maxvalue = 1; if(mainwindow->spectrumdock_sqrt) { dock = new QDockWidget("Amplitude Spectrum", w_parent); } else { dock = new QDockWidget("Power Spectrum", w_parent); } dock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); dock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); dock->setMinimumHeight(300); if(dashboard) { dock->setWidget(SpectrumDialog); } curve1 = new SignalCurve; curve1->setSignalColor(Qt::green); curve1->setBackgroundColor(Qt::black); curve1->setRasterColor(Qt::gray); curve1->setTraceWidth(0); curve1->setH_label("Hz"); curve1->setLowerLabel("Frequency"); if(mainwindow->spectrumdock_sqrt) { if(mainwindow->spectrumdock_vlog) { snprintf(str, 512, "log10(%s)", physdimension); curve1->setV_label(str); } else { curve1->setV_label(physdimension); } } else { if(mainwindow->spectrumdock_vlog) { snprintf(str, 512, "log((%s)^2/Hz)", physdimension); } else { snprintf(str, 512, "(%s)^2/Hz", physdimension); } curve1->setV_label(str); } curve1->create_button("to Text"); if(!dashboard) { dock->setWidget(curve1); } flywheel1 = new UI_Flywheel; flywheel1->setMinimumSize(20, 85); amplitudeSlider = new QSlider; amplitudeSlider->setOrientation(Qt::Vertical); amplitudeSlider->setMinimum(1); amplitudeSlider->setMaximum(2000); amplitudeSlider->setValue(1000); amplitudeSlider->setInvertedAppearance(true); amplitudeSlider->setMinimumSize(15, 110); log_minslider = new QSlider; log_minslider->setOrientation(Qt::Vertical); log_minslider->setMinimum(1); log_minslider->setMaximum(2000); log_minslider->setValue(1000); log_minslider->setInvertedAppearance(false); log_minslider->setMinimumSize(15, 110); amplitudeLabel = new QLabel; amplitudeLabel->setText("Amplitude"); amplitudeLabel->setMinimumSize(100, 15); amplitudeLabel->setAlignment(Qt::AlignHCenter); sqrtButton = new QCheckBox; sqrtButton->setMinimumSize(50, 20); sqrtButton->setText("Amplitude"); sqrtButton->setTristate(false); if(mainwindow->spectrumdock_sqrt) { sqrtButton->setChecked(true); } else { sqrtButton->setChecked(false); } vlogButton = new QCheckBox; vlogButton->setMinimumSize(50, 20); vlogButton->setText("Log"); vlogButton->setTristate(false); if(mainwindow->spectrumdock_vlog) { vlogButton->setChecked(true); log_minslider->setVisible(true); } else { vlogButton->setChecked(false); log_minslider->setVisible(false); } colorBarButton = new QCheckBox; colorBarButton->setMinimumSize(50, 20); colorBarButton->setText("Colorbar"); colorBarButton->setTristate(false); vlayout3 = new QVBoxLayout; vlayout3->addStretch(100); vlayout3->addWidget(flywheel1, 100); vlayout3->addStretch(100); hlayout4 = new QHBoxLayout; hlayout4->addStretch(100); hlayout4->addLayout(vlayout3, 100); hlayout4->addStretch(100); hlayout4->addWidget(amplitudeSlider, 300); hlayout4->addWidget(log_minslider, 300); vlayout2 = new QVBoxLayout; vlayout2->setSpacing(10); vlayout2->addStretch(100); vlayout2->addWidget(amplitudeLabel, 0, Qt::AlignHCenter); vlayout2->addLayout(hlayout4, 200); // vlayout2->addWidget(amplitudeSlider, 0, Qt::AlignHCenter); vlayout2->addWidget(sqrtButton); vlayout2->addWidget(vlogButton); vlayout2->addWidget(colorBarButton); spanSlider = new QSlider; spanSlider->setOrientation(Qt::Horizontal); spanSlider->setMinimum(1); spanSlider->setMaximum(1000); spanSlider->setValue(1000); spanSlider->setMinimumSize(500, 15); spanLabel = new QLabel; spanLabel->setText("Span"); spanLabel->setMinimumSize(100, 15); spanLabel->setAlignment(Qt::AlignHCenter); centerSlider = new QSlider; centerSlider->setOrientation(Qt::Horizontal); centerSlider->setMinimum(0); centerSlider->setMaximum(1000); centerSlider->setValue(0); centerSlider->setMinimumSize(500, 15); centerLabel = new QLabel; centerLabel->setText("Center"); centerLabel->setMinimumSize(100, 15); centerLabel->setAlignment(Qt::AlignHCenter); hlayout1 = new QHBoxLayout; hlayout1->setSpacing(20); hlayout1->addLayout(vlayout2); if(dashboard) { hlayout1->addWidget(curve1, 100); } hlayout2 = new QHBoxLayout; hlayout2->setSpacing(20); hlayout2->addWidget(spanLabel); hlayout2->addWidget(spanSlider); hlayout2->addStretch(100); hlayout3 = new QHBoxLayout; hlayout3->setSpacing(20); hlayout3->addWidget(centerLabel); hlayout3->addWidget(centerSlider); hlayout3->addStretch(100); vlayout1 = new QVBoxLayout; vlayout1->setSpacing(20); vlayout1->addLayout(hlayout1); vlayout1->addLayout(hlayout2); vlayout1->addLayout(hlayout3); SpectrumDialog->setLayout(vlayout1); t1 = new QTimer(this); t1->setSingleShot(true); #if QT_VERSION >= 0x050000 t1->setTimerType(Qt::PreciseTimer); #endif QObject::connect(t1, SIGNAL(timeout()), this, SLOT(update_curve())); QObject::connect(amplitudeSlider, SIGNAL(valueChanged(int)), this, SLOT(sliderMoved(int))); QObject::connect(log_minslider, SIGNAL(valueChanged(int)), this, SLOT(sliderMoved(int))); QObject::connect(spanSlider, SIGNAL(valueChanged(int)), this, SLOT(sliderMoved(int))); QObject::connect(centerSlider, SIGNAL(valueChanged(int)), this, SLOT(sliderMoved(int))); QObject::connect(sqrtButton, SIGNAL(toggled(bool)), this, SLOT(sqrtButtonClicked(bool))); QObject::connect(vlogButton, SIGNAL(toggled(bool)), this, SLOT(vlogButtonClicked(bool))); QObject::connect(colorBarButton, SIGNAL(toggled(bool)), this, SLOT(colorBarButtonClicked(bool))); QObject::connect(curve1, SIGNAL(extra_button_clicked()), this, SLOT(print_to_txt())); QObject::connect(curve1, SIGNAL(dashBoardClicked()), this, SLOT(setdashboard())); QObject::connect(flywheel1, SIGNAL(dialMoved(int)), this, SLOT(update_flywheel(int))); } void UI_SpectrumDockWindow::setsettings(struct spectrumdocksettings sett) { settings = sett; set_settings = 1; } void UI_SpectrumDockWindow::getsettings(struct spectrumdocksettings *sett) { sett->signalnr = signal_nr; sett->amp = amplitudeSlider->value(); sett->log_min_sl = log_minslider->value(); sett->wheel = flywheel_value; sett->span = spanSlider->value(); sett->center = centerSlider->value(); if(sqrtButton->isChecked() == true) { sett->sqrt = 1; } else { sett->sqrt = 0; } if(vlogButton->isChecked() == true) { sett->log = 1; } else { sett->log = 0; } if(colorBarButton->isChecked() == true) { sett->colorbar = 1; } else { sett->colorbar = 0; } sett->maxvalue = maxvalue; sett->maxvalue_sqrt = maxvalue_sqrt; sett->maxvalue_vlog = maxvalue_vlog; sett->maxvalue_sqrt_vlog = maxvalue_sqrt_vlog; sett->minvalue_vlog = minvalue_vlog; sett->minvalue_sqrt_vlog = minvalue_sqrt_vlog; } void UI_SpectrumDockWindow::update_flywheel(int new_value) { flywheel_value += new_value; if(flywheel_value < 10) { flywheel_value = 10; } if(flywheel_value > 100000) { flywheel_value = 100000; } sliderMoved(0); } void UI_SpectrumDockWindow::setdashboard() { if(dashboard) { dashboard = 0; dock->setWidget(curve1); } else { dashboard = 1; hlayout1->addWidget(curve1, 100); dock->setWidget(SpectrumDialog); } } void UI_SpectrumDockWindow::print_to_txt() { int i; char str[1024], path[MAX_PATH_LENGTH]; FILE *outputfile; path[0] = 0; if(mainwindow->recent_savedir[0]!=0) { strcpy(path, mainwindow->recent_savedir); strcat(path, "/"); } strcat(path, "spectrum.txt"); strcpy(path, QFileDialog::getSaveFileName(0, "Export to text (ASCII)", QString::fromLocal8Bit(path), "Text files (*.txt *.TXT)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(mainwindow->recent_savedir, path, MAX_PATH_LENGTH); outputfile = fopen(path, "wb"); if(outputfile == NULL) { snprintf(str, 1024, "Can not open file %s for writing.", path); QMessageBox messagewindow(QMessageBox::Critical, "Error", QString::fromLocal8Bit(str)); messagewindow.exec(); return; } sprintf(str, "FFT Power Spectral Density (Power/%fHz)\n", freqstep); remove_trailing_zeros(str); fprintf(outputfile, "%s", str); fprintf(outputfile, "Signal: %s\n", signalcomp->signallabel); sprintf(str, "FFT blocksize: %i\n", mainwindow->maxdftblocksize); sprintf(str + strlen(str), "FFT resolution: %f Hz\n", freqstep); sprintf(str + strlen(str), "Data Samples: %i\n", samples); sprintf(str + strlen(str), "Power Samples: %i\n", steps); sprintf(str + strlen(str), "Samplefrequency: %f Hz\n", (double)signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record / ((double)signalcomp->edfhdr->long_data_record_duration / TIME_DIMENSION)); remove_trailing_zeros(str); fprintf(outputfile, "%s", str); for(i=0; ienableSpectrumColors(spectrum_color); } else { curve1->disableSpectrumColors(); } } void UI_SpectrumDockWindow::sqrtButtonClicked(bool value) { char str[600]; if(value == false) { mainwindow->spectrumdock_sqrt = 0; sprintf(str, "Power Spectrum %s", signallabel); dock->setWindowTitle(str); if(mainwindow->spectrumdock_vlog) { sprintf(str, "log10((%s)^2/Hz)", physdimension); } else { sprintf(str, "(%s)^2/Hz", physdimension); } curve1->setV_label(str); } else { mainwindow->spectrumdock_sqrt = 1; sprintf(str, "Amplitude Spectrum %s", signallabel); dock->setWindowTitle(str); if(mainwindow->spectrumdock_vlog) { sprintf(str, "log(%s)", physdimension); } else { sprintf(str, "%s", physdimension); } curve1->setV_label(str); } sliderMoved(0); } void UI_SpectrumDockWindow::vlogButtonClicked(bool value) { char str[600]; if(value == false) { mainwindow->spectrumdock_vlog = 0; if(mainwindow->spectrumdock_sqrt) { sprintf(str, "%s", physdimension); } else { sprintf(str, "(%s)^2/Hz", physdimension); } curve1->setV_label(str); log_minslider->setVisible(false); } else { mainwindow->spectrumdock_vlog = 1; if(mainwindow->spectrumdock_sqrt) { sprintf(str, "log10(%s)", physdimension); } else { sprintf(str, "log10((%s)^2/Hz)", physdimension); } curve1->setV_label(str); log_minslider->setVisible(true); } sliderMoved(0); } void UI_SpectrumDockWindow::sliderMoved(int) { long long startstep, stopstep, spanstep; double max_freq, start_freq; char str[1024]; spanstep = (long long)spanSlider->value() * (long long)steps / 1000LL; startstep = (long long)centerSlider->value() * ((long long)steps - spanstep) / 1000LL; stopstep = startstep + spanstep; if(sqrtButton->checkState() == Qt::Checked) { mainwindow->spectrumdock_sqrt = 1; if(vlogButton->checkState() == Qt::Checked) { mainwindow->spectrumdock_vlog = 1; curve1->drawCurve(buf5 + startstep, stopstep - startstep, (maxvalue_sqrt_vlog * 1.05 * (((double)flywheel_value / 1000.0) * (double)amplitudeSlider->value())) / 1000.0, minvalue_sqrt_vlog * (double)log_minslider->value() / 1000.0); } else { mainwindow->spectrumdock_vlog = 0; curve1->drawCurve(buf3 + startstep, stopstep - startstep, (maxvalue_sqrt * 1.05 * (((double)flywheel_value / 1000.0) * (double)amplitudeSlider->value())) / 1000.0, 0.0); } } else { mainwindow->spectrumdock_sqrt = 0; if(vlogButton->checkState() == Qt::Checked) { mainwindow->spectrumdock_vlog = 1; curve1->drawCurve(buf4 + startstep, stopstep - startstep, (maxvalue_vlog * 1.05 * (((double)flywheel_value / 1000.0) * (double)amplitudeSlider->value())) / 1000.0, minvalue_vlog * (double)log_minslider->value() / 1000.0); } else { mainwindow->spectrumdock_vlog = 0; curve1->drawCurve(buf2 + startstep, stopstep - startstep, (maxvalue * 1.05 * (((double)flywheel_value / 1000.0) * (double)amplitudeSlider->value())) / 1000.0, 0.0); } } max_freq = ((double)samplefreq / 2.0) * stopstep / steps; start_freq = ((double)samplefreq / 2.0) * startstep / steps; curve1->setH_RulerValues(start_freq, max_freq); strcpy(str, "Center "); convert_to_metric_suffix(str + strlen(str), start_freq + ((max_freq - start_freq) / 2.0), 3); remove_trailing_zeros(str); strcat(str, "Hz"); centerLabel->setText(str); strcpy(str, "Span "); convert_to_metric_suffix(str + strlen(str), max_freq - start_freq, 3); remove_trailing_zeros(str); strcat(str, "Hz"); spanLabel->setText(str); } void UI_SpectrumDockWindow::init(int signal_num) { char str[600]; init_maxvalue = 1; if(signal_num < 0) { signalcomp = NULL; viewbuf = NULL; } else { signal_nr = signal_num; signalcomp = mainwindow->signalcomp[signal_num]; viewbuf = mainwindow->viewbuf; strcpy(signallabel, signalcomp->signallabel); strcpy(physdimension, signalcomp->physdimension); if(mainwindow->spectrumdock_sqrt) { sqrtButton->setChecked(true); if(mainwindow->spectrumdock_vlog) { vlogButton->setChecked(true); snprintf(str, 512, "log10(%s)", physdimension); curve1->setV_label(str); } else { vlogButton->setChecked(false); curve1->setV_label(physdimension); } } else { sqrtButton->setChecked(false); if(mainwindow->spectrumdock_vlog) { vlogButton->setChecked(true); snprintf(str, 512, "log((%s)^2/Hz)", physdimension); } else { vlogButton->setChecked(false); snprintf(str, 512, "(%s)^2/Hz", physdimension); } curve1->setV_label(str); } amplitudeSlider->setValue(1000); log_minslider->setValue(1000); dock->show(); t1->start(1); } } void UI_SpectrumDockWindow::rescan() { t1->start(1); } void UI_SpectrumDockWindow::clear() { int i; init_maxvalue = 1; signalcomp = NULL; viewbuf = NULL; if(buf1 != NULL) { free(buf1); buf1 = NULL; } if(buf2 != NULL) { free(buf2); buf2 = NULL; } if(buf3 != NULL) { free(buf3); buf3 = NULL; } if(buf4 != NULL) { free(buf4); buf4 = NULL; } if(buf5 != NULL) { free(buf5); buf5 = NULL; } if(spectrum_color != NULL) { for(i=0; i < spectrum_color->items; i++) { spectrum_color->value[i] = 0.0; } } curve1->clear(); signal_nr = -1; } void UI_SpectrumDockWindow::update_curve() { int i, j, k, n, dftblocksize, dftblocks, samplesleft, fft_outputbufsize; long long s, s2; char str[512]; double dig_value=0.0, f_tmp=0.0; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; if(signalcomp == NULL) { return; } if(busy) { return; } viewbuf = mainwindow->viewbuf; if(viewbuf == NULL) { return; } busy = 1; curve1->setUpdatesEnabled(false); samples = signalcomp->samples_on_screen; if(signalcomp->samples_on_screen > signalcomp->sample_stop) { samples = signalcomp->sample_stop; } samples -= signalcomp->sample_start; if((samples < 10) || (viewbuf == NULL)) { curve1->setUpdatesEnabled(true); busy = 0; if(spectrum_color != NULL) { for(i=0; i < spectrum_color->items; i++) { spectrum_color->value[i] = 0.0; } } curve1->clear(); return; } if(buf1 != NULL) { free(buf1); } buf1 = (double *)malloc(sizeof(double) * signalcomp->samples_on_screen); if(buf1 == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.\n" "Decrease the timescale and try again."); messagewindow.exec(); return; } samples = 0; for(s=signalcomp->sample_start; ssamples_on_screen; s++) { if(s>signalcomp->sample_stop) break; dig_value = 0.0; s2 = s + signalcomp->sample_timeoffset - signalcomp->sample_start; for(j=0; jnum_of_signals; j++) { if(signalcomp->edfhdr->bdf) { var.two[0] = *((unsigned short *)( viewbuf + signalcomp->viewbufoffset + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)) + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset + ((s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record) * 3))); var.four[2] = *((unsigned char *)( viewbuf + signalcomp->viewbufoffset + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)) + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset + ((s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record) * 3) + 2)); if(var.four[2]&0x80) { var.four[3] = 0xff; } else { var.four[3] = 0x00; } f_tmp = var.one_signed; } if(signalcomp->edfhdr->edf) { f_tmp = *(((short *)( viewbuf + signalcomp->viewbufoffset + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)) + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset)) + (s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)); } f_tmp += signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].offset; f_tmp *= signalcomp->factor[j]; dig_value += f_tmp; } if(signalcomp->spike_filter) { if(s==signalcomp->sample_start) { spike_filter_restore_buf(signalcomp->spike_filter); } dig_value = run_spike_filter(dig_value, signalcomp->spike_filter); } for(k=0; kfilter_cnt; k++) { dig_value = first_order_filter(dig_value, signalcomp->filter[k]); } for(k=0; kravg_filter_cnt; k++) { if(s==signalcomp->sample_start) { ravg_filter_restore_buf(signalcomp->ravg_filter[k]); } dig_value = run_ravg_filter(dig_value, signalcomp->ravg_filter[k]); } for(k=0; kfidfilter_cnt; k++) { if(s==signalcomp->sample_start) { memcpy(signalcomp->fidbuf[k], signalcomp->fidbuf2[k], fid_run_bufsize(signalcomp->fid_run[k])); } dig_value = signalcomp->fidfuncp[k](signalcomp->fidbuf[k], dig_value); } if(signalcomp->ecg_filter != NULL) { if(s==signalcomp->sample_start) { ecg_filter_restore_buf(signalcomp->ecg_filter); } dig_value = run_ecg_filter(dig_value, signalcomp->ecg_filter); } if(s>=signalcomp->sample_start) { buf1[samples++] = dig_value * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue; } } samplefreq = (double)signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record / ((double)signalcomp->edfhdr->long_data_record_duration / TIME_DIMENSION); dftblocksize = mainwindow->maxdftblocksize; if(dftblocksize & 1) { dftblocksize--; } dftblocks = 1; if(dftblocksize < samples) { dftblocks = samples / dftblocksize; } else { dftblocksize = samples; } if(dftblocksize & 1) { dftblocksize--; } samplesleft = samples % dftblocksize; if(samplesleft & 1) { samplesleft--; } freqstep = samplefreq / (double)dftblocksize; fft_outputbufsize = dftblocksize / 2; steps = fft_outputbufsize; if(buf2 != NULL) { free(buf2); } buf2 = (double *)calloc(1, sizeof(double) * fft_outputbufsize); if(buf2 == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); messagewindow.exec(); free(buf1); buf1 = NULL; return; } if(buf3 != NULL) { free(buf3); } buf3 = (double *)malloc(sizeof(double) * fft_outputbufsize); if(buf3 == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); messagewindow.exec(); free(buf1); free(buf2); buf1 = NULL; buf2 = NULL; return; } if(buf4 != NULL) { free(buf4); } buf4 = (double *)malloc(sizeof(double) * fft_outputbufsize); if(buf4 == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); messagewindow.exec(); free(buf1); free(buf2); free(buf3); buf1 = NULL; buf2 = NULL; buf3 = NULL; return; } if(buf5 != NULL) { free(buf5); } buf5 = (double *)malloc(sizeof(double) * fft_outputbufsize); if(buf5 == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); messagewindow.exec(); free(buf1); free(buf2); free(buf3); free(buf4); buf1 = NULL; buf2 = NULL; buf3 = NULL; buf4 = NULL; return; } if(init_maxvalue && !set_settings) { maxvalue = 0.000001; maxvalue_sqrt = 0.000001; maxvalue_vlog = 0.000001; maxvalue_sqrt_vlog = 0.000001; minvalue_vlog = 0.0; minvalue_sqrt_vlog = 0.0; } if(set_settings) { maxvalue = settings.maxvalue; maxvalue_sqrt = settings.maxvalue_sqrt; maxvalue_vlog = settings.maxvalue_vlog; maxvalue_sqrt_vlog = settings.maxvalue_sqrt_vlog; minvalue_vlog = settings.minvalue_vlog; minvalue_sqrt_vlog = settings.minvalue_sqrt_vlog; } kiss_fftr_cfg cfg; kiss_fft_cpx *kiss_fftbuf; kiss_fftbuf = (kiss_fft_cpx *)malloc((fft_outputbufsize + 1) * sizeof(kiss_fft_cpx)); if(kiss_fftbuf == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); messagewindow.exec(); free(buf1); free(buf2); free(buf3); free(buf4); free(buf5); buf1 = NULL; buf2 = NULL; buf3 = NULL; buf4 = NULL; buf5 = NULL; return; } cfg = kiss_fftr_alloc(dftblocksize, 0, NULL, NULL); for(j=0; jecg_filter == NULL) { buf2[0] /= 2.0; // DC! } else { buf2[0] = 0.0; // Remove DC because heart rate is always a positive value } free(cfg); free(kiss_fftbuf); for(i=0; i maxvalue) { maxvalue = buf2[i]; } if(buf3[i] > maxvalue_sqrt) { maxvalue_sqrt = buf3[i]; } if(buf4[i] > maxvalue_vlog) { maxvalue_vlog = buf4[i]; } if(buf5[i] > maxvalue_sqrt_vlog) { maxvalue_sqrt_vlog = buf5[i]; } if((buf4[i] < minvalue_vlog) && (buf4[i] >= SPECT_LOG_MINIMUM_LOG)) { minvalue_vlog = buf4[i]; } if((buf5[i] < minvalue_sqrt_vlog) && (buf5[i] >= SPECT_LOG_MINIMUM_LOG)) { minvalue_sqrt_vlog = buf5[i]; } } } } if(init_maxvalue) { if(minvalue_vlog < SPECT_LOG_MINIMUM_LOG) minvalue_vlog = SPECT_LOG_MINIMUM_LOG; if(minvalue_sqrt_vlog < SPECT_LOG_MINIMUM_LOG) minvalue_sqrt_vlog = SPECT_LOG_MINIMUM_LOG; } if(samplesleft) { dftblocks++; } if(buf1 != NULL) { free(buf1); buf1 = NULL; } // sprintf(str, "FFT resolution: %f Hz %i blocks of %i samples", freqstep, dftblocks, dftblocksize); strcpy(str, "FFT resolution: "); convert_to_metric_suffix(str + strlen(str), freqstep, 3); remove_trailing_zeros(str); sprintf(str + strlen(str), "Hz %i blocks of %i samples", dftblocks, dftblocksize); curve1->setUpperLabel1(str); curve1->setUpperLabel2(signallabel); if(spectrum_color != NULL) { if(spectrum_color->items > 0) { spectrum_color->value[0] = 0.0; n = 0; for(j=0; jfreq[0]) { if(spectrum_color->method == 0) // sum { spectrum_color->value[0] += buf2[j]; } if(spectrum_color->method == 1) // peak { if(spectrum_color->value[0] < buf2[j]) { spectrum_color->value[0] = buf2[j]; } } if(spectrum_color->method == 2) // average { spectrum_color->value[0] += buf2[j]; n++; } } } if(spectrum_color->method == 2) // average { if(n) { spectrum_color->value[0] /= n; } } } for(i=1; i < spectrum_color->items; i++) { spectrum_color->value[i] = 0.0; n = 0; for(j=0; j spectrum_color->freq[i-1]) && (((freqstep * j) + (freqstep * 0.5)) < spectrum_color->freq[i])) { if(spectrum_color->method == 0) // sum { spectrum_color->value[i] += buf2[j]; } if(spectrum_color->method == 1) // peak { if(spectrum_color->value[i] < buf2[j]) { spectrum_color->value[i] = buf2[j]; } } if(spectrum_color->method == 2) // average { spectrum_color->value[i] += buf2[j]; n++; } } } if(spectrum_color->method == 2) // average { if(n) { spectrum_color->value[i] /= n; } } } } if(mainwindow->spectrumdock_sqrt) { snprintf(str, 512, "Amplitude Spectrum %s", signallabel); } else { snprintf(str, 512, "Power Spectrum %s", signallabel); } dock->setWindowTitle(str); if(set_settings) { set_settings = 0; if((settings.amp >= 1) && (settings.amp <= 2000)) { amplitudeSlider->setValue(settings.amp); } if((settings.log_min_sl >= 1) && (settings.log_min_sl <= 2000)) { log_minslider->setValue(settings.log_min_sl); } if((settings.span >= 10) && (settings.span <= 1000)) { spanSlider->setValue(settings.span); } if((settings.center >= 0) && (settings.center <= 1000)) { centerSlider->setValue(settings.center); } if(settings.sqrt > 0) { sqrtButton->setChecked(true); } else { sqrtButton->setChecked(false); } if(settings.log > 0) { vlogButton->setChecked(true); log_minslider->setVisible(true); } else { vlogButton->setChecked(false); log_minslider->setVisible(false); } if(settings.colorbar > 0) { colorBarButton->setChecked(true); } else { colorBarButton->setChecked(false); } if((flywheel_value >= 10) && (flywheel_value <= 100000)) { flywheel_value = settings.wheel; } } sliderMoved(0); curve1->setUpdatesEnabled(true); busy = 0; init_maxvalue = 0; } UI_SpectrumDockWindow::~UI_SpectrumDockWindow() { if(buf2 != NULL) { free(buf2); } if(buf3 != NULL) { free(buf3); } if(buf4 != NULL) { free(buf4); } if(buf5 != NULL) { free(buf5); } delete SpectrumDialog; } edfbrowser_157_source/PaxHeaders.7921/statistics_dialog.h0000644000000000000000000000013212646460742020550 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/statistics_dialog.h0000644000175000001440000000401312646460742021107 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef STATISTICS_DIALOGFORM1_H #define STATISTICS_DIALOGFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "ecg_filter.h" #include "signalcurve.h" class UI_StatisticWindow : public QObject { Q_OBJECT public: UI_StatisticWindow(struct signalcompblock *, long long); private: QDialog *StatDialog; QHBoxLayout *hlayout1, *hlayout1_1_1; QVBoxLayout *vlayout1_1, *vlayout2_1; QSlider *startSlider, *stopSlider; QLabel *Label1, *startLabel, *stopLabel; QPushButton *pushButton1; SignalCurve *curve1; int beat_cnt, bpm_distribution[300], max_val, start_ruler, end_ruler; private slots: void startSliderMoved(int); void stopSliderMoved(int); }; #endif // STATISTICS_DIALOGFORM1_H edfbrowser_157_source/PaxHeaders.7921/README.txt0000644000000000000000000000013212646460742016364 xustar0030 mtime=1452958178.264246676 30 atime=1452958178.264246676 30 ctime=1452958178.264246676 edfbrowser_157_source/README.txt0000644000175000001440000000202512646460742016724 0ustar00guvusers00000000000000 Requirements ============ Qt http://www.qt.io/ Minimum version 4.7.1 or later, preferable 4.8.7 Do not use Qt 5.x.x to compile EDFbrowser, Qt5 is not yet ready for production use. It contains still bugs that affects EDFbrowser. The GCC compiler on Linux or Mingw-w64 on windows. http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.8.2/threads-posix/dwarf/i686-4.8.2-release-posix-dwarf-rt_v3-rev3.7z/download Please, do not use any microsoft tools or compilers. Don't waste your time, it's not going to work! Introduction ============ EDFbrowser is a Qt4 application and uses qmake as part of the build process. qmake is part of your Qt4 installation. Build and run without "installing" ================================== You need to have Qt and GCC (Mingw-w64 on Windows) installed. Extract the sourcefile and enter the following commands: qmake make Now you can run the program. Installing ========== sudo make install edfbrowser_157_source/PaxHeaders.7921/colordialog.h0000644000000000000000000000013212646460742017335 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/colordialog.h0000644000175000001440000000531112646460742017676 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef COLORMENUFORM1_H #define COLORMENUFORM1_H #include #include #include #include #include #include #include "global.h" #include "special_button.h" class UI_Mainwindow; class UI_ColorMenuDialog : public QObject { Q_OBJECT public: UI_ColorMenuDialog(int *oldColor, QWidget *parent = NULL); private: int *color; QDialog *colormenu_dialog; QPushButton *CloseButton; SpecialButton *ColorButton1, *ColorButton2, *ColorButton3, *ColorButton4, *ColorButton5, *ColorButton6, *ColorButton7, *ColorButton8, *ColorButton9, *ColorButton10, *ColorButton11, *ColorButton12, *ColorButton13, *ColorButton14, *ColorButton15, *ColorButton16, *parentbutton; private slots: void ColorButton1_pressed(SpecialButton *); void ColorButton2_pressed(SpecialButton *); void ColorButton3_pressed(SpecialButton *); void ColorButton4_pressed(SpecialButton *); void ColorButton5_pressed(SpecialButton *); void ColorButton6_pressed(SpecialButton *); void ColorButton7_pressed(SpecialButton *); void ColorButton8_pressed(SpecialButton *); void ColorButton9_pressed(SpecialButton *); void ColorButton10_pressed(SpecialButton *); void ColorButton11_pressed(SpecialButton *); void ColorButton12_pressed(SpecialButton *); void ColorButton13_pressed(SpecialButton *); void ColorButton14_pressed(SpecialButton *); void ColorButton15_pressed(SpecialButton *); void ColorButton16_pressed(SpecialButton *); }; #endif // COLORMENUFORM1_H edfbrowser_157_source/PaxHeaders.7921/raw2edf.h0000644000000000000000000000013212646460742016371 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/raw2edf.h0000644000175000001440000000654212646460742016741 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_RAW2EDFFORM_H #define UI_RAW2EDFFORM_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "xml.h" #include "utils.h" #include "edflib.h" #include "global.h" struct raw2edf_var_struct{ int sf; int chns; int phys_max; int straightbinary; int endianness; int samplesize; int offset; int skipblocksize; int skipbytes; char phys_dim[16]; }; class UI_RAW2EDFapp : public QObject { Q_OBJECT public: UI_RAW2EDFapp(struct raw2edf_var_struct *, char *recent_dir=NULL, char *save_dir=NULL); private: QDialog *raw2edfDialog; QLabel *SignalsLabel, *OffsetLabel, *SamplefreqLabel, *PatientnameLabel, *RecordingLabel, *DatetimeLabel, *SampleSizeLabel, *skipblocksizeLabel, *skipbytesLabel, *PhysicalMaximumLabel, *PhysicalDimensionLabel, *EncodingLabel, *variableTypeLabel, *EndiannessLabel; QLineEdit *PatientnameLineEdit, *RecordingLineEdit, *PhysicalDimensionLineEdit; QSpinBox *SignalsSpinbox, *OffsetSpinbox, *SamplefreqSpinbox, *SampleSizeSpinbox, *skipblocksizeSpinbox, *skipbytesSpinbox, *PhysicalMaximumSpinbox; QComboBox *EncodingCombobox, *EndiannessCombobox; QDateTimeEdit *StartDatetimeedit; QPushButton *GoButton, *CloseButton, *SaveButton, *LoadButton; char *recent_opendir, *recent_savedir; int edfsignals, offset, samplefrequency, edf_format; struct raw2edf_var_struct *raw2edf_var; private slots: void gobuttonpressed(); void savebuttonpressed(); void loadbuttonpressed(); void PhysicalDimensionLineEdited(QString); void sampleTypeChanged(int); }; #endif edfbrowser_157_source/PaxHeaders.7921/mit2edf.h0000644000000000000000000000012712646460742016375 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/mit2edf.h0000644000175000001440000000426612646460742016742 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_MIT2EDFFORM_H #define UI_MIT2EDFFORM_H #include #include #include #include #include #include #include #include #include #if QT_VERSION < 0x050000 #include #include #endif #include #include #include #include #include #include #include "global.h" #include "utils.h" #include "edflib.h" #include "utc_date_time.h" class UI_MIT2EDFwindow : public QObject { Q_OBJECT public: UI_MIT2EDFwindow(char *recent_dir=NULL, char *save_dir=NULL); private: QPushButton *pushButton1, *pushButton2; QTextEdit *textEdit1; QDialog *myobjectDialog; char *recent_opendir, *recent_savedir; struct { int chns; int sf; int sf_div; int sf_block; long long smp_period; int format[MAXSIGNALS]; double adc_gain[MAXSIGNALS]; int adc_resolution[MAXSIGNALS]; int adc_zero[MAXSIGNALS]; int init_val[MAXSIGNALS]; char label[MAXSIGNALS][17]; } mit_hdr; private slots: void SelectFileButton(); }; #endif edfbrowser_157_source/PaxHeaders.7921/special_button.h0000644000000000000000000000013212646460742020052 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/special_button.h0000644000175000001440000000343012646460742020413 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef SPECIALBUTTON_H #define SPECIALBUTTON_H #include #include #include #include #include class SpecialButton: public QWidget { Q_OBJECT public: SpecialButton(QWidget *parent=0); QSize sizeHint() const {return minimumSizeHint(); } QSize minimumSizeHint() const {return QSize(30,10); } public slots: void setColor(QColor); QColor color(); void setGlobalColor(int); int globalColor(); void setText(const char *); protected: void paintEvent(QPaintEvent *); QColor ButtonColor; void mouseReleaseEvent(QMouseEvent *); private: char buttonText[2048]; int global_Color; signals: void clicked(SpecialButton *); }; #endif edfbrowser_157_source/PaxHeaders.7921/view_montage_dialog.h0000644000000000000000000000013212646460742021042 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/view_montage_dialog.h0000644000175000001440000000402112646460742021400 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef VIEWMONTAGEFORM1_H #define VIEWMONTAGEFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "xml.h" #include "utils.h" class UI_Mainwindow; class UI_ViewMontagewindow : public QObject { Q_OBJECT public: UI_ViewMontagewindow(QWidget *parent); UI_Mainwindow *mainwindow; private: QDialog *ViewMontageDialog; QPushButton *CloseButton, *SelectButton; QBoxLayout *box; QHBoxLayout *hbox; QTreeView *tree; QStandardItemModel *t_model; char mtg_path[MAX_PATH_LENGTH], mtg_dir[MAX_PATH_LENGTH]; private slots: void SelectButtonClicked(); }; #endif // VIEWMONTAGEFORM1_H edfbrowser_157_source/PaxHeaders.7921/fma_ecg2edf.h0000644000000000000000000000012712646460742017165 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/fma_ecg2edf.h0000644000175000001440000000500512646460742017522 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2015, 2016 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 . * *************************************************************************** */ #ifndef UI_FMA2EDFFORM_H #define UI_FMA2EDFFORM_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "utils.h" #include "edflib.h" #include "ravg_filter.h" class UI_FMaudio2EDFwindow : public QObject { Q_OBJECT public: UI_FMaudio2EDFwindow(char *recent_dir=NULL, char *save_dir=NULL); private: QDialog *myobjectDialog; QPushButton *pushButton1, *pushButton2; QLabel *PatientnameLabel, *RecordingLabel, *DatetimeLabel; QLineEdit *PatientnameLineEdit, *RecordingLineEdit; QDateTimeEdit *StartDatetimeedit; char *recent_opendir, *recent_savedir; struct ravg_filter_settings *hpf44, *lpf9a, *lpf9b, *lpf9c, *lpf9d, *lpf9e, *lpf200a, *lpf200b, *lpf200c, *lpf200d, *lpf200e; void enable_widgets(bool); bool allocateFilters(int, int, int); void deleteFilters(void); private slots: void SelectFileButton(); }; #endif edfbrowser_157_source/PaxHeaders.7921/adjustfiltersettings.cpp0000644000000000000000000000013212646460742021653 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/adjustfiltersettings.cpp0000644000175000001440000004673012646460742022226 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ /* type: 0 : highpass 1 : lowpass 2 : notch 3 : bandpass 4 : bandstop model: 0 : Butterworth 1 : Chebyshev 2 : Bessel 3 : moving average 0 : resonator */ #include "adjustfiltersettings.h" AdjustFilterSettings::AdjustFilterSettings(struct signalcompblock *signal_comp, QWidget *w_parent) { int i; char txtbuf[2048]; signalcomp = signal_comp; maincurve = (ViewCurve *)w_parent; mainwindow = maincurve->mainwindow; filtersettings_dialog = new QDialog(w_parent); filtersettings_dialog->setMinimumSize(460, 255); filtersettings_dialog->setMaximumSize(460, 255); strcpy(txtbuf, "Filter settings "); if(signalcomp->alias[0] != 0) { strcat(txtbuf, signalcomp->alias); } else { strcat(txtbuf, signalcomp->signallabel); } filtersettings_dialog->setWindowTitle(txtbuf); filtersettings_dialog->setModal(true); filtersettings_dialog->setAttribute(Qt::WA_DeleteOnClose, true); for(i=0; i<5; i++) { label[i] = new QLabel(filtersettings_dialog); label[i]->setGeometry(10, 10 + (i * 35), 100, 25); } label[0]->setText("Filter"); label[1]->setText("Order"); label[2]->setText("Frequency"); label[3]->setText("Frequency 2"); label[3]->setVisible(false); label[4]->setText("Stepsize"); filterbox = new QComboBox(filtersettings_dialog); filterbox->setGeometry(120, 10, 330, 25); orderbox = new QSpinBox(filtersettings_dialog); orderbox->setGeometry(120, 45, 100, 25); orderbox->setSuffix("th order"); orderbox->setMinimum(1); orderbox->setMaximum(8); orderbox->setValue(1); orderbox->setSingleStep(1); freq1box = new QDoubleSpinBox(filtersettings_dialog); freq1box->setGeometry(120, 80, 180, 25); freq1box->setDecimals(6); freq1box->setSuffix(" Hz"); freq1box->setMinimum(0.0001); freq1box->setMaximum(100000.0); freq1box->setValue(1.0); freq1box->setSingleStep(1.0); freq2box = new QDoubleSpinBox(filtersettings_dialog); freq2box->setGeometry(120, 115, 180, 25); freq2box->setDecimals(6); freq2box->setSuffix(" Hz"); freq2box->setMinimum(0.0001); freq2box->setMaximum(100000.0); freq2box->setValue(2.0); freq2box->setVisible(false); freq2box->setSingleStep(1.0); stepsizebox = new QComboBox(filtersettings_dialog); stepsizebox->setGeometry(120, 150, 80, 25); stepsizebox->addItem("0.01Hz"); stepsizebox->addItem("0.1Hz"); stepsizebox->addItem("1Hz"); stepsizebox->addItem("10Hz"); stepsizebox->addItem("100Hz"); stepsizebox->setCurrentIndex(2); RemoveButton = new QPushButton(filtersettings_dialog); RemoveButton->setGeometry(120, 220, 80, 25); RemoveButton->setText("Remove"); CloseButton = new QPushButton(filtersettings_dialog); CloseButton->setGeometry(360, 220, 80, 25); CloseButton->setText("Close"); filter_cnt = 0; loadFilterSettings(); QObject::connect(freq1box, SIGNAL(valueChanged(double)), this, SLOT(freqbox1valuechanged(double))); QObject::connect(freq2box, SIGNAL(valueChanged(double)), this, SLOT(freqbox2valuechanged(double))); QObject::connect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); QObject::connect(filterbox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterboxchanged(int))); QObject::connect(stepsizebox, SIGNAL(currentIndexChanged(int)), this, SLOT(stepsizeboxchanged(int))); QObject::connect(RemoveButton, SIGNAL(clicked()), this, SLOT(removeButtonClicked())); QObject::connect(CloseButton, SIGNAL(clicked()), filtersettings_dialog, SLOT(close())); filtersettings_dialog->exec(); } void AdjustFilterSettings::loadFilterSettings(void) { int i; char txtbuf[2048]; txtbuf[0] = 0; filterbox->clear(); for(i=0; ifidfilter_cnt; i++) { type = signalcomp->fidfilter_type[i]; model = signalcomp->fidfilter_model[i]; order = signalcomp->fidfilter_order[i]; ripple = signalcomp->fidfilter_ripple[i]; frequency1 = signalcomp->fidfilter_freq[i]; if(type == 0) { if(model == 0) { sprintf(txtbuf, "HighPass Butterworth"); } if(model == 1) { sprintf(txtbuf, "HighPass Chebyshev %.1fdB ripple", ripple); } if(model == 2) { sprintf(txtbuf, "HighPass Bessel"); } } if(type == 1) { if(model == 0) { sprintf(txtbuf, "LowPass Butterworth"); } if(model == 1) { sprintf(txtbuf, "LowPass Chebyshev %.1fdB ripple", ripple); } if(model == 2) { sprintf(txtbuf, "LowPass Bessel"); } } if(type == 2) { sprintf(txtbuf, "Notch (resonator)"); } if(type == 3) { if(model == 0) { sprintf(txtbuf, "BandPass Butterworth"); } if(model == 1) { sprintf(txtbuf, "BandPass Chebyshev %.1fdB ripple", ripple); } if(model == 2) { sprintf(txtbuf, "BandPass Bessel"); } } if(type == 4) { if(model == 0) { sprintf(txtbuf, "BandStop Butterworth"); } if(model == 1) { sprintf(txtbuf, "BandStop Chebyshev %.1fdB ripple", ripple); } if(model == 2) { sprintf(txtbuf, "BandStop Bessel"); } } sprintf(txtbuf + strlen(txtbuf), " %f", frequency1); remove_trailing_zeros(txtbuf); strcat(txtbuf, " Hz"); filterbox->addItem(txtbuf); brand[filter_cnt++] = 0; } for(i=0; iravg_filter_cnt; i++) { type = signalcomp->ravg_filter_type[i]; size = signalcomp->ravg_filter_size[i]; if(type == 0) { sprintf(txtbuf, "Highpass Moving Average %i samples", size); } if(type == 1) { sprintf(txtbuf, "Lowpass Moving Average %i samples", size); } filterbox->addItem(txtbuf); brand[filter_cnt++] = 1; } filterboxchanged(filterbox->currentIndex()); } void AdjustFilterSettings::orderboxvaluechanged(int) { int j; for(j=0; j<10; j++) qApp->processEvents(); update_filter(); } void AdjustFilterSettings::freqbox1valuechanged(double value) { int j; if((type == 3) || (type == 4)) { if(freq2box->value() < (value * 1.12)) { QObject::disconnect(freq2box, SIGNAL(valueChanged(double)), this, SLOT(freqbox2valuechanged(double))); freq2box->setValue(value * 1.12); QObject::connect(freq2box, SIGNAL(valueChanged(double)), this, SLOT(freqbox2valuechanged(double))); } } for(j=0; j<10; j++) qApp->processEvents(); update_filter(); } void AdjustFilterSettings::freqbox2valuechanged(double value) { int j; if(freq1box->value() > (value * 0.9)) { QObject::disconnect(freq1box, SIGNAL(valueChanged(double)), this, SLOT(freqbox1valuechanged(double))); freq1box->setValue(value * 0.9); QObject::connect(freq1box, SIGNAL(valueChanged(double)), this, SLOT(freqbox1valuechanged(double))); } for(j=0; j<10; j++) qApp->processEvents(); update_filter(); } void AdjustFilterSettings::filterboxchanged(int i) { int n; if(i < 0) { return; } QObject::disconnect(freq1box, SIGNAL(valueChanged(double)), this, SLOT(freqbox1valuechanged(double))); QObject::disconnect(freq2box, SIGNAL(valueChanged(double)), this, SLOT(freqbox2valuechanged(double))); QObject::disconnect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); if(brand[i] == 0) // fidfilter { n = i; frequency1 = signalcomp->fidfilter_freq[n]; frequency2 = signalcomp->fidfilter_freq2[n]; type = signalcomp->fidfilter_type[n]; model = signalcomp->fidfilter_model[n]; order = signalcomp->fidfilter_order[n]; ripple = signalcomp->fidfilter_ripple[n]; freq1box->setValue(frequency1); label[1]->setText("Order"); label[2]->setText("Frequency"); freq1box->setVisible(true); stepsizebox->clear(); stepsizebox->addItem("0.01Hz"); stepsizebox->addItem("0.1Hz"); stepsizebox->addItem("1Hz"); stepsizebox->addItem("10Hz"); stepsizebox->addItem("100Hz"); stepsizebox->setCurrentIndex(2); if((type == 3) || (type == 4)) { freq2box->setValue(frequency2); label[3]->setVisible(true); freq2box->setVisible(true); orderbox->setMinimum(2); orderbox->setSingleStep(2); orderbox->setMaximum(16); } else { freq2box->setValue(0.0); label[3]->setVisible(false); freq2box->setVisible(false); orderbox->setMinimum(1); orderbox->setSingleStep(1); orderbox->setMaximum(8); } if(type == 2) { orderbox->setPrefix("Q-factor "); orderbox->setSuffix(""); orderbox->setMaximum(100); orderbox->setMinimum(3); } else { orderbox->setPrefix(""); orderbox->setSuffix("th order"); } orderbox->setValue(order); } if(brand[i] == 1) // moving average filter { n = i - signalcomp->fidfilter_cnt; type = signalcomp->ravg_filter_type[n]; size = signalcomp->ravg_filter_size[n]; stepsizebox->clear(); stepsizebox->addItem("1"); stepsizebox->addItem("10"); stepsizebox->addItem("100"); stepsizebox->addItem("1000"); stepsizebox->setCurrentIndex(0); label[1]->setText("Size"); label[2]->setText(""); freq1box->setVisible(false); label[3]->setVisible(false); freq2box->setVisible(false); orderbox->setMinimum(2); orderbox->setSingleStep(1); orderbox->setMaximum(10000); orderbox->setPrefix(""); orderbox->setSuffix(" samples"); orderbox->setValue(size); } QObject::connect(freq1box, SIGNAL(valueChanged(double)), this, SLOT(freqbox1valuechanged(double))); QObject::connect(freq2box, SIGNAL(valueChanged(double)), this, SLOT(freqbox2valuechanged(double))); QObject::connect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); } void AdjustFilterSettings::removeButtonClicked() { int i; filter_nr = filterbox->currentIndex(); if(filter_nr < 0) { return; } QObject::disconnect(freq1box, SIGNAL(valueChanged(double)), this, SLOT(freqbox1valuechanged(double))); QObject::disconnect(freq2box, SIGNAL(valueChanged(double)), this, SLOT(freqbox2valuechanged(double))); QObject::disconnect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); if(brand[filter_nr] == 0) // fidfilter { free(signalcomp->fidfilter[filter_nr]); fid_run_free(signalcomp->fid_run[filter_nr]); fid_run_freebuf(signalcomp->fidbuf[filter_nr]); fid_run_freebuf(signalcomp->fidbuf2[filter_nr]); for(i=filter_nr; i<(signalcomp->fidfilter_cnt - 1); i++) { signalcomp->fidfilter[i] = signalcomp->fidfilter[i + 1]; signalcomp->fid_run[i] = signalcomp->fid_run[i + 1]; signalcomp->fidbuf[i] = signalcomp->fidbuf[i + 1]; signalcomp->fidbuf2[i] = signalcomp->fidbuf2[i + 1]; } signalcomp->fidfilter_cnt--; } else if(brand[filter_nr] == 1) // moving average filter { filter_nr -= signalcomp->fidfilter_cnt; free_ravg_filter(signalcomp->ravg_filter[filter_nr]); for(i=filter_nr; i<(signalcomp->ravg_filter_cnt - 1); i++) { signalcomp->ravg_filter[i] = signalcomp->ravg_filter[i + 1]; } signalcomp->ravg_filter_cnt--; } loadFilterSettings(); mainwindow->setup_viewbuf(); } void AdjustFilterSettings::update_filter() { char *filter_spec, spec_str_1[256], spec_str_2[256], *err=NULL; filter_nr = filterbox->currentIndex(); if(filter_nr < 0) { return; } QObject::disconnect(freq1box, SIGNAL(valueChanged(double)), this, SLOT(freqbox1valuechanged(double))); QObject::disconnect(freq2box, SIGNAL(valueChanged(double)), this, SLOT(freqbox2valuechanged(double))); QObject::disconnect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); if(brand[filter_nr] == 0) // fidfilter { frequency1 = freq1box->value(); frequency2 = freq2box->value(); order = orderbox->value(); if(type < 3) { if(frequency1 >= ((signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record / signalcomp->edfhdr->data_record_duration) / 2.0)) { frequency1 = (signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record / signalcomp->edfhdr->data_record_duration) / 2.0; frequency1 -= freq1box->singleStep(); freq1box->setValue(frequency1); } } else { if(frequency2 >= ((signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record / signalcomp->edfhdr->data_record_duration) / 2.0)) { frequency2 = (signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record / signalcomp->edfhdr->data_record_duration) / 2.0; frequency2 -= freq2box->singleStep(); freq2box->setValue(frequency2); } if(frequency1 >= frequency2 * 0.9) { frequency1 = frequency2 * 0.9; freq1box->setValue(frequency1); } } if(type < 3) { if(frequency1 >= ((signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record / signalcomp->edfhdr->data_record_duration) / 2.0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The frequency must be less than: samplerate / 2"); messagewindow.exec(); return; } } else { if(frequency2 >= ((signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record / signalcomp->edfhdr->data_record_duration) / 2.0)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The frequency must be less than: samplerate / 2"); messagewindow.exec(); return; } } spec_str_1[0] = 0; if(type == 0) { if(model == 0) { sprintf(spec_str_1, "HpBu%i/%f", order, frequency1); } if(model == 1) { sprintf(spec_str_1, "HpCh%i/%f/%f", order, ripple, frequency1); } if(model == 2) { sprintf(spec_str_1, "HpBe%i/%f", order, frequency1); } } if(type == 1) { if(model == 0) { sprintf(spec_str_1, "LpBu%i/%f", order, frequency1); } if(model == 1) { sprintf(spec_str_1, "LpCh%i/%f/%f", order, ripple, frequency1); } if(model == 2) { sprintf(spec_str_1, "LpBe%i/%f", order, frequency1); } } if(type == 2) { sprintf(spec_str_1, "BsRe/%i/%f", order, frequency1); } if(type == 3) { if(model == 0) { sprintf(spec_str_1, "BpBu%i/%f-%f", order, frequency1, frequency2); } if(model == 1) { sprintf(spec_str_1, "BpCh%i/%f/%f-%f", order, ripple, frequency1, frequency2); } if(model == 2) { sprintf(spec_str_1, "BpBe%i/%f-%f", order, frequency1, frequency2); } } if(type == 4) { if(model == 0) { sprintf(spec_str_1, "BsBu%i/%f-%f", order, frequency1, frequency2); } if(model == 1) { sprintf(spec_str_1, "BsCh%i/%f/%f-%f", order, ripple, frequency1, frequency2); } if(model == 2) { sprintf(spec_str_1, "BsBe%i/%f-%f", order, frequency1, frequency2); } } strcpy(spec_str_2, spec_str_1); filter_spec = spec_str_2; free(signalcomp->fidfilter[filter_nr]); fid_run_free(signalcomp->fid_run[filter_nr]); fid_run_freebuf(signalcomp->fidbuf[filter_nr]); fid_run_freebuf(signalcomp->fidbuf2[filter_nr]); err = fid_parse(((double)(signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record)) / signalcomp->edfhdr->data_record_duration, &filter_spec, &signalcomp->fidfilter[filter_nr]); if(err != NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", err); messagewindow.exec(); free(err); return; } signalcomp->fid_run[filter_nr] = fid_run_new(signalcomp->fidfilter[filter_nr], &signalcomp->fidfuncp[filter_nr]); signalcomp->fidbuf[filter_nr] = fid_run_newbuf(signalcomp->fid_run[filter_nr]); signalcomp->fidbuf2[filter_nr] = fid_run_newbuf(signalcomp->fid_run[filter_nr]); signalcomp->fidfilter_freq[filter_nr] = frequency1; signalcomp->fidfilter_freq2[filter_nr] = frequency2; signalcomp->fidfilter_order[filter_nr] = order; } if(brand[filter_nr] == 1) // moving average filter { filter_nr -= signalcomp->fidfilter_cnt; size = orderbox->value(); free_ravg_filter(signalcomp->ravg_filter[filter_nr]); signalcomp->ravg_filter[filter_nr] = create_ravg_filter(type, size); if(signalcomp->ravg_filter[filter_nr] == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An internal error occurred while creating a moving average filter."); messagewindow.exec(); return; } signalcomp->ravg_filter_size[filter_nr] = size; } mainwindow->setup_viewbuf(); QObject::connect(freq1box, SIGNAL(valueChanged(double)), this, SLOT(freqbox1valuechanged(double))); QObject::connect(freq2box, SIGNAL(valueChanged(double)), this, SLOT(freqbox2valuechanged(double))); QObject::connect(orderbox, SIGNAL(valueChanged(int)), this, SLOT(orderboxvaluechanged(int))); } void AdjustFilterSettings::stepsizeboxchanged(int index) { int n; n = filterbox->currentIndex(); if(n < 0) { return; } if(brand[n] == 0) // fidfilter { switch(index) { case 0: freq1box->setSingleStep(0.01); freq2box->setSingleStep(0.01); break; case 1: freq1box->setSingleStep(0.1); freq2box->setSingleStep(0.1); break; case 2: freq1box->setSingleStep(1.0); freq2box->setSingleStep(1.0); break; case 3: freq1box->setSingleStep(10.0); freq2box->setSingleStep(10.0); break; case 4: freq1box->setSingleStep(100.0); freq2box->setSingleStep(100.0); break; } } if(brand[n] == 1) // moving average filter { switch(index) { case 0: orderbox->setSingleStep(1); break; case 1: orderbox->setSingleStep(10); break; case 2: orderbox->setSingleStep(100); break; case 3: orderbox->setSingleStep(1000); break; } } } edfbrowser_157_source/PaxHeaders.7921/header_editor.cpp0000644000000000000000000000013212646460742020170 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/header_editor.cpp0000644000175000001440000012412112646460742020532 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "header_editor.h" UI_headerEditorWindow::UI_headerEditorWindow(QWidget *w_parent) { mainwindow = (UI_Mainwindow *)w_parent; setWindowTitle("EDF+/BDF+ header editor"); edf = 0; bdf = 0; edfplus = 0; bdfplus = 0; edfsignals = 0; file = NULL; setMinimumSize(690, 525); setMaximumSize(690, 525); tabholder = new QTabWidget(this); tabholder->setGeometry(0, 0, 690, 455); tab1 = new QWidget; tab2 = new QWidget; fileNameLabel = new QLabel(tab1); fileNameLabel->setGeometry(10, 10, 670, 25); startTimeDateLabel = new QLabel(tab1); startTimeDateLabel->setGeometry(10, 45, 80, 25); startTimeDateLabel->setText("Starttime"); startTimeDateLabel->setVisible(false); startTimeDate = new QDateTimeEdit(tab1); startTimeDate->setGeometry(100, 45, 250, 25); startTimeDate->setDisplayFormat("dd.MM.yyyy hh:mm:ss"); startTimeDate->setMinimumDate(QDate(1970, 1, 1)); startTimeDate->setMaximumDate(QDate(2299, 12, 31)); startTimeDate->setVisible(false); label1 = new QLabel(tab1); label1->setGeometry(10, 80, 80, 25); label1->setText("Subject"); label1->setVisible(false); lineEdit1 = new QLineEdit(tab1); lineEdit1->setGeometry(100, 80, 580, 25); lineEdit1->setMaxLength(80); lineEdit1->setVisible(false); label2 = new QLabel(tab1); label2->setGeometry(10, 115, 80, 25); label2->setText("Recording"); label2->setVisible(false); lineEdit2 = new QLineEdit(tab1); lineEdit2->setGeometry(100, 115, 580, 25); lineEdit2->setMaxLength(80); lineEdit2->setVisible(false); label3 = new QLabel(tab1); label3->setGeometry(10, 80, 80, 25); label3->setText("Subject code"); label3->setVisible(false); lineEdit3 = new QLineEdit(tab1); lineEdit3->setGeometry(100, 80, 580, 25); lineEdit3->setMaxLength(80); lineEdit3->setVisible(false); label4 = new QLabel(tab1); label4->setGeometry(10, 115, 80, 25); label4->setText("Subject name"); label4->setVisible(false); lineEdit4 = new QLineEdit(tab1); lineEdit4->setGeometry(100, 115, 580, 25); lineEdit4->setMaxLength(80); lineEdit4->setVisible(false); label11 = new QLabel(tab1); label11->setGeometry(10, 150, 80, 25); label11->setText("Gender"); label11->setVisible(false); comboBox1 = new QComboBox(tab1); comboBox1->setGeometry(100, 150, 125, 25); comboBox1->addItem("unknown"); comboBox1->addItem("male"); comboBox1->addItem("female"); comboBox1->setVisible(false); charsleft1Label = new QLabel(tab1); charsleft1Label->setGeometry(500, 150, 120, 25); charsleft1Label->setVisible(false); label12 = new QLabel(tab1); label12->setGeometry(10, 185, 80, 25); label12->setText("Birthdate"); label12->setVisible(false); dateEdit1 = new QDateEdit(tab1); dateEdit1->setGeometry(100, 185, 125, 25); dateEdit1->setDisplayFormat("d MMM yyyy"); dateEdit1->setVisible(false); checkBox1 = new QCheckBox("No birthdate", tab1); checkBox1->setGeometry(245, 185, 125, 25); checkBox1->setTristate(false); checkBox1->setCheckState(Qt::Unchecked); checkBox1->setVisible(false); label5 = new QLabel(tab1); label5->setGeometry(10, 220, 80, 25); label5->setText("Additional info"); label5->setVisible(false); lineEdit5 = new QLineEdit(tab1); lineEdit5->setGeometry(100, 220, 580, 25); lineEdit5->setMaxLength(80); lineEdit5->setVisible(false); label6 = new QLabel(tab1); label6->setGeometry(10, 255, 80, 25); label6->setText("Admin. code"); label6->setVisible(false); lineEdit6 = new QLineEdit(tab1); lineEdit6->setGeometry(100, 255, 580, 25); lineEdit6->setMaxLength(80); lineEdit6->setVisible(false); label7 = new QLabel(tab1); label7->setGeometry(10, 290, 80, 25); label7->setText("Technician"); label7->setVisible(false); lineEdit7 = new QLineEdit(tab1); lineEdit7->setGeometry(100, 290, 580, 25); lineEdit7->setMaxLength(80); lineEdit7->setVisible(false); label8 = new QLabel(tab1); label8->setGeometry(10, 325, 80, 25); label8->setText("Device"); label8->setVisible(false); lineEdit8 = new QLineEdit(tab1); lineEdit8->setGeometry(100, 325, 580, 25); lineEdit8->setMaxLength(80); lineEdit8->setVisible(false); label9 = new QLabel(tab1); label9->setGeometry(10, 360, 80, 25); label9->setText("Additional info"); label9->setVisible(false); lineEdit9 = new QLineEdit(tab1); lineEdit9->setGeometry(100, 360, 580, 25); lineEdit9->setMaxLength(80); lineEdit9->setVisible(false); charsleft2Label = new QLabel(tab1); charsleft2Label->setGeometry(500, 395, 120, 25); charsleft2Label->setVisible(false); signallist = new QTableWidget(tab2); signallist->setGeometry(10, 10, 670, 375); signallist->setSelectionMode(QAbstractItemView::NoSelection); signallist->setEditTriggers(QAbstractItemView::NoEditTriggers); signallist->setColumnCount(4); signallist->setSelectionMode(QAbstractItemView::NoSelection); signallist->setColumnWidth(0, 180); signallist->setColumnWidth(1, 120); signallist->setColumnWidth(2, 520); signallist->setColumnWidth(3, 520); QStringList horizontallabels; horizontallabels += "Label"; horizontallabels += "Physical dimension"; horizontallabels += "Prefilter"; horizontallabels += "Transducer"; signallist->setHorizontalHeaderLabels(horizontallabels); pushButton1 = new QPushButton(this); pushButton1->setGeometry(580, 475, 100, 25); pushButton1->setText("Close"); pushButton2 = new QPushButton(this); pushButton2->setGeometry(200, 475, 100, 25); pushButton2->setText("Save"); pushButton3 = new QPushButton(this); pushButton3->setGeometry(10, 475, 100, 25); pushButton3->setText("Select file"); connect(pushButton1, SIGNAL(clicked()), this, SLOT(close())); connect(pushButton2, SIGNAL(clicked()), this, SLOT(save_hdr())); connect(pushButton3, SIGNAL(clicked()), this, SLOT(open_file())); tabholder->addTab(tab1, "Header"); tabholder->addTab(tab2, "Signals"); hdr = (char *)malloc(256 * 2050); QMessageBox messagewindow(QMessageBox::Warning, "Warning", "Always make a backup copy of your file before using this tool!"); messagewindow.exec(); exec(); } void UI_headerEditorWindow::closeEvent(QCloseEvent *cl_event) { if(file != NULL) { fclose(file); } if(hdr != NULL) { free(hdr); } cl_event->accept(); } void UI_headerEditorWindow::open_file() { long long filesize; if(file != NULL) { fclose(file); file = NULL; } edf = 0; bdf = 0; edfplus = 0; bdfplus = 0; edfsignals = 0; disconnect(lineEdit3, SIGNAL(textEdited(const QString &)), this, SLOT(calculate_chars_left_name(const QString &))); disconnect(lineEdit4, SIGNAL(textEdited(const QString &)), this, SLOT(calculate_chars_left_name(const QString &))); disconnect(lineEdit5, SIGNAL(textEdited(const QString &)), this, SLOT(calculate_chars_left_name(const QString &))); disconnect(lineEdit6, SIGNAL(textEdited(const QString &)), this, SLOT(calculate_chars_left_recording(const QString &))); disconnect(lineEdit7, SIGNAL(textEdited(const QString &)), this, SLOT(calculate_chars_left_recording(const QString &))); disconnect(lineEdit8, SIGNAL(textEdited(const QString &)), this, SLOT(calculate_chars_left_recording(const QString &))); disconnect(lineEdit9, SIGNAL(textEdited(const QString &)), this, SLOT(calculate_chars_left_recording(const QString &))); lineEdit3->setMaxLength(80); lineEdit4->setMaxLength(80); lineEdit5->setMaxLength(80); lineEdit6->setMaxLength(80); lineEdit7->setMaxLength(80); lineEdit8->setMaxLength(80); lineEdit9->setMaxLength(80); lineEdit1->clear(); lineEdit2->clear(); lineEdit3->clear(); lineEdit4->clear(); lineEdit5->clear(); lineEdit6->clear(); lineEdit7->clear(); lineEdit8->clear(); lineEdit9->clear(); signallist->setRowCount(0); fileNameLabel->clear(); if(hdr==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "A memory allocation error occurred. (hdr)"); messagewindow.exec(); return; } strcpy(path, QFileDialog::getOpenFileName(0, "Open file", QString::fromLocal8Bit(mainwindow->recent_opendir), "EDF/BDF files (*.edf *.EDF *.bdf *.BDF)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(mainwindow->recent_opendir, path, MAX_PATH_LENGTH); if(mainwindow->file_is_opened(path)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Selected file is in use."); messagewindow.exec(); return; } file = fopeno(path, "r+b"); if(file==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file."); messagewindow.exec(); return; } rewind(file); if(fread(hdr, 256, 1, file) != 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not read from file."); messagewindow.exec(); fclose(file); file = NULL; return; } if(!(strncmp(hdr, "0 ", 8))) edf = 1; if((!(strncmp(hdr + 1, "BIOSEMI", 7))) && (((unsigned char *)hdr)[0] == 255)) { bdf = 1; } if((!edf) && (!bdf)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "File is not a valid EDF or BDF file.\n" "Invalid version."); messagewindow.exec(); fclose(file); file = NULL; return; } edfsignals = antoi(hdr + 252, 4); if(edfsignals < 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Invalid number of signals in header (less than 1)"); messagewindow.exec(); fclose(file); file = NULL; return; } if(edfsignals > 2049) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Number of signals in header is more than 2048.\n" "This tool can not process more than 2048 signals."); messagewindow.exec(); fclose(file); file = NULL; return; } fseeko(file, 0LL, SEEK_END); filesize = ftello(file); if(filesize < (((edfsignals + 1LL) * 256LL) + edfsignals)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Filesize is too small.\n" "Can not fix this file."); messagewindow.exec(); fclose(file); file = NULL; return; } if((!(strncmp(hdr + 192, "EDF+C", 5))) || (!(strncmp(hdr + 192, "EDF+D", 5)))) { edfplus = 1; } if((!(strncmp(hdr + 192, "BDF+C", 5))) || (!(strncmp(hdr + 192, "BDF+D", 5)))) { bdfplus = 1; } read_header(); } void UI_headerEditorWindow::read_header() { int i, j, p, r; char scratchpad[256], str[256]; if(file == NULL) { return; } fileNameLabel->setText(QString::fromLocal8Bit(path)); rewind(file); if(fread(hdr, (256 * edfsignals) + 256, 1, file) != 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not read from file."); messagewindow.exec(); fclose(file); file = NULL; return; } startTimeDate->setVisible(true); startTimeDateLabel->setVisible(true); if(edfplus || bdfplus) { startTimeDate->setMinimumDate(QDate(1970, 1, 1)); startTimeDate->setMaximumDate(QDate(2299, 12, 31)); startTimeDate->setDate(QDate(1970, 1, 1)); } else { startTimeDate->setMinimumDate(QDate(1985, 1, 1)); startTimeDate->setMaximumDate(QDate(2084, 12, 31)); startTimeDate->setDate(QDate(1985, 1, 1)); } startTimeDate->setTime(QTime(0, 0, 0)); memcpy(scratchpad, hdr + 168, 8); scratchpad[2] = 0; scratchpad[5] = 0; scratchpad[8] = 0; r = atoi(scratchpad + 6); if(r < 85) { r += 2000; } else { r += 1900; } startTimeDate->setDate(QDate(r, atoi(scratchpad + 3), atoi(scratchpad))); startTimeDate->setMinimumDate(QDate(1985, 1, 1)); startTimeDate->setMaximumDate(QDate(2084, 12, 31)); memcpy(scratchpad, hdr + 176, 8); scratchpad[2] = 0; scratchpad[5] = 0; scratchpad[8] = 0; startTimeDate->setTime(QTime(atoi(scratchpad), atoi(scratchpad + 3), atoi(scratchpad + 6))); if(edfplus || bdfplus) { label1->setVisible(false); label2->setVisible(false); lineEdit1->setVisible(false); lineEdit2->setVisible(false); label3->setVisible(true); label4->setVisible(true); label5->setVisible(true); label6->setVisible(true); label7->setVisible(true); label8->setVisible(true); label9->setVisible(true); label11->setVisible(true); label12->setVisible(true); charsleft1Label->setVisible(true); charsleft2Label->setVisible(true); lineEdit3->setVisible(true); lineEdit4->setVisible(true); lineEdit5->setVisible(true); lineEdit6->setVisible(true); lineEdit7->setVisible(true); lineEdit8->setVisible(true); lineEdit9->setVisible(true); comboBox1->setVisible(true); checkBox1->setVisible(true); dateEdit1->setVisible(true); strncpy(scratchpad, hdr + 8, 80); scratchpad[80] = 0; strcat(scratchpad, " "); p = 0; for(i=0; i<80; i++) { if(scratchpad[i] == ' ') break; } if(strncmp(scratchpad, "X ", 2)) { scratchpad[i] = 0; for(j=p; jsetText(str); } else { lineEdit3->clear(); } p = ++i; for(; i<80; i++) { if(scratchpad[i] == ' ') break; } comboBox1->setCurrentIndex(0); if(!(strncmp(scratchpad + p, "M ", 2))) { comboBox1->setCurrentIndex(1); } if(!(strncmp(scratchpad + p, "F ", 2))) { comboBox1->setCurrentIndex(2); } p = ++i; for(; i<80; i++) { if(scratchpad[i] == ' ') break; } dateEdit1->setDate(QDate(1800, 1, 1)); if(strncmp(scratchpad + p, "X ", 2)) { scratchpad[i] = 0; r = 0; if(!strncmp(scratchpad + p + 3, "JAN", 3)) r = 1; else if(!strncmp(scratchpad + p + 3, "FEB", 3)) r = 2; else if(!strncmp(scratchpad + p + 3, "MAR", 3)) r = 3; else if(!strncmp(scratchpad + p + 3, "APR", 3)) r = 4; else if(!strncmp(scratchpad + p + 3, "MAY", 3)) r = 5; else if(!strncmp(scratchpad + p + 3, "JUN", 3)) r = 6; else if(!strncmp(scratchpad + p + 3, "JUL", 3)) r = 7; else if(!strncmp(scratchpad + p + 3, "AUG", 3)) r = 8; else if(!strncmp(scratchpad + p + 3, "SEP", 3)) r = 9; else if(!strncmp(scratchpad + p + 3, "OCT", 3)) r = 10; else if(!strncmp(scratchpad + p + 3, "NOV", 3)) r = 11; else if(!strncmp(scratchpad + p + 3, "DEC", 3)) r = 12; if(r) { dateEdit1->setDate(QDate(atoi(scratchpad + p + 7), r, atoi(scratchpad + p))); checkBox1->setCheckState(Qt::Unchecked); } p += 10; } else { checkBox1->setCheckState(Qt::Checked); } p = ++i; for(; i<80; i++) { if(scratchpad[i] == ' ') break; } if(strncmp(scratchpad + p, "X ", 2)) { scratchpad[i] = 0; for(j=p; jsetText(str); } else { lineEdit4->clear(); } p = ++i; scratchpad[80] = 0; strcpy(str, scratchpad + p); remove_trailing_spaces(str); lineEdit5->setText(str); strncpy(scratchpad, hdr + 88, 80); scratchpad[80] = 0; strcat(scratchpad, " "); p = 10; for(i=10; i<80; i++) { if(scratchpad[i] == ' ') break; } if(strncmp(scratchpad + p, "X ", 2)) { scratchpad[i] = 0; has_startdate = 1; scratchpad[12] = 0; scratchpad[16] = 0; scratchpad[21] = 0; r = 0; if(!strncmp(scratchpad + 13, "JAN", 3)) r = 1; else if(!strncmp(scratchpad + 13, "FEB", 3)) r = 2; else if(!strncmp(scratchpad + 13, "MAR", 3)) r = 3; else if(!strncmp(scratchpad + 13, "APR", 3)) r = 4; else if(!strncmp(scratchpad + 13, "MAY", 3)) r = 5; else if(!strncmp(scratchpad + 13, "JUN", 3)) r = 6; else if(!strncmp(scratchpad + 13, "JUL", 3)) r = 7; else if(!strncmp(scratchpad + 13, "AUG", 3)) r = 8; else if(!strncmp(scratchpad + 13, "SEP", 3)) r = 9; else if(!strncmp(scratchpad + 13, "OCT", 3)) r = 10; else if(!strncmp(scratchpad + 13, "NOV", 3)) r = 11; else if(!strncmp(scratchpad + 13, "DEC", 3)) r = 12; if(r) { startTimeDate->setDate(QDate(atoi(scratchpad + 17), r, atoi(scratchpad + 10))); startTimeDate->setMinimumDate(QDate(1970, 1, 1)); startTimeDate->setMaximumDate(QDate(2299, 12, 31)); } } else { has_startdate = 0; } p = ++i; for(; i<80; i++) { if(scratchpad[i] == ' ') break; } if(strncmp(scratchpad + p, "X ", 2)) { scratchpad[i] = 0; for(j=p; jsetText(str); } else { lineEdit6->clear(); } p = ++i; for(; i<80; i++) { if(scratchpad[i] == ' ') break; } if(strncmp(scratchpad + p, "X ", 2)) { scratchpad[i] = 0; for(j=p; jsetText(str); } else { lineEdit7->clear(); } p = ++i; for(; i<80; i++) { if(scratchpad[i] == ' ') break; } if(strncmp(scratchpad + p, "X ", 2)) { scratchpad[i] = 0; for(j=p; jsetText(str); } else { lineEdit8->clear(); } p = ++i; scratchpad[80] = 0; strcpy(str, scratchpad + p); remove_trailing_spaces(str); lineEdit9->setText(str); calculate_chars_left_name(""); calculate_chars_left_recording(""); connect(lineEdit3, SIGNAL(textEdited(const QString &)), this, SLOT(calculate_chars_left_name(const QString &))); connect(lineEdit4, SIGNAL(textEdited(const QString &)), this, SLOT(calculate_chars_left_name(const QString &))); connect(lineEdit5, SIGNAL(textEdited(const QString &)), this, SLOT(calculate_chars_left_name(const QString &))); connect(lineEdit6, SIGNAL(textEdited(const QString &)), this, SLOT(calculate_chars_left_recording(const QString &))); connect(lineEdit7, SIGNAL(textEdited(const QString &)), this, SLOT(calculate_chars_left_recording(const QString &))); connect(lineEdit8, SIGNAL(textEdited(const QString &)), this, SLOT(calculate_chars_left_recording(const QString &))); connect(lineEdit9, SIGNAL(textEdited(const QString &)), this, SLOT(calculate_chars_left_recording(const QString &))); } else { label3->setVisible(false); label4->setVisible(false); label5->setVisible(false); label6->setVisible(false); label7->setVisible(false); label8->setVisible(false); label9->setVisible(false); label11->setVisible(false); label12->setVisible(false); charsleft1Label->setVisible(false); charsleft2Label->setVisible(false); lineEdit3->setVisible(false); lineEdit4->setVisible(false); lineEdit5->setVisible(false); lineEdit6->setVisible(false); lineEdit7->setVisible(false); lineEdit8->setVisible(false); lineEdit9->setVisible(false); comboBox1->setVisible(false); checkBox1->setVisible(false); dateEdit1->setVisible(false); label1->setVisible(true); label2->setVisible(true); lineEdit1->setVisible(true); lineEdit2->setVisible(true); strncpy(scratchpad, hdr + 8, 80); scratchpad[80] = 0; remove_trailing_spaces(scratchpad); lineEdit1->setText(scratchpad); strncpy(scratchpad, hdr + 88, 80); scratchpad[80] = 0; remove_trailing_spaces(scratchpad); lineEdit2->setText(scratchpad); } datrecs = antoi(hdr + 236, 8); signallist->setRowCount(edfsignals); recordsize = 0; for(i=0; isetRowHeight(i, 25); strncpy(scratchpad, hdr + 256 + (i * 16), 16); scratchpad[16] = 0; remove_trailing_spaces(scratchpad); signallist->setCellWidget(i, 0, new QLineEdit(scratchpad)); ((QLineEdit *)(signallist->cellWidget(i, 0)))->setMaxLength(16); ((QLineEdit *)(signallist->cellWidget(i, 0)))->setText(scratchpad); strncpy(scratchpad, hdr + 256 + (edfsignals * 96) + (i * 8), 8); scratchpad[8] = 0; remove_trailing_spaces(scratchpad); signallist->setCellWidget(i, 1, new QLineEdit(scratchpad)); ((QLineEdit *)(signallist->cellWidget(i, 1)))->setMaxLength(8); ((QLineEdit *)(signallist->cellWidget(i, 1)))->setText(scratchpad); strncpy(scratchpad, hdr + 256 + (edfsignals * 136) + (i * 80), 80); scratchpad[80] = 0; remove_trailing_spaces(scratchpad); signallist->setCellWidget(i, 2, new QLineEdit(scratchpad)); ((QLineEdit *)(signallist->cellWidget(i, 2)))->setMaxLength(80); ((QLineEdit *)(signallist->cellWidget(i, 2)))->setText(scratchpad); strncpy(scratchpad, hdr + 256 + (edfsignals * 16) + (i * 80), 80); scratchpad[80] = 0; remove_trailing_spaces(scratchpad); signallist->setCellWidget(i, 3, new QLineEdit(scratchpad)); ((QLineEdit *)(signallist->cellWidget(i, 3)))->setMaxLength(80); ((QLineEdit *)(signallist->cellWidget(i, 3)))->setText(scratchpad); strncpy(scratchpad, hdr + 256 + (edfsignals * 216) + (i * 8), 8); scratchpad[8] = 0; if(atoi(scratchpad) < 1) { sprintf(str, "Samples per record of signal %i is less than 1.\n" "Can not fix this file.", i + 1); QMessageBox messagewindow(QMessageBox::Critical, "Error", str); messagewindow.exec(); fclose(file); file = NULL; return; } if(bdf) { recordsize += (atoi(scratchpad) * 3); } else { recordsize += (atoi(scratchpad) * 2); } if(edfplus) { if(!(strncmp(((QLineEdit *)(signallist->cellWidget(i, 0)))->text().toLatin1().data(), "EDF Annotations", 15))) { ((QLineEdit *)(signallist->cellWidget(i, 0)))->setEnabled(false); ((QLineEdit *)(signallist->cellWidget(i, 1)))->setEnabled(false); ((QLineEdit *)(signallist->cellWidget(i, 2)))->setEnabled(false); ((QLineEdit *)(signallist->cellWidget(i, 3)))->setEnabled(false); } } if(bdfplus) { if(!(strncmp(((QLineEdit *)(signallist->cellWidget(i, 0)))->text().toLatin1().data(), "BDF Annotations", 15))) { ((QLineEdit *)(signallist->cellWidget(i, 0)))->setEnabled(false); ((QLineEdit *)(signallist->cellWidget(i, 1)))->setEnabled(false); ((QLineEdit *)(signallist->cellWidget(i, 2)))->setEnabled(false); ((QLineEdit *)(signallist->cellWidget(i, 3)))->setEnabled(false); } } } if(recordsize < 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Recordsize is less than 1.\n" "Can not fix this file."); messagewindow.exec(); fclose(file); file = NULL; return; } } void UI_headerEditorWindow::save_hdr() { int i, j, p, len, hassign; char scratchpad[256], str[256]; long long filesize, l_tmp=0LL; if(file == NULL) { return; } sprintf(scratchpad, "%02i.%02i.%02i%02i.%02i.%02i", startTimeDate->date().day(), startTimeDate->date().month(), startTimeDate->date().year() % 100, startTimeDate->time().hour(), startTimeDate->time().minute(), startTimeDate->time().second()); fseeko(file, 168LL, SEEK_SET); fprintf(file, "%s", scratchpad); if(edfplus || bdfplus) { str[0] = 0; len = strlen(lineEdit3->text().toLatin1().data()); // patient code if(len) { strcpy(scratchpad, lineEdit3->text().toLatin1().data()); latin1_to_ascii(scratchpad, len); remove_trailing_spaces(scratchpad); for(i=0; icurrentIndex() == 0) // gender { strcat(str, "X "); } if(comboBox1->currentIndex() == 1) { strcat(str, "M "); } if(comboBox1->currentIndex() == 2) { strcat(str, "F "); } if(checkBox1->checkState() == Qt::Checked) // birthdate { strcat(str, "X "); } else { i = dateEdit1->date().month(); switch(i) { case 1 : sprintf(scratchpad, "%02i-JAN-%04i ", dateEdit1->date().day(), dateEdit1->date().year()); break; case 2 : sprintf(scratchpad, "%02i-FEB-%04i ", dateEdit1->date().day(), dateEdit1->date().year()); break; case 3 : sprintf(scratchpad, "%02i-MAR-%04i ", dateEdit1->date().day(), dateEdit1->date().year()); break; case 4 : sprintf(scratchpad, "%02i-APR-%04i ", dateEdit1->date().day(), dateEdit1->date().year()); break; case 5 : sprintf(scratchpad, "%02i-MAY-%04i ", dateEdit1->date().day(), dateEdit1->date().year()); break; case 6 : sprintf(scratchpad, "%02i-JUN-%04i ", dateEdit1->date().day(), dateEdit1->date().year()); break; case 7 : sprintf(scratchpad, "%02i-JUL-%04i ", dateEdit1->date().day(), dateEdit1->date().year()); break; case 8 : sprintf(scratchpad, "%02i-AUG-%04i ", dateEdit1->date().day(), dateEdit1->date().year()); break; case 9 : sprintf(scratchpad, "%02i-SEP-%04i ", dateEdit1->date().day(), dateEdit1->date().year()); break; case 10 : sprintf(scratchpad, "%02i-OCT-%04i ", dateEdit1->date().day(), dateEdit1->date().year()); break; case 11 : sprintf(scratchpad, "%02i-NOV-%04i ", dateEdit1->date().day(), dateEdit1->date().year()); break; case 12 : sprintf(scratchpad, "%02i-DEC-%04i ", dateEdit1->date().day(), dateEdit1->date().year()); break; } strcat(str, scratchpad); } len = strlen(lineEdit4->text().toLatin1().data()); // patient name if(len) { strcpy(scratchpad, lineEdit4->text().toLatin1().data()); latin1_to_ascii(scratchpad, len); remove_trailing_spaces(scratchpad); for(i=0; itext().toLatin1().data()); // additional info if(len) { strcpy(scratchpad, lineEdit5->text().toLatin1().data()); latin1_to_ascii(scratchpad, len); remove_trailing_spaces(scratchpad); strcat(str, scratchpad); } for(i=0; i<8; i++) { strcat(str, " "); } str[80] = 0; fseeko(file, 8LL, SEEK_SET); fprintf(file, "%s", str); if(has_startdate) { strcpy(str, "Startdate "); i = startTimeDate->date().month(); switch(i) { case 1 : sprintf(scratchpad, "%02i-JAN-%04i ", startTimeDate->date().day(), startTimeDate->date().year()); break; case 2 : sprintf(scratchpad, "%02i-FEB-%04i ", startTimeDate->date().day(), startTimeDate->date().year()); break; case 3 : sprintf(scratchpad, "%02i-MAR-%04i ", startTimeDate->date().day(), startTimeDate->date().year()); break; case 4 : sprintf(scratchpad, "%02i-APR-%04i ", startTimeDate->date().day(), startTimeDate->date().year()); break; case 5 : sprintf(scratchpad, "%02i-MAY-%04i ", startTimeDate->date().day(), startTimeDate->date().year()); break; case 6 : sprintf(scratchpad, "%02i-JUN-%04i ", startTimeDate->date().day(), startTimeDate->date().year()); break; case 7 : sprintf(scratchpad, "%02i-JUL-%04i ", startTimeDate->date().day(), startTimeDate->date().year()); break; case 8 : sprintf(scratchpad, "%02i-AUG-%04i ", startTimeDate->date().day(), startTimeDate->date().year()); break; case 9 : sprintf(scratchpad, "%02i-SEP-%04i ", startTimeDate->date().day(), startTimeDate->date().year()); break; case 10 : sprintf(scratchpad, "%02i-OCT-%04i ", startTimeDate->date().day(), startTimeDate->date().year()); break; case 11 : sprintf(scratchpad, "%02i-NOV-%04i ", startTimeDate->date().day(), startTimeDate->date().year()); break; case 12 : sprintf(scratchpad, "%02i-DEC-%04i ", startTimeDate->date().day(), startTimeDate->date().year()); break; } strcat(str, scratchpad); } else { strcpy(str, "Startdate X "); } len = strlen(lineEdit6->text().toLatin1().data()); // administration code if(len) { strcpy(scratchpad, lineEdit6->text().toLatin1().data()); latin1_to_ascii(scratchpad, len); remove_trailing_spaces(scratchpad); for(i=0; itext().toLatin1().data()); // technician if(len) { strcpy(scratchpad, lineEdit7->text().toLatin1().data()); latin1_to_ascii(scratchpad, len); remove_trailing_spaces(scratchpad); for(i=0; itext().toLatin1().data()); // device if(len) { strcpy(scratchpad, lineEdit8->text().toLatin1().data()); latin1_to_ascii(scratchpad, len); remove_trailing_spaces(scratchpad); for(i=0; itext().toLatin1().data()); // additional info if(len) { strcpy(scratchpad, lineEdit9->text().toLatin1().data()); latin1_to_ascii(scratchpad, len); remove_trailing_spaces(scratchpad); strcat(str, scratchpad); } for(i=0; i<8; i++) { strcat(str, " "); } str[80] = 0; fseeko(file, 88LL, SEEK_SET); fprintf(file, "%s", str); } else { strcpy(scratchpad, lineEdit1->text().toLatin1().data()); for(j=strlen(scratchpad); j<80; j++) { scratchpad[j] = ' '; } latin1_to_ascii(scratchpad, 80); scratchpad[80] = 0; fseeko(file, 8LL, SEEK_SET); fprintf(file, "%s", scratchpad); strcpy(scratchpad, lineEdit2->text().toLatin1().data()); for(j=strlen(scratchpad); j<80; j++) { scratchpad[j] = ' '; } latin1_to_ascii(scratchpad, 80); scratchpad[80] = 0; fseeko(file, 88LL, SEEK_SET); fprintf(file, "%s", scratchpad); } fseeko(file, 170LL, SEEK_SET); fputc('.', file); fseeko(file, 173LL, SEEK_SET); fputc('.', file); fseeko(file, 178LL, SEEK_SET); fputc('.', file); fseeko(file, 181LL, SEEK_SET); fputc('.', file); if(edfplus || bdfplus) // reserved { fseeko(file, 197LL, SEEK_SET); for(j=0; j<39; j++) { fputc(' ', file); } } else { fseeko(file, 192LL, SEEK_SET); for(j=0; j<44; j++) { fputc(' ', file); } } for(i=0; icellWidget(i, 0)))->isEnabled() == false) // EDF/BDF Annotations signal { fseeko(file, (long long)(256 + (edfsignals * 96) + (i * 8)), SEEK_SET); // physical dimension fprintf(file, " "); for(j=0; j<80; j++) { scratchpad[j] = ' '; } scratchpad[80] = 0; fseeko(file, (long long)(256 + (edfsignals * 136) + (i * 80)), SEEK_SET); // prefiltering fprintf(file, "%s", scratchpad); for(j=0; j<80; j++) { scratchpad[j] = ' '; } scratchpad[80] = 0; fseeko(file, (long long)(256 + (edfsignals * 16) + (i * 80)), SEEK_SET); // transducer type fprintf(file, "%s", scratchpad); fseeko(file, (long long)(256 + (edfsignals * 120) + (i * 8)), SEEK_SET); // digital minimum if(edfplus) { fprintf(file, "-32768 "); } else { if(bdfplus) { fprintf(file, "-8388608"); } } fseeko(file, (long long)(256 + (edfsignals * 128) + (i * 8)), SEEK_SET); // digital maximum if(edfplus) { fprintf(file, "32767 "); } else { if(bdfplus) { fprintf(file, "8388607 "); } } fseeko(file, (long long)(256 + (edfsignals * 104) + (i * 8)), SEEK_SET); // physical minimum fprintf(file, "-1 "); fseeko(file, (long long)(256 + (edfsignals * 112) + (i * 8)), SEEK_SET); // physical maximum fprintf(file, "1 "); } else { strcpy(scratchpad, ((QLineEdit *)(signallist->cellWidget(i, 0)))->text().toLatin1().data()); for(j=strlen(scratchpad); j<16; j++) { scratchpad[j] = ' '; } latin1_to_ascii(scratchpad, 16); scratchpad[16] = 0; fseeko(file, (long long)(256 + (i * 16)), SEEK_SET); fprintf(file, "%s", scratchpad); strcpy(scratchpad, ((QLineEdit *)(signallist->cellWidget(i, 1)))->text().toLatin1().data()); for(j=strlen(scratchpad); j<8; j++) { scratchpad[j] = ' '; } latin1_to_ascii(scratchpad, 8); scratchpad[8] = 0; fseeko(file, (long long)(256 + (edfsignals * 96) + (i * 8)), SEEK_SET); fprintf(file, "%s", scratchpad); strcpy(scratchpad, ((QLineEdit *)(signallist->cellWidget(i, 2)))->text().toLatin1().data()); for(j=strlen(scratchpad); j<80; j++) { scratchpad[j] = ' '; } latin1_to_ascii(scratchpad, 80); scratchpad[80] = 0; fseeko(file, (long long)(256 + (edfsignals * 136) + (i * 80)), SEEK_SET); fprintf(file, "%s", scratchpad); strcpy(scratchpad, ((QLineEdit *)(signallist->cellWidget(i, 3)))->text().toLatin1().data()); for(j=strlen(scratchpad); j<80; j++) { scratchpad[j] = ' '; } latin1_to_ascii(scratchpad, 80); scratchpad[80] = 0; fseeko(file, (long long)(256 + (edfsignals * 16) + (i * 80)), SEEK_SET); fprintf(file, "%s", scratchpad); strncpy(scratchpad, hdr + 256 + (edfsignals * 120) + (i * 8), 8); // digital minimum hassign = 0; p = 0; if((scratchpad[0] == '+') || (scratchpad[0] == '-')) { hassign = 1; p++; } for(; p<8; p++) { if((scratchpad[p] < '0') || (scratchpad[p] > '9')) { break; } } if(p != hassign) { for(; p<8; p++) { scratchpad[p] = ' '; } scratchpad[8] = 0; fseeko(file, (long long)(256 + (edfsignals * 120) + (i * 8)), SEEK_SET); fprintf(file, "%s", scratchpad); } strncpy(scratchpad, hdr + 256 + (edfsignals * 128) + (i * 8), 8); // digital maximum hassign = 0; p = 0; if((scratchpad[0] == '+') || (scratchpad[0] == '-')) { hassign = 1; p++; } for(; p<8; p++) { if((scratchpad[p] < '0') || (scratchpad[p] > '9')) { break; } } if(p != hassign) { for(; p<8; p++) { scratchpad[p] = ' '; } scratchpad[8] = 0; fseeko(file, (long long)(256 + (edfsignals * 128) + (i * 8)), SEEK_SET); fprintf(file, "%s", scratchpad); } strncpy(scratchpad, hdr + 256 + (edfsignals * 104) + (i * 8), 8); // physical minimum for(p=7; p>0; p--) { if((scratchpad[p] < '0') || (scratchpad[p] > '9')) { scratchpad[p] = ' '; } else { break; } } scratchpad[8] = 0; fseeko(file, (long long)(256 + (edfsignals * 104) + (i * 8)), SEEK_SET); fprintf(file, "%s", scratchpad); strncpy(scratchpad, hdr + 256 + (edfsignals * 112) + (i * 8), 8); // physical maximum for(p=7; p>0; p--) { if((scratchpad[p] < '0') || (scratchpad[p] > '9')) { scratchpad[p] = ' '; } else { break; } } scratchpad[8] = 0; fseeko(file, (long long)(256 + (edfsignals * 112) + (i * 8)), SEEK_SET); fprintf(file, "%s", scratchpad); } fseeko(file, (long long)(256 + (edfsignals * 224) + (i * 32)), SEEK_SET); // reserved for(j=0; j<32; j++) { fputc(' ', file); } } fseeko(file, 236LL, SEEK_SET); fprintf(file, "%-8i", datrecs); // datarecords fseeko(file, 0LL, SEEK_END); filesize = ftello(file); if(filesize != (((long long)recordsize * (long long)datrecs)) + ((edfsignals * 256) + 256)) { l_tmp = filesize - ((edfsignals * 256) + 256); datrecs = l_tmp / (long long)recordsize; if(datrecs > 0) { if(datrecs > 99999999) { datrecs = 99999999; } fseeko(file, 236LL, SEEK_SET); fprintf(file, "%-8i", datrecs); l_tmp = ((edfsignals * 256) + 256); l_tmp += (long long)datrecs * (long long)recordsize; if(l_tmp != filesize) { fclose(file); if(QFile::resize(QString::fromLocal8Bit(path), l_tmp) == false) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not resize file."); messagewindow.exec(); } file = fopeno(path, "r+b"); if(file==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file."); messagewindow.exec(); return; } } } } fflush(file); read_header(); } void UI_headerEditorWindow::calculate_chars_left_name(const QString &) { int n = 61; int len; int cursorposition[3]; char str[128]; cursorposition[0] = lineEdit3->cursorPosition(); cursorposition[1] = lineEdit4->cursorPosition(); cursorposition[2] = lineEdit5->cursorPosition(); len = strlen(lineEdit3->text().toLatin1().data()); if(len>1) { n -= (len - 1); } len = strlen(lineEdit4->text().toLatin1().data()); if(len>1) { n -= (len - 1); } len = strlen(lineEdit5->text().toLatin1().data()); if(len>1) { n -= (len - 1); } if(n<1) { lineEdit3->setMaxLength(strlen(lineEdit3->text().toLatin1().data())); lineEdit4->setMaxLength(strlen(lineEdit4->text().toLatin1().data())); lineEdit5->setMaxLength(strlen(lineEdit5->text().toLatin1().data())); } else { lineEdit3->setMaxLength(80); lineEdit4->setMaxLength(80); lineEdit5->setMaxLength(80); } lineEdit3->setCursorPosition(cursorposition[0]); lineEdit4->setCursorPosition(cursorposition[1]); lineEdit5->setCursorPosition(cursorposition[2]); sprintf(str, "Characters left: %i", n); charsleft1Label->setText(str); } void UI_headerEditorWindow::calculate_chars_left_recording(const QString &) { int n = 42; int len; int cursorposition[4]; char str[128]; cursorposition[0] = lineEdit6->cursorPosition(); cursorposition[1] = lineEdit7->cursorPosition(); cursorposition[2] = lineEdit8->cursorPosition(); cursorposition[3] = lineEdit9->cursorPosition(); len = strlen(lineEdit6->text().toLatin1().data()); if(len>1) { n -= (len - 1); } len = strlen(lineEdit7->text().toLatin1().data()); if(len>1) { n -= (len - 1); } len = strlen(lineEdit8->text().toLatin1().data()); if(len>1) { n -= (len - 1); } len = strlen(lineEdit9->text().toLatin1().data()); if(len>1) { n -= (len - 1); } if(n<1) { lineEdit6->setMaxLength(strlen(lineEdit6->text().toLatin1().data())); lineEdit7->setMaxLength(strlen(lineEdit7->text().toLatin1().data())); lineEdit8->setMaxLength(strlen(lineEdit8->text().toLatin1().data())); lineEdit9->setMaxLength(strlen(lineEdit9->text().toLatin1().data())); } else { lineEdit6->setMaxLength(80); lineEdit7->setMaxLength(80); lineEdit8->setMaxLength(80); lineEdit9->setMaxLength(80); } lineEdit6->setCursorPosition(cursorposition[0]); lineEdit7->setCursorPosition(cursorposition[1]); lineEdit8->setCursorPosition(cursorposition[2]); lineEdit9->setCursorPosition(cursorposition[3]); sprintf(str, "Characters left: %i", n); charsleft2Label->setText(str); } edfbrowser_157_source/PaxHeaders.7921/export_annotations.cpp0000644000000000000000000000013212646460742021330 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/export_annotations.cpp0000644000175000001440000005466112646460742021705 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "export_annotations.h" UI_ExportAnnotationswindow::UI_ExportAnnotationswindow(QWidget *w_parent) { int i; mainwindow = (UI_Mainwindow *)w_parent; ExportAnnotsDialog = new QDialog; ExportAnnotsDialog->setMinimumSize(800, 570); ExportAnnotsDialog->setMaximumSize(800, 570); ExportAnnotsDialog->setWindowTitle("Export annotations"); ExportAnnotsDialog->setModal(true); ExportAnnotsDialog->setAttribute(Qt::WA_DeleteOnClose, true); filelist = new QListWidget(ExportAnnotsDialog); filelist->setGeometry(10, 10, 780, 75); filelist->setSelectionBehavior(QAbstractItemView::SelectRows); filelist->setSelectionMode(QAbstractItemView::SingleSelection); for(i=0; ifiles_open; i++) { new QListWidgetItem(QString::fromLocal8Bit(mainwindow->edfheaderlist[i]->filename), filelist); } formatGroupBox = new QGroupBox("output format", ExportAnnotsDialog); formatGroupBox->setGeometry(10, 120, 200, 135); CSVRadioButton = new QRadioButton("ASCII/CSV"); EDFplusRadioButton = new QRadioButton("EDFplus"); XMLRadioButton = new QRadioButton("XML"); formatVBoxLayout = new QVBoxLayout; formatVBoxLayout->addWidget(CSVRadioButton); formatVBoxLayout->addWidget(EDFplusRadioButton); formatVBoxLayout->addWidget(XMLRadioButton); formatGroupBox->setLayout(formatVBoxLayout); fileGroupBox = new QGroupBox("export annotations", ExportAnnotsDialog); fileGroupBox->setGeometry(320, 120, 200, 90); selectRadioButton = new QRadioButton("from selected file"); selectRadioButton->setChecked(true); mergeRadioButton = new QRadioButton("from all files (merge)"); fileVBoxLayout = new QVBoxLayout; fileVBoxLayout->addWidget(selectRadioButton); fileVBoxLayout->addWidget(mergeRadioButton); fileGroupBox->setLayout(fileVBoxLayout); asciiSettingsGroupBox = new QGroupBox("ASCII settings", ExportAnnotsDialog); asciiSettingsGroupBox->setGeometry(10, 270, 300, 290); separatorLabel = new QLabel(ExportAnnotsDialog); separatorLabel->setText("separator:"); separatorBox = new QComboBox(ExportAnnotsDialog); separatorBox->addItem("comma"); separatorBox->addItem("tab"); asciiSecondsRadioButton = new QRadioButton("seconds relative to start of file"); asciiSecondsRadioButton->setChecked(true); asciiISOtimeRadioButton = new QRadioButton("ISO timestamp hh:mm:ss"); asciiISOtimedateRadioButton = new QRadioButton("ISO datetimestamp yyyy-mm-ddThh:mm:ss"); asciiISOtimeFractionRadioButton = new QRadioButton("ISO timestamp hh:mm:ss.xxx"); asciiISOtimedateFractionRadioButton = new QRadioButton("ISO datetimestamp yyyy-mm-ddThh:mm:ss.xxx"); durationCheckBox = new QCheckBox("include duration", ExportAnnotsDialog); durationCheckBox->setTristate(false); durationCheckBox->setCheckState(Qt::Unchecked); asciiSettingsHBoxLayout = new QHBoxLayout; asciiSettingsHBoxLayout->addWidget(separatorLabel); asciiSettingsHBoxLayout->addWidget(separatorBox); asciiSettingsVBoxLayout = new QVBoxLayout; asciiSettingsVBoxLayout->addLayout(asciiSettingsHBoxLayout); asciiSettingsVBoxLayout->addWidget(asciiSecondsRadioButton); asciiSettingsVBoxLayout->addWidget(asciiISOtimeRadioButton); asciiSettingsVBoxLayout->addWidget(asciiISOtimedateRadioButton); asciiSettingsVBoxLayout->addWidget(asciiISOtimeFractionRadioButton); asciiSettingsVBoxLayout->addWidget(asciiISOtimedateFractionRadioButton); asciiSettingsVBoxLayout->addWidget(durationCheckBox); asciiSettingsGroupBox->setLayout(asciiSettingsVBoxLayout); ExportButton = new QPushButton(ExportAnnotsDialog); ExportButton->setGeometry(500, 530, 100, 25); ExportButton->setText("Export"); CloseButton = new QPushButton(ExportAnnotsDialog); CloseButton->setGeometry(690, 530, 100, 25); CloseButton->setText("Close"); separatorBox->setCurrentIndex(mainwindow->export_annotations_var->separator); switch(mainwindow->export_annotations_var->format) { case 0 : EDFplusRadioButton->setChecked(true); asciiSettingsGroupBox->setEnabled(false); break; case 8 : XMLRadioButton->setChecked(true); asciiSettingsGroupBox->setEnabled(false); break; case 1 : CSVRadioButton->setChecked(true); asciiSettingsGroupBox->setEnabled(true); asciiSecondsRadioButton->setChecked(true); break; case 2 : CSVRadioButton->setChecked(true); asciiSettingsGroupBox->setEnabled(true); asciiISOtimeRadioButton->setChecked(true); break; case 3 : CSVRadioButton->setChecked(true); asciiSettingsGroupBox->setEnabled(true); asciiISOtimedateRadioButton->setChecked(true); break; case 4 : CSVRadioButton->setChecked(true); asciiSettingsGroupBox->setEnabled(true); asciiISOtimeFractionRadioButton->setChecked(true); break; case 5 : CSVRadioButton->setChecked(true); asciiSettingsGroupBox->setEnabled(true); asciiISOtimedateFractionRadioButton->setChecked(true); break; } if(mainwindow->export_annotations_var->duration) { durationCheckBox->setChecked(true); } else { durationCheckBox->setChecked(false); } QObject::connect(CloseButton, SIGNAL(clicked()), ExportAnnotsDialog, SLOT(close())); QObject::connect(ExportButton, SIGNAL(clicked()), this, SLOT(ExportButtonClicked())); QObject::connect(CSVRadioButton, SIGNAL(toggled(bool)), this, SLOT(outputformatRadioButtonClicked(bool))); filelist->setCurrentRow(mainwindow->files_open - 1); ExportAnnotsDialog->exec(); } void UI_ExportAnnotationswindow::outputformatRadioButtonClicked(bool checked) { if(checked == true) { asciiSettingsGroupBox->setEnabled(true); } else { asciiSettingsGroupBox->setEnabled(false); } } void UI_ExportAnnotationswindow::ExportButtonClicked() { int i, j, n, len, csv_format=0, hdl, annot_cnt, temp, include_duration; char path[MAX_PATH_LENGTH], str[1024], separator; FILE *annotationfile=NULL; struct annotationblock *annot, *annot_list; struct edfhdrblock *hdr; struct date_time_struct tm; if(CSVRadioButton->isChecked() == true) { if(asciiSecondsRadioButton->isChecked() == true) { csv_format = 1; } if(asciiISOtimeRadioButton->isChecked() == true) { csv_format = 2; } if(asciiISOtimedateRadioButton->isChecked() == true) { csv_format = 3; } if(asciiISOtimeFractionRadioButton->isChecked() == true) { csv_format = 4; } if(asciiISOtimedateFractionRadioButton->isChecked() == true) { csv_format = 5; } } if(EDFplusRadioButton->isChecked() == true) { csv_format = 0; } if(XMLRadioButton->isChecked() == true) { csv_format = 8; } mainwindow->export_annotations_var->format = csv_format; if(separatorBox->currentIndex() == 0) { separator = ','; mainwindow->export_annotations_var->separator = 0; } else { separator = '\t'; mainwindow->export_annotations_var->separator = 1; } if(durationCheckBox->checkState() == Qt::Checked) { include_duration = 1; mainwindow->export_annotations_var->duration = 1; } else { include_duration = 0; mainwindow->export_annotations_var->duration = 0; } if(!mainwindow->files_open) { ExportAnnotsDialog->close(); return; } if(filelist->count() < 1) { ExportAnnotsDialog->close(); return; } ExportButton->setEnabled(false); CloseButton->setEnabled(false); for(i=0; ifiles_open; i++) { if(!strcmp(mainwindow->edfheaderlist[i]->filename, filelist->item(filelist->currentRow())->text().toLocal8Bit().data())) { break; } } if(i==mainwindow->files_open) { ExportAnnotsDialog->close(); return; } n = i; if(mergeRadioButton->isChecked() == true) { n = mainwindow->sel_viewtime; } hdr = mainwindow->edfheaderlist[n]; path[0] = 0; if(mainwindow->recent_savedir[0]!=0) { strcpy(path, mainwindow->recent_savedir); strcat(path, "/"); } len = strlen(path); get_filename_from_path(path + len, mainwindow->edfheaderlist[n]->filename, MAX_PATH_LENGTH - len); remove_extension_from_filename(path); if((csv_format > 0) && (csv_format < 6)) { strcat(path, "_annotations.txt"); strcpy(path, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(path), "Text files (*.txt *.TXT *.csv *.CSV)").toLocal8Bit().data()); } if(csv_format == 8) { strcat(path, "_annotations.xml"); strcpy(path, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(path), "XML files (*.xml *.XML)").toLocal8Bit().data()); } if(csv_format == 0) { strcat(path, "_annotations.edf"); strcpy(path, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(path), "EDF files (*.edf *.EDF)").toLocal8Bit().data()); } if(!strcmp(path, "")) { ExportAnnotsDialog->close(); return; } get_directory_from_path(mainwindow->recent_savedir, path, MAX_PATH_LENGTH); if(mainwindow->file_is_opened(path)) { QMessageBox messagewindow(QMessageBox::Critical, "Export annotations", "Error, selected file is in use."); messagewindow.exec(); return; } annot_list = edfplus_annotation_copy_list(&mainwindow->annotationlist[n]); if(mergeRadioButton->isChecked() == true) { for(i=0; i < mainwindow->files_open; i++) { if(i != mainwindow->sel_viewtime) { annot_cnt = edfplus_annotation_count(&mainwindow->annotationlist[i]); for(j=0; j < annot_cnt; j++) { edfplus_annotation_add_copy(&annot_list, edfplus_annotation_item(&mainwindow->annotationlist[i], j)); annot = edfplus_annotation_item(&annot_list, edfplus_annotation_count(&annot_list) - 1); annot->onset -= (mainwindow->edfheaderlist[i]->viewtime - mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime); } } } edfplus_annotation_sort(&annot_list); } annot_cnt = edfplus_annotation_count(&annot_list); ///////////////////////////// CSV (text) export ////////////////////////////////////// if((csv_format > 0) && (csv_format < 6)) { annotationfile = fopeno(path, "wb"); if(annotationfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open annotationfile for writing."); messagewindow.exec(); ExportAnnotsDialog->close(); edfplus_annotation_delete_list(&annot_list); return; } if(include_duration) { fprintf(annotationfile, "Onset%cDuration%cAnnotation\n", separator, separator); } else { fprintf(annotationfile, "Onset%cAnnotation\n", separator); } for(j=0; j < annot_cnt; j++) { annot = edfplus_annotation_item(&annot_list, j); if(annot == NULL) { break; } strncpy(str, annot->annotation, 1024); str[1023] = 0; utf8_to_latin1(str); len = strlen(str); for(i=0; ionset - hdr->starttime_offset) / TIME_DIMENSION, separator, annot->duration, separator, str); } else { fprintf(annotationfile, "%+.7f%c%s\n", (double)(annot->onset - hdr->starttime_offset) / TIME_DIMENSION, separator, str); } } if(csv_format == 2) { temp = annot->onset % TIME_DIMENSION; if(temp < 0) { utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION) - 1, &tm); } else { utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION), &tm); } if(include_duration) { fprintf(annotationfile, "%02i:%02i:%02i%c%s%c%s\n", tm.hour, tm.minute, tm.second, separator, annot->duration, separator, str); } else { fprintf(annotationfile, "%02i:%02i:%02i%c%s\n", tm.hour, tm.minute, tm.second, separator, str); } } if(csv_format == 3) { temp = annot->onset % TIME_DIMENSION; if(temp < 0) { utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION) - 1, &tm); } else { utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION), &tm); } if(include_duration) { fprintf(annotationfile, "%04i-%02i-%02iT%02i:%02i:%02i%c%s%c%s\n", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second, separator, annot->duration, separator, str); } else { fprintf(annotationfile, "%04i-%02i-%02iT%02i:%02i:%02i%c%s\n", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second, separator, str); } } if(csv_format == 4) { temp = annot->onset % TIME_DIMENSION; if(temp < 0) { utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION) - 1, &tm); temp = TIME_DIMENSION + temp; } else { utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION), &tm); } if(include_duration) { fprintf(annotationfile, "%02i:%02i:%02i.%07i%c%s%c%s\n", tm.hour, tm.minute, tm.second, temp, separator, annot->duration, separator, str); } else { fprintf(annotationfile, "%02i:%02i:%02i.%07i%c%s\n", tm.hour, tm.minute, tm.second, temp, separator, str); } } if(csv_format == 5) { temp = annot->onset % TIME_DIMENSION; if(temp < 0) { utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION) - 1, &tm); temp = TIME_DIMENSION + temp; } else { utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION), &tm); } if(include_duration) { fprintf(annotationfile, "%04i-%02i-%02iT%02i:%02i:%02i.%07i%c%s%c%s\n", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second, temp, separator, annot->duration, separator, str); } else { fprintf(annotationfile, "%04i-%02i-%02iT%02i:%02i:%02i.%07i%c%s\n", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second, temp, separator, str); } } } fclose(annotationfile); edfplus_annotation_delete_list(&annot_list); QMessageBox messagewindow(QMessageBox::Information, "Ready", "Done."); messagewindow.setIconPixmap(QPixmap(":/images/ok.png")); messagewindow.exec(); ExportAnnotsDialog->close(); return; } ///////////////////////////// XML export ////////////////////////////////////// if(csv_format == 8) { annotationfile = fopeno(path, "wb"); if(annotationfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open annotationfile for writing."); messagewindow.exec(); ExportAnnotsDialog->close(); edfplus_annotation_delete_list(&annot_list); return; } fprintf(annotationfile, "\n"); fprintf(annotationfile, "\n"); fprintf(annotationfile, "\n"); utc_to_date_time(hdr->utc_starttime, &tm); fprintf(annotationfile, " %04i-%02i-%02iT%02i:%02i:%02i.%07i\n", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second, (int)hdr->starttime_offset); for(j=0; j < annot_cnt; j++) { annot = edfplus_annotation_item(&annot_list, j); if(annot == NULL) { break; } temp = annot->onset % TIME_DIMENSION; if(temp < 0) { utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION) - 1, &tm); temp = TIME_DIMENSION + temp; } else { utc_to_date_time(hdr->utc_starttime + (annot->onset / TIME_DIMENSION), &tm); } fprintf(annotationfile, " \n" " %04i-%02i-%02iT%02i:%02i:%02i.%07i\n" " %s\n" " ", tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second, temp, annot->duration); xml_fwrite_encode_entity(annotationfile, annot->annotation); fprintf(annotationfile, "\n" " \n"); } fprintf(annotationfile, "\n"); fclose(annotationfile); edfplus_annotation_delete_list(&annot_list); QMessageBox messagewindow(QMessageBox::Information, "Ready", "Done."); messagewindow.setIconPixmap(QPixmap(":/images/ok.png")); messagewindow.exec(); ExportAnnotsDialog->close(); return; } ///////////////////////////// EDFplus export ////////////////////////////////////// if(csv_format == 0) { hdl = edfopen_file_writeonly(path, EDFLIB_FILETYPE_EDFPLUS, 0); if(hdl < 0) { switch(hdl) { case EDFLIB_MALLOC_ERROR : strcpy(str, "EDFlib: malloc error"); break; case EDFLIB_NO_SUCH_FILE_OR_DIRECTORY : strcpy(str, "EDFlib: no such file or directory"); break; case EDFLIB_MAXFILES_REACHED : strcpy(str, "EDFlib: maximum files reached"); break; case EDFLIB_FILE_ALREADY_OPENED : strcpy(str, "EDFlib: file already opened"); break; case EDFLIB_NUMBER_OF_SIGNALS_INVALID : strcpy(str, "EDFlib: number of signals is invalid"); break; default : strcpy(str, "EDFlib: unknown error"); break; } QMessageBox messagewindow(QMessageBox::Critical, "Error", str); messagewindow.exec(); edfplus_annotation_delete_list(&annot_list); ExportAnnotsDialog->close(); return; } utc_to_date_time(hdr->utc_starttime, &tm); edf_set_startdatetime(hdl, tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second); if((hdr->edfplus) || (hdr->bdfplus)) { edf_set_patientname(hdl, hdr->plus_patient_name); edf_set_patientcode(hdl, hdr->plus_patientcode); if(!(strcmp(hdr->plus_gender, "Male"))) { edf_set_gender(hdl, 1); } if(!(strcmp(hdr->plus_gender, "Female"))) { edf_set_gender(hdl, 0); } if(hdr->plus_birthdate[0] != 0) { if(!(strncmp(hdr->plus_birthdate + 3, "jan", 3))) n = 1; if(!(strncmp(hdr->plus_birthdate + 3, "feb", 3))) n = 2; if(!(strncmp(hdr->plus_birthdate + 3, "mar", 3))) n = 3; if(!(strncmp(hdr->plus_birthdate + 3, "apr", 3))) n = 4; if(!(strncmp(hdr->plus_birthdate + 3, "may", 3))) n = 5; if(!(strncmp(hdr->plus_birthdate + 3, "jun", 3))) n = 6; if(!(strncmp(hdr->plus_birthdate + 3, "jul", 3))) n = 7; if(!(strncmp(hdr->plus_birthdate + 3, "aug", 3))) n = 8; if(!(strncmp(hdr->plus_birthdate + 3, "sep", 3))) n = 9; if(!(strncmp(hdr->plus_birthdate + 3, "oct", 3))) n = 10; if(!(strncmp(hdr->plus_birthdate + 3, "nov", 3))) n = 11; if(!(strncmp(hdr->plus_birthdate + 3, "dec", 3))) n = 12; edf_set_birthdate(hdl, atoi(hdr->plus_birthdate + 7), n, atoi(hdr->plus_birthdate)); } edf_set_patient_additional(hdl, hdr->plus_patient_additional); edf_set_admincode(hdl, hdr->plus_admincode); edf_set_technician(hdl, hdr->plus_technician); edf_set_equipment(hdl, hdr->plus_equipment); edf_set_recording_additional(hdl, hdr->plus_recording_additional); } else { edf_set_patientname(hdl, hdr->patient); edf_set_recording_additional(hdl, hdr->recording); } int hasdot, decimals; for(j=0; j < annot_cnt; j++) { annot = edfplus_annotation_item(&annot_list, j); if(annot == NULL) { break; } if(annot->duration[0] == 0) { edfwrite_annotation_utf8(hdl, annot->onset / 1000LL, -1LL, annot->annotation); } else { strcpy(str, annot->duration); len = strlen(str); hasdot = 0; for(i=0; ionset / 1000LL, atoi(str), annot->annotation); } } if(edfclose_file(hdl) != 0) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred: edfclose_file()"); messagewindow.exec(); } edfplus_annotation_delete_list(&annot_list); QMessageBox messagewindow(QMessageBox::Information, "Ready", "Done."); messagewindow.setIconPixmap(QPixmap(":/images/ok.png")); messagewindow.exec(); ExportAnnotsDialog->close(); } } edfbrowser_157_source/PaxHeaders.7921/filteredblockread.cpp0000644000000000000000000000013212646460742021037 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/filteredblockread.cpp0000644000175000001440000001364512646460742021411 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "filteredblockread.h" double * FilteredBlockReadClass::init_signalcomp(struct signalcompblock *i_signalcomp, int i_datarecord_cnt, int skip_f) { skip_filters = skip_f; if(i_signalcomp == NULL) { datarecord_cnt = -1; total_samples = -1; return(NULL); } signalcomp = i_signalcomp; hdr = signalcomp->edfhdr; if(hdr == NULL) { datarecord_cnt = -1; total_samples = -1; return(NULL); } inputfile = hdr->file_hdl; if(inputfile == NULL) { datarecord_cnt = -1; total_samples = -1; return(NULL); } datarecord_cnt = i_datarecord_cnt; if((datarecord_cnt > hdr->datarecords) || (datarecord_cnt < 1)) { datarecord_cnt = -1; total_samples = -1; return(NULL); } samples_per_datrec = hdr->edfparam[signalcomp->edfsignal[0]].smp_per_record; total_samples = samples_per_datrec * datarecord_cnt; if(processed_samples_buf != NULL) { free(processed_samples_buf); } processed_samples_buf = (double *)malloc(total_samples * sizeof(double)); if(processed_samples_buf == NULL) { datarecord_cnt = -1; total_samples = -1; return(NULL); } if(readbuf != NULL) { free(readbuf); } readbuf = (char *)malloc(hdr->recordsize * datarecord_cnt); if(readbuf == NULL) { datarecord_cnt = -1; total_samples = -1; free(processed_samples_buf); processed_samples_buf = NULL; return(NULL); } bitvalue = signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue; return(processed_samples_buf); } int FilteredBlockReadClass::samples_in_buf(void) { return(total_samples); } FilteredBlockReadClass::FilteredBlockReadClass() { readbuf = NULL; processed_samples_buf = NULL; datarecord_cnt = -1; total_samples = -1; inputfile = NULL; hdr = NULL; signalcomp = NULL; } FilteredBlockReadClass::~FilteredBlockReadClass() { if(processed_samples_buf != NULL) { free(processed_samples_buf); } if(readbuf != NULL) { free(readbuf); } } int FilteredBlockReadClass::process_signalcomp(int datarecord_start) { int j, k, s; double dig_value=0.0, f_tmp=0.0; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; if((total_samples < 1) || (datarecord_cnt < 1)) { return(-1); } if((datarecord_start < 0) || (datarecord_start >= hdr->datarecords)) { return(-1); } if(datarecord_cnt > (hdr->datarecords - datarecord_start)) { return(-1); } if(fseeko(inputfile, ((long long)hdr->hdrsize) + (((long long)datarecord_start) * ((long long) hdr->recordsize)), SEEK_SET) == -1LL) { return(-1); } if(fread(readbuf, hdr->recordsize * datarecord_cnt, 1, inputfile) != 1) { return(-1); } if((readbuf == NULL) || (processed_samples_buf == NULL)) { return(-1); } for(s=0; snum_of_signals; j++) { if(signalcomp->edfhdr->bdf) { var.two[0] = *((unsigned short *)( readbuf + (signalcomp->edfhdr->recordsize * (s / samples_per_datrec)) + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset + ((s % samples_per_datrec) * 3))); var.four[2] = *((unsigned char *)( readbuf + (signalcomp->edfhdr->recordsize * (s / samples_per_datrec)) + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset + ((s % samples_per_datrec) * 3) + 2)); if(var.four[2]&0x80) { var.four[3] = 0xff; } else { var.four[3] = 0x00; } f_tmp = var.one_signed; } if(signalcomp->edfhdr->edf) { f_tmp = *(((short *)( readbuf + (signalcomp->edfhdr->recordsize * (s / samples_per_datrec)) + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset)) + (s % samples_per_datrec)); } f_tmp += signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].offset; f_tmp *= signalcomp->factor[j]; dig_value += f_tmp; } if(!skip_filters) { if(signalcomp->spike_filter) { dig_value = run_spike_filter(dig_value, signalcomp->spike_filter); } for(k=0; kfilter_cnt; k++) { dig_value = first_order_filter(dig_value, signalcomp->filter[k]); } for(k=0; kravg_filter_cnt; k++) { dig_value = run_ravg_filter(dig_value, signalcomp->ravg_filter[k]); } for(k=0; kfidfilter_cnt; k++) { dig_value = signalcomp->fidfuncp[k](signalcomp->fidbuf[k], dig_value); } if(signalcomp->ecg_filter != NULL) { dig_value = run_ecg_filter(dig_value, signalcomp->ecg_filter); } } processed_samples_buf[s] = (dig_value * bitvalue); } return(0); } edfbrowser_157_source/PaxHeaders.7921/nexfin2edf.cpp0000644000000000000000000000012712646460742017426 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/nexfin2edf.cpp0000644000175000001440000005340712646460742017774 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "nexfin2edf.h" UI_NEXFIN2EDFwindow::UI_NEXFIN2EDFwindow(char *recent_dir, char *save_dir) { recent_opendir = recent_dir; recent_savedir = save_dir; myobjectDialog = new QDialog; myobjectDialog->setMinimumSize(600, 280); myobjectDialog->setMaximumSize(600, 280); myobjectDialog->setWindowTitle("Nexfin to EDF converter"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); PatientnameLabel = new QLabel(myobjectDialog); PatientnameLabel->setGeometry(20, 20, 140, 25); PatientnameLabel->setText("Subject name"); RecordingLabel = new QLabel(myobjectDialog); RecordingLabel->setGeometry(20, 55, 140, 25); RecordingLabel->setText("Recording"); DatetimeLabel = new QLabel(myobjectDialog); DatetimeLabel->setGeometry(20, 90, 140, 25); DatetimeLabel->setText("Startdate and time"); PatientnameLineEdit = new QLineEdit(myobjectDialog); PatientnameLineEdit->setGeometry(160, 20, 420, 25); PatientnameLineEdit->setMaxLength(80); RecordingLineEdit = new QLineEdit(myobjectDialog); RecordingLineEdit->setGeometry(160, 55, 420, 25); RecordingLineEdit->setMaxLength(80); RecordingLineEdit->setText("Nexfin"); StartDatetimeedit = new QDateTimeEdit(myobjectDialog); StartDatetimeedit->setGeometry(160, 90, 140, 25); StartDatetimeedit->setDisplayFormat("dd/MM/yyyy hh:mm:ss"); StartDatetimeedit->setDateTime(QDateTime::currentDateTime()); pushButton1 = new QPushButton(myobjectDialog); pushButton1->setGeometry(20, 230, 100, 25); pushButton1->setText("Select File"); pushButton2 = new QPushButton(myobjectDialog); pushButton2->setGeometry(480, 230, 100, 25); pushButton2->setText("Close"); radio100button = new QRadioButton(myobjectDialog); radio100button->setGeometry(160, 130, 200, 20); radio100button->setText("Beat-to-beat data"); radio100button->setChecked(true); radio103button = new QRadioButton(myobjectDialog); radio103button->setGeometry(160, 160, 200, 20); radio103button->setText("Blood pressure waveform"); radio032button = new QRadioButton(myobjectDialog); radio032button->setGeometry(160, 190, 200, 20); radio032button->setText("Analog inputs"); analoginputscombobox = new QComboBox(myobjectDialog); analoginputscombobox->setGeometry(280, 190, 80, 25); analoginputscombobox->addItem("1 input"); analoginputscombobox->addItem("4 inputs"); analoginputscombobox->setCurrentIndex(1); analoginputscombobox->setEnabled(false); QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton())); QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close())); QObject::connect(radio032button, SIGNAL(toggled(bool)), this, SLOT(radiobuttonchecked(bool))); myobjectDialog->exec(); } void UI_NEXFIN2EDFwindow::SelectFileButton() { FILE *inputfile=NULL, *outputfile=NULL; int i, j, k, p, temp, separator=';', edfsignals=0, ok, timestep, new_smpl_time=0, str_start, column, line_nr; long long datarecords=-1LL, file_size; char txt_string[2048], path[512], outputfilename[MAX_PATH_LENGTH], line[2048], scratchpad[128], labels[MAX_SIGNALS][17], phys_dim[MAX_SIGNALS][9], phys_min[MAX_SIGNALS][9], phys_max[MAX_SIGNALS][9], patientname[81], recording[81], datetime[17]; double sensitivity[MAX_SIGNALS], new_value[MAX_SIGNALS], old_value[MAX_SIGNALS]; union{ short two; char one[2]; } var; if(radio100button->isChecked()==true) { file_type = 100; } if(radio103button->isChecked()==true) { file_type = 103; } if(radio032button->isChecked()==true) { file_type = 32; } for(j=0; jtext().toLatin1().data()))) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a subject name."); messagewindow.exec(); enable_widgets(true); return; } if(!(strlen(RecordingLineEdit->text().toLatin1().data()))) { QMessageBox messagewindow(QMessageBox::Critical, "Invalid input", "Please enter a recordingdescription."); messagewindow.exec(); enable_widgets(true); return; } if(file_type==100) { strcpy(path, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "CSV files (*_100.csv *_100.CSV)").toLocal8Bit().data()); } if(file_type==103) { strcpy(path, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "BIN files (*_103.bin *_103.BIN)").toLocal8Bit().data()); } if(file_type==32) { strcpy(path, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "BIN files (*_032.bin *_032.BIN)").toLocal8Bit().data()); } if(!strcmp(path, "")) { enable_widgets(true); return; } get_directory_from_path(recent_opendir, path, MAX_PATH_LENGTH); inputfile = fopeno(path, "rb"); if(inputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for reading.", path); QMessageBox messagewindow(QMessageBox::Critical, "Error", QString::fromLocal8Bit(txt_string)); messagewindow.exec(); enable_widgets(true); return; } if(file_type==100) { /***************** check if the txtfile is valid ******************************/ rewind(inputfile); if(fread(scratchpad, 32, 1, inputfile)!=1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not read from file."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(strncmp(scratchpad, "Time;IBI;HR;LVET;HRS;Sys;Dia;MAP", 32)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Unknown data in file (1)."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } /***************** collect items *****************************************/ rewind(inputfile); while(1) { temp = fgetc(inputfile); if(temp==EOF) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Reached end of file unexpectedly (5)."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(temp==separator) { break; } } i = 0; while(temp!='\n') { temp = fgetc(inputfile); if(temp==EOF) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Reached end of file unexpectedly (6)."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } if(temp=='\r') { continue; } if(((temp==separator)||(temp=='\n'))&&(edfsignals<7)) { if(edfsignals>=MAX_SIGNALS) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Too many labels/signals (7)."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } line[i] = 0; ok = 0; if(!strcmp(line, "IBI")) { strcpy(labels[edfsignals], "IBI "); strcpy(phys_dim[edfsignals], "s "); strcpy(phys_min[edfsignals], "-31.744 "); strcpy(phys_max[edfsignals], "31.744 "); sensitivity[edfsignals] = 1000.0; ok = 1; } if(!strcmp(line, "HR")) { strcpy(labels[edfsignals], "HR "); strcpy(phys_dim[edfsignals], "bpm "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "LVET")) { strcpy(labels[edfsignals], "LVET "); strcpy(phys_dim[edfsignals], "s "); strcpy(phys_min[edfsignals], "-10 "); strcpy(phys_max[edfsignals], "10 "); sensitivity[edfsignals] = 3174.4; ok = 1; } if(!strcmp(line, "HRS")) { strcpy(labels[edfsignals], "HRS "); strcpy(phys_dim[edfsignals], "mmHg "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "Sys")) { strcpy(labels[edfsignals], "Sys "); strcpy(phys_dim[edfsignals], "mmHg "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "Dia")) { strcpy(labels[edfsignals], "Dia "); strcpy(phys_dim[edfsignals], "mmHg "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!strcmp(line, "MAP")) { strcpy(labels[edfsignals], "MAP "); strcpy(phys_dim[edfsignals], "mmHg "); strcpy(phys_min[edfsignals], "-1024 "); strcpy(phys_max[edfsignals], "1024 "); sensitivity[edfsignals] = 31.0; ok = 1; } if(!ok) { snprintf(txt_string, 2048, "Found unknown label/signal: %s", line); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } edfsignals++; i = 0; } if(temp==separator) { continue; } line[i++] = temp; } if(!edfsignals) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There are no labels/signals."); messagewindow.exec(); fclose(inputfile); enable_widgets(true); return; } } /********** end if(file_type==100) ********************/ if(file_type==103) { edfsignals = 1; } if(file_type==32) { if(analoginputscombobox->currentIndex()==1) { edfsignals = 4; } else { edfsignals = 1; } } p = sprintf(patientname, "%s", PatientnameLineEdit->text().toLatin1().data()); latin1_to_ascii(patientname, p); for( ; p<80; p++) { patientname[p] = ' '; } patientname[80] = 0; p = sprintf(recording, "%s", RecordingLineEdit->text().toLatin1().data()); latin1_to_ascii(recording, p); for( ; p<80; p++) { recording[p] = ' '; } recording[80] = 0; sprintf(datetime, "%02i.%02i.%02i%02i.%02i.%02i", StartDatetimeedit->date().day(), StartDatetimeedit->date().month(), StartDatetimeedit->date().year() % 100, StartDatetimeedit->time().hour(), StartDatetimeedit->time().minute(), StartDatetimeedit->time().second()); datetime[16] = 0; /***************** write header *****************************************/ get_filename_from_path(outputfilename, path, MAX_PATH_LENGTH); remove_extension_from_filename(outputfilename); strcat(outputfilename, ".edf"); path[0] = 0; if(recent_savedir[0]!=0) { strcpy(path, recent_savedir); strcat(path, "/"); } strcat(path, outputfilename); strcpy(path, QFileDialog::getSaveFileName(0, "Output file", QString::fromLocal8Bit(path), "EDF files (*.edf *.EDF)").toLocal8Bit().data()); if(!strcmp(path, "")) { enable_widgets(true); fclose(inputfile); return; } get_directory_from_path(recent_savedir, path, MAX_PATH_LENGTH); outputfile = fopeno(path, "wb"); if(outputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for writing.", path); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); enable_widgets(true); fclose(inputfile); return; } fprintf(outputfile, "0 "); fprintf(outputfile, "%s", patientname); fprintf(outputfile, "%s", recording); fprintf(outputfile, "%s", datetime); fprintf(outputfile, "%-8i", 256 * edfsignals + 256); fprintf(outputfile, " "); fprintf(outputfile, "-1 "); if(file_type==100) { fprintf(outputfile, "0.01 "); } if(file_type==103) { fprintf(outputfile, "0.005 "); } if(file_type==32) { fprintf(outputfile, "0.005 "); } fprintf(outputfile, "%-4i", edfsignals); if(file_type==100) { for(i=0; i0) break; } QApplication::setOverrideCursor(Qt::WaitCursor); for(k=0; k<10; k++) qApp->processEvents(); i = 0; column = 0; datarecords = 0LL; str_start = 0; line_nr = 1; while(1) { temp = fgetc(inputfile); if(temp==EOF) { for(k=0; k31744) temp = 31744; if(temp<-31744) temp = -31744; var.two = (short)temp; fputc(var.one[0], outputfile); fputc(var.one[1], outputfile); } datarecords++; break; } line[i] = temp; /**************************************/ if(line[i]==',') { line[i] = '.'; } if((line[i]==separator)||(line[i]=='\n')) { if(column) { new_value[column-1] = atof(line + str_start); } else { new_smpl_time = (int)(atof(line + str_start) * 100.0); } if(line[i]=='\n') { /**************************************/ line_nr++; if(column!=edfsignals) { QApplication::restoreOverrideCursor(); snprintf(txt_string, 2048, "Number of separators in line %i is wrong.", line_nr); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); fclose(inputfile); fclose(outputfile); enable_widgets(true); return; } timestep = new_smpl_time - datarecords; if(timestep<=0) { QApplication::restoreOverrideCursor(); snprintf(txt_string, 2048, "Timestep <= 0 in line %i.", line_nr); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); fclose(inputfile); fclose(outputfile); enable_widgets(true); return; } for(j=0; j31744) temp = 31744; if(temp<-31744) temp = -31744; var.two = (short)temp; fputc(var.one[0], outputfile); fputc(var.one[1], outputfile); } datarecords++; } for(j=0; j2046) { QApplication::restoreOverrideCursor(); snprintf(txt_string, 2048, "Line %i is too long.", line_nr); QMessageBox messagewindow(QMessageBox::Critical, "Error", txt_string); messagewindow.exec(); fclose(inputfile); fclose(outputfile); enable_widgets(true); return; } } } /********** end if(file_type==100) ********************/ if((file_type==103) || (file_type==32)) { fseeko(inputfile, 0LL, SEEK_END); file_size = ftello(inputfile); file_size /= 2LL; file_size /= edfsignals; rewind(inputfile); QApplication::setOverrideCursor(Qt::WaitCursor); for(k=0; k<10; k++) qApp->processEvents(); if(file_type==103) { for(datarecords=0LL; datarecordssetEnabled(toggle); PatientnameLineEdit->setEnabled(toggle); RecordingLineEdit->setEnabled(toggle); pushButton1->setEnabled(toggle); pushButton2->setEnabled(toggle); } void UI_NEXFIN2EDFwindow::radiobuttonchecked(bool checked) { if(checked==true) { analoginputscombobox->setEnabled(true); } else { analoginputscombobox->setEnabled(false); } } edfbrowser_157_source/PaxHeaders.7921/show_actual_montage_dialog.cpp0000644000000000000000000000012712646460742022740 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/show_actual_montage_dialog.cpp0000644000175000001440000002361712646460742023306 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "show_actual_montage_dialog.h" UI_ShowActualMontagewindow::UI_ShowActualMontagewindow(QWidget *w_parent) { int i, j, type, model, order; char txtbuf[2048]; double frequency, frequency2, ripple; QStandardItem *parentItem, *signalItem, *filterItem; mainwindow = (UI_Mainwindow *)w_parent; ShowMontageDialog = new QDialog; ShowMontageDialog->setMinimumSize(500, 300); ShowMontageDialog->resize(500, 440); ShowMontageDialog->setWindowTitle("Show montage"); ShowMontageDialog->setModal(true); ShowMontageDialog->setAttribute(Qt::WA_DeleteOnClose, true); tree = new QTreeView; tree->setHeaderHidden(true); tree->setIndentation(30); tree->setSelectionMode(QAbstractItemView::NoSelection); tree->setEditTriggers(QAbstractItemView::NoEditTriggers); tree->setSortingEnabled(false); tree->setDragDropMode(QAbstractItemView::NoDragDrop); CloseButton = new QPushButton; CloseButton->setFixedSize(100, 25); CloseButton->setText("Close"); box = new QBoxLayout(QBoxLayout::TopToBottom, ShowMontageDialog); box->addWidget(tree); box->addWidget(CloseButton, 0, Qt::AlignRight); QObject::connect(CloseButton, SIGNAL(clicked()), ShowMontageDialog, SLOT(close())); t_model = new QStandardItemModel(this); parentItem = t_model->invisibleRootItem(); for(i=0; isignalcomps; i++) { txtbuf[0] = 0; if(mainwindow->signalcomp[i]->alias[0] != 0) { strcpy(txtbuf, "alias: "); strcat(txtbuf, mainwindow->signalcomp[i]->alias); strcat(txtbuf, " "); } for(j=0; jsignalcomp[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, " "); } if(mainwindow->signalcomp[i]->polarity == -1) { strcat(txtbuf, "Inverted: yes"); } signalItem = new QStandardItem(txtbuf); parentItem->appendRow(signalItem); sprintf(txtbuf, "amplitude: %f", mainwindow->signalcomp[i]->voltpercm); strcat(txtbuf, mainwindow->signalcomp[i]->physdimension); remove_trailing_spaces(txtbuf); sprintf(txtbuf + strlen(txtbuf), "/cm offset: %f%s", mainwindow->signalcomp[i]->screen_offset * mainwindow->pixelsizefactor * mainwindow->signalcomp[i]->voltpercm, mainwindow->signalcomp[i]->physdimension); remove_trailing_zeros(txtbuf); remove_trailing_spaces(txtbuf); strcat(txtbuf, " color: "); switch(mainwindow->signalcomp[i]->color) { case Qt::white : strcat(txtbuf, "white"); break; case Qt::black : strcat(txtbuf, "black"); break; case Qt::red : strcat(txtbuf, "red"); break; case Qt::darkRed : strcat(txtbuf, "dark red"); break; case Qt::green : strcat(txtbuf, "green"); break; case Qt::darkGreen : strcat(txtbuf, "dark green"); break; case Qt::blue : strcat(txtbuf, "blue"); break; case Qt::darkBlue : strcat(txtbuf, "dark blue"); break; case Qt::cyan : strcat(txtbuf, "cyan"); break; case Qt::darkCyan : strcat(txtbuf, "dark cyan"); break; case Qt::magenta : strcat(txtbuf, "magenta"); break; case Qt::darkMagenta : strcat(txtbuf, "dark magenta"); break; case Qt::yellow : strcat(txtbuf, "yellow"); break; case Qt::darkYellow : strcat(txtbuf, "dark yellow"); break; case Qt::gray : strcat(txtbuf, "gray"); break; case Qt::darkGray : strcat(txtbuf, "dark gray"); break; case Qt::lightGray : strcat(txtbuf, "light gray"); break; } signalItem->appendRow(new QStandardItem(txtbuf)); filterItem = new QStandardItem("Filters"); signalItem->appendRow(filterItem); 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; jsignalcomp[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; jsignalcomp[i]->ravg_filter_cnt; j++) { if(mainwindow->signalcomp[i]->ravg_filter_type[j] == 0) { sprintf(txtbuf, "highpass moving average %i smpls", mainwindow->signalcomp[i]->ravg_filter[j]->size); } if(mainwindow->signalcomp[i]->ravg_filter_type[j] == 1) { sprintf(txtbuf, "lowpass moving average %i smpls", mainwindow->signalcomp[i]->ravg_filter[j]->size); } filterItem->appendRow(new QStandardItem(txtbuf)); } for(j=0; jsignalcomp[i]->fidfilter_cnt; j++) { 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]->zratio_filter != NULL) { sprintf(txtbuf, "Z-ratio cross-over frequency is %.1f Hz", mainwindow->signalcomp[i]->zratio_crossoverfreq); filterItem->appendRow(new QStandardItem(txtbuf)); } } sprintf(txtbuf, "timescale: %f seconds", (double)mainwindow->pagetime / (double)TIME_DIMENSION); remove_trailing_zeros(txtbuf); parentItem->appendRow(new QStandardItem(txtbuf)); tree->setModel(t_model); tree->expandAll(); ShowMontageDialog->exec(); } edfbrowser_157_source/PaxHeaders.7921/filteredblockread.h0000644000000000000000000000012712646460742020510 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/filteredblockread.h0000644000175000001440000000334212646460742021047 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef filteredblockread_INCLUDED #define filteredblockread_INCLUDED #include #include #include #include "global.h" #include "filter.h" #include "spike_filter.h" #include "ravg_filter.h" #include "third_party/fidlib/fidlib.h" class FilteredBlockReadClass { private: FILE *inputfile; struct edfhdrblock *hdr; struct signalcompblock *signalcomp; int datarecord_cnt, samples_per_datrec, total_samples, skip_filters; char *readbuf; double *processed_samples_buf, bitvalue; public: double * init_signalcomp(struct signalcompblock *, int, int); int process_signalcomp(int); int samples_in_buf(void); FilteredBlockReadClass(); ~FilteredBlockReadClass(); }; #endif edfbrowser_157_source/PaxHeaders.7921/viewbuf.cpp0000644000000000000000000000013212646460742017041 xustar0030 mtime=1452958178.249246726 30 atime=1452958178.249246726 30 ctime=1452958178.249246726 edfbrowser_157_source/viewbuf.cpp0000644000175000001440000006631512646460742017415 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "mainwindow.h" void UI_Mainwindow::setup_viewbuf() { int i, j, k, r, s, temp=0, skip, totalsize, hasprefilter=0, readsize=0, dif; double pre_time=0.0, d_temp, dig_value; long long l_temp, datarecords; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; struct date_time_struct date_time_str; for(i=0; iprefiltertime = 0; for(i=0; ifilter_cnt) { hasprefilter = 1; for(k=0; kfilter_cnt; k++) { if(pre_time < (1.0 / signalcomp[i]->filter[k]->cutoff_frequency)) { pre_time = (1.0 / signalcomp[i]->filter[k]->cutoff_frequency); } } } if(signalcomp[i]->spike_filter) { hasprefilter = 1; if(pre_time < 5.0) { pre_time = 5.0; } } if(signalcomp[i]->ravg_filter_cnt) { hasprefilter = 1; for(k=0; kravg_filter_cnt; k++) { if(pre_time < ((double)(signalcomp[i]->ravg_filter[k]->size + 3) / ((double)signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record / signalcomp[i]->edfhdr->data_record_duration))) { pre_time = (double)(signalcomp[i]->ravg_filter[k]->size + 3) / ((double)signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record / signalcomp[i]->edfhdr->data_record_duration); } } } if(signalcomp[i]->ecg_filter != NULL) { hasprefilter = 1; if(pre_time < 10.0) { pre_time = 10.0; } } if(signalcomp[i]->zratio_filter != NULL) { hasprefilter = 1; if(pre_time < 4.0) { pre_time = 4.0; } } if(signalcomp[i]->fidfilter_cnt) { hasprefilter = 1; for(k=0; kfidfilter_cnt; k++) { if(pre_time < ((2.0 * signalcomp[i]->fidfilter_order[k]) / signalcomp[i]->fidfilter_freq[k])) { pre_time = (2.0 * signalcomp[i]->fidfilter_order[k]) / signalcomp[i]->fidfilter_freq[k]; } } } } if(hasprefilter) { for(i=0; ifilter_cnt) || (signalcomp[i]->spike_filter) || (signalcomp[i]->ravg_filter_cnt) || (signalcomp[i]->fidfilter_cnt) || (signalcomp[i]->ecg_filter != NULL) || (signalcomp[i]->zratio_filter != NULL)) { signalcomp[i]->edfhdr->prefiltertime = (long long)(pre_time * ((double)TIME_DIMENSION)); if(signalcomp[i]->edfhdr->prefiltertime>signalcomp[i]->edfhdr->viewtime) { signalcomp[i]->edfhdr->prefiltertime = signalcomp[i]->edfhdr->viewtime; if(signalcomp[i]->edfhdr->prefiltertime<0) signalcomp[i]->edfhdr->prefiltertime = 0; } } } totalsize = 0; for(i=0; iedfhdr->prefiltertime) signalcomp[i]->records_in_viewbuf = (signalcomp[i]->edfhdr->viewtime / signalcomp[i]->edfhdr->long_data_record_duration) - ((signalcomp[i]->edfhdr->viewtime - signalcomp[i]->edfhdr->prefiltertime) / signalcomp[i]->edfhdr->long_data_record_duration) + 1; else signalcomp[i]->records_in_viewbuf = 0; signalcomp[i]->viewbufsize = signalcomp[i]->records_in_viewbuf * signalcomp[i]->edfhdr->recordsize; if(signalcomp[i]->edfhdr->prefiltertime) { signalcomp[i]->samples_in_prefilterbuf = (signalcomp[i]->records_in_viewbuf - 1) * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record; signalcomp[i]->samples_in_prefilterbuf += (int)(((double)(signalcomp[i]->edfhdr->viewtime % signalcomp[i]->edfhdr->long_data_record_duration) / (double)signalcomp[i]->edfhdr->long_data_record_duration) * (double)signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record); } else { signalcomp[i]->samples_in_prefilterbuf = 0; } if(!i) { signalcomp[i]->viewbufoffset = 0; totalsize = signalcomp[i]->viewbufsize; } else { skip = 0; for(j=0; jedfhdr->file_hdl==signalcomp[j]->edfhdr->file_hdl) { skip = 1; signalcomp[i]->viewbufoffset = signalcomp[j]->viewbufoffset; signalcomp[i]->records_in_viewbuf = signalcomp[j]->records_in_viewbuf; signalcomp[i]->viewbufsize = signalcomp[j]->viewbufsize; break; } } if(!skip) { signalcomp[i]->viewbufoffset = signalcomp[i-1]->viewbufoffset + signalcomp[i-1]->viewbufsize; totalsize += signalcomp[i]->viewbufsize; } } } if(viewbuf!=NULL) { free(viewbuf); viewbuf = NULL; } viewbuf = (char *)malloc(totalsize); if(viewbuf==NULL) { live_stream_active = 0; QMessageBox messagewindow(QMessageBox::Critical, "Error", "Internal error: Memory allocation error:\n\"prefilterbuf\""); messagewindow.exec(); remove_all_signals(); return; } for(i=0; iedfhdr->viewtime - signalcomp[i]->edfhdr->prefiltertime) / signalcomp[i]->edfhdr->long_data_record_duration; signalcomp[i]->prefilter_starttime = datarecords * signalcomp[i]->edfhdr->long_data_record_duration; if((signalcomp[i]->viewbufsize>0)&&(datarecordsedfhdr->datarecords)) { fseeko(signalcomp[i]->edfhdr->file_hdl, (long long)(signalcomp[i]->edfhdr->hdrsize + (datarecords * signalcomp[i]->edfhdr->recordsize)), SEEK_SET); if(signalcomp[i]->viewbufsize>((signalcomp[i]->edfhdr->datarecords - datarecords) * signalcomp[i]->edfhdr->recordsize)) { signalcomp[i]->viewbufsize = (signalcomp[i]->edfhdr->datarecords - datarecords) * signalcomp[i]->edfhdr->recordsize; } if(fread(viewbuf + signalcomp[i]->viewbufoffset, signalcomp[i]->viewbufsize, 1, signalcomp[i]->edfhdr->file_hdl)!=1) { live_stream_active = 0; QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read error occurred. 2"); messagewindow.exec(); remove_all_signals(); return; } } } else { skip = 0; for(j=0; jedfhdr->file_hdl==signalcomp[j]->edfhdr->file_hdl) { skip = 1; break; } } if(!skip) { datarecords = (signalcomp[i]->edfhdr->viewtime - signalcomp[i]->edfhdr->prefiltertime) / signalcomp[i]->edfhdr->long_data_record_duration; signalcomp[i]->prefilter_starttime = datarecords * signalcomp[i]->edfhdr->long_data_record_duration; if((signalcomp[i]->viewbufsize>0)&&(datarecordsedfhdr->datarecords)) { fseeko(signalcomp[i]->edfhdr->file_hdl, (long long)(signalcomp[i]->edfhdr->hdrsize + (datarecords * signalcomp[i]->edfhdr->recordsize)), SEEK_SET); if(signalcomp[i]->viewbufsize>((signalcomp[i]->edfhdr->datarecords - datarecords) * signalcomp[i]->edfhdr->recordsize)) { signalcomp[i]->viewbufsize = (signalcomp[i]->edfhdr->datarecords - datarecords) * signalcomp[i]->edfhdr->recordsize; } if(fread(viewbuf + signalcomp[i]->viewbufoffset, signalcomp[i]->viewbufsize, 1, signalcomp[i]->edfhdr->file_hdl)!=1) { live_stream_active = 0; QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read error occurred. 3"); messagewindow.exec(); remove_all_signals(); return; } } } } } for(i=0; izratio_filter != NULL) { l_temp = signalcomp[i]->prefilter_starttime % (TIME_DIMENSION * 2LL); // necessary for the Z-ratio filter if(l_temp != 0L) { temp = (TIME_DIMENSION * 2LL) - l_temp; l_temp = temp; signalcomp[i]->prefilter_reset_sample = (l_temp / signalcomp[i]->edfhdr->long_data_record_duration) * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record; signalcomp[i]->prefilter_reset_sample += (int)(((double)(l_temp % signalcomp[i]->edfhdr->long_data_record_duration) / (double)signalcomp[i]->edfhdr->long_data_record_duration) * (double)signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record); } else { signalcomp[i]->prefilter_reset_sample = 0; } // printf("records_in_viewbuf is %lli\n" // "samples_in_prefilterbuf is %i\n" // "l_temp is %lli\n" // "temp is %i\n" // "prefilter_reset_sample is %i\n\n", // signalcomp[i]->records_in_viewbuf, // signalcomp[i]->samples_in_prefilterbuf, // l_temp, // temp, // signalcomp[i]->prefilter_reset_sample); } } for(i=0; ifilter_cnt) && (!signalcomp[i]->spike_filter) && (!signalcomp[i]->ravg_filter_cnt) && (!signalcomp[i]->fidfilter_cnt) && (signalcomp[i]->ecg_filter == NULL) && (signalcomp[i]->zratio_filter == NULL)) continue; for(s=0; ssamples_in_prefilterbuf; s++) { dig_value = 0.0; for(k=0; knum_of_signals; k++) { if(signalcomp[i]->edfhdr->bdf) { var.two[0] = *((unsigned short *)( viewbuf + signalcomp[i]->viewbufoffset + (signalcomp[i]->edfhdr->recordsize * (s / signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[k]].smp_per_record)) + signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[k]].buf_offset + ((s % signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[k]].smp_per_record) * 3))); var.four[2] = *((unsigned char *)( viewbuf + signalcomp[i]->viewbufoffset + (signalcomp[i]->edfhdr->recordsize * (s / signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[k]].smp_per_record)) + signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[k]].buf_offset + ((s % signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[k]].smp_per_record) * 3) + 2)); if(var.four[2]&0x80) { var.four[3] = 0xff; } else { var.four[3] = 0x00; } temp = var.one_signed; } if(signalcomp[i]->edfhdr->edf) { temp = *(((short *)( viewbuf + signalcomp[i]->viewbufoffset + (signalcomp[i]->edfhdr->recordsize * (s / signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[k]].smp_per_record)) + signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[k]].buf_offset)) + (s % signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[k]].smp_per_record)); } temp += signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[k]].offset; temp *= signalcomp[i]->factor[k]; dig_value += temp; } if(signalcomp[i]->spike_filter) { dig_value = run_spike_filter(dig_value, signalcomp[i]->spike_filter); } for(j=0; jfilter_cnt; j++) { dig_value = first_order_filter(dig_value, signalcomp[i]->filter[j]); } for(j=0; jravg_filter_cnt; j++) { dig_value = run_ravg_filter(dig_value, signalcomp[i]->ravg_filter[j]); } for(j=0; jfidfilter_cnt; j++) { dig_value = signalcomp[i]->fidfuncp[j](signalcomp[i]->fidbuf[j], dig_value); } if(signalcomp[i]->ecg_filter != NULL) { if(s == 0) { reset_ecg_filter(signalcomp[i]->ecg_filter); } dig_value = run_ecg_filter(dig_value, signalcomp[i]->ecg_filter); } if(signalcomp[i]->zratio_filter != NULL) { if(s == signalcomp[i]->prefilter_reset_sample) { reset_zratio_filter(signalcomp[i]->zratio_filter); } dig_value = run_zratio_filter(dig_value, signalcomp[i]->zratio_filter); } } } for(i=0; isamples_in_prefilterbuf > 0) { if(signalcomp[i]->spike_filter) { spike_filter_save_buf(signalcomp[i]->spike_filter); } for(j=0; jfilter_cnt; j++) { signalcomp[i]->filterpreset_a[j] = signalcomp[i]->filter[j]->old_input; signalcomp[i]->filterpreset_b[j] = signalcomp[i]->filter[j]->old_output; } for(j=0; jravg_filter_cnt; j++) { ravg_filter_save_buf(signalcomp[i]->ravg_filter[j]); } for(j=0; jfidfilter_cnt; j++) { memcpy(signalcomp[i]->fidbuf2[j], signalcomp[i]->fidbuf[j], fid_run_bufsize(signalcomp[i]->fid_run[j])); } if(signalcomp[i]->ecg_filter != NULL) { ecg_filter_save_buf(signalcomp[i]->ecg_filter); } if(signalcomp[i]->zratio_filter != NULL) { zratio_filter_save_buf(signalcomp[i]->zratio_filter); } } } } totalsize = 0; for(i=0; iedfhdr->viewtime>=0) signalcomp[i]->records_in_viewbuf = ((pagetime + (signalcomp[i]->edfhdr->viewtime % signalcomp[i]->edfhdr->long_data_record_duration)) / signalcomp[i]->edfhdr->long_data_record_duration) + 1; else signalcomp[i]->records_in_viewbuf = ((pagetime + ((-(signalcomp[i]->edfhdr->viewtime)) % signalcomp[i]->edfhdr->long_data_record_duration)) / signalcomp[i]->edfhdr->long_data_record_duration) + 1; signalcomp[i]->viewbufsize = signalcomp[i]->records_in_viewbuf * signalcomp[i]->edfhdr->recordsize; signalcomp[i]->samples_on_screen = (int)(((double)pagetime / (double)signalcomp[i]->edfhdr->long_data_record_duration) * (double)signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record); if(signalcomp[i]->edfhdr->viewtime<0) { d_temp = (((double)(-(signalcomp[i]->edfhdr->viewtime))) / (double)signalcomp[i]->edfhdr->long_data_record_duration) * (double)signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record; if(d_temp>2147483648.0) { signalcomp[i]->sample_start = 2147483647LL; } else { signalcomp[i]->sample_start = (int)d_temp; } } else { signalcomp[i]->sample_start = 0; } if(signalcomp[i]->edfhdr->viewtime>=0) { signalcomp[i]->sample_timeoffset_part = ((double)(signalcomp[i]->edfhdr->viewtime % signalcomp[i]->edfhdr->long_data_record_duration) / (double)signalcomp[i]->edfhdr->long_data_record_duration) * (double)signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record; signalcomp[i]->sample_timeoffset = (int)(signalcomp[i]->sample_timeoffset_part); signalcomp[i]->sample_timeoffset_part -= signalcomp[i]->sample_timeoffset; } else { signalcomp[i]->sample_timeoffset_part = 0.0; signalcomp[i]->sample_timeoffset = 0; } if(!i) { signalcomp[i]->viewbufoffset = 0; totalsize = signalcomp[i]->viewbufsize; } else { skip = 0; for(j=0; jedfhdr->file_hdl==signalcomp[j]->edfhdr->file_hdl) { skip = 1; signalcomp[i]->viewbufoffset = signalcomp[j]->viewbufoffset; signalcomp[i]->records_in_viewbuf = signalcomp[j]->records_in_viewbuf; signalcomp[i]->viewbufsize = signalcomp[j]->viewbufsize; break; } } if(!skip) { signalcomp[i]->viewbufoffset = signalcomp[i-1]->viewbufoffset + signalcomp[i-1]->viewbufsize; totalsize += signalcomp[i]->viewbufsize; } } } if(viewbuf!=NULL) { free(viewbuf); viewbuf = NULL; } if(totalsize) { viewbuf = (char *)malloc(totalsize); if(viewbuf==NULL) { live_stream_active = 0; QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action.\n" "Decrease the timescale and try again."); messagewindow.exec(); remove_all_signals(); return; } } for(i=0; iedfhdr->viewtime>=0) { datarecords = signalcomp[i]->edfhdr->viewtime / signalcomp[i]->edfhdr->long_data_record_duration; } else { datarecords = 0; } dif = signalcomp[i]->edfhdr->datarecords - datarecords; if(dif<=0) { memset(viewbuf + signalcomp[i]->viewbufoffset, 0, signalcomp[i]->records_in_viewbuf * signalcomp[i]->edfhdr->recordsize); signalcomp[i]->sample_stop = 0; } else { if(difrecords_in_viewbuf) { readsize = dif * signalcomp[i]->edfhdr->recordsize; memset(viewbuf + signalcomp[i]->viewbufoffset + readsize, 0, (signalcomp[i]->records_in_viewbuf * signalcomp[i]->edfhdr->recordsize) - readsize); signalcomp[i]->sample_stop = (dif * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record) - signalcomp[i]->sample_timeoffset; } else { readsize = signalcomp[i]->records_in_viewbuf * signalcomp[i]->edfhdr->recordsize; signalcomp[i]->sample_stop = signalcomp[i]->samples_on_screen; } l_temp = signalcomp[i]->edfhdr->hdrsize; l_temp += (datarecords * signalcomp[i]->edfhdr->recordsize); fseeko(signalcomp[i]->edfhdr->file_hdl, l_temp, SEEK_SET); if(fread(viewbuf + signalcomp[i]->viewbufoffset, readsize, 1, signalcomp[i]->edfhdr->file_hdl)!=1) { live_stream_active = 0; QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read error occurred. 5"); messagewindow.exec(); remove_all_signals(); return; } } } else { skip = 0; for(j=0; jedfhdr->file_hdl==signalcomp[j]->edfhdr->file_hdl) { skip = 1; break; } } if(signalcomp[i]->edfhdr->viewtime>=0) { datarecords = signalcomp[i]->edfhdr->viewtime / signalcomp[i]->edfhdr->long_data_record_duration; } else { datarecords = 0; } dif = signalcomp[i]->edfhdr->datarecords - datarecords; if(dif<=0) { if(!skip) { memset(viewbuf + signalcomp[i]->viewbufoffset, 0, signalcomp[i]->records_in_viewbuf * signalcomp[i]->edfhdr->recordsize); } signalcomp[i]->sample_stop = 0; } else { if(difrecords_in_viewbuf) { if(!skip) { readsize = dif * signalcomp[i]->edfhdr->recordsize; memset(viewbuf + signalcomp[i]->viewbufoffset + readsize, 0, (signalcomp[i]->records_in_viewbuf * signalcomp[i]->edfhdr->recordsize) - readsize); } signalcomp[i]->sample_stop = (dif * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record) - signalcomp[i]->sample_timeoffset; } else { if(!skip) { readsize = signalcomp[i]->records_in_viewbuf * signalcomp[i]->edfhdr->recordsize; } signalcomp[i]->sample_stop = signalcomp[i]->samples_on_screen; } if(!skip) { l_temp = signalcomp[i]->edfhdr->hdrsize; l_temp += (datarecords * signalcomp[i]->edfhdr->recordsize); fseeko(signalcomp[i]->edfhdr->file_hdl, l_temp, SEEK_SET); if(fread(viewbuf + signalcomp[i]->viewbufoffset, readsize, 1, signalcomp[i]->edfhdr->file_hdl)!=1) { live_stream_active = 0; QMessageBox messagewindow(QMessageBox::Critical, "Error", "A read error occurred. 6"); messagewindow.exec(); remove_all_signals(); return; } } } } signalcomp[i]->sample_stop += signalcomp[i]->sample_start; } if(signalcomps && (!signal_averaging_active)) { viewtime_string[0] = 0; if(viewtime_indicator_type == 2) { l_temp = (edfheaderlist[sel_viewtime]->viewtime + edfheaderlist[sel_viewtime]->starttime_offset) / TIME_DIMENSION; l_temp += edfheaderlist[sel_viewtime]->utc_starttime; utc_to_date_time(l_temp, &date_time_str); snprintf(viewtime_string, 32, "%2i-%s ", date_time_str.day, date_time_str.month_str); } if((edfheaderlist[sel_viewtime]->viewtime + edfheaderlist[sel_viewtime]->starttime_offset)>=0LL) { if(viewtime_indicator_type > 0) { snprintf(viewtime_string + strlen(viewtime_string), 32, "%2i:%02i:%02i.%04i (", (int)((((edfheaderlist[sel_viewtime]->l_starttime + edfheaderlist[sel_viewtime]->viewtime + edfheaderlist[sel_viewtime]->starttime_offset) / TIME_DIMENSION)/ 3600LL) % 24LL), (int)((((edfheaderlist[sel_viewtime]->l_starttime + edfheaderlist[sel_viewtime]->viewtime + edfheaderlist[sel_viewtime]->starttime_offset) / TIME_DIMENSION) % 3600LL) / 60LL), (int)(((edfheaderlist[sel_viewtime]->l_starttime + edfheaderlist[sel_viewtime]->viewtime + edfheaderlist[sel_viewtime]->starttime_offset) / TIME_DIMENSION) % 60LL), (int)(((edfheaderlist[sel_viewtime]->l_starttime + edfheaderlist[sel_viewtime]->viewtime + edfheaderlist[sel_viewtime]->starttime_offset) % TIME_DIMENSION) / 1000LL)); } snprintf(viewtime_string + strlen(viewtime_string), 32, "%i:%02i:%02i.%04i", (int)((edfheaderlist[sel_viewtime]->viewtime / TIME_DIMENSION)/ 3600LL), (int)(((edfheaderlist[sel_viewtime]->viewtime / TIME_DIMENSION) % 3600LL) / 60LL), (int)((edfheaderlist[sel_viewtime]->viewtime / TIME_DIMENSION) % 60LL), (int)((edfheaderlist[sel_viewtime]->viewtime % TIME_DIMENSION) / 1000LL)); if(viewtime_indicator_type > 0) { sprintf(viewtime_string + strlen(viewtime_string), ")"); } } else { l_temp = edfheaderlist[sel_viewtime]->l_starttime + ((edfheaderlist[sel_viewtime]->viewtime + edfheaderlist[sel_viewtime]->starttime_offset) % (86400LL * TIME_DIMENSION)); if(l_temp<=0) { l_temp += (86400LL * TIME_DIMENSION); } if(viewtime_indicator_type > 0) { snprintf(viewtime_string + strlen(viewtime_string), 32, "%2i:%02i:%02i.%04i (", (int)((((l_temp) / TIME_DIMENSION)/ 3600LL) % 24LL), (int)((((l_temp) / TIME_DIMENSION) % 3600LL) / 60LL), (int)(((l_temp) / TIME_DIMENSION) % 60LL), (int)(((l_temp) % TIME_DIMENSION) / 1000LL)); } l_temp = -edfheaderlist[sel_viewtime]->viewtime; snprintf(viewtime_string + strlen(viewtime_string), 32, "-%i:%02i:%02i.%04i", (int)((l_temp / TIME_DIMENSION)/ 3600LL), (int)(((l_temp / TIME_DIMENSION) % 3600LL) / 60LL), (int)((l_temp / TIME_DIMENSION) % 60LL), (int)((l_temp % TIME_DIMENSION) / 1000LL)); if(viewtime_indicator_type > 0) { sprintf(viewtime_string + strlen(viewtime_string), ")"); } } if(pagetime >= (3600LL * TIME_DIMENSION)) { snprintf(pagetime_string, 32, "%i:%02i:%02i.%04i", ((int)(pagetime / TIME_DIMENSION)) / 3600, (((int)(pagetime / TIME_DIMENSION)) % 3600) / 60, ((int)(pagetime / TIME_DIMENSION)) % 60, (int)((pagetime % TIME_DIMENSION) / 1000LL)); } else if(pagetime >= (60LL * TIME_DIMENSION)) { snprintf(pagetime_string, 32, "%i:%02i.%04i", ((int)(pagetime / TIME_DIMENSION)) / 60, ((int)(pagetime / TIME_DIMENSION)) % 60, (int)((pagetime % TIME_DIMENSION) / 1000LL)); } else if(pagetime >= TIME_DIMENSION) { snprintf(pagetime_string, 32, "%i.%04i sec", (int)(pagetime / TIME_DIMENSION), (int)((pagetime % TIME_DIMENSION) / 1000LL)); } else { convert_to_metric_suffix(pagetime_string, (double)pagetime / TIME_DIMENSION, 3); strcat(pagetime_string, "S"); } remove_trailing_zeros(viewtime_string); remove_trailing_zeros(pagetime_string); } if(!signal_averaging_active) { if(print_to_edf_active) { print_to_edf_active = 0; } else { if(signalcomps && (!live_stream_active)) { positionslider->blockSignals(true); long long record_duration = edfheaderlist[sel_viewtime]->long_data_record_duration * edfheaderlist[sel_viewtime]->datarecords; record_duration -= pagetime; if(edfheaderlist[sel_viewtime]->viewtime<=0) { positionslider->setValue(0); } else { if(edfheaderlist[sel_viewtime]->viewtime>=record_duration) { positionslider->setValue(1000000); } else { if(record_durationsetValue(1000000); } else { positionslider->setValue(edfheaderlist[sel_viewtime]->viewtime * 1000000LL / record_duration); } } } slidertoolbar->setEnabled(true); } else { slidertoolbar->setEnabled(false); positionslider->blockSignals(true); } maincurve->drawCurve_stage_1(); if(signalcomps && (!live_stream_active)) { positionslider->blockSignals(false); } } for(r=0; rdock->isVisible()) { spectrumdock[r]->rescan(); } } } } edfbrowser_157_source/PaxHeaders.7921/utils.h0000644000000000000000000000013212646460742016177 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/utils.h0000644000175000001440000000736212646460742016550 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef UTILS_INCLUDED #define UTILS_INCLUDED #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include void remove_trailing_spaces(char *); void remove_leading_spaces(char *); void remove_trailing_zeros(char *); void convert_trailing_zeros_to_spaces(char *); void remove_extension_from_filename(char *); /* removes extension including the dot */ int get_filename_from_path(char *dest, const char *src, int size); /* size is size of destination, returns length of filename */ int get_directory_from_path(char *dest, const char *src, int size); /* size is size of destination, returns length of directory */ void latin1_to_ascii(char *, int); void latin1_to_utf8(char *, int); void utf8_to_latin1(char *); int antoi(const char *, int); int atoi_nonlocalized(const char *); double atof_nonlocalized(const char *); int sprint_number_nonlocalized(char *, double); long long atoll_x(const char *, int); void strntolower(char *, int); /* 3th argument is the minimum digits that will be printed (minus sign not included), leading zero's will be added if necessary */ /* if 4th argument is zero, only negative numbers will have the sign '-' character */ /* if 4th argument is one, the sign '+' or '-' character will always be printed */ /* returns the amount of characters printed */ int sprint_int_number_nonlocalized(char *, int, int, int); int sprint_ll_number_nonlocalized(char *, long long, int, int); int fprint_int_number_nonlocalized(FILE *, int, int, int); int fprint_ll_number_nonlocalized(FILE *, long long, int, int); /* returns 1 in case the string is not a number */ int is_integer_number(char *); int is_number(char *); int round_125_cat(double); /* returns 10, 20 or 50, depending on the value */ void hextoascii(char *); /* inline copy */ void bintoascii(char *); /* inline copy */ void bintohex(char *); /* inline copy */ void asciitohex(char *, const char *); /* destination must have double the size of source! */ void asciitobin(char *, const char *); /* destination must have eight times the size of source! */ void hextobin(char *, const char *); /* destination must have four times the size of source! */ /* Converts a double to Giga/Mega/Kilo/milli/micro/etc. */ /* int is number of decimals. Result is written into the string argument */ int convert_to_metric_suffix(char *, double, int); double round_up_step125(double, double *); /* Rounds the value up to 1-2-5 steps */ double round_down_step125(double, double *); /* Rounds the value down to 1-2-5 steps */ int strtoipaddr(unsigned int *, const char *); /* convert a string "192.168.1.12" to an integer */ int dblcmp(double, double); /* returns 0 when equal */ #ifdef __cplusplus } /* extern "C" */ #endif #endif edfbrowser_157_source/PaxHeaders.7921/ecg_filter.cpp0000644000000000000000000000013212646460742017475 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/ecg_filter.cpp0000644000175000001440000005071412646460742020045 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "ecg_filter.h" #define ECG_FILTER_STAT_BUFSIZE 262144 #define SECONDS_RUNIN 5 // #define ECG_FILTER_DEBUG_ACTIVE struct ecg_filter_settings * create_ecg_filter(double sf, double bitval, int powerlinefreq) { int i; double d_tmp; struct ecg_filter_settings *settings; if(sf < 99.9) return(NULL); if((powerlinefreq != 50) && (powerlinefreq != 60)) return(NULL); settings = (struct ecg_filter_settings *) calloc(1, sizeof(struct ecg_filter_settings)); if(settings==NULL) return(NULL); d_tmp = sf / (double)powerlinefreq; settings->avgfilter_50_size = d_tmp; if((d_tmp - settings->avgfilter_50_size) > 0.5) settings->avgfilter_50_size++; d_tmp = sf / 35.0; settings->avgfilter_35_size = d_tmp; if((d_tmp - settings->avgfilter_35_size) > 0.5) settings->avgfilter_35_size++; d_tmp = sf / 25.0; settings->avgfilter_25_size = d_tmp; if((d_tmp - settings->avgfilter_25_size) > 0.5) settings->avgfilter_25_size++; settings->avgfilter_50_idx = 0; settings->avgfilter_35_idx = 0; settings->avgfilter_25_idx = 0; settings->avgfilter_50_buf = (double *)calloc(1, settings->avgfilter_50_size * sizeof(double)); if(settings->avgfilter_50_buf == NULL) { free(settings); return(NULL); } settings->avgfilter_50_buf_bu = (double *)calloc(1, settings->avgfilter_50_size * sizeof(double)); if(settings->avgfilter_50_buf_bu == NULL) { free(settings->avgfilter_50_buf); free(settings); return(NULL); } settings->avgfilter_35_buf = (double *)calloc(1, settings->avgfilter_35_size * sizeof(double)); if(settings->avgfilter_35_buf == NULL) { free(settings->avgfilter_50_buf); free(settings->avgfilter_50_buf_bu); free(settings); return(NULL); } settings->avgfilter_35_buf_bu = (double *)calloc(1, settings->avgfilter_35_size * sizeof(double)); if(settings->avgfilter_35_buf_bu == NULL) { free(settings->avgfilter_50_buf); free(settings->avgfilter_50_buf_bu); free(settings->avgfilter_35_buf); free(settings); return(NULL); } settings->avgfilter_25_buf = (double *)calloc(1, settings->avgfilter_25_size * sizeof(double)); if(settings->avgfilter_25_buf == NULL) { free(settings->avgfilter_50_buf); free(settings->avgfilter_50_buf_bu); free(settings->avgfilter_35_buf); free(settings->avgfilter_35_buf_bu); free(settings); return(NULL); } settings->avgfilter_25_buf_bu = (double *)calloc(1, settings->avgfilter_25_size * sizeof(double)); if(settings->avgfilter_25_buf_bu == NULL) { free(settings->avgfilter_50_buf); free(settings->avgfilter_50_buf_bu); free(settings->avgfilter_35_buf); free(settings->avgfilter_35_buf_bu); free(settings->avgfilter_25_buf); free(settings); return(NULL); } settings->SV_idx = 0; settings->SV_sz = ((((int)sf) + 25) / 100) + 1; if(settings->SV_sz < 3) { settings->SV_sz = 3; } settings->SV = (double *)calloc(1, settings->SV_sz * sizeof(double)); if(settings->SV == NULL) { free(settings->avgfilter_50_buf); free(settings->avgfilter_50_buf_bu); free(settings->avgfilter_35_buf); free(settings->avgfilter_35_buf_bu); free(settings->avgfilter_25_buf); free(settings->avgfilter_25_buf_bu); free(settings); return(NULL); } settings->M_startslope = sf * 0.2; settings->M_endslope = sf * 1.2; settings->smpl_n = 0; for(i=0; i<5; i++) { settings->M[i] = 0.0; } settings->M_avg = 0.0; settings->M_idx = 0; settings->drain = 0.0; settings->top = 0.0; settings->runin = SECONDS_RUNIN * sf; settings->sf = sf; settings->F_size = 0.35 * sf; settings->F_wd = 0.05 * sf; settings->F_sf_factor = 150.0 * (sf / 200.0); if(settings->F_sf_factor < 150.0) { settings->F_sf_factor = 150.0; } settings->F_value = 0.0; settings->F_idx = 0; settings->F = (double *)calloc(1, settings->F_size * sizeof(double)); if(settings->F == NULL) { free(settings->avgfilter_50_buf); free(settings->avgfilter_50_buf_bu); free(settings->avgfilter_35_buf); free(settings->avgfilter_35_buf_bu); free(settings->avgfilter_25_buf); free(settings->SV); free(settings); return(NULL); } settings->F_bu = (double *)calloc(1, settings->F_size * sizeof(double)); if(settings->F_bu == NULL) { free(settings->avgfilter_50_buf); free(settings->avgfilter_50_buf_bu); free(settings->avgfilter_35_buf); free(settings->avgfilter_35_buf_bu); free(settings->avgfilter_25_buf); free(settings->SV); free(settings->F); free(settings); return(NULL); } for(i=0; i<5; i++) { settings->R[i] = sf; } settings->R_idx = 0; settings->R_avg = sf; settings->R_value = 0.0; settings->R_startslope = sf * 0.66; settings->R_endslope = sf; settings->bu_filled = 0; settings->bpm = 60.0; settings->bitvalue = bitval; settings->stat_buf_idx = 0; settings->sample_cntr = 0; settings->T_peak_avg = 0.0; settings->stat_buf = (double *)malloc(sizeof(double) * ECG_FILTER_STAT_BUFSIZE); if(settings->stat_buf == NULL) { free(settings->avgfilter_50_buf); free(settings->avgfilter_50_buf_bu); free(settings->avgfilter_35_buf); free(settings->avgfilter_35_buf_bu); free(settings->avgfilter_25_buf); free(settings->SV); free(settings->F); free(settings->F_bu); free(settings); return(NULL); } settings->stat_smpl_buf = (long long *)malloc(sizeof(long long) * ECG_FILTER_STAT_BUFSIZE); if(settings->stat_smpl_buf == NULL) { free(settings->avgfilter_50_buf); free(settings->avgfilter_50_buf_bu); free(settings->avgfilter_35_buf); free(settings->avgfilter_35_buf_bu); free(settings->avgfilter_25_buf); free(settings->SV); free(settings->F); free(settings->F_bu); free(settings->stat_buf); free(settings); return(NULL); } return(settings); } double run_ecg_filter(double new_sample, struct ecg_filter_settings *settings) // double run_ecg_filter(double new_sample, struct ecg_filter_settings *settings, int signalcompnr) // debug { int i, j; double new_input, max_value, result; /* running average filter 1 */ settings->avgfilter_50_buf[settings->avgfilter_50_idx] = new_sample; settings->avgfilter_50_idx++; if(settings->avgfilter_50_idx >= settings->avgfilter_50_size) { settings->avgfilter_50_idx = 0; } settings->avgfilter_50_mean = 0.0; for(i=0; iavgfilter_50_size; i++) { settings->avgfilter_50_mean += settings->avgfilter_50_buf[i]; } settings->avgfilter_50_mean /= settings->avgfilter_50_size; /* running average filter 2 */ settings->avgfilter_35_buf[settings->avgfilter_35_idx] = settings->avgfilter_50_mean; settings->avgfilter_35_idx++; if(settings->avgfilter_35_idx >= settings->avgfilter_35_size) { settings->avgfilter_35_idx = 0; } settings->avgfilter_35_mean = 0.0; for(i=0; iavgfilter_35_size; i++) { settings->avgfilter_35_mean += settings->avgfilter_35_buf[i]; } settings->avgfilter_35_mean /= settings->avgfilter_35_size; /* running average filter 3 */ settings->avgfilter_25_buf[settings->avgfilter_25_idx] = settings->avgfilter_35_mean; settings->avgfilter_25_idx++; if(settings->avgfilter_25_idx >= settings->avgfilter_25_size) { settings->avgfilter_25_idx = 0; } settings->avgfilter_25_mean = 0.0; for(i=0; iavgfilter_25_size; i++) { settings->avgfilter_25_mean += settings->avgfilter_25_buf[i]; } settings->avgfilter_25_mean /= settings->avgfilter_25_size; // return(settings->avgfilter_25_mean); // debug // if(signalcompnr == 1) return(settings->avgfilter_25_mean); // debug /* spatial velocity filter */ settings->SV[settings->SV_idx] = settings->avgfilter_25_mean; new_input = settings->SV[settings->SV_idx] - settings->SV[(settings->SV_idx + 1) % settings->SV_sz]; if(++settings->SV_idx >= settings->SV_sz) settings->SV_idx = 0; if(new_input < 0.0) new_input *= -1.0; // return(new_input); // debug // if(signalcompnr == 2) return(new_input); // debug settings->F[settings->F_idx++] = new_input; settings->F_idx %= settings->F_size; max_value = 0.0; for(i=0; iF_wd; i++) { j = (settings->F_idx + settings->F_size - i - 1) % settings->F_size; if(settings->F[j] > max_value) { max_value = settings->F[j]; } } result = max_value; max_value = 0.0; for(i=0; iF_wd; i++) { j = (settings->F_idx + i) % settings->F_size; if(settings->F[j] > max_value) { max_value = settings->F[j]; } } result -= max_value; settings->F_value += (result / settings->F_sf_factor); // return(settings->F_value); // debug //////////////////////////////////////////////// if(settings->runin) { if(settings->sample_cntr > settings->sf) { if(new_input > settings->top) { settings->top = new_input; } if(new_input > settings->T_peak_avg) { settings->T_peak_avg = new_input; } } if(settings->sample_cntr == settings->sf) { settings->F_value = 0.0; settings->F_idx = 0; memset(settings->F, 0, settings->F_size * sizeof(double)); } if(settings->runin == 1) { for(i=0; i<5; i++) { settings->M[i] = settings->top * 0.5; } settings->M_avg = settings->top * 0.5; settings->drain = settings->top * 0.2 / settings->sf; settings->smpl_n = settings->M_startslope; #ifdef ECG_FILTER_DEBUG_ACTIVE printf("-> settings->drain is %f\n", settings->drain); printf("-> settings->M_avg is %f\n", settings->M_avg); #endif } settings->runin--; settings->sample_cntr++; // if(signalcompnr == 6) return(settings->M_avg + settings->R_value); // debug: check ecg detection treshold // if(signalcompnr == 3) return(settings->M_avg); // debug: check ecg detection treshold // if(signalcompnr == 4) return(settings->F_value); // debug: check ecg detection treshold // if(signalcompnr == 5) return(settings->R_value); // debug: check ecg detection treshold // if(signalcompnr == 7) return(settings->T_peak_avg / 2.0); // debug: check ecg detection treshold return(settings->bpm / settings->bitvalue); } if(new_input > settings->T_peak_avg) { settings->T_peak_avg += ((new_input - settings->T_peak_avg) / (settings->sf / 10.0)); } else { settings->T_peak_avg -= (settings->T_peak_avg / (settings->sf * 10.0)); } if((settings->smpl_n > settings->R_startslope) && (settings->smpl_n < settings->R_endslope)) { settings->R_value -= (settings->drain * 0.7); } if(settings->smpl_n < settings->M_startslope) { if(new_input > settings->top) { settings->top = new_input; #ifdef ECG_FILTER_DEBUG_ACTIVE printf("new_input is %f\n", new_input); #endif } settings->sample_cntr++; settings->smpl_n++; } else { if(settings->smpl_n == settings->M_startslope) { settings->top *= 0.6; #ifdef ECG_FILTER_DEBUG_ACTIVE printf("settings->top is %f\n", settings->top); #endif if(settings->top > (1.5 * settings->M[settings->M_idx])) { settings->top = 1.1 * settings->M[settings->M_idx]; } settings->M[settings->M_idx++] = settings->top; settings->M_idx %= 5; settings->M_avg = (settings->M[0] + settings->M[1] + settings->M[2] + settings->M[3] + settings->M[4]) / 5.0; settings->drain = settings->M_avg * 0.4 / settings->sf; #ifdef ECG_FILTER_DEBUG_ACTIVE printf("settings->top is %f\n", settings->top); printf("settings->M_avg is %f\n", settings->M_avg); printf("settings->drain is %f\n", settings->drain); #endif } if((new_input > (settings->M_avg + settings->F_value + settings->R_value)) // beat detected? && (new_input > (settings->T_peak_avg / 2.0))) // if(new_input > (settings->M_avg + settings->F_value + settings->R_value)) // beat detected? // if(new_input > (settings->M_avg + settings->R_value)) // beat detected? // debug // if(new_input > (settings->M_avg)) // debug { settings->top = new_input; settings->R[settings->R_idx++] = settings->smpl_n; #ifdef ECG_FILTER_DEBUG_ACTIVE printf("beat detected: settings->top is %f\n", settings->top); printf("beat detected: settings->smpl_n is %i\n", settings->smpl_n); #endif settings->R_idx %= 5; settings->R_avg = (settings->R[0] + settings->R[1] + settings->R[2] + settings->R[3] + settings->R[4]) / 5; settings->R_value = 0.0; settings->R_startslope = 0.66 * settings->R_avg; settings->R_endslope = settings->R_avg; settings->bpm = (settings->sf * 60.0) / settings->smpl_n; if(settings->stat_buf_idx < (ECG_FILTER_STAT_BUFSIZE - 1)) { settings->stat_buf[settings->stat_buf_idx] = ((double)settings->smpl_n) / settings->sf; if(settings->stat_buf_idx > 0) { settings->stat_smpl_buf[settings->stat_buf_idx] = settings->stat_smpl_buf[settings->stat_buf_idx - 1] + settings->sample_cntr; } else { settings->stat_smpl_buf[settings->stat_buf_idx] = settings->sample_cntr; } settings->stat_buf_idx++; } settings->sample_cntr = 1; settings->smpl_n = 1; } else { if(settings->smpl_n < settings->M_endslope) { settings->M_avg -= settings->drain; } settings->sample_cntr++; settings->smpl_n++; } } // if(signalcompnr == 6) return(settings->M_avg + settings->F_value + settings->R_value); // debug: check ecg detection treshold // if(signalcompnr == 6) return(settings->M_avg + settings->R_value); // debug: check ecg detection treshold // if(signalcompnr == 3) return(settings->M_avg); // debug: check ecg detection treshold // if(signalcompnr == 4) return(settings->F_value); // debug: check ecg detection treshold // if(signalcompnr == 5) return(settings->R_value); // debug: check ecg detection treshold // if(signalcompnr == 7) return(settings->T_peak_avg / 2.0); // debug: check ecg detection treshold return(settings->bpm / settings->bitvalue); } void ecg_filter_save_buf(struct ecg_filter_settings *settings) { int i; settings->avgfilter_50_idx_bu = settings->avgfilter_50_idx; memcpy(settings->avgfilter_50_buf_bu, settings->avgfilter_50_buf, sizeof(double) * settings->avgfilter_50_size); settings->avgfilter_50_mean_bu = settings->avgfilter_50_mean; settings->avgfilter_35_idx_bu = settings->avgfilter_35_idx; memcpy(settings->avgfilter_35_buf_bu, settings->avgfilter_35_buf, sizeof(double) * settings->avgfilter_35_size); settings->avgfilter_35_mean_bu = settings->avgfilter_35_mean; settings->avgfilter_25_idx_bu = settings->avgfilter_25_idx; memcpy(settings->avgfilter_25_buf_bu, settings->avgfilter_25_buf, sizeof(double) * settings->avgfilter_25_size); settings->avgfilter_25_mean_bu = settings->avgfilter_25_mean; settings->runin_bu = settings->runin; for(i=0; i<3; i++) { settings->SV_bu[i] = settings->SV[i]; } settings->SV_idx_bu = settings->SV_idx; settings->smpl_n_bu = settings->smpl_n; for(i=0; i<5; i++) { settings->M_bu[i] = settings->M[i]; settings->R_bu[i] = settings->R[i]; } settings->M_idx_bu = settings->M_idx; settings->M_avg_bu = settings->M_avg; settings->drain_bu = settings->drain; settings->top_bu = settings->top; for(i=0; iF_size; i++) { settings->F_bu[i] = settings->F[i]; } settings->F_idx_bu = settings->F_idx; settings->F_value_bu = settings->F_value; settings->R_idx_bu = settings->R_idx; settings->R_avg_bu = settings->R_avg; settings->R_value_bu = settings->R_value; settings->R_startslope_bu = settings->R_startslope; settings->R_endslope_bu = settings->R_endslope; settings->bpm_bu = settings->bpm; settings->T_peak_avg_bu = settings->T_peak_avg; settings->bu_filled = 1; } void ecg_filter_restore_buf(struct ecg_filter_settings *settings) { int i; settings->stat_buf_idx = 0; settings->sample_cntr = 0; if(settings->bu_filled == 0) return; settings->avgfilter_50_idx = settings->avgfilter_50_idx_bu; memcpy(settings->avgfilter_50_buf, settings->avgfilter_50_buf_bu, sizeof(double) * settings->avgfilter_50_size); settings->avgfilter_50_mean = settings->avgfilter_50_mean_bu; settings->avgfilter_35_idx = settings->avgfilter_35_idx_bu; memcpy(settings->avgfilter_35_buf, settings->avgfilter_35_buf_bu, sizeof(double) * settings->avgfilter_35_size); settings->avgfilter_35_mean = settings->avgfilter_35_mean_bu; settings->avgfilter_25_idx = settings->avgfilter_25_idx_bu; memcpy(settings->avgfilter_25_buf, settings->avgfilter_25_buf_bu, sizeof(double) * settings->avgfilter_25_size); settings->avgfilter_25_mean = settings->avgfilter_25_mean_bu; settings->runin = settings->runin_bu; for(i=0; i<3; i++) { settings->SV[i] = settings->SV_bu[i]; } settings->SV_idx = settings->SV_idx_bu; settings->smpl_n = settings->smpl_n_bu; for(i=0; i<5; i++) { settings->M[i] = settings->M_bu[i]; settings->R[i] = settings->R_bu[i]; } settings->M_idx = settings->M_idx_bu; settings->M_avg = settings->M_avg_bu; settings->drain = settings->drain_bu; settings->top = settings->top_bu; for(i=0; iF_size; i++) { settings->F[i] = settings->F_bu[i]; } settings->F_idx = settings->F_idx_bu; settings->F_value = settings->F_value_bu; settings->R_idx = settings->R_idx_bu; settings->R_avg = settings->R_avg_bu; settings->R_value = settings->R_value_bu; settings->R_startslope = settings->R_startslope_bu; settings->R_endslope = settings->R_endslope_bu; settings->bpm = settings->bpm_bu; settings->T_peak_avg = settings->T_peak_avg_bu; } void reset_ecg_filter(struct ecg_filter_settings *settings) { int i; settings->avgfilter_50_idx = 0; settings->avgfilter_35_idx = 0; settings->avgfilter_25_idx = 0; memset(settings->avgfilter_50_buf, 0, settings->avgfilter_50_size * sizeof(double)); memset(settings->avgfilter_35_buf, 0, settings->avgfilter_35_size * sizeof(double)); memset(settings->avgfilter_25_buf, 0, settings->avgfilter_25_size * sizeof(double)); settings->SV_idx = 0; for(i=0; iSV_sz; i++) { settings->SV[i] = 0.0; } settings->smpl_n = 0; for(i=0; i<5; i++) { settings->M[i] = 0.0; } settings->M_avg = 0.0; settings->M_idx = 0; settings->drain = 0.0; settings->top = 0.0; settings->runin = SECONDS_RUNIN * settings->sf; settings->F_value = 0.0; settings->F_idx = 0; memset(settings->F, 0, settings->F_size * sizeof(double)); for(i=0; i<5; i++) { settings->R[i] = settings->sf; } settings->R_idx = 0; settings->R_avg = settings->sf; settings->R_value = 0.0; settings->R_startslope = settings->sf * 0.66; settings->R_endslope = settings->sf; settings->bu_filled = 0; settings->bpm = 60.0; settings->stat_buf_idx = 0; settings->sample_cntr = 0; settings->T_peak_avg = 0.0; } void free_ecg_filter(struct ecg_filter_settings *settings) { free(settings->avgfilter_50_buf); free(settings->avgfilter_50_buf_bu); free(settings->avgfilter_35_buf); free(settings->avgfilter_35_buf_bu); free(settings->avgfilter_25_buf); free(settings->SV); free(settings->F); free(settings->F_bu); free(settings->stat_buf); free(settings->stat_smpl_buf); free(settings); } int ecg_filter_get_beat_cnt(struct ecg_filter_settings *settings) { return(settings->stat_buf_idx); } long long * ecg_filter_get_onset_beatlist(struct ecg_filter_settings *settings) { return(settings->stat_smpl_buf); } double * ecg_filter_get_interval_beatlist(struct ecg_filter_settings *settings) { return(settings->stat_buf); } edfbrowser_157_source/PaxHeaders.7921/mainwindow.cpp0000644000000000000000000000013212646460742017546 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/mainwindow.cpp0000644000175000001440000022610212646460742020112 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "mainwindow.h" UI_Mainwindow::~UI_Mainwindow() { delete pixmap; delete splash; delete myfont; delete monofont; delete maincurve; delete annotationEditDock; for(int i=0; iignore(); } else { exit_in_progress = 1; for(i=0; iaccept(); } } // void UI_Mainwindow::search_pattern() // { // if(!signalcomps) // { // return; // } // // // // } void UI_Mainwindow::Escape_fun() { int i; for(i=0; ihascursor1 = 0; signalcomp[i]->hascursor2 = 0; signalcomp[i]->hasoffsettracking = 0; } maincurve->crosshair_1.active = 0; maincurve->crosshair_2.active = 0; maincurve->crosshair_1.moving = 0; maincurve->crosshair_2.moving = 0; maincurve->use_move_events = 0; maincurve->setMouseTracking(false); for(i=0; ihasruler = 0; } maincurve->ruler_active = 0; maincurve->ruler_moving = 0; maincurve->update(); } void UI_Mainwindow::open_stream() { if(files_open) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Close all files before opening a stream."); messagewindow.exec(); return; } live_stream_active = 1; open_new_file(); if(files_open == 1) { toolsmenu->setEnabled(false); timemenu->setEnabled(false); // windowmenu->setEnabled(false); windowmenu->actions().at(0)->setEnabled(false); // Annotations window windowmenu->actions().at(1)->setEnabled(false); // Annotation editor former_page_Act->setEnabled(false); shift_page_left_Act->setEnabled(false); shift_page_right_Act->setEnabled(false); next_page_Act->setEnabled(false); shift_page_up_Act->setEnabled(false); shift_page_down_Act->setEnabled(false); printmenu->setEnabled(false); recent_filesmenu->setEnabled(false); playback_realtime_Act->setEnabled(false); live_stream_timer->start(live_stream_update_interval); } else { live_stream_active = 0; } } void UI_Mainwindow::live_stream_timer_func() { long long datarecords_old, datarecords_new; if((!live_stream_active) || (files_open != 1)) { return; } if(!signalcomps) { live_stream_timer->start(live_stream_update_interval); return; } datarecords_old = edfheaderlist[0]->datarecords; datarecords_new = check_edf_file_datarecords(edfheaderlist[0]); if((datarecords_new > datarecords_old) && (datarecords_new > 0)) { jump_to_end(); } live_stream_timer->start(live_stream_update_interval); } long long UI_Mainwindow::check_edf_file_datarecords(struct edfhdrblock *hdr) { long long datarecords; if(fseeko(hdr->file_hdl, 0LL, SEEK_END) == -1LL) { hdr->datarecords = 0LL; return(0LL); } datarecords = ftello(hdr->file_hdl); if(datarecords < 1LL) { hdr->datarecords = 0LL; return(0LL); } datarecords -= (long long)hdr->hdrsize; datarecords /= (long long)hdr->recordsize; if(datarecords < 1LL) { hdr->datarecords = 0LL; return(0LL); } hdr->datarecords = datarecords; return(datarecords); } void UI_Mainwindow::save_file() { int len; char f_path[MAX_PATH_LENGTH]; struct edfhdrblock *hdr; struct annotationblock *annot; FILE *outputfile; if((!annotations_edited)||(!files_open)) { save_act->setEnabled(false); return; } hdr = edfheaderlist[0]; strcpy(f_path, recent_savedir); strcat(f_path, "/"); len = strlen(f_path); get_filename_from_path(f_path + len, hdr->filename, MAX_PATH_LENGTH - len); remove_extension_from_filename(f_path); if(hdr->edf) { strcat(f_path, "_edited.edf"); } else { strcat(f_path, "_edited.bdf"); } strcpy(f_path, QFileDialog::getSaveFileName(this, "Save file", QString::fromLocal8Bit(f_path), "EDF/BDF files (*.edf *.EDF *.bdf *.BDF *.rec *.REC)").toLocal8Bit().data()); if(!strcmp(f_path, "")) { return; } get_directory_from_path(recent_savedir, f_path, MAX_PATH_LENGTH); if(file_is_opened(f_path)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Selected file is in use."); messagewindow.exec(); return; } outputfile = fopeno(f_path, "wb"); if(outputfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not create a file for writing."); messagewindow.exec(); return; } if(save_annotations(this, outputfile, hdr, annotationlist[0])) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "An error occurred during saving."); messagewindow.exec(); fclose(outputfile); return; } fclose(outputfile); annot = annotationlist[0]; annotationlist[0] = annotationlist_backup; annotationlist_backup = NULL; edfplus_annotation_delete_list(&annot); annotations_dock[0]->updateList(); annotations_edited = 0; save_act->setEnabled(false); annotationEditDock->dockedit->hide(); maincurve->update(); } void UI_Mainwindow::slider_moved(int value) { int i; long long new_viewtime, tmp; if(!signalcomps) return; new_viewtime = edfheaderlist[sel_viewtime]->long_data_record_duration * edfheaderlist[sel_viewtime]->datarecords; new_viewtime -= pagetime; if(new_viewtime<0) { new_viewtime = 0; } else { new_viewtime /= 1000000; new_viewtime *= value; } if(pagetime >= (300LL * TIME_DIMENSION)) { tmp = new_viewtime % (30LL * TIME_DIMENSION); new_viewtime -= tmp; } else if(pagetime >= (60LL * TIME_DIMENSION)) { tmp = new_viewtime % (6LL * TIME_DIMENSION); new_viewtime -= tmp; } else if(pagetime >= (30LL * TIME_DIMENSION)) { tmp = new_viewtime % (3LL * TIME_DIMENSION); new_viewtime -= tmp; } else if(pagetime >= (20LL * TIME_DIMENSION)) { tmp = new_viewtime % (2LL * TIME_DIMENSION); new_viewtime -= tmp; } else if(pagetime >= (10LL * TIME_DIMENSION)) { tmp = new_viewtime % TIME_DIMENSION; new_viewtime -= tmp; } else if(pagetime >= TIME_DIMENSION) { tmp = new_viewtime % (TIME_DIMENSION / 10LL); new_viewtime -= tmp; } if(video_player->status == VIDEO_STATUS_PLAYING) { video_player_seek((int)(new_viewtime / TIME_DIMENSION)); return; } if(video_player->status == VIDEO_STATUS_PAUSED) { video_player_seek((int)(new_viewtime / TIME_DIMENSION)); } if(viewtime_sync==VIEWTIME_SYNCED_OFFSET) { for(i=0; iviewtime = new_viewtime; } } if(viewtime_sync==VIEWTIME_UNSYNCED) { edfheaderlist[sel_viewtime]->viewtime = new_viewtime; } if(viewtime_sync==VIEWTIME_SYNCED_ABSOLUT) { edfheaderlist[sel_viewtime]->viewtime = new_viewtime; for(i=0; iviewtime = edfheaderlist[sel_viewtime]->viewtime - ((edfheaderlist[i]->utc_starttime - edfheaderlist[sel_viewtime]->utc_starttime) * TIME_DIMENSION); } } } if(viewtime_sync==VIEWTIME_USER_DEF_SYNCED) { for(i=0; iviewtime -= (edfheaderlist[sel_viewtime]->viewtime - new_viewtime); } } edfheaderlist[sel_viewtime]->viewtime = new_viewtime; } setup_viewbuf(); } void UI_Mainwindow::set_timesync_reference(QAction *action) { int i; for(i=0; ifilename, action->text().toLocal8Bit().data())) { break; } } sel_viewtime = i; setMainwindowTitle(edfheaderlist[sel_viewtime]); setup_viewbuf(); } void UI_Mainwindow::set_timesync(QAction *) { int i; if(no_timesync_act->isChecked()) { viewtime_sync = VIEWTIME_UNSYNCED; } if(offset_timesync_act->isChecked()) { viewtime_sync = VIEWTIME_SYNCED_OFFSET; for(i=0; iviewtime = edfheaderlist[sel_viewtime]->viewtime; } } if(absolut_timesync_act->isChecked()) { viewtime_sync = VIEWTIME_SYNCED_ABSOLUT; for(i=0; iviewtime = edfheaderlist[sel_viewtime]->viewtime + edfheaderlist[sel_viewtime]->starttime_offset - ((edfheaderlist[i]->utc_starttime - edfheaderlist[sel_viewtime]->utc_starttime) * TIME_DIMENSION) - edfheaderlist[i]->starttime_offset; } } } if(user_def_sync_act->isChecked()) { viewtime_sync = VIEWTIME_USER_DEF_SYNCED; } setup_viewbuf(); } void UI_Mainwindow::sync_by_crosshairs() { if(files_open<2) return; if(signalcomps<2) return; if(maincurve->crosshair_1.active&&maincurve->crosshair_2.active) { if(maincurve->crosshair_1.file_num!=maincurve->crosshair_2.file_num) { viewtime_sync = VIEWTIME_USER_DEF_SYNCED; edfheaderlist[maincurve->crosshair_2.file_num]->viewtime -= ((maincurve->crosshair_1.time - edfheaderlist[maincurve->crosshair_1.file_num]->l_starttime - edfheaderlist[maincurve->crosshair_1.file_num]->viewtime - edfheaderlist[maincurve->crosshair_1.file_num]->starttime_offset) - (maincurve->crosshair_2.time - edfheaderlist[maincurve->crosshair_2.file_num]->l_starttime - edfheaderlist[maincurve->crosshair_2.file_num]->viewtime - edfheaderlist[maincurve->crosshair_2.file_num]->starttime_offset)); maincurve->crosshair_2.x_position = maincurve->crosshair_1.x_position; user_def_sync_act->setChecked(true); viewtime_sync = VIEWTIME_USER_DEF_SYNCED; setup_viewbuf(); } } } void UI_Mainwindow::show_options_dialog() { UI_OptionsDialog OptionsDialog(this); } void UI_Mainwindow::nk2edf_converter() { UI_NK2EDFwindow nk2edf(recent_opendir); } void UI_Mainwindow::convert_ascii_to_edf() { UI_ASCII2EDFapp ascii2edf(recent_opendir, recent_savedir); } void UI_Mainwindow::convert_binary_to_edf() { UI_RAW2EDFapp bin2edf(&raw2edf_var, recent_opendir, recent_savedir); } void UI_Mainwindow::convert_fino_to_edf() { UI_FINO2EDFwindow fino2edf(recent_opendir, recent_savedir); } void UI_Mainwindow::convert_wave_to_edf() { UI_WAV2EDFwindow wav2edf(recent_opendir, recent_savedir); } void UI_Mainwindow::convert_fm_audio_to_edf() { UI_FMaudio2EDFwindow fma2edf(recent_opendir, recent_savedir); } void UI_Mainwindow::convert_nexfin_to_edf() { UI_NEXFIN2EDFwindow nexfin2edf(recent_opendir, recent_savedir); } void UI_Mainwindow::convert_emsa_to_edf() { UI_EMSA2EDFwindow emsa2edf(recent_opendir, recent_savedir); } void UI_Mainwindow::convert_manscan_to_edf() { UI_MANSCAN2EDFwindow manscan2edf(recent_opendir, recent_savedir); } void UI_Mainwindow::convert_mit_to_edf() { UI_MIT2EDFwindow mit2edf(recent_opendir, recent_savedir); } void UI_Mainwindow::convert_biox_to_edf() { UI_BIOX2EDFwindow biox2edf(recent_opendir, recent_savedir); } void UI_Mainwindow::convert_scpecg_to_edf() { UI_SCPECG2EDFwindow scpecg2edf(recent_opendir, recent_savedir); } void UI_Mainwindow::edfd_converter() { UI_EDFDwindow edfplusd2edfplusc(recent_opendir, recent_savedir); } void UI_Mainwindow::bdf2edf_converter() { UI_BDF2EDFwindow bdf2edfconv(this); } void UI_Mainwindow::biosemi2bdfplus_converter() { UI_BIOSEMI2BDFPLUSwindow biosemi2bdfplusconv(this); } void UI_Mainwindow::reduce_signals() { if(!files_open) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "You have to open the file first."); messagewindow.exec(); return; } UI_ReduceSignalsWindow reduceSignals(this); } void UI_Mainwindow::edit_header() { UI_headerEditorWindow header_edit(this); } void UI_Mainwindow::unisens2edf_converter() { UI_UNISENS2EDFwindow unisens2edfconv(recent_opendir, recent_savedir); } void UI_Mainwindow::BI98002edf_converter() { UI_BI98002EDFwindow BI98002edfconv(recent_opendir, recent_savedir); } void UI_Mainwindow::edit_predefined_montages() { UI_edit_predefined_mtg_window edit_predef_mtgs_app(this); } void UI_Mainwindow::jump_to_dialog() { UI_JumpMenuDialog jumpmenu(this); } void UI_Mainwindow::jump_to_start() { int i; if(viewtime_sync==VIEWTIME_SYNCED_OFFSET) { for(i=0; iviewtime = 0; } } if(viewtime_sync==VIEWTIME_UNSYNCED) { edfheaderlist[sel_viewtime]->viewtime = 0; } if(viewtime_sync==VIEWTIME_SYNCED_ABSOLUT) { edfheaderlist[sel_viewtime]->viewtime = 0; for(i=0; iviewtime = ((edfheaderlist[sel_viewtime]->utc_starttime - edfheaderlist[i]->utc_starttime) * TIME_DIMENSION) + edfheaderlist[sel_viewtime]->starttime_offset - edfheaderlist[i]->starttime_offset; } } } if(viewtime_sync==VIEWTIME_USER_DEF_SYNCED) { for(i=0; iviewtime -= edfheaderlist[sel_viewtime]->viewtime; } } edfheaderlist[sel_viewtime]->viewtime = 0; } setup_viewbuf(); } void UI_Mainwindow::jump_to_time_millisec(long long milliseconds) { int i; if(viewtime_sync==VIEWTIME_SYNCED_OFFSET) { for(i=0; iviewtime = milliseconds * (TIME_DIMENSION / 1000); } } if(viewtime_sync==VIEWTIME_UNSYNCED) { edfheaderlist[sel_viewtime]->viewtime = milliseconds * (TIME_DIMENSION / 1000); } if(viewtime_sync==VIEWTIME_SYNCED_ABSOLUT) { edfheaderlist[sel_viewtime]->viewtime = milliseconds * (TIME_DIMENSION / 1000); for(i=0; iviewtime = edfheaderlist[sel_viewtime]->viewtime - ((edfheaderlist[i]->utc_starttime - edfheaderlist[sel_viewtime]->utc_starttime) * TIME_DIMENSION); } } } if(viewtime_sync==VIEWTIME_USER_DEF_SYNCED) { for(i=0; iviewtime -= (edfheaderlist[sel_viewtime]->viewtime - milliseconds * (TIME_DIMENSION / 1000)); } } edfheaderlist[sel_viewtime]->viewtime = milliseconds * (TIME_DIMENSION / 1000); } setup_viewbuf(); } void UI_Mainwindow::jump_to_end() { int i; long long new_viewtime; new_viewtime = edfheaderlist[sel_viewtime]->datarecords * edfheaderlist[sel_viewtime]->long_data_record_duration - pagetime; if(viewtime_sync==VIEWTIME_SYNCED_OFFSET) { for(i=0; iviewtime = new_viewtime; } } if(viewtime_sync==VIEWTIME_UNSYNCED) { edfheaderlist[sel_viewtime]->viewtime = new_viewtime; } if(viewtime_sync==VIEWTIME_SYNCED_ABSOLUT) { edfheaderlist[sel_viewtime]->viewtime = new_viewtime; for(i=0; iviewtime = edfheaderlist[sel_viewtime]->viewtime + edfheaderlist[sel_viewtime]->starttime_offset - ((edfheaderlist[i]->utc_starttime - edfheaderlist[sel_viewtime]->utc_starttime) * TIME_DIMENSION) - edfheaderlist[i]->starttime_offset; } } } if(viewtime_sync==VIEWTIME_USER_DEF_SYNCED) { for(i=0; iviewtime -= (edfheaderlist[sel_viewtime]->viewtime - new_viewtime); } } edfheaderlist[sel_viewtime]->viewtime = new_viewtime; } setup_viewbuf(); } void UI_Mainwindow::add_new_filter() { UI_FilterDialog filterdialog(this); } void UI_Mainwindow::add_spike_filter() { UI_SpikeFilterDialog spikefilterdialog(this); } // void UI_Mainwindow::add_new_math_func() // { // } // void UI_Mainwindow::remove_all_math_funcs() // { // } void UI_Mainwindow::zoomback() { int i, j; if(!zoomhistory->history_size_tail) { return; } zoomhistory->history_size_front++; zoomhistory->history_size_tail--; for(i=0; iviewtime[zoomhistory->pntr][i] = edfheaderlist[i]->viewtime; } zoomhistory->pagetime[zoomhistory->pntr] = pagetime; for(i=0; ivoltpercm[zoomhistory->pntr][i] = signalcomp[i]->voltpercm; zoomhistory->screen_offset[zoomhistory->pntr][i] = signalcomp[i]->screen_offset; for(j=0; jnum_of_signals; j++) { zoomhistory->sensitivity[zoomhistory->pntr][i][j] = signalcomp[i]->sensitivity[j]; } } zoomhistory->pntr--; if(zoomhistory->pntr<0) zoomhistory->pntr = 63; for(i=0; iviewtime = zoomhistory->viewtime[zoomhistory->pntr][i]; } pagetime = zoomhistory->pagetime[zoomhistory->pntr]; for(i=0; ivoltpercm = zoomhistory->voltpercm[zoomhistory->pntr][i]; signalcomp[i]->screen_offset = zoomhistory->screen_offset[zoomhistory->pntr][i]; for(j=0; jnum_of_signals; j++) { signalcomp[i]->sensitivity[j] = zoomhistory->sensitivity[zoomhistory->pntr][i][j]; } } setup_viewbuf(); } void UI_Mainwindow::forward() { int i, j; if(!zoomhistory->history_size_front) { return; } zoomhistory->history_size_front--; zoomhistory->history_size_tail++; zoomhistory->pntr++; if(zoomhistory->pntr>63) zoomhistory->pntr = 0; for(i=0; iviewtime = zoomhistory->viewtime[zoomhistory->pntr][i]; } pagetime = zoomhistory->pagetime[zoomhistory->pntr]; for(i=0; ivoltpercm = zoomhistory->voltpercm[zoomhistory->pntr][i]; signalcomp[i]->screen_offset = zoomhistory->screen_offset[zoomhistory->pntr][i]; for(j=0; jnum_of_signals; j++) { signalcomp[i]->sensitivity[j] = zoomhistory->sensitivity[zoomhistory->pntr][i][j]; } } setup_viewbuf(); } void UI_Mainwindow::former_page() { int i; if(video_player->status == VIDEO_STATUS_PLAYING) { video_player_seek((int)((edfheaderlist[sel_viewtime]->viewtime - pagetime) / TIME_DIMENSION)); return; } if(video_player->status == VIDEO_STATUS_PAUSED) { video_player_seek((int)((edfheaderlist[sel_viewtime]->viewtime - pagetime) / TIME_DIMENSION)); } if((viewtime_sync==VIEWTIME_SYNCED_OFFSET)||(viewtime_sync==VIEWTIME_SYNCED_ABSOLUT)||(viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { for(i=0; iviewtime -= pagetime; } } if(viewtime_sync==VIEWTIME_UNSYNCED) { edfheaderlist[sel_viewtime]->viewtime -= pagetime; } setup_viewbuf(); } void UI_Mainwindow::shift_page_left() { int i; if(video_player->status == VIDEO_STATUS_PLAYING) { video_player_seek((int)((edfheaderlist[sel_viewtime]->viewtime - (pagetime / 10)) / TIME_DIMENSION)); return; } if(video_player->status == VIDEO_STATUS_PAUSED) { video_player_seek((int)((edfheaderlist[sel_viewtime]->viewtime - (pagetime / 10)) / TIME_DIMENSION)); } if((viewtime_sync==VIEWTIME_SYNCED_OFFSET)||(viewtime_sync==VIEWTIME_SYNCED_ABSOLUT)||(viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { for(i=0; iviewtime -= (pagetime / 10); } } if(viewtime_sync==VIEWTIME_UNSYNCED) { edfheaderlist[sel_viewtime]->viewtime -= (pagetime / 10); } setup_viewbuf(); } void UI_Mainwindow::shift_page_right() { int i; if(video_player->status == VIDEO_STATUS_PLAYING) { video_player_seek((int)((edfheaderlist[sel_viewtime]->viewtime + (pagetime / 10)) / TIME_DIMENSION)); return; } if(video_player->status == VIDEO_STATUS_PAUSED) { video_player_seek((int)((edfheaderlist[sel_viewtime]->viewtime + (pagetime / 10)) / TIME_DIMENSION)); } if((viewtime_sync==VIEWTIME_SYNCED_OFFSET)||(viewtime_sync==VIEWTIME_SYNCED_ABSOLUT)||(viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { for(i=0; iviewtime += (pagetime / 10); } } if(viewtime_sync==VIEWTIME_UNSYNCED) { edfheaderlist[sel_viewtime]->viewtime += (pagetime / 10); } setup_viewbuf(); } void UI_Mainwindow::playback_realtime() { if(!signalcomps) { return; } if(live_stream_active) { return; } if(video_player->status == VIDEO_STATUS_PLAYING) { return; } if(playback_realtime_active) { stop_playback_realtime(); } else { playback_realtime_time->start(); playback_realtime_timer->start(); playback_realtime_Act->setText("[stop]"); playback_realtime_active = 1; } } void UI_Mainwindow::stop_playback_realtime() { playback_realtime_timer->stop(); playback_realtime_Act->setText("[play]"); playback_realtime_active = 0; } void UI_Mainwindow::playback_realtime_timer_func() { if((viewtime_sync==VIEWTIME_SYNCED_OFFSET)||(viewtime_sync==VIEWTIME_SYNCED_ABSOLUT)||(viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { for(int i=0; iviewtime += (playback_realtime_time->restart() * 10000); } } if(viewtime_sync==VIEWTIME_UNSYNCED) { edfheaderlist[sel_viewtime]->viewtime += (playback_realtime_time->restart() * 10000); } setup_viewbuf(); } void UI_Mainwindow::next_page() { int i; if(video_player->status == VIDEO_STATUS_PLAYING) { video_player_seek((int)((edfheaderlist[sel_viewtime]->viewtime + pagetime) / TIME_DIMENSION)); return; } if(video_player->status == VIDEO_STATUS_PAUSED) { video_player_seek((int)((edfheaderlist[sel_viewtime]->viewtime + pagetime) / TIME_DIMENSION)); } if((viewtime_sync==VIEWTIME_SYNCED_OFFSET)||(viewtime_sync==VIEWTIME_SYNCED_ABSOLUT)||(viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { for(i=0; iviewtime += pagetime; } } if(viewtime_sync==VIEWTIME_UNSYNCED) { edfheaderlist[sel_viewtime]->viewtime += pagetime; } setup_viewbuf(); } void UI_Mainwindow::shift_page_up() { int i; for(i=0; iscreen_offset += (height() / 20.0); } maincurve->drawCurve_stage_1(); } void UI_Mainwindow::shift_page_down() { int i; for(i=0; iscreen_offset -= (height() / 20.0); } maincurve->drawCurve_stage_1(); } void UI_Mainwindow::show_annotations() { int i; EDF_annotations annotations; for(i=0; iannots_not_read) { if((edfheaderlist[i]->edfplus) || (edfheaderlist[i]->bdfplus)) { edfheaderlist[i]->annots_not_read = 0; annotations.get_annotations(i, edfheaderlist[i], &annotationlist[i], read_nk_trigger_signal); if(edfheaderlist[i]->annots_not_read) { edfplus_annotation_delete_list(&annotationlist[i]); } else { if(annotations_dock[i] == NULL) { annotations_dock[i] = new UI_Annotationswindow(i, this); addDockWidget(Qt::RightDockWidgetArea, annotations_dock[i]->docklist, Qt::Vertical); } } } } if(annotationlist[i] != NULL) { if(annotations_dock[i] != NULL) { annotations_dock[i]->docklist->show(); } } } } void UI_Mainwindow::annotation_editor() { stop_video_generic(); stop_playback_realtime(); if(files_open==1) { if(edfheaderlist[0]->annots_not_read) { edfplus_annotation_delete_list(&annotationlist[0]); if(annotations_dock[0] != NULL) { annotations_dock[0]->docklist->close(); delete annotations_dock[0]; annotations_dock[0] = NULL; } edfheaderlist[0]->annots_not_read = 0; EDF_annotations annotations; annotations.get_annotations(0, edfheaderlist[0], &annotationlist[0], read_nk_trigger_signal); if(edfheaderlist[0]->annots_not_read) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Editing annotations is not possible when you abort the scanning of the file."); messagewindow.exec(); return; } } if(annotations_dock[0]==NULL) { annotations_dock[0] = new UI_Annotationswindow(0, this); addDockWidget(Qt::RightDockWidgetArea, annotations_dock[0]->docklist, Qt::Vertical); } annotations_dock[0]->docklist->show(); annotationEditDock->dockedit->show(); } else { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Editing annotations is possible when you have opened one file only."); messagewindow.exec(); } } void UI_Mainwindow::show_spectrum_dock() { UI_SignalChooser signalchooserdialog(this, 1); } void UI_Mainwindow::open_new_file() { FILE *newfile; int i, len, present, position, button_nr=0; char str[2048]; str[0] = 0; struct edfhdrblock *edfhdr=NULL; if(annot_editor_active && files_open) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "You can not open multiple files when editing annotations.\n" "Close the annotation edit window first."); messagewindow.exec(); cmdlineargument = 0; return; } if((files_open > 0) && (live_stream_active)) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "You can not open multiple files while a streaming file is open.\n" "Close the streaming file first."); messagewindow.exec(); return; } if(files_open >= MAXFILES) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There are too many files opened."); messagewindow.exec(); cmdlineargument = 0; return; } if(cmdlineargument == 0) { strcpy(path, QFileDialog::getOpenFileName(this, "Open file", QString::fromLocal8Bit(recent_opendir), "EDF/BDF files (*.edf *.EDF *.bdf *.BDF *.rec *.REC)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(recent_opendir, path, MAX_PATH_LENGTH); } if((cmdlineargument == 0) || (cmdlineargument == 1)) { montagepath[0] = 0; } present = 0; for(i=0; i0; i--) { strcpy(&recent_file_path[i][0], &recent_file_path[i-1][0]); strcpy(&recent_file_mtg_path[i][0], &recent_file_mtg_path[i-1][0]); } } else { for(i=MAX_RECENTFILES-1; i>0; i--) { strcpy(&recent_file_path[i][0], &recent_file_path[i-1][0]); strcpy(&recent_file_mtg_path[i][0], &recent_file_mtg_path[i-1][0]); } } strcpy(&recent_file_path[0][0], path); strcpy(&recent_file_mtg_path[0][0], montagepath); recent_filesmenu->clear(); for(i=0; iaddAction(QString::fromLocal8Bit(&recent_file_path[i][0])); } present = 0; for(i=0; ifilename, path)) { present = 1; break; } } if(!present) { len = strlen(path); if((strcmp(path + (len - 4), ".edf")) &&(strcmp(path + (len - 4), ".EDF")) &&(strcmp(path + (len - 4), ".rec")) &&(strcmp(path + (len - 4), ".REC")) &&(strcmp(path + (len - 4), ".bdf")) &&(strcmp(path + (len - 4), ".BDF"))) { snprintf(str, 2048, "File has an unknown extension: \"%s\"", path + (len - 4)); QMessageBox messagewindow(QMessageBox::Critical, "Error", QString::fromLocal8Bit(str)); messagewindow.exec(); cmdlineargument = 0; return; } newfile = fopeno(path, "rb"); if(newfile==NULL) { snprintf(str, 2048, "Can not open file for reading:\n\"%s\"\n" "Check if you have the right permissions.", path); QMessageBox messagewindow(QMessageBox::Critical, "Error", QString::fromLocal8Bit(str)); messagewindow.exec(); cmdlineargument = 0; return; } strcpy(recent_opendir, path); if(len) { for(i=len-1; i>=0; i--) { if((path[i] == '/')||(path[i] == '\\')) { break; } } } recent_opendir[i] = 0; EDFfileCheck EDFfilechecker; edfhdr = EDFfilechecker.check_edf_file(newfile, str, live_stream_active); if(edfhdr==NULL) { fclose(newfile); strcat(str, "\n File is not a valid EDF or BDF file."); QMessageBox messagewindow(QMessageBox::Critical, "Error", str); messagewindow.exec(); cmdlineargument = 0; return; } if(edfhdr->discontinuous) { if(edfhdr->edf) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "EDFbrowser can not show EDF+D (discontiguous) files.\n" "Convert this file to EDF+C first. You can find this converter\n" "in the Tools menu (EDF+D to EDF+C converter)."); messagewindow.exec(); } if(edfhdr->bdf) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "EDFbrowser can not show BDF+D (discontiguous) files.\n" "Convert this file to BDF+C first. You can find this converter\n" "in the Tools menu (EDF+D to EDF+C converter)."); messagewindow.exec(); } free(edfhdr->edfparam); free(edfhdr); fclose(newfile); cmdlineargument = 0; return; } strcpy(edfhdr->filename, path); edfhdr->file_hdl = newfile; edfhdr->file_num = files_open; edfheaderlist[files_open] = edfhdr; annotationlist[files_open] = NULL; annotations_dock[files_open] = NULL; if((edfhdr->edfplus || edfhdr->bdfplus) && (!live_stream_active)) { if((edfhdr->datarecords * (long long)edfhdr->recordsize) <= maxfilesize_to_readin_annotations) { EDF_annotations annotations; annotations.get_annotations(files_open, edfhdr, &annotationlist[files_open], read_nk_trigger_signal); if(edfhdr->annots_not_read) { edfplus_annotation_delete_list(&annotationlist[files_open]); } else { annotations_dock[files_open] = new UI_Annotationswindow(files_open, this); addDockWidget(Qt::RightDockWidgetArea, annotations_dock[files_open]->docklist, Qt::Vertical); if(!annotationlist[files_open]) { annotations_dock[files_open]->docklist->hide(); } } } else { edfhdr->annots_not_read = 1; } } if((edfhdr->bdf && (!edfhdr->bdfplus) && read_biosemi_status_signal) && (!live_stream_active)) { if((edfhdr->datarecords * (long long)edfhdr->recordsize) <= maxfilesize_to_readin_annotations) { BDF_triggers bdf_triggers_obj; bdf_triggers_obj.get_triggers(edfhdr, &annotationlist[files_open]); annotations_dock[files_open] = new UI_Annotationswindow(files_open, this); addDockWidget(Qt::RightDockWidgetArea, annotations_dock[files_open]->docklist, Qt::Vertical); if(!annotationlist[files_open]) { annotations_dock[files_open]->docklist->hide(); } } } if(!files_open) { edfheaderlist[0]->viewtime = 0; setMainwindowTitle(edfhdr); } else { if(viewtime_sync==VIEWTIME_SYNCED_OFFSET) { edfheaderlist[files_open]->viewtime = edfheaderlist[sel_viewtime]->viewtime; } if(viewtime_sync==VIEWTIME_UNSYNCED) { edfheaderlist[files_open]->viewtime = 0; } if(viewtime_sync==VIEWTIME_SYNCED_ABSOLUT) { edfheaderlist[files_open]->viewtime = edfheaderlist[sel_viewtime]->viewtime + edfheaderlist[sel_viewtime]->starttime_offset - edfheaderlist[files_open]->starttime_offset - ((edfheaderlist[files_open]->utc_starttime - edfheaderlist[sel_viewtime]->utc_starttime) * TIME_DIMENSION); } if(viewtime_sync==VIEWTIME_USER_DEF_SYNCED) { edfheaderlist[files_open]->viewtime = 0; } } sel_viewtime_act[files_open] = new QAction(QString::fromLocal8Bit(edfhdr->filename), this); sel_viewtime_act[files_open]->setCheckable(true); if(!files_open) { sel_viewtime_act[files_open]->setChecked(true); } sel_viewtime_act_group->addAction(sel_viewtime_act[files_open]); timemenu->addAction(sel_viewtime_act[files_open]); files_open++; } if((montagepath[0]!=0)&&(cmdlineargument==2)) { UI_LoadMontagewindow load_mtg(this, montagepath); strcpy(&recent_file_mtg_path[0][0], montagepath); } else { if((recent_file_mtg_path[0][0] != 0) && (files_open == 1) && auto_reload_mtg) { QMessageBox messagewindow; messagewindow.setText("Load last used montage?"); messagewindow.setInformativeText(QString::fromLocal8Bit(&recent_file_mtg_path[0][0])); messagewindow.setIcon(QMessageBox::Question); messagewindow.setStandardButtons(QMessageBox::Yes | QMessageBox::No); messagewindow.setDefaultButton(QMessageBox::Yes); button_nr = messagewindow.exec(); if(button_nr == QMessageBox::No) { recent_file_mtg_path[0][0] = 0; UI_Signalswindow signalwindow(this); } else { UI_LoadMontagewindow load_mtg(this, &recent_file_mtg_path[0][0]); if(recent_file_mtg_path[0][0] == 0) { UI_Signalswindow signalwindow(this); } } } else { UI_Signalswindow signalwindow(this); } } cmdlineargument = 0; close_filemenu->addAction(QString::fromLocal8Bit(path)); } void UI_Mainwindow::remove_recent_file_mtg_path(const char *mtg_path) { int i; for(i=0; iedfplus || edfhdr->bdfplus) { snprintf(str, 256, PROGRAM_NAME " subject %s birthdate %s startdate %s", edfhdr->plus_patient_name, edfhdr->plus_birthdate, edfhdr->plus_startdate); } else { utc_to_date_time(edfhdr->utc_starttime, &date_time); date_time.month_str[0] += 32; date_time.month_str[1] += 32; date_time.month_str[2] += 32; snprintf(str, 256, PROGRAM_NAME " %s startdate %i %s %i", edfhdr->patient, date_time.day, date_time.month_str, date_time.year); len = strlen(str); for(i=0; ifilename, MAX_PATH_LENGTH); strcat(str, " - " PROGRAM_NAME); } if(mainwindow_title_type == 2) { strcpy(str, edfhdr->filename); strcat(str, " - " PROGRAM_NAME); } setWindowTitle(str); } void UI_Mainwindow::signalproperties_dialog() { UI_SignalChooser signalchooserdialog(this, 0); } void UI_Mainwindow::filterproperties_dialog() { UI_SignalChooser signalchooserdialog(this, 2); } void UI_Mainwindow::add_signals_dialog() { UI_Signalswindow signalwindow(this); } void UI_Mainwindow::show_splashscreen() { splash = new QSplashScreen(this, *pixmap, Qt::WindowStaysOnTopHint); splash->show(); } void UI_Mainwindow::show_file_info() { UI_EDFhdrwindow showhdr(this); } void UI_Mainwindow::remove_all_filters() { int i, j, update_scr=0; for(i=0; ifilter_cnt; j++) { free(signalcomp[i]->filter[j]); update_scr = 1; } signalcomp[i]->filter_cnt = 0; for(j=0; jfidfilter_cnt; j++) { free(signalcomp[i]->fidfilter[j]); fid_run_free(signalcomp[i]->fid_run[j]); fid_run_freebuf(signalcomp[i]->fidbuf[j]); fid_run_freebuf(signalcomp[i]->fidbuf2[j]); update_scr = 1; } signalcomp[i]->fidfilter_cnt = 0; for(j=0; jravg_filter_cnt; j++) { free_ravg_filter(signalcomp[i]->ravg_filter[j]); update_scr = 1; } signalcomp[i]->ravg_filter_cnt = 0; if(signalcomp[i]->ecg_filter != NULL) { free_ecg_filter(signalcomp[i]->ecg_filter); signalcomp[i]->ecg_filter = NULL; strcpy(signalcomp[i]->signallabel, signalcomp[i]->signallabel_bu); signalcomp[i]->signallabellen = signalcomp[i]->signallabellen_bu; strcpy(signalcomp[i]->physdimension, signalcomp[i]->physdimension_bu); } if(signalcomp[i]->zratio_filter != NULL) { free_zratio_filter(signalcomp[i]->zratio_filter); signalcomp[i]->zratio_filter = NULL; strcpy(signalcomp[i]->signallabel, signalcomp[i]->signallabel_bu); signalcomp[i]->signallabellen = signalcomp[i]->signallabellen_bu; strcpy(signalcomp[i]->physdimension, signalcomp[i]->physdimension_bu); } } if(update_scr) { setup_viewbuf(); } } void UI_Mainwindow::remove_all_spike_filters() { int i, update_scr=0; for(i=0; ispike_filter) { free_spike_filter(signalcomp[i]->spike_filter); signalcomp[i]->spike_filter = NULL; update_scr = 1; } } if(update_scr) { setup_viewbuf(); } } void UI_Mainwindow::remove_all_signals() { int i; stop_video_generic(); stop_playback_realtime(); for(i=0; iclear(); spectrumdock[i]->dock->hide(); } for(i=0; icrosshair_1.active = 0; maincurve->crosshair_2.active = 0; maincurve->crosshair_1.moving = 0; maincurve->crosshair_2.moving = 0; remove_all_filters(); remove_all_spike_filters(); for(i=0; isetEnabled(false); positionslider->blockSignals(true); setup_viewbuf(); } void UI_Mainwindow::close_file_action_func(QAction *action) { int i, j, k, p, file_n; char f_path[MAX_PATH_LENGTH]; if(files_open < 2) { close_all_files(); return; } strcpy(f_path, action->text().toLocal8Bit().data()); for(file_n=0; file_nfilename)) { break; } } if(file_n == files_open) return; delete action; stop_video_generic(); stop_playback_realtime(); for(j=0; jfilenum == file_n) { for(i=0; isignalcomp == signalcomp[j]) { spectrumdock[i]->clear(); spectrumdock[i]->dock->hide(); } } for(i=0; ispectr_dialog[i]; if(p != 0) { delete spectrumdialog[p - 1]; spectrumdialog[p - 1] = NULL; } } for(i=0; iavg_dialog[i]; if(p != 0) { delete averagecurvedialog[p - 1]; averagecurvedialog[p - 1] = NULL; } } for(i=0; izscoredialog[i]; if(p != 0) { delete zscoredialog[p - 1]; zscoredialog[p - 1] = NULL; } } if(signalcomp[j]->hascursor2) { maincurve->crosshair_2.active = 0; maincurve->crosshair_2.moving = 0; } if(signalcomp[j]->hascursor1) { maincurve->crosshair_1.active = 0; maincurve->crosshair_2.active = 0; maincurve->crosshair_1.moving = 0; maincurve->crosshair_2.moving = 0; for(i=0; ihascursor2 = 0; } } if(signalcomp[j]->hasruler) { maincurve->ruler_active = 0; maincurve->ruler_moving = 0; } for(k=0; kfilter_cnt; k++) { free(signalcomp[j]->filter[k]); } signalcomp[j]->filter_cnt = 0; if(signalcomp[j]->spike_filter) { free_spike_filter(signalcomp[j]->spike_filter); signalcomp[j]->spike_filter = NULL; } for(k=0; kravg_filter_cnt; k++) { free_ravg_filter(signalcomp[j]->ravg_filter[k]); } signalcomp[j]->ravg_filter_cnt = 0; if(signalcomp[j]->ecg_filter != NULL) { free_ecg_filter(signalcomp[j]->ecg_filter); signalcomp[j]->ecg_filter = NULL; strcpy(signalcomp[j]->signallabel, signalcomp[j]->signallabel_bu); signalcomp[j]->signallabellen = signalcomp[j]->signallabellen_bu; strcpy(signalcomp[j]->physdimension, signalcomp[j]->physdimension_bu); } for(k=0; kfidfilter_cnt; k++) { free(signalcomp[j]->fidfilter[k]); fid_run_free(signalcomp[j]->fid_run[k]); fid_run_freebuf(signalcomp[j]->fidbuf[k]); fid_run_freebuf(signalcomp[j]->fidbuf2[k]); } signalcomp[j]->fidfilter_cnt = 0; free(signalcomp[j]); for(i=j; ifilenum > file_n) { signalcomp[j]->filenum--; } } fclose(edfheaderlist[file_n]->file_hdl); free(edfheaderlist[file_n]->edfparam); free(edfheaderlist[file_n]); edfplus_annotation_delete_list(&annotationlist[file_n]); if(annotations_dock[file_n] != NULL) { annotations_dock[file_n]->docklist->close(); delete annotations_dock[file_n]; annotations_dock[file_n] = NULL; } if((file_n == sel_viewtime) && (files_open > 1)) { if(file_n > 0) { sel_viewtime = 0; } else { sel_viewtime = 1; } sel_viewtime_act[sel_viewtime]->setChecked(true); setMainwindowTitle(edfheaderlist[sel_viewtime]); } delete sel_viewtime_act[file_n]; for(i=file_n; istop(); toolsmenu->setEnabled(true); timemenu->setEnabled(true); // windowmenu->setEnabled(true); windowmenu->actions().at(0)->setEnabled(true); // Annotations window windowmenu->actions().at(1)->setEnabled(true); // Annotation editor former_page_Act->setEnabled(true); shift_page_left_Act->setEnabled(true); shift_page_right_Act->setEnabled(true); next_page_Act->setEnabled(true); shift_page_up_Act->setEnabled(true); shift_page_down_Act->setEnabled(true); printmenu->setEnabled(true); recent_filesmenu->setEnabled(true); playback_realtime_Act->setEnabled(true); if(annotations_edited) { QMessageBox messagewindow; messagewindow.setText("There are unsaved annotations,\n are you sure you want to close this file?"); messagewindow.setIcon(QMessageBox::Question); messagewindow.setStandardButtons(QMessageBox::Cancel | QMessageBox::Close); messagewindow.setDefaultButton(QMessageBox::Cancel); button_nr = messagewindow.exec(); } if(button_nr == QMessageBox::Cancel) { return; } annotations_edited = 0; remove_all_signals(); while(files_open) { files_open--; if(edfheaderlist[files_open]->file_hdl != NULL) { fclose(edfheaderlist[files_open]->file_hdl); } free(edfheaderlist[files_open]->edfparam); free(edfheaderlist[files_open]); edfplus_annotation_delete_list(&annotationlist[files_open]); if(annotations_dock[files_open] != NULL) { annotations_dock[files_open]->docklist->close(); delete annotations_dock[files_open]; annotations_dock[files_open] = NULL; } delete sel_viewtime_act[files_open]; } edfplus_annotation_delete_list(&annotationlist_backup); sel_viewtime = 0; pagetime = 10 * TIME_DIMENSION; timescale_doubler = 10; amplitude_doubler = 10; for(i=0; i<64; i++) { zoomhistory->pntr = 0; zoomhistory->pagetime[i] = 10 * TIME_DIMENSION; for(j=0; jviewtime[i][j] = 0; } for(j=0; jvoltpercm[i][j] = 70; zoomhistory->screen_offset[i][j] = 0.0; for(k=0; ksensitivity[i][j][k] = 0.0475; } } } annotationEditDock->dockedit->hide(); save_act->setEnabled(false); annotations_edited = 0; setWindowTitle(PROGRAM_NAME); close_filemenu->clear(); if(!exit_in_progress) { setup_viewbuf(); } } void UI_Mainwindow::show_about_dialog() { UI_Aboutwindow aboutwindow(this); } void UI_Mainwindow::page_3cmsec() { double mm; if(auto_dpi) { mm = maincurve->widthMM(); pagetime = mm * 333333.3333; } else { pagetime = (long long)((((double)maincurve->width()) / (1.0 / x_pixelsizefactor) / 3.0) * TIME_DIMENSION); } setup_viewbuf(); } void UI_Mainwindow::set_page_div2() { int i; long long l_tmp, trshld=100LL; if((viewtime_sync==VIEWTIME_SYNCED_OFFSET)||(viewtime_sync==VIEWTIME_SYNCED_ABSOLUT)||(viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { for(i=0; iviewtime += (pagetime * 0.3); } else { edfheaderlist[i]->viewtime += (pagetime / 4); } if(viewtime_sync!=VIEWTIME_USER_DEF_SYNCED) { l_tmp = edfheaderlist[i]->viewtime % TIME_DIMENSION; if(l_tmp < trshld) { edfheaderlist[i]->viewtime -= l_tmp; } if(l_tmp > (TIME_DIMENSION - trshld)) { edfheaderlist[i]->viewtime += (TIME_DIMENSION - l_tmp); } } } } if(viewtime_sync==VIEWTIME_UNSYNCED) { if(timescale_doubler == 50) { edfheaderlist[sel_viewtime]->viewtime += (pagetime * 0.3); } else { edfheaderlist[sel_viewtime]->viewtime += (pagetime / 4); } l_tmp = edfheaderlist[sel_viewtime]->viewtime % TIME_DIMENSION; if(l_tmp < trshld) { edfheaderlist[sel_viewtime]->viewtime -= l_tmp; } if(l_tmp > (TIME_DIMENSION - trshld)) { edfheaderlist[sel_viewtime]->viewtime += (TIME_DIMENSION - l_tmp); } } if(timescale_doubler == 10) { timescale_doubler = 50; pagetime /= 2; } else { if(timescale_doubler == 50) { timescale_doubler = 20; pagetime /= 2.5; } else { timescale_doubler = 10; pagetime /= 2; } } setup_viewbuf(); } void UI_Mainwindow::set_page_mult2() { int i; long long l_tmp, trshld=100LL; if((viewtime_sync==VIEWTIME_SYNCED_OFFSET)||(viewtime_sync==VIEWTIME_SYNCED_ABSOLUT)||(viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { for(i=0; iviewtime -= (pagetime * 0.75); } else { edfheaderlist[i]->viewtime -= (pagetime / 2); } if(viewtime_sync!=VIEWTIME_USER_DEF_SYNCED) { l_tmp = edfheaderlist[i]->viewtime % TIME_DIMENSION; if(l_tmp < trshld) { edfheaderlist[i]->viewtime -= l_tmp; } if(l_tmp > (TIME_DIMENSION - trshld)) { edfheaderlist[i]->viewtime += (TIME_DIMENSION - l_tmp); } } } } if(viewtime_sync==VIEWTIME_UNSYNCED) { if(timescale_doubler == 20) { edfheaderlist[sel_viewtime]->viewtime -= (pagetime * 0.75); } else { edfheaderlist[sel_viewtime]->viewtime -= (pagetime / 2); } l_tmp = edfheaderlist[sel_viewtime]->viewtime % TIME_DIMENSION; if(l_tmp < trshld) { edfheaderlist[sel_viewtime]->viewtime -= l_tmp; } if(l_tmp > (TIME_DIMENSION - trshld)) { edfheaderlist[sel_viewtime]->viewtime += (TIME_DIMENSION - l_tmp); } } if(timescale_doubler == 10) { timescale_doubler = 20; pagetime *= 2; } else { if(timescale_doubler == 20) { timescale_doubler = 50; pagetime *= 2.5; } else { timescale_doubler = 10; pagetime *= 2; } } setup_viewbuf(); } void UI_Mainwindow::set_display_time(QAction *action) { if(action==page_10u) { pagetime = TIME_DIMENSION / 100000; timescale_doubler = 10; } if(action==page_20u) { pagetime = TIME_DIMENSION / 50000; timescale_doubler = 20; } if(action==page_50u) { pagetime = TIME_DIMENSION / 20000; timescale_doubler = 50; } if(action==page_100u) { pagetime = TIME_DIMENSION / 10000; timescale_doubler = 10; } if(action==page_200u) { pagetime = TIME_DIMENSION / 5000; timescale_doubler = 20; } if(action==page_500u) { pagetime = TIME_DIMENSION / 2000; timescale_doubler = 50; } if(action==page_1m) { pagetime = TIME_DIMENSION / 1000; timescale_doubler = 10; } if(action==page_2m) { pagetime = TIME_DIMENSION / 500; timescale_doubler = 20; } if(action==page_5m) { pagetime = TIME_DIMENSION / 200; timescale_doubler = 50; } if(action==page_10m) { pagetime = TIME_DIMENSION / 100; timescale_doubler = 10; } if(action==page_20m) { pagetime = TIME_DIMENSION / 50; timescale_doubler = 20; } if(action==page_50m) { pagetime = TIME_DIMENSION / 20; timescale_doubler = 50; } if(action==page_100m) { pagetime = TIME_DIMENSION / 10; timescale_doubler = 10; } if(action==page_200m) { pagetime = TIME_DIMENSION / 5; timescale_doubler = 20; } if(action==page_500m) { pagetime = TIME_DIMENSION / 2; timescale_doubler = 50; } if(action==page_1) { pagetime = TIME_DIMENSION; timescale_doubler = 10; } if(action==page_2) { pagetime = TIME_DIMENSION * 2; timescale_doubler = 20; } if(action==page_5) { pagetime = TIME_DIMENSION * 5; timescale_doubler = 50; } if(action==page_10) { pagetime = TIME_DIMENSION * 10; timescale_doubler = 10; } if(action==page_15) pagetime = TIME_DIMENSION * 15; if(action==page_20) { pagetime = TIME_DIMENSION * 20; timescale_doubler = 20; } if(action==page_30) pagetime = TIME_DIMENSION * 30; if(action==page_60) pagetime = TIME_DIMENSION * 60; if(action==page_300) pagetime = TIME_DIMENSION * 300; if(action==page_1200) pagetime = TIME_DIMENSION * 1200; if(action==page_3600) pagetime = TIME_DIMENSION * 3600; setup_viewbuf(); } void UI_Mainwindow::set_user_defined_display_time() { UI_Userdefined_timepage_Dialog set_displaytime_dialog(this); } void UI_Mainwindow::set_display_time_whole_rec() { int i; if(!files_open) return; if(viewtime_sync==VIEWTIME_SYNCED_OFFSET) { for(i=0; iviewtime = 0; } } if(viewtime_sync==VIEWTIME_UNSYNCED) { edfheaderlist[sel_viewtime]->viewtime = 0; } if(viewtime_sync==VIEWTIME_SYNCED_ABSOLUT) { edfheaderlist[sel_viewtime]->viewtime = 0; for(i=0; iviewtime = ((edfheaderlist[sel_viewtime]->utc_starttime - edfheaderlist[i]->utc_starttime) * TIME_DIMENSION) + edfheaderlist[sel_viewtime]->starttime_offset - - edfheaderlist[i]->starttime_offset; } } } if(viewtime_sync==VIEWTIME_USER_DEF_SYNCED) { for(i=0; iviewtime -= edfheaderlist[sel_viewtime]->viewtime; } } edfheaderlist[sel_viewtime]->viewtime = 0; } pagetime = edfheaderlist[sel_viewtime]->datarecords * edfheaderlist[sel_viewtime]->long_data_record_duration; setup_viewbuf(); } void UI_Mainwindow::fit_signals_to_pane() { int i, j, pane_size; if(!signalcomps) return; pane_size = maincurve->height() / (signalcomps + 1); for(i=0; inum_of_signals; j++) { if(signalcomp[i]->max_dig_value!=signalcomp[i]->min_dig_value) { signalcomp[i]->sensitivity[j] = (double)pane_size / (double)(signalcomp[i]->max_dig_value - signalcomp[i]->min_dig_value); } else { signalcomp[i]->sensitivity[j] = pane_size; } } signalcomp[i]->voltpercm = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue / (signalcomp[i]->sensitivity[0] * pixelsizefactor); signalcomp[i]->screen_offset = ((signalcomp[i]->max_dig_value + signalcomp[i]->min_dig_value) / 2.0) * signalcomp[i]->sensitivity[0] * signalcomp[i]->polarity; } maincurve->drawCurve_stage_1(); } void UI_Mainwindow::fit_signals_dc_offset() { int i; if(!signalcomps) return; for(i=0; iscreen_offset = ((signalcomp[i]->max_dig_value + signalcomp[i]->min_dig_value) / 2.0) * signalcomp[i]->sensitivity[0] * signalcomp[i]->polarity; } maincurve->drawCurve_stage_1(); } void UI_Mainwindow::set_amplitude(QAction *action) { int i, j; double value=100.0, original_value, value2=100.0; if(action==amp_00001) { value = 0.0001; amplitude_doubler = 10; } if(action==amp_00002) { value = 0.0002; amplitude_doubler = 20; } if(action==amp_00005) { value = 0.0005; amplitude_doubler = 50; } if(action==amp_0001) { value = 0.001; amplitude_doubler = 10; } if(action==amp_0002) { value = 0.002; amplitude_doubler = 20; } if(action==amp_0005) { value = 0.005; amplitude_doubler = 50; } if(action==amp_001) { value = 0.01; amplitude_doubler = 10; } if(action==amp_002) { value = 0.02; amplitude_doubler = 20; } if(action==amp_005) { value = 0.05; amplitude_doubler = 50; } if(action==amp_01) { value = 0.1; amplitude_doubler = 10; } if(action==amp_02) { value = 0.2; amplitude_doubler = 20; } if(action==amp_05) { value = 0.5; amplitude_doubler = 50; } if(action==amp_1) { value = 1.0; amplitude_doubler = 10; } if(action==amp_2) { value = 2.0; amplitude_doubler = 20; } if(action==amp_5) { value = 5.0; amplitude_doubler = 50; } if(action==amp_10) { value = 10.0; amplitude_doubler = 10; } if(action==amp_20) { value = 20.0; amplitude_doubler = 20; } if(action==amp_50) { value = 50.0; amplitude_doubler = 50; } if(action==amp_100) { value = 100.0; amplitude_doubler = 10; } if(action==amp_200) { value = 200.0; amplitude_doubler = 20; } if(action==amp_500) { value = 500.0; amplitude_doubler = 50; } if(action==amp_1000) { value = 1000.0; amplitude_doubler = 10; } if(action==amp_2000) { value = 2000.0; amplitude_doubler = 20; } if(action==amp_5000) { value = 5000.0; amplitude_doubler = 50; } if(action==amp_10000) { value = 10000.0; amplitude_doubler = 10; } if(action==amp_20000) { value = 20000.0; amplitude_doubler = 20; } if(action==amp_50000) { value = 50000.0; amplitude_doubler = 50; } for(i=0; iedfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue < 0.0) { value2 *= -1.0; } for(j=0; jnum_of_signals; j++) { signalcomp[i]->sensitivity[j] = (signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].bitvalue / value2) / pixelsizefactor; } original_value = signalcomp[i]->voltpercm; signalcomp[i]->voltpercm = value2; signalcomp[i]->screen_offset *= (original_value / value2); } maincurve->drawCurve_stage_1(); } void UI_Mainwindow::set_amplitude_mult2() { int i, j; for(i=0; ivoltpercm < 0) { if(signalcomp[i]->voltpercm < -5000000.0) { return; } } else { if(signalcomp[i]->voltpercm > 5000000.0) { return; } } } for(i=0; ivoltpercm *= 2; signalcomp[i]->screen_offset /= 2; } else { signalcomp[i]->voltpercm *= 2.5; signalcomp[i]->screen_offset /= 2.5; } for(j=0; jnum_of_signals; j++) { signalcomp[i]->sensitivity[j] = (signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].bitvalue / signalcomp[i]->voltpercm) / pixelsizefactor; } } if(amplitude_doubler == 10) { amplitude_doubler = 20; } else { if(amplitude_doubler == 20) { amplitude_doubler = 50; } else { amplitude_doubler = 10; } } maincurve->drawCurve_stage_1(); } void UI_Mainwindow::set_amplitude_div2() { int i, j; for(i=0; ivoltpercm < 0) { if(signalcomp[i]->voltpercm > -0.000001) { return; } } else { if(signalcomp[i]->voltpercm < 0.000001) { return; } } } for(i=0; ivoltpercm /= 2; signalcomp[i]->screen_offset *= 2; } else { signalcomp[i]->voltpercm /= 2.5; signalcomp[i]->screen_offset *= 2.5; } for(j=0; jnum_of_signals; j++) { signalcomp[i]->sensitivity[j] = (signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].bitvalue / signalcomp[i]->voltpercm) / pixelsizefactor; } } if(amplitude_doubler == 10) { amplitude_doubler = 50; } else { if(amplitude_doubler == 50) { amplitude_doubler = 20; } else { amplitude_doubler = 10; } } maincurve->drawCurve_stage_1(); } void UI_Mainwindow::load_predefined_mtg(QAction *action) { int i; if(!files_open) { return; } for(i=0; i < MAXPREDEFINEDMONTAGES; i++) { if(action==load_predefined_mtg_act[i]) { if(predefined_mtg_path[i][0] != 0) { strcpy(montagepath, &predefined_mtg_path[i][0]); UI_LoadMontagewindow load_mtg(this, montagepath); return; } } } } void UI_Mainwindow::export_to_ascii() { if(!files_open) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "You have to open a file first."); messagewindow.exec(); return; } UI_AsciiExportwindow exportdialog(this); } void UI_Mainwindow::export_ecg_rr_interval_to_ascii() { UI_ECGExport ECG_export(this); } void UI_Mainwindow::export_annotations() { if(!files_open) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "You have to open a file first."); messagewindow.exec(); return; } UI_ExportAnnotationswindow exportAnnotsDialog(this); } void UI_Mainwindow::import_annotations() { UI_ImportAnnotationswindow importAnnotsDialog(this); } void UI_Mainwindow::check_edf_compatibility() { if(!files_open) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "You have to open the file first."); messagewindow.exec(); return; } UI_EDFCompatwindow edfcompatdialog(this); } void UI_Mainwindow::print_to_img_640x480() { maincurve->print_to_image(640, 480); } void UI_Mainwindow::print_to_img_800x600() { maincurve->print_to_image(800, 600); } void UI_Mainwindow::print_to_img_1024x768() { maincurve->print_to_image(1024, 768); } void UI_Mainwindow::print_to_img_1280x1024() { maincurve->print_to_image(1280, 1024); } void UI_Mainwindow::print_to_img_1600x1200() { maincurve->print_to_image(1600, 1200); } long long UI_Mainwindow::get_long_time(char *str) { int i, len, hasdot=0, dotposition=0; long long value=0, radix; str = str + 1; len = strlen(str); for(i=0; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } radix = TIME_DIMENSION / 10; for(i=dotposition+1; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } } if(str[-1]=='-') value = -value; return(value); } void UI_Mainwindow::recent_file_action_func(QAction *action) { strcpy(path, action->text().toLocal8Bit().data()); cmdlineargument = 1; open_new_file(); } void UI_Mainwindow::save_montage() { if(!files_open) return; if(!signalcomps) return; UI_SaveMontagewindow save_mtg(this); } void UI_Mainwindow::load_montage() { if(!files_open) return; UI_LoadMontagewindow load_mtg(this); } void UI_Mainwindow::view_montage() { UI_ViewMontagewindow view_mtg(this); } void UI_Mainwindow::show_this_montage() { UI_ShowActualMontagewindow show_mtg(this); } void UI_Mainwindow::print_to_edf() { print_screen_to_edf(this); } void UI_Mainwindow::print_to_bdf() { print_screen_to_bdf(this); } void UI_Mainwindow::set_dc_offset_to_zero() { int i; if(!signalcomps) { return; } for(i=0; iscreen_offset = 0.0; } maincurve->drawCurve_stage_1(); } void UI_Mainwindow::show_help() { #ifdef Q_OS_LINUX QDesktopServices::openUrl(QUrl("file:///usr/share/doc/edfbrowser/manual.html")); #endif #ifdef Q_OS_WIN32 char p_path[MAX_PATH_LENGTH]; strcpy(p_path, "file:///"); strcat(p_path, specialFolder(CSIDL_PROGRAM_FILES).toLocal8Bit().data()); strcat(p_path, "\\EDFbrowser\\manual.html"); QDesktopServices::openUrl(QUrl(p_path)); #endif } void UI_Mainwindow::show_kb_shortcuts() { QMessageBox messagewindow(QMessageBox::NoIcon, "Keyboard shortcuts", "PgDn\t\tnext page\n" "PgUp\t\tformer page\n" "Right Arrow\t\tshift right one tenth of pagetime\n" "Left Arrow\t\tshift left one tenth of pagetime\n" "Plus\t\tincrease sensitivity\n" "Minus\t\tdecrease sensitivity\n" "Up Arrow\t\tshift up\n" "Down Arrow\t\tshift down\n" "Ctrl-Home\t\tgo to start of file\n" "Ctrl-End\t\tgo to end of file\n" "Ctrl++\t\tzoom in\n" "Ctrl+-\t\tzoom out\n" "F1 - F8\t\tload predefined montage\n" "Esc\t\tremove crosshairs or floating ruler\n" "\nafter zooming in by dragging a rectangle:\n" "Backspace\t\tzoom back\n" "Insert\t\tzoom in\n" #ifdef Q_OS_WIN32 "\nCtrl+O\t\tOpen a file\n" "Ctrl+Shift+O\t\tOpen a stream\n" "Ctrl+F4\tClose all files\n" "Alt+F4\tExit program\n" #else "\nCtrl+O\t\tOpen a file\n" "Ctrl+Shift+O\t\tOpen a stream\n" "Ctrl+W\t\tClose all files\n" "Ctrl+Q\t\tExit program\n" #endif "\nMousewheel\t\tshift left or right\n" "Ctrl+Mousewheel\tzoom in or out\n" "\nCtrl+Space\t\tToggle Playback\n" #ifdef Q_OS_LINUX "Ctrl+Shift+V\t\tPlayback with video" #endif ); messagewindow.exec(); } #ifdef Q_OS_WIN32 QString UI_Mainwindow::specialFolder(int type) { QString result; QLibrary library(QLatin1String("shell32")); QT_WA( { typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPTSTR, int, BOOL); GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW"); if (SHGetSpecialFolderPath) { TCHAR path[MAX_PATH]; SHGetSpecialFolderPath(0, path, type, false); result = QString::fromUtf16((ushort*)path); } } , { typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, char*, int, BOOL); GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathA"); if (SHGetSpecialFolderPath) { char path[MAX_PATH]; SHGetSpecialFolderPath(0, path, type, false); result = QString::fromLocal8Bit(path); } } ); if (result.isEmpty()) { result = QLatin1String("C:\\temp"); } return result; } #endif int UI_Mainwindow::file_is_opened(const char *o_path) { int i; for(i=0; ifilename, o_path)) { return(1); } } return(0); } void UI_Mainwindow::organize_signals() { UI_SignalChooser signalchooser(this, 3); } void UI_Mainwindow::edfplus_annotation_remove_duplicates() { int i, j, k, list_size, dup_cnt=0; char str[256]; struct annotationblock **list, *annot, *annot_cmp; if(!files_open) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "You have to open a file first."); messagewindow.exec(); return; } QProgressDialog progress("Checking for duplicates...", "Abort", 0, 10, this); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); for(k=0; kprocessEvents(); if(progress.wasCanceled() == true) { break; } annot_cmp = edfplus_annotation_item(list, j); for(i=j; ionset != annot_cmp->onset) continue; if(annot->file_num != annot_cmp->file_num) continue; if(strcmp(annot->annotation, annot_cmp->annotation)) continue; if(strcmp(annot->duration, annot_cmp->duration)) continue; edfplus_annotation_delete(list, i); dup_cnt++; list_size--; if(j) j--; if(i) i--; } } } } progress.reset(); if(dup_cnt) { for(k=0; kupdateList(); } } annotations_edited = 1; save_act->setEnabled(true); } snprintf(str, 256, "Removed %i duplicates from the annotationlist(s)", dup_cnt); QMessageBox messagewindow(QMessageBox::Information, "Ready", str); messagewindow.exec(); } struct signalcompblock * UI_Mainwindow::create_signalcomp_copy(struct signalcompblock *original_signalcomp) { int i; char spec_str[256], *filter_spec, *err; struct signalcompblock *newsignalcomp; if(signalcomps >= MAXSIGNALS) { return(NULL); } if(original_signalcomp->ecg_filter != NULL) { return(NULL); } if(original_signalcomp->zratio_filter != NULL) { return(NULL); } newsignalcomp = (struct signalcompblock *)calloc(1, sizeof(struct signalcompblock)); if(newsignalcomp == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "malloc() error"); messagewindow.exec(); return(NULL); } memcpy(newsignalcomp, original_signalcomp, sizeof(struct signalcompblock)); if(newsignalcomp->spike_filter) { newsignalcomp->spike_filter = create_spike_filter_copy(original_signalcomp->spike_filter); if(newsignalcomp->spike_filter == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "malloc() error"); messagewindow.exec(); free(signalcomp); return(NULL); } } for(i=0; ifilter_cnt; i++) { newsignalcomp->filter[i] = create_filter_copy(original_signalcomp->filter[i]); if(newsignalcomp->filter[i] == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "malloc() error"); messagewindow.exec(); free(signalcomp); return(NULL); } } for(i=0; iravg_filter_cnt; i++) { newsignalcomp->ravg_filter[i] = create_ravg_filter_copy(original_signalcomp->ravg_filter[i]); if(newsignalcomp->ravg_filter[i] == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "malloc() error"); messagewindow.exec(); free(signalcomp); return(NULL); } } for(i=0; ifidfilter_cnt; i++) { if(newsignalcomp->fidfilter_type[i] == 0) { if(newsignalcomp->fidfilter_model[i] == 0) { sprintf(spec_str, "HpBu%i/%f", newsignalcomp->fidfilter_order[i], newsignalcomp->fidfilter_freq[i]); } if(newsignalcomp->fidfilter_model[i] == 1) { sprintf(spec_str, "HpCh%i/%f/%f", newsignalcomp->fidfilter_order[i], newsignalcomp->fidfilter_ripple[i], newsignalcomp->fidfilter_freq[i]); } if(newsignalcomp->fidfilter_model[i] == 2) { sprintf(spec_str, "HpBe%i/%f", newsignalcomp->fidfilter_order[i], newsignalcomp->fidfilter_freq[i]); } } if(newsignalcomp->fidfilter_type[i] == 1) { if(newsignalcomp->fidfilter_model[i] == 0) { sprintf(spec_str, "LpBu%i/%f", newsignalcomp->fidfilter_order[i], newsignalcomp->fidfilter_freq[i]); } if(newsignalcomp->fidfilter_model[i] == 1) { sprintf(spec_str, "LpCh%i/%f/%f", newsignalcomp->fidfilter_order[i], newsignalcomp->fidfilter_ripple[i], newsignalcomp->fidfilter_freq[i]); } if(newsignalcomp->fidfilter_model[i] == 2) { sprintf(spec_str, "LpBe%i/%f", newsignalcomp->fidfilter_order[i], newsignalcomp->fidfilter_freq[i]); } } if(newsignalcomp->fidfilter_type[i] == 2) { if(newsignalcomp->fidfilter_model[i] == 0) { sprintf(spec_str, "BsRe/%i/%f", newsignalcomp->fidfilter_order[i], newsignalcomp->fidfilter_freq[i]); } } if(newsignalcomp->fidfilter_type[i] == 3) { if(newsignalcomp->fidfilter_model[i] == 0) { sprintf(spec_str, "BpBu%i/%f-%f", newsignalcomp->fidfilter_order[i], newsignalcomp->fidfilter_freq[i], newsignalcomp->fidfilter_freq2[i]); } if(newsignalcomp->fidfilter_model[i] == 1) { sprintf(spec_str, "BpCh%i/%f/%f-%f", newsignalcomp->fidfilter_order[i], newsignalcomp->fidfilter_ripple[i], newsignalcomp->fidfilter_freq[i], newsignalcomp->fidfilter_freq2[i]); } if(newsignalcomp->fidfilter_model[i] == 2) { sprintf(spec_str, "BpBe%i/%f-%f", newsignalcomp->fidfilter_order[i], newsignalcomp->fidfilter_freq[i], newsignalcomp->fidfilter_freq2[i]); } } if(newsignalcomp->fidfilter_type[i] == 4) { if(newsignalcomp->fidfilter_model[i] == 0) { sprintf(spec_str, "BsBu%i/%f-%f", newsignalcomp->fidfilter_order[i], newsignalcomp->fidfilter_freq[i], newsignalcomp->fidfilter_freq2[i]); } if(newsignalcomp->fidfilter_model[i] == 1) { sprintf(spec_str, "BsCh%i/%f/%f-%f", newsignalcomp->fidfilter_order[i], newsignalcomp->fidfilter_ripple[i], newsignalcomp->fidfilter_freq[i], newsignalcomp->fidfilter_freq2[i]); } if(newsignalcomp->fidfilter_model[i] == 2) { sprintf(spec_str, "BsBe%i/%f-%f", newsignalcomp->fidfilter_order[i], newsignalcomp->fidfilter_freq[i], newsignalcomp->fidfilter_freq2[i]); } } filter_spec = spec_str; err = fid_parse(((double)(newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].smp_per_record)) / newsignalcomp->edfhdr->data_record_duration, &filter_spec, &newsignalcomp->fidfilter[i]); if(err != NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", err); messagewindow.exec(); free(err); free(signalcomp); return(NULL); } newsignalcomp->fid_run[i] = fid_run_new(newsignalcomp->fidfilter[i], &newsignalcomp->fidfuncp[i]); newsignalcomp->fidbuf[i] = fid_run_newbuf(newsignalcomp->fid_run[i]); newsignalcomp->fidbuf2[i] = fid_run_newbuf(newsignalcomp->fid_run[i]); // memcpy(newsignalcomp->fidbuf[i], original_signalcomp->fidbuf[i], fid_run_bufsize(original_signalcomp->fid_run[i])); // memcpy(newsignalcomp->fidbuf2[i], original_signalcomp->fidbuf2[i], fid_run_bufsize(original_signalcomp->fid_run[i])); } signalcomp[signalcomps] = newsignalcomp; signalcomps++; return(newsignalcomp); } edfbrowser_157_source/PaxHeaders.7921/popup_save_cancelwindow.h0000644000000000000000000000012712646460742021761 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/popup_save_cancelwindow.h0000644000175000001440000000321312646460742022315 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef POPUP_CANCELSAVEFORM1_H #define POPUP_CANCELSAVEFORM1_H #include #include #include #include #include #include #include #include "global.h" class UI_CancelSavewindow : public QObject { Q_OBJECT public: UI_CancelSavewindow(const char *, const char *, const char *, const char *, int *); private: QDialog *MessageDialog; QLabel *Label1; QPushButton *pushButton1, *pushButton2; int *buttonnr; private slots: void button1Clicked(); void button2Clicked(); }; #endif edfbrowser_157_source/PaxHeaders.7921/check_edf_file.cpp0000644000000000000000000000013212646460742020264 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/check_edf_file.cpp0000644000175000001440000014113212646460742020627 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "check_edf_file.h" struct edfhdrblock * EDFfileCheck::check_edf_file(FILE *inputfile, char *txt_string, int live_stream) { int i, j, p, r=0, n, dotposition, error; char *edf_hdr, scratchpad[128], scratchpad2[64]; long long l_tmp, l_tmp2; struct date_time_struct date_time; /***************** check header ******************************/ edf_hdr = (char *)calloc(1, 256); if(edf_hdr==NULL) { sprintf(txt_string, "Memory allocation error. (edf_hdr)"); return(NULL); } edfhdr = (struct edfhdrblock *)calloc(1, sizeof(struct edfhdrblock)); if(edfhdr==NULL) { sprintf(txt_string, "Memory allocation error. (edfhdr)"); return(NULL); } rewind(inputfile); if(fread(edf_hdr, 256, 1, inputfile)!=1) { sprintf(txt_string, "Error, reading file"); free(edf_hdr); free(edfhdr); return(NULL); } /**************************** VERSION ***************************************/ strncpy(scratchpad, edf_hdr, 8); scratchpad[8] = 0; if(((signed char *)scratchpad)[0]==-1) // BDF-file { for(i=1; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { sprintf(txt_string, "Error, %ith character of version field is not a valid 7-bit ASCII character.", i + 1); free(edf_hdr); free(edfhdr); return(NULL); } } if(strcmp(scratchpad + 1, "BIOSEMI")) { sprintf(txt_string, "Error, header has unknown version: \".%s\",\n" "expected \".BIOSEMI\"", scratchpad + 1); free(edf_hdr); free(edfhdr); return(NULL); } edfhdr->bdf = 1; } else // EDF-file { for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { sprintf(txt_string, "Error, %ith character of version field is not a valid 7-bit ASCII character.", i + 1); free(edf_hdr); free(edfhdr); return(NULL); } } if(strcmp(scratchpad, "0 ")) { sprintf(txt_string, "Error, header has unknown version: \"%s\",\n" "expected \"0 \"", scratchpad); free(edf_hdr); free(edfhdr); return(NULL); } edfhdr->edf = 1; } strncpy(edfhdr->version, edf_hdr, 8); edfhdr->version[8] = 0; if(edfhdr->bdf) edfhdr->version[0] = '.'; /********************* PATIENTNAME *********************************************/ strncpy(scratchpad, edf_hdr + 8, 80); scratchpad[80] = 0; for(i=0; i<80; i++) { if((((unsigned char *)scratchpad)[i]<32)||(((unsigned char *)scratchpad)[i]>126)) { sprintf(txt_string, "Error, %ith character of local patient identification field is not a valid 7-bit ASCII character.\n" "Use the header editor to fix your file. Look at the manual for the details.", i + 1); free(edf_hdr); free(edfhdr); return(NULL); } } strncpy(edfhdr->patient, edf_hdr + 8, 80); edfhdr->patient[80] = 0; /********************* RECORDING *********************************************/ strncpy(scratchpad, edf_hdr + 88, 80); scratchpad[80] = 0; for(i=0; i<80; i++) { if((((unsigned char *)scratchpad)[i]<32)||(((unsigned char *)scratchpad)[i]>126)) { sprintf(txt_string, "Error, %ith character of local recording identification field is not a valid 7-bit ASCII character.\n" "Use the header editor to fix your file. Look at the manual for the details.", i + 1); free(edf_hdr); free(edfhdr); return(NULL); } } strncpy(edfhdr->recording, edf_hdr + 88, 80); edfhdr->recording[80] = 0; /********************* STARTDATE *********************************************/ strncpy(scratchpad, edf_hdr + 168, 8); scratchpad[8] = 0; for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { sprintf(txt_string, "Error, %ith character of startdate field is not a valid 7-bit ASCII character.", i + 1); free(edf_hdr); free(edfhdr); return(NULL); } } error = 0; if((edf_hdr[170]!='.')||(edf_hdr[173]!='.')) { sprintf(txt_string, "Error, separator character of startdate is not a dot.\n" "You can fix this problem with the header editor, check the manual for details."); free(edf_hdr); free(edfhdr); return(NULL); } if((edf_hdr[168]<48)||(edf_hdr[168]>57)) error = 1; if((edf_hdr[169]<48)||(edf_hdr[169]>57)) error = 1; if((edf_hdr[171]<48)||(edf_hdr[171]>57)) error = 1; if((edf_hdr[172]<48)||(edf_hdr[172]>57)) error = 1; if((edf_hdr[174]<48)||(edf_hdr[174]>57)) error = 1; if((edf_hdr[175]<48)||(edf_hdr[175]>57)) error = 1; strncpy(scratchpad, edf_hdr + 168, 8); if(error) { scratchpad[8] = 0; sprintf(txt_string, "Error, startdate of recording is invalid: \"%s\",\n" "expected \"dd.mm.yy\"", scratchpad); free(edf_hdr); return(NULL); } scratchpad[2] = 0; scratchpad[5] = 0; scratchpad[8] = 0; if((atoi(scratchpad)<1)||(atoi(scratchpad)>31)) { strncpy(scratchpad, edf_hdr + 168, 8); scratchpad[8] = 0; sprintf(txt_string, "Error, startdate of recording is invalid: \"%s\",\n" "expected \"dd.mm.yy\" where \"dd\" should be more than 00 and less than 32", scratchpad); free(edf_hdr); return(NULL); } if((atoi(scratchpad+3)<1)||(atoi(scratchpad+3)>12)) { strncpy(scratchpad, edf_hdr + 168, 8); scratchpad[8] = 0; sprintf(txt_string, "Error, startdate of recording is invalid: \"%s\",\n" "expected \"dd.mm.yy\" where \"mm\" should be more than 00 and less than 13", scratchpad); free(edf_hdr); free(edfhdr); return(NULL); } date_time.day = atoi(scratchpad); date_time.month = atoi(scratchpad + 3); date_time.year = atoi(scratchpad + 6); if(date_time.year>84) { date_time.year += 1900; } else { date_time.year += 2000; } /********************* STARTTIME *********************************************/ strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { sprintf(txt_string, "Error, %ith character of starttime field is not a valid 7-bit ASCII character.", i + 1); free(edf_hdr); free(edfhdr); return(NULL); } } error = 0; if((edf_hdr[178]!='.')||(edf_hdr[181]!='.')) { sprintf(txt_string, "Error, separator character of starttime is not a dot.\n" "You can fix this problem with the header editor, check the manual for details."); free(edf_hdr); free(edfhdr); return(NULL); } if((edf_hdr[176]<48)||(edf_hdr[176]>57)) error = 1; if((edf_hdr[177]<48)||(edf_hdr[177]>57)) error = 1; if((edf_hdr[179]<48)||(edf_hdr[179]>57)) error = 1; if((edf_hdr[180]<48)||(edf_hdr[180]>57)) error = 1; if((edf_hdr[182]<48)||(edf_hdr[182]>57)) error = 1; if((edf_hdr[183]<48)||(edf_hdr[183]>57)) error = 1; strncpy(scratchpad, edf_hdr + 176, 8); if(error) { strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; sprintf(txt_string, "Error, starttime of recording is invalid: \"%s\",\n" "expected \"hh.mm.ss\"", scratchpad); free(edf_hdr); free(edfhdr); return(NULL); } scratchpad[2] = 0; scratchpad[5] = 0; scratchpad[8] = 0; if(atoi(scratchpad)>23) { strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; sprintf(txt_string, "Error, starttime of recording is invalid: \"%s\",\n" "expected \"hh.mm.ss\" where \"hh\" should be less than 24", scratchpad); free(edf_hdr); free(edfhdr); return(NULL); } if(atoi(scratchpad+3)>59) { strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; sprintf(txt_string, "Error, starttime of recording is invalid: \"%s\",\n" "expected \"hh.mm.ss\" where \"mm\" should be less than 60", scratchpad); free(edf_hdr); free(edfhdr); return(NULL); } if(atoi(scratchpad+6)>59) { strncpy(scratchpad, edf_hdr + 176, 8); scratchpad[8] = 0; sprintf(txt_string, "Error, starttime of recording is invalid: \"%s\",\n" "expected \"hh.mm.ss\" where \"ss\" should be less than 60", scratchpad); free(edf_hdr); free(edfhdr); return(NULL); } date_time.hour = atoi(scratchpad); date_time.minute = atoi(scratchpad + 3); date_time.second = atoi(scratchpad + 6); date_time_to_utc(&edfhdr->utc_starttime, date_time); edfhdr->l_starttime = 3600 * atoi(scratchpad); edfhdr->l_starttime += 60 * atoi(scratchpad + 3); edfhdr->l_starttime += atoi(scratchpad + 6); edfhdr->l_starttime *= TIME_DIMENSION; /***************** NUMBER OF SIGNALS IN HEADER *******************************/ strncpy(scratchpad, edf_hdr + 252, 4); scratchpad[4] = 0; for(i=0; i<4; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { sprintf(txt_string, "Error, %ith character of number of signals field is not a valid 7-bit ASCII character.", i + 1); free(edf_hdr); free(edfhdr); return(NULL); } } if(is_integer_number(scratchpad)) { sprintf(txt_string, "Error, number of signals field is invalid: \"%s\".", scratchpad); free(edf_hdr); free(edfhdr); return(NULL); } edfhdr->edfsignals = atoi(scratchpad); if(edfhdr->edfsignals<1) { sprintf(txt_string, "Error, number of signals is %i, expected >0.", edfhdr->edfsignals); free(edf_hdr); free(edfhdr); return(NULL); } if(edfhdr->edfsignals>MAXSIGNALS) { sprintf(txt_string, "Error, number of signals in file is %i, can not support more than %i signals.", edfhdr->edfsignals, MAXSIGNALS); free(edf_hdr); free(edfhdr); return(NULL); } /***************** NUMBER OF BYTES IN HEADER *******************************/ strncpy(scratchpad, edf_hdr + 184, 8); scratchpad[8] = 0; for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { sprintf(txt_string, "Error, %ith character of number of bytes in header field is not a valid 7-bit ASCII character.", i + 1); free(edf_hdr); free(edfhdr); return(NULL); } } if(is_integer_number(scratchpad)) { sprintf(txt_string, "Error, number of bytes in header field is invalid: \"%s\".", scratchpad); free(edf_hdr); free(edfhdr); return(NULL); } n = atoi(scratchpad); if((edfhdr->edfsignals * 256 + 256)!=n) { sprintf(txt_string, "Error, number of bytes in header does not match: %i,\n" "expected %i signals * 256 + 256 = %i bytes.", n, edfhdr->edfsignals, edfhdr->edfsignals * 256 + 256); free(edf_hdr); free(edfhdr); return(NULL); } /********************* RESERVED FIELD *************************************/ edfhdr->edfplus = 0; edfhdr->discontinuous = 0; strncpy(scratchpad, edf_hdr + 192, 44); scratchpad[44] = 0; for(i=0; i<44; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { sprintf(txt_string, "Error, %ith character of reserved field is not a valid 7-bit ASCII character.", i + 1); free(edf_hdr); free(edfhdr); return(NULL); } } if(edfhdr->edf) { if(!strncmp(scratchpad, "EDF+C", 5)) { edfhdr->edfplus = 1; } if(!strncmp(scratchpad, "EDF+D", 5)) { edfhdr->edfplus = 1; edfhdr->discontinuous = 1; } } if(edfhdr->bdf) { if(!strncmp(scratchpad, "BDF+C", 5)) { edfhdr->bdfplus = 1; } if(!strncmp(scratchpad, "BDF+D", 5)) { edfhdr->bdfplus = 1; edfhdr->discontinuous = 1; } } strncpy(edfhdr->reserved, edf_hdr + 192, 44); edfhdr->reserved[44] = 0; /********************* NUMBER OF DATARECORDS *************************************/ strncpy(scratchpad, edf_hdr + 236, 8); scratchpad[8] = 0; for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { sprintf(txt_string, "Error, %ith character of number of datarecords field is not a valid ASCII character.", i + 1); free(edf_hdr); free(edfhdr); return(NULL); } } if(is_integer_number(scratchpad)) { sprintf(txt_string, "Error, number of datarecords field is invalid: \"%s\".\n" "You can fix this problem with the header editor, check the manual for details.", scratchpad); free(edf_hdr); free(edfhdr); return(NULL); } edfhdr->datarecords = atoi(scratchpad); if(live_stream == 0) { if(edfhdr->datarecords<1) { #ifdef Q_OS_WIN32 __mingw_sprintf(txt_string, "Error, number of datarecords is %lli, expected >0.\n" "You can fix this problem with the header editor, check the manual for details.", edfhdr->datarecords); #else sprintf(txt_string, "Error, number of datarecords is %lli, expected >0.\n" "You can fix this problem with the header editor, check the manual for details.", edfhdr->datarecords); #endif free(edf_hdr); free(edfhdr); return(NULL); } } /********************* DATARECORD DURATION *************************************/ strncpy(scratchpad, edf_hdr + 244, 8); scratchpad[8] = 0; for(i=0; i<8; i++) { if((scratchpad[i]<32)||(scratchpad[i]>126)) { sprintf(txt_string, "Error, %ith character of recordduration field is not a valid 7-bit ASCII character.", i + 1); free(edf_hdr); free(edfhdr); return(NULL); } } if(is_number(scratchpad)) { sprintf(txt_string, "Error, record duration field is invalid: \"%s\".", scratchpad); free(edf_hdr); free(edfhdr); return(NULL); } edfhdr->data_record_duration = atof(scratchpad); if(edfhdr->data_record_duration<-0.000001) { sprintf(txt_string, "Error, record duration is invalid: \"%s\", should be >=0", scratchpad); free(edf_hdr); free(edfhdr); return(NULL); } edfhdr->long_data_record_duration = get_long_duration(scratchpad); free(edf_hdr); /********************* START WITH THE SIGNALS IN THE HEADER *********************/ edf_hdr = (char *)calloc(1, (edfhdr->edfsignals + 1) * 256); if(edf_hdr==NULL) { sprintf(txt_string, "Memory allocation error. (edf_hdr takes %i bytes)", (edfhdr->edfsignals + 1) * 256); free(edfhdr); return(NULL); } rewind(inputfile); if(fread(edf_hdr, (edfhdr->edfsignals + 1) * 256, 1, inputfile)!=1) { sprintf(txt_string, "Error, reading %i bytes from file", (edfhdr->edfsignals + 1) * 256); free(edf_hdr); free(edfhdr); return(NULL); } edfhdr->edfparam = (struct edfparamblock *)calloc(1, sizeof(struct edfparamblock[edfhdr->edfsignals])); if(edfhdr->edfparam==NULL) { sprintf(txt_string, "Memory allocation error! (edfparam)"); free(edf_hdr); free(edfhdr); return(NULL); } /**************************** LABELS *************************************/ edfhdr->nr_annot_chns = 0; for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (i * 16), 16); for(j=0; j<16; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { sprintf(txt_string, "Error, %ith character of label field of signal %i is not a valid 7-bit ASCII character.\n" "Use the header editor to fix your file. Look at the manual for the details.", j + 1, i + 1); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } if(edfhdr->edfplus) { if(!strncmp(scratchpad, "EDF Annotations ", 16)) { edfhdr->annot_ch[edfhdr->nr_annot_chns] = i; edfhdr->nr_annot_chns++; edfhdr->edfparam[i].annotation = 1; } } if(edfhdr->bdfplus) { if(!strncmp(scratchpad, "BDF Annotations ", 16)) { edfhdr->annot_ch[edfhdr->nr_annot_chns] = i; edfhdr->nr_annot_chns++; edfhdr->edfparam[i].annotation = 1; } } strncpy(edfhdr->edfparam[i].label, edf_hdr + 256 + (i * 16), 16); edfhdr->edfparam[i].label[16] = 0; } if(edfhdr->edfplus&&(!edfhdr->nr_annot_chns)) { sprintf(txt_string, "Error, file is marked as EDF+ but it has no annotations-signal."); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } if(edfhdr->bdfplus&&(!edfhdr->nr_annot_chns)) { sprintf(txt_string, "Error, file is marked as BDF+ but it has no annotations-signal."); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } if((edfhdr->edfsignals!=edfhdr->nr_annot_chns)||((!edfhdr->edfplus)&&(!edfhdr->bdfplus))) { if(edfhdr->data_record_duration<0.000001) { sprintf(txt_string, "Error, record duration is invalid, should be >0"); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } /**************************** TRANSDUCER TYPES *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 16) + (i * 80), 80); for(j=0; j<80; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { sprintf(txt_string, "Error, %ith character of transducer type field of signal %i is not a valid 7-bit ASCII character.\n" "Use the header editor to fix your file. Look at the manual for the details.", j + 1, i + 1); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } strncpy(edfhdr->edfparam[i].transducer, edf_hdr + 256 + (edfhdr->edfsignals * 16) + (i * 80), 80); edfhdr->edfparam[i].transducer[80] = 0; if(edfhdr->edfplus) { if(edfhdr->edfparam[i].annotation) { for(j=0; j<80; j++) { if(edfhdr->edfparam[i].transducer[j]!=' ') { sprintf(txt_string, "Error, transducer type field of EDF annotationchannel must be empty.\n" "Use the header editor to fix your file. Look at the manual for the details."); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } } } if(edfhdr->bdfplus) { if(edfhdr->edfparam[i].annotation) { for(j=0; j<80; j++) { if(edfhdr->edfparam[i].transducer[j]!=' ') { sprintf(txt_string, "Error, transducer type field of BDF annotationchannel must be empty." "Use the header editor to fix your file. Look at the manual for the details."); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } } } } /**************************** PHYSICAL DIMENSIONS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 96) + (i * 8), 8); for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { sprintf(txt_string, "Error, %ith character of physical dimension field of signal %i is not a valid 7-bit ASCII character.\n" "Use the header editor to fix your file. Look at the manual for the details.", j + 1, i + 1); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } strncpy(edfhdr->edfparam[i].physdimension, edf_hdr + 256 + (edfhdr->edfsignals * 96) + (i * 8), 8); edfhdr->edfparam[i].physdimension[8] = 0; } /**************************** PHYSICAL MINIMUMS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 104) + (i * 8), 8); scratchpad[8] = 0; for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { sprintf(txt_string, "Error, %ith character of physical minimum field of signal %i is not a valid 7-bit ASCII character.", j + 1, i + 1); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } if(is_number(scratchpad)) { sprintf(txt_string, "Error, physical minimum field of signal %i is invalid: \"%s\".", i + 1, scratchpad); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } edfhdr->edfparam[i].phys_min = atof(scratchpad); } /**************************** PHYSICAL MAXIMUMS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 112) + (i * 8), 8); scratchpad[8] = 0; for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { sprintf(txt_string, "Error, %ith character of physical maximum field of signal %i is not a valid 7-bit ASCII character.", j + 1, i + 1); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } if(is_number(scratchpad)) { sprintf(txt_string, "Error, physical maximum field of signal %i is invalid: \"%s\".", i + 1, scratchpad); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } edfhdr->edfparam[i].phys_max = atof(scratchpad); if(edfhdr->edfparam[i].phys_max==edfhdr->edfparam[i].phys_min) { sprintf(txt_string, "Error, physical maximum of signal %i is equal to physical minimum", i + 1); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } /**************************** DIGITAL MINIMUMS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 120) + (i * 8), 8); scratchpad[8] = 0; for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { sprintf(txt_string, "Error, %ith character of digital minimum field of signal %i is not a valid 7-bit ASCII character.", j + 1, i + 1); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } if(is_integer_number(scratchpad)) { sprintf(txt_string, "Error, digital minimum field of signal %i is invalid: \"%s\".\n" "Use the header editor to fix your file. Look at the manual for the details.", i + 1, scratchpad); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } n = atoi(scratchpad); if(edfhdr->edfplus) { if(edfhdr->edfparam[i].annotation) { if(n!=-32768) { sprintf(txt_string, "Error, digital minimum of signal %i is wrong: %i," "\ndigital minimum of an EDF Annotations signal should be -32768\n" "Use the header editor to fix your file. Look at the manual for the details.", i + 1, n); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } } if(edfhdr->bdfplus) { if(edfhdr->edfparam[i].annotation) { if(n!=-8388608) { sprintf(txt_string, "Error, digital minimum of signal %i is wrong: %i," "\ndigital minimum of a BDF Annotations signal should be -8388608\n" "Use the header editor to fix your file. Look at the manual for the details.", i + 1, n); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } } if(edfhdr->edf) { if((n>32767)||(n<-32768)) { sprintf(txt_string, "Error, digital minimum of signal %i is out of range: %i,\nshould be in the range -32768 to 32767", i + 1, n); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } if(edfhdr->bdf) { if((n>8388607)||(n<-8388608)) { sprintf(txt_string, "Error, digital minimum of signal %i is out of range: %i,\nshould be in the range -8388608 to 8388607", i + 1, n); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } edfhdr->edfparam[i].dig_min = n; } /**************************** DIGITAL MAXIMUMS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 128) + (i * 8), 8); scratchpad[8] = 0; for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { sprintf(txt_string, "Error, %ith character of digital maximum field of signal %i is not a valid 7-bit ASCII character.", j + 1, i + 1); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } if(is_integer_number(scratchpad)) { sprintf(txt_string, "Error, digital maximum field of signal %i is invalid: \"%s\".\n" "Use the header editor to fix your file. Look at the manual for the details.", i + 1, scratchpad); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } n = atoi(scratchpad); if(edfhdr->edfplus) { if(edfhdr->edfparam[i].annotation) { if(n!=32767) { sprintf(txt_string, "Error, digital maximum of signal %i is wrong: %i," "\ndigital maximum of an EDF Annotations signal should be 32767\n" "Use the header editor to fix your file. Look at the manual for the details.", i + 1, n); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } } if(edfhdr->bdfplus) { if(edfhdr->edfparam[i].annotation) { if(n!=8388607) { sprintf(txt_string, "Error, digital maximum of signal %i is wrong: %i," "\ndigital maximum of a BDF Annotations signal should be 8388607\n" "Use the header editor to fix your file. Look at the manual for the details.", i + 1, n); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } } if(edfhdr->edf) { if((n>32767)||(n<-32768)) { sprintf(txt_string, "Error, digital maximum of signal %i is out of range: %i,\nshould be in the range -32768 to 32767", i + 1, n); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } else { if((n>8388607)||(n<-8388608)) { sprintf(txt_string, "Error, digital maximum of signal %i is out of range: %i,\nshould be in the range -8388608 to 8388607", i + 1, n); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } edfhdr->edfparam[i].dig_max = n; if(edfhdr->edfparam[i].dig_max<(edfhdr->edfparam[i].dig_min + 1)) { sprintf(txt_string, "Error, digital maximum of signal %i is less than or equal to digital minimum", i + 1); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } /**************************** PREFILTER FIELDS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 136) + (i * 80), 80); for(j=0; j<80; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { sprintf(txt_string, "Error, %ith character of prefilter field of signal %i is not a valid 7-bit ASCII character.\n" "Use the header editor to fix your file. Look at the manual for the details.", j + 1, i + 1); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } strncpy(edfhdr->edfparam[i].prefilter, edf_hdr + 256 + (edfhdr->edfsignals * 136) + (i * 80), 80); edfhdr->edfparam[i].prefilter[80] = 0; if(edfhdr->edfplus) { if(edfhdr->edfparam[i].annotation) { for(j=0; j<80; j++) { if(edfhdr->edfparam[i].prefilter[j]!=' ') { sprintf(txt_string, "Error, prefilter field of EDF annotationchannel must be empty.\n" "Use the header editor to fix your file. Look at the manual for the details."); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } } } if(edfhdr->bdfplus) { if(edfhdr->edfparam[i].annotation) { for(j=0; j<80; j++) { if(edfhdr->edfparam[i].prefilter[j]!=' ') { sprintf(txt_string, "Error, prefilter field of BDF annotationchannel must be empty.\n" "Use the header editor to fix your file. Look at the manual for the details."); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } } } } /*********************** NR OF SAMPLES IN EACH DATARECORD ********************/ edfhdr->recordsize = 0; for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 216) + (i * 8), 8); scratchpad[8] = 0; for(j=0; j<8; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { sprintf(txt_string, "Error, %ith character of number of samples field of signal %i is not a valid 7-bit ASCII character.", j + 1, i + 1); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } if(is_integer_number(scratchpad)) { sprintf(txt_string, "Error, number of samples in datarecord field of signal %i is invalid: \"%s\".", i + 1, scratchpad); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } n = atoi(scratchpad); if(n<1) { sprintf(txt_string, "Error, number of samples in datarecord of signal %i is out of range: %i,\nshould be >0", i + 1, n); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } edfhdr->edfparam[i].smp_per_record = n; edfhdr->recordsize += n; } if(edfhdr->bdf) { edfhdr->recordsize *= 3; if(edfhdr->recordsize > 15728640) { sprintf(txt_string, "Error, the datarecordsize is %i bytes. The datarecordsize should not exceed 15 MB.", edfhdr->recordsize); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } else { edfhdr->recordsize *= 2; if(edfhdr->recordsize > 10485760) { sprintf(txt_string, "Error, the datarecordsize is %i bytes. The datarecordsize should not exceed 10 MB.", edfhdr->recordsize); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } /**************************** RESERVED FIELDS *************************************/ for(i=0; iedfsignals; i++) { strncpy(scratchpad, edf_hdr + 256 + (edfhdr->edfsignals * 224) + (i * 32), 32); for(j=0; j<32; j++) { if((scratchpad[j]<32)||(scratchpad[j]>126)) { sprintf(txt_string, "Error, %ith character of reserved field of signal %i is not a valid 7-bit ASCII character.", j + 1, i + 1); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } strncpy(edfhdr->edfparam[i].reserved, edf_hdr + 256 + (edfhdr->edfsignals * 224) + (i * 32), 32); edfhdr->edfparam[i].reserved[32] = 0; } /********************* EDF+ PATIENTNAME *********************************************/ if(edfhdr->edfplus || edfhdr->bdfplus) { error = 0; dotposition = 0; strncpy(scratchpad, edf_hdr + 8, 80); scratchpad[80] = 0; for(i=0; i<80; i++) { if(scratchpad[i]==' ') { dotposition = i; break; } } dotposition++; if((dotposition>73)||(dotposition<2)) error = 1; if(scratchpad[dotposition + 2]!='X') { if(dotposition>65) error = 1; } if((scratchpad[dotposition]!='M')&&(scratchpad[dotposition]!='F')&&(scratchpad[dotposition]!='X')) error = 1; dotposition++; if(scratchpad[dotposition]!=' ') error = 1; if(scratchpad[dotposition + 1]=='X') { if(scratchpad[dotposition + 2]!=' ') error = 1; if(scratchpad[dotposition + 3]==' ') error = 1; } else { if(scratchpad[dotposition + 12]!=' ') error = 1; if(scratchpad[dotposition + 13]==' ') error = 1; dotposition++; strncpy(scratchpad2, scratchpad + dotposition, 11); scratchpad2[11] = 0; if((scratchpad2[2]!='-')||(scratchpad2[6]!='-')) error = 1; scratchpad2[2] = 0; scratchpad2[6] = 0; if((scratchpad2[0]<48)||(scratchpad2[0]>57)) error = 1; if((scratchpad2[1]<48)||(scratchpad2[1]>57)) error = 1; if((scratchpad2[7]<48)||(scratchpad2[7]>57)) error = 1; if((scratchpad2[8]<48)||(scratchpad2[8]>57)) error = 1; if((scratchpad2[9]<48)||(scratchpad2[9]>57)) error = 1; if((scratchpad2[10]<48)||(scratchpad2[10]>57)) error = 1; if((atoi(scratchpad2)<1)||(atoi(scratchpad2)>31)) error = 1; if(strcmp(scratchpad2 + 3, "JAN")) if(strcmp(scratchpad2 + 3, "FEB")) if(strcmp(scratchpad2 + 3, "MAR")) if(strcmp(scratchpad2 + 3, "APR")) if(strcmp(scratchpad2 + 3, "MAY")) if(strcmp(scratchpad2 + 3, "JUN")) if(strcmp(scratchpad2 + 3, "JUL")) if(strcmp(scratchpad2 + 3, "AUG")) if(strcmp(scratchpad2 + 3, "SEP")) if(strcmp(scratchpad2 + 3, "OCT")) if(strcmp(scratchpad2 + 3, "NOV")) if(strcmp(scratchpad2 + 3, "DEC")) error = 1; } if(error) { if(edfhdr->edfplus) { sprintf(txt_string, "Error, file is marked as EDF+ but local patient identification field does not\ncomply to the EDF+ standard:\n" "\"%.80s\"", edf_hdr+8); } if(edfhdr->bdfplus) { sprintf(txt_string, "Error, file is marked as BDF+ but local patient identification field does not\ncomply to the BDF+ standard:\n" "\"%.80s\"", edf_hdr+8); } free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } p = 0; if(edfhdr->patient[p]=='X') { edfhdr->plus_patientcode[0] = 0; p += 2; } else { for(i=0; i<(80-p); i++) { if(edfhdr->patient[i+p]==' ') { break; } edfhdr->plus_patientcode[i] = edfhdr->patient[i+p]; if(edfhdr->plus_patientcode[i]=='_') edfhdr->plus_patientcode[i] = ' '; } edfhdr->plus_patientcode[i] = 0; p += i + 1; } if(edfhdr->patient[p]=='M') { strcpy(edfhdr->plus_gender, "Male"); } if(edfhdr->patient[p]=='F') { strcpy(edfhdr->plus_gender, "Female"); } if(edfhdr->patient[p]=='X') { edfhdr->plus_gender[0] = 0; } for(i=0; i<(80-p);i++) { if(edfhdr->patient[i+p]==' ') { break; } } p += i + 1; if(edfhdr->patient[p]=='X') { edfhdr->plus_birthdate[0] = 0; p += 2; } else { for(i=0; i<(80-p); i++) { if(edfhdr->patient[i+p]==' ') { break; } edfhdr->plus_birthdate[i] = edfhdr->patient[i+p]; } edfhdr->plus_birthdate[2] = ' '; edfhdr->plus_birthdate[3] += 32; edfhdr->plus_birthdate[4] += 32; edfhdr->plus_birthdate[5] += 32; edfhdr->plus_birthdate[6] = ' '; edfhdr->plus_birthdate[11] = 0; p += i + 1; } for(i=0; i<(80-p);i++) { if(edfhdr->patient[i+p]==' ') { break; } edfhdr->plus_patient_name[i] = edfhdr->patient[i+p]; if(edfhdr->plus_patient_name[i]=='_') edfhdr->plus_patient_name[i] = ' '; } edfhdr->plus_patient_name[i] = 0; p += i + 1; for(i=0; i<(80-p);i++) { edfhdr->plus_patient_additional[i] = edfhdr->patient[i+p]; } edfhdr->plus_patient_additional[i] = 0; p += i + 1; } /********************* EDF+ RECORDINGFIELD *********************************************/ if(edfhdr->edfplus || edfhdr->bdfplus) { error = 0; strncpy(scratchpad, edf_hdr + 88, 80); scratchpad[80] = 0; if(strncmp(scratchpad, "Startdate ", 10)) error = 1; if(scratchpad[10]=='X') { if(scratchpad[11]!=' ') error = 1; if(scratchpad[12]==' ') error = 1; p = 12; } else { if(scratchpad[21]!=' ') error = 1; if(scratchpad[22]==' ') error = 1; p = 22; strncpy(scratchpad2, scratchpad + 10, 11); scratchpad2[11] = 0; if((scratchpad2[2]!='-')||(scratchpad2[6]!='-')) error = 1; scratchpad2[2] = 0; scratchpad2[6] = 0; if((scratchpad2[0]<48)||(scratchpad2[0]>57)) error = 1; if((scratchpad2[1]<48)||(scratchpad2[1]>57)) error = 1; if((scratchpad2[7]<48)||(scratchpad2[7]>57)) error = 1; if((scratchpad2[8]<48)||(scratchpad2[8]>57)) error = 1; if((scratchpad2[9]<48)||(scratchpad2[9]>57)) error = 1; if((scratchpad2[10]<48)||(scratchpad2[10]>57)) error = 1; if((atoi(scratchpad2)<1)||(atoi(scratchpad2)>31)) error = 1; r = 0; if(!strcmp(scratchpad2 + 3, "JAN")) r = 1; else if(!strcmp(scratchpad2 + 3, "FEB")) r = 2; else if(!strcmp(scratchpad2 + 3, "MAR")) r = 3; else if(!strcmp(scratchpad2 + 3, "APR")) r = 4; else if(!strcmp(scratchpad2 + 3, "MAY")) r = 5; else if(!strcmp(scratchpad2 + 3, "JUN")) r = 6; else if(!strcmp(scratchpad2 + 3, "JUL")) r = 7; else if(!strcmp(scratchpad2 + 3, "AUG")) r = 8; else if(!strcmp(scratchpad2 + 3, "SEP")) r = 9; else if(!strcmp(scratchpad2 + 3, "OCT")) r = 10; else if(!strcmp(scratchpad2 + 3, "NOV")) r = 11; else if(!strcmp(scratchpad2 + 3, "DEC")) r = 12; else error = 1; } n = 0; for(i=p; i<80; i++) { if(i>78) { error = 1; break; } if(scratchpad[i]==' ') { n++; if(scratchpad[i + 1]==' ') { error = 1; break; } } if(n>1) break; } if(error) { if(edfhdr->edfplus) { sprintf(txt_string, "Error, file is marked as EDF+ but recording field does not comply to the\nEDF+ standard:\n" "\"%.80s\"", edf_hdr+88); } if(edfhdr->bdfplus) { sprintf(txt_string, "Error, file is marked as BDF+ but recording field does not comply to the\nBDF+ standard:\n" "\"%.80s\"", edf_hdr+88); } free(edf_hdr); free(edfhdr->edfparam); return(NULL); } if(edf_hdr[98]!='X') { error = 0; strncpy(scratchpad, edf_hdr + 168, 8); scratchpad[2] = 0; scratchpad[5] = 0; scratchpad[8] = 0; if(atoi(scratchpad)!=atoi(scratchpad2)) error = 1; if(atoi(scratchpad+3)!=r) error = 1; if(atoi(scratchpad+6)!=atoi(scratchpad2+9)) error = 1; if(error) { if(edfhdr->edfplus) { sprintf(txt_string, "Error, file is marked as EDF+ but startdate field does not match with startdate in\nrecordfield:\n" "\"%.8s\" <-> \"%.11s\".", edf_hdr+168, edf_hdr+98); } if(edfhdr->bdfplus) { sprintf(txt_string, "Error, file is marked as BDF+ but startdate field does not match with startdate in\nrecordfield:\n" "\"%.8s\" <-> \"%.11s\".", edf_hdr+168, edf_hdr+98); } free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } date_time.year = atoi(scratchpad2 + 7); if(date_time.year<1970) { sprintf(txt_string, "Error, recording startdate is older than 1970."); free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } date_time_to_utc(&edfhdr->utc_starttime, date_time); } p = 10; for(i=0; i<(80-p); i++) { if(edfhdr->recording[i+p]==' ') { break; } edfhdr->plus_startdate[i] = edfhdr->recording[i+p]; } edfhdr->plus_startdate[2] = ' '; edfhdr->plus_startdate[3] += 32; edfhdr->plus_startdate[4] += 32; edfhdr->plus_startdate[5] += 32; edfhdr->plus_startdate[6] = ' '; edfhdr->plus_startdate[11] = 0; p += i + 1; if(edfhdr->recording[p]=='X') { edfhdr->plus_admincode[0] = 0; p += 2; } else { for(i=0; i<(80-p); i++) { if(edfhdr->recording[i+p]==' ') { break; } edfhdr->plus_admincode[i] = edfhdr->recording[i+p]; if(edfhdr->plus_admincode[i]=='_') edfhdr->plus_admincode[i] = ' '; } edfhdr->plus_admincode[i] = 0; p += i + 1; } if(edfhdr->recording[p]=='X') { edfhdr->plus_technician[0] = 0; p += 2; } else { for(i=0; i<(80-p); i++) { if(edfhdr->recording[i+p]==' ') { break; } edfhdr->plus_technician[i] = edfhdr->recording[i+p]; if(edfhdr->plus_technician[i]=='_') edfhdr->plus_technician[i] = ' '; } edfhdr->plus_technician[i] = 0; p += i + 1; } if(edfhdr->recording[p]=='X') { edfhdr->plus_equipment[0] = 0; p += 2; } else { for(i=0; i<(80-p); i++) { if(edfhdr->recording[i+p]==' ') { break; } edfhdr->plus_equipment[i] = edfhdr->recording[i+p]; if(edfhdr->plus_equipment[i]=='_') edfhdr->plus_equipment[i] = ' '; } edfhdr->plus_equipment[i] = 0; p += i + 1; } for(i=0; i<(80-p);i++) { edfhdr->plus_recording_additional[i] = edfhdr->recording[i+p]; } edfhdr->plus_recording_additional[i] = 0; p += i + 1; } /********************* FILESIZE *********************************************/ edfhdr->hdrsize = edfhdr->edfsignals * 256 + 256; if(live_stream) { fseeko(inputfile, 0LL, SEEK_END); edfhdr->datarecords = ftello(inputfile); edfhdr->datarecords -= (long long)edfhdr->hdrsize; edfhdr->datarecords /= (long long)edfhdr->recordsize; } else { l_tmp = edfhdr->recordsize; l_tmp *= edfhdr->datarecords; l_tmp += (edfhdr->edfsignals * 256 + 256); fseeko(inputfile, 0LL, SEEK_END); l_tmp2 = ftello(inputfile); if(l_tmp != l_tmp2) { #ifdef Q_OS_WIN32 __mingw_sprintf(txt_string, "Error, filesize does not match with the calculated filesize based on the parameters\n" "in the header. Filesize is %lli and filesize according to header is %lli.\n" "You can fix this problem with the header editor, check the manual for details.", l_tmp2, l_tmp); #else sprintf(txt_string, "Error, filesize does not match with the calculated filesize based on the parameters\n" "in the header. Filesize is %lli and filesize according to header is %lli.\n" "You can fix this problem with the header editor, check the manual for details.", l_tmp2, l_tmp); #endif free(edf_hdr); free(edfhdr->edfparam); free(edfhdr); return(NULL); } } n = 0; for(i=0; iedfsignals; i++) { edfhdr->edfparam[i].buf_offset = n; if(edfhdr->bdf) n += edfhdr->edfparam[i].smp_per_record * 3; else n += edfhdr->edfparam[i].smp_per_record * 2; edfhdr->edfparam[i].bitvalue = (edfhdr->edfparam[i].phys_max - edfhdr->edfparam[i].phys_min) / (edfhdr->edfparam[i].dig_max - edfhdr->edfparam[i].dig_min); edfhdr->edfparam[i].offset = edfhdr->edfparam[i].phys_max / edfhdr->edfparam[i].bitvalue - edfhdr->edfparam[i].dig_max; } edfhdr->recording_len_sec = (int)((edfhdr->datarecords * edfhdr->long_data_record_duration) / TIME_DIMENSION); txt_string[0] = 0; free(edf_hdr); return(edfhdr); } int EDFfileCheck::is_integer_number(char *str) { int i=0, l, hasspace = 0, hassign=0, digit=0; l = strlen(str); if(!l) return(1); if((str[0]=='+')||(str[0]=='-')) { hassign++; i++; } for(; i57)) { return(1); } else { if(hasspace) { return(1); } digit++; } } } if(digit) return(0); else return(1); } int EDFfileCheck::is_number(char *str) { int i=0, l, hasspace = 0, hassign=0, digit=0, hasdot=0, hasexp=0; l = strlen(str); if(!l) return(1); if((str[0]=='+')||(str[0]=='-')) { hassign++; i++; } for(; i57))&&str[i]!='.') { return(1); } else { if(hasspace) { return(1); } if(str[i]=='.') { if(hasdot) return(1); hasdot++; } else { digit++; } } } } if(hasexp) { if(++i==l) { return(1); } if((str[i]=='+')||(str[i]=='-')) { hassign++; i++; } for(; i57)) { return(1); } else { if(hasspace) { return(1); } digit++; } } } } if(digit) return(0); else return(1); } long long EDFfileCheck::get_long_duration(char *str) { int i, len=8, hasdot=0, dotposition=0; long long value=0, radix; for(i=0; i<8; i++) { if(str[i]==' ') { len = i; break; } } for(i=0; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } radix = TIME_DIMENSION / 10; for(i=dotposition+1; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } } return(value); } edfbrowser_157_source/PaxHeaders.7921/pagetime_dialog.h0000644000000000000000000000012712646460742020155 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/pagetime_dialog.h0000644000175000001440000000341512646460742020515 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef PAGETIMEFORM1_H #define PAGETIMEFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" class UI_Mainwindow; class UI_Userdefined_timepage_Dialog : public QObject { Q_OBJECT public: UI_Userdefined_timepage_Dialog(QWidget *parent=0); UI_Mainwindow *mainwindow; private: QDialog *set_diplaytime_dialog; QLabel *label1; QPushButton *CloseButton, *OKButton; QTimeEdit *timeEdit1; QTime time1; private slots: void okbutton_pressed(); }; #endif // PAGETIMEFORM1_H edfbrowser_157_source/PaxHeaders.7921/signalcurve.h0000644000000000000000000000013212646460742017361 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/signalcurve.h0000644000175000001440000001456412646460742017734 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef SIGNALCURVE_H #define SIGNALCURVE_H #include #include #include #include #include #include #if QT_VERSION < 0x050000 #include #else #include #endif #include #include #include #include #include #include #include #include #include #include "utils.h" #define MAXSPECTRUMMARKERS 16 #define SC_MAX_PATH_LEN 1024 struct spectrum_markersblock{ int items; double freq[MAXSPECTRUMMARKERS]; int color[MAXSPECTRUMMARKERS]; char label[MAXSPECTRUMMARKERS][17]; double value[MAXSPECTRUMMARKERS]; int method; double max_colorbar_value; int auto_adjust; }; class SignalCurve: public QWidget { Q_OBJECT public: SignalCurve(QWidget *parent=0); QSize sizeHint() const {return minimumSizeHint(); } QSize minimumSizeHint() const {return QSize(30,10); } void setSignalColor(QColor); void setTraceWidth(int); void setBackgroundColor(QColor); void setRasterColor(QColor); void setBorderColor(QColor); void setTextColor(QColor); void setBorderSize(int); void setH_RulerValues(double, double); void setH_label(const char *); void setV_label(const char *); void setUpperLabel1(const char *); void setUpperLabel2(const char *); void setLowerLabel(const char *); void drawCurve(double *, int , double , double ); void drawCurve(int *, int , double , double ); void drawCurve( float *, int , double , double ); void drawLine(int, double, int, double, QColor); void setLineEnabled(bool); void create_button(const char *); void setCursorEnabled(bool); bool isCursorEnabled(void); bool isCursorActive(void); void setPrintEnabled(bool); void setDashBoardEnabled(bool); void setMarker1Enabled(bool); void setMarker1MovableEnabled(bool); void setMarker1Position(double); void setMarker1Color(QColor); double getMarker1Position(void); void setMarker2Enabled(bool); void setMarker2MovableEnabled(bool); void setMarker2Position(double); void setMarker2Color(QColor); double getMarker2Position(void); void setCrosshairColor(QColor); void clear(); void setUpdatesEnabled(bool); void enableSpectrumColors(struct spectrum_markersblock *); void disableSpectrumColors(); void setFillSurfaceEnabled(bool); void setV_rulerEnabled(bool); void setUpsidedownEnabled(bool); int getCursorPosition(void); void shiftCursorPixelsLeft(int); void shiftCursorPixelsRight(int); void shiftCursorIndexLeft(int); void shiftCursorIndexRight(int); signals: void extra_button_clicked(); void dashBoardClicked(); void markerHasMoved(); private slots: void exec_sidemenu(); #if QT_VERSION < 0x050000 void print_to_postscript(); #endif void print_to_pdf(); void print_to_image(); void print_to_printer(); void print_to_ascii(); void send_button_event(); private: QDialog *sidemenu; QPushButton *sidemenuButton1, #if QT_VERSION < 0x050000 *sidemenuButton2, #endif *sidemenuButton3, *sidemenuButton4, *sidemenuButton5, *sidemenuButton6; QColor SignalColor, BackgroundColor, RasterColor, BorderColor, RulerColor, TextColor, crosshair_1_color, line1Color, backup_color_1, backup_color_2, backup_color_3, backup_color_4, backup_color_5, backup_color_6; QPrinter *printer; QPen Marker1Pen, Marker2Pen; double max_value, min_value, *dbuf, h_ruler_startvalue, h_ruler_endvalue, printsize_x_factor, printsize_y_factor, crosshair_1_value, crosshair_1_value_2, crosshair_1_x_position, line1_start_y, line1_end_y, marker_1_position, marker_2_position; float *fbuf; int bufsize, bordersize, drawHruler, drawVruler, drawcurve_before_raster, tracewidth, extra_button, use_move_events, mouse_x, mouse_y, mouse_old_x, mouse_old_y, crosshair_1_active, crosshair_1_moving, crosshair_1_y_position, crosshair_1_y_value, marker_1_moving, marker_1_x_position, marker_2_moving, marker_2_x_position, line1_start_x, line1_end_x, w, h, old_w, updates_enabled, fillsurface, *ibuf; char h_label[32], v_label[21], upperlabel1[64], upperlabel2[64], lowerlabel[64], extra_button_txt[16], recent_savedir[SC_MAX_PATH_LEN]; bool printEnabled, cursorEnabled, dashBoardEnabled, Marker1Enabled, Marker1MovableEnabled, Marker2Enabled, Marker2MovableEnabled, curveUpSideDown, line1Enabled; struct spectrum_markersblock *spectrum_color; void backup_colors_for_printing(); void restore_colors_after_printing(); void drawWidget(QPainter *, int, int); void drawWidget_to_printer(QPainter *, int, int); int get_directory_from_path(char *, const char *, int); protected: void paintEvent(QPaintEvent *); void mousePressEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *); void resizeEvent(QResizeEvent *); }; #endif edfbrowser_157_source/PaxHeaders.7921/spike_filter_dialog.h0000644000000000000000000000013212646460742021036 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/spike_filter_dialog.h0000644000175000001440000000400312646460742021374 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef ADD_SPIKE_FILTERFORM1_H #define ADD_SPIKE_FILTERFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "spike_filter.h" #include "utils.h" class UI_Mainwindow; class UI_SpikeFilterDialog : public QObject { Q_OBJECT public: UI_SpikeFilterDialog(QWidget *parent=0); UI_Mainwindow *mainwindow; private: QDialog *spikefilterdialog; QPushButton *CancelButton, *ApplyButton; QListWidget *list; QLabel *listlabel, *velocityLabel, *holdOffLabel; QDoubleSpinBox *velocitySpinBox; QSpinBox *holdOffSpinBox; private slots: void ApplyButtonClicked(); }; #endif // ADD_SPIKE_FILTERFORM1_H edfbrowser_157_source/PaxHeaders.7921/nk2edf.cpp0000644000000000000000000000012712646460742016547 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/nk2edf.cpp0000644000175000001440000011701312646460742017107 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "nk2edf.h" #define ELECTRODE_TAG "[ELECTRODE]" #define ELECTRODE_UNTAG "[" #define ELECTRODE_NAME_MAXLEN 256 #define ANNOT_TRACKSIZE 54 UI_NK2EDFwindow::UI_NK2EDFwindow(char *recent_dir) { char txt_string[2048]; recent_opendir = recent_dir; myobjectDialog = new QDialog; myobjectDialog->setMinimumSize(600, 480); myobjectDialog->setMaximumSize(600, 480); myobjectDialog->setWindowTitle("Nihon Kohden to EDF(+) converter"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); 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"); checkBox1 = new QCheckBox(myobjectDialog); checkBox1->setGeometry(200, 430, 120, 25); checkBox1->setText("Create EDF+"); checkBox1->setCheckState(Qt::Checked); textEdit1 = new QTextEdit(myobjectDialog); textEdit1->setGeometry(20, 20, 560, 380); textEdit1->setFrameStyle(QFrame::Panel | QFrame::Sunken); textEdit1->setReadOnly(true); textEdit1->setLineWrapMode(QTextEdit::NoWrap); sprintf(txt_string, "Nihon Kohden to EDF(+) converter.\n"); textEdit1->append(txt_string); QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton())); QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close())); myobjectDialog->exec(); } void UI_NK2EDFwindow::SelectFileButton() { FILE *inputfile=NULL, *outputfile=NULL, *logfile=NULL, *pntfile=NULL; int i, j, k, error, ctl_block_cnt, datablock_cnt, total_blocks, edfplus, n_logs=0, n_sublogs=0, total_logs=0, n_logblocks=0, ctlblock_address, wfmblock_address, logblock_address, read_subevents=0; char txt_string[2048], path[MAX_PATH_LENGTH], outputpath[MAX_PATH_LENGTH], logfilepath[MAX_PATH_LENGTH], pntfilepath[MAX_PATH_LENGTH], *log_buf=NULL, *sublog_buf=NULL, scratchpad[256]; pushButton1->setEnabled(false); edfplus = checkBox1->checkState(); total_elapsed_time = 0; strcpy(path, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "EEG files (*.eeg *.EEG)").toLocal8Bit().data()); if(!strcmp(path, "")) { pushButton1->setEnabled(true); return; } get_directory_from_path(recent_opendir, path, MAX_PATH_LENGTH); inputfile = fopeno(path, "rb"); if(inputfile==NULL) { snprintf(txt_string, 2048, "can not open file %s for reading.\n", path); textEdit1->append(QString::fromLocal8Bit(txt_string)); pushButton1->setEnabled(true); return; } /***************** check if the EEG file is valid ******************************/ rewind(inputfile); if(fread(scratchpad, 16, 1, inputfile)!=1) { textEdit1->append("error reading .eeg file.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } scratchpad[16] = 0; if(check_device(scratchpad)) { snprintf(txt_string, 2048, "error, deviceblock has unknown signature: \"%s\"\n", scratchpad); textEdit1->append(txt_string); fclose(inputfile); pushButton1->setEnabled(true); return; } fseeko(inputfile, 0x0081LL, SEEK_SET); if(fread(scratchpad, 16, 1, inputfile)!=1) { textEdit1->append("error reading .eeg file.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } scratchpad[16] = 0; if(check_device(scratchpad)) { snprintf(txt_string, 2048, "error, controlblock has unknown signature: \"%s\"\n", scratchpad); textEdit1->append(txt_string); fclose(inputfile); pushButton1->setEnabled(true); return; } fseeko(inputfile, 0x17feLL, SEEK_SET); if(fgetc(inputfile)!=0x01) { snprintf(txt_string, 2048, "error, waveformdatablock has wrong signature.\n"); textEdit1->append(txt_string); fclose(inputfile); pushButton1->setEnabled(true); return; } /************************* read logs **********************************************/ if(edfplus) { strncpy(logfilepath, path, MAX_PATH_LENGTH); remove_extension_from_filename(logfilepath); strcat(logfilepath, ".LOG"); logfile = fopeno(logfilepath, "rb"); if(logfile==NULL) { remove_extension_from_filename(logfilepath); strcat(logfilepath, ".log"); logfile = fopeno(logfilepath, "rb"); if(logfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for reading,\n" "if there is no .log file you can try to create an EDF file instead of EDF+.\n", logfilepath); textEdit1->append(QString::fromLocal8Bit(txt_string)); fclose(inputfile); pushButton1->setEnabled(true); return; } } rewind(logfile); if(fread(scratchpad, 16, 1, logfile)!=1) { textEdit1->append("error reading .log file.\n"); fclose(logfile); fclose(inputfile); pushButton1->setEnabled(true); return; } scratchpad[16] = 0; if(check_device(scratchpad)) { snprintf(txt_string, 2048, "error, .log file has unknown signature: \"%s\"\n", scratchpad); textEdit1->append(QString::fromLocal8Bit(txt_string)); fclose(logfile); fclose(inputfile); pushButton1->setEnabled(true); return; } fseeko(logfile, 0x0091LL, SEEK_SET); n_logblocks = fgetc(logfile); log_buf = (char *)calloc(1, n_logblocks * 11521); if(log_buf==NULL) { textEdit1->append("malloc error\n"); fclose(logfile); fclose(inputfile); pushButton1->setEnabled(true); return; } sublog_buf = (char *)calloc(1, n_logblocks * 11521); if(sublog_buf==NULL) { textEdit1->append("malloc error\n"); fclose(logfile); fclose(inputfile); free(log_buf); pushButton1->setEnabled(true); return; } read_subevents = 1; total_logs = 0; for(i=0; iappend("error reading .log file.\n"); fclose(inputfile); fclose(logfile); free(log_buf); free(sublog_buf); pushButton1->setEnabled(true); return; } fseeko(logfile, (long long)(logblock_address + 0x0012), SEEK_SET); n_logs = fgetc(logfile); fseeko(logfile, (long long)(logblock_address + 0x0014), SEEK_SET); if(fread(log_buf + (total_logs * 45), n_logs * 45, 1, logfile)!=1) { textEdit1->append("error reading .log file.\n"); fclose(inputfile); fclose(logfile); free(log_buf); free(sublog_buf); pushButton1->setEnabled(true); return; } if(read_subevents) { if(fseeko(logfile, 0x0092LL + ((i + 22) * 20) , SEEK_SET)) { read_subevents = 0; } else { if(fread((char *)(&logblock_address), 4, 1, logfile)!=1) { read_subevents = 0; } else { if(fseeko(logfile, logblock_address + 0x0012LL, SEEK_SET)) { read_subevents = 0; } else { n_sublogs = fgetc(logfile); if(n_sublogs != n_logs) { read_subevents = 0; } else { if(fseeko(logfile, logblock_address + 0x0014LL, SEEK_SET)) { read_subevents = 0; } else { if(fread(sublog_buf + (total_logs * 45), n_sublogs * 45, 1, logfile)!=1) { read_subevents = 0; } } } } } } } total_logs += n_logs; } for(i=0; iappend(QString::fromLocal8Bit(txt_string)); fclose(logfile); fclose(inputfile); free(log_buf); free(sublog_buf); pushButton1->setEnabled(true); return; } } rewind(pntfile); if(fread(scratchpad, 16, 1, pntfile)!=1) { textEdit1->append("error reading .pnt file.\n"); fclose(pntfile); fclose(logfile); fclose(inputfile); free(log_buf); free(sublog_buf); pushButton1->setEnabled(true); return; } scratchpad[16] = 0; if(check_device(scratchpad)) { snprintf(txt_string, 2048, "error, .pnt file has unknown signature: \"%s\"\n", scratchpad); textEdit1->append(QString::fromLocal8Bit(txt_string)); fclose(pntfile); fclose(logfile); fclose(inputfile); free(log_buf); free(sublog_buf); pushButton1->setEnabled(true); return; } } /***************** initialize labels **************************************/ for(i=0; i<256; i++) { strcpy(labels[i], "- "); } strcpy(labels[0], "EEG FP1 "); strcpy(labels[1], "EEG FP2 "); strcpy(labels[2], "EEG F3 "); strcpy(labels[3], "EEG F4 "); strcpy(labels[4], "EEG C3 "); strcpy(labels[5], "EEG C4 "); strcpy(labels[6], "EEG P3 "); strcpy(labels[7], "EEG P4 "); strcpy(labels[8], "EEG O1 "); strcpy(labels[9], "EEG O2 "); strcpy(labels[10], "EEG F7 "); strcpy(labels[11], "EEG F8 "); strcpy(labels[12], "EEG T3 "); strcpy(labels[13], "EEG T4 "); strcpy(labels[14], "EEG T5 "); strcpy(labels[15], "EEG T6 "); strcpy(labels[16], "EEG FZ "); strcpy(labels[17], "EEG CZ "); strcpy(labels[18], "EEG PZ "); strcpy(labels[19], "EEG E "); strcpy(labels[20], "EEG PG1 "); strcpy(labels[21], "EEG PG2 "); strcpy(labels[22], "EEG A1 "); strcpy(labels[23], "EEG A2 "); strcpy(labels[24], "EEG T1 "); strcpy(labels[25], "EEG T2 "); for(i=26; i<35; i++) { sprintf(labels[i], "EEG X%i ", i - 25); } strcpy(labels[35], "EEG X10 "); strcpy(labels[36], "EEG X11 "); for(i=42; i<74; i++) { sprintf(labels[i], "DC%02i ", i - 41); } strcpy(labels[74], "EEG BN1 "); strcpy(labels[75], "EEG BN2 "); strcpy(labels[76], "EEG Mark1 "); strcpy(labels[77], "EEG Mark2 "); strcpy(labels[100], "EEG X12/BP1 "); strcpy(labels[101], "EEG X13/BP2 "); strcpy(labels[102], "EEG X14/BP3 "); strcpy(labels[103], "EEG X15/BP4 "); for(i=104; i<188; i++) { sprintf(labels[i], "EEG X%i ", i - 88); } for(i=188; i<254; i++) { sprintf(labels[i], "EEG X%i ", i - 88); } strcpy(labels[255], "Z "); if(read_21e_file(path)) { textEdit1->append("Can not open *.21e file, converter will use default electrode names."); } /***************** start conversion **************************************/ total_blocks = 0; fseeko(inputfile, 0x0091LL, SEEK_SET); ctl_block_cnt = fgetc(inputfile); if(ctl_block_cnt==EOF) { textEdit1->append("error reading inputfile.\n"); pushButton1->setEnabled(true); fclose(inputfile); if(edfplus) { fclose(logfile); free(log_buf); free(sublog_buf); fclose(pntfile); } return; } for(i=0; iappend("error reading inputfile.\n"); pushButton1->setEnabled(true); fclose(inputfile); if(edfplus) { fclose(logfile); free(log_buf); free(sublog_buf); fclose(pntfile); } return; } fseeko(inputfile, (long long)(ctlblock_address + 17), SEEK_SET); datablock_cnt = fgetc(inputfile); if(datablock_cnt==EOF) { textEdit1->append("error reading inputfile.\n"); pushButton1->setEnabled(true); fclose(inputfile); if(edfplus) { fclose(logfile); free(log_buf); free(sublog_buf); fclose(pntfile); } return; } for(j=0; jappend("error reading inputfile.\n"); pushButton1->setEnabled(true); fclose(inputfile); if(edfplus) { fclose(logfile); free(log_buf); free(sublog_buf); fclose(pntfile); } return; } /********************************************************************/ strcpy(outputpath, path); if(edfplus) sprintf(outputpath + strlen(path) - 4, "_%u-%u+.edf", i + 1, j + 1); else sprintf(outputpath + strlen(path) - 4, "_%u-%u.edf", i + 1, j + 1); outputfile = fopeno(outputpath, "wb"); if(outputfile==NULL) { snprintf(txt_string, 2048, "can not open file %s for writing.\n", outputpath); textEdit1->append(QString::fromLocal8Bit(txt_string)); pushButton1->setEnabled(true); fclose(inputfile); if(edfplus) { fclose(logfile); free(log_buf); free(sublog_buf); fclose(pntfile); } return; } textEdit1->append("Converting a waveform datablock..."); for(k=0; k<10; k++) qApp->processEvents(); error = convert_nk2edf(inputfile, outputfile, pntfile, wfmblock_address, edfplus, total_logs, log_buf, read_subevents); if(error==0) { snprintf(txt_string, 2048, "to %s", outputpath); textEdit1->append(txt_string); } if(error==1) textEdit1->append("malloc error.\n"); if(error==2) textEdit1->append("read error during conversion.\n"); if(error==3) textEdit1->append("write error during conversion.\n"); if(error==4) textEdit1->append("format error.\n"); if(fclose(outputfile)) { textEdit1->append("error closing outputfile.\n"); pushButton1->setEnabled(true); fclose(inputfile); if(edfplus) { fclose(logfile); fclose(pntfile); free(log_buf); free(sublog_buf); } return; } if(error) { if(edfplus) { fclose(logfile); fclose(pntfile); free(log_buf); free(sublog_buf); } pushButton1->setEnabled(true); return; } total_blocks++; /**************************************************************/ } } if(fclose(inputfile)) textEdit1->append("error closing inputfile.\n"); if(edfplus) { if(fclose(logfile)) textEdit1->append("error closing .log file.\n"); if(fclose(pntfile)) textEdit1->append("error closing .pnt file.\n"); free(log_buf); free(sublog_buf); } if(edfplus) snprintf(txt_string, 2048, "Converted %u waveformblock(s) successfully to EDF+.\n", total_blocks); else snprintf(txt_string, 2048, "Converted %u waveformblock(s) successfully to EDF.\n", total_blocks); textEdit1->append(txt_string); pushButton1->setEnabled(true); } int UI_NK2EDFwindow::convert_nk2edf(FILE *inputfile, FILE *outputfile, FILE *pntfile, int offset, int edfplus, int n_logs, char *log_buf, int read_subevents) { int i, j, k, p, temp, channels, samplefrequency, record_duration, raster, record_size, max_buf_records, bufsize, records_in_buf, seconds, deci_seconds, left_records, elapsed_time, error, records_written, progress_steps, n_log_processed; char *buf, *annotations, scratchpad[48]; /************************* filter events ******************************************/ for(i=0; i=total_elapsed_time) break; } log_buf += i * 45; n_logs -= i; /************************* write EDF-header ***************************************/ rewind(outputfile); fprintf(outputfile, "0 "); if(edfplus) { error = 0; fseeko(pntfile, 0x0604LL, SEEK_SET); if(fread(scratchpad, 10, 1, pntfile)!=1) { return(2); } scratchpad[10] = 0; latin1_to_ascii(scratchpad, strlen(scratchpad)); for(i=0; i<10; i++) { if(scratchpad[i]==0) break; if(scratchpad[i]==' ') scratchpad[i] = '_'; } if(i) { p = i; if(fwrite(scratchpad, i, 1, outputfile)!=1) { return(3); } } else { fputc('X', outputfile); p = 1; } fputc(' ', outputfile); p++; fseeko(pntfile, 0x064aLL, SEEK_SET); if(fread(scratchpad, 6, 1, pntfile)!=1) { return(2); } if(!strncmp(scratchpad, "Male", 4)) fputc('M', outputfile); else { if(!strncmp(scratchpad, "Female", 6)) fputc('F', outputfile); else fputc('X', outputfile); } p++; fputc(' ', outputfile); p++; fseeko(pntfile, 0x0668LL, SEEK_SET); if(fread(scratchpad, 2, 1, pntfile)!=1) { return(2); } scratchpad[2] = 0; temp = atoi(scratchpad); if((temp<1)||(temp>31)) error = 1; for(i=0; i<2; i++) { if((scratchpad[i]<'0')||(scratchpad[i]>'9')) { error = 1; break; } } fseeko(pntfile, 0x0665LL, SEEK_SET); if(fread(scratchpad, 2, 1, pntfile)!=1) { return(2); } scratchpad[2] = 0; temp = atoi(scratchpad); if((temp<1)||(temp>12)) error = 1; fseeko(pntfile, 0x0660LL, SEEK_SET); if(fread(scratchpad, 4, 1, pntfile)!=1) { return(2); } scratchpad[4] = 0; temp = atoi(scratchpad); if((temp<1)||(temp>9999)) error = 1; for(i=0; i<4; i++) { if((scratchpad[i]<'0')||(scratchpad[i]>'9')) { error = 1; break; } } if(error) { fputc('X', outputfile); p++; } else { fseeko(pntfile, 0x0668LL, SEEK_SET); if(fread(scratchpad, 2, 1, pntfile)!=1) { return(2); } scratchpad[2] = 0; temp = atoi(scratchpad); if((temp<1)||(temp>31)) { snprintf(scratchpad, 48, "01"); error = 1; } for(i=0; i<2; i++) { if((scratchpad[i]<'0')||(scratchpad[i]>'9')) { snprintf(scratchpad, 48, "01"); error = 1; break; } } if(fwrite(scratchpad, 2, 1, outputfile)!=1) { return(3); } p += 2; fputc('-', outputfile); p++; fseeko(pntfile, 0x0665LL, SEEK_SET); if(fread(scratchpad, 2, 1, pntfile)!=1) { return(2); } scratchpad[2] = 0; temp = atoi(scratchpad); switch(temp) { case 1 : strcpy(scratchpad, "JAN"); break; case 2 : strcpy(scratchpad, "FEB"); break; case 3 : strcpy(scratchpad, "MAR"); break; case 4 : strcpy(scratchpad, "APR"); break; case 5 : strcpy(scratchpad, "MAY"); break; case 6 : strcpy(scratchpad, "JUN"); break; case 7 : strcpy(scratchpad, "JUL"); break; case 8 : strcpy(scratchpad, "AUG"); break; case 9 : strcpy(scratchpad, "SEP"); break; case 10 : strcpy(scratchpad, "OCT"); break; case 11 : strcpy(scratchpad, "NOV"); break; case 12 : strcpy(scratchpad, "DEC"); break; default : strcpy(scratchpad, "JAN"); error = 1; break; } if(fwrite(scratchpad, 3, 1, outputfile)!=1) { return(3); } p += 3; fputc('-', outputfile); p++; fseeko(pntfile, 0x0660LL, SEEK_SET); if(fread(scratchpad, 4, 1, pntfile)!=1) { return(2); } scratchpad[4] = 0; temp = atoi(scratchpad); if((temp<1)||(temp>9999)) { snprintf(scratchpad, 48, "1800"); error = 1; } for(i=0; i<4; i++) { if((scratchpad[i]<'0')||(scratchpad[i]>'9')) { snprintf(scratchpad, 48, "1800"); error = 1; break; } } if(fwrite(scratchpad, 4, 1, outputfile)!=1) { return(3); } p += 4; } fputc(' ', outputfile); p++; fseeko(pntfile, 0x062eLL, SEEK_SET); if(fread(scratchpad, 20, 1, pntfile)!=1) { return(2); } scratchpad[20] = 0; latin1_to_ascii(scratchpad, strlen(scratchpad)); for(i=0; i<20; i++) { if(scratchpad[i]==0) break; if(scratchpad[i]==' ') scratchpad[i] = '_'; } if(i) { p += i; if(fwrite(scratchpad, i, 1, outputfile)!=1) { return(3); } } else { fputc('X', outputfile); p++; } for(i=0; i<80-p; i++) fputc(' ', outputfile); if(fwrite("Startdate ", 10, 1, outputfile)!=1) { return(3); } p = 10; error = 0; fseeko(pntfile, 0x0046LL, SEEK_SET); if(fread(scratchpad, 2, 1, pntfile)!=1) { return(2); } scratchpad[2] = 0; temp = atoi(scratchpad); if((temp<1)||(temp>31)) error = 1; for(i=0; i<2; i++) { if((scratchpad[i]<'0')||(scratchpad[i]>'9')) { error = 1; break; } } fseeko(pntfile, 0x0044LL, SEEK_SET); if(fread(scratchpad, 2, 1, pntfile)!=1) { return(2); } scratchpad[2] = 0; temp = atoi(scratchpad); if((temp<1)||(temp>12)) error = 1; fseeko(pntfile, 0x0040LL, SEEK_SET); if(fread(scratchpad, 4, 1, pntfile)!=1) { return(2); } scratchpad[4] = 0; temp = atoi(scratchpad); if((temp<1970)||(temp>9999)) error = 1; for(i=0; i<4; i++) { if((scratchpad[i]<'0')||(scratchpad[i]>'9')) { error = 1; break; } } if(error) { fputc('X', outputfile); p++; } else { fseeko(pntfile, 0x0046LL, SEEK_SET); if(fread(scratchpad, 2, 1, pntfile)!=1) { return(2); } scratchpad[2] = 0; temp = atoi(scratchpad); if((temp<1)||(temp>31)) snprintf(scratchpad, 48, "01"); for(i=0; i<2; i++) { if((scratchpad[i]<'0')||(scratchpad[i]>'9')) { snprintf(scratchpad, 48, "01"); break; } } if(fwrite(scratchpad, 2, 1, outputfile)!=1) { return(3); } fputc('-', outputfile); fseeko(pntfile, 0x0044LL, SEEK_SET); if(fread(scratchpad, 2, 1, pntfile)!=1) { return(2); } scratchpad[2] = 0; temp = atoi(scratchpad); switch(temp) { case 1 : strcpy(scratchpad, "JAN"); break; case 2 : strcpy(scratchpad, "FEB"); break; case 3 : strcpy(scratchpad, "MAR"); break; case 4 : strcpy(scratchpad, "APR"); break; case 5 : strcpy(scratchpad, "MAY"); break; case 6 : strcpy(scratchpad, "JUN"); break; case 7 : strcpy(scratchpad, "JUL"); break; case 8 : strcpy(scratchpad, "AUG"); break; case 9 : strcpy(scratchpad, "SEP"); break; case 10 : strcpy(scratchpad, "OCT"); break; case 11 : strcpy(scratchpad, "NOV"); break; case 12 : strcpy(scratchpad, "DEC"); break; default : strcpy(scratchpad, "JAN"); break; } if(fwrite(scratchpad, 3, 1, outputfile)!=1) { return(3); } fputc('-', outputfile); fseeko(pntfile, 0x0040LL, SEEK_SET); if(fread(scratchpad, 4, 1, pntfile)!=1) { return(2); } scratchpad[4] = 0; temp = atoi(scratchpad); if((temp<1)||(temp>9999)) snprintf(scratchpad, 48, "1800"); for(i=0; i<4; i++) { if((scratchpad[i]<'0')||(scratchpad[i]>'9')) { snprintf(scratchpad, 48, "1800"); break; } } if(fwrite(scratchpad, 4, 1, outputfile)!=1) { return(3); } p += 11; } fputc(' ', outputfile); p++; fseeko(pntfile, 0x061cLL, SEEK_SET); if(fread(scratchpad, 10, 1, pntfile)!=1) { return(2); } scratchpad[10] = 0; latin1_to_ascii(scratchpad, strlen(scratchpad)); for(i=0; i<10; i++) { if(scratchpad[i]==0) break; if(scratchpad[i]==' ') scratchpad[i] = '_'; } if(i) { p += i; if(fwrite(scratchpad, i, 1, outputfile)!=1) { return(3); } } else { fputc('X', outputfile); p++; } fputc(' ', outputfile); p++; fseeko(pntfile, 0x06aaLL, SEEK_SET); if(fread(scratchpad, 20, 1, pntfile)!=1) { return(2); } scratchpad[20] = 0; latin1_to_ascii(scratchpad, strlen(scratchpad)); for(i=0; i<20; i++) { if(scratchpad[i]==0) break; if(scratchpad[i]==' ') scratchpad[i] = '_'; } if(i) { p += i; if(fwrite(scratchpad, i, 1, outputfile)!=1) { return(3); } } else { fputc('X', outputfile); p++; } fputc(' ', outputfile); p++; if(fwrite("Nihon_Kohden_", 13, 1, outputfile)!=1) { return(3); } p += 13; rewind(inputfile); if(fread(scratchpad, 16, 1, inputfile)!=1) { return(2); } scratchpad[16] = 0; latin1_to_ascii(scratchpad, strlen(scratchpad)); for(i=0; i<16; i++) { if(scratchpad[i]==0) break; if(scratchpad[i]==' ') scratchpad[i] = '_'; } if(fwrite(scratchpad, i, 1, outputfile)!=1) { return(3); } p += i; for(i=0; i<80-p; i++) fputc(' ', outputfile); } else { fseeko(inputfile, 0x004fLL, SEEK_SET); if(fread(scratchpad, 32, 1, inputfile)!=1) { return(2); } scratchpad[32] = 0; latin1_to_ascii(scratchpad, strlen(scratchpad)); for(i=0; i<32; i++) { if(scratchpad[i]==0) break; } p = 80 - i; if(fwrite(scratchpad, i, 1, outputfile)!=1) { return(3); } for(i=0; i> 4) * 10) + (temp & 15)); fseeko(inputfile, (long long)(0x0015 + offset), SEEK_SET); temp = fgetc(inputfile); fprintf(outputfile, "%02u.", ((temp >> 4) * 10) + (temp & 15)); fseeko(inputfile, (long long)(0x0014 + offset), SEEK_SET); temp = fgetc(inputfile); fprintf(outputfile, "%02u", ((temp >> 4) * 10) + (temp & 15)); fseeko(inputfile, (long long)(0x0017 + offset), SEEK_SET); temp = fgetc(inputfile); fprintf(outputfile, "%02u.", ((temp >> 4) * 10) + (temp & 15)); temp = fgetc(inputfile); fprintf(outputfile, "%02u.", ((temp >> 4) * 10) + (temp & 15)); temp = fgetc(inputfile); fprintf(outputfile, "%02u", ((temp >> 4) * 10) + (temp & 15)); fseeko(inputfile, (long long)(0x0026 + offset), SEEK_SET); channels = fgetc(inputfile) + 1; if(edfplus) { fprintf(outputfile, "%-8u", (channels + 1) * 256 + 256); fprintf(outputfile, "EDF+C"); for(i=0; i<39; i++) fputc(' ', outputfile); } else { fprintf(outputfile, "%-8u", channels * 256 + 256); for(i=0; i<44; i++) fputc(' ', outputfile); } fseeko(inputfile, (long long)(0x001c + offset), SEEK_SET); if(fread((char *)(&record_duration), 4, 1, inputfile)!=1) { return(2); } if((record_duration < 10) || (record_duration > 99999999)) { return(4); } fprintf(outputfile, "%-8u", record_duration); fprintf(outputfile, "0.1 "); if(edfplus) fprintf(outputfile, "%-4u", channels + 1); else fprintf(outputfile, "%-4u", channels); for(i=0; i<(channels - 1); i++) { fseeko(inputfile, (long long)(0x0027 + (i * 10) + offset), SEEK_SET); temp = fgetc(inputfile); if((temp < 0) || (temp > 255)) { fprintf(outputfile, "%s", "- "); } else { fprintf(outputfile, "%s", labels[temp]); } } fprintf(outputfile, "Events/Markers "); if(edfplus) fprintf(outputfile, "EDF Annotations "); for(i=0; i<(channels * 80); i++) fputc(' ', outputfile); if(edfplus) for(i=0; i<80; i++) fputc(' ', outputfile); for(i=0; i<(channels - 1); i++) { fseeko(inputfile, (long long)(0x0027 + (i * 10) + offset), SEEK_SET); temp = fgetc(inputfile); if(((temp<42)||(temp>73)) && (temp!=76) && (temp!=77)) fprintf(outputfile, "uV "); else fprintf(outputfile, "mV "); } fprintf(outputfile, " "); if(edfplus) fprintf(outputfile, " "); for(i=0; i<(channels - 1); i++) { fseeko(inputfile, (long long)(0x0027 + (i * 10) + offset), SEEK_SET); temp = fgetc(inputfile); if(((temp<42)||(temp>73)) && (temp!=76) && (temp!=77)) fprintf(outputfile, "-3200 "); else fprintf(outputfile, "-12002.9"); } fprintf(outputfile, "-1 "); if(edfplus) fprintf(outputfile, "-1 "); for(i=0; i<(channels - 1); i++) { fseeko(inputfile, (long long)(0x0027 + (i * 10) + offset), SEEK_SET); temp = fgetc(inputfile); if(((temp<42)||(temp>73)) && (temp!=76) && (temp!=77)) fprintf(outputfile, "3199.902"); else fprintf(outputfile, "12002.56"); } fprintf(outputfile, "1 "); if(edfplus) fprintf(outputfile, "1 "); for(i=0; imax_buf_records) records_in_buf = max_buf_records; else records_in_buf = left_records; for(i=0; iprocessEvents(); } for(j=0; j=total_elapsed_time) { elapsed_time -= total_elapsed_time; if(elapsed_time<(record_duration / 10)) { p++; p += sprintf(annotations + p, "%+i", elapsed_time); if(read_subevents) { annotations[p] = '.'; p++; strncpy(annotations + p, log_buf + (n_log_processed * 45) + 26, 3); p += 3; } annotations[p++] = 20; strncpy(annotations + p, log_buf + (n_log_processed * 45), 20); p += 20; annotations[p] = 20; n_log_processed++; break; } } } } if(++deci_seconds>9) { deci_seconds = 0; seconds++; } records_written++; } if(fwrite(buf, records_in_buf * record_size, 1, outputfile)!=1) { free(buf); return(3); } left_records -= records_in_buf; } progress.reset(); total_elapsed_time += record_duration / 10; free(buf); return(0); } int UI_NK2EDFwindow::check_device(char *str) { int error = 1; if(!strncmp(str, "EEG-1100A V01.00", 16)) error = 0; if(!strncmp(str, "EEG-1100B V01.00", 16)) error = 0; if(!strncmp(str, "EEG-1100C V01.00", 16)) error = 0; if(!strncmp(str, "QI-403A V01.00", 16)) error = 0; if(!strncmp(str, "QI-403A V02.00", 16)) error = 0; if(!strncmp(str, "EEG-2100 V01.00", 16)) error = 0; if(!strncmp(str, "EEG-2100 V02.00", 16)) error = 0; if(!strncmp(str, "DAE-2100D V01.30", 16)) error = 0; if(!strncmp(str, "DAE-2100D V02.00", 16)) error = 0; // if(!strncmp(str, "EEG-1200A V01.00", 16)) error = 0; if(!strncmp(str, "EEG-1100A V02.00", 16)) error = 0; if(!strncmp(str, "EEG-1100B V02.00", 16)) error = 0; if(!strncmp(str, "EEG-1100C V02.00", 16)) error = 0; return(error); } int UI_NK2EDFwindow::read_21e_file(char *e21filepath) { int n, flag_eleclines=0, idx; char *electrode_name, electrode_name_buffer[ELECTRODE_NAME_MAXLEN], scratchpad[64], *charpntr; FILE *inputfile; remove_extension_from_filename(e21filepath); strcat(e21filepath, ".21E"); inputfile = fopeno(e21filepath, "rb"); if(inputfile==NULL) { remove_extension_from_filename(e21filepath); strcat(e21filepath, ".21e"); inputfile = fopeno(e21filepath, "rb"); if(inputfile==NULL) { return(1); } } while (!feof(inputfile)) { charpntr = fgets(electrode_name_buffer, ELECTRODE_NAME_MAXLEN-1, inputfile); if(charpntr == NULL) { break; } if(strncmp(electrode_name_buffer, ELECTRODE_TAG, strlen(ELECTRODE_TAG)) == 0) { flag_eleclines = 1; } else { if(strncmp(electrode_name_buffer, ELECTRODE_UNTAG, strlen(ELECTRODE_UNTAG)) == 0) { flag_eleclines = 0; } } if(flag_eleclines) { if(strtok(electrode_name_buffer, "=") != NULL) { idx = atoi(electrode_name_buffer); electrode_name = strtok(NULL, "="); if(electrode_name != NULL) { n = strlen(electrode_name); if((n > 0)&&(electrode_name[n-1] == 10)) { electrode_name[n-1] = 0; } if((n > 1)&&(electrode_name[n-2] == 13)) { electrode_name[n-2] = 0; } n = strlen(electrode_name); if((idx >= 0) && (idx < 256)) { if(n > 0) { strncpy(scratchpad, electrode_name, 16); strcat(scratchpad, " "); latin1_to_ascii(scratchpad, 16); scratchpad[16] = 0; strcpy(labels[idx], scratchpad); } else { strcpy(labels[idx], "- "); } } } } } } fclose(inputfile); return(0); } edfbrowser_157_source/PaxHeaders.7921/ecg_export.h0000644000000000000000000000013212646460742017176 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/ecg_export.h0000644000175000001440000000427612646460742017550 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef ECGEXPORTCLASS_H #define ECGEXPORTCLASS_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "viewcurve.h" #include "utils.h" #include "filteredblockread.h" #include "edf_annot_list.h" class UI_Mainwindow; class ViewCurve; class UI_ECGExport : public QObject { Q_OBJECT public: UI_ECGExport(QWidget *parent); UI_Mainwindow *mainwindow; private: QDialog *myobjectDialog; QListWidget *list; QPushButton *startButton, *cancelButton; QGroupBox *groupBox1; QVBoxLayout *vbox1; QRadioButton *radioButton1, *radioButton2, *radioButton3; QCheckBox *checkBox1, *checkBox2; void load_signalcomps(void); private slots: void Export_RR_intervals(); }; #endif edfbrowser_157_source/PaxHeaders.7921/options_dialog.cpp0000644000000000000000000000012712646460742020410 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/options_dialog.cpp0000644000175000001440000015661412646460742020762 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "options_dialog.h" UI_OptionsDialog::UI_OptionsDialog(QWidget *w_parent) { int i, showminimized=0; mainwindow = (UI_Mainwindow *)w_parent; optionsdialog = new QDialog(w_parent); if(QApplication::desktop()->screenGeometry().height() < 900) { showminimized = 1; } if(showminimized) { optionsdialog->setMinimumSize(480, 500); optionsdialog->setMaximumSize(480, 820); scrollarea = new QScrollArea; scrollarea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); frame = new QFrame; frame->setMinimumSize(440, 780); frame->setMaximumSize(440, 780); } else { optionsdialog->setMinimumSize(440, 780); optionsdialog->setMaximumSize(440, 780); } optionsdialog->setWindowTitle("Settings"); optionsdialog->setModal(true); optionsdialog->setAttribute(Qt::WA_DeleteOnClose, true); tabholder = new QTabWidget; CloseButton = new QPushButton; CloseButton->setText("Close"); /////////////////////////////////////// tab 1 Colors /////////////////////////////////////////////////////////////////////// tab1 = new QWidget; label1 = new QLabel(tab1); label1->setGeometry(20, 15, 200, 25); label1->setText("Background color"); BgColorButton = new SpecialButton(tab1); BgColorButton->setGeometry(240, 20, 60, 15); BgColorButton->setColor(mainwindow->maincurve->backgroundcolor); label2 = new QLabel(tab1); label2->setGeometry(20, 55, 200, 25); label2->setText("Small ruler color"); SrColorButton = new SpecialButton(tab1); SrColorButton->setGeometry(240, 60, 60, 15); SrColorButton->setColor(mainwindow->maincurve->small_ruler_color); label3 = new QLabel(tab1); label3->setGeometry(20, 95, 200, 25); label3->setText("Big ruler color"); BrColorButton = new SpecialButton(tab1); BrColorButton->setGeometry(240, 100, 60, 15); BrColorButton->setColor(mainwindow->maincurve->big_ruler_color); label4 = new QLabel(tab1); label4->setGeometry(20, 135, 200, 25); label4->setText("Mouse rectangle color"); MrColorButton = new SpecialButton(tab1); MrColorButton->setGeometry(240, 140, 60, 15); MrColorButton->setColor(mainwindow->maincurve->mouse_rect_color); label5 = new QLabel(tab1); label5->setGeometry(20, 175, 200, 25); label5->setText("Text color"); TxtColorButton = new SpecialButton(tab1); TxtColorButton->setGeometry(240, 180, 60, 15); TxtColorButton->setColor(mainwindow->maincurve->text_color); label6 = new QLabel(tab1); label6->setGeometry(20, 215, 200, 25); label6->setText("Signals color"); SigColorButton = new SpecialButton(tab1); SigColorButton->setGeometry(240, 220, 60, 15); SigColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->signal_color); label7 = new QLabel(tab1); label7->setGeometry(20, 255, 200, 25); label7->setText("Baseline color"); checkbox3 = new QCheckBox(tab1); checkbox3->setGeometry(200, 258, 20, 20); checkbox3->setTristate(false); if(mainwindow->show_baselines) { checkbox3->setCheckState(Qt::Checked); } else { checkbox3->setCheckState(Qt::Unchecked); } BaseColorButton = new SpecialButton(tab1); BaseColorButton->setGeometry(240, 260, 60, 15); BaseColorButton->setColor(mainwindow->maincurve->baseline_color); label8 = new QLabel(tab1); label8->setGeometry(20, 295, 200, 25); label8->setText("Crosshair color"); Crh1ColorButton = new SpecialButton(tab1); Crh1ColorButton->setGeometry(240, 300, 60, 15); Crh1ColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->crosshair_1.color); label9 = new QLabel(tab1); label9->setGeometry(20, 335, 200, 25); label9->setText("2th Crosshair color"); Crh2ColorButton = new SpecialButton(tab1); Crh2ColorButton->setGeometry(240, 340, 60, 15); Crh2ColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->crosshair_2.color); label10 = new QLabel(tab1); label10->setGeometry(20, 375, 200, 25); label10->setText("Floating ruler color"); FrColorButton = new SpecialButton(tab1); FrColorButton->setGeometry(240, 380, 60, 15); FrColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->floating_ruler_color); label12 = new QLabel(tab1); label12->setGeometry(20, 415, 200, 25); label12->setText("Annotation marker"); checkbox2 = new QCheckBox(tab1); checkbox2->setGeometry(200, 418, 20, 20); checkbox2->setTristate(false); if(mainwindow->show_annot_markers) { checkbox2->setCheckState(Qt::Checked); } else { checkbox2->setCheckState(Qt::Unchecked); } AnnotMkrButton = new SpecialButton(tab1); AnnotMkrButton->setGeometry(240, 420, 60, 15); AnnotMkrButton->setColor(mainwindow->maincurve->annot_marker_color); label11 = new QLabel(tab1); label11->setGeometry(20, 455, 200, 25); label11->setText("Print in grayscale"); checkbox1 = new QCheckBox(tab1); checkbox1->setGeometry(200, 458, 20, 20); checkbox1->setTristate(false); if(mainwindow->maincurve->blackwhite_printing) { checkbox1->setCheckState(Qt::Checked); } else { checkbox1->setCheckState(Qt::Unchecked); } label13 = new QLabel(tab1); label13->setGeometry(20, 495, 200, 25); label13->setText("Clip signals to pane"); checkbox4 = new QCheckBox(tab1); checkbox4->setGeometry(200, 498, 20, 20); checkbox4->setTristate(false); if(mainwindow->clip_to_pane) { checkbox4->setCheckState(Qt::Checked); } else { checkbox4->setCheckState(Qt::Unchecked); } colorSchema_Dark_Button = new QPushButton(tab1); colorSchema_Dark_Button->setGeometry(140, 540, 140, 20); colorSchema_Dark_Button->setText("Colorschema \"Dark\""); colorSchema_NK_Button = new QPushButton(tab1); colorSchema_NK_Button->setGeometry(140, 570, 140, 20); colorSchema_NK_Button->setText("Colorschema \"NK\""); DefaultButton = new QPushButton(tab1); DefaultButton->setGeometry(140, 600, 140, 20); DefaultButton->setText("Default colorschema"); saveColorSchemaButton = new QPushButton(tab1); saveColorSchemaButton->setGeometry(140, 630, 140, 20); saveColorSchemaButton->setText("Save colorschema"); loadColorSchemaButton = new QPushButton(tab1); loadColorSchemaButton->setGeometry(140, 660, 140, 20); loadColorSchemaButton->setText("Load colorschema"); QObject::connect(BgColorButton, SIGNAL(clicked(SpecialButton *)), this, SLOT(BgColorButtonClicked(SpecialButton *))); QObject::connect(SrColorButton, SIGNAL(clicked(SpecialButton *)), this, SLOT(SrColorButtonClicked(SpecialButton *))); QObject::connect(BrColorButton, SIGNAL(clicked(SpecialButton *)), this, SLOT(BrColorButtonClicked(SpecialButton *))); QObject::connect(MrColorButton, SIGNAL(clicked(SpecialButton *)), this, SLOT(MrColorButtonClicked(SpecialButton *))); QObject::connect(TxtColorButton, SIGNAL(clicked(SpecialButton *)), this, SLOT(TxtColorButtonClicked(SpecialButton *))); QObject::connect(SigColorButton, SIGNAL(clicked(SpecialButton *)), this, SLOT(SigColorButtonClicked(SpecialButton *))); QObject::connect(BaseColorButton, SIGNAL(clicked(SpecialButton *)), this, SLOT(BaseColorButtonClicked(SpecialButton *))); QObject::connect(Crh1ColorButton, SIGNAL(clicked(SpecialButton *)), this, SLOT(Crh1ColorButtonClicked(SpecialButton *))); QObject::connect(Crh2ColorButton, SIGNAL(clicked(SpecialButton *)), this, SLOT(Crh2ColorButtonClicked(SpecialButton *))); QObject::connect(FrColorButton, SIGNAL(clicked(SpecialButton *)), this, SLOT(FrColorButtonClicked(SpecialButton *))); QObject::connect(AnnotMkrButton, SIGNAL(clicked(SpecialButton *)), this, SLOT(AnnotMkrButtonClicked(SpecialButton *))); QObject::connect(checkbox1, SIGNAL(stateChanged(int)), this, SLOT(checkbox1Clicked(int))); QObject::connect(checkbox2, SIGNAL(stateChanged(int)), this, SLOT(checkbox2Clicked(int))); QObject::connect(checkbox3, SIGNAL(stateChanged(int)), this, SLOT(checkbox3Clicked(int))); 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_NK_Button, SIGNAL(clicked()), this, SLOT(loadColorSchema_NK())); QObject::connect(colorSchema_Dark_Button, SIGNAL(clicked()), this, SLOT(loadColorSchema_Dark())); tabholder->addTab(tab1, "Colors"); /////////////////////////////////////// tab 2 Calibration /////////////////////////////////////////////////////////////////////// tab2 = new QWidget; checkbox2_1 = new QCheckBox("Manually override automatic DPI settings", tab2); checkbox2_1->setGeometry(85, 560, 300, 20); checkbox2_1->setTristate(false); if(mainwindow->auto_dpi) { checkbox2_1->setCheckState(Qt::Unchecked); } else { checkbox2_1->setCheckState(Qt::Checked); } slabel2_1 = new SpecialButton(tab2); slabel2_1->setGeometry(30, 20, 10, 445); slabel2_1->setColor(Qt::black); slabel2_3 = new SpecialButton(tab2); slabel2_3->setGeometry(30, 500, 355, 10); slabel2_3->setColor(Qt::black); label2_2 = new QLabel(tab2); label2_2->setGeometry(85, 50, 220, 50); label2_2->setText("Measure the length of the black\nrectangles and enter the values."); spinbox2_1 = new QSpinBox(tab2); spinbox2_1->setGeometry(85, 240, 100, 25); spinbox2_1->setSuffix(" mm"); spinbox2_1->setMinimum(10); spinbox2_1->setMaximum(500); spinbox2_1->setValue((int)(4450.0 / (1.0 / mainwindow->pixelsizefactor))); spinbox2_2 = new QSpinBox(tab2); spinbox2_2->setGeometry(170, 450, 100, 25); spinbox2_2->setSuffix(" mm"); spinbox2_2->setMinimum(10); spinbox2_2->setMaximum(500); spinbox2_2->setValue((int)(3550.0 / (1.0 / mainwindow->x_pixelsizefactor))); ApplyButton = new QPushButton(tab2); ApplyButton->setGeometry(85, 600, 100, 25); ApplyButton->setText("Apply"); if(checkbox2_1->checkState() == Qt::Unchecked) { spinbox2_1->setEnabled(false); spinbox2_2->setEnabled(false); ApplyButton->setEnabled(false); } QObject::connect(ApplyButton, SIGNAL(clicked()), this, SLOT(ApplyButtonClicked())); QObject::connect(checkbox2_1, SIGNAL(stateChanged(int)), this, SLOT(calibrate_checkbox_stateChanged(int))); tabholder->addTab(tab2, "Calibration"); /////////////////////////////////////// tab 3 Powerspectrum /////////////////////////////////////////////////////////////////////// tab3 = new QWidget; label1_3 = new QLabel(tab3); label1_3->setGeometry(20, 20, 330, 25); label1_3->setText("Frequency regions of the colorbars:"); colorBarTable = new QTableWidget(tab3); colorBarTable->setGeometry(20, 50, 370, 350); colorBarTable->setSelectionMode(QAbstractItemView::NoSelection); colorBarTable->setColumnCount(4); colorBarTable->setColumnWidth(0, 20); colorBarTable->setColumnWidth(1, 140); colorBarTable->setColumnWidth(2, 80); colorBarTable->setColumnWidth(3, 100); colorBarTable->setRowCount(MAXSPECTRUMMARKERS); for(i=0; i < MAXSPECTRUMMARKERS; i++) { colorBarTable->setRowHeight(i, 25); colorBarTable->setCellWidget(i, 0, new QCheckBox); ((QCheckBox *)(colorBarTable->cellWidget(i, 0)))->setTristate(false); if(i < mainwindow->spectrum_colorbar->items) { ((QCheckBox *)(colorBarTable->cellWidget(i, 0)))->setCheckState(Qt::Checked); } else { ((QCheckBox *)(colorBarTable->cellWidget(i, 0)))->setCheckState(Qt::Unchecked); } QObject::connect(colorBarTable->cellWidget(i, 0), SIGNAL(stateChanged(int)), this, SLOT(checkBoxChanged(int))); colorBarTable->setCellWidget(i, 1, new QDoubleSpinBox); ((QDoubleSpinBox *)(colorBarTable->cellWidget(i, 1)))->setDecimals(3); ((QDoubleSpinBox *)(colorBarTable->cellWidget(i, 1)))->setSuffix(" Hz"); ((QDoubleSpinBox *)(colorBarTable->cellWidget(i, 1)))->setRange(0.001, 100000.0); ((QDoubleSpinBox *)(colorBarTable->cellWidget(i, 1)))->setValue(mainwindow->spectrum_colorbar->freq[i]); QObject::connect((QDoubleSpinBox *)(colorBarTable->cellWidget(i, 1)), SIGNAL(valueChanged(double)), this, SLOT(spinBoxValueChanged(double))); colorBarTable->setCellWidget(i, 2, new SpecialButton); ((SpecialButton *)(colorBarTable->cellWidget(i, 2)))->setGlobalColor(mainwindow->spectrum_colorbar->color[i]); QObject::connect((SpecialButton *)(colorBarTable->cellWidget(i, 2)), SIGNAL(clicked(SpecialButton *)), this, SLOT(colorBarButtonClicked(SpecialButton *))); colorBarTable->setCellWidget(i, 3, new QLineEdit); ((QLineEdit *)(colorBarTable->cellWidget(i, 3)))->setText(mainwindow->spectrum_colorbar->label[i]); ((QLineEdit *)(colorBarTable->cellWidget(i, 3)))->setMaxLength(16); QObject::connect((QLineEdit *)(colorBarTable->cellWidget(i, 3)), SIGNAL(textEdited(const QString &)), this, SLOT(labelEdited(const QString &))); } QStringList horizontallabels; horizontallabels += ""; horizontallabels += "Frequency"; horizontallabels += "Color"; horizontallabels += "Label"; colorBarTable->setHorizontalHeaderLabels(horizontallabels); label2_3 = new QLabel(tab3); label2_3->setGeometry(20, 410, 310, 25); label2_3->setText("Height of colorbars are relative to the"); radiobutton1 = new QRadioButton(tab3); radiobutton1->setGeometry(20, 435, 200, 25); radiobutton1->setText("sum"); if(mainwindow->spectrum_colorbar->method == 0) { radiobutton1->setChecked(true); // sum } radiobutton2 = new QRadioButton(tab3); radiobutton2->setGeometry(20, 460, 200, 25); radiobutton2->setText("peak"); if(mainwindow->spectrum_colorbar->method == 1) { radiobutton2->setChecked(true); // peak } radiobutton3 = new QRadioButton(tab3); radiobutton3->setGeometry(20, 485, 200, 25); radiobutton3->setText("average"); if(mainwindow->spectrum_colorbar->method == 2) { radiobutton3->setChecked(true); // average } label3_3 = new QLabel(tab3); label3_3->setGeometry(20, 515, 310, 25); label3_3->setText("of the power in the colorbar region."); label3_4 = new QLabel(tab3); label3_4->setGeometry(20, 550, 120, 25); label3_4->setText("FFT blocksize:"); spinbox3_1 = new QSpinBox(tab3); spinbox3_1->setGeometry(140, 550, 140, 25); spinbox3_1->setSuffix(" samples"); spinbox3_1->setMinimum(10); spinbox3_1->setMaximum(16777216); // (2^24) spinbox3_1->setSingleStep(2); spinbox3_1->setValue(mainwindow->maxdftblocksize); label3_5 = new QLabel(tab3); label3_5->setGeometry(20, 590, 120, 25); label3_5->setText("Colorbar sensitivity:"); dspinbox3_2 = new QDoubleSpinBox(tab3); dspinbox3_2->setGeometry(140, 590, 140, 25); dspinbox3_2->setMinimum(0.0001); dspinbox3_2->setMaximum(100000.0); dspinbox3_2->setValue(mainwindow->spectrum_colorbar->max_colorbar_value); checkbox3_1 = new QCheckBox("Auto", tab3); checkbox3_1->setGeometry(300, 592, 100, 20); checkbox3_1->setTristate(false); if(mainwindow->spectrum_colorbar->auto_adjust) { checkbox3_1->setCheckState(Qt::Checked); dspinbox3_2->setEnabled(false); } else { checkbox3_1->setCheckState(Qt::Unchecked); } DefaultButton2 = new QPushButton(tab3); DefaultButton2->setGeometry(245, 650, 100, 25); DefaultButton2->setText("Restore default"); ApplyButton2 = new QPushButton(tab3); ApplyButton2->setGeometry(20, 650, 100, 25); ApplyButton2->setText("Apply"); ApplyButton2->setEnabled(false); QObject::connect(radiobutton1, SIGNAL(toggled(bool)), this, SLOT(radioButtonToggled(bool))); QObject::connect(radiobutton2, SIGNAL(toggled(bool)), this, SLOT(radioButtonToggled(bool))); QObject::connect(radiobutton3, SIGNAL(toggled(bool)), this, SLOT(radioButtonToggled(bool))); QObject::connect(spinbox3_1, SIGNAL(valueChanged(int)), this, SLOT(spinBox3_1ValueChanged(int))); QObject::connect(dspinbox3_2, SIGNAL(valueChanged(double)), this, SLOT(dspinBox3_2ValueChanged(double))); QObject::connect(ApplyButton2, SIGNAL(clicked()), this, SLOT(ApplyButton2Clicked())); QObject::connect(DefaultButton2, SIGNAL(clicked()), this, SLOT(DefaultButton2Clicked())); QObject::connect(checkbox3_1, SIGNAL(stateChanged(int)), this, SLOT(checkbox3_1Clicked(int))); tabholder->addTab(tab3, "Power Spectrum"); /////////////////////////////////////// tab 4 Other /////////////////////////////////////////////////////////////////////// tab4 = new QWidget; label4_1 = new QLabel(tab4); label4_1->setGeometry(20, 20, 280, 25); label4_1->setText("Reload last used montage"); checkbox4_1 = new QCheckBox(tab4); checkbox4_1->setGeometry(325, 23, 20, 20); checkbox4_1->setTristate(false); if(mainwindow->auto_reload_mtg) { checkbox4_1->setCheckState(Qt::Checked); } else { checkbox4_1->setCheckState(Qt::Unchecked); } QObject::connect(checkbox4_1, SIGNAL(stateChanged(int)), this, SLOT(checkbox4_1Clicked(int))); label4_7 = new QLabel(tab4); label4_7->setGeometry(20, 60, 280, 60); label4_7->setText("Do not read annotations, Biosemi Status signal\n" "or Nihon Kohden triggers when filesize\n" "is more than:"); spinbox4_3 = new QSpinBox(tab4); spinbox4_3->setGeometry(200, 100, 140, 25); spinbox4_3->setSuffix(" MB"); spinbox4_3->setMinimum(100); spinbox4_3->setMaximum(100000); spinbox4_3->setSingleStep(1); spinbox4_3->setValue((int)(mainwindow->maxfilesize_to_readin_annotations / 1048576LL)); QObject::connect(spinbox4_3, SIGNAL(valueChanged(int)), this, SLOT(spinBox4_3ValueChanged(int))); label4_2 = new QLabel(tab4); label4_2->setGeometry(20, 135, 280, 25); label4_2->setText("Read Biosemi Status signal"); checkbox4_2 = new QCheckBox(tab4); checkbox4_2->setGeometry(325, 138, 20, 20); checkbox4_2->setTristate(false); if(mainwindow->read_biosemi_status_signal) { checkbox4_2->setCheckState(Qt::Checked); } else { checkbox4_2->setCheckState(Qt::Unchecked); } QObject::connect(checkbox4_2, SIGNAL(stateChanged(int)), this, SLOT(checkbox4_2Clicked(int))); label4_6 = new QLabel(tab4); label4_6->setGeometry(20, 175, 280, 25); label4_6->setText("Read Nihon Kohden Trigger/Marker signal"); checkbox4_3 = new QCheckBox(tab4); checkbox4_3->setGeometry(325, 178, 20, 20); checkbox4_3->setTristate(false); if(mainwindow->read_nk_trigger_signal) { checkbox4_3->setCheckState(Qt::Checked); } else { checkbox4_3->setCheckState(Qt::Unchecked); } QObject::connect(checkbox4_3, SIGNAL(stateChanged(int)), this, SLOT(checkbox4_3Clicked(int))); label4_3 = new QLabel(tab4); label4_3->setGeometry(20, 215, 200, 25); label4_3->setText("livestream update interval"); spinbox4_1 = new QSpinBox(tab4); spinbox4_1->setGeometry(200, 215, 140, 25); spinbox4_1->setSuffix(" mSec"); spinbox4_1->setMinimum(100); spinbox4_1->setMaximum(3000); spinbox4_1->setSingleStep(1); spinbox4_1->setValue(mainwindow->live_stream_update_interval); QObject::connect(spinbox4_1, SIGNAL(valueChanged(int)), this, SLOT(spinBox4_1ValueChanged(int))); label4_4 = new QLabel(tab4); label4_4->setGeometry(20, 255, 200, 25); label4_4->setText("Powerline Frequency"); combobox4_1 = new QComboBox(tab4); combobox4_1->setGeometry(200, 255, 140, 25); combobox4_1->addItem("50 Hz"); combobox4_1->addItem("60 Hz"); if(mainwindow->powerlinefreq == 50) { combobox4_1->setCurrentIndex(0); } if(mainwindow->powerlinefreq == 60) { combobox4_1->setCurrentIndex(1); } QObject::connect(combobox4_1, SIGNAL(currentIndexChanged(int)), this, SLOT(combobox4_1IndexChanged(int))); label4_4 = new QLabel(tab4); label4_4->setGeometry(20, 295, 200, 40); label4_4->setText("Mousewheel stepsize\n" "(0 is no scroll)"); spinbox4_2 = new QSpinBox(tab4); spinbox4_2->setGeometry(200, 295, 140, 25); spinbox4_2->setPrefix("Timescale / "); spinbox4_2->setMinimum(0); spinbox4_2->setMaximum(100); spinbox4_2->setSingleStep(1); spinbox4_2->setValue(mainwindow->mousewheelsens); QObject::connect(spinbox4_2, SIGNAL(valueChanged(int)), this, SLOT(spinBox4_2ValueChanged(int))); label4_5 = new QLabel(tab4); label4_5->setGeometry(20, 335, 280, 25); label4_5->setText("Use Multi-Threading"); checkbox4_4 = new QCheckBox(tab4); checkbox4_4->setGeometry(325, 338, 20, 20); checkbox4_4->setTristate(false); if(mainwindow->use_threads) { checkbox4_4->setCheckState(Qt::Checked); } else { checkbox4_4->setCheckState(Qt::Unchecked); } QObject::connect(checkbox4_4, SIGNAL(stateChanged(int)), this, SLOT(checkbox4_4Clicked(int))); label4_8 = new QLabel(tab4); label4_8->setGeometry(20, 375, 310, 25); label4_8->setText("Check for updates during startup"); checkbox4_5 = new QCheckBox(tab4); checkbox4_5->setGeometry(325, 378, 20, 20); checkbox4_5->setTristate(false); if(mainwindow->check_for_updates) { checkbox4_5->setCheckState(Qt::Checked); } else { checkbox4_5->setCheckState(Qt::Unchecked); } QObject::connect(checkbox4_5, SIGNAL(stateChanged(int)), this, SLOT(checkbox4_5Clicked(int))); label4_9 = new QLabel(tab4); label4_9->setGeometry(20, 415, 310, 25); label4_9->setText("Viewtime / fileposition indicator"); combobox4_2 = new QComboBox(tab4); combobox4_2->setGeometry(200, 415, 140, 25); combobox4_2->addItem("relative"); combobox4_2->addItem("real (relative)"); combobox4_2->addItem("date real (relative)"); combobox4_2->setCurrentIndex(mainwindow->viewtime_indicator_type); QObject::connect(combobox4_2, SIGNAL(currentIndexChanged(int)), this, SLOT(combobox4_2IndexChanged(int))); label4_10 = new QLabel(tab4); label4_10->setGeometry(20, 455, 310, 25); label4_10->setText("Window title content"); combobox4_3 = new QComboBox(tab4); combobox4_3->setGeometry(200, 455, 180, 25); combobox4_3->addItem("Subject info"); combobox4_3->addItem("Filename"); combobox4_3->addItem("Filename with full path"); combobox4_3->setCurrentIndex(mainwindow->mainwindow_title_type); QObject::connect(combobox4_3, SIGNAL(currentIndexChanged(int)), this, SLOT(combobox4_3IndexChanged(int))); label4_11 = new QLabel(tab4); label4_11->setGeometry(20, 495, 310, 25); label4_11->setText("Default amplitude"); dspinbox4_4 = new QDoubleSpinBox(tab4); dspinbox4_4->setGeometry(200, 495, 140, 25); dspinbox4_4->setMinimum(0.001); dspinbox4_4->setMaximum(10000000); dspinbox4_4->setSuffix(" /cm"); dspinbox4_4->setValue(mainwindow->default_amplitude); QObject::connect(dspinbox4_4, SIGNAL(valueChanged(double)), this, SLOT(dspinbox4_4ValueChanged(double))); label4_12 = new QLabel(tab4); label4_12->setGeometry(20, 535, 310, 25); label4_12->setText("Use linear interpolation"); checkbox4_6 = new QCheckBox(tab4); checkbox4_6->setGeometry(325, 538, 20, 20); checkbox4_6->setTristate(false); if(mainwindow->linear_interpol) { checkbox4_6->setCheckState(Qt::Checked); } else { checkbox4_6->setCheckState(Qt::Unchecked); } QObject::connect(checkbox4_6, SIGNAL(stateChanged(int)), this, SLOT(checkbox4_6Clicked(int))); tabholder->addTab(tab4, "Other"); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// horLayout = new QHBoxLayout; horLayout->addSpacing(300); horLayout->addWidget(CloseButton); mainLayout = new QVBoxLayout; mainLayout->addWidget(tabholder); mainLayout->addLayout(horLayout); if(showminimized) { frame->setLayout(mainLayout); scrollarea->setWidget(frame); scrolllayout = new QGridLayout; scrolllayout->addWidget(scrollarea, 0, 0); optionsdialog->setLayout(scrolllayout); } else { optionsdialog->setLayout(mainLayout); } QObject::connect(CloseButton, SIGNAL(clicked()), optionsdialog, SLOT(close())); optionsdialog->exec(); } void UI_OptionsDialog::spinBox4_3ValueChanged(int filesize) { mainwindow->maxfilesize_to_readin_annotations = (long long)filesize * 1048576LL; } void UI_OptionsDialog::spinBox4_2ValueChanged(int stepsize) { mainwindow->mousewheelsens = stepsize; } void UI_OptionsDialog::combobox4_1IndexChanged(int index) { if(index == 0) { mainwindow->powerlinefreq = 50; } if(index == 1) { mainwindow->powerlinefreq = 60; } } void UI_OptionsDialog::combobox4_2IndexChanged(int index) { mainwindow->viewtime_indicator_type = index; mainwindow->setup_viewbuf(); } void UI_OptionsDialog::combobox4_3IndexChanged(int index) { mainwindow->mainwindow_title_type = index; mainwindow->setMainwindowTitle(mainwindow->edfheaderlist[mainwindow->sel_viewtime]); } void UI_OptionsDialog::spinBox4_1ValueChanged(int interval) { mainwindow->live_stream_update_interval = interval; } void UI_OptionsDialog::calibrate_checkbox_stateChanged(int state) { if(state == Qt::Checked) { spinbox2_1->setEnabled(true); spinbox2_2->setEnabled(true); ApplyButton->setEnabled(true); mainwindow->auto_dpi = 0; } else { spinbox2_1->setEnabled(false); spinbox2_2->setEnabled(false); ApplyButton->setEnabled(false); mainwindow->auto_dpi = 1; mainwindow->pixelsizefactor = 1.0 / ((double)mainwindow->dpiy / 2.54); mainwindow->x_pixelsizefactor = 1.0 / ((double)mainwindow->dpix / 2.54); mainwindow->maincurve->drawCurve_stage_1(); } } void UI_OptionsDialog::ApplyButtonClicked() { int i, j; mainwindow->pixelsizefactor = 1.0 / (4450.0 / spinbox2_1->value()); mainwindow->x_pixelsizefactor = 1.0 / (3550.0 / spinbox2_2->value()); for(i=0; isignalcomps; i++) { for(j=0; jsignalcomp[i]->num_of_signals; j++) { mainwindow->signalcomp[i]->sensitivity[j] = mainwindow->signalcomp[i]->edfhdr->edfparam[mainwindow->signalcomp[i]->edfsignal[j]].bitvalue / ((double)mainwindow->signalcomp[i]->voltpercm * mainwindow->pixelsizefactor); } } mainwindow->maincurve->drawCurve_stage_1(); } void UI_OptionsDialog::labelEdited(const QString &) { ApplyButton2->setEnabled(true); } void UI_OptionsDialog::spinBox3_1ValueChanged(int) { ApplyButton2->setEnabled(true); } void UI_OptionsDialog::dspinBox3_2ValueChanged(double) { ApplyButton2->setEnabled(true); } void UI_OptionsDialog::radioButtonToggled(bool) { ApplyButton2->setEnabled(true); } void UI_OptionsDialog::spinBoxValueChanged(double) { ApplyButton2->setEnabled(true); } void UI_OptionsDialog::ApplyButton2Clicked() { int i, row; char str[256]; for(row = 1; row < MAXSPECTRUMMARKERS; row++) { if(((QCheckBox *)(colorBarTable->cellWidget(row, 0)))->checkState() == Qt::Checked) { if(((QDoubleSpinBox *)(colorBarTable->cellWidget(row - 1, 1)))->value() >= ((QDoubleSpinBox *)(colorBarTable->cellWidget(row, 1)))->value()) { sprintf(str, "Row %i must have a higher frequency than row %i", row + 1, row); QMessageBox messagewindow(QMessageBox::Critical, "Error", str); messagewindow.exec(); return; } } else { break; } } for(row = 0; row < MAXSPECTRUMMARKERS; row++) { if(((QCheckBox *)(colorBarTable->cellWidget(row, 0)))->checkState() == Qt::Checked) { mainwindow->spectrum_colorbar->freq[row] = ((QDoubleSpinBox *)(colorBarTable->cellWidget(row, 1)))->value(); mainwindow->spectrum_colorbar->color[row] = ((SpecialButton *)(colorBarTable->cellWidget(row, 2)))->globalColor(); strncpy(mainwindow->spectrum_colorbar->label[row], ((QLineEdit *)(colorBarTable->cellWidget(row, 3)))->text().toLatin1().data(), 16); mainwindow->spectrum_colorbar->label[row][16] = 0; } else { break; } } mainwindow->spectrum_colorbar->items = row; for(; row < MAXSPECTRUMMARKERS; row++) { mainwindow->spectrum_colorbar->freq[row] = ((QDoubleSpinBox *)(colorBarTable->cellWidget(row, 1)))->value(); mainwindow->spectrum_colorbar->color[row] = ((SpecialButton *)(colorBarTable->cellWidget(row, 2)))->globalColor(); } if(radiobutton1->isChecked()) // sum { mainwindow->spectrum_colorbar->method = 0; } else if(radiobutton2->isChecked()) // peak { mainwindow->spectrum_colorbar->method = 1; } else if(radiobutton3->isChecked()) // average { mainwindow->spectrum_colorbar->method = 2; } mainwindow->maxdftblocksize = spinbox3_1->value(); if(mainwindow->maxdftblocksize & 1) { mainwindow->maxdftblocksize--; } mainwindow->spectrum_colorbar->max_colorbar_value = dspinbox3_2->value(); if(checkbox3_1->checkState() == Qt::Checked) { mainwindow->spectrum_colorbar->auto_adjust = 1; } else { mainwindow->spectrum_colorbar->auto_adjust = 0; } ApplyButton2->setEnabled(false); for(i=0; ispectrumdock[i]->dock->isVisible()) { mainwindow->spectrumdock[i]->rescan(); } } } void UI_OptionsDialog::checkBoxChanged(int state) { int i, row, lastrow=0; if(state == Qt::Checked) { for(row = MAXSPECTRUMMARKERS - 1; row >= 0; row--) { if(((QCheckBox *)(colorBarTable->cellWidget(row, 0)))->checkState() == Qt::Checked) { lastrow = row; if(row) { for(i=row-1; i>=0; i--) { ((QCheckBox *)(colorBarTable->cellWidget(i, 0)))->setCheckState(Qt::Checked); } } break; } } } else { for(row = 0; row < MAXSPECTRUMMARKERS; row++) { if(((QCheckBox *)(colorBarTable->cellWidget(row, 0)))->checkState() == Qt::Unchecked) { lastrow = row - 1; for(; row < MAXSPECTRUMMARKERS; row++) { ((QCheckBox *)(colorBarTable->cellWidget(row, 0)))->setCheckState(Qt::Unchecked); } break; } } } for(row=0; row < lastrow; row++) { if(((QDoubleSpinBox *)(colorBarTable->cellWidget(row, 1)))->value() >= ((QDoubleSpinBox *)(colorBarTable->cellWidget(row + 1, 1)))->value()) { ((QDoubleSpinBox *)(colorBarTable->cellWidget(row + 1, 1)))->setValue(((QDoubleSpinBox *)(colorBarTable->cellWidget(row, 1)))->value() + 1.0); } } ApplyButton2->setEnabled(true); } void UI_OptionsDialog::DefaultButton2Clicked() { int i; for(i=0; i<5; i++) { ((QCheckBox *)(colorBarTable->cellWidget(i, 0)))->setCheckState(Qt::Checked); ((QLineEdit *)(colorBarTable->cellWidget(i, 3)))->clear(); } ((QDoubleSpinBox *)(colorBarTable->cellWidget(0, 1)))->setValue(4.0); ((SpecialButton *)(colorBarTable->cellWidget(0, 2)))->setGlobalColor(Qt::darkRed); ((QDoubleSpinBox *)(colorBarTable->cellWidget(1, 1)))->setValue(8.0); ((SpecialButton *)(colorBarTable->cellWidget(1, 2)))->setGlobalColor(Qt::darkGreen); ((QDoubleSpinBox *)(colorBarTable->cellWidget(2, 1)))->setValue(12.0); ((SpecialButton *)(colorBarTable->cellWidget(2, 2)))->setGlobalColor(Qt::darkBlue); ((QDoubleSpinBox *)(colorBarTable->cellWidget(3, 1)))->setValue(30.0); ((SpecialButton *)(colorBarTable->cellWidget(3, 2)))->setGlobalColor(Qt::darkCyan); ((QDoubleSpinBox *)(colorBarTable->cellWidget(4, 1)))->setValue(100.0); ((SpecialButton *)(colorBarTable->cellWidget(4, 2)))->setGlobalColor(Qt::darkMagenta); for(i=5; icellWidget(i, 0)))->setCheckState(Qt::Unchecked); ((QDoubleSpinBox *)(colorBarTable->cellWidget(i, 1)))->setValue(1.0); ((SpecialButton *)(colorBarTable->cellWidget(i, 2)))->setGlobalColor(Qt::white); ((QLineEdit *)(colorBarTable->cellWidget(i, 3)))->clear(); } spinbox3_1->setValue(1000); radiobutton2->setChecked(true); ApplyButton2->setEnabled(true); } void UI_OptionsDialog::colorBarButtonClicked(SpecialButton *button) { int color; UI_ColorMenuDialog colormenudialog(&color); if(color < 0) return; button->setGlobalColor(color); ApplyButton2->setEnabled(true); } void UI_OptionsDialog::checkbox1Clicked(int state) { if(state==Qt::Checked) { mainwindow->maincurve->blackwhite_printing = 1; } if(state==Qt::Unchecked) { mainwindow->maincurve->blackwhite_printing = 0; } } void UI_OptionsDialog::checkbox2Clicked(int state) { if(state==Qt::Checked) { mainwindow->show_annot_markers = 1; } if(state==Qt::Unchecked) { mainwindow->show_annot_markers = 0; } mainwindow->maincurve->update(); } void UI_OptionsDialog::checkbox3Clicked(int state) { if(state==Qt::Checked) { mainwindow->show_baselines = 1; } if(state==Qt::Unchecked) { mainwindow->show_baselines = 0; } mainwindow->maincurve->update(); } void UI_OptionsDialog::checkbox4Clicked(int state) { if(state==Qt::Checked) { mainwindow->clip_to_pane = 1; } if(state==Qt::Unchecked) { mainwindow->clip_to_pane = 0; } mainwindow->maincurve->update(); } void UI_OptionsDialog::checkbox3_1Clicked(int state) { if(state==Qt::Checked) { dspinbox3_2->setEnabled(false); mainwindow->spectrum_colorbar->auto_adjust = 1; } if(state==Qt::Unchecked) { dspinbox3_2->setEnabled(true); mainwindow->spectrum_colorbar->auto_adjust = 0; } ApplyButton2->setEnabled(true); } void UI_OptionsDialog::checkbox4_1Clicked(int state) { if(state==Qt::Checked) { mainwindow->auto_reload_mtg = 1; } if(state==Qt::Unchecked) { mainwindow->auto_reload_mtg = 0; } } void UI_OptionsDialog::checkbox4_2Clicked(int state) { if(state==Qt::Checked) { mainwindow->read_biosemi_status_signal = 1; } if(state==Qt::Unchecked) { mainwindow->read_biosemi_status_signal = 0; } } void UI_OptionsDialog::checkbox4_3Clicked(int state) { if(state==Qt::Checked) { mainwindow->read_nk_trigger_signal = 1; } if(state==Qt::Unchecked) { mainwindow->read_nk_trigger_signal = 0; } } void UI_OptionsDialog::checkbox4_4Clicked(int state) { if(state==Qt::Checked) { mainwindow->use_threads = 1; } if(state==Qt::Unchecked) { mainwindow->use_threads = 0; } } void UI_OptionsDialog::checkbox4_5Clicked(int state) { if(state==Qt::Checked) { mainwindow->check_for_updates = 1; } if(state==Qt::Unchecked) { mainwindow->check_for_updates = 0; } } void UI_OptionsDialog::checkbox4_6Clicked(int state) { if(state==Qt::Checked) { mainwindow->linear_interpol = 1; } if(state==Qt::Unchecked) { mainwindow->linear_interpol = 0; } mainwindow->setup_viewbuf(); } 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); palette.setColor(QPalette::Text, mainwindow->maincurve->text_color); palette.setColor(QPalette::Base, mainwindow->maincurve->backgroundcolor); for(i=0; ifiles_open; i++) { if(mainwindow->annotations_dock[i]) { mainwindow->annotations_dock[i]->list->setPalette(palette); } } for(i=0; isignalcomps; 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; QColor temp; QPalette palette; temp = QColorDialog::getColor(mainwindow->maincurve->backgroundcolor, tab1); if(temp.isValid()) { mainwindow->maincurve->backgroundcolor = temp; BgColorButton->setColor(mainwindow->maincurve->backgroundcolor); palette.setColor(QPalette::Text, mainwindow->maincurve->text_color); palette.setColor(QPalette::Base, mainwindow->maincurve->backgroundcolor); for(i=0; ifiles_open; i++) { if(mainwindow->annotations_dock[i]) { mainwindow->annotations_dock[i]->list->setPalette(palette); } } mainwindow->maincurve->update(); } } void UI_OptionsDialog::SrColorButtonClicked(SpecialButton *) { QColor temp; temp = QColorDialog::getColor(mainwindow->maincurve->small_ruler_color, tab1); if(temp.isValid()) { mainwindow->maincurve->small_ruler_color = temp; SrColorButton->setColor(mainwindow->maincurve->small_ruler_color); mainwindow->maincurve->update(); } } void UI_OptionsDialog::BrColorButtonClicked(SpecialButton *) { QColor temp; temp = QColorDialog::getColor(mainwindow->maincurve->big_ruler_color, tab1); if(temp.isValid()) { mainwindow->maincurve->big_ruler_color = temp; BrColorButton->setColor(mainwindow->maincurve->big_ruler_color); mainwindow->maincurve->update(); } } void UI_OptionsDialog::MrColorButtonClicked(SpecialButton *) { QColor temp; temp = QColorDialog::getColor(mainwindow->maincurve->mouse_rect_color, tab1); if(temp.isValid()) { mainwindow->maincurve->mouse_rect_color = temp; MrColorButton->setColor(mainwindow->maincurve->mouse_rect_color); mainwindow->maincurve->update(); } } void UI_OptionsDialog::TxtColorButtonClicked(SpecialButton *) { int i; QColor temp; QPalette palette; temp = QColorDialog::getColor(mainwindow->maincurve->text_color, tab1); if(temp.isValid()) { mainwindow->maincurve->text_color = temp; TxtColorButton->setColor(mainwindow->maincurve->text_color); palette.setColor(QPalette::Text, mainwindow->maincurve->text_color); palette.setColor(QPalette::Base, mainwindow->maincurve->backgroundcolor); for(i=0; ifiles_open; i++) { if(mainwindow->annotationlist[i]) { mainwindow->annotations_dock[i]->list->setPalette(palette); } } mainwindow->maincurve->update(); } } void UI_OptionsDialog::SigColorButtonClicked(SpecialButton *) { int i, color; UI_ColorMenuDialog colormenudialog(&color); if(color < 0) return; SigColorButton->setColor((Qt::GlobalColor)color); mainwindow->maincurve->signal_color = color; for(i=0; isignalcomps; i++) { mainwindow->signalcomp[i]->color = color; } mainwindow->maincurve->update(); } void UI_OptionsDialog::BaseColorButtonClicked(SpecialButton *) { QColor temp; temp = QColorDialog::getColor(mainwindow->maincurve->baseline_color, tab1); if(temp.isValid()) { mainwindow->maincurve->baseline_color = temp; BaseColorButton->setColor(mainwindow->maincurve->baseline_color); mainwindow->maincurve->update(); } } void UI_OptionsDialog::Crh1ColorButtonClicked(SpecialButton *) { int color; UI_ColorMenuDialog colormenudialog(&color); if(color < 0) return; Crh1ColorButton->setColor((Qt::GlobalColor)color); mainwindow->maincurve->crosshair_1.color = color; mainwindow->maincurve->update(); } void UI_OptionsDialog::Crh2ColorButtonClicked(SpecialButton *) { int color; UI_ColorMenuDialog colormenudialog(&color); if(color < 0) return; Crh2ColorButton->setColor((Qt::GlobalColor)color); mainwindow->maincurve->crosshair_2.color = color; mainwindow->maincurve->update(); } void UI_OptionsDialog::FrColorButtonClicked(SpecialButton *) { int color; UI_ColorMenuDialog colormenudialog(&color); if(color < 0) return; FrColorButton->setColor((Qt::GlobalColor)color); mainwindow->maincurve->floating_ruler_color = color; mainwindow->maincurve->update(); } void UI_OptionsDialog::AnnotMkrButtonClicked(SpecialButton *) { QColor temp; temp = QColorDialog::getColor(mainwindow->maincurve->annot_marker_color, tab1); if(temp.isValid()) { mainwindow->maincurve->annot_marker_color = temp; AnnotMkrButton->setColor(mainwindow->maincurve->annot_marker_color); mainwindow->maincurve->update(); } } void UI_OptionsDialog::dspinbox4_4ValueChanged(double val) { mainwindow->default_amplitude = val; } void UI_OptionsDialog::saveColorSchemaButtonClicked() { char path[MAX_PATH_LENGTH]; FILE *colorfile; strcpy(path, mainwindow->recent_colordir); strcat(path, "/my_colorschema.color"); strcpy(path, QFileDialog::getSaveFileName(0, "Save colorschema", QString::fromLocal8Bit(path), "Colorschema files (*.color *.COLOR)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } if(strlen(path) > 4) { if(strcmp(path + strlen(path) - 6, ".color")) { strcat(path, ".color"); } } get_directory_from_path(mainwindow->recent_colordir, path, MAX_PATH_LENGTH); colorfile = fopen(path, "wb"); if(colorfile==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Can not open file for writing."); messagewindow.exec(); return; } fprintf(colorfile, "\n<" PROGRAM_NAME "_colorschema>\n"); fprintf(colorfile, " \n" " %i\n" " %i\n" " %i\n" " \n", mainwindow->maincurve->backgroundcolor.red(), mainwindow->maincurve->backgroundcolor.green(), mainwindow->maincurve->backgroundcolor.blue()); fprintf(colorfile, " \n" " %i\n" " %i\n" " %i\n" " \n", mainwindow->maincurve->small_ruler_color.red(), mainwindow->maincurve->small_ruler_color.green(), mainwindow->maincurve->small_ruler_color.blue()); fprintf(colorfile, " \n" " %i\n" " %i\n" " %i\n" " \n", mainwindow->maincurve->big_ruler_color.red(), mainwindow->maincurve->big_ruler_color.green(), mainwindow->maincurve->big_ruler_color.blue()); fprintf(colorfile, " \n" " %i\n" " %i\n" " %i\n" " \n", mainwindow->maincurve->mouse_rect_color.red(), mainwindow->maincurve->mouse_rect_color.green(), mainwindow->maincurve->mouse_rect_color.blue()); fprintf(colorfile, " \n" " %i\n" " %i\n" " %i\n" " \n", mainwindow->maincurve->text_color.red(), mainwindow->maincurve->text_color.green(), mainwindow->maincurve->text_color.blue()); fprintf(colorfile, " \n" " %i\n" " %i\n" " %i\n" " \n", mainwindow->maincurve->baseline_color.red(), mainwindow->maincurve->baseline_color.green(), mainwindow->maincurve->baseline_color.blue()); fprintf(colorfile, " \n" " %i\n" " %i\n" " %i\n" " \n", mainwindow->maincurve->annot_marker_color.red(), mainwindow->maincurve->annot_marker_color.green(), mainwindow->maincurve->annot_marker_color.blue()); fprintf(colorfile, " %i\n", mainwindow->maincurve->signal_color); fprintf(colorfile, " %i\n", mainwindow->maincurve->crosshair_1.color); fprintf(colorfile, " %i\n", mainwindow->maincurve->crosshair_2.color); fprintf(colorfile, " %i\n", mainwindow->maincurve->floating_ruler_color); fprintf(colorfile, " %i\n", mainwindow->maincurve->blackwhite_printing); fprintf(colorfile, " %i\n", mainwindow->show_annot_markers); fprintf(colorfile, " %i\n", mainwindow->show_baselines); fprintf(colorfile, " %i\n", mainwindow->clip_to_pane); fprintf(colorfile, "\n"); fclose(colorfile); } void UI_OptionsDialog::loadColorSchemaButtonClicked() { char path[MAX_PATH_LENGTH], scratchpad[2048], result[XML_STRBUFLEN]; struct xml_handle *xml_hdl; strcpy(path, QFileDialog::getOpenFileName(0, "Load colorschema", QString::fromLocal8Bit(mainwindow->recent_colordir), "Montage files (*.color *.COLOR)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(mainwindow->recent_colordir, path, MAX_PATH_LENGTH); xml_hdl = xml_get_handle(path); if(xml_hdl==NULL) { sprintf(scratchpad, "Can not open colorschema:\n%s", path); QMessageBox messagewindow(QMessageBox::Critical, "Error", QString::fromLocal8Bit(scratchpad)); messagewindow.exec(); return; } if(strcmp(xml_hdl->elementname[xml_hdl->level], PROGRAM_NAME "_colorschema")) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "There seems to be an error in this colorschema."); messagewindow.exec(); xml_close(xml_hdl); return; } mainwindow->get_rgbcolor_settings(xml_hdl, "backgroundcolor", 0, &mainwindow->maincurve->backgroundcolor); mainwindow->get_rgbcolor_settings(xml_hdl, "small_ruler_color", 0, &mainwindow->maincurve->small_ruler_color); mainwindow->get_rgbcolor_settings(xml_hdl, "big_ruler_color", 0, &mainwindow->maincurve->big_ruler_color); mainwindow->get_rgbcolor_settings(xml_hdl, "mouse_rect_color", 0, &mainwindow->maincurve->mouse_rect_color); mainwindow->get_rgbcolor_settings(xml_hdl, "text_color", 0, &mainwindow->maincurve->text_color); mainwindow->get_rgbcolor_settings(xml_hdl, "baseline_color", 0, &mainwindow->maincurve->baseline_color); mainwindow->get_rgbcolor_settings(xml_hdl, "annot_marker_color", 0, &mainwindow->maincurve->annot_marker_color); if(xml_goto_nth_element_inside(xml_hdl, "signal_color", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } mainwindow->maincurve->signal_color = atoi(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "floating_ruler_color", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } mainwindow->maincurve->floating_ruler_color = atoi(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "blackwhite_printing", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } mainwindow->maincurve->blackwhite_printing = atoi(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "show_annot_markers", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } mainwindow->show_annot_markers = atoi(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "show_baselines", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } mainwindow->show_baselines = atoi(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "clip_to_pane", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } mainwindow->clip_to_pane = atoi(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "crosshair_1_color", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } mainwindow->maincurve->crosshair_1.color = atoi(result); xml_go_up(xml_hdl); if(xml_goto_nth_element_inside(xml_hdl, "crosshair_2_color", 0)) { xml_close(xml_hdl); return; } if(xml_get_content_of_element(xml_hdl, result, XML_STRBUFLEN)) { xml_close(xml_hdl); return; } mainwindow->maincurve->crosshair_2.color = atoi(result); xml_close(xml_hdl); update_interface(); } void UI_OptionsDialog::update_interface(void) { int i; QPalette palette; BgColorButton->setColor(mainwindow->maincurve->backgroundcolor); SrColorButton->setColor(mainwindow->maincurve->small_ruler_color); BrColorButton->setColor(mainwindow->maincurve->big_ruler_color); MrColorButton->setColor(mainwindow->maincurve->mouse_rect_color); TxtColorButton->setColor(mainwindow->maincurve->text_color); SigColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->signal_color); if(mainwindow->show_baselines) { checkbox3->setCheckState(Qt::Checked); } else { checkbox3->setCheckState(Qt::Unchecked); } BaseColorButton->setColor(mainwindow->maincurve->baseline_color); Crh1ColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->crosshair_1.color); Crh2ColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->crosshair_2.color); FrColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->floating_ruler_color); if(mainwindow->show_annot_markers) { checkbox2->setCheckState(Qt::Checked); } else { checkbox2->setCheckState(Qt::Unchecked); } AnnotMkrButton->setColor(mainwindow->maincurve->annot_marker_color); if(mainwindow->maincurve->blackwhite_printing) { checkbox1->setCheckState(Qt::Checked); } else { checkbox1->setCheckState(Qt::Unchecked); } if(mainwindow->clip_to_pane) { checkbox4->setCheckState(Qt::Checked); } else { checkbox4->setCheckState(Qt::Unchecked); } palette.setColor(QPalette::Text, mainwindow->maincurve->text_color); palette.setColor(QPalette::Base, mainwindow->maincurve->backgroundcolor); for(i=0; ifiles_open; i++) { if(mainwindow->annotations_dock[i]) { mainwindow->annotations_dock[i]->list->setPalette(palette); } } for(i=0; isignalcomps; i++) { mainwindow->signalcomp[i]->color = mainwindow->maincurve->signal_color; } mainwindow->maincurve->update(); } void UI_OptionsDialog::loadColorSchema_NK() { mainwindow->maincurve->backgroundcolor.setRed(255); mainwindow->maincurve->backgroundcolor.setGreen(255); mainwindow->maincurve->backgroundcolor.setBlue(255); mainwindow->maincurve->small_ruler_color.setRed(0); mainwindow->maincurve->small_ruler_color.setGreen(0); mainwindow->maincurve->small_ruler_color.setBlue(0); mainwindow->maincurve->big_ruler_color.setRed(255); mainwindow->maincurve->big_ruler_color.setGreen(255); mainwindow->maincurve->big_ruler_color.setBlue(0); mainwindow->maincurve->mouse_rect_color.setRed(0); mainwindow->maincurve->mouse_rect_color.setGreen(0); mainwindow->maincurve->mouse_rect_color.setBlue(0); mainwindow->maincurve->text_color.setRed(0); mainwindow->maincurve->text_color.setGreen(0); mainwindow->maincurve->text_color.setBlue(0); mainwindow->maincurve->baseline_color.setRed(128); mainwindow->maincurve->baseline_color.setGreen(128); mainwindow->maincurve->baseline_color.setBlue(128); mainwindow->maincurve->annot_marker_color.setRed(0); mainwindow->maincurve->annot_marker_color.setGreen(0); mainwindow->maincurve->annot_marker_color.setBlue(0); mainwindow->maincurve->signal_color = 2; mainwindow->maincurve->floating_ruler_color = 7; mainwindow->maincurve->blackwhite_printing = 1; mainwindow->show_annot_markers = 1; mainwindow->show_baselines = 1; mainwindow->maincurve->crosshair_1.color = 7; mainwindow->maincurve->crosshair_2.color = 9; mainwindow->clip_to_pane = 0; update_interface(); } void UI_OptionsDialog::loadColorSchema_Dark() { mainwindow->maincurve->backgroundcolor.setRed(64); mainwindow->maincurve->backgroundcolor.setGreen(64); mainwindow->maincurve->backgroundcolor.setBlue(64); mainwindow->maincurve->small_ruler_color.setRed(255); mainwindow->maincurve->small_ruler_color.setGreen(255); mainwindow->maincurve->small_ruler_color.setBlue(255); mainwindow->maincurve->big_ruler_color.setRed(128); mainwindow->maincurve->big_ruler_color.setGreen(128); mainwindow->maincurve->big_ruler_color.setBlue(128); mainwindow->maincurve->mouse_rect_color.setRed(255); mainwindow->maincurve->mouse_rect_color.setGreen(255); mainwindow->maincurve->mouse_rect_color.setBlue(255); mainwindow->maincurve->text_color.setRed(255); mainwindow->maincurve->text_color.setGreen(255); mainwindow->maincurve->text_color.setBlue(255); mainwindow->maincurve->baseline_color.setRed(128); mainwindow->maincurve->baseline_color.setGreen(128); mainwindow->maincurve->baseline_color.setBlue(128); mainwindow->maincurve->annot_marker_color.setRed(255); mainwindow->maincurve->annot_marker_color.setGreen(255); mainwindow->maincurve->annot_marker_color.setBlue(255); mainwindow->maincurve->signal_color = 12; mainwindow->maincurve->floating_ruler_color = 10; mainwindow->maincurve->blackwhite_printing = 1; mainwindow->show_annot_markers = 1; mainwindow->show_baselines = 1; mainwindow->maincurve->crosshair_1.color = 7; mainwindow->maincurve->crosshair_2.color = 10; mainwindow->clip_to_pane = 0; update_interface(); } edfbrowser_157_source/PaxHeaders.7921/edit_annotation_dock.h0000644000000000000000000000013212646460742021216 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/edit_annotation_dock.h0000644000175000001440000000502712646460742021563 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef ANNOTATION_EDIT_FORM1_H #define ANNOTATION_EDIT_FORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "annotations_dock.h" #include "popup_save_cancelwindow.h" #include "edf_annot_list.h" class UI_Mainwindow; class UI_AnnotationEditwindow : public QObject { Q_OBJECT public: UI_AnnotationEditwindow(int, QWidget *parent); UI_Mainwindow *mainwindow; QDockWidget *dockedit; void annotEditSetOnset(long long); void annotEditSetDuration(long long); void set_selected_annotation(int, int); void set_selected_annotation(struct annotationblock *); private: struct annotationblock *annotation; int file_num, annot_num; QDialog *annot_edit_dialog; QLabel *onsetLabel, *durationLabel, *descriptionLabel; QLineEdit *annot_descript_lineEdit; QTimeEdit *onset_timeEdit; QSpinBox *onset_daySpinbox; QDoubleSpinBox *duration_spinbox; QPushButton *modifybutton, *deletebutton, *createbutton; QComboBox *posNegTimebox; private slots: void modifyButtonClicked(); void deleteButtonClicked(); void createButtonClicked(); void open_close_dock(bool); }; #endif edfbrowser_157_source/PaxHeaders.7921/scp_ecg2edf.cpp0000644000000000000000000000012712646460742017542 xustar0029 mtime=1452958178.24824673 29 atime=1452958178.24824673 29 ctime=1452958178.24824673 edfbrowser_157_source/scp_ecg2edf.cpp0000644000175000001440000010661412646460742020107 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "scp_ecg2edf.h" #define SPCECGBUFSIZE 1048576 UI_SCPECG2EDFwindow::UI_SCPECG2EDFwindow(char *recent_dir, char *save_dir) { char txt_string[2048]; recent_opendir = recent_dir; recent_savedir = save_dir; myobjectDialog = new QDialog; myobjectDialog->setMinimumSize(600, 480); myobjectDialog->setMaximumSize(600, 480); myobjectDialog->setWindowTitle("SCP ECG to EDF+ converter"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); 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"); textEdit1 = new QTextEdit(myobjectDialog); textEdit1->setGeometry(20, 20, 560, 380); textEdit1->setFrameStyle(QFrame::Panel | QFrame::Sunken); textEdit1->setReadOnly(true); textEdit1->setLineWrapMode(QTextEdit::NoWrap); sprintf(txt_string, "SCP ECG to EDF+ converter.\n"); textEdit1->append(txt_string); crc_ccitt_init(); QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton())); QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close())); myobjectDialog->exec(); } void UI_SCPECG2EDFwindow::SelectFileButton() { FILE *inputfile=NULL; int i, j, k, n, hdl, chns, sf, avm, blocks, *buf, encoding, compression, offset, abs_val_a[256], abs_val_b[256], var_tmp; unsigned short sh_tmp; long long filesize, ll_tmp, bits; char input_filename[MAX_PATH_LENGTH], txt_string[2048], edf_filename[MAX_PATH_LENGTH], scratchpad[MAX_PATH_LENGTH], *block, ch_tmp; union{ unsigned long long ll_int; unsigned int one[2]; unsigned short two[4]; unsigned char four[8]; } var; pushButton1->setEnabled(false); for(i=0; i<256; i++) { abs_val_a[i] = 0; abs_val_b[i] = 0; } strcpy(input_filename, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "SCP files (*.scp *.SCP)").toLocal8Bit().data()); if(!strcmp(input_filename, "")) { pushButton1->setEnabled(true); return; } get_directory_from_path(recent_opendir, input_filename, MAX_PATH_LENGTH); inputfile = fopeno(input_filename, "rb"); if(inputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for reading.\n", input_filename); textEdit1->append(QString::fromLocal8Bit(txt_string)); pushButton1->setEnabled(true); return; } get_filename_from_path(scratchpad, input_filename, MAX_PATH_LENGTH); snprintf(txt_string, 2048, "Read file: %s", scratchpad); textEdit1->append(QString::fromLocal8Bit(txt_string)); fseeko(inputfile, 0LL, SEEK_END); filesize = ftello(inputfile); if(filesize<126) { textEdit1->append("Error, filesize is too small.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } ll_tmp = 0LL; fseeko(inputfile, 2LL, SEEK_SET); if(fread(&ll_tmp, 4, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (1)\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } if(ll_tmp != filesize) { textEdit1->append("Error, filesize does not match with header.\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } block = (char *)malloc(SPCECGBUFSIZE); if(block == NULL) { textEdit1->append("Malloc error (block 1)\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } rewind(inputfile); if(fread(&sh_tmp, 2, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (2)\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } if(check_crc(inputfile, 2LL, filesize - 2LL, sh_tmp, block)) { fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } memset(&sp, 0, sizeof(struct section_prop_struct[12])); if(read_section_header(0, inputfile, 6LL, block)) { fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } if(strncmp(sp[0].reserved, "SCPECG", 6)) { textEdit1->append("Error, reserved field of section header 0 does not contain string \"SCPECG\".\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } sp[0].file_offset = 6LL; // printf("\nsection ID is %i\n" // "section file offset is %lli\n" // "section CRC is 0x%04X\n" // "section length is %i\n" // "section version is %i\n" // "section protocol version is %i\n", // sp[0].section_id, // sp[0].file_offset, // (int)sp[0].crc, // sp[0].section_length, // sp[0].section_version, // sp[0].section_protocol_version); if(read_data_section_zero(inputfile, block, filesize)) { fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } fseeko(inputfile, sp[6].file_offset + 16LL, SEEK_SET); if(fread(block, 6, 1, inputfile) != 1) { textEdit1->append("A read-error occurred\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } avm = *((unsigned short *)block); sf = 1000000 / *((unsigned short *)(block + 2)); encoding = *((unsigned char *)(block + 4)); compression = *((unsigned char *)(block + 5)); if(compression != 0) { textEdit1->append("File contains bimodal compressed data which is not supported by this converter.\n "); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } fseeko(inputfile, sp[3].file_offset + 16LL, SEEK_SET); if(fread(scratchpad, 2, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (40)\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } chns = *((unsigned char *)scratchpad); if(chns < 1) { textEdit1->append("Error, number of signals is less than one.\n "); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } if(chns > 256) { textEdit1->append("Error, number of signals is more than 256.\n "); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } if(scratchpad[1] & 1) { textEdit1->append("Reference beat subtraction used for compression which is not supported by this converter.\n "); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } if(!(scratchpad[1] & 4)) { textEdit1->append("Leads are not simultaneously recorded which is not supported by this converter. (1)\n "); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } // printf("chns is %u AVM is %u sf is %u encoding is %u compression is %u\n", // chns, avm, sf, encoding, compression); memset(&lp, 0, sizeof(struct lead_prop_struct[256])); fseeko(inputfile, sp[3].file_offset + 18LL, SEEK_SET); for(i=0; iappend("A read-error occurred (30)\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } if(fread(&(lp[i].end), 4, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (31)\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } if(fread(&(lp[i].label), 1, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (32)\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } } // for(i=0; i 1) { for(i=1; iappend("Error, leads are not simultaneously recorded. (2)\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } if(lp[i].end != lp[0].end) { textEdit1->append("Error, leads are not simultaneously recorded. (3)\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } } } for(i=0; iappend("Error, start sample number in section 3 is less than 1.\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } if(lp[i].end <= lp[i].start) { textEdit1->append("Error (56) (lp[i].end <= lp[i].start)\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } if(lp[i].start != 1) { textEdit1->append("Error (57) (lp[i].start != 1)\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } lp[i].start--; if((lp[i].end - lp[i].start) < sf) { textEdit1->append("Error, recording length is less than one second.\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } lp[i].samples = lp[i].end - lp[i].start; } fseeko(inputfile, sp[6].file_offset + 22LL, SEEK_SET); n = 0; for(i=0; iappend("A read-error occurred (41)\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } lp[i].bytes = *((unsigned short *)block); n += lp[i].bytes; // printf("lead samples is %i bytes is %i\n", lp[i].samples, lp[i].bytes); if(sp[2].present != 1) // huffmantable { if(lp[i].bytes < (lp[i].samples * 2)) { textEdit1->append("Error, lead samples is less than lead bytes.\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } } } if(n > (sp[6].section_length - 22 - (chns * 2))) { textEdit1->append("Error, total databytes is more than section size.\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } //////////////////////////////// Huffman tables //////////////////// if(sp[2].present == 1) // huffmantable { fseeko(inputfile, sp[2].file_offset + 16LL, SEEK_SET); if(fread(block, 13, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (50)\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } ht.h_tables_cnt = *((unsigned short *)block); ht.code_structs_cnt = *((unsigned short *)(block + 2)); ht.prefix_bits = *((unsigned char *)(block + 4)); ht.total_bits = *((unsigned char *)(block + 5)); ht.table_mode_switch = *((unsigned char *)(block + 6)); ht.base_value = *((unsigned short *)(block + 7)); ht.base_code = *((unsigned int *)(block + 9)); // printf("ht.h_tables_cnt is %i ht.code_structs_cnt is %i ht.prefix_bits is %i ht.total_bits is %i\n", // ht.h_tables_cnt, ht.code_structs_cnt, ht.prefix_bits, ht.total_bits); if(ht.h_tables_cnt != 19999) { textEdit1->append("Aborted, this converter does not support customized Huffmantables.\n"); fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } } //////////////////////////////// patient data //////////////////// memset(&pat_dat, 0, sizeof(struct patient_data_struct)); if(get_patient_data(inputfile)) { fclose(inputfile); free(block); pushButton1->setEnabled(true); return; } // printf("patient ID: %s\n" // "patient lastname: %s\n" // "patient firstname: %s\n" // "patient sex: %i\n" // "startdate year: %i\n" // "startdate month: %i\n" // "startdate day: %i\n" // "starttime hour: %i\n" // "starttime minute: %i\n" // "starttime second: %i\n" // "birthdate year: %i\n" // "birthdate month: %i\n" // "birthdate day: %i\n" // "device model: %s\n" // "language code: %u\n" // "manufacturer: %s\n", // pat_dat.pat_id, // pat_dat.last_name, // pat_dat.first_name, // pat_dat.sex, // pat_dat.startdate_year, // pat_dat.startdate_month, // pat_dat.startdate_day, // pat_dat.starttime_hour, // pat_dat.starttime_minute, // pat_dat.starttime_second, // pat_dat.birthdate_year, // pat_dat.birthdate_month, // pat_dat.birthdate_day, // pat_dat.device_model, // pat_dat.lang_code, // pat_dat.manufacturer); ////////////////////////// start conversion /////////////////////////////// free(block); buf = (int *)malloc(((lp[0].samples / sf) + 1) * chns * sf * sizeof(int)); if(buf == NULL) { textEdit1->append("Malloc error (buf)\n"); fclose(inputfile); pushButton1->setEnabled(true); return; } n = 0; for(i=0; iappend("Malloc error (block 3)\n"); fclose(inputfile); free(buf); pushButton1->setEnabled(true); return; } fseeko(inputfile, sp[6].file_offset + 22LL + (chns * 2LL), SEEK_SET); // rhythm data if(fread(block, n, 1, inputfile) != 1) { textEdit1->append("A read-error occurred during conversion (70)\n"); fclose(inputfile); free(buf); free(block); pushButton1->setEnabled(true); return; } offset = 0; for(j=0; j 0) { offset += lp[j - 1].bytes; } bits = 0LL; for(i=0; i lp[j].bytes) { textEdit1->append("Error, (bits / 8) >= lp[j].bytes (71)\n"); fclose(inputfile); free(buf); free(block); pushButton1->setEnabled(true); return; } memcpy(&var, block + offset + ((int)(bits / 8LL)), 5); for(k=0; k<5; k++) { var.four[k] = reverse_bitorder(var.four[k]); } var.ll_int >>= (int)(bits % 8LL); if((var.four[0] & 1) == 0) // b00000001 { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = 0; bits++; } else if((var.four[0] & 7) == 1) // b00000111 { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = 1; bits += 3LL; } else if((var.four[0] & 7) == 5) // b00000111 { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = -1; bits += 3LL; } else if((var.four[0] & 15) == 3) // b00001111 { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = 2; bits += 4LL; } else if((var.four[0] & 15) == 11) // b00001111 { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = -2; bits += 4LL; } else if((var.four[0] & 31) == 7) // b00011111 { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = 3; bits += 5LL; } else if((var.four[0] & 31) == 23) // b00011111 { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = -3; bits += 5LL; } else if((var.four[0] & 63) == 15) // b00111111 { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = 4; bits += 6LL; } else if((var.four[0] & 63) == 47) // b00111111 { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = -4; bits += 6LL; } else if((var.four[0] & 127) == 31) // b01111111 { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = 5; bits += 7LL; } else if((var.four[0] & 127) == 95) // b01111111 { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = -5; bits += 7LL; } else if(var.four[0] == 63) // b11111111 { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = 6; bits += 8LL; } else if(var.four[0] == 191) // b11111111 { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = -6; bits += 8LL; } else if(var.four[0] == 127) // b11111111 { if((var.four[1] & 1) == 0) // b00000001 { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = 7; bits += 9LL; } else { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = -7; bits += 9LL; } } else if(var.four[0] == 255) // b11111111 { if((var.four[1] & 3) == 0) // b00000011 { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = 8; bits += 10LL; } else if((var.four[1] & 3) == 2) // b00000011 { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = -8; bits += 10LL; } else if((var.four[1] & 3) == 1) // b00000011 { var.ll_int >>= 2; var.four[1] = reverse_bitorder(var.four[1]); buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = *((signed char *)&(var.four[1])); // 8-bit original bits += 18LL; } else if((var.four[1] & 3) == 3) // b00000011 { var.ll_int >>= 10; ch_tmp = reverse_bitorder(var.four[0]); var.four[0] = reverse_bitorder(var.four[1]); var.four[1] = ch_tmp; buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = *((signed short *)&(var.two[0])); // 16-bit original bits += 26LL; } } } else // huffmantable not present { buf[((i / sf) * (sf * chns)) + (j * sf) + (i % sf)] = ((signed short *)(block + offset))[i]; } } } strcpy(edf_filename, input_filename); remove_extension_from_filename(edf_filename); strcat(edf_filename, ".edf"); hdl = edfopen_file_writeonly(edf_filename, EDFLIB_FILETYPE_EDFPLUS, chns); if(hdl<0) { snprintf(txt_string, 2048, "Can not open file %s for writing.\n", edf_filename); textEdit1->append(txt_string); fclose(inputfile); free(buf); free(block); pushButton1->setEnabled(true); return; } for(i=0; iappend("Error: edf_set_samplefrequency()\n"); fclose(inputfile); edfclose_file(hdl); free(buf); free(block); pushButton1->setEnabled(true); return; } if(edf_set_digital_minimum(hdl, i, -32768)) { textEdit1->append("Error: edf_set_digital_minimum()\n"); fclose(inputfile); edfclose_file(hdl); free(buf); free(block); pushButton1->setEnabled(true); return; } if(edf_set_digital_maximum(hdl, i, 32767)) { textEdit1->append("Error: edf_set_digital_maximum()\n"); fclose(inputfile); edfclose_file(hdl); free(buf); free(block); pushButton1->setEnabled(true); return; } lead_label_lookup(lp[i].label, scratchpad); if(edf_set_label(hdl, i, scratchpad)) { textEdit1->append("Error: edf_set_label()\n"); fclose(inputfile); edfclose_file(hdl); free(buf); free(block); pushButton1->setEnabled(true); return; } if(edf_set_physical_dimension(hdl, i, "uV")) { textEdit1->append("Error: edf_set_physical_dimension()\n"); fclose(inputfile); edfclose_file(hdl); free(buf); free(block); pushButton1->setEnabled(true); return; } if(edf_set_physical_maximum(hdl, i, 32.767 * (double)avm)) { textEdit1->append("Error: edf_set_physical_maximum()\n"); fclose(inputfile); edfclose_file(hdl); free(buf); free(block); pushButton1->setEnabled(true); return; } if(edf_set_physical_minimum(hdl, i, -32.768 * (double)avm)) { textEdit1->append("Error: edf_set_physical_minimum()\n"); fclose(inputfile); edfclose_file(hdl); free(buf); free(block); pushButton1->setEnabled(true); return; } } strcpy(scratchpad, pat_dat.first_name); strcat(scratchpad, " "); strcat(scratchpad, pat_dat.last_name); remove_trailing_spaces(scratchpad); if(edf_set_patientname(hdl, scratchpad)) { textEdit1->append("Error: edf_set_patientname()\n"); fclose(inputfile); edfclose_file(hdl); free(buf); free(block); pushButton1->setEnabled(true); return; } edf_set_startdatetime(hdl, pat_dat.startdate_year, pat_dat.startdate_month, pat_dat.startdate_day, pat_dat.starttime_hour, pat_dat.starttime_minute, pat_dat.starttime_second); edf_set_birthdate(hdl, pat_dat.birthdate_year, pat_dat.birthdate_month, pat_dat.birthdate_day); if(pat_dat.sex == 1) { edf_set_gender(hdl, 1); } if(pat_dat.sex == 2) { edf_set_gender(hdl, 0); } edf_set_patientcode(hdl, pat_dat.pat_id); strcpy(scratchpad, pat_dat.device_model); strcat(scratchpad, " "); strcat(scratchpad, pat_dat.device_ident); edf_set_equipment(hdl, scratchpad); strcpy(scratchpad, pat_dat.manufacturer); strcat(scratchpad, " "); strcat(scratchpad, pat_dat.device_serial); edf_set_recording_additional(hdl, scratchpad); blocks = lp[0].samples / sf; for(i=0; iappend("A write error occurred during conversion (EDFlib).\n"); fclose(inputfile); edfclose_file(hdl); free(buf); free(block); pushButton1->setEnabled(true); return; } } edfclose_file(hdl); free(buf); free(block); fclose(inputfile); textEdit1->append("Done.\n"); pushButton1->setEnabled(true); } int UI_SCPECG2EDFwindow::read_data_section_zero(FILE *inputfile, char *block, long long filesize) { int i; for(i=1; i<12; i++) { fseeko(inputfile, sp[0].file_offset + 16LL + (i * 10LL), SEEK_SET); if(fread(&(sp[i].section_id), 2, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (20)\n"); return(-1); } if(sp[i].section_id != i) { textEdit1->append("Error, section ID nr does not match\n"); return(-1); } if(fread(&(sp[i].section_length), 4, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (21)\n"); return(-1); } if(fread(&(sp[i].file_offset), 4, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (22)\n"); return(-1); } if((sp[i].section_length > 0) && (sp[i].file_offset > 0LL)) { sp[i].present = 1; sp[i].file_offset--; } else { if((sp[i].section_id == 1) || (sp[i].section_id == 3) || (sp[i].section_id == 6)) { textEdit1->append("Error, a required section is missing\n"); return(-1); } } if((sp[i].file_offset + sp[i].section_length) > filesize) { textEdit1->append("Error, index + length of section is > filesize\n"); return(-1); } if(sp[i].present == 1) { if(read_section_header(i, inputfile, sp[i].file_offset, block)) { return(-1); } } } return(0); } int UI_SCPECG2EDFwindow::check_crc(FILE *inputfile, long long offset, long long len, unsigned short crc2, char *block) { int i, blocks; unsigned short crc = 0xFFFF; long long ll_tmp; blocks = len / SPCECGBUFSIZE; fseeko(inputfile, offset, SEEK_SET); for(i=0; iappend("A read-error occurred (3)\n"); return(-1); } crc = crc_ccitt((unsigned char *)block, SPCECGBUFSIZE, crc); } ll_tmp = len % SPCECGBUFSIZE; if(ll_tmp > 0LL) { if(fread(block, ll_tmp, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (4)\n"); return(-1); } crc = crc_ccitt((unsigned char *)block, ll_tmp, crc); } if(crc != crc2) { textEdit1->append("CRC check failed!\n"); return(-1); } return(0); } int UI_SCPECG2EDFwindow::read_section_header(int n, FILE *inputfile, long long offset, char *block) { char str[256]; fseeko(inputfile, offset, SEEK_SET); if(fread(&(sp[n].crc), 2, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (5)\n"); return(-1); } if(fread(&(sp[n].section_id), 2, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (6)\n"); return(-1); } if(sp[n].section_id != n) { textEdit1->append("Error, section ID does not match"); return(-1); } if(fread(&(sp[n].section_length), 4, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (7)\n"); return(-1); } if(fread(&(sp[n].section_version), 1, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (8)\n"); return(-1); } if(fread(&(sp[n].section_protocol_version), 1, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (9)\n"); return(-1); } if(fread(&(sp[n].reserved), 6, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (10)\n"); return(-1); } if(check_crc(inputfile, offset + 2, sp[n].section_length - 2LL, sp[n].crc, block)) { sprintf(str, "CRC-error in section %i\n", n); textEdit1->append(str); return(-1); } sp[n].present = 1; return(0); } unsigned short UI_SCPECG2EDFwindow::crc_ccitt(const unsigned char *message, int nbytes, unsigned short remainder) { int byte; unsigned char data; for(byte=0; byte> 8); remainder = crc_ccitt_table[data] ^ (remainder << 8); } return(remainder); /* The final remainder is the CRC. */ } void UI_SCPECG2EDFwindow::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. */ } } inline unsigned char UI_SCPECG2EDFwindow::reverse_bitorder(unsigned char byte) { byte = (byte & 0xF0) >> 4 | (byte & 0x0F) << 4; byte = (byte & 0xCC) >> 2 | (byte & 0x33) << 2; byte = (byte & 0xAA) >> 1 | (byte & 0x55) << 1; return byte; } void UI_SCPECG2EDFwindow::lead_label_lookup(unsigned char idx, char *label) { char scp_labels[256][9]={"unspec.", "I", "II", "V1", "V2", "V3", "V4", "V5", "V6", "V7", "V2R", "V3R", "V4R", "V5R", "V6R", "V7R", "X", "Y", "Z", "CC5", "CM5", "LA", "RA", "LL", "fl", "fE", "fC", "fA", "fM", "fF", "fH", "dl", "dll", "dV1", "dV2", "dV3", "dV4", "dV5", "dV6", "dV7", "dV2R", "dV3R", "dV4R", "dV5R", "dV6R", "dV7R", "dX", "dY", "dZ", "dCC5", "dCM5", "dLA", "dRA", "dLL", "dfl", "dfE", "dfC", "dfA", "dfM", "dfF", "dfH", "III", "aVR", "aVL", "aVF", "aVRneg", "V8", "V9", "V8R", "V9R", "D", "A", "J", "Defib", "Extern", "A1", "A2", "A3", "A4", "dV8", "dV9", "dV8R", "dV9R", "dD", "dA", "dj", "Chest", "V", "VR", "VL", "VF", "MCL", "MCL1", "MCL2", "MCL3", "MCL4", "MCL5", "MCL6", "CC", "CC1", "CC2", "CC3", "CC4", "CC6", "CC7", "CM", "CM1", "CM2", "CM3", "CM4", "CM6", "dIII", "daVR", "daVL", "daVF", "daVRneg", "dChest", "dV", "dVR", "dVL", "dVF", "CM7", "CH5", "CS5", "CB5", "CR5", "ML", "AB1", "AB2", "AB3", "AB4", "ES", "AS", "AI", "S", "dDefib", "dExtern", "da1", "da2", "da3", "da4", "dMCL1", "dMCL2", "dMCL3", "dMCL4", "dMCL5", "dMCL6", "RL", "CV5RL", "CV6LL", "CV6LU", "V10", "dMCL", "dCC", "dCC1", "dCC2", "dCC3", "dCC4", "dCC5", "dCC6", "dCM", "dCM1", "dCM2", "dCM3", "dCM4", "dCM6", "dCM7", "dCH5", "dCS5", "dCB5", "dCR5", "dML", "dAB1", "dAB2", "dAB3", "dAB4", "dES", "dAS", "dAI", "dS", "dRL", "dCV5RL", "dCV6LL", "dCV6LU", "dV10", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}; if(idx > 184) { strcpy(label, "unknown"); } else { strcpy(label, scp_labels[idx]); } } int UI_SCPECG2EDFwindow::get_patient_data(FILE *inputfile) { char str[2048]; int i, j, n, len, tag; long long offset; void *pntr=NULL; if(inputfile == NULL) { return(-1); } offset = sp[1].file_offset + 16LL; for(int k=0; ; k++) { fseeko(inputfile, offset, SEEK_SET); if(fread(str, 3, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (80)\n"); return(-1); } len = *((unsigned short *)(str + 1)); if((offset + len + 3 - sp[1].file_offset) > sp[1].section_length) { textEdit1->append("Found an error in section 1 (81)\n" "Conversion aborted\n"); return(-1); } offset += (len + 3); tag = *((unsigned char *)str); if(tag == 255) { return(0); } if(len) { n = len; if(n > 2046) { n = 2046; } if(fread(str, n, 1, inputfile) != 1) { textEdit1->append("A read-error occurred (82)\n"); return(-1); } str[n] = 0; if(tag == 2) // Patient ID { strncpy(pat_dat.pat_id, str, 20); pat_dat.pat_id[20] = 0; remove_trailing_spaces(pat_dat.pat_id); remove_leading_spaces(pat_dat.pat_id); } if(tag == 0) // Patient last name { strncpy(pat_dat.last_name, str, 20); pat_dat.last_name[20] = 0; remove_trailing_spaces(pat_dat.last_name); remove_leading_spaces(pat_dat.last_name); } if(tag == 1) // Patient first name { strncpy(pat_dat.first_name, str, 20); pat_dat.first_name[20] = 0; remove_trailing_spaces(pat_dat.first_name); remove_leading_spaces(pat_dat.first_name); } if(tag == 8) // Patient sex { pat_dat.sex = str[0]; } if(tag == 25) // startdate { pntr = str; pat_dat.startdate_year = *((unsigned short *)pntr); pat_dat.startdate_month = str[2]; pat_dat.startdate_day = str[3]; } if(tag == 26) // starttime { pat_dat.starttime_hour = str[0]; pat_dat.starttime_minute = str[1]; pat_dat.starttime_second = str[2]; } if(tag == 5) // birthdate { pntr = str; pat_dat.startdate_year = *((unsigned short *)pntr); pat_dat.startdate_month = str[2]; pat_dat.startdate_day = str[3]; } if(tag == 14) // machine ID acquiring device { pat_dat.lang_code = str[16]; strncpy(pat_dat.device_model, str + 8, 5); pat_dat.device_model[5] = 0; i = str[35]; i += 36; if(i < 1500) { strncpy(pat_dat.device_serial, str + i + 1, 48); pat_dat.device_serial[48] = 0; latin1_to_ascii(pat_dat.device_serial, 48); remove_trailing_spaces(pat_dat.device_serial); remove_leading_spaces(pat_dat.device_serial); } j = 0; for( ; i<1500; i++) { if(str[i] == 0) { j++; if(j == 1) { strncpy(pat_dat.device_ident, str + i + 1, 48); pat_dat.device_ident[48] = 0; latin1_to_ascii(pat_dat.device_ident, 48); remove_trailing_spaces(pat_dat.device_ident); remove_leading_spaces(pat_dat.device_ident); } if(j == 3) { strncpy(pat_dat.manufacturer, str + i + 1, 48); pat_dat.manufacturer[48] = 0; latin1_to_ascii(pat_dat.manufacturer, 48); remove_trailing_spaces(pat_dat.manufacturer); remove_leading_spaces(pat_dat.manufacturer); break; } } } } } } return(0); } edfbrowser_157_source/PaxHeaders.7921/ascii_export.h0000644000000000000000000000013212646460742017530 xustar0030 mtime=1452958178.238246763 30 atime=1452958178.238246763 30 ctime=1452958178.238246763 edfbrowser_157_source/ascii_export.h0000644000175000001440000000416412646460742020076 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef ASCIIEXPORTFORM1_H #define ASCIIEXPORTFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "utils.h" class UI_Mainwindow; class UI_AsciiExportwindow : public QObject { Q_OBJECT public: UI_AsciiExportwindow(QWidget *parent); UI_Mainwindow *mainwindow; private: QDialog *AsciiExportDialog; QListWidget *filelist; QPushButton *CloseButton, *ExportButton; struct asciiedfparamblock{ int smp_per_record; int smp_written; int dig_min; int dig_max; double offset; int buf_offset; double phys_min; double phys_max; double time_step; double sense; } *edfparamascii; private slots: void ExportButtonClicked(); }; #endif // ASCIIEXPORTFORM1_H edfbrowser_157_source/PaxHeaders.7921/viewcurve.cpp0000644000000000000000000000013212646460742017411 xustar0030 mtime=1452958178.249246726 30 atime=1452958178.249246726 30 ctime=1452958178.249246726 edfbrowser_157_source/viewcurve.cpp0000644000175000001440000040002112646460742017747 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "viewcurve.h" ViewCurve::ViewCurve(QWidget *w_parent) : QWidget(w_parent) { int i; setAttribute(Qt::WA_OpaquePaintEvent); mainwindow = (UI_Mainwindow *)w_parent; special_pen = new QPen(Qt::SolidPattern, 0, Qt::DotLine, Qt::SquareCap, Qt::BevelJoin); annot_marker_pen = new QPen(Qt::SolidPattern, 0, Qt::DashLine, Qt::SquareCap, Qt::BevelJoin); signal_pen = new QPen(Qt::SolidPattern, 2, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin); ruler_pen = new QPen(Qt::SolidPattern, 0, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin); active_markers = (struct active_markersblock *)calloc(1, sizeof(struct active_markersblock)); annot_marker_moving = 0; use_move_events = 0; sidemenu_active = 0; draw_zoom_rectangle = 0; printing = 0; pressed_on_label = 0; 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; crosshair_1.active = 0; crosshair_2.active = 0; ruler_active = 0; crosshair_1.moving = 0; crosshair_2.moving = 0; ruler_moving = 0; crosshair_1.value = 0.0; crosshair_2.value = 0.0; printsize_x_factor=1.0, printsize_y_factor=1.0; printfont = new QFont; printfont->setFamily("Arial"); screensamples = (int *)calloc(1, sizeof(int[MAXSIGNALS])); cpu_cnt = QThread::idealThreadCount(); if(cpu_cnt < 1) cpu_cnt = 1; if(cpu_cnt > MAXSIGNALS) cpu_cnt = MAXSIGNALS; for(i=0; imousewheelsens < 1) return; if(mainwindow->files_open == 0) return; if(QApplication::keyboardModifiers() == Qt::ControlModifier) { if(wheel_event->delta() > 0) { if((mainwindow->viewtime_sync==VIEWTIME_SYNCED_OFFSET)||(mainwindow->viewtime_sync==VIEWTIME_SYNCED_ABSOLUT)||(mainwindow->viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { for(i=0; ifiles_open; i++) { if(mainwindow->timescale_doubler == 50) { mainwindow->edfheaderlist[i]->viewtime += (mainwindow->pagetime * 0.3); } else { mainwindow->edfheaderlist[i]->viewtime += (mainwindow->pagetime / 4); } l_tmp = mainwindow->edfheaderlist[i]->viewtime % TIME_DIMENSION; if(l_tmp < trshld) { mainwindow->edfheaderlist[i]->viewtime -= l_tmp; } if(l_tmp > (TIME_DIMENSION - trshld)) { mainwindow->edfheaderlist[i]->viewtime += (TIME_DIMENSION - l_tmp); } } } if(mainwindow->viewtime_sync==VIEWTIME_UNSYNCED) { if(mainwindow->timescale_doubler == 50) { mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime += (mainwindow->pagetime * 0.3); } else { mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime += (mainwindow->pagetime / 4); } l_tmp = mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime % TIME_DIMENSION; if(l_tmp < trshld) { mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime -= l_tmp; } if(l_tmp > (TIME_DIMENSION - trshld)) { mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime += (TIME_DIMENSION - l_tmp); } } if(mainwindow->timescale_doubler == 10) { mainwindow->timescale_doubler = 50; mainwindow->pagetime /= 2; } else { if(mainwindow->timescale_doubler == 50) { mainwindow->timescale_doubler = 20; mainwindow->pagetime /= 2.5; } else { mainwindow->timescale_doubler = 10; mainwindow->pagetime /= 2; } } } else { if((mainwindow->viewtime_sync==VIEWTIME_SYNCED_OFFSET)||(mainwindow->viewtime_sync==VIEWTIME_SYNCED_ABSOLUT)||(mainwindow->viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { for(i=0; ifiles_open; i++) { if(mainwindow->timescale_doubler == 20) { mainwindow->edfheaderlist[i]->viewtime -= (mainwindow->pagetime * 0.75); } else { mainwindow->edfheaderlist[i]->viewtime -= (mainwindow->pagetime / 2); } l_tmp = mainwindow->edfheaderlist[i]->viewtime % TIME_DIMENSION; if(l_tmp < trshld) { mainwindow->edfheaderlist[i]->viewtime -= l_tmp; } if(l_tmp > (TIME_DIMENSION - trshld)) { mainwindow->edfheaderlist[i]->viewtime += (TIME_DIMENSION - l_tmp); } } } if(mainwindow->viewtime_sync==VIEWTIME_UNSYNCED) { if(mainwindow->timescale_doubler == 20) { mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime -= (mainwindow->pagetime * 0.75); } else { mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime -= (mainwindow->pagetime / 2); } l_tmp = mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime % TIME_DIMENSION; if(l_tmp < trshld) { mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime -= l_tmp; } if(l_tmp > (TIME_DIMENSION - trshld)) { mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime += (TIME_DIMENSION - l_tmp); } } if(mainwindow->timescale_doubler == 10) { mainwindow->timescale_doubler = 20; mainwindow->pagetime *= 2; } else { if(mainwindow->timescale_doubler == 20) { mainwindow->timescale_doubler = 50; mainwindow->pagetime *= 2.5; } else { mainwindow->timescale_doubler = 10; mainwindow->pagetime *= 2; } } } } else { if((mainwindow->video_player->status == VIDEO_STATUS_PLAYING) || (mainwindow->video_player->status == VIDEO_STATUS_PAUSED)) { if(wheel_event->delta() > 0) { mainwindow->video_player_seek((int)((mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime - (mainwindow->pagetime / mainwindow->mousewheelsens)) / TIME_DIMENSION)); } else { mainwindow->video_player_seek((int)((mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime + (mainwindow->pagetime / mainwindow->mousewheelsens)) / TIME_DIMENSION)); } if(mainwindow->video_player->status == VIDEO_STATUS_PLAYING) return; } if((mainwindow->viewtime_sync==VIEWTIME_SYNCED_OFFSET)||(mainwindow->viewtime_sync==VIEWTIME_SYNCED_ABSOLUT)||(mainwindow->viewtime_sync==VIEWTIME_USER_DEF_SYNCED)) { for(i=0; ifiles_open; i++) { if(wheel_event->delta() > 0) { mainwindow->edfheaderlist[i]->viewtime -= (mainwindow->pagetime / mainwindow->mousewheelsens); } else { mainwindow->edfheaderlist[i]->viewtime += (mainwindow->pagetime / mainwindow->mousewheelsens); } } } if(mainwindow->viewtime_sync==VIEWTIME_UNSYNCED) { if(wheel_event->delta() > 0) { mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime -= (mainwindow->pagetime / mainwindow->mousewheelsens); } else { mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime += (mainwindow->pagetime / mainwindow->mousewheelsens); } } } mainwindow->setup_viewbuf(); } void ViewCurve::mousePressEvent(QMouseEvent *press_event) { int i, j, baseline, signalcomps, m_x, m_y, h_size; struct signalcompblock **signalcomp; if(!mainwindow->files_open) return; if(!mainwindow->signalcomps) return; signalcomps = mainwindow->signalcomps; signalcomp = mainwindow->signalcomp; m_x = press_event->x(); m_y = press_event->y(); mouse_press_coordinate_x = m_x; mouse_press_coordinate_y = m_y; pressed_on_label = 0; h_size = (int)(4.0 / mainwindow->pixelsizefactor); setFocus(Qt::MouseFocusReason); if(press_event->button()==Qt::LeftButton) { crosshair_1.moving = 0; crosshair_2.moving = 0; ruler_moving = 0; use_move_events = 1; setMouseTracking(true); mouse_old_x = m_x; mouse_old_y = m_y; if(ruler_active) { if((m_y>(ruler_y_position + h_size + 10))&&(m_y<(ruler_y_position + h_size + 30))&&(m_x>ruler_x_position)&&(m_x<(ruler_x_position + 60))) { if(floating_ruler_value) { floating_ruler_value = 0; } else { floating_ruler_value = 1; } update(); return; } else if((m_y>ruler_y_position)&&(m_y<(ruler_y_position + ((int)(4.0 / mainwindow->pixelsizefactor))))&&(m_x>ruler_x_position)&&(m_x<(ruler_x_position + 150 + (w / 5)))) { ruler_moving = 1; } } if(!ruler_moving) { if(crosshair_1.active) { if((m_y(crosshair_1.y_position - 51))&&(m_x>crosshair_1.x_position)&&(m_x<(crosshair_1.x_position + 171))) { crosshair_1.moving = 1; } if(m_x>(crosshair_1.x_position-10)&&(m_x<(crosshair_1.x_position + 10))) { crosshair_1.moving = 1; } } } if((!ruler_moving)&&(!crosshair_1.moving)) { if(crosshair_2.active) { if((m_y(crosshair_2.y_position - 80))&&(m_x>crosshair_2.x_position)&&(m_x<(crosshair_2.x_position + 171))) { crosshair_2.moving = 1; } if(m_x>(crosshair_2.x_position-10)&&(m_x<(crosshair_2.x_position + 10))) { crosshair_2.moving = 1; } } } if(mainwindow->annot_editor_active) { if((!ruler_moving)&&(!crosshair_1.moving)&&(!crosshair_2.moving)) { for(i=0; icount; i++) { if(m_x>(active_markers->list[i]->x_pos-5)&&(m_x<(active_markers->list[i]->x_pos+5))) { active_markers->selected = i; annot_marker_moving = 1; active_markers->list[i]->selected = 1; break; } } } } if((!ruler_moving)&&(!crosshair_1.moving)&&(!crosshair_2.moving)&&(!annot_marker_moving)) { for(i=0; i(baseline-24))&&(m_x>3)&&(m_x<110)) { original_screen_offset = signalcomp[i]->screen_offset; signalcomp[i]->hasoffsettracking = 1; signal_nr = i; pressed_on_label = i + 1; label_press_y_position = m_y; break; } } } if((!pressed_on_label)&&(!ruler_moving)&&(!crosshair_1.moving)&&(!crosshair_2.moving)&&(!annot_marker_moving)) { draw_zoom_rectangle = 1; mouse_x = m_x; mouse_y = m_y; } } if(press_event->button()==Qt::RightButton) { for(i=0; ihascursor1 = 0; signalcomp[i]->hascursor2 = 0; signalcomp[i]->hasoffsettracking = 0; } crosshair_1.active = 0; crosshair_2.active = 0; crosshair_1.moving = 0; crosshair_2.moving = 0; use_move_events = 0; setMouseTracking(false); for(i=0; i(baseline-24))&&(m_x>3)&&(m_x<110)) { for(j=0; jnum_of_signals; j++) { original_sensitivity[j] = signalcomp[i]->sensitivity[j]; } original_screen_offset = signalcomp[i]->screen_offset; signalcomp[i]->hasgaintracking = 1; use_move_events = 1; setMouseTracking(true); signal_nr = i; break; } } if(!use_move_events) { for(i=0; ihasruler = 0; } ruler_active = 0; ruler_moving = 0; update(); } } } void ViewCurve::mouseReleaseEvent(QMouseEvent *release_event) { int i, j, baseline, signalcomps, m_x, m_y; double zoomfactor; struct signalcompblock **signalcomp; if(!mainwindow->files_open) return; if(!mainwindow->signalcomps) return; signalcomps = mainwindow->signalcomps; signalcomp = mainwindow->signalcomp; m_x = release_event->x(); m_y = release_event->y(); if(release_event->button()==Qt::LeftButton) { if(crosshair_1.moving) { mainwindow->annotationEditDock->annotEditSetOnset(crosshair_1.time_relative); } if(crosshair_2.moving) { mainwindow->annotationEditDock->annotEditSetDuration(crosshair_2.time_relative - crosshair_1.time_relative); } if(annot_marker_moving) { active_markers->list[active_markers->selected]->x_pos = m_x; active_markers->list[active_markers->selected]->onset = ((long long)((((double)m_x) / w) * mainwindow->pagetime)) + mainwindow->edfheaderlist[active_markers->file_num]->viewtime + mainwindow->edfheaderlist[active_markers->file_num]->starttime_offset; active_markers->list[active_markers->selected]->modified = 1; active_markers->list[active_markers->selected]->selected = 1; mainwindow->annotationEditDock->set_selected_annotation(active_markers->list[active_markers->selected]); mainwindow->annotations_dock[active_markers->file_num]->updateList(); mainwindow->annotations_edited = 1; update(); } ruler_moving = 0; crosshair_1.moving = 0; crosshair_2.moving = 0; annot_marker_moving = 0; use_move_events = 0; setMouseTracking(false); if(draw_zoom_rectangle) { draw_zoom_rectangle = 0; if((m_x>(mouse_press_coordinate_x + 50))&&(m_y > mouse_press_coordinate_y + 50)) { for(i=0; ifiles_open; i++) { mainwindow->zoomhistory->viewtime[mainwindow->zoomhistory->pntr][i] = mainwindow->edfheaderlist[i]->viewtime; } mainwindow->zoomhistory->pagetime[mainwindow->zoomhistory->pntr] = mainwindow->pagetime; for(i=0; izoomhistory->voltpercm[mainwindow->zoomhistory->pntr][i] = signalcomp[i]->voltpercm; mainwindow->zoomhistory->screen_offset[mainwindow->zoomhistory->pntr][i] = signalcomp[i]->screen_offset; for(j=0; jnum_of_signals; j++) { mainwindow->zoomhistory->sensitivity[mainwindow->zoomhistory->pntr][i][j] = signalcomp[i]->sensitivity[j]; } } mainwindow->zoomhistory->pntr++; mainwindow->zoomhistory->pntr %= 64; for(i=0; ifiles_open; i++) { mainwindow->edfheaderlist[i]->viewtime += (long long)(((double)mainwindow->pagetime / (double)w) * (double)mouse_press_coordinate_x); } mainwindow->pagetime = (long long)((double)mainwindow->pagetime / ((double)w / (double)(m_x - mouse_press_coordinate_x))); if(mainwindow->pagetime<1) mainwindow->pagetime = 1; zoomfactor = (double)h / (double)(m_y - mouse_press_coordinate_y); for(i=0; isignalcomp[i]->screen_offset = mainwindow->signalcomp[i]->screen_offset * zoomfactor; mainwindow->signalcomp[i]->screen_offset += (((double)h * (zoomfactor - 1.0) * (double)(i + 1.0)) / (double)(signalcomps + 1.0)); mainwindow->signalcomp[i]->screen_offset -= ((double)mouse_press_coordinate_y * zoomfactor); mainwindow->signalcomp[i]->voltpercm = mainwindow->signalcomp[i]->voltpercm / ((double)h / (double)(m_y - mouse_press_coordinate_y)); for(j=0; jsignalcomp[i]->num_of_signals; j++) { mainwindow->signalcomp[i]->sensitivity[j] = mainwindow->signalcomp[i]->sensitivity[j] * ((double)h / (double)(m_y - mouse_press_coordinate_y)); } } mainwindow->zoomhistory->history_size_tail++; mainwindow->zoomhistory->history_size_front = 0; mainwindow->setup_viewbuf(); } else { update(); } } for(i=0; ihasoffsettracking) { signalcomp[i]->hasoffsettracking = 0; use_move_events = 0; setMouseTracking(false); update(); } } for(i=0; i(baseline-24))&&(m_x>3)&&(m_x<110)) { if(pressed_on_label == (i + 1)) { use_move_events = 0; setMouseTracking(false); update(); signal_nr = i; exec_sidemenu(i); break; } } } } if(release_event->button()==Qt::RightButton) { for(i=0; ihasgaintracking) { signalcomp[i]->hasgaintracking = 0; use_move_events = 0; setMouseTracking(false); update(); } } } pressed_on_label = 0; } void ViewCurve::mouseMoveEvent(QMouseEvent *move_event) { int i, j, signalcomps, delta_y; double d_temp; struct signalcompblock **signalcomp; if(!mainwindow->files_open) return; if(!mainwindow->signalcomps) return; if(use_move_events) { signalcomps = mainwindow->signalcomps; signalcomp = mainwindow->signalcomp; mouse_x = move_event->x(); mouse_y = move_event->y(); if(pressed_on_label) { if((mouse_y > (label_press_y_position + 10)) || (mouse_y < (label_press_y_position - 10))) { pressed_on_label = 0; } } if(crosshair_1.moving) { if(mouse_x<(w-100)) { crosshair_1.x_position += (mouse_x - mouse_old_x); mouse_old_x = mouse_x; if(crosshair_1.x_position<0) { crosshair_1.x_position = 0; } } if((mouse_y<(h-30))&&(mouse_y>30)) { crosshair_1.y_position += (mouse_y - mouse_old_y); mouse_old_y = mouse_y; if(crosshair_1.y_position<1) { crosshair_1.y_position = 1; } } } if(crosshair_2.moving) { if(mouse_x<(w-100)) { crosshair_2.x_position += (mouse_x - mouse_old_x); mouse_old_x = mouse_x; if(crosshair_2.x_position<0) { crosshair_2.x_position = 0; } } if((mouse_y<(h-30))&&(mouse_y>30)) { crosshair_2.y_position += (mouse_y - mouse_old_y); mouse_old_y = mouse_y; if(crosshair_2.y_position<1) { crosshair_2.y_position = 1; } } } if(ruler_moving) { if(mouse_x<(w-100)) { ruler_x_position += (mouse_x - mouse_old_x); mouse_old_x = mouse_x; if(ruler_x_position<1) { ruler_x_position = 1; } } if(mouse_y<(h-100)) { ruler_y_position += (mouse_y - mouse_old_y); mouse_old_y = mouse_y; if(ruler_y_position<1) { ruler_y_position = 1; } } } if(annot_marker_moving) { active_markers->list[active_markers->selected]->x_pos = mouse_x; active_markers->list[active_markers->selected]->onset = ((long long)((((double)mouse_x) / w) * mainwindow->pagetime)) + mainwindow->edfheaderlist[active_markers->file_num]->viewtime + mainwindow->edfheaderlist[active_markers->file_num]->starttime_offset; } delta_y = mouse_y - mouse_press_coordinate_y; for(i=0; ihasoffsettracking) { signalcomp[i]->screen_offset = original_screen_offset + delta_y; } if(signalcomp[i]->hasgaintracking) { for(j=0; jnum_of_signals; j++) { d_temp = original_sensitivity[j] * (1.0 + ((double)(-delta_y) / 50.0)); if(d_temp>0.000001) { signalcomp[i]->sensitivity[j] = d_temp; d_temp = signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].bitvalue / (signalcomp[i]->sensitivity[j] * mainwindow->pixelsizefactor); signalcomp[i]->voltpercm = d_temp; } } signalcomp[i]->screen_offset = original_screen_offset * (signalcomp[i]->sensitivity[0] / original_sensitivity[0]); } } if(draw_zoom_rectangle||annot_marker_moving) { update(); } else { drawCurve_stage_1(); } } } void ViewCurve::paintEvent(QPaintEvent *) { QPainter paint(this); #if QT_VERSION >= 0x050000 paint.setRenderHint(QPainter::Qt4CompatiblePainting, true); #endif drawCurve_stage_2(&paint); } void ViewCurve::print_to_printer() { int i, j, len; char path[MAX_PATH_LENGTH]; double height_factor; struct date_time_struct date_time; if(!mainwindow->files_open) return; if(!mainwindow->signalcomps) return; QPrinter print(QPrinter::HighResolution); print.setOutputFormat(QPrinter::NativeFormat); print.setPageSize(QPrinter::A4); print.setOrientation(QPrinter::Landscape); print.setCreator(PROGRAM_NAME); QPrintDialog printerdialog(&print, this); printerdialog.setWindowTitle("Print"); if(printerdialog.exec()==QDialog::Accepted) { if(blackwhite_printing) { backup_colors_for_printing(); } height_factor = ((double)print.pageRect().height()) / 9000.0; QPainter paint(&print); #if QT_VERSION >= 0x050000 paint.setRenderHint(QPainter::Qt4CompatiblePainting, true); #endif paint.translate(0, (int)(260.0 * height_factor)); drawCurve_stage_1(&paint, print.pageRect().width() - 30, (int)((double)print.pageRect().height() - (260.0 * height_factor) - 30), 2); paint.translate(0, -(int)(260.0 * height_factor)); len = strlen(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename); for(i=len-1; i>=0; i--) { if((mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename[i] == '/')||(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename[i] == '\\')) break; } i++; strcpy(path, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename + i); strcat(path, " "); strcat(path, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->patient); remove_trailing_spaces(path); utc_to_date_time(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime, &date_time); date_time.month_str[0] += 32; date_time.month_str[1] += 32; date_time.month_str[2] += 32; sprintf(path + strlen(path), " %i %s %i ", date_time.day, date_time.month_str, date_time.year); if(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->edfplus||mainwindow->edfheaderlist[mainwindow->sel_viewtime]->bdfplus) { strcat(path, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->recording + 22); } else { strcat(path, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->recording); } remove_trailing_spaces(path); len = strlen(path); for(j=0; jsetPixelSize((int)((double)print.pageRect().width() / 104.0)); paint.setPen(text_color); paint.setFont(*printfont); paint.drawText(0, (int)(160.0 * height_factor), path); if(blackwhite_printing) { restore_colors_after_printing(); } drawCurve_stage_1(); } } #if QT_VERSION < 0x050000 void ViewCurve::print_to_postscript() { double height_factor; int i, j, len; char path[MAX_PATH_LENGTH]; struct date_time_struct date_time; if(!mainwindow->files_open) return; if(!mainwindow->signalcomps) return; path[0] = 0; if(mainwindow->recent_savedir[0]!=0) { strcpy(path, mainwindow->recent_savedir); strcat(path, "/"); } len = strlen(path); get_filename_from_path(path + len, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename, MAX_PATH_LENGTH - len); remove_extension_from_filename(path); strcat(path, ".ps"); strcpy(path, QFileDialog::getSaveFileName(0, "Print to PostScript", QString::fromLocal8Bit(path), "PostScript files (*.ps *.PS)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(mainwindow->recent_savedir, path, MAX_PATH_LENGTH); QPrinter print(QPrinter::HighResolution); print.setOutputFormat(QPrinter::PostScriptFormat); print.setOutputFileName(QString::fromLocal8Bit(path)); print.setPageSize(QPrinter::A4); print.setOrientation(QPrinter::Landscape); print.setCreator(PROGRAM_NAME); if(blackwhite_printing) { backup_colors_for_printing(); } height_factor = ((double)print.pageRect().height()) / 9000.0; QPainter paint(&print); paint.translate(0, (int)(260.0 * height_factor)); drawCurve_stage_1(&paint, print.pageRect().width() - 30, (int)((double)print.pageRect().height() - (260.0 * height_factor) - 30), 2); paint.translate(0, -(int)(260.0 * height_factor)); len = strlen(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename); for(i=len; i>=0; i--) { if((mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename[i] == '/')||(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename[i] == '\\')) { break; } } i++; strcpy(path, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename + i); strcat(path, " "); strcat(path, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->patient); remove_trailing_spaces(path); utc_to_date_time(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime, &date_time); date_time.month_str[0] += 32; date_time.month_str[1] += 32; date_time.month_str[2] += 32; sprintf(path + strlen(path), " %i %s %i ", date_time.day, date_time.month_str, date_time.year); if(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->edfplus||mainwindow->edfheaderlist[mainwindow->sel_viewtime]->bdfplus) { strcat(path, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->recording + 22); } else { strcat(path, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->recording); } remove_trailing_spaces(path); len = strlen(path); for(j=0; jsetPixelSize((int)((double)print.pageRect().width() / 104.0)); paint.setPen(text_color); paint.setFont(*printfont); paint.drawText(0, (int)(160.0 * height_factor), path); if(blackwhite_printing) { restore_colors_after_printing(); } drawCurve_stage_1(); } #endif void ViewCurve::print_to_pdf() { double height_factor; int i, j, len; char path[MAX_PATH_LENGTH]; struct date_time_struct date_time; if(!mainwindow->files_open) return; if(!mainwindow->signalcomps) return; path[0] = 0; if(mainwindow->recent_savedir[0]!=0) { strcpy(path, mainwindow->recent_savedir); strcat(path, "/"); } len = strlen(path); get_filename_from_path(path + len, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename, MAX_PATH_LENGTH - len); remove_extension_from_filename(path); strcat(path, ".pdf"); strcpy(path, QFileDialog::getSaveFileName(0, "Print to PDF", QString::fromLocal8Bit(path), "PDF files (*.pdf *.PDF)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(mainwindow->recent_savedir, path, MAX_PATH_LENGTH); QPrinter print(QPrinter::HighResolution); print.setOutputFormat(QPrinter::PdfFormat); print.setOutputFileName(QString::fromLocal8Bit(path)); print.setPageSize(QPrinter::A4); print.setOrientation(QPrinter::Landscape); print.setCreator(PROGRAM_NAME); if(blackwhite_printing) { backup_colors_for_printing(); } height_factor = ((double)print.pageRect().height()) / 9000.0; QPainter paint(&print); #if QT_VERSION >= 0x050000 paint.setRenderHint(QPainter::Qt4CompatiblePainting, true); #endif paint.translate(0, (int)(260.0 * height_factor)); drawCurve_stage_1(&paint, print.pageRect().width() - 30, (int)((double)print.pageRect().height() - (260.0 * height_factor) - 30), 2); paint.translate(0, -(int)(260.0 * height_factor)); len = strlen(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename); for(i=len; i>=0; i--) { if((mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename[i] == '/')||(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename[i] == '\\')) { break; } } i++; strcpy(path, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename + i); strcat(path, " "); strcat(path, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->patient); remove_trailing_spaces(path); utc_to_date_time(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime, &date_time); date_time.month_str[0] += 32; date_time.month_str[1] += 32; date_time.month_str[2] += 32; sprintf(path + strlen(path), " %i %s %i ", date_time.day, date_time.month_str, date_time.year); if(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->edfplus||mainwindow->edfheaderlist[mainwindow->sel_viewtime]->bdfplus) { strcat(path, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->recording + 22); } else { strcat(path, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->recording); } remove_trailing_spaces(path); len = strlen(path); for(j=0; jsetPixelSize((int)((double)print.pageRect().width() / 104.0)); paint.setPen(text_color); paint.setFont(*printfont); paint.drawText(0, (int)(160.0 * height_factor), path); if(blackwhite_printing) { restore_colors_after_printing(); } drawCurve_stage_1(); } void ViewCurve::print_to_image(int w_img, int h_img) { int i, j, len; char path[MAX_PATH_LENGTH], str[1024]; struct date_time_struct date_time; if(!mainwindow->files_open) return; if(!mainwindow->signalcomps) return; path[0] = 0; if(mainwindow->recent_savedir[0]!=0) { strcpy(path, mainwindow->recent_savedir); strcat(path, "/"); } len = strlen(path); get_filename_from_path(path + len, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename, MAX_PATH_LENGTH - len); remove_extension_from_filename(path); strcat(path, ".png"); strcpy(path, QFileDialog::getSaveFileName(0, "Print to Image", QString::fromLocal8Bit(path), "PNG (*.png *.PNG)").toLocal8Bit().data()); if(!strcmp(path, "")) { return; } get_directory_from_path(mainwindow->recent_savedir, path, MAX_PATH_LENGTH); QPixmap pixmap(w_img, h_img); QPainter paint(&pixmap); #if QT_VERSION >= 0x050000 paint.setRenderHint(QPainter::Qt4CompatiblePainting, true); #endif paint.fillRect(0, 0, w_img, h_img, backgroundcolor); paint.translate(0, 25); drawCurve_stage_1(&paint, w_img, h_img - 25, 0); paint.translate(0, -25); len = strlen(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename); for(i=len; i>=0; i--) { if((mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename[i] == '/')||(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename[i] == '\\')) { break; } } i++; strcpy(str, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->filename + i); strcat(str, " "); strcat(str, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->patient); remove_trailing_spaces(str); utc_to_date_time(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->utc_starttime, &date_time); date_time.month_str[0] += 32; date_time.month_str[1] += 32; date_time.month_str[2] += 32; sprintf(str + strlen(str), " %i %s %i ", date_time.day, date_time.month_str, date_time.year); if(mainwindow->edfheaderlist[mainwindow->sel_viewtime]->edfplus||mainwindow->edfheaderlist[mainwindow->sel_viewtime]->bdfplus) { strcat(str, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->recording + 22); } else { strcat(str, mainwindow->edfheaderlist[mainwindow->sel_viewtime]->recording); } len = strlen(str); for(j=0; jsetPixelSize((int)((double)w / 104.0)); paint.setPen(text_color); paint.setFont(*printfont); paint.drawText(5, 15, str); pixmap.save(QString::fromLocal8Bit(path), "PNG", 90); drawCurve_stage_1(); } void ViewCurve::drawCurve_stage_2(QPainter *painter, int w_width, int w_height, int print_linewidth) { int i, j, x_pix=0, signalcomps, baseline, m_pagetime, vert_ruler_offset, vertical_distance, marker_x; char *viewbuf, string[600], str2[32], str3[128]; long long time_ppixel, ll_elapsed_time, l_time, l_tmp; struct signalcompblock **signalcomp; struct annotationblock *annot; QFont paintersfont; if(mainwindow->exit_in_progress) { return; } signalcomps = mainwindow->signalcomps; signalcomp = mainwindow->signalcomp; viewbuf = mainwindow->viewbuf; vertical_distance = 1; painter_pixelsizefactor = 1.0 / mainwindow->pixelsizefactor; if(!w_width||!w_height) { w = width(); h = height(); paintersfont = *mainwindow->myfont; paintersfont.setBold(true); paintersfont.setWeight(QFont::Black); painter->setFont(paintersfont); printing = 0; } else { w = w_width; h = w_height; printfont->setPixelSize((int)((double)w / 104.0)); painter->setFont(*printfont); printsize_x_factor = ((double)w_width) / ((double)width()); printsize_y_factor = ((double)w_height) / ((double)height()); painter_pixelsizefactor *= printsize_y_factor; printing = 1; } for(i=0; isample_pixel_ratio = (double)signalcomp[i]->samples_on_screen / (double)w; } painter->fillRect(0, 0, w, h, backgroundcolor); m_pagetime = (int)(mainwindow->pagetime / TIME_DIMENSION); time_ppixel = mainwindow->pagetime / w; if(mainwindow->files_open&&mainwindow->signalcomps) { ll_elapsed_time = mainwindow->edfheaderlist[mainwindow->sel_viewtime]->viewtime; } else { ll_elapsed_time = 0; } ruler_pen->setWidth(print_linewidth); if(printing) { ruler_pen->setColor(Qt::black); painter->setPen(*ruler_pen); painter->drawLine(0, 0, 0, h-1); painter->drawLine(0, 0, w-1, 0); painter->drawLine(w-1, h-1, w-1, 0); painter->drawLine(w-1, h-1, 0, h-1); } if(m_pagetime<=20) { ruler_pen->setColor(small_ruler_color); painter->setPen(*ruler_pen); for(x_pix=0; x_pixdrawLine(x_pix, 0, x_pix, 4 * printsize_y_factor); } else { painter->drawLine(x_pix, 0, x_pix, 4); } } if(((ll_elapsed_time / TIME_DIMENSION)!=((ll_elapsed_time + time_ppixel) / TIME_DIMENSION)) || ((ll_elapsed_time < time_ppixel) && (ll_elapsed_time > -time_ppixel))) { if(x_pix) { ruler_pen->setColor(big_ruler_color); painter->setPen(*ruler_pen); painter->drawLine(x_pix, 0, x_pix, h); ruler_pen->setColor(small_ruler_color); painter->setPen(*ruler_pen); } if(printing) { painter->drawLine(x_pix, 0, x_pix, 7 * printsize_y_factor); } else { painter->drawLine(x_pix, 0, x_pix, 7); } } ll_elapsed_time += time_ppixel; } } if((m_pagetime>20)&&(m_pagetime<100)) { ruler_pen->setColor(small_ruler_color); painter->setPen(*ruler_pen); for(x_pix=0; x_pixdrawLine(x_pix, 0, x_pix, 4 * printsize_y_factor); } else { painter->drawLine(x_pix, 0, x_pix, 4); } } if(((ll_elapsed_time / TIME_DIMENSION)!=((ll_elapsed_time + time_ppixel) / TIME_DIMENSION)) || ((ll_elapsed_time < time_ppixel) && (ll_elapsed_time > -time_ppixel))) { if(x_pix) { ruler_pen->setColor(big_ruler_color); painter->setPen(*ruler_pen); painter->drawLine(x_pix, 0, x_pix, h); ruler_pen->setColor(small_ruler_color); painter->setPen(*ruler_pen); } if(printing) { painter->drawLine(x_pix, 0, x_pix, 7 * printsize_y_factor); } else { painter->drawLine(x_pix, 0, x_pix, 7); } } ll_elapsed_time += time_ppixel; } } if((m_pagetime>=100)&&(m_pagetime<1000)) { ruler_pen->setColor(small_ruler_color); painter->setPen(*ruler_pen); for(x_pix=0; x_pixdrawLine(x_pix, 0, x_pix, 4 * printsize_y_factor); } else { painter->drawLine(x_pix, 0, x_pix, 4); } } if(((ll_elapsed_time / (TIME_DIMENSION * 10))!=((ll_elapsed_time + time_ppixel) / (TIME_DIMENSION * 10))) || ((ll_elapsed_time < time_ppixel) && (ll_elapsed_time > -time_ppixel))) { if(x_pix) { ruler_pen->setColor(big_ruler_color); painter->setPen(*ruler_pen); painter->drawLine(x_pix, 0, x_pix, h); ruler_pen->setColor(small_ruler_color); painter->setPen(*ruler_pen); } if(printing) { painter->drawLine(x_pix, 0, x_pix, 7 * printsize_y_factor); } else { painter->drawLine(x_pix, 0, x_pix, 7); } } ll_elapsed_time += time_ppixel; } } if((m_pagetime>=1000)&&(m_pagetime<5000)) { ruler_pen->setColor(small_ruler_color); painter->setPen(*ruler_pen); for(x_pix=0; x_pixdrawLine(x_pix, 0, x_pix, 4 * printsize_y_factor); } else { painter->drawLine(x_pix, 0, x_pix, 4); } } if(((ll_elapsed_time / (TIME_DIMENSION * 60))!=((ll_elapsed_time + time_ppixel) / (TIME_DIMENSION * 60))) || ((ll_elapsed_time < time_ppixel) && (ll_elapsed_time > -time_ppixel))) { if(x_pix) { ruler_pen->setColor(big_ruler_color); painter->setPen(*ruler_pen); painter->drawLine(x_pix, 0, x_pix, h); ruler_pen->setColor(small_ruler_color); painter->setPen(*ruler_pen); } if(printing) { painter->drawLine(x_pix, 0, x_pix, 7 * printsize_y_factor); } else { painter->drawLine(x_pix, 0, x_pix, 7); } } ll_elapsed_time += time_ppixel; } } if((m_pagetime>=5000)&&(m_pagetime<173000)) { ruler_pen->setColor(small_ruler_color); painter->setPen(*ruler_pen); for(x_pix=0; x_pixdrawLine(x_pix, 0, x_pix, 4 * printsize_y_factor); } else { painter->drawLine(x_pix, 0, x_pix, 4); } } if(((ll_elapsed_time / (TIME_DIMENSION * 3600))!=((ll_elapsed_time + time_ppixel) / (TIME_DIMENSION * 3600))) || ((ll_elapsed_time < time_ppixel) && (ll_elapsed_time > -time_ppixel))) { if(x_pix) { ruler_pen->setColor(big_ruler_color); painter->setPen(*ruler_pen); painter->drawLine(x_pix, 0, x_pix, h); ruler_pen->setColor(small_ruler_color); painter->setPen(*ruler_pen); } if(printing) { painter->drawLine(x_pix, 0, x_pix, 7 * printsize_y_factor); } else { painter->drawLine(x_pix, 0, x_pix, 7); } } ll_elapsed_time += time_ppixel; } } if((m_pagetime>=173000)&&(m_pagetime<3000000)) { ruler_pen->setColor(small_ruler_color); painter->setPen(*ruler_pen); for(x_pix=0; x_pixdrawLine(x_pix, 0, x_pix, 4 * printsize_y_factor); } else { painter->drawLine(x_pix, 0, x_pix, 4); } } if(((ll_elapsed_time / (TIME_DIMENSION * 86400))!=((ll_elapsed_time + time_ppixel) / (TIME_DIMENSION * 86400))) || ((ll_elapsed_time < time_ppixel) && (ll_elapsed_time > -time_ppixel))) { if(x_pix) { ruler_pen->setColor(big_ruler_color); painter->setPen(*ruler_pen); painter->drawLine(x_pix, 0, x_pix, h); ruler_pen->setColor(small_ruler_color); painter->setPen(*ruler_pen); } if(printing) { painter->drawLine(x_pix, 0, x_pix, 7 * printsize_y_factor); } else { painter->drawLine(x_pix, 0, x_pix, 7); } } ll_elapsed_time += time_ppixel; } } if((viewbuf==NULL)||(graphicBuf==NULL)||(screensamples==NULL)) { return; } if(mainwindow->show_baselines) { vertical_distance = h / (signalcomps + 1); painter->setPen(baseline_color); for(i=0; idrawLine(0, baseline, w, baseline); if(signalcomp[i]->voltpercm < 0.1) { strcpy(str2, "%+.3f "); } else if(signalcomp[i]->voltpercm < 1.0) { strcpy(str2, "%+.2f "); } else if(signalcomp[i]->voltpercm < 10.0) { strcpy(str2, "%+.1f "); } else { strcpy(str2, "%+.0f "); } strcat(str2, signalcomp[i]->physdimension); for(j=1; j<18; j++) { vert_ruler_offset = j * painter_pixelsizefactor; if(signalcomps!=1) { if(vert_ruler_offset>((vertical_distance / 2)) - 8) { break; } } if(printing) { if((baseline + vert_ruler_offset)>(h - (15 * printsize_y_factor))) { break; } if((baseline - vert_ruler_offset)<(15 * printsize_y_factor)) { break; } } else { if((baseline + vert_ruler_offset)>(h - 15)) { break; } if((baseline - vert_ruler_offset)<15) { break; } } painter->drawLine(0, baseline - vert_ruler_offset, w, baseline - vert_ruler_offset); #pragma GCC diagnostic ignored "-Wformat-nonliteral" if(printing) { snprintf(string, 128, str2, ((signalcomp[i]->voltpercm * j) + ((signalcomp[i]->screen_offset * signalcomp[i]->voltpercm) / (painter_pixelsizefactor / printsize_y_factor))) * (double)signalcomp[i]->polarity); } else { snprintf(string, 128, str2, ((signalcomp[i]->voltpercm * j) + ((signalcomp[i]->screen_offset * signalcomp[i]->voltpercm) / painter_pixelsizefactor)) * (double)signalcomp[i]->polarity); } painter->drawText(5 * printsize_x_factor, baseline - vert_ruler_offset - (4 * printsize_y_factor), string); painter->drawLine(0, baseline + vert_ruler_offset, w, baseline + vert_ruler_offset); if(printing) { snprintf(string, 128, str2, (((signalcomp[i]->screen_offset * signalcomp[i]->voltpercm) / (painter_pixelsizefactor / printsize_y_factor)) - (signalcomp[i]->voltpercm * j)) * (double)signalcomp[i]->polarity); } else { snprintf(string, 128, str2, (((signalcomp[i]->screen_offset * signalcomp[i]->voltpercm) / painter_pixelsizefactor) - (signalcomp[i]->voltpercm * j)) * (double)signalcomp[i]->polarity); } #pragma GCC diagnostic warning "-Wformat-nonliteral" painter->drawText(5 * printsize_x_factor, baseline + vert_ruler_offset - (4 * printsize_y_factor), string); } } } if(mainwindow->show_annot_markers) { annot_marker_pen->setColor(annot_marker_color); annot_marker_pen->setWidth(print_linewidth); painter->setPen(*annot_marker_pen); if(!annot_marker_moving) { active_markers->count = 0; } for(i=0; ifiles_open; i++) { annot = mainwindow->annotationlist[i]; j = 0; while(annot!=NULL) { 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 + mainwindow->pagetime)) { break; } l_tmp -= mainwindow->edfheaderlist[i]->viewtime; marker_x = (int)((((double)w) / mainwindow->pagetime) * l_tmp); painter->drawLine(marker_x, 0, marker_x, h); l_tmp = annot->onset - mainwindow->edfheaderlist[i]->starttime_offset; if(mainwindow->annotations_onset_relative) { if(l_tmp < 0LL) { snprintf(string, (MAX_ANNOTATION_LEN + 32) / 2, "-%i:%02i:%02i.%04i", (int)(((-(l_tmp)) / TIME_DIMENSION)/ 3600LL), (int)((((-(l_tmp)) / TIME_DIMENSION) % 3600LL) / 60LL), (int)(((-(l_tmp)) / TIME_DIMENSION) % 60LL), (int)((((-(l_tmp)) % TIME_DIMENSION) / 1000LL))); } else { snprintf(string, (MAX_ANNOTATION_LEN + 32) / 2, "%i:%02i:%02i.%04i", (int)((l_tmp / TIME_DIMENSION)/ 3600LL), (int)(((l_tmp / TIME_DIMENSION) % 3600LL) / 60LL), (int)((l_tmp / TIME_DIMENSION) % 60LL), (int)(((l_tmp % TIME_DIMENSION) / 1000LL))); } } else { snprintf(string, MAX_ANNOTATION_LEN + 32, "%i:%02i:%02i.%04i", (int)((((annot->onset + mainwindow->edfheaderlist[i]->l_starttime) / TIME_DIMENSION)/ 3600) % 24), (int)((((annot->onset + mainwindow->edfheaderlist[i]->l_starttime) / TIME_DIMENSION) % 3600) / 60), (int)(((annot->onset + mainwindow->edfheaderlist[i]->l_starttime) / TIME_DIMENSION) % 60), (int)(((annot->onset + mainwindow->edfheaderlist[i]->l_starttime) % TIME_DIMENSION) / 1000LL)); } remove_trailing_zeros(string); if(printing) { painter->drawText(marker_x + (5 * printsize_x_factor), h - (25 * printsize_y_factor), string); } else { painter->drawText(marker_x + 5, h - 65 + ((j % 3) * 30), string); } strncpy(string, annot->annotation, 20); string[20] = 0; if(printing) { painter->drawText(marker_x + (5 * printsize_x_factor), h - (40 * printsize_y_factor), QString::fromUtf8(string)); } else { painter->drawText(marker_x + 5, h - 80 + ((j % 3) * 30), QString::fromUtf8(string)); } if(!annot_marker_moving) { if(active_markers->countx_pos = marker_x; active_markers->list[active_markers->count] = annot; active_markers->count++; } } } annot = annot->next_annotation; j++; } } } if(mainwindow->clip_to_pane) { painter->setClipping(true); vertical_distance = h / (signalcomps + 1); } for(i=0; iclip_to_pane) { painter->setClipRect(0, vertical_distance * i + (vertical_distance / 2), w, vertical_distance); } if(printing) { signal_pen->setColor((Qt::GlobalColor)signalcomp[i]->color); signal_pen->setWidth(print_linewidth); painter->setPen(*signal_pen); } else { painter->setPen((Qt::GlobalColor)signalcomp[i]->color); } for(j=0; jdrawLine(graphicBuf[j].graphicLine[i].x1, graphicBuf[j].graphicLine[i].y1, graphicBuf[j].graphicLine[i].x2, graphicBuf[j].graphicLine[i].y2); } } painter->setClipping(false); for(i=0; isetPen((Qt::GlobalColor)signalcomp[i]->color); if(signalcomp[i]->hascursor1) { if(printing) { painter->setPen((Qt::GlobalColor)crosshair_1.color); painter->drawLine(0, crosshair_1.y_value, w, crosshair_1.y_value); painter->drawLine((int)((double)crosshair_1.x_position * printsize_x_factor), 0, (int)((double)crosshair_1.x_position * printsize_x_factor), h); snprintf(string, 128, "%+f %s", crosshair_1.value, signalcomp[i]->physdimension); painter->drawText((int)(((double)crosshair_1.x_position + 5.0) * printsize_x_factor), (int)(((double)crosshair_1.y_position - 40.0) * printsize_y_factor), string); snprintf(string, 128, "%2i:%02i:%02i.%04i", (int)(((crosshair_1.time / TIME_DIMENSION)/ 3600LL) % 24LL), (int)(((crosshair_1.time / TIME_DIMENSION) % 3600LL) / 60LL), (int)((crosshair_1.time / TIME_DIMENSION) % 60LL), (int)((crosshair_1.time % TIME_DIMENSION) / 1000LL)); painter->drawText((int)(((double)crosshair_1.x_position + 5.0) * printsize_x_factor), (int)(((double)crosshair_1.y_position - 25.0) * printsize_y_factor), string); if(signalcomp[i]->alias[0] != 0) { painter->drawText((int)(((double)crosshair_1.x_position + 5.0) * printsize_x_factor), (int)(((double)crosshair_1.y_position - 10.0) * printsize_y_factor), signalcomp[i]->alias); } else { painter->drawText((int)(((double)crosshair_1.x_position + 5.0) * printsize_x_factor), (int)(((double)crosshair_1.y_position - 10.0) * printsize_y_factor), signalcomp[i]->signallabel); } painter->setPen((Qt::GlobalColor)signalcomp[i]->color); } else { painter->setPen((Qt::GlobalColor)crosshair_1.color); painter->drawLine(0, crosshair_1.y_value, w, crosshair_1.y_value); painter->drawLine(crosshair_1.x_position, 0, crosshair_1.x_position, h); snprintf(string, 128, "%+f %s", crosshair_1.value, signalcomp[i]->physdimension); painter->drawText(crosshair_1.x_position + 5, crosshair_1.y_position - 40, string); snprintf(string, 128, "%2i:%02i:%02i.%04i", (int)(((crosshair_1.time / TIME_DIMENSION)/ 3600LL) % 24LL), (int)(((crosshair_1.time / TIME_DIMENSION) % 3600LL) / 60LL), (int)((crosshair_1.time / TIME_DIMENSION) % 60LL), (int)((crosshair_1.time % TIME_DIMENSION) / 1000LL)); if(crosshair_1.time_relative >= TIME_DIMENSION) { snprintf(string + strlen(string), 32, " (%i:%02i:%02i.%04i)", (int)((crosshair_1.time_relative / TIME_DIMENSION)/ 3600LL), (int)(((crosshair_1.time_relative / TIME_DIMENSION) % 3600LL) / 60LL), (int)((crosshair_1.time_relative / TIME_DIMENSION) % 60LL), (int)((crosshair_1.time_relative % TIME_DIMENSION) / 1000LL)); } else { convert_to_metric_suffix(str3, (double)crosshair_1.time_relative / TIME_DIMENSION, 3); snprintf(string + strlen(string), 32, " (%sS)", str3); } painter->drawText(crosshair_1.x_position + 5, crosshair_1.y_position - 25, string); if(signalcomp[i]->alias[0] != 0) { painter->drawText(crosshair_1.x_position + 5, crosshair_1.y_position - 10, signalcomp[i]->alias); } else { painter->drawText(crosshair_1.x_position + 5, crosshair_1.y_position - 10, signalcomp[i]->signallabel); } painter->setPen((Qt::GlobalColor)signalcomp[i]->color); mainwindow->annotationEditDock->annotEditSetOnset(crosshair_1.time_relative); } } if(signalcomp[i]->hascursor2) { if(printing) { painter->setPen((Qt::GlobalColor)crosshair_2.color); painter->drawLine(0, crosshair_2.y_value, w, crosshair_2.y_value); painter->drawLine((int)((double)crosshair_2.x_position * printsize_x_factor), 0, (int)((double)crosshair_2.x_position * printsize_x_factor), h); snprintf(string, 128, "%+f %s", crosshair_2.value, signalcomp[i]->physdimension); painter->drawText((int)(((double)crosshair_2.x_position + 5.0) * printsize_x_factor), (int)(((double)crosshair_2.y_position - 70.0) * printsize_y_factor), string); snprintf(string, 128, "%2i:%02i:%02i.%04i", (int)(((crosshair_2.time / TIME_DIMENSION)/ 3600LL) % 24LL), (int)(((crosshair_2.time / TIME_DIMENSION) % 3600LL) / 60LL), (int)((crosshair_2.time / TIME_DIMENSION) % 60LL), (int)((crosshair_2.time % TIME_DIMENSION) / 1000LL)); painter->drawText((int)(((double)crosshair_2.x_position + 5.0) * printsize_x_factor), (int)(((double)crosshair_2.y_position - 55.0) * printsize_y_factor), string); snprintf(string, 128, "delta %+f %s", crosshair_2.value - crosshair_1.value, signalcomp[i]->physdimension); painter->drawText((int)(((double)crosshair_2.x_position + 5.0) * printsize_x_factor), (int)(((double)crosshair_2.y_position - 40.0) * printsize_y_factor), string); l_time = crosshair_2.time - crosshair_1.time; if(l_time<0) l_time = -l_time; snprintf(string, 128, "delta %i:%02i:%02i.%04i", (int)((l_time / TIME_DIMENSION)/ 3600LL), (int)(((l_time / TIME_DIMENSION) % 3600LL) / 60LL), (int)((l_time / TIME_DIMENSION) % 60LL), (int)((l_time % TIME_DIMENSION) / 1000LL)); painter->drawText((int)(((double)crosshair_2.x_position + 5.0) * printsize_x_factor), (int)(((double)crosshair_2.y_position - 25.0) * printsize_y_factor), string); if(signalcomp[i]->alias[0] != 0) { painter->drawText((int)(((double)crosshair_2.x_position + 5.0) * printsize_x_factor), (int)(((double)crosshair_2.y_position - 10.0) * printsize_y_factor), signalcomp[i]->alias); } else { painter->drawText((int)(((double)crosshair_2.x_position + 5.0) * printsize_x_factor), (int)(((double)crosshair_2.y_position - 10.0) * printsize_y_factor), signalcomp[i]->signallabel); } painter->setPen((Qt::GlobalColor)signalcomp[i]->color); } else { painter->setPen((Qt::GlobalColor)crosshair_2.color); painter->drawLine(0, crosshair_2.y_value, w, crosshair_2.y_value); painter->drawLine(crosshair_2.x_position, 0, crosshair_2.x_position, h); snprintf(string, 128, "%+f %s", crosshair_2.value, signalcomp[i]->physdimension); painter->drawText(crosshair_2.x_position + 5, crosshair_2.y_position - 70, string); snprintf(string, 128, "%2i:%02i:%02i.%04i", (int)(((crosshair_2.time / TIME_DIMENSION)/ 3600LL) % 24LL), (int)(((crosshair_2.time / TIME_DIMENSION) % 3600LL) / 60LL), (int)((crosshair_2.time / TIME_DIMENSION) % 60LL), (int)((crosshair_2.time % TIME_DIMENSION) / 1000LL)); if(crosshair_2.time_relative >= TIME_DIMENSION) { snprintf(string + strlen(string), 32, " (%i:%02i:%02i.%04i)", (int)((crosshair_2.time_relative / TIME_DIMENSION)/ 3600LL), (int)(((crosshair_2.time_relative / TIME_DIMENSION) % 3600LL) / 60LL), (int)((crosshair_2.time_relative / TIME_DIMENSION) % 60LL), (int)((crosshair_2.time_relative % TIME_DIMENSION) / 1000LL)); } else { convert_to_metric_suffix(str3, (double)crosshair_2.time_relative / TIME_DIMENSION, 3); snprintf(string + strlen(string), 32, " (%sS)", str3); } painter->drawText(crosshair_2.x_position + 5, crosshair_2.y_position - 55, string); snprintf(string, 128, "delta %+f %s", crosshair_2.value - crosshair_1.value, signalcomp[i]->physdimension); painter->drawText(crosshair_2.x_position + 5, crosshair_2.y_position - 40, string); l_time = crosshair_2.time - crosshair_1.time; if(l_time<0) l_time = -l_time; if(l_time >= TIME_DIMENSION) { snprintf(string, 128, "delta %i:%02i:%02i.%04i", (int)((l_time / TIME_DIMENSION)/ 3600LL), (int)(((l_time / TIME_DIMENSION) % 3600LL) / 60LL), (int)((l_time / TIME_DIMENSION) % 60LL), (int)((l_time % TIME_DIMENSION) / 1000LL)); } else { convert_to_metric_suffix(str3, (double)l_time / TIME_DIMENSION, 3); snprintf(string, 32, "delta %sS", str3); } painter->drawText(crosshair_2.x_position + 5, crosshair_2.y_position - 25, string); if(signalcomp[i]->alias[0] != 0) { painter->drawText(crosshair_2.x_position + 5, crosshair_2.y_position - 10, signalcomp[i]->alias); } else { painter->drawText(crosshair_2.x_position + 5, crosshair_2.y_position - 10, signalcomp[i]->signallabel); } painter->setPen((Qt::GlobalColor)signalcomp[i]->color); } } if(signalcomp[i]->hasoffsettracking) { snprintf(string, 128, "offset: %f %s", -signalcomp[i]->screen_offset * mainwindow->pixelsizefactor * signalcomp[i]->voltpercm, signalcomp[i]->physdimension); painter->fillRect(92, baseline, 190, 12, backgroundcolor); painter->setPen((Qt::GlobalColor)signalcomp[i]->color); painter->drawText(95, baseline + 10, string); } if(signalcomp[i]->hasgaintracking) { snprintf(string, 128, "gain: %f %s/cm", signalcomp[i]->voltpercm, signalcomp[i]->physdimension); painter->fillRect(92, baseline, 190, 12, backgroundcolor); painter->setPen((Qt::GlobalColor)signalcomp[i]->color); painter->drawText(95, baseline + 10, string); } } vertical_distance = h / (signalcomps + 1); for(i=0; ialias[0] != 0) { painter->fillRect(2, baseline - 20, strlen(signalcomp[i]->alias) * 7 + 6, 12, backgroundcolor); } else { painter->fillRect(2, baseline - 20, strlen(signalcomp[i]->signallabel) * 7 + 6, 12, backgroundcolor); } painter->setPen((Qt::GlobalColor)signalcomp[i]->color); if(signalcomp[i]->alias[0] != 0) { painter->drawText(5, baseline - 10, signalcomp[i]->alias); } else { painter->drawText(5, baseline - 10, signalcomp[i]->signallabel); } if(signalcomp[i]->hasruler) { floating_ruler(painter, ruler_x_position, ruler_y_position, signalcomp[i], print_linewidth); } } if(draw_zoom_rectangle) { special_pen->setColor(mouse_rect_color); painter->setPen(*special_pen); painter->drawRect(mouse_press_coordinate_x, mouse_press_coordinate_y, mouse_x - mouse_press_coordinate_x, mouse_y - mouse_press_coordinate_y); } painter->setPen(text_color); if(printing) { painter->drawText((int)(8.0 * printsize_y_factor), h - (int)(4.0 * printsize_y_factor), mainwindow->viewtime_string); painter->drawText(w - (int)(60.0 * printsize_y_factor), h - (int)(4.0 * printsize_y_factor), mainwindow->pagetime_string); } else { painter->fillRect(5, h - 14, 180, 12, backgroundcolor); painter->drawText(8, h - 4, mainwindow->viewtime_string); painter->fillRect(w - 63, h - 14, 60, 12, backgroundcolor); painter->drawText(w - 60, h - 4, mainwindow->pagetime_string); } } void ViewCurve::drawCurve_stage_1(QPainter *painter, int w_width, int w_height, int print_linewidth) { int i, j, k, n, x1, y1, x2, y2, signalcomps, baseline, value, minimum, maximum, runin_samples, stat_zero_crossing=0; char *viewbuf; long long s, s2; double dig_value=0.0, f_tmp=0.0; struct signalcompblock **signalcomp; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; if(mainwindow->exit_in_progress) { if(graphicBuf!=NULL) { free(graphicBuf); graphicBuf = NULL; } return; } for(i=0; isignalcomps; signalcomp = mainwindow->signalcomp; viewbuf = mainwindow->viewbuf; linear_interpol = mainwindow->linear_interpol; painter_pixelsizefactor = 1.0 / mainwindow->pixelsizefactor; if(!w_width||!w_height) { w = width(); h = height(); printsize_x_factor = 1.0; printsize_y_factor = 1.0; printing = 0; } else { w = w_width; h = w_height; printsize_x_factor = ((double)w_width) / ((double)width()); printsize_y_factor = ((double)w_height) / ((double)height()); painter_pixelsizefactor *= printsize_y_factor; printing = 1; } for(i=0; isamples_on_screen < (w / 2)) { signalcomp[i]->sample_pixel_ratio = (((double)signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record / signalcomp[i]->edfhdr->data_record_duration) * ((double)mainwindow->pagetime / (double)TIME_DIMENSION)) / (double)w; } else { signalcomp[i]->sample_pixel_ratio = (double)signalcomp[i]->samples_on_screen / (double)w; } } if((viewbuf==NULL)||(screensamples==NULL)) { if(graphicBuf!=NULL) { free(graphicBuf); graphicBuf = NULL; } update(); return; } if((graphicBuf==NULL)||(graphicBufWidth!=w)) { if(graphicBuf!=NULL) { free(graphicBuf); } graphicBuf = (struct graphicBufStruct *)malloc(sizeof(struct graphicBufStruct) * w * 2 + 4); graphicBufWidth = w; } if(graphicBuf==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); messagewindow.exec(); return; } if(mainwindow->use_threads) { n = cpu_cnt; if(signalcomps < n) { n = signalcomps; } // for(i=0; iinit_vars(mainwindow, &signalcomp[0], i, signalcomps, viewbuf, w, h, &screensamples[0], printing, graphicBuf, printsize_x_factor, printsize_y_factor, &crosshair_1, &crosshair_2, cpu_cnt, linear_interpol); thr[i]->start(); } for(i=0; iwait(); } } else { for(i=0; imax_dig_value = -2147483647; signalcomp[i]->min_dig_value = 2147483647; signalcomp[i]->stat_cnt = 0; signalcomp[i]->stat_zero_crossing_cnt = 0; signalcomp[i]->stat_sum = 0.0; signalcomp[i]->stat_sum_sqr = 0.0; signalcomp[i]->stat_sum_rectified = 0.0; baseline = h / (signalcomps + 1); baseline *= (i + 1); signalcomp[i]->pixels_shift = signalcomp[i]->sample_timeoffset_part / signalcomp[i]->sample_pixel_ratio; for(s=signalcomp[i]->sample_start; ssamples_on_screen; s++) { if(s>=signalcomp[i]->sample_stop) break; dig_value = 0.0; s2 = s + signalcomp[i]->sample_timeoffset - signalcomp[i]->sample_start; for(j=0; jnum_of_signals; j++) { if(signalcomp[i]->edfhdr->bdf) { var.two[0] = *((unsigned short *)( viewbuf + signalcomp[i]->viewbufoffset + (signalcomp[i]->edfhdr->recordsize * (s2 / signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record)) + signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].buf_offset + ((s2 % signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record) * 3))); var.four[2] = *((unsigned char *)( viewbuf + signalcomp[i]->viewbufoffset + (signalcomp[i]->edfhdr->recordsize * (s2 / signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record)) + signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].buf_offset + ((s2 % signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record) * 3) + 2)); if(var.four[2]&0x80) { var.four[3] = 0xff; } else { var.four[3] = 0x00; } f_tmp = var.one_signed; } if(signalcomp[i]->edfhdr->edf) { f_tmp = *(((short *)( viewbuf + signalcomp[i]->viewbufoffset + (signalcomp[i]->edfhdr->recordsize * (s2 / signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record)) + signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].buf_offset)) + (s2 % signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].smp_per_record)); } f_tmp += signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[j]].offset; f_tmp *= signalcomp[i]->factor[j]; dig_value += f_tmp; } if(signalcomp[i]->spike_filter) { if(s==signalcomp[i]->sample_start) { if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime<=0) { reset_spike_filter(signalcomp[i]->spike_filter); } else { spike_filter_restore_buf(signalcomp[i]->spike_filter); } } dig_value = run_spike_filter(dig_value, signalcomp[i]->spike_filter); } for(k=0; kfilter_cnt; k++) { if(s==signalcomp[i]->sample_start) { if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime==0) { reset_filter(dig_value, signalcomp[i]->filter[k]); } else { signalcomp[i]->filter[k]->old_input = signalcomp[i]->filterpreset_a[k]; signalcomp[i]->filter[k]->old_output = signalcomp[i]->filterpreset_b[k]; } } dig_value = first_order_filter(dig_value, signalcomp[i]->filter[k]); } for(k=0; kravg_filter_cnt; k++) { if(s==signalcomp[i]->sample_start) { if((mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime <= 0) && signalcomp[i]->ravg_filter_setup[k]) { reset_ravg_filter(dig_value, signalcomp[i]->ravg_filter[k]); } else { ravg_filter_restore_buf(signalcomp[i]->ravg_filter[k]); } signalcomp[i]->ravg_filter_setup[k] = 0; } dig_value = run_ravg_filter(dig_value, signalcomp[i]->ravg_filter[k]); } for(k=0; kfidfilter_cnt; k++) { if(s==signalcomp[i]->sample_start) { if((mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime <= 0) && signalcomp[i]->fidfilter_setup[k]) { runin_samples = (signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].smp_per_record / signalcomp[i]->edfhdr->data_record_duration) / signalcomp[i]->fidfilter_freq[k]; runin_samples *= 26; if(runin_samples < 10) { runin_samples = 10; } for(n=0; nfidfuncp[k](signalcomp[i]->fidbuf[k], dig_value); } memcpy(signalcomp[i]->fidbuf2[k], signalcomp[i]->fidbuf[k], fid_run_bufsize(signalcomp[i]->fid_run[k])); } else { memcpy(signalcomp[i]->fidbuf[k], signalcomp[i]->fidbuf2[k], fid_run_bufsize(signalcomp[i]->fid_run[k])); } signalcomp[i]->fidfilter_setup[k] = 0; } dig_value = signalcomp[i]->fidfuncp[k](signalcomp[i]->fidbuf[k], dig_value); } if(signalcomp[i]->ecg_filter != NULL) { if(s==signalcomp[i]->sample_start) { if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime <= 0LL) { reset_ecg_filter(signalcomp[i]->ecg_filter); } else { ecg_filter_restore_buf(signalcomp[i]->ecg_filter); } } dig_value = run_ecg_filter(dig_value, signalcomp[i]->ecg_filter); } if(signalcomp[i]->zratio_filter != NULL) { if(s==signalcomp[i]->sample_start) { if(mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime <= 0LL) { reset_zratio_filter(signalcomp[i]->zratio_filter); } else { zratio_filter_restore_buf(signalcomp[i]->zratio_filter); } } dig_value = run_zratio_filter(dig_value, signalcomp[i]->zratio_filter); } if(printing) { value = (int)(dig_value * signalcomp[i]->sensitivity[0] * printsize_y_factor) * signalcomp[i]->polarity; } else { value = (int)(dig_value * signalcomp[i]->sensitivity[0]) * signalcomp[i]->polarity; signalcomp[i]->stat_cnt++; signalcomp[i]->stat_sum += dig_value; signalcomp[i]->stat_sum_sqr += ((dig_value) * (dig_value)); if(dig_value < 0) { signalcomp[i]->stat_sum_rectified += (dig_value * -1.0); } else { signalcomp[i]->stat_sum_rectified += dig_value; } if(s==signalcomp[i]->sample_start) { if(dig_value < 0.0) { stat_zero_crossing = 0; } else { stat_zero_crossing = 1; } } else { if(dig_value < 0.0) { if(stat_zero_crossing) { stat_zero_crossing = 0; signalcomp[i]->stat_zero_crossing_cnt++; } } else { if(!stat_zero_crossing) { stat_zero_crossing = 1; signalcomp[i]->stat_zero_crossing_cnt++; } } } } if(((int)dig_value)>signalcomp[i]->max_dig_value) signalcomp[i]->max_dig_value = dig_value; if(((int)dig_value)min_dig_value) signalcomp[i]->min_dig_value = dig_value; if(printing) { value = baseline - value + (int)(signalcomp[i]->screen_offset * printsize_y_factor); } else { value = baseline - value + signalcomp[i]->screen_offset; } if(s>=signalcomp[i]->sample_start) { x1 = (int)((double)s / signalcomp[i]->sample_pixel_ratio); y1 = signalcomp[i]->oldvalue; x2 = (int)(((double)s + 1.0) / signalcomp[i]->sample_pixel_ratio); y2 = value; if(signalcomp[i]->samples_on_screen < (w / 2)) { if(linear_interpol) { x1 = (int)(((double)s - 1.0) / signalcomp[i]->sample_pixel_ratio); x2 = (int)((double)s / signalcomp[i]->sample_pixel_ratio); graphicBuf[screensamples[i]].graphicLine[i].x1 = x1 - signalcomp[i]->pixels_shift; graphicBuf[screensamples[i]].graphicLine[i].y1 = y1; graphicBuf[screensamples[i]].graphicLine[i].x2 = x2 - signalcomp[i]->pixels_shift; graphicBuf[screensamples[i]].graphicLine[i].y2 = y2; } else { graphicBuf[screensamples[i]].graphicLine[i].x1 = x1 - signalcomp[i]->pixels_shift; graphicBuf[screensamples[i]].graphicLine[i].y1 = y2; graphicBuf[screensamples[i]].graphicLine[i].x2 = x2 - signalcomp[i]->pixels_shift; graphicBuf[screensamples[i]].graphicLine[i].y2 = y2; if(screensamples[i]) { screensamples[i]++; graphicBuf[screensamples[i]].graphicLine[i].x1 = x1 - signalcomp[i]->pixels_shift; graphicBuf[screensamples[i]].graphicLine[i].y1 = y1; graphicBuf[screensamples[i]].graphicLine[i].x2 = x1 - signalcomp[i]->pixels_shift; graphicBuf[screensamples[i]].graphicLine[i].y2 = y2; } } screensamples[i]++; } else { if(!screensamples[i]) { graphicBuf[screensamples[i]].graphicLine[i].x1 = x1; graphicBuf[screensamples[i]].graphicLine[i].y1 = y1; graphicBuf[screensamples[i]].graphicLine[i].x2 = x2; graphicBuf[screensamples[i]].graphicLine[i].y2 = y2; screensamples[i]++; } else { if((x1==x2)&&(x1==graphicBuf[screensamples[i]-1].graphicLine[i].x1)&& (graphicBuf[screensamples[i]-1].graphicLine[i].x1==graphicBuf[screensamples[i]-1].graphicLine[i].x2)) { maximum = y1; if(y2>maximum) maximum = y2; if(graphicBuf[screensamples[i]-1].graphicLine[i].y1>maximum) maximum = graphicBuf[screensamples[i]-1].graphicLine[i].y1; if(graphicBuf[screensamples[i]-1].graphicLine[i].y2>maximum) maximum = graphicBuf[screensamples[i]-1].graphicLine[i].y2; minimum = y1; if(y2oldvalue = value; if(signalcomp[i]->hascursor1) { if(printing) { if(s==((int)((double)(crosshair_1.x_position * printsize_x_factor + (double)signalcomp[i]->pixels_shift) * signalcomp[i]->sample_pixel_ratio))) { crosshair_1.y_value = value; crosshair_1.value = dig_value * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue; crosshair_1.time = mainwindow->edfheaderlist[signalcomp[i]->filenum]->l_starttime + mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + signalcomp[i]->edfhdr->starttime_offset + (long long)(((double)mainwindow->pagetime / ((double)w / printsize_x_factor)) * (double)crosshair_1.x_position); crosshair_1.time_relative = mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + (long long)(((double)mainwindow->pagetime / ((double)w / printsize_x_factor)) * (double)crosshair_1.x_position); } } else { if(s==((int)((double)(crosshair_1.x_position + signalcomp[i]->pixels_shift) * signalcomp[i]->sample_pixel_ratio))) { crosshair_1.y_value = value; crosshair_1.value = dig_value * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue; crosshair_1.time = mainwindow->edfheaderlist[signalcomp[i]->filenum]->l_starttime + mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + signalcomp[i]->edfhdr->starttime_offset + (long long)(((double)mainwindow->pagetime / (double)w) * (double)crosshair_1.x_position); crosshair_1.time_relative = mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + (long long)(((double)mainwindow->pagetime / (double)w) * (double)crosshair_1.x_position); } } } if(signalcomp[i]->hascursor2) { if(printing) { if(s==((int)((double)(crosshair_2.x_position * printsize_x_factor + (double)signalcomp[i]->pixels_shift) * signalcomp[i]->sample_pixel_ratio))) { crosshair_2.y_value = value; crosshair_2.value = dig_value * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue; crosshair_2.time = mainwindow->edfheaderlist[signalcomp[i]->filenum]->l_starttime + mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + signalcomp[i]->edfhdr->starttime_offset + (long long)(((double)mainwindow->pagetime / ((double)w / printsize_x_factor)) * (double)crosshair_2.x_position); crosshair_2.time_relative = mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + (long long)(((double)mainwindow->pagetime / ((double)w / printsize_x_factor)) * (double)crosshair_2.x_position); } } else { if(s==((int)((double)(crosshair_2.x_position + signalcomp[i]->pixels_shift) * signalcomp[i]->sample_pixel_ratio))) { crosshair_2.y_value = value; crosshair_2.value = dig_value * signalcomp[i]->edfhdr->edfparam[signalcomp[i]->edfsignal[0]].bitvalue; crosshair_2.time = mainwindow->edfheaderlist[signalcomp[i]->filenum]->l_starttime + mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + signalcomp[i]->edfhdr->starttime_offset + (long long)(((double)mainwindow->pagetime / (double)w) * (double)crosshair_2.x_position); crosshair_2.time_relative = mainwindow->edfheaderlist[signalcomp[i]->filenum]->viewtime + (long long)(((double)mainwindow->pagetime / (double)w) * (double)crosshair_2.x_position); } } } } } } if(printing) { drawCurve_stage_2(painter, w_width, w_height, print_linewidth); } else { update(); } } void drawCurve_stage_1_thread::init_vars(UI_Mainwindow *mainwindow_a, struct signalcompblock **signalcomp_a, int i_a, int signalcomps_a, char *viewbuf_a, int w_a, int h_a, int *screensamples_a, int printing_a, struct graphicBufStruct *graphicBuf_a, double printsize_x_factor_a, double printsize_y_factor_a, struct crossHairStruct *crosshair_1_a, struct crossHairStruct *crosshair_2_a, int cpu_cnt_a, int linear_interpol_a) { mainwindow = mainwindow_a; signalcomp_b = signalcomp_a; i = i_a; signalcomps = signalcomps_a; viewbuf = viewbuf_a; w = w_a; h = h_a; screensamples_b = screensamples_a; printing = printing_a; graphicBuf = graphicBuf_a; printsize_x_factor = printsize_x_factor_a; printsize_y_factor = printsize_y_factor_a; crosshair_1 = crosshair_1_a; crosshair_2 = crosshair_2_a; cpu_cnt = cpu_cnt_a; linear_interpol = linear_interpol_a; // printf("init_vars(): i is %i signalcomp_b is %08X screensamples_b is %08X\n------------------------\n", // i, (int)signalcomp_b[i], (int)screensamples_b); } void drawCurve_stage_1_thread::run() { int j, k, n, x1, y1, x2, y2, baseline, value, minimum, maximum, runin_samples, stat_zero_crossing; long long s, s2; double dig_value, f_tmp; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; for(; i < signalcomps; i += cpu_cnt) { // printf("i is %i cpu_cnt is %i\n", i, cpu_cnt); screensamples = &screensamples_b[i]; signalcomp = signalcomp_b[i]; // printf("i is %i signalcomp is %08X screensamples is %08X\n", // i, (int)signalcomp, (int)screensamples); f_tmp = 0.0; dig_value=0.0; stat_zero_crossing=0; signalcomp->max_dig_value = -2147483647; signalcomp->min_dig_value = 2147483647; signalcomp->stat_cnt = 0; signalcomp->stat_zero_crossing_cnt = 0; signalcomp->stat_sum = 0.0; signalcomp->stat_sum_sqr = 0.0; signalcomp->stat_sum_rectified = 0.0; baseline = h / (signalcomps + 1); baseline *= (i + 1); signalcomp->pixels_shift = signalcomp->sample_timeoffset_part / signalcomp->sample_pixel_ratio; for(s=signalcomp->sample_start; ssamples_on_screen; s++) { if(s>=signalcomp->sample_stop) break; dig_value = 0.0; s2 = s + signalcomp->sample_timeoffset - signalcomp->sample_start; for(j=0; jnum_of_signals; j++) { if(signalcomp->edfhdr->bdf) { var.two[0] = *((unsigned short *)( viewbuf + signalcomp->viewbufoffset + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)) + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset + ((s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record) * 3))); var.four[2] = *((unsigned char *)( viewbuf + signalcomp->viewbufoffset + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)) + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset + ((s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record) * 3) + 2)); if(var.four[2]&0x80) { var.four[3] = 0xff; } else { var.four[3] = 0x00; } f_tmp = var.one_signed; } if(signalcomp->edfhdr->edf) { f_tmp = *(((short *)( viewbuf + signalcomp->viewbufoffset + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)) + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset)) + (s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)); } f_tmp += signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].offset; f_tmp *= signalcomp->factor[j]; dig_value += f_tmp; } if(signalcomp->spike_filter) { if(s==signalcomp->sample_start) { if(mainwindow->edfheaderlist[signalcomp->filenum]->viewtime<=0) { reset_spike_filter(signalcomp->spike_filter); } else { spike_filter_restore_buf(signalcomp->spike_filter); } } dig_value = run_spike_filter(dig_value, signalcomp->spike_filter); } for(k=0; kfilter_cnt; k++) { if(s==signalcomp->sample_start) { if(mainwindow->edfheaderlist[signalcomp->filenum]->viewtime==0) { reset_filter(dig_value, signalcomp->filter[k]); } else { signalcomp->filter[k]->old_input = signalcomp->filterpreset_a[k]; signalcomp->filter[k]->old_output = signalcomp->filterpreset_b[k]; } } dig_value = first_order_filter(dig_value, signalcomp->filter[k]); } for(k=0; kravg_filter_cnt; k++) { if(s==signalcomp->sample_start) { if((mainwindow->edfheaderlist[signalcomp->filenum]->viewtime <= 0) && signalcomp->ravg_filter_setup[k]) { reset_ravg_filter(dig_value, signalcomp->ravg_filter[k]); } else { ravg_filter_restore_buf(signalcomp->ravg_filter[k]); } signalcomp->ravg_filter_setup[k] = 0; } dig_value = run_ravg_filter(dig_value, signalcomp->ravg_filter[k]); } for(k=0; kfidfilter_cnt; k++) { if(s==signalcomp->sample_start) { if((mainwindow->edfheaderlist[signalcomp->filenum]->viewtime <= 0) && signalcomp->fidfilter_setup[k]) { runin_samples = (signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].smp_per_record / signalcomp->edfhdr->data_record_duration) / signalcomp->fidfilter_freq[k]; runin_samples *= 26; if(runin_samples < 10) { runin_samples = 10; } for(n=0; nfidfuncp[k](signalcomp->fidbuf[k], dig_value); } memcpy(signalcomp->fidbuf2[k], signalcomp->fidbuf[k], fid_run_bufsize(signalcomp->fid_run[k])); } else { memcpy(signalcomp->fidbuf[k], signalcomp->fidbuf2[k], fid_run_bufsize(signalcomp->fid_run[k])); } signalcomp->fidfilter_setup[k] = 0; } dig_value = signalcomp->fidfuncp[k](signalcomp->fidbuf[k], dig_value); } if(signalcomp->ecg_filter != NULL) { if(s==signalcomp->sample_start) { if(mainwindow->edfheaderlist[signalcomp->filenum]->viewtime <= 0LL) { reset_ecg_filter(signalcomp->ecg_filter); } else { ecg_filter_restore_buf(signalcomp->ecg_filter); } } dig_value = run_ecg_filter(dig_value, signalcomp->ecg_filter); } if(signalcomp->zratio_filter != NULL) { if(s==signalcomp->sample_start) { if(mainwindow->edfheaderlist[signalcomp->filenum]->viewtime <= 0LL) { reset_zratio_filter(signalcomp->zratio_filter); } else { zratio_filter_restore_buf(signalcomp->zratio_filter); } } dig_value = run_zratio_filter(dig_value, signalcomp->zratio_filter); } if(printing) { value = (int)(dig_value * signalcomp->sensitivity[0] * printsize_y_factor) * signalcomp->polarity; } else { value = (int)(dig_value * signalcomp->sensitivity[0]) * signalcomp->polarity; signalcomp->stat_cnt++; signalcomp->stat_sum += dig_value; signalcomp->stat_sum_sqr += ((dig_value) * (dig_value)); if(dig_value < 0) { signalcomp->stat_sum_rectified += (dig_value * -1.0); } else { signalcomp->stat_sum_rectified += dig_value; } if(s==signalcomp->sample_start) { if(dig_value < 0.0) { stat_zero_crossing = 0; } else { stat_zero_crossing = 1; } } else { if(dig_value < 0.0) { if(stat_zero_crossing) { stat_zero_crossing = 0; signalcomp->stat_zero_crossing_cnt++; } } else { if(!stat_zero_crossing) { stat_zero_crossing = 1; signalcomp->stat_zero_crossing_cnt++; } } } } if(dig_value > signalcomp->max_dig_value) signalcomp->max_dig_value = dig_value; if(dig_value < signalcomp->min_dig_value) signalcomp->min_dig_value = dig_value; if(printing) { value = baseline - value + (int)(signalcomp->screen_offset * printsize_y_factor); } else { value = baseline - value + signalcomp->screen_offset; } if(s>=signalcomp->sample_start) { x1 = (int)((double)s / signalcomp->sample_pixel_ratio); y1 = signalcomp->oldvalue; x2 = (int)(((double)s + 1.0) / signalcomp->sample_pixel_ratio); y2 = value; if(signalcomp->samples_on_screen < (w / 2)) { if(linear_interpol) { x1 = (int)(((double)s - 1.0) / signalcomp->sample_pixel_ratio); x2 = (int)((double)s / signalcomp->sample_pixel_ratio); graphicBuf[*screensamples].graphicLine[i].x1 = x1 - signalcomp->pixels_shift; graphicBuf[*screensamples].graphicLine[i].y1 = y1; graphicBuf[*screensamples].graphicLine[i].x2 = x2 - signalcomp->pixels_shift; graphicBuf[*screensamples].graphicLine[i].y2 = y2; } else { graphicBuf[*screensamples].graphicLine[i].x1 = x1 - signalcomp->pixels_shift; graphicBuf[*screensamples].graphicLine[i].y1 = y2; graphicBuf[*screensamples].graphicLine[i].x2 = x2 - signalcomp->pixels_shift; graphicBuf[*screensamples].graphicLine[i].y2 = y2; if(*screensamples) { (*screensamples)++; graphicBuf[*screensamples].graphicLine[i].x1 = x1 - signalcomp->pixels_shift; graphicBuf[*screensamples].graphicLine[i].y1 = y1; graphicBuf[*screensamples].graphicLine[i].x2 = x1 - signalcomp->pixels_shift; graphicBuf[*screensamples].graphicLine[i].y2 = y2; } } (*screensamples)++; } else { if(!(*screensamples)) { graphicBuf[*screensamples].graphicLine[i].x1 = x1; graphicBuf[*screensamples].graphicLine[i].y1 = y1; graphicBuf[*screensamples].graphicLine[i].x2 = x2; graphicBuf[*screensamples].graphicLine[i].y2 = y2; (*screensamples)++; } else { if((x1==x2)&&(x1==graphicBuf[(*screensamples)-1].graphicLine[i].x1)&& (graphicBuf[(*screensamples)-1].graphicLine[i].x1==graphicBuf[(*screensamples)-1].graphicLine[i].x2)) { maximum = y1; if(y2>maximum) maximum = y2; if(graphicBuf[(*screensamples)-1].graphicLine[i].y1>maximum) maximum = graphicBuf[(*screensamples)-1].graphicLine[i].y1; if(graphicBuf[(*screensamples)-1].graphicLine[i].y2>maximum) maximum = graphicBuf[(*screensamples)-1].graphicLine[i].y2; minimum = y1; if(y2oldvalue = value; if(signalcomp->hascursor1) { if(printing) { if(s==((int)((double)(crosshair_1->x_position * printsize_x_factor + (double)signalcomp->pixels_shift) * signalcomp->sample_pixel_ratio))) { crosshair_1->y_value = value; crosshair_1->value = dig_value * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue; crosshair_1->time = mainwindow->edfheaderlist[signalcomp->filenum]->l_starttime + mainwindow->edfheaderlist[signalcomp->filenum]->viewtime + signalcomp->edfhdr->starttime_offset + (long long)(((double)mainwindow->pagetime / ((double)w / printsize_x_factor)) * (double)crosshair_1->x_position); crosshair_1->time_relative = mainwindow->edfheaderlist[signalcomp->filenum]->viewtime + (long long)(((double)mainwindow->pagetime / ((double)w / printsize_x_factor)) * (double)crosshair_1->x_position); } } else { if(s==((int)((double)(crosshair_1->x_position + signalcomp->pixels_shift) * signalcomp->sample_pixel_ratio))) { crosshair_1->y_value = value; crosshair_1->value = dig_value * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue; crosshair_1->time = mainwindow->edfheaderlist[signalcomp->filenum]->l_starttime + mainwindow->edfheaderlist[signalcomp->filenum]->viewtime + signalcomp->edfhdr->starttime_offset + (long long)(((double)mainwindow->pagetime / (double)w) * (double)crosshair_1->x_position); crosshair_1->time_relative = mainwindow->edfheaderlist[signalcomp->filenum]->viewtime + (long long)(((double)mainwindow->pagetime / (double)w) * (double)crosshair_1->x_position); } } } if(signalcomp->hascursor2) { if(printing) { if(s==((int)((double)(crosshair_2->x_position * printsize_x_factor + (double)signalcomp->pixels_shift) * signalcomp->sample_pixel_ratio))) { crosshair_2->y_value = value; crosshair_2->value = dig_value * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue; crosshair_2->time = mainwindow->edfheaderlist[signalcomp->filenum]->l_starttime + mainwindow->edfheaderlist[signalcomp->filenum]->viewtime + signalcomp->edfhdr->starttime_offset + (long long)(((double)mainwindow->pagetime / ((double)w / printsize_x_factor)) * (double)crosshair_2->x_position); crosshair_2->time_relative = mainwindow->edfheaderlist[signalcomp->filenum]->viewtime + (long long)(((double)mainwindow->pagetime / ((double)w / printsize_x_factor)) * (double)crosshair_2->x_position); } } else { if(s==((int)((double)(crosshair_2->x_position + signalcomp->pixels_shift) * signalcomp->sample_pixel_ratio))) { crosshair_2->y_value = value; crosshair_2->value = dig_value * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue; crosshair_2->time = mainwindow->edfheaderlist[signalcomp->filenum]->l_starttime + mainwindow->edfheaderlist[signalcomp->filenum]->viewtime + signalcomp->edfhdr->starttime_offset + (long long)(((double)mainwindow->pagetime / (double)w) * (double)crosshair_2->x_position); crosshair_2->time_relative = mainwindow->edfheaderlist[signalcomp->filenum]->viewtime + (long long)(((double)mainwindow->pagetime / (double)w) * (double)crosshair_2->x_position); } } } } } } void ViewCurve::exec_sidemenu(int signal_nr_intern) { int i; char str[32]={0,0,0,0,0,0}; signal_nr = signal_nr_intern; sidemenu = new QDialog(this); sidemenu->setMinimumSize(190, 515); sidemenu->setMaximumSize(190, 515); sidemenu->setWindowTitle("Signal"); sidemenu->setModal(true); sidemenu->setAttribute(Qt::WA_DeleteOnClose, true); SidemenuLabel = new QLabel(sidemenu); SidemenuLabel->setGeometry(45, 5, 100, 25); SidemenuLabel->setText(mainwindow->signalcomp[signal_nr]->signallabel); AliasLabel = new QLabel(sidemenu); AliasLabel->setGeometry(5, 35, 35, 25); AliasLabel->setText("Alias"); AliasLineEdit = new QLineEdit(sidemenu); AliasLineEdit->setGeometry(45, 35, 140, 25); AliasLineEdit->setText(mainwindow->signalcomp[signal_nr]->alias); AliasLineEdit->setMaxLength(16); AmpLabel = new QLabel(sidemenu); AmpLabel->setGeometry(5, 65, 35, 25); AmpLabel->setText("Ampl."); OffsetLabel = new QLabel(sidemenu); OffsetLabel->setGeometry(5, 95, 35, 25); OffsetLabel->setText("Offset"); ScaleBox = new QDoubleSpinBox(sidemenu); ScaleBox->setGeometry(45, 65, 140, 25); ScaleBox->setDecimals(8); ScaleBox->setMaximum(1000000.0); ScaleBox->setMinimum(0.0000001); if(mainwindow->signalcomp[signal_nr]->edfhdr->edfparam[mainwindow->signalcomp[signal_nr]->edfsignal[0]].bitvalue < 0.0) { ScaleBox->setValue(mainwindow->signalcomp[signal_nr]->voltpercm * -1.0); } else { ScaleBox->setValue(mainwindow->signalcomp[signal_nr]->voltpercm); } strcpy(str, mainwindow->signalcomp[signal_nr]->physdimension); for(i=1; i<4; i++) { if(str[i]==' ') break; } strcpy(str + i, "/cm"); ScaleBox->setSuffix(str); ScaleBox2 = new QDoubleSpinBox(sidemenu); ScaleBox2->setGeometry(45, 95, 140, 25); ScaleBox2->setDecimals(8); ScaleBox2->setMaximum(1000000.0); ScaleBox2->setMinimum(-1000000.0); ScaleBox2->setValue(-mainwindow->signalcomp[signal_nr]->screen_offset * mainwindow->pixelsizefactor * mainwindow->signalcomp[signal_nr]->voltpercm); ScaleBox2->setSuffix(mainwindow->signalcomp[signal_nr]->physdimension); sidemenuButton1 = new QPushButton(sidemenu); sidemenuButton1->setGeometry(45, 125, 100, 25); sidemenuButton1->setText("Ruler"); sidemenuButton2 = new QPushButton(sidemenu); sidemenuButton2->setGeometry(45, 155, 100, 25); sidemenuButton2->setText("Crosshair"); sidemenuButton3 = new QPushButton(sidemenu); sidemenuButton3->setGeometry(45, 185, 100, 25); sidemenuButton3->setText("Fit to pane"); sidemenuButton4 = new QPushButton(sidemenu); sidemenuButton4->setGeometry(45, 215, 100, 25); sidemenuButton4->setText("Color"); sidemenuButton5 = new QPushButton(sidemenu); sidemenuButton5->setGeometry(45, 245, 100, 25); sidemenuButton5->setText("Invert"); sidemenuButton6 = new QPushButton(sidemenu); sidemenuButton6->setGeometry(45, 275, 100, 25); sidemenuButton6->setText("Spectrum"); sidemenuButton7 = new QPushButton(sidemenu); sidemenuButton7->setGeometry(45, 305, 100, 25); sidemenuButton7->setText("Z-EEG"); sidemenuButton8 = new QPushButton(sidemenu); sidemenuButton8->setGeometry(45, 335, 100, 25); sidemenuButton8->setText("Remove filter"); sidemenuButton9 = new QPushButton(sidemenu); sidemenuButton9->setGeometry(45, 365, 100, 25); sidemenuButton9->setText("Remove signal"); sidemenuButton10 = new QPushButton(sidemenu); sidemenuButton10->setGeometry(45, 395, 100, 25); sidemenuButton10->setText("Adjust filter"); sidemenuButton11 = new QPushButton(sidemenu); sidemenuButton11->setGeometry(45, 425, 100, 25); sidemenuButton11->setText("Statistics"); sidemenuButton12 = new QPushButton(sidemenu); sidemenuButton12->setGeometry(45, 455, 100, 25); sidemenuButton12->setText("Heart Rate"); sidemenuButton13 = new QPushButton(sidemenu); sidemenuButton13->setGeometry(45, 485, 100, 25); sidemenuButton13->setText("Close"); QObject::connect(ScaleBox, SIGNAL(valueChanged(double)), this, SLOT(ScaleBoxChanged(double))); QObject::connect(ScaleBox2, SIGNAL(valueChanged(double)), this, SLOT(ScaleBox2Changed(double))); QObject::connect(sidemenuButton1, SIGNAL(clicked()), this, SLOT(RulerButton())); QObject::connect(sidemenuButton2, SIGNAL(clicked()), this, SLOT(CrosshairButton())); QObject::connect(sidemenuButton3, SIGNAL(clicked()), this, SLOT(FittopaneButton())); QObject::connect(sidemenuButton4, SIGNAL(clicked()), this, SLOT(ColorButton())); QObject::connect(sidemenuButton5, SIGNAL(clicked()), this, SLOT(signalInvert())); QObject::connect(sidemenuButton6, SIGNAL(clicked()), this, SLOT(FreqSpecButton())); QObject::connect(sidemenuButton7, SIGNAL(clicked()), this, SLOT(Z_scoringButton())); QObject::connect(sidemenuButton8, SIGNAL(clicked()), this, SLOT(RemovefilterButton())); QObject::connect(sidemenuButton9, SIGNAL(clicked()), this, SLOT(RemovesignalButton())); QObject::connect(sidemenuButton10, SIGNAL(clicked()), this, SLOT(AdjustFilterButton())); QObject::connect(sidemenuButton11, SIGNAL(clicked()), this, SLOT(StatisticsButton())); QObject::connect(sidemenuButton12, SIGNAL(clicked()), this, SLOT(ECGdetectButton())); QObject::connect(sidemenuButton13, SIGNAL(clicked()), this, SLOT(sidemenu_close())); QObject::connect(AliasLineEdit, SIGNAL(returnPressed()), this, SLOT(sidemenu_close())); sidemenu->exec(); } void ViewCurve::sidemenu_close() { if(AliasLineEdit->isModified() == true) { strncpy(mainwindow->signalcomp[signal_nr]->alias, AliasLineEdit->text().toLatin1().data(), 16); mainwindow->signalcomp[signal_nr]->alias[16] = 0; latin1_to_ascii(mainwindow->signalcomp[signal_nr]->alias, 16); remove_trailing_spaces(mainwindow->signalcomp[signal_nr]->alias); remove_leading_spaces(mainwindow->signalcomp[signal_nr]->alias); } sidemenu->close(); } void ViewCurve::signalInvert() { sidemenu->close(); if(!mainwindow->signalcomps) { return; } if(signal_nr>(mainwindow->signalcomps - 1)) { return; } mainwindow->signalcomp[signal_nr]->polarity *= -1; mainwindow->signalcomp[signal_nr]->screen_offset *= -1; mainwindow->setup_viewbuf(); } void ViewCurve::ECGdetectButton() { int i; struct signalcompblock *newsignalcomp; sidemenu->close(); if(!mainwindow->signalcomps) { return; } if(signal_nr>(mainwindow->signalcomps - 1)) { return; } if(mainwindow->signalcomp[signal_nr]->zratio_filter != NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Z-ratio is active for this signal!"); messagewindow.exec(); return; } if(mainwindow->signalcomp[signal_nr]->ecg_filter != NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Heartrate detection is already active for this signal!"); messagewindow.exec(); return; } newsignalcomp = mainwindow->create_signalcomp_copy(mainwindow->signalcomp[signal_nr]); if(newsignalcomp == NULL) { return; } newsignalcomp->ecg_filter = create_ecg_filter(newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].smp_per_record / newsignalcomp->edfhdr->data_record_duration, newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].bitvalue, mainwindow->powerlinefreq); strcpy(newsignalcomp->signallabel_bu, newsignalcomp->signallabel); newsignalcomp->signallabellen_bu = newsignalcomp->signallabellen; strcpy(newsignalcomp->signallabel, "HR"); newsignalcomp->signallabellen = strlen(newsignalcomp->signallabel); strcpy(newsignalcomp->physdimension_bu, newsignalcomp->physdimension); strcpy(newsignalcomp->physdimension, "bpm"); newsignalcomp->alias[0] = 0; if(newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].bitvalue < 0.0) { for(i=0; inum_of_signals; i++) { newsignalcomp->sensitivity[i] = newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[i]].bitvalue / -5.0 / mainwindow->pixelsizefactor; } newsignalcomp->voltpercm = -5.0; } else { for(i=0; inum_of_signals; i++) { newsignalcomp->sensitivity[i] = newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[i]].bitvalue / 5.0 / mainwindow->pixelsizefactor; } newsignalcomp->voltpercm = 5.0; } newsignalcomp->screen_offset = 55.0 / (mainwindow->pixelsizefactor * newsignalcomp->voltpercm); mainwindow->setup_viewbuf(); } void ViewCurve::AdjustFilterButton() { sidemenu->close(); if(!mainwindow->signalcomps) { return; } if(signal_nr>(mainwindow->signalcomps - 1)) { return; } AdjustFilterSettings filtersettings(mainwindow->signalcomp[signal_nr], this); } void ViewCurve::StatisticsButton() { if(!mainwindow->signalcomps) { sidemenu->close(); return; } if(signal_nr>(mainwindow->signalcomps - 1)) { sidemenu->close(); return; } sidemenu->close(); UI_StatisticWindow show_stats_window(mainwindow->signalcomp[signal_nr], mainwindow->pagetime); } void ViewCurve::FreqSpecButton() { int i, j; for(i=0; ispectrumdialog[i] == NULL) { mainwindow->spectrumdialog[i] = new UI_FreqSpectrumWindow(mainwindow->signalcomp[signal_nr], mainwindow->viewbuf, mainwindow->spectrumdialog, i, mainwindow); break; } } sidemenu->close(); if(isignalcomp[signal_nr]->spectr_dialog[j] == 0) { mainwindow->signalcomp[signal_nr]->spectr_dialog[j] = i + 1; break; } } mainwindow->spectrumdialog[i]->SpectrumDialog->move(((i % 15) * 30) + 200, ((i % 15) * 30) + 200); for(j=0; jspectrumdialog[j] != NULL) { mainwindow->spectrumdialog[j]->SpectrumDialog->raise(); } } mainwindow->spectrumdialog[i]->SpectrumDialog->activateWindow(); mainwindow->spectrumdialog[i]->SpectrumDialog->raise(); } } void ViewCurve::Z_scoringButton() { int i, j; if(mainwindow->signalcomp[signal_nr]->ecg_filter != NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Heartrate detection is active for this signal!"); messagewindow.exec(); return; } if(mainwindow->signalcomp[signal_nr]->zratio_filter != NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Z-ratio is already active for this signal!"); messagewindow.exec(); return; } if(mainwindow->annot_editor_active) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Close the annotation editor and try again."); messagewindow.exec(); return; } for(i=0; izscoredialog[i] == NULL) { mainwindow->zscoredialog[i] = new UI_ZScoreWindow(mainwindow, mainwindow->zscoredialog, i, signal_nr); break; } } sidemenu->close(); if(isignalcomp[signal_nr]->zscoredialog[j] == 0) { mainwindow->signalcomp[signal_nr]->zscoredialog[j] = i + 1; break; } } mainwindow->zscoredialog[i]->zscore_dialog->move(((i % 15) * 30) + 200, ((i % 15) * 30) + 200); for(j=0; jzscoredialog[j] != NULL) { mainwindow->zscoredialog[j]->zscore_dialog->raise(); } } mainwindow->zscoredialog[i]->zscore_dialog->activateWindow(); mainwindow->zscoredialog[i]->zscore_dialog->raise(); } } void ViewCurve::FittopaneButton() { int j, pane_size, signalcomps; struct signalcompblock **signalcomp; signalcomps = mainwindow->signalcomps; signalcomp = mainwindow->signalcomp; if(!signalcomps) { sidemenu->close(); return; } if(signal_nr>(signalcomps - 1)) { sidemenu->close(); return; } pane_size = (int)(((double)height() * 0.95) / signalcomps); for(j=0; jnum_of_signals; j++) { if(signalcomp[signal_nr]->max_dig_value!=signalcomp[signal_nr]->min_dig_value) { signalcomp[signal_nr]->sensitivity[j] = (double)pane_size / (double)(signalcomp[signal_nr]->max_dig_value - signalcomp[signal_nr]->min_dig_value); } else { signalcomp[signal_nr]->sensitivity[j] = pane_size; } signalcomp[signal_nr]->voltpercm = signalcomp[signal_nr]->edfhdr->edfparam[signalcomp[signal_nr]->edfsignal[0]].bitvalue / (signalcomp[signal_nr]->sensitivity[0] * mainwindow->pixelsizefactor); signalcomp[signal_nr]->screen_offset = ((signalcomp[signal_nr]->max_dig_value + signalcomp[signal_nr]->min_dig_value) / 2.0) * signalcomp[signal_nr]->sensitivity[0]; } drawCurve_stage_1(); sidemenu->close(); } void ViewCurve::ColorButton() { int color; sidemenu->hide(); UI_ColorMenuDialog colormenudialog(&color, this); if(color < 0) { sidemenu->close(); return; } mainwindow->signalcomp[signal_nr]->color = color; update(); sidemenu->close(); } void ViewCurve::ScaleBox2Changed(double value) { mainwindow->signalcomp[signal_nr]->screen_offset = -(value / (mainwindow->pixelsizefactor * mainwindow->signalcomp[signal_nr]->voltpercm)); drawCurve_stage_1(); } void ViewCurve::ScaleBoxChanged(double value) { int i; double original_value; if(mainwindow->signalcomp[signal_nr]->edfhdr->edfparam[mainwindow->signalcomp[signal_nr]->edfsignal[0]].bitvalue < 0.0) { value *= -1.0; } for(i=0; isignalcomp[signal_nr]->num_of_signals; i++) { mainwindow->signalcomp[signal_nr]->sensitivity[i] = mainwindow->signalcomp[signal_nr]->edfhdr->edfparam[mainwindow->signalcomp[signal_nr]->edfsignal[i]].bitvalue / value / mainwindow->pixelsizefactor; } original_value = mainwindow->signalcomp[signal_nr]->voltpercm; mainwindow->signalcomp[signal_nr]->voltpercm = value; mainwindow->signalcomp[signal_nr]->screen_offset *= (original_value / value); drawCurve_stage_1(); } void ViewCurve::RemovefilterButton() { int j; if(!mainwindow->signalcomps) { sidemenu->close(); return; } if(signal_nr>(mainwindow->signalcomps - 1)) { sidemenu->close(); return; } for(j=0; jsignalcomp[signal_nr]->filter_cnt; j++) { free(mainwindow->signalcomp[signal_nr]->filter[j]); } mainwindow->signalcomp[signal_nr]->filter_cnt = 0; for(j=0; jsignalcomp[signal_nr]->ravg_filter_cnt; j++) { free_ravg_filter(mainwindow->signalcomp[signal_nr]->ravg_filter[j]); } mainwindow->signalcomp[signal_nr]->ravg_filter_cnt = 0; if(mainwindow->signalcomp[signal_nr]->ecg_filter != NULL) { free_ecg_filter(mainwindow->signalcomp[signal_nr]->ecg_filter); mainwindow->signalcomp[signal_nr]->ecg_filter = NULL; strcpy(mainwindow->signalcomp[signal_nr]->signallabel, mainwindow->signalcomp[signal_nr]->signallabel_bu); mainwindow->signalcomp[signal_nr]->signallabellen = mainwindow->signalcomp[signal_nr]->signallabellen_bu; strcpy(mainwindow->signalcomp[signal_nr]->physdimension, mainwindow->signalcomp[signal_nr]->physdimension_bu); } if(mainwindow->signalcomp[signal_nr]->zratio_filter != NULL) { free_zratio_filter(mainwindow->signalcomp[signal_nr]->zratio_filter); mainwindow->signalcomp[signal_nr]->zratio_filter = NULL; strcpy(mainwindow->signalcomp[signal_nr]->signallabel, mainwindow->signalcomp[signal_nr]->signallabel_bu); mainwindow->signalcomp[signal_nr]->signallabellen = mainwindow->signalcomp[signal_nr]->signallabellen_bu; strcpy(mainwindow->signalcomp[signal_nr]->physdimension, mainwindow->signalcomp[signal_nr]->physdimension_bu); } for(j=0; jsignalcomp[signal_nr]->fidfilter_cnt; j++) { free(mainwindow->signalcomp[signal_nr]->fidfilter[j]); fid_run_free(mainwindow->signalcomp[signal_nr]->fid_run[j]); fid_run_freebuf(mainwindow->signalcomp[signal_nr]->fidbuf[j]); fid_run_freebuf(mainwindow->signalcomp[signal_nr]->fidbuf2[j]); } mainwindow->signalcomp[signal_nr]->fidfilter_cnt = 0; mainwindow->signalcomp[signal_nr]->signallabel[mainwindow->signalcomp[signal_nr]->signallabellen] = 0; drawCurve_stage_1(); sidemenu->close(); } void ViewCurve::RemovesignalButton() { int i, j, p; if(!mainwindow->signalcomps) { sidemenu->close(); return; } if(signal_nr>(mainwindow->signalcomps - 1)) { sidemenu->close(); return; } for(i=0; ispectrumdock[i]->signalcomp == mainwindow->signalcomp[signal_nr]) { mainwindow->spectrumdock[i]->clear(); mainwindow->spectrumdock[i]->dock->hide(); } } for(i=0; isignalcomp[signal_nr]->spectr_dialog[i]; if(p != 0) { delete mainwindow->spectrumdialog[p - 1]; mainwindow->spectrumdialog[p - 1] = NULL; } } for(i=0; isignalcomp[signal_nr]->avg_dialog[i]; if(p != 0) { delete mainwindow->averagecurvedialog[p - 1]; mainwindow->averagecurvedialog[p - 1] = NULL; } } for(i=0; isignalcomp[signal_nr]->zscoredialog[i]; if(p != 0) { delete mainwindow->zscoredialog[p - 1]; mainwindow->zscoredialog[p - 1] = NULL; } } if(mainwindow->signalcomp[signal_nr]->hascursor2) { crosshair_2.active = 0; crosshair_2.moving = 0; } if(mainwindow->signalcomp[signal_nr]->hascursor1) { crosshair_1.active = 0; crosshair_2.active = 0; crosshair_1.moving = 0; crosshair_2.moving = 0; for(i=0; isignalcomps; i++) { mainwindow->signalcomp[i]->hascursor2 = 0; } } if(mainwindow->signalcomp[signal_nr]->hasruler) { ruler_active = 0; ruler_moving = 0; } for(j=0; jsignalcomp[signal_nr]->filter_cnt; j++) { free(mainwindow->signalcomp[signal_nr]->filter[j]); } mainwindow->signalcomp[signal_nr]->filter_cnt = 0; if(mainwindow->signalcomp[signal_nr]->spike_filter) { free_spike_filter(mainwindow->signalcomp[signal_nr]->spike_filter); mainwindow->signalcomp[signal_nr]->spike_filter = NULL; } for(j=0; jsignalcomp[signal_nr]->ravg_filter_cnt; j++) { free_ravg_filter(mainwindow->signalcomp[signal_nr]->ravg_filter[j]); } mainwindow->signalcomp[signal_nr]->ravg_filter_cnt = 0; if(mainwindow->signalcomp[signal_nr]->ecg_filter != NULL) { free_ecg_filter(mainwindow->signalcomp[signal_nr]->ecg_filter); mainwindow->signalcomp[signal_nr]->ecg_filter = NULL; strcpy(mainwindow->signalcomp[signal_nr]->signallabel, mainwindow->signalcomp[signal_nr]->signallabel_bu); mainwindow->signalcomp[signal_nr]->signallabellen = mainwindow->signalcomp[signal_nr]->signallabellen_bu; strcpy(mainwindow->signalcomp[signal_nr]->physdimension, mainwindow->signalcomp[signal_nr]->physdimension_bu); } if(mainwindow->signalcomp[signal_nr]->zratio_filter != NULL) { free_zratio_filter(mainwindow->signalcomp[signal_nr]->zratio_filter); mainwindow->signalcomp[signal_nr]->zratio_filter = NULL; strcpy(mainwindow->signalcomp[signal_nr]->signallabel, mainwindow->signalcomp[signal_nr]->signallabel_bu); mainwindow->signalcomp[signal_nr]->signallabellen = mainwindow->signalcomp[signal_nr]->signallabellen_bu; strcpy(mainwindow->signalcomp[signal_nr]->physdimension, mainwindow->signalcomp[signal_nr]->physdimension_bu); } for(j=0; jsignalcomp[signal_nr]->fidfilter_cnt; j++) { free(mainwindow->signalcomp[signal_nr]->fidfilter[j]); fid_run_free(mainwindow->signalcomp[signal_nr]->fid_run[j]); fid_run_freebuf(mainwindow->signalcomp[signal_nr]->fidbuf[j]); fid_run_freebuf(mainwindow->signalcomp[signal_nr]->fidbuf2[j]); } mainwindow->signalcomp[signal_nr]->fidfilter_cnt = 0; free(mainwindow->signalcomp[signal_nr]); for(i=signal_nr; isignalcomps - 1; i++) { mainwindow->signalcomp[i] = mainwindow->signalcomp[i + 1]; } mainwindow->signalcomps--; drawCurve_stage_1(); sidemenu->close(); } void ViewCurve::RulerButton() { int i; crosshair_1.moving = 0; crosshair_2.moving = 0; ruler_active = 0; ruler_moving = 0; use_move_events = 0; setMouseTracking(false); for(i=0; isignalcomps; i++) { mainwindow->signalcomp[i]->hasruler = 0; } if(width() < 300) { goto END_OF_FUNC; } if(height() < 300) { goto END_OF_FUNC; } if((mainwindow->pagetime / TIME_DIMENSION) < 2LL) { QMessageBox messagewindow(QMessageBox::Warning, "Ruler", "The ruler can not be used when the Timescale\n is set to a value less than 2 seconds."); messagewindow.exec(); goto END_OF_FUNC; } if((mainwindow->pagetime / TIME_DIMENSION) > 120LL) { QMessageBox messagewindow(QMessageBox::Warning, "Ruler", "The ruler can not be used when the Timescale\n is set to a value more than 120 seconds."); messagewindow.exec(); goto END_OF_FUNC; } if((mainwindow->signalcomp[signal_nr]->voltpercm < 1.0) && (mainwindow->signalcomp[signal_nr]->voltpercm > -1.0)) { QMessageBox messagewindow(QMessageBox::Warning, "Ruler", "The ruler can not be used when the Amplitude\n is set to a value less than 1."); messagewindow.exec(); goto END_OF_FUNC; } if((mainwindow->signalcomp[signal_nr]->voltpercm > 2000.0) || (mainwindow->signalcomp[signal_nr]->voltpercm < -2000.0)) { QMessageBox messagewindow(QMessageBox::Warning, "Ruler", "The ruler can not be used when the Amplitude\n is set to a value more than 2000."); messagewindow.exec(); goto END_OF_FUNC; } ruler_x_position = 200; ruler_y_position = 200; mainwindow->signalcomp[signal_nr]->hasruler = 1; ruler_active = 1; update(); END_OF_FUNC: sidemenu->close(); } void ViewCurve::CrosshairButton() { int i; if(!crosshair_1.active) { for(i=0; isignalcomps; i++) { mainwindow->signalcomp[i]->hascursor1 = 0; mainwindow->signalcomp[i]->hascursor2 = 0; } crosshair_1.value = 0.0; crosshair_2.value = 0.0; mainwindow->signalcomp[signal_nr]->hascursor1 = 1; use_move_events = 0; setMouseTracking(true); crosshair_1.active = 1; crosshair_2.active = 0; crosshair_1.moving = 0; crosshair_2.moving = 0; crosshair_1.file_num = mainwindow->signalcomp[signal_nr]->filenum; crosshair_1.x_position = w * 0.3; crosshair_1.y_position = h * 0.7; drawCurve_stage_1(); } else { if(!crosshair_2.active) { for(i=0; isignalcomps; i++) { mainwindow->signalcomp[i]->hascursor2 = 0; } crosshair_2.value = 0.0; mainwindow->signalcomp[signal_nr]->hascursor2 = 1; use_move_events = 0; setMouseTracking(true); crosshair_2.active = 1; crosshair_1.moving = 0; crosshair_2.moving = 0; crosshair_2.file_num = mainwindow->signalcomp[signal_nr]->filenum; crosshair_2.x_position = w * 0.3; crosshair_2.y_position = h * 0.7; drawCurve_stage_1(); } } sidemenu->close(); } void ViewCurve::resizeEvent(QResizeEvent *rs_event) { drawCurve_stage_1(); QWidget::resizeEvent(rs_event); } inline void ViewCurve::floating_ruler(QPainter *painter, int x_pos, int y_pos, struct signalcompblock *signalcomp, int print_linewidth) { int i, j; double d_tmp, d_tmp2, h_size, w_size, pixels_per_second; char str_hz[7][16]={" 9", "10", "11", "12", "13", "14", "15"}; char str_uv[5][16]={"200", "150", "100", "50", "0"}; char str_s[4][16]={"1.00", "0.75", "0.50", "0.25"}; if(w < 400) { return; } if((mainwindow->pagetime / TIME_DIMENSION) < 2LL) { return; } if((mainwindow->pagetime / TIME_DIMENSION) > 60LL) { return; } if((signalcomp->voltpercm < 1.0) && (signalcomp->voltpercm > -1.0)) { return; } if((signalcomp->voltpercm > 2000.0) || (signalcomp->voltpercm < -2000.0)) { return; } x_pos *= printsize_x_factor; y_pos *= printsize_y_factor; pixels_per_second = ((double)w) / (((double)mainwindow->pagetime) / ((double)TIME_DIMENSION)); h_size = 4.0 * painter_pixelsizefactor; w_size = (double)w / 10.0; d_tmp = h_size / 7.0; d_tmp2 = h_size / 14.0; if(floating_ruler_value) { for(i=0; i<7; i++) { snprintf(str_hz[i], 15, "%.1f", (pixels_per_second / w_size) * (2.0 + i)); str_hz[i][15] = 0; } if(((int)signalcomp->voltpercm) < 20) { for(i=0; i<5; i++) { snprintf(str_uv[i], 15, "%.1f", signalcomp->voltpercm * i * (double)(signalcomp->polarity * -1)); str_uv[i][15] = 0; } } else { for(i=0; i<5; i++) { snprintf(str_uv[i], 15, "%i", (int)(signalcomp->voltpercm * i * (double)(signalcomp->polarity * -1))); str_uv[i][15] = 0; } } } else { for(i=0; i<7; i++) { snprintf(str_hz[i], 15, "%.1f", (w_size / pixels_per_second) * (9.0 + i)); str_hz[i][15] = 0; } if(((int)signalcomp->voltpercm) < 20) { for(i=0; i<5; i++) { snprintf(str_uv[i], 15, "%.1f", signalcomp->voltpercm * (4 - i) * (double)signalcomp->polarity); str_uv[i][15] = 0; } } else { for(i=0; i<5; i++) { snprintf(str_uv[i], 15, "%i", (int)(signalcomp->voltpercm * (4 - i)) * signalcomp->polarity); str_uv[i][15] = 0; } } } for(i=0; i<4; i++) { snprintf(str_s[i], 15, "%.2f", ((w / 40.0) / pixels_per_second) * (4 - i)); str_s[i][15] = 0; } painter->setPen((Qt::GlobalColor)floating_ruler_color); painter->drawText(x_pos, y_pos - ((double)h / 80.0), "Hz"); for(i=0; i<7; i++) { painter->drawText(x_pos - ((double)w / 30.0), y_pos + ((double)h / 204.8) + d_tmp2 + (d_tmp * i), str_hz[i]); } for(i=1; i<7; i++) { painter->drawLine(x_pos, y_pos + (d_tmp * i), x_pos + w_size, y_pos + (d_tmp * i)); } painter->drawRect(x_pos, y_pos, w_size, h_size); if(floating_ruler_value) { for(j=2; j<9; j++) { d_tmp2 = w_size / j; for(i=1; idrawLine(x_pos + (d_tmp2 * i), y_pos + (d_tmp * (j - 2)), x_pos + (d_tmp2 * i), y_pos + (d_tmp * (j - 1))); } } } else { for(j=9; j<16; j++) { d_tmp2 = w_size / j; for(i=1; idrawLine(x_pos + (d_tmp2 * i), y_pos + (d_tmp * (j - 9)), x_pos + (d_tmp2 * i), y_pos + (d_tmp * (j - 8))); } } } painter->drawText(x_pos + (3.0 * printsize_x_factor), y_pos + h_size + (25.0 * printsize_y_factor), "more..."); x_pos += (w_size + ((double)w / 18.0)); d_tmp = h_size / 4.0; painter->drawText(x_pos - ((double)w / 45.0), y_pos - ((double)h / 80.0), signalcomp->physdimension); for(i=0; i<5; i++) { painter->drawText(x_pos - ((double)w / 45.0), y_pos + ((double)h / 204.8) + (d_tmp * i), str_uv[i]); painter->drawLine(x_pos + ((double)w / 160.0), y_pos + (d_tmp * i), x_pos + ((double)w / 45.7), y_pos + (d_tmp * i)); } painter->drawLine(x_pos + ((double)w / 45.7), y_pos, x_pos + ((double)w / 45.7), y_pos + h_size); d_tmp = h_size / 20.0; for(i=1; i<20; i++) { painter->drawLine(x_pos + ((double)w / 71.1), y_pos + (d_tmp * i), x_pos + ((double)w / 45.7), y_pos + (d_tmp * i)); } x_pos += ((double)w / 10.0); painter->drawLine(x_pos, y_pos, x_pos + (w_size / 2.0), y_pos + h_size); painter->drawLine(x_pos + w_size, y_pos, x_pos + (w_size / 2.0), y_pos + h_size); d_tmp = h_size / 4.0; d_tmp2 = w_size / 8.0; for(i=0; i<4; i++) { painter->drawLine(x_pos + (d_tmp2 * i), y_pos + (d_tmp * i), x_pos + w_size - (d_tmp2 * i), y_pos + (d_tmp * i)); } for(i=0; i<4; i++) { painter->drawText(x_pos - ((double)w / 25.0) + (d_tmp2 * i), y_pos + ((double)h / 204.8) + (d_tmp * i), str_s[i]); } painter->drawText(x_pos + ((double)w / 125.0) + w_size, y_pos + ((double)h / 204.8), "Sec"); special_pen->setColor((Qt::GlobalColor)floating_ruler_color); special_pen->setWidth(print_linewidth); painter->setPen(*special_pen); d_tmp = h_size / 20.0; d_tmp2 = w_size / 40.0; for(i=1; i<20; i++) { painter->drawLine(x_pos + (d_tmp2 * i), y_pos + (d_tmp * i), x_pos + w_size - (d_tmp2 * i), y_pos + (d_tmp * i)); } } void ViewCurve::backup_colors_for_printing() { int i; backup_color_1 = backgroundcolor; backgroundcolor = Qt::white; backup_color_2 = small_ruler_color; small_ruler_color = Qt::black; backup_color_3 = big_ruler_color; big_ruler_color = Qt::black; backup_color_4 = mouse_rect_color; mouse_rect_color = Qt::black; backup_color_5 = text_color; text_color = Qt::black; backup_color_14 = floating_ruler_color; floating_ruler_color = Qt::black; for(i=0; isignalcomps; i++) { backup_color_10[i] = mainwindow->signalcomp[i]->color; mainwindow->signalcomp[i]->color = Qt::black; } backup_color_11 = crosshair_1.color; crosshair_1.color = Qt::black; backup_color_12 = crosshair_2.color; crosshair_2.color = Qt::black; backup_color_13 = baseline_color; baseline_color = Qt::black; backup_color_15 = annot_marker_color; annot_marker_color = Qt::black; } void ViewCurve::restore_colors_after_printing() { int i; backgroundcolor = backup_color_1; small_ruler_color = backup_color_2; big_ruler_color = backup_color_3; mouse_rect_color = backup_color_4; text_color = backup_color_5; floating_ruler_color = backup_color_14; for(i=0; isignalcomps; i++) { mainwindow->signalcomp[i]->color = backup_color_10[i]; } crosshair_1.color = backup_color_11; crosshair_2.color = backup_color_12; baseline_color = backup_color_13; annot_marker_color = backup_color_15; } void ViewCurve::setCrosshair_1_center(void) { crosshair_1.x_position = width() / 2; } void ViewCurve::strip_types_from_label(char *label) { int i, len; len = strlen(label); if(len<16) { return; } if((!(strncmp(label, "EEG ", 4))) ||(!(strncmp(label, "ECG ", 4))) ||(!(strncmp(label, "EOG ", 4))) ||(!(strncmp(label, "ERG ", 4))) ||(!(strncmp(label, "EMG ", 4))) ||(!(strncmp(label, "MEG ", 4))) ||(!(strncmp(label, "MCG ", 4)))) { if(label[4]!=' ') { for(i=0; i<(len-4); i++) { label[i] = label[i+4]; } for(; i. * *************************************************************************** */ #include "signals_dialog.h" UI_Signalswindow::UI_Signalswindow(QWidget *w_parent) { int i; mainwindow = (UI_Mainwindow *)w_parent; SignalsDialog = new QDialog; SignalsDialog->setMinimumSize(800, 500); SignalsDialog->setMaximumSize(800, 500); SignalsDialog->setWindowTitle("Signals"); SignalsDialog->setModal(true); SignalsDialog->setAttribute(Qt::WA_DeleteOnClose, true); filelist = new QListWidget(SignalsDialog); filelist->setGeometry(10, 10, 780, 75); for(i=0; ifiles_open; i++) { new QListWidgetItem(QString::fromLocal8Bit(mainwindow->edfheaderlist[i]->filename), filelist); } label1 = new QLabel(SignalsDialog); label1->setGeometry(10, 95, 760, 25); label2 = new QLabel(SignalsDialog); label2->setGeometry(10, 120, 760, 25); label3 = new QLabel(SignalsDialog); label3->setGeometry(10, 145, 250, 25); label4 = new QLabel(SignalsDialog); label4->setGeometry(270, 145, 250, 25); label5 = new QLabel(SignalsDialog); label5->setGeometry(10, 190, 120, 25); label5->setText("Signals in file"); label6 = new QLabel(SignalsDialog); label6->setGeometry(430, 190, 120, 25); label6->setText("Signal Composition"); colorlabel = new QLabel(SignalsDialog); colorlabel->setGeometry(320, 380, 100, 25); colorlabel->setText(" Color"); signallist = new QListWidget(SignalsDialog); signallist->setGeometry(10, 210, 300, 225); signallist->setFont(*mainwindow->monofont); signallist->setSelectionBehavior(QAbstractItemView::SelectRows); signallist->setSelectionMode(QAbstractItemView::ExtendedSelection); CloseButton = new QPushButton(SignalsDialog); CloseButton->setGeometry(690, 455, 100, 25); CloseButton->setText("&Close"); SelectAllButton = new QPushButton(SignalsDialog); SelectAllButton->setGeometry(10, 455, 100, 25); SelectAllButton->setText("&Select All"); HelpButton = new QPushButton(SignalsDialog); HelpButton->setGeometry(690, 120, 100, 25); HelpButton->setText("&Help"); DisplayButton = new QPushButton(SignalsDialog); DisplayButton->setGeometry(150, 455, 160, 25); DisplayButton->setText("&Add signal(s)"); DisplayCompButton = new QPushButton(SignalsDialog); DisplayCompButton->setGeometry(430, 455, 160, 25); DisplayCompButton->setText("&Make derivation"); AddButton = new QPushButton(SignalsDialog); AddButton->setGeometry(320, 250, 100, 25); AddButton->setText("Add->"); SubtractButton = new QPushButton(SignalsDialog); SubtractButton->setGeometry(320, 285, 100, 25); SubtractButton->setText("Subtract->"); RemoveButton = new QPushButton(SignalsDialog); RemoveButton->setGeometry(320, 320, 100, 25); RemoveButton->setText("Remove<-"); ColorButton = new SpecialButton(SignalsDialog); ColorButton->setGeometry(320, 405, 100, 25); ColorButton->setColor((Qt::GlobalColor)mainwindow->maincurve->signal_color); compositionlist = new QListWidget(SignalsDialog); compositionlist->setGeometry(430, 210, 360, 225); compositionlist->setFont(*mainwindow->monofont); compositionlist->setSelectionBehavior(QAbstractItemView::SelectRows); compositionlist->setSelectionMode(QAbstractItemView::ExtendedSelection); smp_per_record = 0; QObject::connect(CloseButton, SIGNAL(clicked()), SignalsDialog, SLOT(close())); QObject::connect(SelectAllButton, SIGNAL(clicked()), this, SLOT(SelectAllButtonClicked())); QObject::connect(HelpButton, SIGNAL(clicked()), this, SLOT(HelpButtonClicked())); QObject::connect(DisplayButton, SIGNAL(clicked()), this, SLOT(DisplayButtonClicked())); QObject::connect(DisplayCompButton, SIGNAL(clicked()), this, SLOT(DisplayCompButtonClicked())); QObject::connect(AddButton, SIGNAL(clicked()), this, SLOT(AddButtonClicked())); QObject::connect(SubtractButton, SIGNAL(clicked()), this, SLOT(SubtractButtonClicked())); QObject::connect(RemoveButton, SIGNAL(clicked()), this, SLOT(RemoveButtonClicked())); QObject::connect(ColorButton, SIGNAL(clicked(SpecialButton *)), this, SLOT(ColorButtonClicked(SpecialButton *))); QObject::connect(filelist, SIGNAL(currentRowChanged(int)), this, SLOT(show_signals(int))); curve_color = mainwindow->maincurve->signal_color; filelist->setCurrentRow(mainwindow->files_open - 1); signallist->setFocus(); SignalsDialog->exec(); } void UI_Signalswindow::ColorButtonClicked(SpecialButton *) { int color; UI_ColorMenuDialog colormenudialog(&color); if(color < 0) return; ColorButton->setColor((Qt::GlobalColor)color); curve_color = color; } void UI_Signalswindow::DisplayCompButtonClicked() { int i, j, n; char str[512], str2[128]; struct signalcompblock *newsignalcomp; QListWidgetItem *item; n = compositionlist->count(); if(!n) { return; } newsignalcomp = (struct signalcompblock *)calloc(1, sizeof(struct signalcompblock)); if(newsignalcomp==NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Internal error: Memory allocation error:\n\"new signal composition\""); messagewindow.exec(); SignalsDialog->close(); return; } newsignalcomp->num_of_signals = n; newsignalcomp->filenum = filelist->currentRow(); newsignalcomp->edfhdr = mainwindow->edfheaderlist[newsignalcomp->filenum]; newsignalcomp->file_duration = newsignalcomp->edfhdr->long_data_record_duration * newsignalcomp->edfhdr->datarecords; newsignalcomp->voltpercm = mainwindow->default_amplitude; newsignalcomp->color = curve_color; newsignalcomp->hasruler = 0; newsignalcomp->polarity = 1; for(i=0; iitem(i)->text().toLatin1().data()); for(j=0; jedfhdr->edfsignals; j++) { if(!strncmp(newsignalcomp->edfhdr->edfparam[j].label, str + 5, 16)) { if(j != compositionlist->item(i)->data(Qt::UserRole).toInt()) continue; newsignalcomp->edfsignal[i] = j; newsignalcomp->factor[i] = str[23] - 48; if(str[3]=='-') { newsignalcomp->factor[i] = -(newsignalcomp->factor[i]); strcat(newsignalcomp->signallabel, "- "); } else { if(i) { strcat(newsignalcomp->signallabel, "+ "); } } strcpy(str2, newsignalcomp->edfhdr->edfparam[j].label); strip_types_from_label(str2); strcat(newsignalcomp->signallabel, str2); remove_trailing_spaces(newsignalcomp->signallabel); strcat(newsignalcomp->signallabel, " "); if(newsignalcomp->edfhdr->edfparam[j].bitvalue < 0.0) { newsignalcomp->voltpercm = mainwindow->default_amplitude * -1; } newsignalcomp->sensitivity[i] = newsignalcomp->edfhdr->edfparam[j].bitvalue / ((double)newsignalcomp->voltpercm * mainwindow->pixelsizefactor); } } } remove_trailing_spaces(newsignalcomp->signallabel); newsignalcomp->signallabellen = strlen(newsignalcomp->signallabel); strcpy(newsignalcomp->physdimension, newsignalcomp->edfhdr->edfparam[newsignalcomp->edfsignal[0]].physdimension); remove_trailing_spaces(newsignalcomp->physdimension); mainwindow->signalcomp[mainwindow->signalcomps] = newsignalcomp; mainwindow->signalcomps++; while(compositionlist->count()) { item = compositionlist->takeItem(0); delete item; } mainwindow->setup_viewbuf(); smp_per_record = 0; } void UI_Signalswindow::DisplayButtonClicked() { int i, n, s, old_scomps; struct signalcompblock *newsignalcomp; QListWidgetItem *item; QList selectedlist; selectedlist = signallist->selectedItems(); n = selectedlist.size(); if(!n) { SignalsDialog->close(); return; } old_scomps = mainwindow->signalcomps; for(i=0; iclose(); return; } newsignalcomp->num_of_signals = 1; newsignalcomp->filenum = filelist->currentRow(); 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; newsignalcomp->hasruler = 0; newsignalcomp->polarity = 1; item = selectedlist.at(i); s = item->data(Qt::UserRole).toInt(); newsignalcomp->edfsignal[0] = s; newsignalcomp->factor[0] = 1; if(newsignalcomp->edfhdr->edfparam[s].bitvalue < 0.0) { newsignalcomp->voltpercm = mainwindow->default_amplitude * -1; } newsignalcomp->sensitivity[0] = newsignalcomp->edfhdr->edfparam[s].bitvalue / ((double)newsignalcomp->voltpercm * mainwindow->pixelsizefactor); strcpy(newsignalcomp->signallabel, newsignalcomp->edfhdr->edfparam[s].label); strip_types_from_label(newsignalcomp->signallabel); remove_trailing_spaces(newsignalcomp->signallabel); newsignalcomp->file_duration = newsignalcomp->edfhdr->long_data_record_duration * newsignalcomp->edfhdr->datarecords; newsignalcomp->signallabellen = strlen(newsignalcomp->signallabel); strcpy(newsignalcomp->physdimension, newsignalcomp->edfhdr->edfparam[s].physdimension); remove_trailing_spaces(newsignalcomp->physdimension); mainwindow->signalcomp[mainwindow->signalcomps] = newsignalcomp; mainwindow->signalcomps++; } if((i) && (mainwindow->files_open == 1) && (old_scomps == 0)) { if((mainwindow->signalcomp[0]->file_duration / TIME_DIMENSION) < 5) { mainwindow->pagetime = mainwindow->signalcomp[0]->file_duration; } } SignalsDialog->close(); mainwindow->setup_viewbuf(); } void UI_Signalswindow::RemoveButtonClicked() { int i, n, row; QListWidgetItem *item; QList selectedlist; selectedlist = compositionlist->selectedItems(); n = selectedlist.size(); if(!n) return; for(i=0; irow(item); item = compositionlist->takeItem(row); delete item; } } void UI_Signalswindow::AddButtonClicked() { int i, j, k, n, s, row, duplicate; char str[256]; QListWidgetItem *item; QList selectedlist; selectedlist = signallist->selectedItems(); n = selectedlist.size(); if(!n) return; if(!compositionlist->count()) { smp_per_record = 0; physdimension[0] = 0; bitvalue = 0.0; } for(i=0; idata(Qt::UserRole).toInt(); row = filelist->currentRow(); if(smp_per_record) { if(smp_per_record!=mainwindow->edfheaderlist[row]->edfparam[s].smp_per_record) { QMessageBox messagewindow(QMessageBox::Warning, "Warning", "It is only possible to make combinations/derivations with signals which:\n" " - are from the same file\n" " - have the same samplerate\n" " - have the same physical dimension (e.g. uV)\n" " - have the same sensitivity (e.g. uV/bit)"); messagewindow.exec(); continue; } } else { smp_per_record = mainwindow->edfheaderlist[row]->edfparam[s].smp_per_record; } if(physdimension[0]) { if(strcmp(physdimension, mainwindow->edfheaderlist[row]->edfparam[s].physdimension)) { QMessageBox messagewindow(QMessageBox::Warning, "Warning", "It is only possible to make combinations/derivations with signals which:\n" " - are from the same file\n" " - have the same samplerate\n" " - have the same physical dimension (e.g. uV)\n" " - have the same sensitivity (e.g. uV/bit)"); messagewindow.exec(); continue; } } else { strcpy(physdimension, mainwindow->edfheaderlist[row]->edfparam[s].physdimension); } if(bitvalue!=0.0) { if(bitvalue!=mainwindow->edfheaderlist[row]->edfparam[s].bitvalue) { QMessageBox messagewindow(QMessageBox::Warning, "Warning", "It is only possible to make combinations/derivations with signals which:\n" " - are from the same file\n" " - have the same samplerate\n" " - have the same physical dimension (e.g. uV)\n" " - have the same sensitivity (e.g. uV/bit)"); messagewindow.exec(); continue; } } else { bitvalue = mainwindow->edfheaderlist[row]->edfparam[s].bitvalue; } duplicate = 0; k = compositionlist->count(); for(j=0; jitem(j); strcpy(str, item->text().toLatin1().data()); if(!strncmp(mainwindow->edfheaderlist[row]->edfparam[s].label, str + 5, 16)) { if(str[3]=='+') { if(s == item->data(Qt::UserRole).toInt()) { duplicate = 1; break; } } } } if(duplicate) { if(str[23]==57) continue; str[23] += 1; item->setText(str); } else { snprintf(str, 200, "%-2i + ", row + 1); strcat(str, mainwindow->edfheaderlist[row]->edfparam[s].label); strcat(str, " x1 "); convert_to_metric_suffix(str + strlen(str), mainwindow->edfheaderlist[row]->edfparam[s].smp_per_record / mainwindow->edfheaderlist[row]->data_record_duration, 3); remove_trailing_zeros(str); strcat(str, "Hz"); item = new QListWidgetItem; item->setData(Qt::UserRole, QVariant(s)); item->setText(str); compositionlist->addItem(item); } } } void UI_Signalswindow::SubtractButtonClicked() { int i, j, k, n, s, row, duplicate; char str[256]; QListWidgetItem *item; QList selectedlist; selectedlist = signallist->selectedItems(); n = selectedlist.size(); if(!n) return; if(!compositionlist->count()) { smp_per_record = 0; physdimension[0] = 0; bitvalue = 0.0; } for(i=0; idata(Qt::UserRole).toInt(); row = filelist->currentRow(); if(smp_per_record) { if(smp_per_record!=mainwindow->edfheaderlist[row]->edfparam[s].smp_per_record) { QMessageBox messagewindow(QMessageBox::Warning, "Warning", "It is only possible to make combinations/derivations with signals which:\n" " - are from the same file\n" " - have the same samplerate\n" " - have the same physical dimension (e.g. uV)\n" " - have the same sensitivity (e.g. uV/bit)"); messagewindow.exec(); continue; } } else { smp_per_record = mainwindow->edfheaderlist[row]->edfparam[s].smp_per_record; } if(physdimension[0]) { if(strcmp(physdimension, mainwindow->edfheaderlist[row]->edfparam[s].physdimension)) { QMessageBox messagewindow(QMessageBox::Warning, "Warning", "It is only possible to make combinations/derivations with signals which:\n" " - are from the same file\n" " - have the same samplerate\n" " - have the same physical dimension (e.g. uV)\n" " - have the same sensitivity (e.g. uV/bit)"); messagewindow.exec(); continue; } } else { strcpy(physdimension, mainwindow->edfheaderlist[row]->edfparam[s].physdimension); } if(bitvalue!=0.0) { if(bitvalue!=mainwindow->edfheaderlist[row]->edfparam[s].bitvalue) { QMessageBox messagewindow(QMessageBox::Warning, "Warning", "It is only possible to make combinations/derivations with signals which:\n" " - are from the same file\n" " - have the same samplerate\n" " - have the same physical dimension (e.g. uV)\n" " - have the same sensitivity (e.g. uV/bit)"); messagewindow.exec(); continue; } } else { bitvalue = mainwindow->edfheaderlist[row]->edfparam[s].bitvalue; } duplicate = 0; k = compositionlist->count(); for(j=0; jitem(j); strcpy(str, item->text().toLatin1().data()); if(!strncmp(mainwindow->edfheaderlist[row]->edfparam[s].label, str + 5, 16)) { if(str[3]=='-') { duplicate = 1; break; } } } if(duplicate) { if(str[23]==57) continue; str[23] += 1; item->setText(str); } else { snprintf(str, 200, "%-2i - ", row + 1); strcat(str, mainwindow->edfheaderlist[row]->edfparam[s].label); strcat(str, " x1 "); convert_to_metric_suffix(str + strlen(str), mainwindow->edfheaderlist[row]->edfparam[s].smp_per_record / mainwindow->edfheaderlist[row]->data_record_duration, 3); remove_trailing_zeros(str); strcat(str, "Hz"); item = new QListWidgetItem; item->setData(Qt::UserRole, QVariant(s)); item->setText(str); compositionlist->addItem(item); } } } void UI_Signalswindow::show_signals(int row) { int i, j, len, skip, signal_cnt; char str[256]; long long file_duration; QListWidgetItem *item; struct date_time_struct date_time; if(row<0) return; while(signallist->count()) { delete signallist->item(0); } if((mainwindow->edfheaderlist[row]->edfplus)||(mainwindow->edfheaderlist[row]->bdfplus)) { strcpy(str, "Subject "); strcat(str, mainwindow->edfheaderlist[row]->plus_patient_name); strcat(str, " "); strcat(str, mainwindow->edfheaderlist[row]->plus_birthdate); strcat(str, " "); strcat(str, mainwindow->edfheaderlist[row]->plus_patientcode); label1->setText(str); strcpy(str, "Recording "); strcat(str, mainwindow->edfheaderlist[row]->plus_admincode); label2->setText(str); } else { strcpy(str, "Subject "); strcat(str, mainwindow->edfheaderlist[row]->patient); len = strlen(str); for(j=0; jsetText(str); strcpy(str, "Recording "); strcat(str, mainwindow->edfheaderlist[row]->recording); len = strlen(str); for(j=0; jsetText(str); } utc_to_date_time(mainwindow->edfheaderlist[row]->utc_starttime, &date_time); date_time.month_str[0] += 32; date_time.month_str[1] += 32; date_time.month_str[2] += 32; snprintf(str, 256, "Start %i %s %i %2i:%02i:%02i", date_time.day, date_time.month_str, date_time.year, date_time.hour, date_time.minute, date_time.second); label3->setText(str); strcpy(str, "Duration "); file_duration = mainwindow->edfheaderlist[row]->long_data_record_duration * mainwindow->edfheaderlist[row]->datarecords; if((file_duration / TIME_DIMENSION) / 10) { snprintf(str + 11, 240, "%2i:%02i:%02i", (int)((file_duration / TIME_DIMENSION)/ 3600LL), (int)(((file_duration / TIME_DIMENSION) % 3600LL) / 60LL), (int)((file_duration / TIME_DIMENSION) % 60LL)); } else { snprintf(str + 11, 240, "%2i:%02i:%02i.%06i", (int)((file_duration / TIME_DIMENSION)/ 3600LL), (int)(((file_duration / TIME_DIMENSION) % 3600LL) / 60LL), (int)((file_duration / TIME_DIMENSION) % 60LL), (int)((file_duration % TIME_DIMENSION) / 10LL)); } label4->setText(str); skip = 0; signal_cnt = mainwindow->edfheaderlist[row]->edfsignals; for(i=0; iedfheaderlist[row]->edfplus || mainwindow->edfheaderlist[row]->bdfplus) { for(j=0; jedfheaderlist[row]->nr_annot_chns; j++) { if(i==mainwindow->edfheaderlist[row]->annot_ch[j]) { skip = 1; break; } } if(skip) { skip = 0; continue; } } snprintf(str, 256, "%-3i ", i + 1); strcat(str, mainwindow->edfheaderlist[row]->edfparam[i].label); strcat(str, " "); convert_to_metric_suffix(str + strlen(str), mainwindow->edfheaderlist[row]->edfparam[i].smp_per_record / mainwindow->edfheaderlist[row]->data_record_duration, 6); remove_trailing_zeros(str); strcat(str, "Hz"); item = new QListWidgetItem; item->setText(str); item->setData(Qt::UserRole, QVariant(i)); signallist->addItem(item); } SelectAllButtonClicked(); } void UI_Signalswindow::SelectAllButtonClicked() { int row, i; QListWidgetItem *item; row = signallist->count(); for(i=0; iitem(i); item->setSelected(true); } } void UI_Signalswindow::HelpButtonClicked() { QMessageBox messagewindow(QMessageBox::NoIcon, "Help", "On top you will see a list of opened files.\n" "Select (highlight) the file from which you want to add signals.\n" "At the left part of the dialog you see a list of all the signals which are in the selected file.\n" "Select one or more signals and click on the \"Add signals\" button.\n" "Now you will see the selected signals on the screen.\n" "\nWhen you want to make a combination (derivation) of two or more signals, do as follows.\n" "Select the file from which you want to add signals.\n" "For example, we choose an EEG file which contains the signals \"P3\" and \"C3\"\n" "and we want to subtract \"C3\" from \"P3\".\n" "- Select (highlight) the signal \"P3\".\n" "- Click on the \"Add\" button.\n" "- Select (highlight) the signal \"C3\".\n" "- Click on the \"Subtract\" button.\n" "- Click on the \"Make derivation\" button.\n" "- The result of \"P3\" minus \"C3\" will appear on the screen."); messagewindow.exec(); } void UI_Signalswindow::strip_types_from_label(char *label) { int i, len; len = strlen(label); if(len<16) { return; } if((!(strncmp(label, "EEG ", 4))) ||(!(strncmp(label, "ECG ", 4))) ||(!(strncmp(label, "EOG ", 4))) ||(!(strncmp(label, "ERG ", 4))) ||(!(strncmp(label, "EMG ", 4))) ||(!(strncmp(label, "MEG ", 4))) ||(!(strncmp(label, "MCG ", 4)))) { if(label[4]!=' ') { for(i=0; i<(len-4); i++) { label[i] = label[i+4]; } for(; i. * *************************************************************************** */ #ifndef OPTIONSFORM1_H #define OPTIONSFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "colordialog.h" #include "special_button.h" #include "signalcurve.h" class UI_Mainwindow; class UI_OptionsDialog : public QObject { Q_OBJECT public: UI_OptionsDialog(QWidget *parent=0); UI_Mainwindow *mainwindow; private: QDialog *optionsdialog; QScrollArea *scrollarea; QFrame *frame; QGridLayout *scrolllayout; QTabWidget *tabholder; QWidget *tab1, *tab2, *tab3, *tab4; QVBoxLayout *mainLayout; QHBoxLayout *horLayout; QPushButton *CloseButton, *DefaultButton, *colorSchema_NK_Button, *colorSchema_Dark_Button, *ApplyButton, *DefaultButton2, *ApplyButton2, *saveColorSchemaButton, *loadColorSchemaButton; SpecialButton *BgColorButton, *SrColorButton, *BrColorButton, *MrColorButton, *TxtColorButton, *SigColorButton, *BaseColorButton, *Crh1ColorButton, *Crh2ColorButton, *FrColorButton, *AnnotMkrButton, *slabel2_1, *slabel2_3; QLabel *label1, *label2, *label3, *label4, *label5, *label6, *label7, *label8, *label9, *label10, *label11, *label12, *label13, *label4_1, *label4_2, *label4_3, *label4_4, *label4_5, *label4_6, *label4_7, *label4_8, *label4_9, *label4_10, *label4_11, *label4_12, *label2_2, *label2_4, *label1_3, *label2_3, *label3_3, *label3_4, *label3_5; QSpinBox *spinbox2_1, *spinbox2_2, *spinbox3_1, *spinbox4_1, *spinbox4_2, *spinbox4_3; QDoubleSpinBox *dspinbox3_2, *dspinbox4_4; QComboBox *combobox4_1, *combobox4_2, *combobox4_3; QCheckBox *checkbox1, *checkbox2, *checkbox3, *checkbox3_1, *checkbox4, *checkbox4_1, *checkbox4_2, *checkbox4_3, *checkbox4_4, *checkbox4_5, *checkbox4_6, *checkbox2_1; QTableWidget *colorBarTable; QRadioButton *radiobutton1, *radiobutton2, *radiobutton3; QLineEdit *lineEdit3_1; void update_interface(void); private slots: void BgColorButtonClicked(SpecialButton *); void SrColorButtonClicked(SpecialButton *); void BrColorButtonClicked(SpecialButton *); void MrColorButtonClicked(SpecialButton *); void TxtColorButtonClicked(SpecialButton *); void SigColorButtonClicked(SpecialButton *); void BaseColorButtonClicked(SpecialButton *); void Crh1ColorButtonClicked(SpecialButton *); void Crh2ColorButtonClicked(SpecialButton *); void FrColorButtonClicked(SpecialButton *); void AnnotMkrButtonClicked(SpecialButton *); void checkbox1Clicked(int); void checkbox2Clicked(int); void checkbox3Clicked(int); void checkbox4Clicked(int); void checkbox3_1Clicked(int); void checkbox4_1Clicked(int); void checkbox4_2Clicked(int); 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(); void checkBoxChanged(int); void ApplyButton2Clicked(); void radioButtonToggled(bool); void spinBoxValueChanged(double); void spinBox3_1ValueChanged(int); void dspinBox3_2ValueChanged(double); void labelEdited(const QString &); void calibrate_checkbox_stateChanged(int); void spinBox4_1ValueChanged(int); void combobox4_1IndexChanged(int); void combobox4_2IndexChanged(int); void combobox4_3IndexChanged(int); void spinBox4_2ValueChanged(int); void spinBox4_3ValueChanged(int); void saveColorSchemaButtonClicked(); void loadColorSchemaButtonClicked(); void loadColorSchema_NK(); void loadColorSchema_Dark(); void dspinbox4_4ValueChanged(double); }; #endif // OPTIONSFORM1_H edfbrowser_157_source/PaxHeaders.7921/doc0000644000000000000000000000013212646460742015356 xustar0030 mtime=1452958178.226246804 30 atime=1452958178.225246807 30 ctime=1452958178.226246804 edfbrowser_157_source/doc/0000755000175000001440000000000012646460742015774 5ustar00guvusers00000000000000edfbrowser_157_source/doc/PaxHeaders.7921/montage_file_format.txt0000644000000000000000000000013212646460742022175 xustar0030 mtime=1452958178.226246804 30 atime=1452958178.226246804 30 ctime=1452958178.226246804 edfbrowser_157_source/doc/montage_file_format.txt0000644000175000001440000003006512646460742022542 0ustar00guvusers00000000000000 This document describes the format used by EDFbrowser to write montage files. ----------------------------------------------------------------------------- The montage file uses only basic XML elements. XML attributes are not allowed. The first line of the file must contain: The root element must be "EDFbrowser_montage", like: Inside the root element "EDFbrowser_montage", there will be a child element for every signal composition. A signal composition represents one trace or curve on the screen. The name of this element must be "signalcomposition", like: Inside every element "signalcomposition", there must be one element with the name "num_of_signals", like: 2 The value of this element must be an integer within the range 1 to 512. (The example has a value of 2.) The value represents from how many signals it is derived i.e. if it's monopolar, bipolar or tripolar, etc. Note: all signals in the same signalcomposition must share the same samplerate and sensitivity. Inside every element "signalcomposition", there must be one element with the name "voltpercm", like: 100.000000 The value of this element must be a floating point number. (The example has a value of 100.0.) The value represents the amplitude of the signal expressed in it's physical dimension per cm (vertical). Inside every element "signalcomposition", there must be one element with the name "screen_offset", like: 0 The value of this element must be an integer or floating point number. (The example has a value of 0.) The value represents the vertical offset compared to the baseline. Inside every element "signalcomposition", there must be one element with the name "polarity", like: 1 The value of this element must be either 1 or -1. (The example has a value of 1.) The value has the following meanings: 1 : normal presentation (not inverted) -1 : signal will be drawn inverted (upside down) Inside every element "signalcomposition", there must be one element with the name "color", like: 2 The value of this element must be an integer within the range 2 to 18. (The example has a value of 2.) The value represents the color of the signalcomposition on the screen i.e. the trace or curve. Colortable: 2 Black 3 White 4 Dark gray 5 Gray 6 Light gray 7 Red 8 Green 9 Blue 10 Cyan 11 Magenta 12 Yellow 13 Dark red 14 Dark green 15 Dark blue 16 Dark cyan 17 Dark magenta 18 Dark Yellow Inside every element "signalcomposition", there can be one element with the name "alias", like: average An alias, if used, replaces the signalcomposition label on the screen. It does not influence the montages. Only 7-bit ASCII characters are allowed. Max 16 characters. Inside every element "signalcomposition", there can be one element with the name "fidfilter_cnt", like: 0 The value of this element must be an integer within the range 0 to 8. (The example has a value of 0.) The value represents the number of fid filters applied to the signalcomposition. Inside every element "signalcomposition", there can be one element with the name "ravg_filter_cnt", like: 0 The value of this element must be an integer within the range 0 to 8. (The example has a value of 0.) The value represents the number of running average filters applied to the signalcomposition. Inside every element "signalcomposition", there must be at least one element with the name "signal", like: The number of elements "signal" must be equal to the value of the element "num_of_signals". Note: all signals in the same signalcomposition must have the same samplerate and sensitivity. Inside every element "signal", there must be one element with the name "label", like: The value of this element must be a string containing only 7-bit ASCII characters. (The example has a value of "FP1".) The decimal value of every character must be in the range 32 to 126. This avoids the use of control-codes. The maximum amount of characters allowed is 16. There must be no termination character (like zero). The value represents the label of the signal in the file which must be used for this signalcomposition. Exception: Instead of an element "label", an element "edfindex" can be used: 4 The value of this element must be an integer within the range 0 to 511. (The example has a value of 4.) The value represents the number of the signal in the file which must be used for this signalcomposition. The first signal in an EDF-file has number 0, the second signal has number 1, the third signal has number 2, etc. Inside the element "signal", there must be one element with the name "factor", like: 1 The value of this element must be an integer in the range -128 to 128. 0 is not allowed. (The example has a value of 1.) The value of this element represents a multiplying factor. During the drawing of the samples of the respective signal on the screen, the values of the samples will be multiplied with this factor. If the value of element "fidfilter_cnt" is higher than zero, there must be at least one element with name "fidfilter", like: The number of elements "fidfilter" must be equal to the value of the element "fidfilter_cnt". Inside every element "fidfilter", there must be one element with the name "type", like: 0 The value of this element must be an integer in the range 0 to 4. (The example has a value of 0.) filtertype table: 0 higpass 1 lowpass 2 notch 3 bandpass 4 bandstop Note: when type = 2 (notch), element "model" must be 0 (Butterworth). Inside every element "fidfilter", there must be one element with the name "frequency", like: 0.5 The value of this element must be a floating point number. (The example has a value of 0.5 Hz.) The value represents the cut-off or notch frequency expressed in Hz. Inside every element "fidfilter", there must be one element with the name "frequency2", like: 100.0 The value of this element must be a floating point number. (The example has a value of 100.0 Hz.) The value represents the second cut-off frequency of a bandpass or bandstop filter expressed in Hz and must be higher than the value of "frequency". Inside every element "fidfilter", there must be one element with the name "ripple", like: 3.0 The value of this element must be a floating point number. (The example has a value of 3.0 dB.) The value represents the bandpass ripple expressed in dB. Inside every element "fidfilter", there must be one element with the name "order", like: 1 The value of this element must be an integer number within the range 1 to 100. (The example has a value of 1.) The value represents the filters order e.g. 1th order. Note: when type = 2 (notch), order must be in the range 3 to 100 and represents the Q-factor of the notch-filter. Inside every element "fidfilter", there must be one element with the name "model", like: 0 The value of this element must be an integer number within the range 0 to 2. (The example has a value of 0.) The value represents the filters model. filter model table: 0 Butterworth 1 Chebyshev 2 Bessel Note: when type = 2 (notch), element "model" must be 0 (Butterworth). Note: Not all filter parameters are applicabel to all types of filters. Despite, the parameters must be present. If a parameter is not applicabel e.g. frequency2 when using a highpassfilter, fill in some value. The value will be ignored but must be present in the file. Inside every element "signalcomposition", there can be one element with the name "ecg_filter", like: 1 The value of this element must be an integer with the value 1. (The example has a value of 1.) The value represents the activation of the heartrate detection. If the value of element "ravg_filter_cnt" is higher than zero, there must be at least one element with name "ravg_filter", like: The number of elements "ravg_filter" must be equal to the value of the element "ravg_filter_cnt". Inside every element "ravg_filter", there must be one element with the name "type", like: 0 The value of this element must be an integer in the range 0 to 1. (The example has a value of 0.) filtertype table: 0 higpass running average filter (also called: moving average filter) 1 lowpass running average filter Inside every element "ravg_filter", there must be one element with the name "size", like: 16 The value of this element must be an integer in the range 2 to 10000. (The example has a value of 16.) The value represents the size of the running average filterbuffer expressed in samples. Inside the root element "EDFbrowser_montage", there must be one element with the name "pagetime", like: 100000000 The value of this element must be an integer with a minimum value of 10000. (The example has a value of 100000000.) The value represents the timescale (pagetime) expressed in units of 100 nanoSeconds. Thus, a value of 100000000 means a timescale of 10 seconds. An example of the content of a montage file. --------------------------------------------- It contains three signalcompositions. All of them are derivatives of two signals: F4 - FP2, C4 - F4 and X1 - X2. The first signalcomposition has two filters: a 1th order highpass Butterworth filter at 0.1 Hz and a 1th order lowpass Butterworth filter at 35.0 Hz. ("frequency2" and "ripple" are not applicabel to this type of filter) The second signalcomposition has one filter: a notch filter at 50.0 Hz with a Q-factor of 20. The third signalcomposition has the heartrate detection activated. The timescale is set to 10 seconds. 2 50.000000 0.000000 2 2 0 1 -1 0 0.1000000000000000 0.1120000000000000 -1.0000000000000000 1 0 1 35.0000000000000000 39.2000000000000028 -1.0000000000000000 1 0 2 50.000000 0.000000 2 1 0 1 -1 2 50.0000000000000000 0.0001000000000000 -1.0000000000000000 20 0 2 5.000000 415.748031 7 0 0 1 -1 1 100000000 edfbrowser_157_source/doc/PaxHeaders.7921/manual.html0000644000000000000000000000013212646460742017576 xustar0030 mtime=1452958178.226246804 30 atime=1452958178.226246804 30 ctime=1452958178.226246804 edfbrowser_157_source/doc/manual.html0000644000175000001440000022161312646460742020144 0ustar00guvusers00000000000000 EDFbrowser manual

EDFbrowser 1.57 manual


Table of Contents:


Filemenu

Use the Filemenu to open or close a file. After the file has been opened,
the signaldialog will appear.


Table of Contents



Streaming mode

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


Table of Contents



Video

(Linux version only)
Use the Filemenu to start (or stop) a video. After the video has been started, you can use the slider
on the bottom to change the file position or use page-up/page-down.

In order for EDFbrowser to be able to start a video, the VLC mediaplayer needs to be installed on your system.

Also, the startdate and starttime needs to be set in the filename of the video (for synchronization).
The following text is copied from http://www.edfplus.info/specs/video.html :

Video filenames of the same patient must start with the same patient identification,
followed by the start-date and -time of the video, as follows:
NL_012348168_03-MAY-2013_14h45m49.013s_Video.ogv
in which case the video apparently starts on May 3, 2013 at 0.013 seconds after 14:45:49hr. To be more precise,
the patient identification is followed by an underscore (_), followed by the video startdate DD-MMM-YYYY,
followed by an underscore, followed by the starttime HHhMMmSS.XXXXs. The startdate days, DD, are 01, 02, 03, ... 30 or 31.
The months, MMM, are JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV or DEC.
The years, YYYY, obviously are 2013, 2014 and so on. The starttime is based on the 24h clock with HH ranging from 00 till 23,
so midnight is coded as 00h00m00s. The decimal fraction of a second (noted here by .XXXX) can have any lenght and can also be omitted
(for example in 06h37m12s). The addition _Video is not obligatory and neither do we standardize any video format such as ogv.
So, a perfectly OK video filename would also be:
NL_012348168_03-MAY-2013_14h45m49.013s.mpeg


Table of Contents



Signalsmenu

Use the Signalsmenu to add or remove signals. If you want to remove only one particular signal,
leftclick on the signallabel of the signal you want to remove. A small dialog will appear and gives
you the possibility to remove that particular signal from the screen. See also signaldialog.


Table of Contents



Timescalemenu

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


Table of Contents



Amplitudemenu

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


Table of Contents



Signallabel

The signallabel is the name of the signal which is printed on the screen at the start of the trace.
This little piece of text has some "hidden" functions. When you leftclick on it, the Signalproperties
dialog will be opened. You can also drag this label with the left or right mousebutton to change
the offset or amplitude of the signal, see also Adjusting the position and size of the signals.


Table of Contents



Alias

The alias, if used, is an alternative signallabel which is printed on the screen at the start of the trace.
Aliasses can be created in the Signalproperties dialog and will be stored in your montage.


Table of Contents



Signaldialog

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

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

Now you can add more combinations or simply close the dialog.

note: It is only possible to make combinations with signals who:
- are in the same file
- have the same samplerate
- have the same physical dimension (e.g. uV)
- have the same sensitivity (e.g. uV/bit)

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


Table of Contents



Signalproperties

You can view or adjust the properties of a specific signal by leftclicking on the signallabel.
A small dialog will be opened and let you change the amplitude and color.
You can also remove filters (if any) or remove the signal from the screen.
You can also enter an alias for the signalname.
Another option is to activate one or more crosshairs for precise measurements.

Another way to view/change the properties of a signal is to go to Signals -> Properties.
This will show you a list of all signals which are on the screen. Simply click on the
signal of interest.


Table of Contents



Adjusting the position and size of the signals

Leftclick on the signallabel and move the mousepointer up or down while keeping the
left mousebutton pressed. This will move the signal up or down on the screen i.e. it
changes the offset of the signal.

Rightclick on the signallabel and move the mousepointer up or down while keeping the
right mousebutton pressed. This will increase or decrease the amplitude (size/gain) of
the signal on the screen.


Table of Contents



Organize signals

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


Table of Contents



Navigation

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

You can also zoom-in.


Table of Contents



Annotations

When a file contains annotations, the annotationwindow will appear.
Just click on one of the annotations to jump to that position in the file.
This window is dockable. You can change the size of the window, but also the position.
You can make the window floating as well by dragging it with the mouse. After closing
the annotationwindow, you can make it appear again via Window -> Annotations.

By right-clicking on an annotation in the annotationwindow, you can hide or unhide one or more
annotations from the screen.


Table of Contents



Filters

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

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

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

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

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


Table of Contents



Adjust filters

You can adjust or finetune the filters. Left-click on a signallabel and select "Adjust filter".
You can adjust or finetune the frequency, order or Q-factor of a filter and watch the result at the same time.
Use this dialog when you want to remove a filter.


Table of Contents



Powerspectrum

To view the powerspectrum of a signal, leftclick on the signallabel and choose "Spectrum".
The Power Spectral Density of the corresponding signal will be shown (uV)2/FFT-resolution.
The amount of datasamples used to perform the FFT equals the data which is
shown on the screen. Increasing or decreasing the FFT blocksize affects the FFT resolution.
The FFT blocksize can be set in Settings menu.
So, if the samplefrequency of the selected signal is 256Hz, the timescale is set to 10 seconds and
the FFT-blocksize is 512, the number of FFT's performed is (10 seconds x 256 Hz) / 512 = 5.
The output of the five FFT's are averaged.
In case you set the FFT blocksize equal to timescale x samplefrequency, exactly one FFT will be performed.

This powerspectrum is static and will not update when you change the fileposition (pressing PgUp/PgDn etc.).
This way you can compare multiple powerspectra from different signals and/or filepositions.

There is also a powerspectrum window available that automatically updates when you walk through a file.
Go to Window -> Power Spectrum.
A small dialog will be opened which shows a list of signals which are on the screen.
Click on a signal of interest and a docked Powerspectrum (FFT) will be opened.
This Powerspectrum will be automatically updated when you navigate through the file. Clicking on the
"ctls" button toggles the controls. Here you can switch-on colorbars to highlight different frequency-
regions. The properties of the colorbars (number of colorbars, frequency, color, etc.) can be adjusted
in the Settings menu. The height of the colorbar is relative to the sum, peak or average of the the
power of all the frequency-bins in that region, according to the settings in the Settings menu.
Use the sliders to zoom into a particular area.
When you check the "Amplitude" checkbox, the amplitude spectrum will be shown.
Printing can be done by clicking on the printbutton. You can print to a printer, file (PDF or Postscript)
or as an image. It is also possible to "print" to a textfile. It exports the data to text (ASCII).
Clicking on the cursorbutton will display a cursor. Use the mouse to drag the cursor.


Table of Contents



Averaging (evoked potentials or other triggers)

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

The result can be printed or exported as a new EDF/BDF file.

You can also use external triggers in ASCII(*.csv or *.txt) or XML format.
See Import annotations/events how to import triggers/events/annotations.

Note: It is also possible to change the selection of annotations/triggers for averaging, by editing the annotationlist first.


Table of Contents



ECG heart rate detection

Toggling the "Heart Rate" button toggles on or off the detection and calculation of the heartrate
expressed in beats per minute (bpm).
The "Heart Rate" button can be found in the Signalproperties dialog.
The algorithm used for the heartrate detection is derived from "Real time electrocardiogram QRS detection using combined adaptive threshold"
by Ivaylo I Christov. http://www.biomedical-engineering-online.com/content/3/1/28

The R-onset times and/or RR-interval times (beat to beat) can be exported to an ascii-file for analysis in other programs (e.g. Kubios).
After you switched on the Heart Rate detection, go to "Tools -> Import/Export ECG RR-interval".
Only the part of the signal that is visible on the screen will be exported, except when you check the "Whole recording" checkbox.
There is also the possibility to import the RR-intervals as annotations.

Some statistics about the Heart Rate (variability) are available here.

Important: before using the Heart Rate detection, go to the settings menu (Settings -> Other) and adjust the "Powerline Frequency" to the frequency used in the country
where the recording of the ECG took place (50 or 60 Hz). Otherwise the powerline noise suppression filter in the Heart Rate detection algorithm will not work correctly.


Table of Contents



Heart Rate statistics

When the ECG heart rate detection is enabled, you can view some statistics about the
Heart Rate (variability) in the Signalproperties. Once you see the Signalproperties dialog,
click on the "Statistics" button. A brief description of the statistics:

- Mean, the average of the RR-intervals.
- SDNN, the standard deviation of RR-intervals.
- RMSSD, the square root of the mean squared difference of successive RR's.
- NN50, the number of pairs of successive RR's that differ by more than 50 ms.
- pNN50, the proportion of NN50 divided by total number of RR's as a percentage.

The data used for the statistics is derived from the timewindow that is visible on the screen.


Table of Contents



Spike filter

The Spike filter can be used to filter out spikes, fast transients, glitches or pacemaker impulses.
Velocity is expressed in units (e.g. uV) per 0.5 milli-Seconds. If the filter detects two fast transients
with opposite polarity and within 3 milli-Seconds, it will consider it a spike which will be suppressed.

The transient is measured for every sample with a delta t of 0.5 milli-Seconds.
(The sample will be compared with an older sample 0.5 milli-Seconds before.)

Setting the value of velocity too high, will cause the spikes not to be detected.
Setting the value of velocity too low, will cause false triggers.

Hold-off is used to prevent a re-trigger of the filter within the hold-off period after the last trigger.

The Spike filter can not be used with samplerates lower than 4000 Hz.
Signals with lower samplerates will not be visible in the Spike filter dialog.

The Spike filter dialog has no apply button. Activating or de-activating the spike filter is simply done
by selecting or de-selecting one or more signals.
Changing the value of velocity or holdoff will cause an immediate update of the screen.


Table of Contents



Zoomfunction

There are multiple ways to zoom-in:

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

or

- By using the mousewheel while keeping the Ctrl-button pressed.

or

- You can zoom into a signal/curve on the screen by drawing a rectangle with the mouse.
Keep the left mousebutton pressed and move the mousepointer in the direction of the
right lower corner. When you release the left mousebutton, the content of the rectangle
will be expanded to the whole screen. You can repeat this step and zoom in again.

Use the backspace button on your keyboard to zoom out and restore the previous settings.
After using the backspace button, you can zoom in again by pressing the insert button on
your keyboard.


Table of Contents



Floating ruler

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


Table of Contents



Crosshairs

You can use one or two crosshairs for precise measurements. Leftclick on the signallabel
of the signal of interest. A small dialog will appear. Click on Crosshair. A crosshair will
appear. Drag and drop the crosshair with the left mousebutton. Now you can add another crosshair.
The second crosshair will show you the differences (delta) in time and value of the signal(s).
Rightclick to remove the crosshair(s) or press the "Esc" key.


Table of Contents



Statistics

Some statistical info about a signal can be found in the Signalproperties.
and clicking on the "Statistics" button. It will show the number of samples showed on the screen, the sum, mean, RMS (root mean square), and MRS
(mean root square i.e average of rectified values) value of the samples showed on the screen.
In addition, the number of zero-crossings (i.e. switching from positive to negative or vice versa)
and the frequency of that part of the signal will be shown.


Table of Contents



Montages

Montages can be used to store information about which signals should be shown on
the screen, what combinations (derivations) should be made and other properties
like filters, amplitude (sensitivity), offset, alias, color and pagetime (timescale).
Once you have loaded a file for review and you have added all the signals you want
(and/or all the combinations/derivations) and you have adjusted amplitude and colors
and/or filters, you can save them as a montage.
Go to Montage -> Save. A dialog will be opened where you can choose a directory
and filename to store your montage.
Next time when you load a file, you can load a montage via Montage -> Load.

You can view the properties of a montage via Montage -> View saved montages or
Montage -> View this montage.

note:
It is important that the names (labels) of the signals are correct when you use a montage
to review different files.

You can bind the F1 to F12 keys to twelve different montages. This way you can quickly switch
between different montages by pressing key F1, F2, etc.
Go to Montage -> Edit key-bindings for montages.


Table of Contents



Keyboard bindings for montages

It is possible to create keyboard shortcuts (bindings) for predefined montages.
Go to Montage -> Edit key-bindings for montages. Click on the first row (F1);
Now you can select a montage. You can assign twelve different
montages to keys F1 - F12.
Now you can quickly switch between predefined montages by pressing one of these keys.


Table of Contents



Colors

Go to the Settings menu to change the colors like you prefer.


Table of Contents



Calibration

In the Settings menu go to the Calibration tab to calibrate your screen.
This will achieve that the amplitude expressed in units/cm will have
the correct height/value.


Table of Contents



Timelock and File synchronisation

When you open multiple files, you can choose to "timelock" all files with
each other. This means that when you navigate (by pressing PgUp/Pgdwn)
this will affect all signals on the screen. When you choose to "unlock" the files,
only the signals of the "reference" file will be moved on the screen. You can
change which file should be the reference in the Time menu.

There are three kinds of timelock:

- Offset

The start of the recording of all files will coincide with each other.

- Absolute time

The clock/date-time of the different files will coincide with each other.
(this is only useful when the period of registration overlap eachother)

- No timelock

Only the signals from the file that has the "time reference" will move when you navigate.
Use this option when you want to align two or more files manually.

- Userdefined synchronizing

Files are timelocked with a custom offset. Usually after synchronizing the
files manually.


The time shown in the leftbottom corner represents the time from the
file that acts as the "reference". You can change which file should be
the reference in the Time menu.

You can adjust the horizontal position (time) of two different files by using
two crosshairs. Put one crosshair at a signal of the first file and put the second
crosshair at a signal of the second file. Now click on Time -> synchronize by crosshairs.
Now the position of the two crosshairs (and that particular position of the two files) will
coincide with eachother.


Table of Contents



File info / properties / header

To view the content of the header of a file (subject, recording, signalproperties like samplerates etc.),
go to file -> info and select the file of interest.


Table of Contents



Header editor

This tool can be used to edit (or anonymize) the header (file info) like subject, birthdate, etc.
You can also edit labels (signalnames), physical dimension, pre-filter and transducer names.
If the file you want to edit has been opened in EDFbrowser already, close it first before starting
this tool.
This tool can also be used to repair a file that can not be opened with EDFbrowser because of
invalid characters in the header (the EDF format allows 7-bit ascii characters only) or other errors.

Other errors that can be fixed with this tool:
- a wrong timestamp format in the header (a colon instead of a dot between the numbers)
- a wrong number of datarecords written in the header
- a wrong filesize (file is not ending on the boundary of a datarecord)
- a broken number i.e. a number with decimal(s) in the digital maximum/minimum field

Do as follows: In EDFbrowser go to Tools -> Header editor. Select the file. Now click on the
"save" button (you don't need to edit the content manually). Close the header editor.
Now open the file in the usual way.


Table of Contents



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

This tool converts all the signals in an EDF or BDF-file to a plain ASCII text-file.
It supports different samplerates between the signals.

Four textfiles will be created:

- EDFfilename_header.txt contains the general header of the file.
- EDFfilename_signals.txt contains all signal headers of the file.
- EDFfilename_data.txt contains the data of all signals.
- EDFfilename_annotations.txt contains all annotations.

filename_data.txt contains a separate line for each sampletime that occurs.
Note to windows-users: these lines are separated by a linefeed only,
so the file does NOT look OK in Notepad, use Wordpad instead.

Each line contains the comma-separated values of the sampletime and of all
samples that were taken at that time.
Sampletime is expressed in seconds, while sample values are expressed in the
physical dimensions that are specified in filename_signals.txt.
All values have a dot (.) as decimal separator.

Different sampling frequencies are allowed in the file. In that case,
not all signals are sampled at each sampletime.
Those sample values are simply left empty, but the comma-separator is there.

note:

All comma's in headertext and annotations will be replaced by
single quotes (') because they interfere with the comma-separated
txt-files.

Unicode/UTF-8 decoding in annotations is not supported because of
the limitations of the ASCII txt-files.


Table of Contents



Reduce signals, duration and/or samplerate

This tool can be used to reduce the number of signals in a file and/or to reduce the duration (length) of a file
and/or to reduce the samplerate of one or more signals.
First, open the file in the usual way in EDFbrowser. Then start the tool and select the file.
Uncheck all the signals you do not want into the new file. If you want to shorten the file, choose the first
datarecord (starttime) and the last datarecord (endtime).
If you don't want to downsample, set the samplerate divider to 1 (default). Otherwise select one of the possible
divider values. Those values depend on the actual samplerate and the datarecord duration.

The anti-aliasing filter order can be choosen as well. The default is 5th order. This prevents practically
any change of aliasing.


Table of Contents



Export annotations/events

This tool exports the annotations/events from an EDF+/BDF+ file.
You can choose to save as a comma (or tab) separated textfile, to save as an EDFplus file
or XML. If you have opened multiple files, you can choose to export all
annotations of all opened files into one new file. The header of the file which acts as
the "reference" will be copied into the new EDFplus file. The "reference" file can be selected
in the menu Time -> Timereference.


Table of Contents



Import annotations/events

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

ASCII

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

XML

XML-files need to be encoded either in ISO-8859-1 or UTF-8 character encoding.
The root element name must be "annotationlist", child elements must be named "annotation".
Inside the element "annotation" are the elements "onset", "duration" and "description".
Onset is expressed in the ISO date-time format "yyyy-mm-ddThh:mm:ss" or "yyyy-mm-ddThh:mm:ss.xxx".
Duration is expressed in seconds "145.23" or empty.
Example:

<?xml version="1.0" encoding="UTF-8"?>
<annotationlist>
 <annotation>
  <onset>2006-11-14T09:14:31.0000000</onset>
  <duration></duration>
  <description>REC START IIB CAL   </description>
 </annotation>
 <annotation>
  <onset>2006-11-14T09:14:31.0000000</onset>
  <duration></duration>
  <description>PAT IIB EEG         </description>
 </annotation>
 <annotation>
  <onset>2006-11-14T09:14:32.0000000</onset>
  <duration></duration>
  <description>A1+A2 OFF           </description>
 </annotation>
</annotationlist>

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

DC-events / DC-triggers

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

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

The binary code in the example is 01010101 which is 170 decimal.
The rising edge of the startbit represents the time of the event (for example, an evoked potential).
The voltage levels can be freely chosen. In the importdialog adjust the triggerlevel to a level that is equal
to: (lowlevel + highlevel) / 2.
Also, set the bittime used for the DC-event.
Note that the intervaltime between two consegutive events must be more than ten times the bittime.

It is possible not to use the code but just only the startbit. In that case all triggers will have the code "0".
In that case you can use a simple on/off pulse as a trigger.

Note: The signal which contains the DC-event must be put on the screen in order to be available in the selectionscreen.
Also, the signal must be unipolar, i.e. not a derivation. Next, the detectionalgorithm of the triggers in this signal will bypass
any filters.


Table of Contents



Z-EEG

To use the Z-EEG measurement, leftclick on the signallabel and choose "Z-EEG".

Z-ratio = ((Delta + Theta) - (Alpha + Beta)) / (Delta + Theta + Alpha + Beta)

Z-ratio, therefore, is a measure of the relative contribution of slow to fast EEG activity within a
2-second epoch. It ranges from -1 to +1, with negative values indicating a predominance of fast
activity and positive values indicating a predominance of slow activity.

A per page score for z-ratio was derived by averaging the majority of 15 2-second z-ratios.
The average of the majority is the z-page.

The algorithm is derived from

http://www.ncbi.nlm.nih.gov/pubmed/8746389/

http://www.zzzratio.com/Z-bib.pdf


Table of Contents



ASCII to EDF/BDF format converter

This tool converts an ASCII-file (.csv or .txt file) to EDF or BDF. The following rules apply:

- the data in the ASCII-file must be presented in their physical dimension (i.e. uV, bpm, mmHg, etc.)
- the data in the ASCII-file must be organised in columns and rows
- a row must contain values from different signals/channels aquired at the same sampletime
- a column must represent a continuous sampled signal/channel
- all signals/channels must have the same samplefrequency
- the timeinterval between two consecutive samples of the same signal/channel must have a stable value (fixed samplerate)

Enter the following parameters:

- the character that separates the different columns (i.e. "tab" ","(comma) ";"(semicolon) " "(space) etc.)

- the number of columns

- the line at which the data starts. some ASCII-files contain headers, so use this entry
to tell the converter to skip n-lines before interpreting the data

- samplefrequency

- subject (the name of the subject)

- recording (a description about the type of recording/aquisition)

- startdate and time of the recording/aquisition

- signals: for every column in the ASCII-file, there is a row in the signals-table.
every row has a checkbox and four inputfields:

- label (name of the signal/channel i.e. FP1, SaO2, Heartrate, etc.)
- physical maximum (the maximum physical value that can occur, i.e. the maximum inputlevel
of the aquisition equipment. A common value in EEG applications is 3000 uV)
physical minimum will be equal to physical maximum. for example, if you enter 3000, the
range will be from +3000 to -3000
- physical dimension (i.e. uV, %, mmHg, bpm)
- multiplier is normally 1.0. Some programs exports their ascii-data expressed in Volts while
the signal is in the microVolt range. By changing the multiplier you can add gain to the signal before converting.
For example, if the ascii-data is expressed in Volts and the signal is in the microVolt range (EEG),
set the physical maximum to 3000, set the physical dimension to "uV" and set the multiplier to 1000000.

It is possible to exclude columns, by unchecking the corresponding row in the signals-table,
this can be useful when a column contains a time/datestamp or when you don't want to include
a particular signal in the EDF/BDF-file.

Click on the startbutton to start the conversion.
Click on the savebutton to save the entered parameters in a template.
Click on the loadbutton to load parameters from a template.

Note: It is important to enter the right value in the "physical maximum" field.
If you to choose this value too small, the top of the signal will be cut off.
If you choose this value too big, small values of the signal will not be visible
and the signal will look coarse.
The ideal value for the "physical maximum" is just above (or equal to) the maximum value that can occur,
i.e. the maximum possible output of the sensor or ADC, either positive or negative.
Therefore, it's better to set the checkbox "Auto detect physical maximum". That way you don't need to
enter the values in the column "Physical maximum".

Note 2: The maximum physical value that the converter can handle, is limited to 9999999. Values above
will be clipped to 9999999 and values below -9999999 will be clipped at -9999999.
If you expect higher values in your ascii-file, use the multiplier. For example,
set the multiplier to 0.1, 0.01 or 0.001, etc.

Note 3: If you think that, later, you want to make derivations (for example P4 - C4 in EEG applications),
make sure that the signals have the same value in the physical maximum field.
Also, do not set the checkbox "Auto detect physical maximum".


Table of Contents



Nihon Kohden to EDF(+) format converter

This tool converts EEG-files in Nihon Kohden format to the European Data Format
(EDF or EDF+ with annotations/events).

Three files are needed for a conversion to EDF+:

- nihonkohdenfile.eeg
- nihonkohdenfile.pnt
- nihonkohdenfile.log

In case you have only the nihonkohdenfile.eeg you can not convert to EDF+.
It is still possible to convert to EDF. In that case there will be no annotations/events and patientinfo.

The Marker/Event channel will be decoded on the fly when opening the new created EDF+ file with EDFbrowser.
If the screen becomes too "noisy" because of drawing too many annotations, you can switch them of by
unchecking the "Read Nihon Kohden Trigger/Marker signal" checkbox in the Settings-menu.
The new settings will be effective after closing and re-opening the file.
Also, you can selectively hide annotations by rightclicking on an annotation in the annotationwindow.

Note: In case you changed the default electrodenames in the Nihon Kohden aquisition software,
you need also the *.21e file which contains the electrode names (labels).


Table of Contents



Unisens to EDF+ format converter

This tool converts the waveform data and events/triggers from a collection of Unisense data files to EDF+.

Limitations of the converter:
- the Unisens XML-file must be encoded in UTF-8 or ISO-8859-1.
- Broken numbers for samplerate >= 1 Hz will be rounded to the nearby integer e.g. 2.75 Hz will be rounded to 3 Hz.
Samplerates below 1 Hz will be rounded to 1/2, 1/3, 1/4, etc. til 1/1000 Hz.
Lowest samplerate is 0.001 Hz
- Output format of the converter is EDF+ (16-bit) when all files have a samplesize of 16-bit or lower.
When one or more files have a samplesize of more than 16-bit, output format of the converter will be BDF+ (24-bit).

An extra feature of the converter which is not in the offical Unisens data format specification:
- support for binary sampletypes: int24 and uint24.


Table of Contents



SCP ECG to EDF+ format converter

This tool converts the waveform data of an SCP ECG file to EDF+.
Before conversion it performs a CRC-check on the file.
Encoding using the default Huffman table is supported.
Customized Huffman tables are not supported.
Bimodal compression is not supported. Character-encoding other than ASCII/Latin-1 is not supported.


Table of Contents



MIT to EDF+ format converter

This tool converts the waveform data and annotations from the MIT-format to EDF+.
It's used for files from PhysioBank at physionet.org.
At this moment it supports the "Format 212" and "Format 16".
Most of the signal files in PhysioBank are written in format 212.
Annotations (in the *.atr or *.ari file) will be read and converted to EDF+ as well.
In case the file that contains the annotations has a different extension, just rename the
extension to .atr. Otherwise the converter will not read the annotations.


Table of Contents



Manscan to EDF+ format converter

This tool converts a Manscan MICROAMPS binary data file to EDF+.
Two files are needed for the conversion, one with the extension ".mbi" and one with the extension ".mb2".


Table of Contents



Biosemi to BDF+ format converter

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

BDF+ files are backwards compatibel and can be read and processed with older BDF software.
BDF+ files can be converted to EDF+ while preserving your annotations.
Use the BDF to EDF converter in the Tools menu.

Limitations:

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

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

- Only the 17 lowest bits of the Status signal will be evaluated and converted.


Table of Contents



Finometer to EDF converter

This tool converts the ASCII-output (*.txt) of the Finometer (Beatscope) to EDF.
Finometer is a non-invasive stationary blood measurement and beat to beat haemodynamic monitoring system
made by Finapres Medical Systems.

Start Beatscope and open the file of interest.

Go to File -> Export.

- set export type to textfile
- set timeformat to seconds
- check output: header
- set averaging to none
- check datacolumnwidth: delimiter
- set delimiter to semicolon ";"
- check export beats and/or events: beats only
- select the channels you want to export

Now click on the Export-button to create the file.

In EDFbrowser, you'll find the Finometer to EDF converter in the Tools-menu.
In order to create a correct EDF-file header, enter the subject and a description about
the type of recording/aquisition.
Adjust the startdate and starttime to the date and time when the Finometer registration took place.

Click on the "select file" button to select the Finometer/Beatscope file.


Table of Contents



Wave to EDF converter

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


Table of Contents



FM Audio ECG to EDF converter

This tool converts an audiorecording containing an FM modulated ECG waveform to EDF.
The carrier centerfrequency of the FM signal is 1900Hz. Frequency deviation is 100Hz
per milli-Volt. This technic is used to upload ECG recording via POTS (Plain Old Telephone Service).
The converter has been tested with audio recordings from Cardiette Microtel but should work
also with devices from Aerotel HeartView.

The converter accepts recordings stored in WAV format with 16-bit resolution.
The recording must contain only one channel (mono) and the samplerate must be
one of the following: 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200 or 96000 Hz.


Table of Contents



Nexfin to EDF converter

This tool converts the ASCII-output (*.csv) of the Nexfin (FrameInspector) to EDF.
Nexfin is a non-invasive stationary blood measurement and beat to beat haemodynamic monitoring system
made by Bmeye B.V.

Start FrameInspector (it can be downloaded from the Nexfin website), open the file of interest and
choose "Generic export".

Now click on the Export-button to create the csv and bin files.

In EDFbrowser, you'll find the Nexfin to EDF converter in the Tools-menu.
In order to create a correct EDF-file header, enter the subject and a description about
the type of recording/aquisition.
Adjust the startdate and starttime to the date and time when the Nexfin registration took place.

Select which file you want to convert: beat-to-beat data, blood pressure waveform or the analog inputs.
(for analog inputs: select "4 inputs" in case AO option is configured, else "1 input")
Click on the "select file" button to select the Nexfin/FrameInspector csv or bin file.
For beat-to-beat data you need to select the file that ends with "_100.csv".
For blood pressure waveform you need to select the file that ends with "_103.bin".
For the analog inputs you need to select the file that ends with "_032.bin".


Table of Contents



Emsa to EDF+ format converter

This tool converts an Emsa eeg-file (*.PLG) to EDF+. If the corresponding *.LBK file is
present, the annotations/events will be exported to EDF+ as well.


Table of Contents



EDF+D to EDF+C converter

This tool converts an EDF+D file to multiple EDF+C files. An EDF+D file can contain
interrupted recordings. This converter export every uninterrupted recording to a new
uninterrupted EDF+C file.
This tool can be used for BDF+D files as well.


Table of Contents



BDF(+) to EDF(+) converter

This tool converts a BDF file to an EDF file. A BDF+ file will be converted to
EDF+, including the annotations/events.
It uses a first order highpass-filter to remove the DC-part of the signal in order
to make the 24-bits samples fit into the 16-bits samples of EDF.
The cutoff-frequency of the highpass-filters can be adjusted for every signal.
You can also select which signals have to be converted into the new EDF(+) file.
Increasing the divider lowers the resolution but increases the range (physical
maximum and minimum)


Table of Contents



EDF(+) and BDF(+) compatibility checker

This tool checks if a file is EDF(+) or BDF(+) compliant.
It checks the data and all the annotations and timestamps.
When it finds an error, it tells you what the error is and where it is in the file.

A description of the EDF fileformat can be found at:

http://www.teuniz.net/edfbrowser/edf format description.html

A description of the EDF+ fileformat can be found at:

http://www.edfplus.info/specs/edfplus.html

A description of the BDF fileformat can be found at:

http://www.biosemi.com/faq/file_format.htm

A description of the BDF+ fileformat can be found at:

http://www.teuniz.net/edfbrowser/bdfplus format description.html

note:

A compatibility check of the header of the file is always done when you open an
EDF(+)/BDF(+) file. When a file appears to be incompatible it will not be opened,
you will be informed about the cause of the incompatibility instead.

Note: If a file can not be opened with EDFbrowser because of invalid characters in the header
(the EDF format allows 7-bit ascii characters only), you can try to fix it with the header editor.
In EDFbrowser go to Tools -> Header editor. Select the file. Now click on the "save" button
(do not edit the content!). Close the header editor. Now open the file in EDFbrowser.


Table of Contents



Binary/raw to EDF

This tool converts the binary (raw) (ADC-)data from a file to a new EDF-file.
This is a kind of "last resort" measure when there are no other tools or EDF-converters available.
You need to figure out how the data in your file is organised and you need to have a good knowledge of
how computers store data in memory (file). This tool is for experts only.

All signals must have the same samplerate and the data-samples in the file must be stored sequentially:
sample 1 ch.1, sample 1 ch.2, sample 1 ch.3,
sample 2 ch.1, sample 2 ch.2, sample 2 ch.3,
sample 3 ch.1, sample 3 ch.2, sample 3 ch.3,
sample 4 ch.1, etc.

Set the samplefrequency and the number of signals (channels).
The samplesize is the size of a digital sample expressed in bytes.
Encoding is the binary system used to present a digital value:

  value   bipolar offset binary    2's complement
15 1111 0111
14 1110 0110
.... .... ....
2 1010 0010
1 1001 0001
0 1000 0000
-1 0111 1111
-2 0110 1110
.... .... ....
-15 0001 1001
-16 0000 1000

See also: Coding Schemes Used with Data Converters
Most files contain some kind of header. Adjust the Offset to the point where the data starts.
When a digital sample consists of multiple bytes, and the LSB (least significant byte) comes first,
select little Endian. If the MSB (most significant byte) comes first, select big endian.
Data blocksize is usually 0. Used only when some bytes must be skipped in a regular interval.
Skip bytes is the number of bytes that must be skipped (ignored) after every Data blocksize number of databytes.
Skip bytes is ignored when Data blocksize is set to 0.


Table of Contents



Print to PDF

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


Table of Contents



Print to image

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


Table of Contents



Print to EDF

The option "Print to EDF" creates a new EDF-file which will contain the signals
(and annotations) as they are on your screen. What you see is what you get,
like when you print to a printer, PDF-file or image. You can also open multiple
files, shift them in time (by using the different timelock options in the timemenu)
and "print" the result as one new EDF-file. The result wil contain the time-shifted
signals.
It is also possible to extract one or more signals from one (or more) files into a new file.

This function is located in File -> Print menu.

The following rules apply:

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

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

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

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

- when selected multiple files, the datarecordduration of these files
needs to be the same or an integer multiple of eachother

- if you selected any filters, these will be applied as well


Table of Contents



Print to BDF

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


Table of Contents



Annotation editor

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

Instead of manually entering the onset time, you can use a crosshair.
Drag and drop the crosshair and the onset time will be automatically adjusted.
You can use a second crosshair to adjust the duration time.

To modify an existent annotation, click on the annotation in the annotation window.
Adjust the text and or time, manually or drag and drop the annotation marker.

To delete an annotation, click on the annotation in the annotation window and click
on the delete button.

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

Note: The annotation editor will limit the precision of the onset-time of the annotations
to 1 milliSecond.


Table of Contents



Commandline options

edfbrowser [[--stream] datafile.edf [mymontage.mtg]]

It is possible to start the program from the commandline:

edfbrowser

this will start the program.

or

edfbrowser myfile.edf

this will start the program with the file myfile.edf opened.

or

edfbrowser myfile.edf mymontage.mtg

this will start the program with the file myfile.edf opened and using the montage mymontage.mtg.

or

edfbrowser --stream myfile.edf mymontage.mtg

this will start the program with the streaming file myfile.edf opened and using the montage mymontage.mtg.


Table of Contents



FAQ


Q. How do I add signals to the screen?

A. Use the signalsdialog.


Q. How can I change the amplitude of a signal?

A. Leftclick on the signallabel of that signal. A small dialog will appear. There is a
spinbox that will let you change the amplitude of the signal.
Another way is to rightclick on the signallabel and move the mousepointer up or down
while keeping the right mousebutton pressed. This will increase or decrease the amplitude
of the signal on the screen.

Q. How can I see the value of a signal?

A. Use a crosshair.


Q. I added signals from multiple files but some of them are not visible on the screen.

A. Go to the "Time" menu and set it to "Synchronize start of files".
Then select Time -> Go to start of file.
Now select Amplitude -> Fit to pane.


Q. I want to open two files in different windows.

A. Start the program twice and you can open files in different windows.


Q. When I try to open a file, it says that the file is not EDF(+)/BDF(+) compliant.
What do I do?

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

Q. How can I combine multiple EDF/BDF files?

A. Use the Print to EDF function.


Q. What is the difference between EDF and BDF?

A. The difference is the resolution. In EDF the maximum resolution is 16 bits, so the ratio
between the smallest and the largest value is 1 to 2^16 or 1:65536.
In BDF the resolution is 24 bits, so the ratio between the smallest and the largest value is
1 to 2^24 or 1:16777216. In other words, the dynamic range of a BDF file is much higher.
BDF is the 24-bits version of EDF, invented because more and more ADC's/aquisition systems use
24-bits analoog to digital converters. When you try to store the data from a 24-bits ADC into EDF,
you will lose information.


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

A. In the printerdialog, choose "landscape" and the right papersize (A4) and
adjust the margins in the printerproperties.
For example, set top and bottom margins to 0.85 cm and the left and right margins to 1.27 cm.


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

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


Q. Why are the annotationmarkers not visible?

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


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

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


Q. What are the system requirements?

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


Q. Which operatingsystems are supported?

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


Q. Which license is used for the program?

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


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

A. First check if you are using the latest version of EDFbrowser.
If the bug persists, send an email to teuniz@gmail.com


Table of Contents














edfbrowser_157_source/PaxHeaders.7921/load_montage_dialog.h0000644000000000000000000000012712646460742021013 xustar0029 mtime=1452958178.23924676 29 atime=1452958178.23924676 29 ctime=1452958178.23924676 edfbrowser_157_source/load_montage_dialog.h0000644000175000001440000000406012646460742021350 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef LOADMONTAGEFORM1_H #define LOADMONTAGEFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "xml.h" #include "filter.h" #include "spike_filter.h" #include "utc_date_time.h" #include "utils.h" #include "spectrum_dock.h" #include "third_party/fidlib/fidlib.h" class UI_Mainwindow; class UI_LoadMontagewindow : public QObject { Q_OBJECT public: UI_LoadMontagewindow(QWidget *parent, char *path = NULL); UI_Mainwindow *mainwindow; private: QDialog *LoadMontageDialog; QLabel *label1; QListWidget *filelist; QPushButton *CloseButton, *LoadButton; char mtg_path[MAX_PATH_LENGTH]; void strip_types_from_label(char *); private slots: void LoadButtonClicked(); }; #endif // LOADMONTAGEFORM1_H edfbrowser_157_source/PaxHeaders.7921/spectrumanalyzer.h0000644000000000000000000000013212646460742020447 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/spectrumanalyzer.h0000644000175000001440000000642412646460742021016 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef SPECTRUMANALYZER_H #define SPECTRUMANALYZER_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "signalcurve.h" #include "utils.h" #include "filter.h" #include "spike_filter.h" #include "ravg_filter.h" #include "flywheel.h" #include "third_party/fidlib/fidlib.h" #include "third_party/kiss_fft/kiss_fftr.h" class UI_Mainwindow; class UI_FreqSpectrumWindow : public QThread { Q_OBJECT public: UI_FreqSpectrumWindow(struct signalcompblock *, char *, UI_FreqSpectrumWindow **, int, QWidget *); ~UI_FreqSpectrumWindow(); UI_Mainwindow *mainwindow; QDialog *SpectrumDialog; struct signalcompblock *signalcomp; private: QHBoxLayout *hlayout1, *hlayout2, *hlayout3, *hlayout4; QVBoxLayout *vlayout1, *vlayout2, *vlayout3; SignalCurve *curve1; QTimer *t1; QSlider *amplitudeSlider, *spanSlider, *centerSlider, *log_minslider; QLabel *spanLabel, *centerLabel, *amplitudeLabel; QCheckBox *sqrtCheckBox, *VlogCheckBox, *BWCheckBox; UI_Flywheel *flywheel1; int samples, steps, dftblocksize, dftblocks, spectrumdialog_is_destroyed, class_is_deleted, spectrumdialognumber, flywheel_value; volatile int busy, malloc_err; double samplefreq, freqstep, maxvalue, maxvalue_sqrt, maxvalue_vlog, maxvalue_sqrt_vlog, minvalue_vlog, minvalue_sqrt_vlog, *buf1, *buf2, *buf3, *buf4, *buf5; char *viewbuf, signallabel[512], physdimension[9]; UI_FreqSpectrumWindow **spectrumdialog; void run(); private slots: void update_curve(); void sliderMoved(int); void SpectrumDialogDestroyed(QObject *); void print_to_txt(); void update_flywheel(int); void thr_finished_func(); }; #endif edfbrowser_157_source/PaxHeaders.7921/signals_dialog.h0000644000000000000000000000013212646460742020016 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/signals_dialog.h0000644000175000001440000000530612646460742020363 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef SIGNALSFORM1_H #define SIGNALSFORM1_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "mainwindow.h" #include "colordialog.h" #include "utc_date_time.h" #include "special_button.h" #include "utils.h" class UI_Mainwindow; class UI_Signalswindow : public QObject { Q_OBJECT public: UI_Signalswindow(QWidget *parent); UI_Mainwindow *mainwindow; private: QDialog *SignalsDialog; QListWidget *filelist, *signallist, *compositionlist; QLabel *label1, *label2, *label3, *label4, *label5, *label6, *colorlabel; QPushButton *CloseButton, *SelectAllButton, *DisplayButton, *DisplayCompButton, *AddButton, *SubtractButton, *RemoveButton, *HelpButton; SpecialButton *ColorButton; int smp_per_record, curve_color; char physdimension[64]; double bitvalue; void strip_types_from_label(char *); private slots: void show_signals(int); void SelectAllButtonClicked(); void DisplayButtonClicked(); void DisplayCompButtonClicked(); void AddButtonClicked(); void SubtractButtonClicked(); void RemoveButtonClicked(); void ColorButtonClicked(SpecialButton *); void HelpButtonClicked(); }; #endif // SIGNALSFORM1_H edfbrowser_157_source/PaxHeaders.7921/spike_filter.h0000644000000000000000000000013212646460742017517 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/spike_filter.h0000644000175000001440000000427512646460742020070 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef spike_filter_INCLUDED #define spike_filter_INCLUDED #include #include #include #define SPIKEFILTER_SPIKE_NO 0 #define SPIKEFILTER_SPIKE_ONSET 1 struct spike_filter_settings{ int sf; int holdoff; int holdoff_sav; int holdoff_set; int cutoff; int cutoff_sav; int spikewidth; int spikewidth_sav; double array[1024]; double array_sav[1024]; int idx; int idx_sav; int n_max; int bufsz; double velocity; int polarity; int polarity_sav; int flank_det; int flank_det_sav; int flank_det_set; int run_in; int run_in_sav; double base_smpl; double base_smpl_sav; int spike_pos; int spike_pos_sav; int *pd_sig; }; struct spike_filter_settings * create_spike_filter(int, double, int, int *); double run_spike_filter(double, struct spike_filter_settings *); void free_spike_filter(struct spike_filter_settings *); void reset_spike_filter(struct spike_filter_settings *); struct spike_filter_settings * create_spike_filter_copy(struct spike_filter_settings *); void spike_filter_save_buf(struct spike_filter_settings *); void spike_filter_restore_buf(struct spike_filter_settings *); #endif edfbrowser_157_source/PaxHeaders.7921/manscan2edf.cpp0000644000000000000000000000013212646460742017553 xustar0030 mtime=1452958178.247246733 30 atime=1452958178.247246733 30 ctime=1452958178.247246733 edfbrowser_157_source/manscan2edf.cpp0000644000175000001440000011750212646460742020122 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "manscan2edf.h" #define MBILINEBUFSZ 4096 #define MBIMAXEVENTS 10000 #define MBIMAXEVLEN 40 struct segment_prop_struct{ long long data_offset; int sweeps; int channels; int samplefrequency; int sec_duration; char label[MAXSIGNALS][17]; double gain[MAXSIGNALS]; int startdate_year; int startdate_month; int startdate_day; int starttime_hour; int starttime_minute; int starttime_second; double hpf; double lpf; char recorder_version[128]; char recorder_brand[128]; char datafilename[MAX_PATH_LENGTH]; long long starttime_offset; int ev_cnt; long long ev_onset[MBIMAXEVENTS]; long long ev_duration[MBIMAXEVENTS]; char ev_description[MBIMAXEVENTS][MBIMAXEVLEN + 1]; }; UI_MANSCAN2EDFwindow::UI_MANSCAN2EDFwindow(char *recent_dir, char *save_dir) { char txt_string[2048]; recent_opendir = recent_dir; recent_savedir = save_dir; myobjectDialog = new QDialog; myobjectDialog->setMinimumSize(600, 480); myobjectDialog->setMaximumSize(600, 480); myobjectDialog->setWindowTitle("Manscan to EDF+ converter"); myobjectDialog->setModal(true); myobjectDialog->setAttribute(Qt::WA_DeleteOnClose, true); 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"); textEdit1 = new QTextEdit(myobjectDialog); textEdit1->setGeometry(20, 20, 560, 380); textEdit1->setFrameStyle(QFrame::Panel | QFrame::Sunken); textEdit1->setReadOnly(true); textEdit1->setLineWrapMode(QTextEdit::NoWrap); sprintf(txt_string, "Manscan MICROAMPS binary data to EDF+ converter.\n"); textEdit1->append(txt_string); QObject::connect(pushButton1, SIGNAL(clicked()), this, SLOT(SelectFileButton())); QObject::connect(pushButton2, SIGNAL(clicked()), myobjectDialog, SLOT(close())); myobjectDialog->exec(); } void UI_MANSCAN2EDFwindow::SelectFileButton() { FILE *header_inputfile=NULL, *data_inputfile=NULL; int i, j, k, n, tmp, hdl, chns=0, sf, blocks, *buf, progress_steps, segment_cnt, n_segments=0; long long filesize, ll_tmp; char header_filename[MAX_PATH_LENGTH], txt_string[2048], edf_filename[MAX_PATH_LENGTH], data_filename[MAX_PATH_LENGTH], scratchpad[MAX_PATH_LENGTH]; double d_tmp; struct segment_prop_struct *segment_properties; union{ int one; char four[4]; } var; struct date_time_struct dtm_struct; pushButton1->setEnabled(false); strcpy(header_filename, QFileDialog::getOpenFileName(0, "Select inputfile", QString::fromLocal8Bit(recent_opendir), "MBI files (*.mbi *.MBI)").toLocal8Bit().data()); if(!strcmp(header_filename, "")) { pushButton1->setEnabled(true); return; } get_directory_from_path(recent_opendir, header_filename, MAX_PATH_LENGTH); header_inputfile = fopeno(header_filename, "rb"); if(header_inputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for reading.\n", header_filename); textEdit1->append(QString::fromLocal8Bit(txt_string)); pushButton1->setEnabled(true); return; } get_filename_from_path(scratchpad, header_filename, MAX_PATH_LENGTH); snprintf(txt_string, 2048, "Read file: %s", scratchpad); textEdit1->append(QString::fromLocal8Bit(txt_string)); fseeko(header_inputfile, 0LL, SEEK_END); filesize = ftello(header_inputfile); if(filesize<10) { textEdit1->append("Error, filesize is too small.\n"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } segment_properties = (struct segment_prop_struct *)malloc(sizeof(struct segment_prop_struct)); if(segment_properties == NULL) { textEdit1->append("Malloc error (struct segment_prop_struct)"); fclose(header_inputfile); pushButton1->setEnabled(true); return; } n_segments = get_number_of_segments(header_inputfile); ////////////////// start segment processing /////////////////////////////////////////// for(segment_cnt=0; segment_cnt < n_segments; segment_cnt++) { memset(segment_properties, 0, sizeof(struct segment_prop_struct)); for(i=0; ilabel[i], "ch.%i", i + 1); segment_properties->gain[i] = 1.0; } segment_properties->samplefrequency = 256; if(get_worddatafile(segment_properties, segment_cnt, header_inputfile)) { textEdit1->append("Error, can not find or process item \"WordDataFile\".\n"); fclose(header_inputfile); free(segment_properties); pushButton1->setEnabled(true); return; } if(get_channel_gain(segment_properties, segment_cnt, header_inputfile)) { textEdit1->append("Error, can not find or process item \"Channel gain\".\n"); fclose(header_inputfile); free(segment_properties); pushButton1->setEnabled(true); return; } if(get_start_date(segment_properties, segment_cnt, header_inputfile)) { textEdit1->append("Error, can not find or process item \"Startdate\".\n"); fclose(header_inputfile); free(segment_properties); pushButton1->setEnabled(true); return; } if(get_sample_rate(segment_properties, segment_cnt, header_inputfile)) { textEdit1->append("Error, can not find or process item \"SampleRate\".\n"); fclose(header_inputfile); free(segment_properties); pushButton1->setEnabled(true); return; } if(get_filter_settings(segment_properties, segment_cnt, header_inputfile)) { textEdit1->append("Error, can not find or process item \"Filtersettings\".\n"); fclose(header_inputfile); free(segment_properties); pushButton1->setEnabled(true); return; } if(get_recorder_version(segment_properties, segment_cnt, header_inputfile)) { textEdit1->append("Error, can not find or process item \"Filtersettings\".\n"); fclose(header_inputfile); free(segment_properties); pushButton1->setEnabled(true); return; } if(get_starttime_offset(segment_properties, segment_cnt, header_inputfile)) { textEdit1->append("Error, can not find or process item \"Starttime offset\".\n"); fclose(header_inputfile); free(segment_properties); pushButton1->setEnabled(true); return; } if(get_events(segment_properties, segment_cnt, header_inputfile)) { textEdit1->append("Error, can not find or process item \"Events\".\n"); fclose(header_inputfile); free(segment_properties); pushButton1->setEnabled(true); return; } segment_properties->sec_duration = segment_properties->sweeps / segment_properties->samplefrequency; // for(i=0; iev_cnt; i++) // { // printf("%s %lli %lli\n", segment_properties->ev_description[i], segment_properties->ev_onset[i], segment_properties->ev_duration[i]); // } // // for(i=0; ichannels; i++) // { // printf("%s %.10f\n", segment_properties->label[i], segment_properties->gain[i]); // } // printf("data_offset is %lli sweeps is %i datafileheader_filename is %s\n", segment_properties->data_offset, segment_properties->sweeps, segment_properties->datafilename); // // printf("startdate_day is %i startdate_month is %i startdate_year is %i\n", segment_properties->startdate_day, segment_properties->startdate_month, segment_properties->startdate_year); // // printf("starttime is: %02i:%02i:%02i starttime offset is: %lli\n", segment_properties->starttime_hour, segment_properties->starttime_minute, segment_properties->starttime_second, segment_properties->starttime_offset); // // printf("samplerate is: %i hpf is %f lpf is %f\n", segment_properties->samplefrequency, segment_properties->hpf, segment_properties->lpf); // // printf("recorder version: %s recorder brand: %s\n", segment_properties->recorder_version, segment_properties->recorder_brand); // // printf("recording duration: %i seconds\n", segment_properties->sec_duration); chns = segment_properties->channels; sf = segment_properties->samplefrequency; blocks = segment_properties->sec_duration; if(blocks < 1) { snprintf(txt_string, 2048, "Skipping segment %i because it's shorter dan one second.", segment_cnt + 1); textEdit1->append(txt_string); continue; } buf = (int *)malloc(sf * chns * sizeof(int)); if(buf == NULL) { textEdit1->append("Malloc() error (buf)\n"); fclose(header_inputfile); free(segment_properties); pushButton1->setEnabled(true); return; } strcpy(edf_filename, header_filename); remove_extension_from_filename(edf_filename); if(n_segments > 1) { sprintf(edf_filename + strlen(edf_filename), "_%02i", segment_cnt + 1); } strcat(edf_filename, ".edf"); get_directory_from_path(data_filename, header_filename, MAX_PATH_LENGTH - 1); strcat(data_filename, "/"); strcat(data_filename, segment_properties->datafilename); data_inputfile = fopeno(data_filename, "rb"); if(data_inputfile==NULL) { snprintf(txt_string, 2048, "Can not open file %s for reading.\n", data_filename); textEdit1->append(QString::fromLocal8Bit(txt_string)); fclose(header_inputfile); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } fseeko(data_inputfile, 0LL, SEEK_END); filesize = ftello(data_inputfile); if(filesize < (segment_properties->data_offset + (chns * 2))) { textEdit1->append("Error, filesize is too small.\n"); fclose(header_inputfile); fclose(data_inputfile); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } n = (filesize - segment_properties->data_offset) / (chns * 2); if(n < segment_properties->sweeps) { segment_properties->sweeps = n; snprintf(txt_string, 2048, "Warning: samples in datafile are less than in headerfile."); textEdit1->append(txt_string); } get_filename_from_path(scratchpad, edf_filename, MAX_PATH_LENGTH - 1); snprintf(txt_string, 2048, "Convert a segment to %s ...", scratchpad); textEdit1->append(txt_string); hdl = edfopen_file_writeonly(edf_filename, EDFLIB_FILETYPE_EDFPLUS, chns); if(hdl<0) { snprintf(txt_string, 2048, "Can not open file %s for writing.\n", edf_filename); textEdit1->append(QString::fromLocal8Bit(txt_string)); fclose(header_inputfile); fclose(data_inputfile); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } for(i=0; iappend("Error: edf_set_samplefrequency()\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } } for(i=0; iappend("Error: edf_set_digital_minimum()\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } } for(i=0; iappend("Error: edf_set_digital_maximum()\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } } for(i=0; ilabel[i])) { textEdit1->append("Error: edf_set_label()\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } } for(i=0; igain[i] > 0.999) { d_tmp = 32767.0 / segment_properties->gain[i]; strcpy(scratchpad, "uV"); } else { d_tmp = 32.767 / segment_properties->gain[i]; strcpy(scratchpad, "mV"); } if(edf_set_physical_dimension(hdl, i, scratchpad)) { textEdit1->append("Error: edf_set_physical_dimension()\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } if(edf_set_physical_maximum(hdl, i, d_tmp)) { textEdit1->append("Error: edf_set_physical_maximum()\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } if(edf_set_physical_minimum(hdl, i, -(d_tmp))) { textEdit1->append("Error: edf_set_physical_minimum()\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } } dtm_struct.year = segment_properties->startdate_year; dtm_struct.month = segment_properties->startdate_month; dtm_struct.day = segment_properties->startdate_day; dtm_struct.hour = segment_properties->starttime_hour; dtm_struct.minute = segment_properties->starttime_minute; dtm_struct.second = segment_properties->starttime_second; date_time_to_utc(&ll_tmp, dtm_struct); ll_tmp += segment_properties->starttime_offset / TIME_DIMENSION; utc_to_date_time(ll_tmp, &dtm_struct); if(edf_set_startdatetime(hdl, dtm_struct.year, dtm_struct.month, dtm_struct.day, dtm_struct.hour, dtm_struct.minute, dtm_struct.second)) { textEdit1->append("Error: edf_set_startdatetime()\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } if(edf_set_equipment(hdl, segment_properties->recorder_brand)) { textEdit1->append("Error: edf_set_equipment()\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } if(edf_set_recording_additional(hdl, segment_properties->recorder_version)) { textEdit1->append("Error: edf_set_recording_additional()\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } scratchpad[0] = 0; if(segment_properties->hpf > 0.0001) { sprintf(scratchpad + strlen(scratchpad), "HP:%f", segment_properties->hpf); remove_trailing_zeros(scratchpad); strcat(scratchpad, "Hz "); } if(segment_properties->lpf > 0.0001) { sprintf(scratchpad + strlen(scratchpad), "LP:%f", segment_properties->lpf); remove_trailing_zeros(scratchpad); strcat(scratchpad, "Hz "); } for(i=0; iappend("Error: edf_set_prefilter()\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } } ////////////////// start conversion /////////////////////////////////////////// QProgressDialog progress("Converting a segment...", "Abort", 0, blocks); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); progress_steps = blocks / 100; if(progress_steps < 1) { progress_steps = 1; } fseeko(data_inputfile, segment_properties->data_offset, SEEK_SET); for(i=0; iprocessEvents(); if(progress.wasCanceled() == true) { textEdit1->append("Conversion aborted by user.\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } } for(j=0; jappend("A read error occurred during conversion.\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } var.four[3] = tmp; buf[(k * sf) + j] = (var.one >> 16); } } if(edf_blockwrite_digital_samples(hdl, buf)) { progress.reset(); textEdit1->append("A write error occurred during conversion.\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } } progress.reset(); ////////////////// end of conversion /////////////////////////////////////////// if(edfwrite_annotation_latin1(hdl, 0LL, -1LL, "Recording starts")) { textEdit1->append("Error: edfwrite_annotation_latin1()\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } for(i=0; iev_cnt; i++) { if(edfwrite_annotation_latin1(hdl, segment_properties->ev_onset[i], segment_properties->ev_duration[i], segment_properties->ev_description[i])) { textEdit1->append("Error: edfwrite_annotation_latin1()\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } } if(edfwrite_annotation_latin1(hdl, (long long)blocks * 10000LL, -1LL, "Recording ends")) { textEdit1->append("Error: edfwrite_annotation_latin1()\n"); fclose(header_inputfile); fclose(data_inputfile); edfclose_file(hdl); free(buf); free(segment_properties); pushButton1->setEnabled(true); return; } fclose(data_inputfile); edfclose_file(hdl); free(buf); textEdit1->append("... conversion of segment done."); } ////////////////// end of segment processing /////////////////////////////////////////// fclose(header_inputfile); free(segment_properties); textEdit1->append("Ready.\n"); pushButton1->setEnabled(true); } int UI_MANSCAN2EDFwindow::get_events(struct segment_prop_struct *segprop, int segment, FILE *inputfile) { int i, order=0, startsmpl, durationsmpl, ev_cnt=0, segment_cnt=0; char linebuf[MBILINEBUFSZ], annot_descr[MBIMAXEVLEN + 1]; long long onset, duration, sf; sf = segprop->samplefrequency; rewind(inputfile); while(segment_cnt != segment) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(0); } strntolower(linebuf, 11); if(!(strncmp(linebuf, "datatypeid ", 11))) { segment_cnt++; } } while(1) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(0); } strntolower(linebuf, 11); if(!(strncmp(linebuf, "datatypeid ", 11))) { return(0); } strntolower(linebuf, 33); if((!(strncmp(linebuf, "event beginsample durationsamples", 33))) || (!(strncmp(linebuf, "event durationsamples beginsample", 33)))) { if(!(strncmp(linebuf, "event beginsample durationsamples", 33))) { order = 1; } else { order = 0; } if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(0); } strntolower(linebuf, 22); if(!(strncmp(linebuf, "string integer integer", 22))) { for(i=0; ; i++) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(-1); } if(strlen(linebuf) == 0) { break; } if(strlen(linebuf) < 5) { return(-1); } if(order) { if(sscanf(linebuf, "%40s %i %i", annot_descr, &startsmpl, &durationsmpl) != 3) { return(-1); } } else { if(sscanf(linebuf, "%40s %i %i", annot_descr, &durationsmpl, &startsmpl) != 3) { return(-1); } } if(startsmpl < 0) { continue; } onset = ((long long)startsmpl * 10000LL) / sf; if(durationsmpl < 2) { duration = -1LL; } else { duration = ((long long)durationsmpl * 10000LL) / sf; } strcpy(segprop->ev_description[ev_cnt], annot_descr); segprop->ev_onset[ev_cnt] = onset; segprop->ev_duration[ev_cnt] = duration; segprop->ev_cnt = ++ev_cnt; if(ev_cnt >= MBIMAXEVENTS) { return(0); } } } else { continue; } } } return(0); } int UI_MANSCAN2EDFwindow::get_starttime_offset(struct segment_prop_struct *segprop, int segment, FILE *inputfile) { int segment_cnt=0; char linebuf[MBILINEBUFSZ]; long long time; rewind(inputfile); while(segment_cnt != segment) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(0); } strntolower(linebuf, 11); if(!(strncmp(linebuf, "datatypeid ", 11))) { segment_cnt++; } } while(1) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(0); } strntolower(linebuf, 11); if(!(strncmp(linebuf, "datatypeid ", 11))) { return(0); } strntolower(linebuf, 24); if(!(strncmp(linebuf, "offsetdisplayexperiment ", 24))) { break; } } if(strlen(linebuf) < 25) { return(-1); } time = get_long_time(linebuf + 24); segprop->starttime_offset = time; return(0); } int UI_MANSCAN2EDFwindow::get_recorder_version(struct segment_prop_struct *segprop, int segment, FILE *inputfile) { int segment_cnt=0; char linebuf[MBILINEBUFSZ]; rewind(inputfile); while(segment_cnt != segment) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(0); } strntolower(linebuf, 11); if(!(strncmp(linebuf, "datatypeid ", 11))) { segment_cnt++; } } while(1) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(0); } strntolower(linebuf, 11); if(!(strncmp(linebuf, "datatypeid ", 11))) { return(0); } strntolower(linebuf, 25); if(!(strncmp(linebuf, "comment recorder version ", 25))) { break; } } if(strlen(linebuf) < 26) { return(-1); } strncpy(segprop->recorder_version, linebuf + 25, 100); return(0); } int UI_MANSCAN2EDFwindow::get_filter_settings(struct segment_prop_struct *segprop, int segment, FILE *inputfile) { int segment_cnt=0; char linebuf[MBILINEBUFSZ], *chrpntr; double lpf, hpf; rewind(inputfile); while(segment_cnt != segment) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(0); } strntolower(linebuf, 11); if(!(strncmp(linebuf, "datatypeid ", 11))) { segment_cnt++; } } while(1) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(0); } strntolower(linebuf, 11); if(!(strncmp(linebuf, "datatypeid ", 11))) { return(0); } strntolower(linebuf, 18); if(!(strncmp(linebuf, "comment microamps ", 18))) { break; } } if(strlen(linebuf) < 53) { return(-1); } strncpy(segprop->recorder_brand, linebuf + 8, 13); chrpntr = linebuf + 18; chrpntr = strchr(chrpntr, ' '); if(chrpntr == NULL) { return(-1); } chrpntr++; if(strncmp(chrpntr, "highpass ", 9)) { return(-1); } chrpntr = strchr(chrpntr, ' '); if(chrpntr == NULL) { return(-1); } chrpntr++; hpf = atof(chrpntr); if((hpf < 0.000001) || (hpf > 100000.0)) { return(-1); } chrpntr = strchr(chrpntr, ' '); if(chrpntr == NULL) { return(-1); } chrpntr++; if(strncmp(chrpntr, "hz, ", 4)) { return(-1); } chrpntr = strchr(chrpntr, ' '); if(chrpntr == NULL) { return(-1); } chrpntr++; if(strncmp(chrpntr, "lowpass ", 8)) { return(-1); } chrpntr++; chrpntr = strchr(chrpntr, ' '); if(chrpntr == NULL) { return(-1); } chrpntr++; lpf = atof(chrpntr); if((lpf < 0.000001) || (lpf > 100000.0)) { return(-1); } chrpntr = strchr(chrpntr, ' '); if(chrpntr == NULL) { return(-1); } chrpntr++; if(strncmp(chrpntr, "hz", 2)) { return(-1); } segprop->hpf = hpf; segprop->lpf = lpf; return(0); } int UI_MANSCAN2EDFwindow::get_sample_rate(struct segment_prop_struct *segprop, int segment, FILE *inputfile) { int sf, segment_cnt=0; char linebuf[MBILINEBUFSZ]; double d_tmp; rewind(inputfile); while(segment_cnt != segment) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(0); } strntolower(linebuf, 11); if(!(strncmp(linebuf, "datatypeid ", 11))) { segment_cnt++; } } while(1) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(0); } strntolower(linebuf, 11); if(!(strncmp(linebuf, "datatypeid ", 11))) { return(0); } strntolower(linebuf, 11); if(!(strncmp(linebuf, "samplerate ", 11))) { if(strlen(linebuf) < 12) { return(-1); } break; } strntolower(linebuf, 16); if(!(strncmp(linebuf, "sampletodisplay ", 16))) { if(strlen(linebuf) < 17) { return(-1); } break; } } if(!(strncmp(linebuf, "samplerate ", 11))) { sf = atoi(linebuf + 11); } else { d_tmp = atof(linebuf + 16); if(d_tmp < 0.00001) { return(-1); } d_tmp = 1.0 / d_tmp; sf = d_tmp; d_tmp -= sf; if(d_tmp > 0.5) { sf++; } } if((sf < 1) || (sf > 100000)) { return(-1); } segprop->samplefrequency = sf; return(0); } int UI_MANSCAN2EDFwindow::get_start_date(struct segment_prop_struct *segprop, int segment, FILE *inputfile) { int p, p2, len, segment_cnt=0, starttime_second, starttime_minute, starttime_hour, startdate_day, startdate_month, startdate_year; char linebuf[MBILINEBUFSZ]; rewind(inputfile); while(segment_cnt != segment) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(-1); } strntolower(linebuf, 11); if(!(strncmp(linebuf, "datatypeid ", 11))) { segment_cnt++; } } while(1) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(-1); } strntolower(linebuf, 11); if(!(strncmp(linebuf, "datatypeid ", 11))) { return(-1); } strntolower(linebuf, 15); if(!(strncmp(linebuf, "experimenttime ", 15))) { break; } } len = strlen(linebuf); if(len < 23) { return(-1); } p = 15; if(((linebuf[p+2] != '/') || (linebuf[p+5] != '/')) && ((linebuf[p+2] != '-') || (linebuf[p+5] != '-'))) { return(-1); } if((linebuf[p] < '0') || (linebuf[p] > '9') || (linebuf[p+1] < '0') || (linebuf[p+1] > '9') || (linebuf[p+3] < '0') || (linebuf[p+3] > '9') || (linebuf[p+4] < '0') || (linebuf[p+4] > '9') || (linebuf[p+6] < '0') || (linebuf[p+6] > '9') || (linebuf[p+7] < '0') || (linebuf[p+7] > '9')) { return(-1); } if((len - p) > 9) { if((linebuf[p+8] >= '0') && (linebuf[p+8] <= '9') && (linebuf[p+9] >= '0') && (linebuf[p+9] <= '9')) { startdate_year = atoi(linebuf + p + 6); p2 = p + 10; } else { startdate_year = atoi(linebuf + p + 6); if(startdate_year >= 70) { startdate_year += 1900; } else { startdate_year += 2000; } p2 = p + 8; } } else { startdate_year = atoi(linebuf + p + 6); if(startdate_year >= 70) { startdate_year += 1900; } else { startdate_year += 2000; } p2 = p + 8; } startdate_day = atoi(linebuf + p + 3); startdate_month = atoi(linebuf + p); if((startdate_day < 1) || (startdate_day > 31) || (startdate_month < 1) || (startdate_month > 12)) { return(-1); } segprop->startdate_day = startdate_day; segprop->startdate_month = startdate_month; segprop->startdate_year = startdate_year; p = p2; if(linebuf[p] == ' ') { p++; if((len - p) > 7) { if((linebuf[p+2] == ':') && (linebuf[p+5] == ':')) { if((linebuf[p] < '0') || (linebuf[p] > '9') || (linebuf[p+1] < '0') || (linebuf[p+1] > '9') || (linebuf[p+3] < '0') || (linebuf[p+3] > '9') || (linebuf[p+4] < '0') || (linebuf[p+4] > '9') || (linebuf[p+6] < '0') || (linebuf[p+6] > '9') || (linebuf[p+7] < '0') || (linebuf[p+7] > '9')) { return(-1); } starttime_hour = atoi(linebuf + p); starttime_minute = atoi(linebuf + p + 3); starttime_second = atoi(linebuf + p + 6); if((starttime_hour < 0) || (starttime_hour > 23)) { starttime_hour = 0; starttime_minute = 0; starttime_second = 0; return(-1); } if((starttime_minute < 0) || (starttime_minute > 59)) { starttime_hour = 0; starttime_minute = 0; starttime_second = 0; return(-1); } if((starttime_second < 0) || (starttime_second > 59)) { starttime_hour = 0; starttime_minute = 0; starttime_second = 0; return(-1); } segprop->starttime_hour = starttime_hour; segprop->starttime_minute = starttime_minute; segprop->starttime_second = starttime_second; } } } return(0); } int UI_MANSCAN2EDFwindow::get_channel_gain(struct segment_prop_struct *segprop, int segment, FILE *inputfile) { int i, j, len, segment_cnt=0, channels, column; char linebuf[MBILINEBUFSZ], *chrpntr, label[17]; double gain; channels = segprop->channels; if((channels < 1) || (channels > MAXSIGNALS)) { return(-1); } rewind(inputfile); while(segment_cnt != segment) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(-1); } strntolower(linebuf, 11); if(!(strncmp(linebuf, "datatypeid ", 11))) { segment_cnt++; } } while(1) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(-1); } strntolower(linebuf, 256); if(!(strncmp(linebuf, "datatypeid ", 11))) { return(-1); } if(!(strncmp(linebuf, "channel ", 8))) { if(strstr(linebuf, "unitdisplaytofile") != NULL) { break; } } } chrpntr = linebuf; for(column=1; ; column++) { chrpntr = strchr(chrpntr, ' ') + 1; if((chrpntr == NULL) || (strlen(chrpntr) < 17)) { return(-1); } if(!(strncmp(chrpntr, "unitdisplaytofile", 17))) { break; } } for(i=0; i 16) { len = 16; } strncpy(label, linebuf, len); label[len] = 0; chrpntr++; for(j=1; j= (linebuf + strlen(linebuf))) { return(-1); } gain = atof(chrpntr); for(j=0; jlabel[j]))) { segprop->gain[j] = gain; break; } } } return(0); } int UI_MANSCAN2EDFwindow::get_worddatafile(struct segment_prop_struct *segprop, int segment, FILE *inputfile) { int i, j, p, len, tmp, segment_cnt=0, channels; char linebuf[MBILINEBUFSZ], scratchpad[256]; rewind(inputfile); while(segment_cnt != segment) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(-1); } strntolower(linebuf, 11); if(!(strncmp(linebuf, "datatypeid ", 11))) { segment_cnt++; } } while(1) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(-1); } strntolower(linebuf, 11); if(!(strncmp(linebuf, "datatypeid ", 11))) { return(-1); } strntolower(linebuf, 12); if(!(strncmp(linebuf, "worddatafile", 12))) { break; } } if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { return(-1); } channels = 0; j = 0; for(i=0; ; i++) { if(linebuf[i] == 0) { if(j > 0) { if(j > 16) { j = 16; } segprop->label[channels][j] = 0; channels++; } break; } if(linebuf[i] == ' ') { if(j > 0) { if(j > 16) { j = 16; } segprop->label[channels][j] = 0; channels++; } j = 0; continue; } if(channels >= MAXSIGNALS) { return(-1); } if(j < 16) { segprop->label[channels][j++] = linebuf[i]; } } if(channels < 1) { return(-1); } segprop->channels = channels; if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) // data offset, sweeps, filename { return(-1); } if(strlen(linebuf) < 9) { return(-1); } for(len=0; ; len++) { if((linebuf[len] == ' ') || (linebuf[len] == 0)) { break; } } if((len < 1) || (len > 255)) { return(-1); } strncpy(scratchpad, linebuf, len); scratchpad[len] = 0; tmp = atoi(scratchpad); // field 1 for(p=len; ; p++) { if((linebuf[p] != ' ') || (linebuf[p] == 0)) { break; } } for(len=0; ; len++) { if((linebuf[p+len] == ' ') || (linebuf[p+len] == 0)) { break; } } if((len < 1) || (len > 255)) { return(-1); } strncpy(scratchpad, linebuf + p, len); scratchpad[len] = 0; segprop->data_offset = atoi(scratchpad); // field 2 segprop->data_offset <<= 32; segprop->data_offset += tmp; for(p+=len; ; p++) { if((linebuf[p] != ' ') || (linebuf[p] == 0)) { break; } } for(len=0; ; len++) { if((linebuf[p+len] == ' ') || (linebuf[p+len] == 0)) { break; } } if((len < 1) || (len > 255)) { return(-1); } strncpy(scratchpad, linebuf + p, len); scratchpad[len] = 0; segprop->sweeps = atoi(scratchpad); // field 3 for(p+=len; ; p++) { if((linebuf[p] != ' ') || (linebuf[p] == 0)) { break; } } for(len=0; ; len++) { if((linebuf[p+len] == ' ') || (linebuf[p+len] == 0)) { break; } } if((len < 3) || (len > 255)) { return(-1); } strncpy(scratchpad, linebuf + p, len); scratchpad[len] = 0; strcpy(segprop->datafilename, scratchpad); // field 4 return(0); } int UI_MANSCAN2EDFwindow::get_number_of_segments(FILE *inputfile) { int segment_cnt=1; char linebuf[MBILINEBUFSZ]; rewind(inputfile); while(1) { if(fgetline(linebuf, MBILINEBUFSZ, inputfile) == NULL) { break; } strntolower(linebuf, 11); if(!(strncmp(linebuf, "datatypeid ", 11))) { segment_cnt++; } } return(segment_cnt); } char * UI_MANSCAN2EDFwindow::fgetline(char *s, int size, FILE *stream) { int i, j, n, spc1=0, spc2=0; char *result; result = fgets(s, size, stream); if(result == NULL) { return(result); } for(i=0; ; i++) { if(s[i] == 0) { break; } if(s[i] == '\t') { s[i] = ' '; } if((s[i] == '\n') || (s[i] == '\r')) { s[i] = 0; break; } } remove_leading_spaces(s); for(i=0; ; i++) { if(s[i] == ' ') { if((spc1 == 0) && (spc2 == 0)) { spc1 = i; } spc2 = i; } else { if(spc1 != spc2) { if(s[i] == 0) { s[spc1] = 0; return(result); } n = spc2 - spc1; for(j=spc1; ; j++) { s[j] = s[j+n]; if(s[j] == 0) { break; } } } spc1 = 0; spc2 = 0; } if(s[i] == 0) { break; } } return(result); } long long UI_MANSCAN2EDFwindow::get_long_time(const char *str) { int i, j=0, len=0, hasdot=0, dotposition=0, decimals=0; long long value=0LL, radix, sign=1LL; for(radix = TIME_DIMENSION; radix > 1LL; radix /=10) { decimals++; } if(str[0] == '+') { str++; } else { if(str[0] == '-') { sign = -1LL; str++; } } for(i=0; ; i++) { if(((str[i]<'0') || (str[i]>'9')) && (str[i]!='.')) { len = i; break; } if(str[i]=='.') { if(hasdot) { len = i; break; } hasdot = 1; dotposition = i; } else { if(hasdot) { if(++j > decimals) { len = i; break; } } } } if(hasdot) { radix = TIME_DIMENSION; for(i=dotposition-1; i>=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } radix = TIME_DIMENSION / 10; for(i=dotposition+1; i=0; i--) { value += ((long long)(str[i] - 48)) * radix; radix *= 10; } } return(value * sign); } edfbrowser_157_source/PaxHeaders.7921/averager_dialog.cpp0000644000000000000000000000013212646460742020505 xustar0030 mtime=1452958178.246246736 30 atime=1452958178.246246736 30 ctime=1452958178.246246736 edfbrowser_157_source/averager_dialog.cpp0000644000175000001440000004251512646460742021055 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #include "averager_dialog.h" UI_AveragerWindow::UI_AveragerWindow(QWidget *w_parent, int annot_nr) { int i, n; long long recording_duration; struct annotationblock *annot; mainwindow = (UI_Mainwindow *)w_parent; averager_dialog = new QDialog(w_parent); averager_dialog->setMinimumSize(600, 400); averager_dialog->setMaximumSize(600, 400); averager_dialog->setWindowTitle("Average waveforms"); averager_dialog->setModal(true); averager_dialog->setAttribute(Qt::WA_DeleteOnClose, true); annotLabel = new QLabel(averager_dialog); annotLabel->setGeometry(20, 20, 100, 25); annotLabel->setText("Use annotation:"); annotNameLabel = new QLabel(averager_dialog); annotNameLabel->setGeometry(130, 20, 200, 25); signalLabel = new QLabel(averager_dialog); signalLabel->setGeometry(340, 20, 100, 25); signalLabel->setText("Select signal(s):"); list = new QListWidget(averager_dialog); list->setGeometry(450, 20, 130, 360); list->setSelectionBehavior(QAbstractItemView::SelectRows); list->setSelectionMode(QAbstractItemView::ExtendedSelection); time1.setHMS(0, 0, 0, 0); recording_duration = (mainwindow->edfheaderlist[0]->datarecords * mainwindow->edfheaderlist[0]->long_data_record_duration) / TIME_DIMENSION; time2.setHMS((recording_duration / 3600) % 24, (recording_duration % 3600) / 60, recording_duration % 60, 0); time1Label = new QLabel(averager_dialog); time1Label->setGeometry(20, 65, 100, 25); time1Label->setText("From (hh:mm:ss)"); timeEdit1 = new QTimeEdit(averager_dialog); timeEdit1->setGeometry(130, 65, 110, 25); timeEdit1->setDisplayFormat("hh:mm:ss.zzz"); timeEdit1->setMinimumTime(QTime(0, 0, 0, 0)); timeEdit1->setMaximumTime(time2); time2Label = new QLabel(averager_dialog); time2Label->setGeometry(20, 110, 100, 25); time2Label->setText("To (hh:mm:ss)"); timeEdit2 = new QTimeEdit(averager_dialog); timeEdit2->setGeometry(130, 110, 110, 25); timeEdit2->setDisplayFormat("hh:mm:ss.zzz"); timeEdit2->setMinimumTime(QTime(0, 0, 0, 0)); timeEdit2->setMaximumTime(time2); timeEdit2->setTime(time2); ratioLabel = new QLabel(averager_dialog); ratioLabel->setGeometry(20, 155, 100, 75); ratioLabel->setText("Ratio of time\n" "before and after\n" "trigger:"); ratioBox = new QComboBox(averager_dialog); ratioBox->setGeometry(130, 180, 100, 25); ratioBox->addItem("10 / 90"); ratioBox->addItem("25 / 75"); ratioBox->addItem("50 / 50"); ratioBox->setCurrentIndex(mainwindow->average_ratio); bufsizeLabel = new QLabel(averager_dialog); bufsizeLabel->setGeometry(20, 250, 100, 25); bufsizeLabel->setText("Average period:"); avg_periodspinbox = new QDoubleSpinBox(averager_dialog); avg_periodspinbox->setGeometry(130, 250, 100, 25); avg_periodspinbox->setDecimals(3); avg_periodspinbox->setRange(0.01, 300.0); avg_periodspinbox->setSuffix(" sec"); avg_periodspinbox->setValue(mainwindow->average_period); CloseButton = new QPushButton(averager_dialog); CloseButton->setGeometry(20, 355, 100, 25); CloseButton->setText("Cancel"); StartButton = new QPushButton(averager_dialog); StartButton->setGeometry(310, 355, 100, 25); StartButton->setText("Start"); for(i=0; isignalcomps; i++) { if(mainwindow->signalcomp[i]->alias[0] != 0) { new QListWidgetItem(mainwindow->signalcomp[i]->alias, list); } else { new QListWidgetItem(mainwindow->signalcomp[i]->signallabel, list); } } list->setCurrentRow(0, QItemSelectionModel::Select); annot = mainwindow->annotationlist[0]; n = annot_nr; while(n) { annot = annot->next_annotation; n--; } strcpy(annot_str, annot->annotation); remove_trailing_spaces(annot_str); annotNameLabel->setText(annot_str); QObject::connect(CloseButton, SIGNAL(clicked()), averager_dialog, SLOT(close())); QObject::connect(StartButton, SIGNAL(clicked()), this, SLOT(startButtonClicked())); averager_dialog->exec(); } void UI_AveragerWindow::startButtonClicked() { int i, j, n, avg_cnt=0, samples_on_screen, trigger_position_ratio=4, dialoglistnumber, itemCnt, progress_steps; char str[MAX_ANNOTATION_LEN + 1], scratchpad[1024]; double avg_max_value, avg_min_value; long long backup_viewtime, backup_timescale, l_time1, l_time2; struct annotationblock *annot; QList itemList; mainwindow->average_period = avg_periodspinbox->value(); mainwindow->average_ratio = ratioBox->currentIndex(); itemList = list->selectedItems(); itemCnt = itemList.size(); if(itemCnt < 1) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "You have to select at least one signal."); messagewindow.exec(); return; } if(itemCnt > MAXAVERAGECURVEDIALOGS) { sprintf(scratchpad,"You can not select more than %i signals.", MAXAVERAGECURVEDIALOGS); QMessageBox messagewindow(QMessageBox::Critical, "Error", scratchpad); messagewindow.exec(); return; } time1 = timeEdit1->time(); time2 = timeEdit2->time(); if(time2.operator<=(time1) == true) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Starttime is higher or equal to stoptime."); messagewindow.exec(); return; } l_time1 = (((time1.hour() * 3600) + (time1.minute() * 60) + (time1.second())) * TIME_DIMENSION) + (time1.msec() * TIME_DIMENSION / 1000LL); l_time2 = (((time2.hour() * 3600) + (time2.minute() * 60) + (time2.second())) * TIME_DIMENSION) + (time2.msec() * TIME_DIMENSION / 1000LL); n = ratioBox->currentIndex(); switch(n) { case 0 : trigger_position_ratio = 10; break; case 1 : trigger_position_ratio = 4; break; case 2 : trigger_position_ratio = 2; break; } backup_viewtime = mainwindow->edfheaderlist[0]->viewtime; backup_timescale = mainwindow->pagetime; mainwindow->pagetime = avg_periodspinbox->value() * TIME_DIMENSION; mainwindow->setup_viewbuf(); mainwindow->signal_averaging_active = 1; n = edfplus_annotation_count(&mainwindow->annotationlist[0]); avg_cnt = 0; for(i=0; iannotationlist[0], i); if(((annot->onset - mainwindow->edfheaderlist[0]->starttime_offset) >= l_time1) && ((annot->onset - mainwindow->edfheaderlist[0]->starttime_offset) <= l_time2)) { strcpy(str, annot->annotation); remove_trailing_spaces(str); if(!strcmp(str, annot_str)) { avg_cnt++; } } } QProgressDialog progress("Averaging ...", "Abort", 0, avg_cnt, averager_dialog); progress.setWindowModality(Qt::WindowModal); progress.setMinimumDuration(200); progress.reset(); progress_steps = avg_cnt / 100; if(progress_steps < 1) { progress_steps = 1; } for(j=0; javeragecurvedialog[i] == NULL) { dialoglistnumber = i; break; } } if(i >= MAXAVERAGECURVEDIALOGS) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Too many \"Average\" windows are open.\nClose some first."); messagewindow.exec(); mainwindow->edfheaderlist[0]->viewtime = backup_viewtime; mainwindow->pagetime = backup_timescale; mainwindow->signal_averaging_active = 0; mainwindow->setup_viewbuf(); return; } signal_nr = list->row(itemList.at(j)); if(mainwindow->signalcomp[signal_nr]->samples_on_screen > 2147483646LL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "Too many samples in buf."); messagewindow.exec(); mainwindow->edfheaderlist[0]->viewtime = backup_viewtime; mainwindow->pagetime = backup_timescale; mainwindow->signal_averaging_active = 0; mainwindow->setup_viewbuf(); return; } samples_on_screen = mainwindow->signalcomp[signal_nr]->samples_on_screen; avgbuf = (double *)calloc(1, sizeof(double) * samples_on_screen); if(avgbuf == NULL) { QMessageBox messagewindow(QMessageBox::Critical, "Error", "The system was not able to provide enough resources (memory) to perform the requested action."); messagewindow.exec(); mainwindow->edfheaderlist[0]->viewtime = backup_viewtime; mainwindow->pagetime = backup_timescale; mainwindow->signal_averaging_active = 0; mainwindow->setup_viewbuf(); return; } n = edfplus_annotation_count(&mainwindow->annotationlist[0]); avg_cnt = 0; for(i=0; iannotationlist[0], i); if(((annot->onset - mainwindow->edfheaderlist[0]->starttime_offset) >= l_time1) && ((annot->onset - mainwindow->edfheaderlist[0]->starttime_offset) <= l_time2)) { strcpy(str, annot->annotation); remove_trailing_spaces(str); if(!strcmp(str, annot_str)) { if(!(avg_cnt % progress_steps)) { progress.setValue(avg_cnt); qApp->processEvents(); if(progress.wasCanceled() == true) { free(avgbuf); mainwindow->edfheaderlist[0]->viewtime = backup_viewtime; mainwindow->pagetime = backup_timescale; mainwindow->signal_averaging_active = 0; mainwindow->setup_viewbuf(); return; } } mainwindow->edfheaderlist[0]->viewtime = annot->onset; mainwindow->edfheaderlist[0]->viewtime -= mainwindow->edfheaderlist[0]->starttime_offset; mainwindow->edfheaderlist[0]->viewtime -= (mainwindow->pagetime / trigger_position_ratio); mainwindow->setup_viewbuf(); process_avg(mainwindow->signalcomp[signal_nr]); avg_cnt++; } } } progress.reset(); if(!avg_cnt) { sprintf(scratchpad, "The selected annotation/trigger \"%s\" is not in the selected timewindow\n" "%i:%02i:%02i - %i:%02i:%02i", annot_str, timeEdit1->time().hour(), timeEdit1->time().minute(), timeEdit1->time().second(), timeEdit2->time().hour(), timeEdit2->time().minute(), timeEdit2->time().second()); QMessageBox messagewindow(QMessageBox::Critical, "Error", scratchpad); messagewindow.exec(); free(avgbuf); mainwindow->edfheaderlist[0]->viewtime = backup_viewtime; mainwindow->pagetime = backup_timescale; mainwindow->signal_averaging_active = 0; mainwindow->setup_viewbuf(); return; } avg_max_value = -100000000.0; avg_min_value = 100000000.0; for(i=0; i avg_max_value) { avg_max_value = avgbuf[i]; } if(avgbuf[i] < avg_min_value) { avg_min_value = avgbuf[i]; } } mainwindow->averagecurvedialog[dialoglistnumber] = new UI_AverageCurveWindow(mainwindow->signalcomp[signal_nr], mainwindow, dialoglistnumber, avgbuf, avg_max_value, avg_min_value, mainwindow->pagetime, mainwindow->signalcomp[signal_nr]->samples_on_screen, avg_cnt, trigger_position_ratio, annot_str, avg_periodspinbox->value()); for(i=0; isignalcomp[signal_nr]->avg_dialog[i] == 0) { mainwindow->signalcomp[signal_nr]->avg_dialog[i] = dialoglistnumber + 1; break; } } } mainwindow->edfheaderlist[0]->viewtime = backup_viewtime; mainwindow->pagetime = backup_timescale; mainwindow->signal_averaging_active = 0; mainwindow->setup_viewbuf(); averager_dialog->close(); } UI_AveragerWindow::~UI_AveragerWindow() { int i; for(i=0; iaveragecurvedialog[i] != NULL) { mainwindow->averagecurvedialog[i]->averager_curve_dialog->move(((i % 15) * 30) + 200, ((i % 15) * 30) + 200); mainwindow->averagecurvedialog[i]->averager_curve_dialog->raise(); mainwindow->averagecurvedialog[i]->averager_curve_dialog->activateWindow(); } } } void UI_AveragerWindow::process_avg(struct signalcompblock *signalcomp) { int j, k; char *viewbuf; long long s, s2; double dig_value=0.0, f_tmp=0.0; union { unsigned int one; signed int one_signed; unsigned short two[2]; signed short two_signed[2]; unsigned char four[4]; } var; viewbuf = mainwindow->viewbuf; if(viewbuf == NULL) { return; } if(avgbuf == NULL) { return; } for(s=signalcomp->sample_start; ssamples_on_screen; s++) { if(s>signalcomp->sample_stop) break; dig_value = 0.0; s2 = s + signalcomp->sample_timeoffset - signalcomp->sample_start; for(j=0; jnum_of_signals; j++) { if(signalcomp->edfhdr->bdf) { var.two[0] = *((unsigned short *)( viewbuf + signalcomp->viewbufoffset + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)) + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset + ((s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record) * 3))); var.four[2] = *((unsigned char *)( viewbuf + signalcomp->viewbufoffset + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)) + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset + ((s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record) * 3) + 2)); if(var.four[2]&0x80) { var.four[3] = 0xff; } else { var.four[3] = 0x00; } f_tmp = var.one_signed; } if(signalcomp->edfhdr->edf) { f_tmp = *(((short *)( viewbuf + signalcomp->viewbufoffset + (signalcomp->edfhdr->recordsize * (s2 / signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)) + signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].buf_offset)) + (s2 % signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].smp_per_record)); } f_tmp += signalcomp->edfhdr->edfparam[signalcomp->edfsignal[j]].offset; f_tmp *= signalcomp->factor[j]; dig_value += f_tmp; } if(signalcomp->spike_filter) { if(s==signalcomp->sample_start) { spike_filter_restore_buf(signalcomp->spike_filter); } dig_value = run_spike_filter(dig_value, signalcomp->spike_filter); } for(k=0; kfilter_cnt; k++) { dig_value = first_order_filter(dig_value, signalcomp->filter[k]); } for(k=0; kravg_filter_cnt; k++) { if(s==signalcomp->sample_start) { ravg_filter_restore_buf(signalcomp->ravg_filter[k]); } dig_value = run_ravg_filter(dig_value, signalcomp->ravg_filter[k]); } for(k=0; kfidfilter_cnt; k++) { if(s==signalcomp->sample_start) { memcpy(signalcomp->fidbuf[k], signalcomp->fidbuf2[k], fid_run_bufsize(signalcomp->fid_run[k])); } dig_value = signalcomp->fidfuncp[k](signalcomp->fidbuf[k], dig_value); } if(signalcomp->ecg_filter != NULL) { if(s==signalcomp->sample_start) { ecg_filter_restore_buf(signalcomp->ecg_filter); } dig_value = run_ecg_filter(dig_value, signalcomp->ecg_filter); } avgbuf[s] += (dig_value * signalcomp->edfhdr->edfparam[signalcomp->edfsignal[0]].bitvalue); } } edfbrowser_157_source/PaxHeaders.7921/z_ratio_filter.h0000644000000000000000000000013212646460742020053 xustar0030 mtime=1452958178.240246757 30 atime=1452958178.240246757 30 ctime=1452958178.240246757 edfbrowser_157_source/z_ratio_filter.h0000644000175000001440000000400512646460742020413 0ustar00guvusers00000000000000/* *************************************************************************** * * Author: Teunis van Beelen * * Copyright (C) 2012, 2013, 2014, 2015, 2016 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 . * *************************************************************************** */ #ifndef zratio_filter_INCLUDED #define zratio_filter_INCLUDED #include #include #include #include "global.h" #include "third_party/kiss_fft/kiss_fftr.h" struct zratio_filter_settings{ double crossoverfreq; int dftblocksize; double samplefreq; int fft_outputbufsize; double freqstep; double f1; double f2; double f3; double f4; double *fft_inputbuf; double *fft_outputbuf; kiss_fftr_cfg cfg; kiss_fft_cpx *kiss_fftbuf; int smpls_in_inputbuf; double zratio_value; double *fft_inputbuf_bu; int smpls_in_inputbuf_bu; double zratio_value_bu; double bitvalue; }; struct zratio_filter_settings * create_zratio_filter(int, long long, double, double); double run_zratio_filter(double, struct zratio_filter_settings *); void free_zratio_filter(struct zratio_filter_settings *); void reset_zratio_filter(struct zratio_filter_settings *); void zratio_filter_save_buf(struct zratio_filter_settings *); void zratio_filter_restore_buf(struct zratio_filter_settings *); #endif