├── .classpath ├── .gitignore ├── .project ├── .settings └── org.eclipse.jdt.core.prefs ├── LICENSE ├── Makefile ├── README.md ├── UnitTests ├── BatchTest.m ├── test_ann2rr.m ├── test_bxb.m ├── test_dfa.m ├── test_ecgpuwave.m ├── test_edr.m ├── test_gqrs.m ├── test_lomb.m ├── test_mat2wfdb.m ├── test_mrgann.m ├── test_msentropy.m ├── test_physionetdb.m ├── test_rdann.m ├── test_rdmat.m ├── test_rdmimic2wave.m ├── test_rdsamp.m ├── test_snip.m ├── test_sortann.m ├── test_sqrs.m ├── test_sumann.m ├── test_tach.m ├── test_wabp.m ├── test_wfdb2mat.m ├── test_wfdbdemo.m ├── test_wfdbdesc.m ├── test_wfdbtest.m ├── test_wfdbtime.m ├── test_woody.m ├── test_wqrs.m ├── test_wrann.m ├── test_wrapper.m └── test_wrsamp.m ├── build-toolbox ├── dependencies └── jni │ ├── .gitignore │ ├── 100s.expected │ ├── Makefile.in │ ├── autogen.sh │ ├── configure.ac │ ├── rdsampjni.c │ └── readme ├── gen-doc.sh ├── jarbuild.xml ├── mcode ├── .gitignore ├── Contents.m ├── LICENSE.txt ├── NEWS ├── README.txt ├── ann2rr.m ├── bxb.m ├── corrint.m ├── dfa.m ├── ecgpuwave.m ├── edr.m ├── example │ ├── 100a.atr │ ├── 100a.hea │ ├── 100s.atr │ ├── 100s.dat │ ├── 100s.hea │ ├── a01.dat │ ├── a01.entry1 │ ├── a01.fqrs │ ├── a01.hea │ ├── f1o02.dat │ ├── f1o02.ecg │ ├── f1o02.hea │ └── fort.6 ├── getWfdbClass.m ├── gqrs.m ├── helptoc_template.xml ├── html │ ├── LICENSE.txt │ ├── NEWS │ ├── helptoc.xml │ ├── helpwin.css │ ├── template.html │ └── template_bottom.html ├── info.xml ├── lomb.m ├── mat2wfdb.m ├── mrgann.m ├── msentropy.m ├── mxm.m ├── nativelibs │ ├── Makefile │ └── custom │ │ └── README.txt ├── pbsearch.m ├── physionetdb.m ├── rdann.m ├── rdmat.m ├── rdmimic2wave.m ├── rdsamp.m ├── snip.m ├── sortann.m ├── sqrs.m ├── sumann.m ├── surrogate.m ├── tach.m ├── visgraph.m ├── wabp.m ├── wfdb.m ├── wfdb2mat.m ├── wfdbRecordViewer.fig ├── wfdbRecordViewer.m ├── wfdbdemo.m ├── wfdbdesc.m ├── wfdbdownload.m ├── wfdbexec.m ├── wfdbjava2mat.m ├── wfdbloadlib.m ├── wfdbtest.m ├── wfdbtime.m ├── wfdbtool.m ├── woody.m ├── wqrs.m ├── wrann.m ├── wrsamp.m └── xform.m ├── src └── org │ └── physionet │ └── wfdb │ ├── ErrorReader.java │ ├── InputWriter.java │ ├── OutputReader.java │ ├── SystemSettings.java │ ├── Wfdbexec.java │ ├── jni │ └── Rdsamp.java │ └── physiobank │ ├── GetRecord.java │ ├── PhysioNetDB.java │ ├── PhysioNetRecord.java │ └── PhysioNetSignal.java ├── wsm-matlab-code-Manifest.txt └── zipexclude.lst /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /database/ 3 | /Makefile~ 4 | 5 | *~ 6 | *.orig 7 | *.rej 8 | *.o 9 | *.a 10 | *.so 11 | *.so.* 12 | *.dll 13 | *.exe 14 | *.dylib 15 | *.class 16 | *.zip 17 | *.jar 18 | fort.6 19 | fort.20 20 | fort.21 21 | /mcode/nativelibs/*.c 22 | /mcode/nativelibs/*.tar.gz 23 | /mcode/nativelibs/*/bin/* 24 | /mcode/nativelibs/*/build/* 25 | /mcode/nativelibs/*/database/* 26 | /mcode/nativelibs/*/include/* 27 | /mcode/nativelibs/*/lib/* 28 | /mcode/nativelibs/*/lib64/* 29 | /mcode/nativelibs/*/share/* 30 | /mcode/html/*.html 31 | !/mcode/html/template.html 32 | !/mcode/html/template_bottom.html 33 | /dependencies/jni/aclocal.m4 34 | /dependencies/jni/autom4te.cache/* 35 | /dependencies/jni/configure 36 | /dependencies/jni/config.guess 37 | /dependencies/jni/config.sub 38 | /dependencies/jni/install-sh 39 | /dependencies/jni/ltmain.sh 40 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | wfdb-app-toolbox 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.6 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.6 12 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #Makefile for wfdb-application-toolbox 2 | # 3 | # Written by Ikaro Silva, 2013 4 | # 5 | #For now simple make file for packaging and deploying application. 6 | #Requires that the Java classes be compiled into runnable JARs. 7 | # 8 | #To compile the Toolbox for deployment run: 9 | #make package 10 | 11 | BUILDFILE := ./jarbuild.xml 12 | ANT = ant 13 | 14 | #Always check that this matches with Ant's script (jarbuild.xml), 15 | #with the loading function wfdbloadlib.m , and with Contents.m 16 | #There is really no reason by the *.jar and *.zip should need to have the same 17 | #version numbers, as they are really modular...But for now we keep them at the same 18 | #versioning level in order to avoid (or increase?) confusion. 19 | VERSION=0-10-0 20 | APP_NAME=wfdb-app-toolbox-$(VERSION).zip 21 | JAR7_NAME=wfdb-app-JVM7-$(VERSION).jar 22 | 23 | javasrc=$(shell find src -name \*.java) 24 | 25 | all: jar7 nativelibs 26 | 27 | jar7: mcode/$(JAR7_NAME) 28 | mcode/$(JAR7_NAME): $(javasrc) $(BUILDFILE) 29 | $(ANT) -f $(BUILDFILE) jar7 30 | 31 | nativelibs: jar7 32 | cd mcode/nativelibs && $(MAKE) install 33 | set -e; if grep -q '^WFDB_CUSTOMLIB=0' mcode/wfdbloadlib.m; then \ 34 | sed -e 's/^WFDB_CUSTOMLIB=0/WFDB_CUSTOMLIB=1/' \ 35 | < mcode/wfdbloadlib.m > mcode/wfdbloadlib.m.tmp; \ 36 | mv -f mcode/wfdbloadlib.m.tmp mcode/wfdbloadlib.m; \ 37 | fi 38 | 39 | clean: 40 | cd mcode/nativelibs && $(MAKE) clean 41 | rm -rf bin 42 | rm -f mcode/*.jar 43 | 44 | #Target for HTML doc generation from M-files 45 | doc: 46 | ./gen-doc.sh 47 | 48 | package: jar7 doc unit-test.zip 49 | rm -f $(APP_NAME) 50 | set -e; if grep -q '^WFDB_CUSTOMLIB=1' mcode/wfdbloadlib.m; then \ 51 | sed -e 's/^WFDB_CUSTOMLIB=1/WFDB_CUSTOMLIB=0/' \ 52 | < mcode/wfdbloadlib.m > mcode/wfdbloadlib.m.tmp; \ 53 | mv -f mcode/wfdbloadlib.m.tmp mcode/wfdbloadlib.m; \ 54 | fi 55 | zip -X -r $(APP_NAME) mcode -x@zipexclude.lst 56 | 57 | unit-test.zip: 58 | zip -X -r $@ UnitTests -x@zipexclude.lst 59 | 60 | check: 61 | set -e; unset DISPLAY; mcodedir=`pwd`/mcode; \ 62 | cd UnitTests && octave -q --eval \ 63 | "pkg load signal; \ 64 | addpath('$$mcodedir'); \ 65 | confirm_recursive_rmdir(0); \ 66 | BatchTest; exit(total_failed > 0)" 67 | 68 | check-%: 69 | set -e; unset DISPLAY; mcodedir=`pwd`/mcode; \ 70 | cd UnitTests && octave -q --eval \ 71 | "pkg load signal; \ 72 | addpath('$$mcodedir'); \ 73 | confirm_recursive_rmdir(0); \ 74 | [tests,pass,perf]=test_$*(1); \ 75 | exit(pass < tests)" 76 | 77 | jartest: mcode/$(JAR7_NAME) unit-test.zip 78 | cd mcode; \ 79 | java -cp $(JAR7_NAME) org.physionet.wfdb.Wfdbexec rdsamp -r mitdb/100 -t s5 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | wfdbRecordViewer 3 |

4 | 5 | ## Introduction 6 | The WFDB Toolbox for MATLAB and Octave is a set of Java, GUI, and m-code wrapper functions, 7 | which make system calls to [WFDB Software Package](http://physionet.org/physiotools/wfdb.shtml) and other PhysioToolkit applications. The website for the toolbox (which includes the installation instructions) can be found at: 8 | 9 | http://physionet.org/physiotools/matlab/wfdb-app-matlab/ 10 | 11 | Using the WFDB Toolbox, MATLAB and Octave users have access to over 50 [PhysioNet](http://physionet.org/) databases (over 4 TB of physiologic signals including ECG, EEG, EMG, fetal ECG, PLETH, PPG, ABP, respiration, and more). 12 | Additionally, most of these databases are also accompanied by metadata such as expert annotations of 13 | physiologically relevant events in WFDB annotation files. These can include, for example, 14 | cardiologists' beat and rhythm annotations of ECGs, or sleep experts' hypnograms (sleep stage annotations) 15 | of polysomnograms. All of these physiologic signals and annotations can be read on demand from the 16 | PhysioNet web server and its mirrors using the toolbox functions, or from local copies if you choose 17 | to download them. This feature allows your code to analyze the wide range of physiologic signals 18 | available from PhysioBank without the need to download entire records and to store them locally. 19 | The Toolbox is open-source (distributed under the GPL). The toolbox includes a GUI (WFDBRECORDVIEWER) 20 | for facilitating the browsing, exploration, and analysis of WFBD records stored locally on the users machine, 21 | or remotely in PhysioNet's [databases](http://physionet.org/physiobank/database/DBS). 22 | 23 | ## Forum 24 | 25 | A community discussion group is available at: 26 | http://groups.google.com/forum/#!forum/wfdb-app-toolbox 27 | 28 | ## Available Databases 29 | 30 | For a list of available databases accessible through the WFDB Toolbox, see: 31 | 32 | http://physionet.org/physiobank/database/DBS 33 | 34 | ## Installing from PhysioNet 35 | 36 | To check out and install from PhysioNet using MATLAB, run the following commands: 37 | 38 | ``` 39 | [old_path]=which('rdsamp');if(~isempty(old_path)) rmpath(old_path(1:end-8)); end 40 | wfdb_url='https://physionet.org/physiotools/matlab/wfdb-app-matlab/wfdb-app-toolbox-0-10-0.zip'; 41 | [filestr,status] = urlwrite(wfdb_url,'wfdb-app-toolbox-0-10-0.zip'); 42 | unzip('wfdb-app-toolbox-0-10-0.zip'); 43 | cd mcode 44 | addpath(pwd);savepath 45 | 46 | ``` 47 | ## Checking out and installing from the trunk 48 | 49 | Building the toolbox requires: 50 | - The GNU C compiler (GCC) 51 | - The GNU Fortran compiler (gfortran) 52 | - GNU Make 53 | - GNU Autoconf 54 | - GNU Libtool 55 | - Java Development Kit 56 | - Ant 57 | 58 | To build the toolbox, simply run 'make' in the top-level directory. 59 | This will automatically download various dependencies from PhysioNet 60 | and elsewhere (see 'mcode/nativelibs/Makefile' for details.) 61 | 62 | ## Reference & Toolbox Technical Overview 63 | 64 | [An Open-source Toolbox for Analysing and Processing PhysioNet Databases in MATLAB and Octave. 65 | I Silva, GB Moody, Journal of Open Research Software 2 (1), e27](http://openresearchsoftware.metajnl.com/article/view/jors.bi/77) 66 | 67 | 68 | [WFDB Software Package](http://physionet.org/physiotools/wfdb.shtml) 69 | 70 | -------------------------------------------------------------------------------- /UnitTests/BatchTest.m: -------------------------------------------------------------------------------- 1 | %Perform batch testing of the main functionalities of the WFBD App Toolbox 2 | clear all;close all;clc 3 | 4 | %The test generates and remove temporary files, so it is best run in at a 5 | %specific directory. 6 | total=0; 7 | total_failed=0; 8 | total_time=0; 9 | 10 | test_suite={'test_ann2rr','test_physionetdb', ... 11 | 'test_rdann','test_rdsamp','test_sqrs', 'test_gqrs', ... 12 | 'test_tach','test_wfdbdesc','test_wfdbtime', ... 13 | 'test_wqrs','test_wrann','test_wrsamp','test_wfdbdemo',... 14 | 'test_bxb','test_sumann','test_sortann', ... 15 | 'test_wabp','test_mrgann','test_lomb','test_rdmimic2wave', ... 16 | 'test_msentropy','test_edr','test_ecgpuwave','test_woody',... 17 | 'test_mat2wfdb','test_wfdb2mat','test_dfa','test_snip'}; 18 | M=length(test_suite); 19 | display(['***Running ' num2str(M) ' test suites...']); 20 | 21 | 22 | %Start with the installation test, provide a good initial assesment. 23 | failed={}; 24 | for m=1:M 25 | fprintf(['Testing Suite (%s/%s): %s() ...\n'],num2str(m), num2str(M),test_suite{m}); 26 | eval(['[tests,pass,perf]=' test_suite{m} '();']) 27 | fprintf(['\tTested: %s\tPassed: %s\tTotal Time= %s\n'],num2str(tests),... 28 | num2str(pass),num2str(sum(sum(perf)))); 29 | total=total+tests; 30 | total_failed=total_failed+ (tests-pass); 31 | total_time=total_time+sum(perf); 32 | if(pass < tests) 33 | failed(end+1)=test_suite(m); 34 | end 35 | end 36 | 37 | fprintf(['***Finished all tests!!\n']); 38 | fprintf(['\tTotal test:\t%s\n'], num2str(total)); 39 | fprintf(['\tTotal time:\t%s\n'], num2str(total_time)); 40 | fprintf(['\tTotal failed:\t%s\n'], num2str(total_failed)); 41 | if(total_failed>0) 42 | fprintf(['\tFailed tests:\n\t']); 43 | display(failed) 44 | end 45 | -------------------------------------------------------------------------------- /UnitTests/test_ann2rr.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_ann2rr(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | %Test the examples 11 | test_string={'[rr,tm]=ann2rr(''challenge/2013/set-a/a01'',''fqrs'');'... 12 | }; 13 | 14 | [tests,pass,perf]=test_wrapper(test_string,[],verbose); -------------------------------------------------------------------------------- /UnitTests/test_bxb.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_bxb(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test_string={['[refAnn]=rdann(''mitdb/100'',''atr'');sqrs(''mitdb/100'');'... 13 | '[testAnn]=rdann(''mitdb/100'',''qrs'');r=bxb(''mitdb/100'',''atr'',''qrs'',''bxbReport.txt'')']}; 14 | 15 | clean_up={['delete([pwd filesep ''mitdb'' filesep ''*'']);' ... 16 | 'rmdir([pwd filesep ''mitdb''],''s'');delete([pwd filesep ''bxbReport.txt'']);';]}; 17 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); -------------------------------------------------------------------------------- /UnitTests/test_dfa.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_dfa(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test_string={['gqrs(''mitdb/117'');[rr]=ann2rr(''mitdb/117'',''qrs'');' ... 13 | '[ln,lf]=dfa(rr);plot(ln,lf);close all']}; 14 | clean_up={['delete([pwd filesep ''mitdb'' filesep ''*'']);' ... 15 | 'rmdir([pwd filesep ''mitdb''],''s'')']}; 16 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); -------------------------------------------------------------------------------- /UnitTests/test_ecgpuwave.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_ecgpuwave(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test_string={['curdir=pwd;[~,config]=wfdbloadlib;eval([''cd '' config.WFDB_JAVA_HOME filesep ''example'']);ecgpuwave(''100s'',''test''); ' ... 13 | '[signal,Fs,tm]=rdsamp(''100s'');pwaves=rdann(''100s'',''test'',[],[],[],''p'');cd(curdir);if(size(pwaves)<1);error(''failed'');end']}; 14 | clean_up={['curdir=pwd;[~,config]=wfdbloadlib;eval([''cd '' config.WFDB_JAVA_HOME filesep ''example'']);ecgpuwave(''100s'',''test'');' ... 15 | 'delete(''100s.test'');cd(curdir);']}; 16 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); 17 | -------------------------------------------------------------------------------- /UnitTests/test_edr.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_edr(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | % Note: This requires the Signal Processing toolbox 13 | 14 | test_string={['signal=''fantasia/f1o02'';r_peaks=''ecg'';' ... 15 | 'data_type=1;channel=2;y=edr(data_type,signal,r_peaks,[],[],[],channel);' ... 16 | 'wfdb2mat(''f1o02'');[~,signal,Fs,~]=rdmat(''f1o02m'');' ... 17 | 'resp=signal(:,1);resp=resp-mean(resp);resp=resp*200;sec=length(resp)/Fs;' ... 18 | 'xax=[.25:.25:sec];r=interp1(y(:,1), y(:,2), xax,''spline'');' ... 19 | 'B=fir1(100,[.1 .5],''bandpass'');edr_filt=filtfilt(B,1,r);figure;plot(xax,edr_filt);' ... 20 | 'hold on;plot([1:length(resp)]/Fs,resp,''r'');legend(''edr'',''respiratory signal'');' ... 21 | 'xlabel(''time (s)'');close all']}; 22 | 23 | clean_up={['delete([pwd filesep ''f1o02m*'']);']}; 24 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); 25 | -------------------------------------------------------------------------------- /UnitTests/test_gqrs.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_gqrs(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test_string={['N=5000;gqrs(''mitdb/100'',N);ann=rdann(''mitdb/100'',''qrs'',[],N);[sig,Fs,tm]=rdsamp(''mitdb/100'',[],N);' ... 13 | 'plot(tm,sig(:,1));hold on;grid on;plot(tm(ann),sig(ann,1),''ro'');close all']}; 14 | clean_up={['delete([pwd filesep ''mitdb'' filesep ''*'']);' ... 15 | 'rmdir([pwd filesep ''mitdb''],''s'')']}; 16 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); 17 | -------------------------------------------------------------------------------- /UnitTests/test_lomb.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_lomb(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test_string={['[signal, Fs, tm]=rdsamp(''mitdb/100'',1);[ann]=rdann(''mitdb/100'',''atr'');[Pxx,F]=lomb([tm(ann) signal(ann)]);'... 13 | 'plot(F,Pxx);grid on;hold on']}; 14 | clean_up={}; 15 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); 16 | -------------------------------------------------------------------------------- /UnitTests/test_mat2wfdb.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_mat2wfdb(varargin) 2 | 3 | 4 | 5 | %Generate 3 different signals and convert them to signed 16 bit in WFDB format 6 | str1=['N=1024;Fs=48000;tm=[0:1/Fs:(N-1)/Fs]'';adu=''V/mV/V'';' ... 7 | 'info=''Example 1'';sig1=double(int16(linspace(-2^15,2^15,N)''));'... 8 | 'sig2=double(int8(sin(2*pi*tm*1000).*(2^7)))./(2^7);' ... 9 | 'sig3=(rand(N,1) > 0.97)*2 -1 + 2^16;sig=[sig1 sig2 sig3];' ... 10 | 'mat2wfdb(sig,''Ex1'',Fs,[],adu,info);']; 11 | 12 | cln1=['delete([pwd filesep ''Ex1*'']);']; 13 | 14 | inputs={'verbose'}; 15 | verbose=0; 16 | for n=1:nargin 17 | if(~isempty(varargin{n})) 18 | eval([inputs{n} '=varargin{n};']); 19 | end 20 | end 21 | 22 | %Test the examples 23 | test_string={str1}; 24 | clean_up={cln1}; 25 | 26 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); -------------------------------------------------------------------------------- /UnitTests/test_mrgann.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_mrgann(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test_string={'wqrs(''mitdb/100'');mrgann(''mitdb/100'',''atr'',''wqrs'',''testAnn'')'}; 13 | 14 | clean_up={['delete([pwd filesep ''mitdb'' filesep ''*'']);' ... 15 | 'rmdir([pwd filesep ''mitdb''],''s'');';]}; 16 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); -------------------------------------------------------------------------------- /UnitTests/test_msentropy.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_msentropy(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test1_str=['[RR,tms]=ann2rr(''nsr2db/nsr047'',''ecg'');[y,scale]=msentropy(RR(1:1000));']; 13 | test_string={test1_str}; 14 | 15 | clean_up={['']}; 16 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); -------------------------------------------------------------------------------- /UnitTests/test_physionetdb.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_physionetdb(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test_string={'x=physionetdb;' , ... 13 | 'x=physionetdb(''ucddb'');' ... 14 | }; 15 | 16 | [tests,pass,perf]=test_wrapper(test_string,[],verbose); 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /UnitTests/test_rdann.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_rdann(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | %Example 1- Read a signal and annotaion from PhysioNet's Remote server: 11 | test1_str=['[signal, Fs, tm]=rdsamp(''challenge/2013/set-a/a01'');' ... 12 | '[ann]=rdann(''challenge/2013/set-a/a01'',''fqrs'');' ... 13 | ]; 14 | 15 | test2_str=['ann=rdann(''mitdb/100'',''atr'',[],500);']; 16 | 17 | %Test the examples 18 | test_string={test1_str,test2_str}; 19 | 20 | clean_up={['%do nothing for second test'],... 21 | ['delete([pwd filesep ''mitdb'' filesep ''100'' filesep ''*'']);'] ... 22 | }; 23 | 24 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); 25 | -------------------------------------------------------------------------------- /UnitTests/test_rdmat.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_rdmat(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']) 8 | end 9 | end 10 | 11 | 12 | %Test the examples 13 | test1_str=['wfdb2mat(''mitdb/200'');' ... 14 | '[tm,signal,Fs,siginfo]=rdmat(''200m'');'... 15 | '[signal2,Fs2,tm2]=rdsamp(''200m'');' ... 16 | 'if(sum(abs(signal-signal2)) ~=0);error(''data reading failed'');end' ... 17 | ]; 18 | 19 | test_string={test1_str}; 20 | clean_up={['delete([pwd filesep ''mitdb'' filesep ''*'']);' ... 21 | 'if(exist([pwd filesep ''mitdb''],''dir''));rmdir([pwd filesep ''mitdb''],''s'');end;' ... 22 | 'delete([pwd filesep ''200m*'']);' ... 23 | ]}; 24 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /UnitTests/test_rdmimic2wave.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_rdmimic2wave(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test_string={['[tm,signal,Fs,recList,sigInfo]=rdmimic2wave(32805,''2986-12-15-10-00'',[],0,2);' ... 13 | 'plot(tm,signal(:,2));title([''Found data in record: '' recList]);'... 14 | 'legend(sigInfo(2).Description);close all']}; 15 | 16 | [tests,pass,perf]=test_wrapper(test_string,[],verbose); -------------------------------------------------------------------------------- /UnitTests/test_rdsamp.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_rdsamp(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test1_str=['[signal,Fs,tm]=rdsamp(''mghdb/mgh001'', [1 3 5],1000,[]);']; 13 | test2_str=['[signal,Fs,tm]=rdsamp(''mghdb/mgh001'', [1 3 5],1000,[],2);']; 14 | test3_str=['[signal,Fs,tm]=rdsamp(''challenge/2013/set-a/a01'',[],1000);'... 15 | 'plot(tm,signal(:,1));close all']; 16 | test4_str=['[sig,Fs,tm] = rdsamp(''drivedb/drive02'',[1],[],[],[],1);']; 17 | 18 | %test3_str=['[tm2,sig2]=rdsamp(''mimic2wdb/30/3003521/3003521_0001'',[2 4 5], 30499638,30484638);']; 19 | %test4_str=['[tm2,sig2]=rdsamp(''mimic2wdb/30/3003521/3003521_0001'',[2 4 5],[],[],2);']; 20 | %For now avoid these test conditions from above, which still need to be 21 | %fixed. This looks like it is an issue with reading large multi-record 22 | %signals with N and N0 defined. 23 | 24 | test_string={test1_str,test2_str,test3_str,test4_str}; 25 | 26 | clean_up={[''],[''],[''],['']}; 27 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); 28 | -------------------------------------------------------------------------------- /UnitTests/test_snip.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_snip(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test_string={'Fs=360;err=snip(''mitdb/100'',''100cut'',Fs*60,Fs*2*60);'}; 13 | clean_up={['delete([pwd filesep ''100cut*'']);']}; 14 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); -------------------------------------------------------------------------------- /UnitTests/test_sortann.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_sortann(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test_string={['sortann(''mitdb/100'',''atr'',[],[],''sortedATR'');' ... 13 | 'ann=rdann(''mitdb/100'',''sortedATR'');']}; 14 | 15 | clean_up={['delete([pwd filesep ''mitdb'' filesep ''*'']);' ... 16 | 'rmdir([pwd filesep ''mitdb''],''s'');';]}; 17 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); -------------------------------------------------------------------------------- /UnitTests/test_sqrs.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_sqrs(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test_string={'sqrs(''challenge/2013/set-a/a01'',[],1000);'}; 13 | clean_up={['delete([pwd filesep ''challenge'' filesep ''2013'' filesep ''set-a'' filesep ''*'']);' ... 14 | 'rmdir([pwd filesep ''challenge''],''s'')']}; 15 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); -------------------------------------------------------------------------------- /UnitTests/test_sumann.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_sumann(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test_string={'report=sumann(''mitdb/100'',''atr'');'}; 13 | clean_up={}; 14 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); -------------------------------------------------------------------------------- /UnitTests/test_tach.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_tach(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test_string={['[hr]=tach(''challenge/2013/set-a/a01'',''fqrs'');' ... 13 | 'plot(hr);grid on;hold on;close all']}; 14 | 15 | [tests,pass,perf]=test_wrapper(test_string,[],verbose); -------------------------------------------------------------------------------- /UnitTests/test_wabp.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_wabp(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test_string={['N=2000;[x,Fs,tm]=rdsamp(''slpdb/slp60'',2,N);'... 13 | '[endTime,dateStamp]=wfdbtime(''slpdb/slp60'',N);wabp(''slpdb/slp60'',[],endTime{1},[],2);'... 14 | '[ann]=rdann(''slpdb/slp60'',''wabp'');plot(tm,x);hold on;grid on;plot(tm(ann),x(ann),''or'')']}; 15 | 16 | clean_up={['delete([pwd filesep ''slpdb'' filesep ''*'']);' ... 17 | 'rmdir([pwd filesep ''slpdb''],''s'');';]}; 18 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); 19 | -------------------------------------------------------------------------------- /UnitTests/test_wfdb2mat.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_wfdb2mat(varargin) 2 | 3 | 4 | 5 | %Generate 3 different signals and convert them to signed 16 bit in WFDB format 6 | str1=['wfdb2mat(''mitdb/200'');[tm,signal,Fs,siginfo]=rdmat(''200m'');'... 7 | '[signal2,Fs2,tm2]=rdsamp(''200m'');sum(abs(signal-signal2));']; 8 | 9 | cln1=['delete([pwd filesep ''200m*'']);']; 10 | 11 | inputs={'verbose'}; 12 | verbose=0; 13 | for n=1:nargin 14 | if(~isempty(varargin{n})) 15 | eval([inputs{n} '=varargin{n};']); 16 | end 17 | end 18 | 19 | %Test the examples 20 | test_string={str1}; 21 | clean_up={cln1}; 22 | 23 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); 24 | -------------------------------------------------------------------------------- /UnitTests/test_wfdbdemo.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_wfdbdemo(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | %Test the examples 11 | test_string={'wfdbdemo;close all;'}; 12 | 13 | [tests,pass,perf]=test_wrapper(test_string,[],verbose); -------------------------------------------------------------------------------- /UnitTests/test_wfdbdesc.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_wfdbdesc(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | test_string={'siginfo=wfdbdesc(''challenge/2013/set-a/a01'');'}; 13 | [tests,pass,perf]=test_wrapper(test_string,[],verbose); -------------------------------------------------------------------------------- /UnitTests/test_wfdbtest.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_wfdbtest(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']) 8 | end 9 | end 10 | %Sounds redundant, I know, but wfdbtest is used for remote installation 11 | %debugging, it has a nice suite of test not in the function examples. 12 | %Should be one the first tests run (or for a light check of the toolbox). 13 | test_string={'good=wfdbtest;close all;if(!good) error(''wfdbtest failed'');end'}; 14 | [tests,pass,perf]=test_wrapper(test_string,[],verbose); -------------------------------------------------------------------------------- /UnitTests/test_wfdbtime.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_wfdbtime(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | 12 | %Test the examples 13 | test_string={'[timeStamp,dateStamp]=wfdbtime(''challenge/2013/set-a/a01'',[1 10 30]);'}; 14 | [tests,pass,perf]=test_wrapper(test_string,[],verbose); -------------------------------------------------------------------------------- /UnitTests/test_woody.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_woody(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | %Test the examples 12 | % Note: This requires the Signal Processing toolbox 13 | str=['t=[0:1/1000:1];N=1001;x=sin(2*pi*t)+sin(4*pi*t)+sin(8*pi*t);' ... 14 | 'y=exp(0.01*[-1*[500:-1:1] 0 -1*[1:500]]);'... 15 | 's=x.*y;sig1=0;sig2=0.1;M=100;S=zeros(N,M);center=501;TAU=round((rand(1,M)-0.5)*160);'... 16 | 'for i=1:M;tau=TAU(i);if(tau<0)' ... 17 | 'S(:,i)=[s(-1*tau:end)''; zeros(-1*(tau+1),1)];'... 18 | 'else; S(:,i)=[zeros(tau,1);s(1:N-tau)''; ];end;'... 19 | 'if(i<50) S(:,i)=S(:,i) + randn(N,1).*sig1; else; S(:,i)=S(:,i) + randn(N,1).*sig2; end; end; '... 20 | '[wood]=woody(S,[],[],''woody'',''biased'');[thor]=woody(S,[],[],''thornton'',''biased'');'... 21 | 'figure;subplot(211);' ... 22 | 'plot(s,''b'',''LineWidth'',2);hold on;plot(S,''r'');plot(s,''b'',''LineWidth'',2);legend(''Signal'',''Measurements'');'... 23 | 'subplot(212);plot(s);hold on;plot(mean(S,2),''r'');plot(wood,''g'');plot(thor,''k'');'... 24 | 'legend(''Signal'',''Normal Ave'',''Woody Ave'',''Thornton Ave'');close all;']; 25 | 26 | test_string={str}; 27 | 28 | clean_up={}; 29 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); 30 | -------------------------------------------------------------------------------- /UnitTests/test_wqrs.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_wqrs(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | 12 | %Test the examples 13 | test_string={'wqrs(''challenge/2013/set-a/a01'');'}; 14 | clean_up={['delete([pwd filesep ''challenge'' filesep ''2013'' filesep ''set-a'' filesep ''*'']);' ... 15 | 'rmdir([pwd filesep ''challenge''],''s'')']}; 16 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); -------------------------------------------------------------------------------- /UnitTests/test_wrann.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_wrann(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | 12 | %Test the examples 13 | test1_str=[ '[ann,type,subtype,chan,num]=rdann(''challenge/2013/set-a/a01'',''fqrs'');' ... 14 | 'wrann(''challenge/2013/set-a/a01'',''test'',ann,type,subtype,chan,num);' ... 15 | '[ann,type,subtype,chan,num]=rdann(''challenge/2013/set-a/a01'',''fqrs'');' ... 16 | 'wrann(''challenge/2013/set-a/a01'',''test'',ann,type,subtype,chan,num);' ... 17 | '[ann2,type2,subtype2,chan2,num2]=rdann(''challenge/2013/set-a/a01'',''test'',[],[],1);' ... 18 | 'err=sum(ann ~= ann2);']; 19 | 20 | test2_str=[ '[ann,type,subtype,chan,num]=rdann(''mitdb/100'',''atr'');' ... 21 | 'wrann(''mitdb/100'',''test'',ann,type,subtype,chan,num);']; 22 | 23 | %Test that comments are being written 24 | test3_str=['[ann,type,subtype,chan,num,comments]=rdann(''afdb/04015'',''atr'');' ... 25 | 'wrann(''afdb/04015'',''test'',ann,type,subtype,chan,num,comments);' ... 26 | '[ann2,type2,subtype2,chan2,num2, comments2]=rdann(''afdb/04015'',''test'');'... 27 | 'equal=strcmp([comments{:}],[comments2{:}]);' ... 28 | 'if(equal==0);error(''comments are incorrect'');end;' ]; 29 | 30 | test_string={test1_str,test2_str, test3_str}; 31 | clean_up={['delete([pwd filesep ''challenge'' filesep ''2013'' filesep ''set-a'' filesep ''*'']);' ... 32 | 'rmdir([pwd filesep ''challenge''],''s'');'], ... 33 | ['delete([pwd filesep ''mitdb'' filesep ''100'' filesep ''*'']);' ... 34 | 'rmdir([pwd filesep ''mitdb''],''s'');'] ... 35 | ['delete([pwd filesep ''afdb'' filesep ''*'']);' ... 36 | 'rmdir([pwd filesep ''afdb''],''s'');'], ... 37 | }; 38 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); 39 | 40 | 41 | -------------------------------------------------------------------------------- /UnitTests/test_wrapper.m: -------------------------------------------------------------------------------- 1 | function [varargout]=test_wrapper(varargin) 2 | % 3 | % Wrapper for testing basic functionality of the toolbox. 4 | % 5 | % Written by Ikaro Silva, 2013 6 | 7 | %Set default pararamter values 8 | inputs={'test_string','clean_up','verbose'}; 9 | outputs={'tests','pass','performance'}; 10 | 11 | pass=0; 12 | clean_up={}; 13 | verbose=0; 14 | cur_dir=pwd; 15 | for n=1:nargin 16 | if(~isempty(varargin{n})) 17 | eval([inputs{n} '=varargin{n};']); 18 | end 19 | end 20 | tests=length(test_string); 21 | performance=zeros(tests,1)+NaN; 22 | for n=1:tests 23 | try 24 | if(verbose) 25 | display(test_string{n}); 26 | end 27 | tic; 28 | eval(test_string{n}); 29 | performance(n)=toc; 30 | if(~isempty(clean_up) && ~isempty(clean_up{n})) 31 | try 32 | eval(clean_up{n}); 33 | catch 34 | display('Clean up failed: '); 35 | warning(lasterr); 36 | end 37 | end 38 | pass=pass+1; 39 | catch 40 | fprintf(['\t****Failed test: %s\n'],num2str(n)); 41 | 42 | display(['Last error: ' lasterr]); 43 | if(exist('lasterror')) 44 | err=lasterror; 45 | for m=1:length(err.stack) 46 | if(isfield(err.stack(m),'column')) 47 | colstr=[', column ' num2str(err.stack(m).column)]; 48 | else 49 | colstr=''; 50 | end 51 | display([' in ' err.stack(m).name ... 52 | ' (' err.stack(m).file ... 53 | ', line ' num2str(err.stack(m).line) ... 54 | colstr ')']); 55 | end 56 | end 57 | end 58 | end 59 | cd(cur_dir); 60 | for n=1:nargout 61 | eval(['varargout{n}=' outputs{n} ';']); 62 | end -------------------------------------------------------------------------------- /UnitTests/test_wrsamp.m: -------------------------------------------------------------------------------- 1 | function [tests,pass,perf]=test_wrsamp(varargin) 2 | 3 | inputs={'verbose'}; 4 | verbose=0; 5 | for n=1:nargin 6 | if(~isempty(varargin{n})) 7 | eval([inputs{n} '=varargin{n};']); 8 | end 9 | end 10 | 11 | 12 | %Test the examples 13 | test1_str=[ '[signal, Fs, tm]=rdsamp(''challenge/2013/set-a/a01'',[],[],[],1);' ... 14 | '[siginfo,Fs]=wfdbdesc(''challenge/2013/set-a/a01'');' ... 15 | 'wrsamp(tm,signal(:,1),''a01Copy'',Fs(1),200,siginfo(1).Format);' ... 16 | '[signalCopy, Fs, tm]=rdsamp(''a01Copy'',[],[],[],1);' ... 17 | 'err=sum(signalCopy ~= signal(:,1));' ]; 18 | 19 | test_string={test1_str}; 20 | clean_up={['delete([pwd filesep ''a01Copy*'']);']}; 21 | [tests,pass,perf]=test_wrapper(test_string,clean_up,verbose); 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /build-toolbox: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -x 5 | 6 | if [ $# != 3 ]; then 7 | echo "Usage: $0 repository branch version" >&2 8 | exit 1 9 | fi 10 | 11 | repo=$1 12 | branch=$2 13 | version=$3 14 | 15 | package=wfdb-app-toolbox-$version 16 | 17 | builddir=/tmp/toolbox-build 18 | outdir=/tmp 19 | make="make -j" 20 | 21 | rm -rf $builddir 22 | 23 | git clone --branch $branch --depth 1 $repo $builddir 24 | 25 | cd $builddir 26 | export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) 27 | strip_nondeterminism="strip-nondeterminism -T${SOURCE_DATE_EPOCH}" 28 | 29 | git archive --prefix=wfdb-app-toolbox-$version/ HEAD \ 30 | | gzip -c -9 -n > $outdir/$package.tar.gz 31 | 32 | # FIXME: use wfdb-toolbox-build chroot for this 33 | schroot -p -cjessie make jar7 &> jar7.log 34 | $strip_nondeterminism mcode/*.jar 35 | 36 | $make -C mcode/nativelibs download &> download.log 37 | 38 | (cd dependencies/jni && ./autogen.sh) &> autogen.log 39 | 40 | $make -C mcode/nativelibs install-linux install-windows install-macosx &> nativelibs.log 41 | 42 | x86_64-apple-darwin9-strip -S mcode/nativelibs/macosx/bin/ecgpuwave 43 | x86_64-apple-darwin9-strip -S mcode/nativelibs/macosx/lib/librdsampjni.dylib 44 | x86_64-apple-darwin9-strip -S mcode/nativelibs/macosx/lib/libwfdb.10.dylib 45 | 46 | make package APP_NAME=wfdb-app-toolbox-$version.zip 47 | $strip_nondeterminism $package.zip 48 | mv $package.zip $outdir/ 49 | -------------------------------------------------------------------------------- /dependencies/jni/.gitignore: -------------------------------------------------------------------------------- 1 | /librdsampjni.so 2 | /org_physionet_wfdb_jni_Rdsamp.h 3 | /rdsampjni.o 4 | /100s.atr 5 | /100s.dat 6 | /100s.hea 7 | /wfdb/ 8 | /hello.c 9 | /psamples.c 10 | -------------------------------------------------------------------------------- /dependencies/jni/100s.expected: -------------------------------------------------------------------------------- 1 | 995 2 | 1011 3 | 995 4 | 1011 5 | 995 6 | 1011 7 | 995 8 | 1011 9 | 995 10 | 1011 11 | 995 12 | 1011 13 | 995 14 | 1011 15 | 995 16 | 1011 17 | 1000 18 | 1008 19 | 997 20 | 1008 21 | -------------------------------------------------------------------------------- /dependencies/jni/Makefile.in: -------------------------------------------------------------------------------- 1 | CC = @CC@ 2 | CFLAGS = @CFLAGS@ 3 | CPPFLAGS = @CPPFLAGS@ 4 | DEFS = @DEFS@ 5 | LDFLAGS = @LDFLAGS@ 6 | LIBS = @LIBS@ 7 | LIBTOOL = @LIBTOOL@ 8 | 9 | prefix = @prefix@ 10 | exec_prefix = @exec_prefix@ 11 | libdir = @libdir@ 12 | 13 | SHELL = @SHELL@ 14 | top_builddir = @top_builddir@ 15 | top_srcdir = @top_srcdir@ 16 | srcdir = @srcdir@ 17 | VPATH = @srcdir@ 18 | 19 | JNI_CFLAGS = @JNI_CFLAGS@ 20 | WFDB_CFLAGS = @WFDB_CFLAGS@ 21 | WFDB_LIBS = @WFDB_LIBS@ 22 | 23 | JAVA = @JAVA@ 24 | 25 | classdir = $(srcdir)/../../bin/classes 26 | 27 | all: librdsampjni.la 28 | 29 | check: librdsampjni.la 30 | rm -rf test.jar nativelibs 31 | jar cf test.jar -C $(classdir) . 32 | $(MAKE) install libdir=`pwd`/nativelibs/custom/lib 33 | $(JAVA) -cp test.jar org.physionet.wfdb.jni.Rdsamp -r 100s -t s10 > 100s.out 34 | diff 100s.out $(srcdir)/100s.expected 35 | 36 | install: librdsampjni.la 37 | mkdir -p $(libdir) 38 | $(LIBTOOL) --mode=install cp librdsampjni.la $(libdir) 39 | 40 | librdsampjni.la: rdsampjni.lo 41 | $(LIBTOOL) --mode=link $(CC) $(CLFAGS) $(LDFLAGS) \ 42 | -avoid-version -no-undefined -rpath /fnord \ 43 | rdsampjni.lo -o librdsampjni.la \ 44 | $(WFDB_LIBS) $(LIBS) 45 | 46 | rdsampjni.lo: rdsampjni.c 47 | $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) $(CPPFLAGS) \ 48 | $(DEFS) $(WFDB_CFLAGS) $(JNI_CFLAGS) -I. \ 49 | -c $(srcdir)/rdsampjni.c 50 | 51 | clean: 52 | $(LIBTOOL) --mode=clean rm -f *.la *.lo 53 | rm -rf test.jar nativelibs 100s.out 54 | 55 | distclean: clean 56 | rm -f config.status config.log libtool 57 | rm -f Makefile 58 | 59 | Makefile: Makefile.in config.status 60 | $(SHELL) ./config.status 61 | config.status: configure 62 | $(SHELL) ./config.status --recheck 63 | 64 | .PHONY: all clean distclean install check 65 | -------------------------------------------------------------------------------- /dependencies/jni/autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | aclocal 4 | libtoolize --install --copy 5 | autoconf 6 | -------------------------------------------------------------------------------- /dependencies/jni/configure.ac: -------------------------------------------------------------------------------- 1 | AC_PREREQ([2.63]) 2 | AC_INIT([librdsampjni], [0.9.10], [wfdb-matlab-support@physionet.org]) 3 | AC_CONFIG_SRCDIR([rdsampjni.c]) 4 | 5 | AC_PROG_CC 6 | if test "x$GCC" = "xyes"; then 7 | CFLAGS="$CFLAGS -W -Wall" 8 | fi 9 | 10 | AC_CANONICAL_HOST 11 | AC_DISABLE_STATIC 12 | AC_PROG_LIBTOOL 13 | 14 | AC_ARG_VAR([JAVA], [Java interpreter]) 15 | AC_ARG_VAR([JAVAC], [Java compiler]) 16 | AC_CHECK_PROGS([JAVA], [java]) 17 | AC_CHECK_PROGS([JAVAC], [javac]) 18 | 19 | # try to guess where JNI headers might be 20 | # (partially inspired by Don Anderson's AC_JNI_INCLUDE_DIR) 21 | AC_ARG_VAR([JAVA_HOME], [JDK installation prefix]) 22 | AC_ARG_VAR([JNI_CFLAGS], [C compiler flags for JNI]) 23 | if test "x$JNI_CFLAGS" = "x"; then 24 | if test "x$JAVA_HOME" = "x" && test "x$host_alias" = "x$build_alias"; then 25 | # If JAVA_HOME not set, and we are not cross-compiling, try to 26 | # infer it from the location of 'javac' (after following 27 | # symlinks.) 28 | AC_PATH_PROG([_JAVAC], [$JAVAC]) 29 | _cur=$_JAVAC 30 | while ls -ld "$_cur" 2>/dev/null | grep " -> " >/dev/null; do 31 | AC_MSG_CHECKING(symlink for $_cur) 32 | _slink=`ls -ld "$_cur" | sed 's/.* -> //'` 33 | case "$_slink" in 34 | /*) _cur="$_slink";; 35 | # 'X' avoids triggering unwanted echo options. 36 | *) _cur=`echo "X$_cur" | sed -e 's/^X//' -e 's:[[^/]]*$::'`"$_slink";; 37 | esac 38 | AC_MSG_RESULT($_cur) 39 | done 40 | if test -f "$_cur"; then 41 | JAVA_HOME=`echo "$_cur" | sed -e 's://*:/:g' -e 's:/[[^/]]*/[[^/]]*$::'` 42 | fi 43 | fi 44 | if test "x$JAVA_HOME" != "x" && test -f "$JAVA_HOME/include/jni.h"; then 45 | # If JAVA_HOME is known, look for headers there. 46 | JNI_CFLAGS="-I$JAVA_HOME/include" 47 | case "$host_os" in 48 | bsdi*) subdirs="bsdos";; 49 | freebsd*) subdirs="freebsd";; 50 | darwin*) subdirs="darwin";; 51 | linux*) subdirs="linux genunix";; 52 | osf*) subdirs="alpha";; 53 | solaris*) subdirs="solaris";; 54 | mingw*) subdirs="win32";; 55 | cygwin*) subdirs="win32";; 56 | *) subdirs="genunix";; 57 | esac 58 | for d in $subdirs; do 59 | if test -d "$JAVA_HOME/include/$d"; then 60 | JNI_CFLAGS="$JNI_CFLAGS -I$JAVA_HOME/include/$d" 61 | fi 62 | done 63 | else 64 | # Otherwise try to guess at location for system-provided headers. 65 | case $host_os in 66 | darwin*) 67 | if test "x$cross_compiling" = "xyes"; then 68 | opt="-iwithsysroot " 69 | else 70 | opt="-I" 71 | fi 72 | JNI_CFLAGS="$opt/System/Library/Frameworks/JavaVM.framework/Headers/" 73 | ;; 74 | esac 75 | fi 76 | fi 77 | 78 | AC_ARG_VAR([WFDB_CFLAGS], [C compiler flags for WFDB]) 79 | AC_ARG_VAR([WFDB_LIBS], [Library flags for WFDB]) 80 | if test "x$WFDB_CFLAGS$WFDB_LIBS" = "x"; then 81 | WFDB_CFLAGS=`wfdb-config --cflags 2>/dev/null` 82 | WFDB_LIBS=`wfdb-config --libs 2>/dev/null` 83 | fi 84 | 85 | cppflags1=$CPPFLAGS 86 | libs1=$LIBS 87 | 88 | CPPFLAGS="$cppflags1 $JNI_CFLAGS" 89 | AC_CHECK_HEADER([jni.h], [ : ], [AC_MSG_ERROR([JNI header files not found.])]) 90 | 91 | CPPFLAGS="$cppflags1 $WFDB_CFLAGS" 92 | LIBS="$WFDB_LIBS $libs1" 93 | AC_CHECK_HEADER([wfdb/wfdb.h], [ : ], [AC_MSG_ERROR([WFDB header files not found.])]) 94 | AC_CHECK_FUNC([isigopen], [ : ], [AC_MSG_ERROR([WFDB library not found.])]) 95 | 96 | CPPFLAGS=$cppflags1 97 | LIBS=$libs1 98 | 99 | AC_CONFIG_FILES([Makefile]) 100 | AC_OUTPUT 101 | -------------------------------------------------------------------------------- /dependencies/jni/readme: -------------------------------------------------------------------------------- 1 | 2 | 3 | Implementation of some of the WFDB Applications via the Java Native Interface for 4 | improvements in speed and memory allocation. 5 | 6 | Some useful links to guide through development: 7 | 8 | http://www.lithiumhead.com/notes/windows_jni 9 | https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html#zz-2.1 10 | 11 | 12 | The Eclipse project space need to be configured properly to that these libraries are visible when building 13 | the respective Java classes. -------------------------------------------------------------------------------- /gen-doc.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | #File used to generated HTML documention for functions of the toolbox. 4 | #Should be run from the directory in which it is located. 5 | 6 | #Written by Ikaro Silva 2014 7 | 8 | for i in `grep -nr %endOfHelp ./mcode/ | sed 's/:%.*//'` 9 | do 10 | lineEnd=$(( ${i##.*:} -1 )) 11 | fname=${i%%:*} 12 | func=${fname##.*/} 13 | func=${func%%.*} 14 | help=`head -n ${lineEnd} ${fname} | sed 's/%//'` 15 | 16 | #Generate HTML for the M file 17 | cat ./mcode/html/template.html | sed "s/MYFUNC/${func}/g" > ./mcode/html/${func}.html 18 | echo "${help}" >>./mcode/html/${func}.html 19 | cat ./mcode/html/template_bottom.html >> ./mcode/html/${func}.html 20 | echo "Generated file: ./mcode/html/${func}.html" 21 | done 22 | 23 | #Copy NEWS to HTML as well 24 | cp -vf ./mcode/NEWS ./mcode/html/NEWS 25 | 26 | echo "Finished generated doc files" -------------------------------------------------------------------------------- /jarbuild.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /mcode/.gitignore: -------------------------------------------------------------------------------- 1 | /100m.hea 2 | /100m.mat 3 | -------------------------------------------------------------------------------- /mcode/Contents.m: -------------------------------------------------------------------------------- 1 | % WaveForm DataBase (WFDB) Toolbox 2 | % 3 | % 4 | %This is a set of MATLAB functions and wrappers for reading, writing, and processing 5 | %files in the formats used by PhysioBank databases (among others). 6 | %The WFDB Toolbox has support for reading public PhysioNet databases directly from 7 | %web. This feature allows your code to analyze a wide range of physiological 8 | %signals available from PhysioBank without the need to download entire 9 | %records and to store them locally. This toolbox is distributed under the LGPL 10 | %license (see LICENSE.txt file in this directory). For more informationa about the 11 | %toolbox please go to: http://www.physionet.org 12 | % 13 | % 14 | % 15 | % 16 | % Table of Contents (T0C) 17 | % ----------------------- 18 | % ann2rr - Extract a list of intervals from an annotation file 19 | % bxb - ANSI/AAMI-standard beat-by-beat annotation comparator 20 | % dfa - Detrended Fluctuation Analysis 21 | % corrint - Correlation Integral Analysis 22 | % edr - Derives a respiration signal from an ECG signal 23 | % ecgpuwave - Estimation of QRS and P waves from ECG signals 24 | % gqrs - Estimation of QRS from ECG signals 25 | % lomb - Estimates power spectrum using the Lomb periodogram method 26 | % mat2wfdb - Writes a MATLAB variable into a WDFB record file 27 | % mrgann - Merge annotation files 28 | % msentropy - Multi scale entropy estimation 29 | % physionetdb - Get information about all of PhysioNet's available databases and signals 30 | % pbsearch - Search PhysioBank from MATLAB's browser for records with specific features. 31 | % rdann - Read annotation files for WFDB records 32 | % rdmat - Reads a signal into the workspace from a *.mat file generated by WFDB2MAT 33 | % rdmimic2wave - Searches MIMIC II matched waveform records within a clinical time range 34 | % rdsamp - Read signal files of WFDB records 35 | % sortann - Rearrange annotations in canonical order 36 | % snip - Copy an excerpt of a WFDB record 37 | % sqrs - Finds the QRS complexes of a WFDB ECG record signal 38 | % surrogate - Generates amplitude adjusted phase shuffled surrogate time series 39 | % sumann - Summarize the contents of a WFDB annotation file 40 | % tach - Calculates instantaneous heart rate of a WFDB ECG record signal 41 | % visgraph - Visibility Graph Analysis 42 | % wfdb - Prints this help information of the Toolbox 43 | % wfdb2mat - Converts a record *.dat file into a *.mat file. 44 | % wfdbexec - Executes a system call to any installed native WFDB command. 45 | % wabp - Arterial blood pressure (ABP) pulse detector 46 | % wfdbdemo - Demonstration of the WFDB App Toolbox 47 | % wfdbdesc - Return signal information for about a WFDB record 48 | % wfdbloadlib - Load WFDB library and displays Toolbox configuration. 49 | % wfdbRecordViewer- GUI for visualizing WFDB records and annotations 50 | % wfdbtest - Script to test installation of the Toolbox 51 | % wfdbtime - Converts sample index to WFDB Time based on WFDB record information 52 | % wfdbtool - Launches PhysioNet's Signal and Annotation Viewer ( LightWave ) 53 | % woody - Perform signal averaging with alignment 54 | % wqrs - Finds the QRS complexes of a WFDB ECG record signal 55 | % wrann - Writes annotations for WFDB records into annotation files 56 | % wrsamp - Writes signal data into WFDB-compatible records 57 | % 58 | % 59 | % 60 | % To credit this toolbox, please cite the following references in your work: 61 | % 62 | % Silva, I, Moody, G. 63 | % "An Open-source Toolbox for Analysing and Processing PhysioNet Databases in MATLAB and Octave." 64 | % Journal of Open Research Software 2(1):e27 65 | % [http://dx.doi.org/10.5334/jors.bi] ; 66 | % 2014 (September 24). 67 | % 68 | % 69 | % Goldberger AL, Amaral LAN, Glass L, Hausdorff JM, Ivanov PCh, Mark RG, Mietus JE, Moody GB, Peng CK, Stanley HE. 70 | % "PhysioBank, PhysioToolkit, and PhysioNet: Components of a New Research Resource for Complex 71 | % Physiologic Signals." 72 | % Circulation 101(23):e215-e220 73 | % [http://circ.ahajournals.org/cgi/content/full/101/23/e215]; 74 | % 2000 (June 13). 75 | % PMID: 10851218; doi: 10.1161/01.CIR.101.23.e215 76 | % 77 | % 78 | % In addition, some of these functions use binary executables compiled 79 | % from open-source third-party code contributed to PhysioNet. When using 80 | % these functions on your work, please look at the help for that function 81 | % in order find out how to credit the original paper and authors. 82 | % 83 | % For questions, contributions, and feedback post at our community Forum: 84 | % http://groups.google.com/forum/#!forum/wfdb-app-toolbox 85 | % 86 | % 87 | % The source code for the native libraries used in this toolbox can be obtained from PhysioNet under 88 | % the GNU GPL agreement. 89 | % 90 | % The original contributors of any open source native code that is available at PhysioNet 91 | % and is used by the Toolbox are credited in their respective MATLAB wrappers. In addition, the 92 | % following people have contributed to the development or testing of the MATLAB wrappers 93 | % and the JVM interface: 94 | % 95 | % Sahar Alkhairy 96 | % Fernando Andreotti Lage 97 | % Joachim Behar 98 | % Eudald Bogatell 99 | % Jonas Carlson 100 | % Gari D. Clifford 101 | % Michael Craig 102 | % Mohammad Ghassemi 103 | % Alistair Johnson 104 | % Li-wei Lehman 105 | % Sara Mariani 106 | % Louis Mayaud 107 | % Blaž Merela 108 | % Benjamin Moody 109 | % George B. Moody 110 | % Shamin Nemati 111 | % Piotr Podziemski 112 | % Erina Katsumata 113 | % Aled Rowen 114 | % Kari Schoonbee 115 | % Daniel J. Scott 116 | % Ikaro Silva 117 | % Gabriel Squillace 118 | % Bryan Tripp 119 | % Chen Xie 120 | % Tingting Zhu 121 | % 122 | % 123 | %Created by Ikaro Silva 2012 124 | 125 | %endOfHelp 126 | 127 | -------------------------------------------------------------------------------- /mcode/NEWS: -------------------------------------------------------------------------------- 1 | For a detailed list of changes see the repository Log at: 2 | http://github.com/ikarosilva/wfdb-app-toolbox.git 3 | 4 | 0.10.0 (October 31, 2017) 5 | Updated WFDB library and applications to version 10.5.25pre1. 6 | 7 | The API for the RDSAMP function has changed with this version. 8 | Note that the matrix of sample values is now the *first* output 9 | value rather than the third. 10 | 11 | The toolbox is now compatible with MATLAB/Octave releases that 12 | use Java 1.8 (or later.) 13 | 14 | 0.9.10 (March 13, 2015) 15 | Added the function SNIP to the library. Added local caching of PhysioNet files to the {wfdbroot}/databases directory. 16 | Updated native libraries to WFDB 10.5.24. Implement RSDSAMP via the JNI for improvement in memory and speed. 17 | Several bug fixes. WFDBLOADLIB now issues a warning if installation directory has an empty space in the path. 18 | Added feature to WFDBRECORDVIEWER that allows user to remotely view any record or annotation in PhysioNet 19 | through WFDBRECORDVIEWER's interface. Added following features to WFDBRECORDVIEWER: 20 | display beat labels, export GUI as figure. Added following signal analysis features to WFDBRECORDVIEWER: 21 | Spatial PCA, Karhunen–Loève expansion, Pwelch spectral estimation, filtering (notch, resonator, and custom), 22 | fundamental frequency tracking via LMS, Coherence analysis. 23 | 24 | 0.9.9 (February 1, 2015) 25 | Added a GUI for viewing and processing WFDB records and annotation: 26 | WFDBRECORDVIEWER. Several bug fixes. 27 | 28 | 0.9.8 (December 1, 2014) 29 | Several features added and bug fixes. New implementation of the EDR function 30 | by Sara Mariani. Removed WFDBUPDATE and SCORE2013. Added the following new functions : 31 | CORRINT, DFA, PBSEARCH, SURROGATE, VISGRAPH, and WFDBTOOL. 32 | 33 | 0.9.7 (October 8, 2014) 34 | Updated WFDB library to 10.5.24. Added method to change the Toolbox binary path at runtime. 35 | Added data integrity check in RDSAMP and added extra data type options. 36 | Improved performance in WRANN, and WFDBTIME. Changed API in PHYSIONETDB. 37 | Fixed issues with ECPUWAVE reading annotations passed through signalList. Removed 38 | STDERR from input stream when parsing system calls. Fixed issue with RDANN 39 | returning channels in with 0 indexing. WFDBTEST now also checks if user is running 40 | on supported version of MATLAB or Mac OS X. 41 | 42 | 0.9.6.1 (February 10, 2014): 43 | Minor bug fixes with JAR files loading libraries. 44 | 45 | 0.9.6 (February 6, 2014): 46 | Added support to GNU Octave version 3.6.4 (requires Octave Java package). 47 | Added single, and fixed point, and higher precision options to RDSAMP. 48 | Added a system wide WFDB path configuration to WFDBLOADLIB. The default 49 | search is now the current directory, {WFDB_HOME}/database, and http:physionet/physiobank/database. 50 | So databases can be stored in a single centralized location on the user's machine 51 | ({WFDB_HOME}/database). Added the function WOODY (average with alignment), and HTML 52 | help files. 53 | 54 | 0.9.5 (December 6, 2013): 55 | Updated native libs to WFDB 10.5.22. Added WFDBEXEC 56 | (runs WFDB native commands in their native API and by a system call through the JVM), 57 | EDR, GQRS, MSENTROPY. Added framework for users who want to run their own custom version 58 | of the WFDB native binaries. Any user who can successfully compile and run WFDB executables 59 | on their system should be able to use most functionality of this toolbox provided that 60 | they install the binaries in the '/mcode/nativelibs/custom' directory (see README for details). 61 | Added WDFB and WFDBCAL environment variables and ability to set and change them. Added 62 | system wide debugging information and variable to allow configuration of maximum network 63 | waiting time (default = 1 second). 64 | 65 | 0.9.4.3 (06 November 2013): 66 | Fixed libcurl and path issue. 67 | 68 | 0.9.4.2 (05 November 2013): 69 | Added more diagnostic information and fixed some issues with using spaces in Windows directories. 70 | 71 | 0.9.4.1 (04 November 2013): 72 | Fixed library path issues with Windows systems. 73 | 74 | 0.9.4 (01 November 2013): 75 | Updated native libs to WFDB 10.5.20. Added a LightWave interface: WFDBTOOL. 76 | Fixed bugs in WRANN, RDANN, RDSAMP. Included libcurl with native libs. 77 | 78 | 0.9.3 (22 August 2013): 79 | Fixed bias issues with SCORE2013. 80 | 81 | 0.9.2 (15 August 2013): 82 | Fixed issues with WFDBUPDATE and SCORE2013. 83 | 84 | 0.9.1 (12 July 2013): 85 | Added: MAPRECORD. Fixed parsing issues with RDANN and added option 86 | to load specific annotation types only. 87 | 88 | 0.9.0 (24 June 2013): 89 | Added: WFDBUPDATE, BXB, MXM, SUMANN, SORTANN, WABP, LOMB, and 90 | RDMIMIC2WAVE. Fixed bug and performance issues with RDANN and 91 | RDSAMP. 92 | 93 | 0.0.2 (13 June 2013): 94 | Added score2013 to score PhysioNet2013 challenge entries. 95 | Fixed MATLAB/WDDB indexing issues with RDANN and WRANN. 96 | Allowed scalar parameters into WRANN. 97 | Added external logging capabilities to the Java wrappers. 98 | 99 | 0.0.1 (11 June 2013): 100 | Initial beta release. 101 | -------------------------------------------------------------------------------- /mcode/README.txt: -------------------------------------------------------------------------------- 1 | 2 | -------To install the WFDB Application Toolbox:------- 3 | 4 | 1) Unzip the zip file into the directory you wish to install the toolbox 5 | 6 | 7 | If you run into any problems and need to contact us, 8 | please send the entire output of this script. 9 | 10 | 2) From within MATLAB, cd into the directory and add it to your path: 11 | 12 | cd wfdb-app-toolbox-x-x-x;cd mcode 13 | addpath(pwd);savepath 14 | wfdbdemo %Optional demoing of the toolbox 15 | 16 | 17 | 18 | -------Getting help and information about the WFDB Toolbox-------- 19 | For a information about the Toolbox and the list of functions associated with it 20 | type: 21 | 22 | wfdb 23 | 24 | at the MATLAB prompt. 25 | 26 | 27 | 28 | -------To Uninstall the toolbox:------- 29 | 30 | 1)From MATLAB, find where the toolbox is installed: 31 | 32 | install_dir=which('wfdb') 33 | 34 | 2) Remove the directory from the MATLAB path: 35 | rmpath(install_dir); 36 | 37 | 3)(Optional) Remove the Toolbox files permanently from your machine: 38 | delete(install_dir) 39 | 40 | 41 | 42 | -------CONTACT: For help, feedback, and support please contact us at the community Forum: 43 | https://groups.google.com/forum/#!forum/wfdb-app-toolbox 44 | 45 | *When contacting us about issues with the Toolbox, please send us the output of 46 | the "wfdbtest" script. 47 | 48 | 49 | 50 | -------Join our community!! ------- 51 | Join our community at: 52 | 53 | https://groups.google.com/forum/#!forum/wfdb-app-toolbox 54 | 55 | -------------------------------------------------------------------------------- /mcode/ann2rr.m: -------------------------------------------------------------------------------- 1 | function varargout=ann2rr(varargin) 2 | % 3 | % [RR,tms]=ann2rr(recordName,annotator,N,N0,consecutiveOnly) 4 | % 5 | % Wrapper to WFDB ANN2RR: 6 | % http://www.physionet.org/physiotools/wag/ann2rr-1.htm 7 | % 8 | % Reads a WFDB record and Annotation file to return: 9 | % 10 | % 11 | % RR 12 | % Nx1 vector of integers representing the duration of the RR 13 | % interval in samples. 14 | % 15 | % tms 16 | % Nx1 vector of integers representing the begining of the RR 17 | % interval in samples. 18 | % 19 | % Required Parameters: 20 | % 21 | % recorName 22 | % String specifying the name of the record in the WFDB path or 23 | % in the current directory. 24 | % 25 | % annotator - 26 | % String specifying the name of the annotation file in the WFDB path or 27 | % in the current directory. 28 | % 29 | % Optional Parameters are: 30 | % 31 | % N 32 | % A 1x1 integer specifying the sample number at which to stop reading the 33 | % record file (default read all = N). 34 | % N0 35 | % A 1x1 integer specifying the sample number at which to start reading the 36 | % annotion file (default 1 = begining of the record). 37 | % 38 | % consecutiveOnly 39 | % A 1x1 boolean. If true, prints intervals between consecutive valid 40 | % annotaions only (default =true). 41 | % 42 | % 43 | % Written by Ikaro Silva, 2013 44 | % Last Modified: January, 16, 2013 45 | % Version 1.1 46 | % 47 | % Since 0.0.1 48 | % %Example 49 | %[rr,tm]=ann2rr('challenge/2013/set-a/a01','fqrs'); 50 | 51 | %endOfHelp 52 | 53 | [javaWfdbExec,config]=getWfdbClass('ann2rr'); 54 | 55 | %Set default pararamter values 56 | inputs={'recordName','annotator','N','N0','consecutiveOnly'}; 57 | outputs={'data(:,2)','data(:,1)'}; 58 | N=[]; 59 | N0=1; 60 | consecutiveOnly=1; 61 | for n=1:nargin 62 | if(~isempty(varargin{n})) 63 | eval([inputs{n} '=varargin{n};']); 64 | end 65 | end 66 | 67 | N0=num2str(N0-1); %-1 is necessary because WFDB is 0 based indexed. 68 | wfdb_argument={'-r',recordName,'-a',annotator,'-f',['s' N0]}; 69 | 70 | if(~isempty(N)) 71 | wfdb_argument{end+1}='-t'; 72 | %-1 is necessary because WFDB is 0 based indexed. 73 | wfdb_argument{end+1}=['s' num2str(N-1)]; 74 | end 75 | 76 | if(consecutiveOnly) 77 | wfdb_argument{end+1}='-c'; 78 | end 79 | wfdb_argument{end+1}='-V'; 80 | 81 | data=javaWfdbExec.execToDoubleArray(wfdb_argument); 82 | data=wfdbjava2mat(data); 83 | for n=1:nargout 84 | eval(['varargout{n}=' outputs{n} ';']); 85 | end 86 | -------------------------------------------------------------------------------- /mcode/bxb.m: -------------------------------------------------------------------------------- 1 | function varargout=bxb(varargin) 2 | % 3 | % report=bxb(recName,refAnn,testAnn,reportFile,beginTime,stopTime,matchWindow) 4 | % 5 | % Wrapper to WFDB BXB: 6 | % http://www.physionet.org/physiotools/wag/bxb-1.htm 7 | % 8 | % Creates a report file ("reportFile) using 9 | % ANSI/AAMI-standard beat-by-beat annotation comparator. 10 | % 11 | % Ouput Parameters: 12 | % 13 | % report (Optional) 14 | % Returns a structure containing information on the 'reportFile'. 15 | % This can be used to read report File that has been previously 16 | % generated by BXB (see Example 2 below), into the workspace. 17 | % The structure has the following fields: 18 | % report.data - 7x7 matrix of counters: 19 | % (1,1) normal beats labelled as normal 20 | % (1,2) normal beats labelled as supraventricular 21 | % (1,3) normal beats labelled as ventricular 22 | % (1,4) normal beats labelled as fusion 23 | % (1,5) normal beats labelled as paced/unknown 24 | % (1,6) normal beats not detected 25 | % (1,7) normal beats labelled as unreadable 26 | % (2,1) supraventricular beats labelled as normal 27 | % ... 28 | % (3,1) ventricular beats labelled as normal 29 | % ... 30 | % (4,1) fusion beats labelled as normal 31 | % ... 32 | % (5,1) paced/unknown beats labelled as normal 33 | % ... 34 | % (6,1) falsely detected beats labelled as normal 35 | % ... 36 | % (6,6) unused (NaN) 37 | % (6,7) unused (NaN) 38 | % (7,1) beats detected in unreadable regions, labelled as normal 39 | % ... 40 | % (7,6) unused (NaN) 41 | % (7,7) unused (NaN) 42 | % 43 | %Input Parameters: 44 | % recName 45 | % String specifying the WFDB record file. 46 | % 47 | % refAnn 48 | % String specifying the reference WFDB annotation file. 49 | % 50 | % testAnn 51 | % String specifying the test WFDB annotation file. 52 | % 53 | % reportFile 54 | % String representing the file at which the report will be 55 | % written to. 56 | % 57 | % beginTime (Optional) 58 | % String specifying the begin time in WFDB time format. The 59 | % WFDB time format is described at 60 | % http://www.physionet.org/physiotools/wag/intro.htm#time. 61 | % Default starts comparison after 5 minutes. 62 | % 63 | % stopTime (Optional) 64 | % String specifying the stop time in WFDB format (default is end of 65 | % record). 66 | % 67 | % matchWindow (Optional) 68 | % 1x1 WFDB Time specifying the match window size (default = 0.15 s). 69 | % 70 | % 71 | % Written by Ikaro Silva, 2013 72 | % Last Modified: May 28, 2014 73 | % Version 1.1 74 | % Since 0.9.0 75 | % 76 | % %Example (this will generate a /mitdb/100.qrs file at your directory): 77 | % %Compares SQRS detetor with the MITDB ATR annotations 78 | % 79 | % [refAnn]=rdann('mitdb/100','atr'); 80 | % sqrs('mitdb/100'); 81 | % [testAnn]=rdann('mitdb/100','qrs'); 82 | % report=bxb('mitdb/100','atr','qrs','bxbReport.txt') 83 | % 84 | % 85 | % %Example 2 - Load variables from a report file that has been previously 86 | % %generated 87 | % report=bxb([],[],[],'bxbReport.txt') 88 | % 89 | % 90 | % See also RDANN, MXM, WFDBTIME 91 | 92 | %endOfHelp 93 | 94 | javaWfdbExec=getWfdbClass('bxb'); 95 | 96 | %Set default pararamter values 97 | inputs={'recName','refAnn','testAnn','reportFile','beginTime','stopTime','matchWindow'}; 98 | recName=[]; 99 | refAnn=[]; 100 | testAnn=[]; 101 | reportFile=[]; 102 | beginTime=[]; 103 | stopTime=[]; 104 | matchWindow=[]; 105 | for n=1:nargin 106 | if(~isempty(varargin{n})) 107 | eval([inputs{n} '=varargin{n};']); 108 | end 109 | end 110 | 111 | if(~isempty(recName)) 112 | %Only execute this if recName is defined, otherwise we assume 113 | %that the user just want to load the 'reporFile' variable into the 114 | %workspace based on a previously generated 'reportFile' 115 | wfdb_argument={'-r',recName,'-a',refAnn,testAnn,'-S',reportFile}; 116 | if(~isempty(beginTime)) 117 | wfdb_argument{end+1}='-f'; 118 | wfdb_argument{end+1}=beginTime; 119 | end 120 | if(~isempty(stopTime)) 121 | wfdb_argument{end+1}='-t'; 122 | wfdb_argument{end+1}=stopTime; 123 | end 124 | if(~isempty(matchWindow)) 125 | wfdb_argument{end+1}='-w'; 126 | wfdb_argument{end+1}=matchWindow; 127 | end 128 | report=javaWfdbExec.execToStringList(wfdb_argument); 129 | end 130 | 131 | if(nargout>0) 132 | varargout{1}=bxbReader(reportFile); 133 | end 134 | 135 | function reportData = bxbReader(fileName) 136 | d=[]; 137 | n=0; 138 | f=fopen(fileName,'rt'); 139 | s=fgetl(f); 140 | while(ischar(s) && isempty(strfind(s,'|'))) 141 | s=fgetl(f); 142 | end 143 | while(ischar(s) && ~isempty(strfind(s,'|'))) 144 | v=strread(s(strfind(s,'|')+1:end),'%f'); 145 | while(length(v) 2 | 3 | 4 | 5 | 6 | MyToolbox Toolbox 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Getting Started with the MyToolbox Toolbox 19 | System Requirements 20 | 21 | Features 22 | 23 | Feature 1 24 | 25 | Feature 2 26 | 27 | 28 | 29 | 30 | MyToolbox User Guide 32 | Setting Up MyToolbox 33 | 34 | Processing Data 35 | 36 | Verifying MyToolbox outputs 37 | Handling Test Failures 38 | 39 | 40 | 41 | 42 | 43 | Function Reference 45 | 46 | First Category 47 | 48 | function_1 49 | function_2 50 | 51 | 52 | 53 | Second Category 54 | 55 | function_3 56 | function_4 57 | 58 | 59 | 60 | Third category 61 | 62 | 63 | 64 | 65 | Mytoolbox Examples 67 | 68 | 69 | 71 | MyToolbox Web Site (Example only: goes to mathworks.com) 72 | 73 | 74 | -------------------------------------------------------------------------------- /mcode/html/NEWS: -------------------------------------------------------------------------------- 1 | For a detailed list of changes see the repository Log at: 2 | http://github.com/ikarosilva/wfdb-app-toolbox.git 3 | 4 | 0.9.10 (March 13, 2015) 5 | Added the function SNIP to the library. Added local caching of PhysioNet files to the {wfdbroot}/databases directory. 6 | Updated native libraries to WFDB 10.5.24. Implement RSDSAMP via the JNI for improvement in memory and speed. 7 | Several bug fixes. WFDBLOADLIB now issues a warning if installation directory has an empty space in the path. 8 | Added feature to WFDBRECORDVIEWER that allows user to remotely view any record or annotation in PhysioNet 9 | through WFDBRECORDVIEWER's interface. Added following features to WFDBRECORDVIEWER: 10 | display beat labels, export GUI as figure. Added following signal analysis features to WFDBRECORDVIEWER: 11 | Spatial PCA, Karhunen–Loève expansion, Pwelch spectral estimation, filtering (notch, resonator, and custom), 12 | fundamental frequency tracking via LMS, Coherence analysis. 13 | 14 | 0.9.9 (February 1, 2015) 15 | Added a GUI for viewing and processing WFDB records and annotation: 16 | WFDBRECORDVIEWER. Several bug fixes. 17 | 18 | 0.9.8 (December 1, 2014) 19 | Several features added and bug fixes. New implementation of the EDR function 20 | by Sara Mariani. Removed WFDBUPDATE and SCORE2013. Added the following new functions : 21 | CORRINT, DFA, PBSEARCH, SURROGATE, VISGRAPH, and WFDBTOOL. 22 | 23 | 0.9.7 (October 8, 2014) 24 | Updated WFDB library to 10.5.24. Added method to change the Toolbox binary path at runtime. 25 | Added data integrity check in RDSAMP and added extra data type options. 26 | Improved performance in WRANN, and WFDBTIME. Changed API in PHYSIONETDB. 27 | Fixed issues with ECPUWAVE reading annotations passed through signalList. Removed 28 | STDERR from input stream when parsing system calls. Fixed issue with RDANN 29 | returning channels in with 0 indexing. WFDBTEST now also checks if user is running 30 | on supported version of MATLAB or Mac OS X. 31 | 32 | 0.9.6.1 (February 10, 2014): 33 | Minor bug fixes with JAR files loading libraries. 34 | 35 | 0.9.6 (February 6, 2014): 36 | Added support to GNU Octave version 3.6.4 (requires Octave Java package). 37 | Added single, and fixed point, and higher precision options to RDSAMP. 38 | Added a system wide WFDB path configuration to WFDBLOADLIB. The default 39 | search is now the current directory, {WFDB_HOME}/database, and http:physionet/physiobank/database. 40 | So databases can be stored in a single centralized location on the user's machine 41 | ({WFDB_HOME}/database). Added the function WOODY (average with alignment), and HTML 42 | help files. 43 | 44 | 0.9.5 (December 6, 2013): 45 | Updated native libs to WFDB 10.5.22. Added WFDBEXEC 46 | (runs WFDB native commands in their native API and by a system call through the JVM), 47 | EDR, GQRS, MSENTROPY. Added framework for users who want to run their own custom version 48 | of the WFDB native binaries. Any user who can successfully compile and run WFDB executables 49 | on their system should be able to use most functionality of this toolbox provided that 50 | they install the binaries in the '/mcode/nativelibs/custom' directory (see README for details). 51 | Added WDFB and WFDBCAL environment variables and ability to set and change them. Added 52 | system wide debugging information and variable to allow configuration of maximum network 53 | waiting time (default = 1 second). 54 | 55 | 0.9.4.3 (06 November 2013): 56 | Fixed libcurl and path issue. 57 | 58 | 0.9.4.2 (05 November 2013): 59 | Added more diagnostic information and fixed some issues with using spaces in Windows directories. 60 | 61 | 0.9.4.1 (04 November 2013): 62 | Fixed library path issues with Windows systems. 63 | 64 | 0.9.4 (01 November 2013): 65 | Updated native libs to WFDB 10.5.20. Added a LightWave interface: WFDBTOOL. 66 | Fixed bugs in WRANN, RDANN, RDSAMP. Included libcurl with native libs. 67 | 68 | 0.9.3 (22 August 2013): 69 | Fixed bias issues with SCORE2013. 70 | 71 | 0.9.2 (15 August 2013): 72 | Fixed issues with WFDBUPDATE and SCORE2013. 73 | 74 | 0.9.1 (12 July 2013): 75 | Added: MAPRECORD. Fixed parsing issues with RDANN and added option 76 | to load specific annotation types only. 77 | 78 | 0.9.0 (24 June 2013): 79 | Added: WFDBUPDATE, BXB, MXM, SUMANN, SORTANN, WABP, LOMB, and 80 | RDMIMIC2WAVE. Fixed bug and performance issues with RDANN and 81 | RDSAMP. 82 | 83 | 0.0.2 (13 June 2013): 84 | Added score2013 to score PhysioNet2013 challenge entries. 85 | Fixed MATLAB/WDDB indexing issues with RDANN and WRANN. 86 | Allowed scalar parameters into WRANN. 87 | Added external logging capabilities to the Java wrappers. 88 | 89 | 0.0.1 (11 June 2013): 90 | Initial beta release. 91 | -------------------------------------------------------------------------------- /mcode/html/helptoc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | WFDB Toolbox 4 | Functions 5 | ann2rr 6 | bxb 7 | ecgpuwave 8 | edr 9 | getWfdbClass 10 | gqrs 11 | lomb 12 | maprecord 13 | mat2wfdb 14 | mrgann 15 | msentropy 16 | mxm 17 | physionetdb 18 | rdann 19 | rdmimic2wave 20 | rdsamp 21 | score2013 22 | sortann 23 | sqrs 24 | sumann 25 | tach 26 | wabp 27 | wfdbdesc 28 | wfdbexec 29 | wfdbloadlib 30 | wfdbtest 31 | wfdbtime 32 | wfdbtool 33 | wfdbupdate 34 | wqrs 35 | wrann 36 | wrsamp 37 | 38 | 40 | WFDB Toolbox Web Site 41 | 42 | 44 | FAQ 45 | 46 | 48 | Forum 49 | 50 | 52 | Database List 53 | 54 | 56 | Release Notes 57 | 58 | 60 | License 61 | 62 | 64 | DEMOS 65 | 66 | 67 | -------------------------------------------------------------------------------- /mcode/html/helpwin.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Helvetica, Arial, sans-serif; 3 | font-size: 12px; 4 | } 5 | 6 | a { 7 | color:#000099; 8 | } 9 | 10 | a:visited { 11 | color:#840084; 12 | } 13 | 14 | a:active { 15 | color:#000099; 16 | } 17 | 18 | a:hover { 19 | color:#000033; 20 | } 21 | 22 | hr { 23 | border-style: solid; 24 | border-width: 1px 0px 0px 0px; 25 | height: 1px; 26 | width: 100%; 27 | color: #000000; 28 | } 29 | 30 | p { 31 | margin-left: 5px; 32 | } 33 | 34 | td { 35 | font-family: Helvetica, Arial, sans-serif; 36 | font-size: 12px; 37 | } 38 | 39 | .title { 40 | color:#990000; 41 | font-size:24px; 42 | padding:2px 0px 2px 0px; 43 | margin:10px 0px 0px 5px; 44 | vertical-align: middle; 45 | } 46 | 47 | .sectiontitle { 48 | color:#990000; 49 | font-size:16px; 50 | font-weight: bold; 51 | width:100%; 52 | padding:2px 0px 2px 5px; 53 | margin: 15px 0px 0px 0px; 54 | } 55 | 56 | .headertitle { 57 | font-weight:bold; 58 | padding: 3px 5px 3px 5px; 59 | } 60 | 61 | .helptopic { 62 | font-weight:bold; 63 | color:#990000; 64 | } 65 | 66 | .helptext { 67 | margin-left: 5px; 68 | font-family: monospace; 69 | white-space: pre; 70 | font-size: 13px; 71 | } 72 | 73 | .subheader { 74 | background-color: #E7EBF7; 75 | width: 100%; 76 | } 77 | 78 | .subheader-left { 79 | padding: 3px 5px 3px 5px; 80 | } 81 | 82 | .subheader-right { 83 | text-align: right; 84 | padding: 3px 5px 3px 5px; 85 | } 86 | 87 | .footerlinktitle { 88 | margin: 15px 0px 0px 5px; 89 | color:#990000; 90 | font-size: 16px; 91 | } 92 | 93 | .footerlink { 94 | padding: 3px 5px 3px 15px; 95 | } 96 | 97 | .topiclinks { 98 | margin: 5px 0px 0px 5px; 99 | } 100 | 101 | a.topiclink { 102 | padding-right: 10px; 103 | } 104 | 105 | .class-details { 106 | border-width: 0px 0px 0px 0px; 107 | margin: 0px 0px 0px 5px; 108 | } 109 | 110 | .class-detail-label { 111 | font-weight: bold; 112 | padding: 0px 10px 0px 0px; 113 | spacing: 0px 0px 0px 0px; 114 | } 115 | 116 | .summary-list .m-help { 117 | white-space: nowrap; 118 | } 119 | 120 | .summary-list { 121 | margin: 0px 15px 0px 15px; 122 | } 123 | 124 | .summary-list .summary-item .name { 125 | border-width: 0px 0px 1px 0px; 126 | border-style: solid; 127 | border-color:#E7EBF7; 128 | padding: 2px 15px 2px 5px; 129 | } 130 | 131 | .summary-list .summary-item .m-help { 132 | border-width: 0px 0px 1px 0px; 133 | border-style: solid; 134 | border-color:#E7EBF7; 135 | padding: 2px 5px 2px 5px; 136 | width: 95%; 137 | white-space: normal; 138 | } 139 | 140 | .summary-list .summary-item .attributes { 141 | border-width: 0px 0px 1px 0px; 142 | border-style: solid; 143 | border-color:#E7EBF7; 144 | padding: 2px 15px 2px 5px; 145 | white-space: nowrap; 146 | } 147 | -------------------------------------------------------------------------------- /mcode/html/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | MATLAB File Help: MYFUNC 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
MATLAB File Help: MYFUNCView code for MYFUNCWFDB Contents
17 |
MYFUNC
18 |

19 | 
20 | 
21 | 


--------------------------------------------------------------------------------
/mcode/html/template_bottom.html:
--------------------------------------------------------------------------------
1 | 
2 | 3 | 4 | -------------------------------------------------------------------------------- /mcode/info.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 2013a 5 | WFDB Toolbox 6 | toolbox 7 | 8 | html 9 | $toolbox/matlab/icons/bookicon.gif 10 | -------------------------------------------------------------------------------- /mcode/lomb.m: -------------------------------------------------------------------------------- 1 | function varargout=lomb(varargin) 2 | % 3 | % [Pxx,F]=lomb(x,dcOffset,smooth) 4 | % 5 | % Wrapper to WFDB LOMB: 6 | % http://www.physionet.org/physiotools/wag/lomb-1.htm 7 | % 8 | % Transforms a real-valued time series 'x' into a power spectrum 'X', using a 9 | % technique known as the Lomb periodogram. The input is a Nx2 matrix containing 10 | % a sampled time series, presented as two columns of numbers (the sample times 11 | % in the first column and the sample values in the second). The intervals between 12 | % consecutive samples need not be uniform. 13 | % 14 | %Input Parameters: 15 | % x 16 | % Nx2 vector of doubles. First column is sample time index (in 17 | % seconds), and second column is the sample value of the signal at 18 | % that time. 19 | % 20 | % dcOffset (Optional) 21 | % Booelan. If present add constant to input samples ( x(:,2) ), such that the mean 22 | % values of the time series is zero (default=1). 23 | % 24 | % smooth (Optional) 25 | % Boolean String specifying the if the output should be smoothed (default =1). 26 | % 27 | % 28 | %Output Parameters: 29 | % 30 | %Pxx 31 | % Mx1 Double. Estimated power spectrum. 32 | % 33 | %F 34 | % Mx1 Double. Frequency of the estimated power spectrum (Hz). 35 | % 36 | % 37 | % CITING CREDIT: To credit this function, please cite the following paper at your work: 38 | % 39 | %Moody, G.B. 40 | % Spectral analysis of heart rate without resampling. Computers in Cardiology 1993, pp. 715-718 (IEEE Computer Society Press, 1993). http://www.physionet.org/physiotools/lomb/lomb.html . 41 | % 42 | % 43 | %Additional References: 44 | %Lomb, N.R. 45 | % Least-squares frequency analysis of unequally spaced data. Astrophysics and Space Science 39:447-462 (1976). 46 | %Press, W.H, and Rybicki, G.B. 47 | % Fast algorithm for spectral analysis of unevenly sampled data. Astrophysical J. 338:277-280 (1989). 48 | %Press, W.H. Teukolsky, S.A., Vetterling, W.T., and Flannery, B.P. 49 | % Numerical Recipes in C: the Art of Scientific Computing, pp. 575-584 (Cambridge Univ. Press, 1992). 50 | %Moody, G.B. 51 | % Spectral analysis of heart rate without resampling. Computers in Cardiology 1993, pp. 715-718 (IEEE Computer Society Press, 1993). http://www.physionet.org/physiotools/lomb/lomb.html . 52 | % 53 | % 54 | % 55 | % MATLAB wrapper written by Ikaro Silva, 2013 56 | % Last Modified: - 57 | % Version 1.0 58 | % Since 0.9.0 59 | % 60 | % 61 | % %Example: Heart Rate Spectral Analysis: 62 | % [signal,Fs,tm]=rdsamp('mitdb/100',1); 63 | % [ann]=rdann('mitdb/100','atr'); 64 | % [Pxx,F]=lomb([tm(ann) signal(ann)]); 65 | % plot(F,Pxx);grid on;hold on 66 | % 67 | % See also RDANN, TACH, SQRS, WQRS 68 | 69 | %endOfHelp 70 | 71 | javaWfdbExec=getWfdbClass('lomb'); 72 | 73 | %Set default pararamter values 74 | %[Pxx,F] 75 | inputs={'x','dcOffset','smooth'}; 76 | dcOffset=1; 77 | smooth=1; 78 | for n=1:nargin 79 | if(~isempty(varargin{n})) 80 | eval([inputs{n} '=varargin{n};']); 81 | end 82 | end 83 | 84 | wfdb_argument={'-P'}; 85 | 86 | if(dcOffset) 87 | wfdb_argument{end+1}='-z'; 88 | end 89 | if(smooth) 90 | wfdb_argument{end+1}='-s'; 91 | end 92 | 93 | wfdb_argument{end+1}='-'; 94 | del=repmat([' '],size(x(:,1))); 95 | data=[num2str(x(:,1)) del num2str(x(:,2))]; 96 | javaWfdbExec.setArguments(wfdb_argument); 97 | pxx=char(javaWfdbExec.execWithStandardInput(cellstr(data))); 98 | pxx=sscanf(pxx(2:end-1), '%f %f,'); 99 | 100 | varargout{1}=pxx(2:2:end); 101 | varargout{2}=pxx(1:2:end); 102 | 103 | -------------------------------------------------------------------------------- /mcode/mrgann.m: -------------------------------------------------------------------------------- 1 | function mrgann(varargin) 2 | % 3 | % mrgann(recName,annName1,annName2,outAnn,verbose) 4 | % 5 | % Wrapper to WFDB MRGANN: 6 | % http://www.physionet.org/physiotools/wag/mrgann-1.htm 7 | % 8 | % 9 | % Reads a pair of annotation files (annName1, annName2) for the specified 10 | % record (recName), and writes a third annotation file (specified by outAnn) 11 | % for the same record. Typical applications of MRGANN include combining annotation 12 | % files that apply to different signals within a multi-signal record, and replacing 13 | % a segment of an annotation file with annotations from another file. MRGANN cannot 14 | % concatenate annotation files from different records (e.g., segments of a multi-segment record). 15 | % 16 | % 17 | %Required Parameters: 18 | % 19 | % recName 20 | % String specifying the name of the record in the WFDB path or 21 | % in the current directory. 22 | % 23 | % annName1 24 | % String specifying the name of the first WFDB annotation file to be 25 | % merged. 26 | % 27 | % annName2 28 | % String specifying the name of the second WFDB annotation file to be 29 | % merged. 30 | % 31 | % outAnn 32 | % String specifying the name of the output WFDB annotation file 33 | % containing the merged annotations. 34 | % 35 | % 36 | % Optional Parameters are: 37 | % 38 | % verbose 39 | % Boolean. If true warns about simultaneous annoations with matching 40 | % chan fields (default = true). 41 | % 42 | % 43 | % MATLAB wrapper Written by Ikaro Silva, 2013 44 | % Last Modified: 6/13/2013 45 | % Version 1.0 46 | % 47 | % Since 0.9.0 48 | % 49 | % See also BXB, RDANN, WRANN 50 | % 51 | % 52 | % %Example 1- Read a signal and annotation from PhysioNet's Remote server: 53 | % %and merge with calculated WRQS annotation 54 | % wqrs('mitdb/100'); 55 | % mrgann('mitdb/100','atr','wqrs','testAnn') 56 | % 57 | % 58 | % 59 | % See also wfdbtime, wrann 60 | 61 | %endOfHelp 62 | 63 | javaWfdbExec=getWfdbClass('mrgann'); 64 | 65 | %Set default pararamter values 66 | % [ann,type,subtype,chan,num]=rdann(recordName,annotator,C,N,N0) 67 | inputs={'recName','annName1','annName2','outAnn','verbose'}; 68 | verbose=1; 69 | for n=1:nargin 70 | if(~isempty(varargin{n})) 71 | eval([inputs{n} '=varargin{n};']); 72 | end 73 | end 74 | 75 | wfdb_argument={'-r',recName,'-i',annName1,annName2,'-o',outAnn}; 76 | 77 | if(verbose) 78 | wfdb_argument{end+1}='-v'; 79 | end 80 | javaWfdbExec.execToStringList(wfdb_argument); 81 | -------------------------------------------------------------------------------- /mcode/msentropy.m: -------------------------------------------------------------------------------- 1 | function varargout=msentropy(varargin) 2 | % 3 | % [y,scale,info]=msentropy(x,dn,dm,dr,N,N0,minM,maxM,maxScale,minR,maxR) 4 | % 5 | % Wrapper to the Multiscale Entropy C code written by Madalena Costa (mcosta@fas.harvard.edu): 6 | % http://physionet.org/physiotools/mse/mse-1.htm 7 | % 8 | % Calculates the multi scale entropy of a signal 'x'. A tutorial on Mulsticale 9 | % entropy is available at: 10 | % http://www.physionet.org/physiotools/mse/tutorial/ 11 | % 12 | % 13 | % Please cite these publications when referencing this material: 14 | % Costa M., Goldberger A.L., Peng C.-K. Multiscale entropy analysis of biological signals. Phys Rev E 2005;71:021906. 15 | % Costa M., Goldberger A.L., Peng C.-K. Multiscale entropy analysis of physiologic time series. Phys Rev Lett 2002; 89:062102. 16 | % 17 | % Also include the standard citation for PhysioNet: 18 | % Goldberger AL, Amaral LAN, Glass L, Hausdorff JM, Ivanov PCh, Mark RG, 19 | % Mietus JE, Moody GB, Peng C-K, Stanley HE. PhysioBank, PhysioToolkit, and PhysioNet: components of a new research resource for complex physiologic signals. Circulation 101(23):e215-e220 [Circulation Electronic Pages; http://circ.ahajournals.org/cgi/content/full/101/23/e215]; 2000 (June 13) 20 | % 21 | % Readers of may also wish to read: 22 | % Costa M, Peng C-K, Goldberger AL, Hausdorff JM. Multiscale entropy analysis of human gait dynamics. Physica A 2003;330:53-60. 23 | % 24 | % Required Parameters: 25 | % 26 | % x 27 | % Nx1 vector of doubles in which to caculate the multiscale entropy. 28 | % 29 | % Optional Parameters are: 30 | % dn 31 | % 1x1 double. Sets the scale increment to dn (1-40; default: 1). 32 | % dm 33 | % 1x1 double. Sets the m increment to dm (1-10; default: 1). 34 | % dr 35 | % 1x1 double. Sets the scale increment to dr (>0; default: 0.05). 36 | % N 37 | % 1x1 integer. Stop the analysis with row N. 38 | % By default, analysis ends at row 39999, or at the end of the data set if there are fewer rows. 39 | % N0 40 | % 1x1 integer. Begin the analysis with row N0. 41 | % By default, analysis begins with row 1. 42 | % minM 43 | % 1x1 integer betwee 1-10. Set the minimum pattern length for SampEn to minN (1-10; default: 2). 44 | % maxM 45 | % 1x1 integer betwee 1-10. Set the maximum m to maxM (1-10; default: 2). 46 | % maxScale 47 | % 1x1 integer betwee 1-40. Set the maximum scale for coarse-graining to maxScale (1-40; default: 20). 48 | % minR 49 | % 1x1 double >0. Set the minimum similarity criterion for SampEn to minR (>0; default: 0.15). 50 | % maxR 51 | % 1x1 double > 0. Set the maximum m to maxR (>0; default: 0.15). 52 | % 53 | % 54 | % Outputs: 55 | % y 56 | % A 1xM vector of doubles corresponding to estimated sample entropies at each scale. 57 | % scale 58 | % A 1xM vector of integers specifying the scales in which 'y' was 59 | % estimated. 60 | % 61 | % info 62 | % An optional 3x1 cell array of strings providing loggin and verbose information from 63 | % the calculation. 64 | % 65 | % Wrapper written by Ikaro Silva, 2013 66 | % Last Modified: March 20, 2014 67 | % Version 0.0.1 68 | % 69 | % Since 0.9.5 70 | % 71 | % %Example 72 | % N=30000; 73 | % noise=randn(N,1); 74 | % maxScale=10; 75 | %[entropyNoise,scale1]=msentropy(noise,[],[],[],[],[],[],[],maxScale); 76 | % %Simulate determistic system with noise-like 2nd order statistics 77 | % nlinear=zeros(N,1);nlinear(1)=0.2;u=4; 78 | % for n=2:N;nlinear(n)=u*nlinear(n-1)*(1-nlinear(n-1));end 79 | %[entropyDeterm,scale2]=msentropy(nlinear,[],[],[],[],[],[],[],maxScale); 80 | %subplot(2,1,1); 81 | %plot(noise(1:1000));hold on;grid on;plot(nlinear(1:1000),'r');legend('Stochastic','Deterministic') 82 | %subplot(2,1,2); 83 | %plot(scale1,entropyNoise);hold on;grid on;plot(scale2,entropyDeterm,'r');legend('Stochastic','Deterministic') 84 | % 85 | % 86 | % See also SURROGATE, DFA, WFDBDESC, PHYSIONETDB, RDANN, ANN2RR, MAPRECORD 87 | 88 | %endOfHelp 89 | 90 | [javaWfdbExec,config]=getWfdbClass('mse'); 91 | 92 | %Set default pararamter values 93 | inputs={'x','dn','dm','dr','N','N0','minM','maxM','maxScale','minR','maxR'}; 94 | outputs={'y','scale','info'}; 95 | dn=[]; 96 | dm=[]; 97 | dr=[]; 98 | N=[]; 99 | N0=[]; 100 | minM=[]; 101 | maxM=[]; 102 | maxScale=[]; 103 | minR=[]; 104 | maxR=[]; 105 | wfdb_argument={}; 106 | info=[]; 107 | scale=[]; 108 | y=[]; 109 | x=[]; 110 | for n=1:nargin 111 | if(~isempty(varargin{n})) 112 | eval([inputs{n} '=varargin{n};']); 113 | end 114 | end 115 | if(~isempty(dn)) 116 | wfdb_argument{end+1}='-a'; 117 | wfdb_argument{end+1}=[num2str(dn)]; 118 | end 119 | if(~isempty(dm)) 120 | wfdb_argument{end+1}='-b'; 121 | wfdb_argument{end+1}=[num2str(dm)]; 122 | end 123 | if(~isempty(dr)) 124 | wfdb_argument{end+1}='-c'; 125 | wfdb_argument{end+1}=[num2str(dr)]; 126 | end 127 | if(~isempty(N0)) 128 | wfdb_argument{end+1}='-i'; 129 | wfdb_argument{end+1}=[num2str(N0-1)]; 130 | end 131 | if(~isempty(N)) 132 | wfdb_argument{end+1}='-I'; 133 | wfdb_argument{end+1}=[num2str(N-1)]; 134 | end 135 | if(~isempty(minM)) 136 | wfdb_argument{end+1}='-m'; 137 | wfdb_argument{end+1}=[num2str(minM)]; 138 | end 139 | if(~isempty(maxM)) 140 | wfdb_argument{end+1}='-M'; 141 | wfdb_argument{end+1}=[num2str(maxM)]; 142 | end 143 | if(~isempty(maxScale)) 144 | wfdb_argument{end+1}='-n'; 145 | wfdb_argument{end+1}=[num2str(maxScale)]; 146 | end 147 | if(~isempty(minR)) 148 | wfdb_argument{end+1}='-r'; 149 | wfdb_argument{end+1}=[num2str(minR)]; 150 | end 151 | if(~isempty(maxR)) 152 | wfdb_argument{end+1}='-R'; 153 | wfdb_argument{end+1}=[num2str(maxR)]; 154 | end 155 | javaWfdbExec.setArguments(wfdb_argument); 156 | 157 | if(config.inOctave) 158 | x=cellstr(num2str(x)); 159 | x=javaWfdbExec.execWithStandardInput(x); 160 | Nx=x.size; 161 | out=cell(Nx,1); 162 | for n=1:Nx 163 | out{n}=x.get(n-1); 164 | end 165 | else 166 | out=cell(javaWfdbExec.execWithStandardInput(x).toArray); 167 | end 168 | M=length(out); 169 | if(M<4) 170 | error(['Error calculating MSE:' out{:}]); 171 | end 172 | info=out(1:3); 173 | out(1:4)=[]; 174 | M=M-4; 175 | scale=zeros(M,1)+NaN; 176 | y=zeros(M,1)+NaN; 177 | for m=1:M 178 | str=out{m}; 179 | sep=regexp(str,'\s'); 180 | scale(m)=str2num(str(1:sep)); 181 | y(m)=str2num(str(sep(1):sep(2))); 182 | end 183 | 184 | for n=1:nargout 185 | eval(['varargout{n}=' outputs{n} ';']); 186 | end 187 | 188 | -------------------------------------------------------------------------------- /mcode/mxm.m: -------------------------------------------------------------------------------- 1 | function varargout=mxm(varargin) 2 | % 3 | % mxm(recName,refAnn,testAnn,reportFile,beginTime,appendReport,mType,stopTime,normalize) 4 | % 5 | % Wrapper to WFDB MXM: 6 | % http://www.physionet.org/physiotools/wag/mxm-1.htm 7 | % 8 | % ANSI/AAMI-standard measurement-by-measurement annotation comparator. 9 | % 10 | % 11 | %Input Parameters: 12 | % recName 13 | % String specifying the WFDB record file. 14 | % 15 | % refAnn 16 | % String specifying the reference WFDB annotation file. 17 | % 18 | % testAnn 19 | % String specifying the test WFDB annotation file. 20 | % 21 | % reportFile 22 | % String representing the file at which the report will be 23 | % written to. 24 | % 25 | % 26 | % beginTime (Optional) 27 | % String specifying the begin time in WFDB format. The 28 | % WFDB time format is described at 29 | % http://www.physionet.org/physiotools/wag/intro.htm#time. 30 | % Default starts comparison after 5 minutes. 31 | % 32 | % appendReport (Optional) 33 | % Boolean (default false). Append a line-format report to the 34 | % reportFile. 35 | % 36 | % mType (Optional) 37 | % String defining which measurement type to compare. 38 | % 39 | % stopTime (Optional) 40 | % String specifying the stop time in WFDB format (default is end of 41 | % record). 42 | % 43 | % normalize (Optional) 44 | % Boolean (default true). If false, calculates the unnormalized RMS 45 | % measurement error. 46 | % 47 | % 48 | %TODO: INCLUDE Example 49 | % 50 | % Written by Ikaro Silva, 2013 51 | % Last Modified: - 52 | % Version 1.0 53 | % Since 0.9.0 54 | % 55 | % See also WRANN, RDANN, BXB 56 | 57 | 58 | %endOfHelp 59 | 60 | javaWfdbExec=getWfdbClass('mxm'); 61 | 62 | %Set default pararamter values 63 | inputs={'recName','refAnn','testAnn','reportFile',... 64 | 'beginTime','appendReport','mType','stopTime','normalize'}; 65 | recName=[]; 66 | refAnn=[]; 67 | testAnn=[]; 68 | reportFile=[]; 69 | beginTime=[]; 70 | appendReport=[]; 71 | mType=[]; 72 | stopTime=[]; 73 | normalize=[]; 74 | for n=1:nargin 75 | if(~isempty(varargin{n})) 76 | eval([inputs{n} '=varargin{n};']) 77 | end 78 | end 79 | 80 | wfdb_argument={'-r',recName,'-a',refAnn,testAnn,'-l',reportFile}; 81 | 82 | if(~isempty(beginTime)) 83 | wfdb_argument{end+1}='-f'; 84 | wfdb_argument{end+1}=beginTime; 85 | end 86 | if(~isempty(mType)) 87 | wfdb_argument{end+1}='-m'; 88 | wfdb_argument{end+1}=mType; 89 | end 90 | if(~isempty(appendReport)) 91 | wfdb_argument{end+1}='-s'; 92 | wfdb_argument{end+1}=reportFile; 93 | end 94 | if(~isempty(stopTime)) 95 | wfdb_argument{end+1}='-t'; 96 | wfdb_argument{end+1}=stopTime; 97 | end 98 | if(~isempty(normalize) && ~normalize) 99 | wfdb_argument{end+1}='-u'; 100 | end 101 | 102 | data=javaWfdbExec.execToStringList(wfdb_argument); 103 | 104 | 105 | -------------------------------------------------------------------------------- /mcode/nativelibs/custom/README.txt: -------------------------------------------------------------------------------- 1 | 2 | This folder is provided for those advanced users who want to use the WFDB APP Toolbox with their 3 | custom version of the WFDB native binaries. Several reason why a user would want to do that include: 4 | 5 | *Users who are in an unsupported architecture (such as 32 bit systems etc) 6 | 7 | *Users who want to test on an older version of the WFDB library 8 | 9 | *Users who wan to test on a new version of the WFDB library that has not yet been deployed with this toolbox 10 | 11 | 12 | Users should compile the WFDB binary and put them in their respective folder: 13 | 14 | bin 15 | lib 16 | lib64 17 | 18 | An example is provided in this folder that was build on Linux Debian Wheezy. You can use the Makefile in this directory 19 | as a starting point for compiling all the necessary targets on your architecture or version of WFDB. Once the code has been 20 | compiled. Please make sure that you set the flag: 21 | 22 | 'use_custom_nativlib=1' 23 | 24 | In the /mcode/wfdbloadlib.m function to true in order to load these native applications. 25 | 26 | NOTE: Use of these custom configurations are unsupported by the PhysioNet team. -------------------------------------------------------------------------------- /mcode/pbsearch.m: -------------------------------------------------------------------------------- 1 | function pbsearch 2 | % 3 | % pbsearch() 4 | % 5 | % 6 | % Launches PhsyioNet's record search tool from within 7 | % MATLAB's web browser. 8 | % 9 | % 10 | % Written by Ikaro Silva, 2014 11 | % Last Modified: October 8, 2014 12 | % Version 1.0 13 | % 14 | % Since 0.9.8 15 | % 16 | % %Example - Launch MATLAB webrowser at PhsyioNet's record search tool 17 | % pbsearch 18 | % 19 | % See also WFDBDESC, PHYSIONETDB 20 | 21 | %endOfHelp 22 | 23 | 24 | 25 | web('http://physionet.org/cgi-bin/pbs/pbsearch?subject=&comp_op=&sval=&name_num=&help_on=on&res_action=&sq_action=') -------------------------------------------------------------------------------- /mcode/physionetdb.m: -------------------------------------------------------------------------------- 1 | function varargout=physionetdb(varargin) 2 | % 3 | % db_list=physionetdb(db_name,DoBatchDownload,webBrowserFlag) 4 | % 5 | % 6 | % Lists all the available databases at PhysioNet 7 | % (http://physionet.org/physiobank/) or list all available records in a database. 8 | % Users can read the signals (waveforms) or annotations (labels) using the WFDB 9 | % App Toolbox's functions such as RDSAMP. Options are 10 | % 11 | % Optional Input Parameters: 12 | % db_name 13 | % String specifying the datbase to query for available records. 14 | % If left empty (default) a list of available database names is 15 | % returned. NOTE: Some databases (such as 'mimic2db') have a huge 16 | % number of records so that querying the records in the database 17 | % can take a long time. 18 | % 19 | % DoBatchDownload 20 | % If 'db_name' is present, setting this flag to true 21 | % (DoBatchDownload=1), will download all records of the database 22 | % db_name to a subdirectory in the current directory called 23 | % 'db_name'. Default is false. Note: requires that the user have 24 | % write permission to the current directory. 25 | % 26 | % NOTE: This function currently does not perform any checksum in order 27 | % to verify that the files were dwnloaded properly. 28 | % 29 | % webBrowserFlag 30 | % Boolean. If true, displays database information in MATLAB's 31 | % web browser (default = 0). 32 | % 33 | % Output Parameters 34 | % db_list -(Optional) Cell array list of elements. If an output 35 | % is not provided, results are displayed to the screen. 36 | % The returned valued are either a list of database names to query 37 | % (if db_name is empty), or a list of available records that can 38 | % be read via RDSAMP (if db_name is a name of a valid database as 39 | % given by the return list when db_name is empty). 40 | % 41 | % Author: Ikaro Silva, 2013 42 | % Since: 0.0.1 43 | % Last Modified: April 8, 2015 44 | % 45 | % 46 | % %Example 1 - List all available databases from PhysioNet into the screen 47 | % physionetdb 48 | % 49 | % %Example 2 - List all available databases from PhysioNet in web browser 50 | % physionetdb([],[],1) 51 | % 52 | % %Example 3- List all available records in the ucddb database. 53 | % db_list=physionetdb('ucddb') 54 | % 55 | % %Example 4- Download all records for database MITDB 56 | % physionetdb('mitdb',1); 57 | % 58 | % %Example 5- List all records for database MITDB on a web browser 59 | % physionetdb('mitdb',[],1); 60 | % 61 | 62 | %endOfHelp 63 | 64 | %Add classes to path 65 | [isloaded,config]=wfdbloadlib; 66 | 67 | %URL to PhysioBank database in PhysioNet 68 | PHYSIONET_URL=config.CACHE_SOURCE; 69 | inputs={'db_name','DoBatchDownload','webBrowser'}; 70 | db_name=[]; 71 | DoBatchDownload=0; 72 | webBrowser=0; 73 | for n=1:nargin 74 | if(~isempty(varargin{n})) 75 | eval([inputs{n} '=varargin{n};']); 76 | end 77 | end 78 | if(webBrowser && config.inOctave) 79 | error('Web browser option is not available in Octave.'); 80 | end 81 | 82 | if(isempty(db_name)) 83 | list=javaMethod('main','org.physionet.wfdb.physiobank.PhysioNetDB'); 84 | if(nargout>0) 85 | db_list={}; 86 | for i=0:double(list.size)-1 87 | db_list(end+1)={list.get(i).getDBInfo}; 88 | end 89 | varargout(1)={db_list}; 90 | else 91 | if(webBrowser) 92 | web([PHYSIONET_URL 'DBS']); 93 | else 94 | for i=0:double(list.size)-1 95 | fprintf(char(list.get(i).getDBInfo)); 96 | fprintf('\n'); 97 | end 98 | end 99 | end 100 | else 101 | if(DoBatchDownload) 102 | display(['Making directory: ' db_name ' to store record files']); 103 | mkdir(db_name); 104 | end 105 | rec_list={}; 106 | if(webBrowser) 107 | web([PHYSIONET_URL 'pbi/' db_name]); 108 | else 109 | rec_list=deblank(urlread([PHYSIONET_URL db_name '/RECORDS'])); 110 | rec_list=regexp(rec_list,'\s','split'); 111 | Nstr=length(rec_list); 112 | for i=1:Nstr 113 | if(DoBatchDownload) 114 | recName=rec_list{i}; 115 | display(['Downloading record (' num2str(i+1) ' / ' num2str(Nstr) ') : ' recName]); 116 | [success,files_saved]=wfdbdownload([db_name '/' recName]); 117 | end 118 | end 119 | end 120 | if(nargout>0) 121 | varargout(1)={rec_list}; 122 | end 123 | end 124 | -------------------------------------------------------------------------------- /mcode/rdmat.m: -------------------------------------------------------------------------------- 1 | function varargout=rdmat(varargin) 2 | % 3 | % [tm,signal,Fs,siginfo]=rdmat(recordName) 4 | % 5 | % Import a signal in physical units from a *.mat file generated by WFDB2MAT. 6 | % Required Parameters: 7 | % 8 | % recorName 9 | % String specifying the name of the *.mat file. 10 | % 11 | % Outputs are: 12 | % 13 | % tm 14 | % A Nx1 array of doubles specifying the time in seconds. 15 | % signal 16 | % A NxM matrix of doubles contain the signals in physical units. 17 | % Fs 18 | % A 1x1 integer specifying the sampling frequency in Hz for the entire record. 19 | %siginfo 20 | % A LxN cell array specifying the signal siginfo. Currently it is a 21 | % structure with the following fields: 22 | % 23 | % siginfo.Units 24 | % siginfo.Baseline 25 | % siginfo.Gain 26 | % siginfo.Description 27 | % 28 | % NOTE: 29 | % You can use the WFDB2MAT command in order to convert the record data into a *.mat file, 30 | % which can then be loaded into MATLAB/Octave's workspace using the LOAD command. 31 | % This sequence of procedures is quicker (by several orders of magnitude) than calling RDSAMP. 32 | % The LOAD command will load the signal data in raw units, use RDMAT to load the signal in physical units. 33 | % 34 | % KNOWN LIMITATIONS: 35 | % This function currently does support several of the features described 36 | % in the WFDB record format (such as multiresolution signals) : 37 | % http://www.physionet.org/physiotools/wag/header-5.htm 38 | % If you are not sure that the record (or database format) you are reading is 39 | % supported, you can do an integrity check by comparing the output with RDSAMP: 40 | % 41 | % [tm,signal,Fs,siginfo]=rdmat('200m'); 42 | % [tm2,signal2]=rdsamp('200m'); 43 | % if(sum(abs(signal-signal2)) !=0); 44 | % error('Record not compatible with RDMAT'); 45 | % end 46 | % 47 | % 48 | % Written by Ikaro Silva, 2014 49 | % Last Modified: November 26, 2014 50 | % Version 1.2 51 | % 52 | % Since 0.9.7 53 | % 54 | % %Example: 55 | % wfdb2mat('mitdb/200') 56 | %tic;[tm,signal,Fs,siginfo]=rdmat('200m');toc 57 | %tic;[signal2]=rdsamp('200m');toc 58 | % sum(abs(signal-signal2)) 59 | % 60 | % 61 | % See also RDSAMP, WFDB2MAT 62 | 63 | %endOfHelp 64 | 65 | %Set default pararameter values 66 | inputs={'recordName'}; 67 | defGain=200; %Default value for missing gains 68 | 69 | for n=1:nargin 70 | if(~isempty(varargin{n})) 71 | eval([inputs{n} '=varargin{n};']); 72 | end 73 | end 74 | 75 | outputs={'tm','val','Fs','siginfo'}; 76 | fid = fopen([recordName, '.hea'], 'rt'); 77 | if(fid==-1) 78 | error(['Could not open file: ' recordName '.hea !']); 79 | end 80 | 81 | %Following the documentation described in : 82 | %http://www.physionet.org/physiotools/wag/header-5.htm 83 | %to parse the header file 84 | 85 | %Skip any comment lines 86 | str=fgetl(fid); 87 | while(strcmp(str(1),'#')) 88 | str=fgetl(fid); 89 | end 90 | 91 | %Process Record Line Info 92 | info=textscan(str,'%s %d %f %d %s %s'); 93 | M=info{2}; %Number of signals present 94 | Fs=info{3}; 95 | 96 | %Process Signal Specification lines. Assumes no comments between lines. 97 | siginfo(M)=struct(); 98 | for m = 1:M 99 | str=fgetl(fid); 100 | info=textscan(str,'%s %s %s %d %d %f %d %d %s'); 101 | fmt=info{2}{:}; 102 | gain=info{3}{:}; 103 | 104 | %Get Signal Units if present 105 | ind=strfind(gain,'/'); 106 | if(~isempty(ind)) 107 | siginfo(m).Units=gain(ind+1:end); 108 | gain=gain(1:ind-1); 109 | end 110 | 111 | %Get Signal Baseline if present 112 | ind=strfind(gain,'('); 113 | if(~isempty(ind)) 114 | ind2=strfind(gain,')'); 115 | siginfo(m).Baseline=str2num(gain(ind+1:ind2-1)); 116 | gain=gain(1:ind-1); 117 | else 118 | %If Baseline is missing, set it equal to ADC Zero 119 | adc_zero=info{5}; 120 | if(~isempty(adc_zero)) 121 | siginfo(m).Baseline=double(adc_zero); 122 | else 123 | error('Could not obtain signal baseline'); 124 | end 125 | end 126 | 127 | %Get Signal Gain 128 | gain=str2num(gain); 129 | if(gain==0) 130 | %Set gain to default value in this case 131 | gain=defGain; 132 | end 133 | siginfo(m).Gain=double(gain); 134 | 135 | %Get Signal Descriptor 136 | siginfo(m).Description=info{9}{:}; 137 | 138 | % Store format for later 139 | siginfo(m).fmt=fmt(1:strfind(fmt,'+')-1); 140 | 141 | end 142 | fclose(fid); 143 | 144 | load([recordName '.mat']); 145 | 146 | for m = 1:M 147 | % Interpreting digital values of byte offset format 80 148 | if strcmp(siginfo(m).fmt, '80') 149 | val(m,:)=val(m,:)-128; 150 | wfdbNaN=-128; 151 | elseif strcmp(siginfo(m).fmt, '16') 152 | wfdbNaN=-32768; 153 | else 154 | wfdbNaN=-2147483648; 155 | end 156 | 157 | % Fill in NaNs before subtracting and dividing. 158 | val(m, val(m,:)==wfdbNaN)=nan; 159 | 160 | %Convert from digital units to physical units. 161 | % Mapping should be similar to that of rdsamp.c: 162 | % http://www.physionet.org/physiotools/wfdb/app/rdsamp.c 163 | val(m, :) = (val(m, :) - siginfo(m).Baseline ) / siginfo(m).Gain; 164 | end 165 | 166 | %Reshape to the Toolbox's standard format 167 | val=val'; 168 | 169 | %Generate time vector 170 | N=size(val,1); 171 | tm =linspace(0,(N-1)/Fs,N); 172 | 173 | 174 | for n=1:nargout 175 | eval(['varargout{n}=' outputs{n} ';']); 176 | end 177 | 178 | 179 | end 180 | -------------------------------------------------------------------------------- /mcode/snip.m: -------------------------------------------------------------------------------- 1 | function varargout=snip(varargin) 2 | % 3 | % err=snip(inputRecord,outputRecord,beginTime,stopTime,inputAnn,outFormat) 4 | % 5 | % Wrapper to WFDB SNIP: 6 | % http://www.physionet.org/physiotools/wag/snip-1.htm 7 | % 8 | % Copy an excerpt of a WFDB record 9 | % 10 | % 11 | %Input Parameters: 12 | % inputRecord 13 | % String specifying the input WFDB record file. 14 | % 15 | % outputRecord 16 | % String specifying the output WFDB record file name that will be generated. 17 | % 18 | % beginTime (Optional) 19 | % Integer specifying start time of the output WFDB record. Default is 20 | % the beginning of the input record. 21 | % 22 | % stopTime (Optional) 23 | % Integer specifying end time of the output WFDB record. Defaut is 24 | % end of input record. 25 | % 26 | % inputAnn (Optional) 27 | % String specifying the annotation files to convert along with the 28 | % given record. Defaults i none (empty). 29 | % 30 | % outFormat (Optional) 31 | % String specifying the output format (see http://www.physionet.org/physiotools/wag/header-5.htm). 32 | % Default is the same as input record. 33 | % 34 | %Output Parameters: 35 | % err (Optional) 36 | % String spefiying any error messages. If empty, conversion was 37 | % sucessfull. 38 | % 39 | % Written by Ikaro Silva, 2015 40 | % Last Modified: - 41 | % Version 1.0 42 | % Since 0.9.10 43 | % 44 | % 45 | % %Example- Generate a record from the first minute of mitdb/100 46 | % Fs=360; 47 | % err=snip('mitdb/100','100cut',[],Fs*60); 48 | % [sig2,Fs,tm1]=rdsamp('mitdb/100'); 49 | % [sig2,Fs,tm2]=rdsamp('100cut'); 50 | % plot(tm1,sig1(:,1));hold on;grid on 51 | % plot(tm2,sig2(:,1),'r') 52 | % 53 | % 54 | % See also RDSAMP, RDANN, WFDBDESC 55 | 56 | 57 | %endOfHelp 58 | 59 | javaWfdbExec=getWfdbClass('snip'); 60 | 61 | %Set default pararamter values 62 | 63 | inputs={'inputRecord','outputRecord','beginTime','stopTime','inputAnn','outFormat'}; 64 | inputRecord=[]; 65 | outputRecord=[]; 66 | beginTime=[]; 67 | stopTime=[]; 68 | inputAnn=[]; 69 | outFormat=[]; 70 | for n=1:nargin 71 | if(~isempty(varargin{n})) 72 | eval([inputs{n} '=varargin{n};']); 73 | end 74 | end 75 | 76 | wfdb_argument={'-i',inputRecord,'-n',outputRecord,'-m'}; 77 | 78 | if(~isempty(beginTime)) 79 | wfdb_argument{end+1}='-f'; 80 | wfdb_argument{end+1}=['s ' num2str(beginTime-1)]; 81 | end 82 | if(~isempty(stopTime)) 83 | wfdb_argument{end+1}='-t'; 84 | wfdb_argument{end+1}=['s ' num2str(stopTime)]; 85 | end 86 | if(~isempty(inputAnn)) 87 | wfdb_argument{end+1}='-a'; 88 | wfdb_argument{end+1}=inputAnn; 89 | end 90 | if(~isempty(outFormat)) 91 | wfdb_argument{end+1}='-O'; 92 | wfdb_argument{end+1}=outFormat; 93 | end 94 | 95 | err=javaWfdbExec.execToStringList(wfdb_argument); 96 | if(nargout>0) 97 | err=char(err.toString); 98 | if(strcmp(err,'[]')) 99 | err=[]; 100 | end 101 | varargout{1}=err; 102 | end 103 | -------------------------------------------------------------------------------- /mcode/sortann.m: -------------------------------------------------------------------------------- 1 | function varargout=sortann(varargin) 2 | % 3 | % sortann(recName,annName,beginTime,stopTime,outFile) 4 | % 5 | % Wrapper to WFDB SORTANN: 6 | % http://www.physionet.org/physiotools/wag/sortan-1.htm 7 | % 8 | % Rewrites the annotation file specified by recName and annName, arranging its contents in 9 | % canonical (time, num, and chan) order. The sorted (output) annotation file is always written 10 | % to the current directory. If the input annotation file is in the current directory, SORTANN 11 | % replaces it unless you specify a different output annotator name (using the outFile option). 12 | % If the input annotations are already in the correct order, no output is written unless you 13 | % have used the outFile option. 14 | % 15 | % 16 | %Input Parameters: 17 | % recName 18 | % String specifying the WFDB record file. 19 | % 20 | % annName 21 | % String specifying the reference WFDB annotation file. 22 | % 23 | % stopTime (Optional) 24 | % String specifying the start time in WFDB format (default is beginning of 25 | % record). 26 | % 27 | % stopTime (Optional) 28 | % String specifying the stop time in WFDB format (default is end of 29 | % record). 30 | % 31 | % outFile (Optional) 32 | % String specifying the output annotation file name. 33 | % 34 | % 35 | % Written by Ikaro Silva, 2013 36 | % Last Modified: - 37 | % Version 1.0 38 | % Since 0.9.0 39 | % 40 | % %Example (this will generate a /mitdb/100.sortedATR file at your directory): 41 | % 42 | % sortann('mitdb/100','atr',[],[],'sortedATR'); 43 | % ann=rdann('mitdb/100','sortedATR'); 44 | % 45 | % 46 | % See also RDANN 47 | 48 | %endOfHelp 49 | 50 | javaWfdbExec=getWfdbClass('sortann'); 51 | 52 | %Set default pararamter values 53 | inputs={'recName','annName','beginTime','stopTime','outFile'}; 54 | recName=[]; 55 | annName=[]; 56 | beginTime=[]; 57 | stopTime=[]; 58 | outFile=[]; 59 | for n=1:nargin 60 | if(~isempty(varargin{n})) 61 | eval([inputs{n} '=varargin{n};']); 62 | end 63 | end 64 | 65 | wfdb_argument={'-r',recName,'-a',annName}; 66 | 67 | if(~isempty(beginTime)) 68 | wfdb_argument{end+1}='-f'; 69 | wfdb_argument{end+1}=beginTime; 70 | end 71 | if(~isempty(stopTime)) 72 | wfdb_argument{end+1}='-t'; 73 | wfdb_argument{end+1}=stopTime; 74 | end 75 | if(~isempty(outFile)) 76 | wfdb_argument{end+1}='-o'; 77 | wfdb_argument{end+1}=outFile; 78 | end 79 | 80 | javaWfdbExec.execToStringList(wfdb_argument); 81 | -------------------------------------------------------------------------------- /mcode/sqrs.m: -------------------------------------------------------------------------------- 1 | function varargout=sqrs(varargin) 2 | % 3 | % sqrs(recordName,N,N0,signal,threshold) 4 | % 5 | % Wrapper to WFDB SQRS: 6 | % http://www.physionet.org/physiotools/wag/sqrs-1.htm 7 | % 8 | % Creates a SQRS annotation file at the current MATLAB directory. 9 | % The annotation file will have the same name as the recorName file, 10 | % but followed with the *.qrs suffix. Use RDANN to read the annoations 11 | % into MATLAB's workspace in order to read the sample QRS locations. 12 | % 13 | % If recordName is the path to a record at PhysioNet's database, than 14 | % the annation files will be stored in a subdirectory with the same relative 15 | % path as recordName and under the current directory. 16 | % 17 | % NOTE: In order to read the generated annotation file using RDANN, it is 18 | % necessary to have the WFDB record (*.hea and *.dat) files in the same 19 | % directory as the annotation file. 20 | % 21 | % Required Parameters: 22 | % 23 | % recorName 24 | % String specifying the name of the record in the WFDB path or 25 | % in the current directory. 26 | % 27 | % 28 | % Optional Parameters are: 29 | % 30 | % N 31 | % A 1x1 integer specifying the sample number at which to stop reading the 32 | % record file (default read all = N). 33 | % N0 34 | % A 1x1 integer specifying the sample number at which to start reading the 35 | % annotion file (default 1 = begining of the record). 36 | % 37 | % signal 38 | % A 1x1 integer. Specify the singal to obtain the annotation (default 39 | % = 1, first signal). 40 | % 41 | % threshold 42 | % A 1x1 integer. Specify the detection threshold (default = 500). 43 | % Use higher values to reduce false detections, or lower values to 44 | % reduce the number of missed beats. 45 | % 46 | % 47 | % Source code by George B. Moody. The source code is a fairly literal translation with minor 48 | % corrections of the Pascal original by WAH Engelse and Cees Zeelenberg. 49 | % 50 | % MATLAB wrapper written by Ikaro Silva, 2013 51 | % Last Modified: - 52 | % Version 1.0 53 | % 54 | % Since 0.0.1 55 | % 56 | % %Example 57 | %sqrs('challenge/2013/set-a/a01',[],1000); 58 | 59 | %endOfHelp 60 | 61 | javaWfdbExec=getWfdbClass('sqrs'); 62 | 63 | %Set default pararamter values 64 | inputs={'recordName','annotator','N','N0','signal','threshold'}; 65 | N=[]; 66 | N0=1; 67 | signal=[]; %use application default 68 | threshold=[];%use application default 69 | for n=1:nargin 70 | if(~isempty(varargin{n})) 71 | eval([inputs{n} '=varargin{n};']); 72 | end 73 | end 74 | 75 | N0=num2str(N0-1); %-1 is necessary because WFDB is 0 based indexed. 76 | wfdb_argument={'-r',recordName,'-f',['s' N0]}; 77 | 78 | if(~isempty(N)) 79 | wfdb_argument{end+1}='-t'; 80 | %-1 is necessary because WFDB is 0 based indexed. 81 | wfdb_argument{end+1}=['s' num2str(N-1)]; 82 | end 83 | if(~isempty(signal)) 84 | wfdb_argument{end+1}='-s'; 85 | %-1 is necessary because WFDB is 0 based indexed. 86 | wfdb_argument{end+1}=num2str(signal-1); 87 | end 88 | if(~isempty(threshold)) 89 | wfdb_argument{end+1}='-m'; 90 | %-1 is necessary because WFDB is 0 based indexed. 91 | wfdb_argument{end+1}=num2str(threshold-1); 92 | end 93 | 94 | javaWfdbExec.execToStringList(wfdb_argument); 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /mcode/sumann.m: -------------------------------------------------------------------------------- 1 | function varargout=sumann(varargin) 2 | % 3 | % report=sumann(recName,annName,stopTime,qrsAnnotationsOnly) 4 | % 5 | % Wrapper to WFDB SUMANN: 6 | % http://www.physionet.org/physiotools/wag/sumann-1.htm 7 | % 8 | % Reads a WFDB annotation file and summarize its contents. 9 | % 10 | % Ouput Parameters: 11 | % 12 | % report 13 | % String with the contaning summary of the contents, including the 14 | % number of annotations of each type as well the duration and number of 15 | % episodes of each rhythm and signal quality. 16 | % 17 | %Input Parameters: 18 | % recName 19 | % String specifying the WFDB record file. 20 | % 21 | % annName 22 | % String specifying the reference WFDB annotation file. 23 | % 24 | % stopTime (Optional) 25 | % String specifying the stop time in WFDB format (default is end of 26 | % record). 27 | % 28 | % qrsAnnotationsOnly (Optional) 29 | % 1x1 Boolean. If true, summarize QRS annotation only (default = 0). 30 | % 31 | % 32 | % Written by Ikaro Silva, 2013 33 | % Last Modified: - 34 | % Version 1.0 35 | % Since 0.9.0 36 | % 37 | % %Example (this will generate a /mitdb/100.qrs file at your directory): 38 | % 39 | % report=sumann('mitdb/100','atr'); 40 | % 41 | % 42 | % 43 | % See also RDANN, MXM, WFDBTIME, BXB 44 | 45 | %endOfHelp 46 | 47 | javaWfdbExec=getWfdbClass('sumann'); 48 | 49 | %Set default pararamter values 50 | inputs={'recName','annName','stopTime','qrsAnnotationsOnly'}; 51 | recName=[]; 52 | annName=[]; 53 | stopTime=[]; 54 | qrsAnnotationsOnly=0; 55 | for n=1:nargin 56 | if(~isempty(varargin{n})) 57 | eval([inputs{n} '=varargin{n};']); 58 | end 59 | end 60 | 61 | wfdb_argument={'-r',recName,'-a',annName}; 62 | 63 | if(~isempty(stopTime)) 64 | wfdb_argument{end+1}='-t'; 65 | wfdb_argument{end+1}=stopTime; 66 | end 67 | if(qrsAnnotationsOnly) 68 | wfdb_argument{end+1}='-q'; 69 | end 70 | 71 | report=javaWfdbExec.execToStringList(wfdb_argument); 72 | if(nargout>0) 73 | varargout{1}=report; 74 | end 75 | -------------------------------------------------------------------------------- /mcode/surrogate.m: -------------------------------------------------------------------------------- 1 | function Y=surrogate(x,M) 2 | % 3 | % Y=surrogate(x,M) 4 | % 5 | % Generates M amplitude adjusted phase shuffled surrogate time series from x. 6 | % Useufel for testing the underlying assumption that the null hypothesis consists 7 | % of linear dynamics with possibly non-linear, monotonically increasing, 8 | % measurement function. 9 | % 10 | % Required Input Parameters: 11 | % 12 | % x 13 | % Nx1 vector of doubles 14 | % 15 | % M 16 | % 1x1 scalar specifying the number of surrogate time series to 17 | % generate. 18 | % 19 | % Required Output Parameters: 20 | % 21 | % Y 22 | % NxM vector of doubles 23 | % 24 | % 25 | % 26 | % References: 27 | % 28 | %[1] Kaplan, Daniel, and Leon Glass. Understanding nonlinear dynamics. Vol. 19. Springer, 1995. 29 | % 30 | % 31 | % Written by Ikaro Silva, 2014 32 | % Last Modified: November 20, 2014 33 | % Version 1.0 34 | % Since 0.9.8 35 | % 36 | % 37 | % 38 | % 39 | % See also MSENTROPY, SURROGATE 40 | 41 | %endOfHelp 42 | 43 | % 1. Amp transform original data to Gaussian distribution 44 | % 2. Phase randomize #1 45 | % 3. Amp transform #2 to original 46 | % Auto-correlation function should be similar but not exact! 47 | 48 | x=x(:); 49 | N=length(x); 50 | Y=zeros(N,M); 51 | 52 | for m=1:M 53 | 54 | %Step 1 55 | y=randn(N,1); 56 | y=amplitudeTransform(x,y,N); 57 | 58 | %Step 2 59 | y=phaseShuffle(y,N); 60 | 61 | %Step 3 62 | y=amplitudeTransform(y,x,N); 63 | Y(:,m)=y; 64 | end 65 | 66 | 67 | %%% Helper functions 68 | 69 | function target=amplitudeTransform(x,target,N) 70 | 71 | %Steps: 72 | %1. Sort the source by increasing amp 73 | %2. Sort target as #1 74 | %3. Swap source amp by target amp 75 | %4. Sort #3 by increasing time index of #1 76 | X=[[1:N]' x]; 77 | X=sortrows(X,2); 78 | target=[X(:,1) sort(target)]; 79 | target=sortrows(target,1); 80 | target=target(:,2); 81 | 82 | 83 | 84 | function y=phaseShuffle(x,N) 85 | 86 | %%Shuffle spectrum 87 | X=fft(x); 88 | Y=X; 89 | mid=floor(N/2)+ mod(N,2); 90 | phi=2*pi*rand(mid-1,1); %Generate random phase 91 | Y(2:mid)=abs(X(2:mid)).*cos(phi) + j*abs(X(2:mid)).*sin(phi); 92 | if(~mod(N,2)) 93 | %Even series has Nyquist in the middle+1 because of DC 94 | Y(mid+2:end)=conj(flipud(Y(2:mid))); 95 | Y(mid+1)=X(mid+1); 96 | else 97 | %Odd series is fully symetric except for DC 98 | Y(mid+1:end)=conj(flipud(Y(2:mid))); 99 | end 100 | 101 | y=real(ifft(Y)); 102 | -------------------------------------------------------------------------------- /mcode/tach.m: -------------------------------------------------------------------------------- 1 | function varargout=tach(varargin) 2 | % 3 | % [hr]=tach(recordName,annotator,N,N0,ouputSize) 4 | % 5 | % Wrapper to WFDB TACH: 6 | % http://www.physionet.org/physiotools/wag/tach-1.htm 7 | % 8 | % Reads a WFDB record and Annotation file to return: 9 | % 10 | % 11 | % hr 12 | % Nx1 vector of doubles representing a uniformly sampled and 13 | % smoothed instantaneous heart rate signal. The output are samples 14 | % of the instantaneous heart rate signal in units of beats per minute. 15 | % 16 | % Required Parameters: 17 | % 18 | % recorName 19 | % String specifying the name of the record in the WFDB path or 20 | % in the current directory. 21 | % 22 | % annotator - 23 | % String specifying the name of the annotation file in the WFDB path or 24 | % in the current directory. 25 | % 26 | % Optional Parameters are: 27 | % 28 | % N 29 | % A 1x1 integer specifying the sample number at which to stop reading the 30 | % annotation file (default read all = N). 31 | % N0 32 | % A 1x1 integer specifying the sample number at which to start reading the 33 | % annotation file (default 1 = begining of the record). 34 | % 35 | % outputSize 36 | % 37 | % A 1x1 integer specifying the number of output samples (ie estimated 38 | % heart rate intervals) such that the output 'hr' is a vector of 39 | % size (outputSize-1) x 1. 40 | % 41 | % 42 | % Written by Ikaro Silva, 2013 43 | % Last Modified: January 24, 2014 44 | % Version 1.1 45 | % 46 | % Since 0.0.1 47 | % 48 | % %Example 1- Read a signal and annotaion from PhysioNet's Remote server: 49 | %[hr]=tach('challenge/2013/set-a/a01','fqrs'); 50 | %plot(hr);grid on;hold on 51 | 52 | %endOfHelp 53 | 54 | [javaWfdbExec,config]=getWfdbClass('tach'); 55 | 56 | %Set default pararamter values 57 | inputs={'recordName','annotator','N','N0','ouputSize'}; 58 | outputs={'data(:,1)'}; 59 | N=[]; 60 | N0=1; 61 | ouputSize=[]; 62 | for n=1:nargin 63 | if(~isempty(varargin{n})) 64 | eval([inputs{n} '=varargin{n};']); 65 | end 66 | end 67 | 68 | N0=num2str(N0-1); %-1 is necessary because WFDB is 0 based indexed. 69 | wfdb_argument={'-r',recordName,'-a',annotator,'-f',['s' N0]}; 70 | 71 | if(~isempty(N)) 72 | wfdb_argument{end+1}='-t'; 73 | %-1 is necessary because WFDB is 0 based indexed. 74 | wfdb_argument{end+1}=['s' num2str(N-1)]; 75 | end 76 | 77 | if(~isempty(ouputSize)) 78 | wfdb_argument{end+1}='-n'; 79 | wfdb_argument{end+1}=[num2str(ouputSize)]; 80 | end 81 | 82 | data=javaWfdbExec.execToDoubleArray(wfdb_argument); 83 | data=wfdbjava2mat(data); 84 | for n=1:nargout 85 | eval(['varargout{n}=' outputs{n} ';']); 86 | end 87 | 88 | 89 | -------------------------------------------------------------------------------- /mcode/visgraph.m: -------------------------------------------------------------------------------- 1 | function varargout=visgraph(varargin) 2 | % 3 | % [k,logP]=visgraph(x) 4 | % 5 | % Visibility Graph analysis of a time series as described in: 6 | % 7 | % Lacasa, Lucas, et al. 8 | % "From time series to complex networks: The visibility graph." 9 | % Proceedings of the National Academy of Sciences 105.13 (2008): 4972-4975. 10 | % 11 | % Required input parameter: 12 | % x 13 | % Nx1 matrix (doubles) of time series to be analyzed. 14 | % 15 | % 16 | % 17 | % Written by Ikaro Silva, 20134 18 | % Last Modified: November 24, 2014 19 | % Version 1.0 20 | % 21 | % Since 0.9.8 22 | % 23 | % 24 | % %Example 25 | % %Generate Conway Series 26 | % N=1000; 27 | % a=ones(N,1); 28 | % out=ones(N,1); 29 | % for n=3:N 30 | % a(n)=a(a(n-1))+ a(n-a(n-1)); 31 | % out(n)= a(n) - (n/2); 32 | % end 33 | % 34 | % %Generate Surrogate Data 35 | % nS=5; 36 | % S=surrogate(out,nS); 37 | % subplot(3,1,1) 38 | % plot(out);title('Conway Series') 39 | % subplot(3,1,2) 40 | % plot(S(:,1),'r');title('Amplitude Adjusted Surrogate Data') 41 | % 42 | % %Calculate visibility graph for all series 43 | % [k,logP]=visgraph(out); 44 | % subplot(3,1,3) 45 | % plot(k,logP);hold on;grid on 46 | % 47 | % for n=1:nS 48 | % [k,logP]=visgraph(S(:,n)); 49 | % subplot(3,1,3) 50 | % plot(k,logP,'r'); 51 | % end 52 | % 53 | % See also SURROGATE, DFA, MSENTROPY, CORRINT 54 | 55 | %endOfHelp 56 | 57 | [javaWfdbExec,config]=getWfdbClass('visibility'); 58 | 59 | %Set default pararamter values 60 | inputs={'x'}; 61 | outputs={'k','logP'}; 62 | k=[]; 63 | logP=[]; 64 | for n=1:nargin 65 | if(~isempty(varargin{n})) 66 | eval([inputs{n} '=varargin{n};']) 67 | end 68 | end 69 | 70 | if(config.inOctave) 71 | x=cellstr(num2str(x)); 72 | x=javaWfdbExec.execWithStandardInput(x); 73 | Nx=x.size; 74 | out=cell(Nx,1); 75 | for n=1:Nx 76 | out{n}=x.get(n-1); 77 | end 78 | else 79 | out=cell(javaWfdbExec.execWithStandardInput(x).toArray); 80 | end 81 | 82 | M=length(out); 83 | k=zeros(M,1)+NaN; 84 | logP=zeros(M,1)+NaN; 85 | if(length(out{end})==1) 86 | out(end)=[]; 87 | M=M-1; 88 | end 89 | for m=1:M 90 | str=out{m}; 91 | sep=regexp(str,'\s'); 92 | k(m)=str2num(str(1:sep)); 93 | logP(m)=str2num(str(sep(1):end)); 94 | end 95 | 96 | for n=1:nargout 97 | eval(['varargout{n}=' outputs{n} ';']) 98 | end 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /mcode/wabp.m: -------------------------------------------------------------------------------- 1 | function varargout=wabp(varargin) 2 | % 3 | % wabp(recName,beginTime,stopTime,resample,signal) 4 | % 5 | % Wrapper to WFDB WABP: 6 | % http://www.physionet.org/physiotools/wag/wabp-1.htm 7 | % 8 | % Attempts to locate arterial blood pressure (ABP) pulse waveforms in a continuous ABP signal 9 | % in the specified WFDB record "recName". The detector algorithm is based on analysis of the first derivative 10 | % of the ABP waveform. The output of WABP is an annotation file (with annotator name WABP) in which all 11 | % detected beats are labelled normal. 12 | % 13 | % WABP can process records containing any number of signals, but it uses only one signal for ABP pulse 14 | % detection (by default, the lowest-numbered ABP, ART, or BP signal; this can be changed using the 15 | % 'signal' option, see below). WABP is optimized for use with adult human ABPs. 16 | % It has been designed and tested to work best on signals sampled at 125 Hz. For other ABPs, it may be 17 | % necessary to experiment with the sampling frequency as recorded in the input record’s header file 18 | % (see WFDBDESC ). 19 | % 20 | % 21 | % 22 | % CITING CREDIT: To credit this function, please cite the following paper at your work: 23 | % 24 | % Zong, W., Heldt, T., Moody, G. B., & Mark, R. G. (2003). 25 | % An open-source algorithm to detect onset of arterial blood pressure pulses. 26 | % Computers in Cardiology 2003, 30, 259-262. IEEE. 27 | % 28 | % 29 | %Required Parameters: 30 | % 31 | % recName 32 | % String specifying the name of the record in the WFDB path or 33 | % in the current directory. 34 | % 35 | % 36 | % Optional Parameters are: 37 | % 38 | % beginTime (Optional) 39 | % String or integer specifying the begin time. The 40 | % WFDB time format is described at 41 | % http://www.physionet.org/physiotools/wag/intro.htm#time. 42 | % If an integer is entered, it should be between 1 43 | % (first sample) and N (last sample). 44 | % 45 | % stopTime (Optional) 46 | % String or integer specifying the begin time. If string, it should be 47 | % in WFDB time format, if it is an integer, should be between 1 48 | % (first sample) and N (last sample). 49 | % 50 | % resample 51 | % A 1x1 boolean. If true resamples the signal to 125 Hz (default=0). 52 | % 53 | % signal 54 | % A 1x1 integer. Specify the signal index of the WFDB record to be 55 | % used for ABP pulse detection. 56 | % 57 | % 58 | % C Source file written by Wei Zong 1998 59 | % C Source file revised by George Moody 2010 60 | % 61 | % MATLAB Wrapper Written by Ikaro Silva, 2013 62 | % Last Modified: January 16, 2013 63 | % Version 1.1 64 | % 65 | % Since 0.9.0 66 | % 67 | % See also RDANN, RDSAMP, WFDBDESC, WFDBTIME 68 | % 69 | % 70 | % %Example - Note this will create the file: ./slpdb/slp60.wabp in you 71 | % %directory 72 | % N=2000; 73 | % [signal,Fs,tm]=rdsamp('slpdb/slp60',2,N); 74 | % [endTime,dateStamp]=wfdbtime('slpdb/slp60',N); 75 | % wabp('slpdb/slp60',[],endTime{1},[],2); 76 | % [ann]=rdann('slpdb/slp60','wabp') 77 | % plot(tm,x);hold on;grid on 78 | % plot(tm(ann),x(ann),'or') 79 | % 80 | 81 | %endOfHelp 82 | 83 | [javaWfdbExec]=getWfdbClass('wabp'); 84 | 85 | %Set default pararamter values 86 | inputs={'recName','beginTime','stopTime','resample','signal'}; 87 | beginTime=[]; 88 | stopTime=[]; 89 | resample=0; 90 | signal=[]; 91 | for n=1:nargin 92 | if(~isempty(varargin{n})) 93 | eval([inputs{n} '=varargin{n};']); 94 | end 95 | end 96 | 97 | wfdb_argument={'-r',recName}; 98 | 99 | if(~isempty(beginTime)) 100 | wfdb_argument{end+1}='-f'; 101 | %Convert to string if sample number is entered 102 | if(isnumeric(beginTime)) 103 | [beginTime,~]=wfdbtime(recName,beginTime); 104 | end 105 | wfdb_argument{end+1}=beginTime; 106 | end 107 | if(~isempty(stopTime)) 108 | wfdb_argument{end+1}='-t'; 109 | %Convert to string if sample number is entered 110 | if(isnumeric(stopTime)) 111 | [stopTime,~]=wfdbtime(recName,stopTime); 112 | end 113 | wfdb_argument{end+1}=[stopTime]; 114 | end 115 | if(resample) 116 | wfdb_argument{end+1}='-R'; 117 | end 118 | if(~isempty(signal)) 119 | wfdb_argument{end+1}='-s'; 120 | wfdb_argument{end+1}=num2str(signal-1); 121 | end 122 | 123 | err=javaWfdbExec.execToStringList(wfdb_argument); 124 | if(~isempty(strfind(err.toString,['annopen: can''t']))) 125 | error(err); 126 | end 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /mcode/wfdb.m: -------------------------------------------------------------------------------- 1 | function wfdb 2 | % wfdb 3 | % 4 | %Display list of all function available for the WFDB App Toolbox. 5 | % 6 | %Since 0.0.1 7 | % 8 | %%Example: 9 | % wfdb 10 | % 11 | [~,config]=wfdbloadlib; 12 | help(config.MATLAB_PATH(1:end-1)) 13 | %Display information regarding the WFDB Toolbox. 14 | %Written by Ikaro Silva 2012 15 | 16 | 17 | -------------------------------------------------------------------------------- /mcode/wfdb2mat.m: -------------------------------------------------------------------------------- 1 | function wfdb2mat(varargin) 2 | % 3 | % wfdm2mat(recordName,signaList,N,N0) 4 | % 5 | % Wrapper to WFDB WFDB2MAT: 6 | % http://physionet.org/physiotools/wag/wfdb2m-1.htm 7 | % 8 | % Converts a WFDB-compatible signal file to MATLAB/Octave *.mat file. 9 | % The output files are recordNamem.mat and recordNamem.hea. The standard output of 10 | % WFDB2MAT will be saved in a file recordNamem.info. 11 | % 12 | % Required Parameters: 13 | % 14 | % recorName 15 | % String specifying the name of the record in the WFDB path or 16 | % in the current directory. 17 | % 18 | % Optional Parameters are: 19 | % 20 | % signalList 21 | % A Mx1 array of integers. Read only the signals (columns) 22 | % named in the signalList (default: read all signals). 23 | % N 24 | % A 1x1 integer specifying the sample number at which to stop reading the 25 | % record file (default read all the samples = N). 26 | % N0 27 | % A 1x1 integer specifying the sample number at which to start reading the 28 | % record file (default 1 = first sample). 29 | % 30 | % 31 | % 32 | % NOTE: 33 | % You can use the WFDB2MAT command in order to convert the record data into a *.mat file, 34 | % which can then be loaded into MATLAB/Octave's workspace using the LOAD command. 35 | % This will load the signal data in raw units (use RDMAT to load the signal in physical units). 36 | % 37 | % 38 | % Written by Ikaro Silva, 2014 39 | % Last Modified: September 15, 2014 40 | % Version 0.1 41 | % 42 | % Since 0.9.7 43 | % 44 | % %Example: 45 | % wfdb2mat('mitdb/200') 46 | % [tm,signal,Fs,labels]=rdmat('200m'); 47 | % 48 | % 49 | % See also RDSAMP, RDMAT 50 | 51 | %endOfHelp 52 | 53 | [javaWfdbExec,config]=getWfdbClass('wfdb2mat'); 54 | 55 | %Set default pararameter values 56 | inputs={'recordName','signalList','N','N0'}; 57 | signalList=[]; 58 | N=[]; 59 | N0=1; 60 | for n=1:nargin 61 | if(~isempty(varargin{n})) 62 | eval([inputs{n} '=varargin{n};']); 63 | end 64 | end 65 | 66 | wfdb_argument={'-r',recordName,'-f',['s' num2str(N0-1)]}; 67 | 68 | if(~isempty(N)) 69 | wfdb_argument{end+1}='-t'; 70 | wfdb_argument{end+1}=['s' num2str(N)]; 71 | end 72 | 73 | if(~isempty(signalList)) 74 | wfdb_argument{end+1}='-s '; 75 | %-1 is necessary because WFDB is 0 based indexed. 76 | for sInd=1:length(signalList) 77 | wfdb_argument{end+1}=[num2str(signalList(sInd)-1)]; 78 | end 79 | end 80 | 81 | data=javaWfdbExec.execToStringList(wfdb_argument); 82 | 83 | 84 | -------------------------------------------------------------------------------- /mcode/wfdbRecordViewer.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikarosilva/wfdb-app-toolbox/6e81e0d4e7e275418bc13def7c29d6a4464a519b/mcode/wfdbRecordViewer.fig -------------------------------------------------------------------------------- /mcode/wfdbdemo.m: -------------------------------------------------------------------------------- 1 | function wfdbdemo() 2 | % WFDB App Toolbox Demo 3 | % 4 | % Written by Ikaro Silva, 2013 5 | % Last modified: January 10, 2014 6 | % 7 | 8 | [~,config]=wfdbloadlib; 9 | echo on; 10 | display('Reading samples ECG signal from MIT-BIH Arrhythmia Database'); 11 | N=10000; 12 | [ecg,Fs,tm]=rdsamp('mitdb/100',1,N); 13 | 14 | display('Reading and plotting annotations (human labels) of QRS complexes performend on the signals'); 15 | %by cardiologists. 16 | [ann,type,subtype,chan,num]=rdann('mitdb/100','atr',1,N); 17 | 18 | %Plot 2D version of signal and labels 19 | figure; 20 | plot(tm(1:N),ecg(1:N));hold on;grid on; 21 | plot(tm(ann(ann0, an integer representing the number of files 30 | % downloaded. 31 | % 32 | % files_saved 33 | % A cell array of string specifying the saved files full path. 34 | % 35 | % 36 | % Written by Ikaro Silva, April 6, 2015 37 | % Last Modified: - 38 | % Version 0.1 39 | % 40 | % Since 0.0.1 41 | % %Example: 42 | %[success,files_saved]=wfdbdownload('mitdb/102') 43 | % 44 | % 45 | % See also WFDBLOADLIB, RDSAMP 46 | 47 | %endOfHelp 48 | 49 | 50 | %Set default pararamter values 51 | inputs={'recordName'}; 52 | outputs={'success','files_saved'}; 53 | success=0; 54 | files_saved={}; 55 | for n=1:nargin 56 | if(~isempty(varargin{n})) 57 | eval([inputs{n} '=varargin{n};']); 58 | end 59 | end 60 | 61 | [~,config]=wfdbloadlib; 62 | 63 | %Check if file exist already, if exists in CACHE, exit 64 | file_info=dir([config.CACHE_DEST recordName '.*']); 65 | ind=findstr(recordName,'/'); %If empty, not in PhysioBank DB format 66 | 67 | if(~isempty(file_info) || isempty(ind) || (config.CACHE==0)) 68 | success=-1; 69 | else 70 | 71 | db_name=recordName(1:ind(end)); 72 | db_dir=[config.CACHE_DEST db_name]; 73 | if(~isdir(db_dir)) 74 | mkdir(db_dir); 75 | end 76 | if(isdir(db_dir)) 77 | %File extensions to download 78 | wfdb_extensions={'.dat','.atr','.edf','.rec','.hea','.hea-','.trigger','.mat'}; 79 | M=length(wfdb_extensions); 80 | timeout=600; %timeout in seconds 81 | 82 | %File does not exist on cache, attempt to download from server 83 | for m=1:M 84 | try 85 | [furl] = urlwrite([config.CACHE_SOURCE recordName wfdb_extensions{m}],... 86 | [config.CACHE_DEST recordName wfdb_extensions{m}],'Timeout',timeout); 87 | if(~isempty(furl)) 88 | files_saved{end+1}=furl; 89 | warning(['Downloaded WFDB cache file: ' furl]); 90 | end 91 | catch 92 | %Do nothing, because some extensions will not exist 93 | end 94 | end 95 | success=length(files_saved); 96 | end 97 | end 98 | 99 | for n=1:nargout 100 | eval(['varargout{n}=' outputs{n} ';']); 101 | end -------------------------------------------------------------------------------- /mcode/wfdbexec.m: -------------------------------------------------------------------------------- 1 | function varargout=wfdbexec(varargin) 2 | % 3 | % [output]=wfdbexec(commandName,inputArguments,logLevel) 4 | % [nativeCommands]=wfdbexec() 5 | % 6 | % Executes a WFDB native command ('commandName'), with input arguments 7 | % given by 'inputArguments', and outputs everything into a cell array 8 | % called 'output'. The execution is done through a system call outside of 9 | % MATLAB. If no input arguments are provided to the function, the 10 | % output is an array list of all available native WFDB commands in this OS. 11 | % Substantial, non-trivial text parsing maybe required for processing the 12 | % output into a useful MATLAB numerical variable. 13 | % 14 | % WFDBEXEC is useful in cases where a specific command, or feature for a 15 | % command, is not yet in implemented in the MATLAB wrapper. This function 16 | % may be useful for those wishing to do some debugging or performance comparisons. 17 | % 18 | % The user should be very carefull when using this command. The user should 19 | % be familiar with the input and output arguments of the native command 20 | % that he/she is using. In some cases, information about the command can be 21 | % obtained by running the command by itself, of with either '-h', 22 | % '-help','--help' as input arguments in order to access the command help 23 | % information. Offcourse, you can also look at the man page or source code 24 | % for the command at http://www.physionet.org/. 25 | % 26 | % 27 | % 28 | %Required Parameters: 29 | % 30 | % commandName 31 | % String specifying the command to be called. To ge a list of 32 | % available WFDB commands that may be runnable by system calls run 33 | % this function by itself: 34 | % [nativeCommands]=wfdbexec(); 35 | % 36 | %inputArguments 37 | % Cell array of strings specifying the inputArguments to the command. 38 | % Each command flag is an element on the cell array. Command flags 39 | % that require additional parameters should be followed by another 40 | % String element with the requied parameter(s). In cases you are 41 | % usign a command that is already implemente in a MATLAB wrapper, it 42 | % maybe helpful to look at that command's MATLAB code. 43 | % 44 | %Optional Parameters: 45 | % 46 | % logLevel 47 | % 1x1 integer that specifies the logleve (verbosity) of the execution process. 48 | % Options are: 49 | % 0 OFF (Default) 50 | % 1 SEVERE 51 | % 2 WARNING 52 | % 3 INFO 53 | % 4 FINEST 54 | % 5 ALL 55 | % 56 | %Output: 57 | % 58 | %output 59 | % Nx1 Cell array list of Strings. 60 | % 61 | % 62 | % Written by Ikaro Silva, 2013 63 | % Last Modified: January 7, 2014 64 | % Version 0.0.1 65 | % Since 0.9.5 66 | % 67 | % %Get a list of all WFDB native executables 68 | % nativeComands=wfdbexec() 69 | % 70 | % %Get help on RDSAMP 71 | % out=wfdbexec('rdsamp',{'-h'}) 72 | % 73 | % %Read the first five samples of a record 74 | % %Note: This will be very inefficient because we are not buffering 75 | % %and we are returning a list of Strings (instead of doubles and ints). 76 | % %This is provided just as an example on how WFDBEXEC works. 77 | % out=wfdbexec('rdsamp',{'-r','mitdb/100','-t','s5'}) 78 | % 79 | % See also WFDB 80 | 81 | %endOfHelp 82 | logLevel=[]; 83 | 84 | [~,config]=wfdbloadlib; 85 | 86 | if(nargin==0) 87 | %With no arguments passed in, we provide the user a list of native 88 | %commands available for this OS. 89 | del=findstr(' ',config.WFDB_NATIVE_BIN); 90 | if(~isempty(del) && del(1)==1) 91 | config.WFDB_NATIVE_BIN(1)=[]; 92 | end 93 | commandList={}; 94 | if(ispc) 95 | [~,message,~] = fileattrib([config.WFDB_NATIVE_BIN '/bin/*.exec']); 96 | commandList=cell(length(message),1); 97 | for n=1:length(message) 98 | str=message(n).Name; 99 | st=strfind(str,filesep); 100 | if(~isempty(st)) 101 | str=str(st(end)+1:end); 102 | end 103 | commandList(n)={str}; 104 | end 105 | else 106 | [~,message,~] = fileattrib([config.WFDB_NATIVE_BIN '/bin/*']); 107 | for n=1:length(message) 108 | if(~message(n).directory && message(n).UserExecute) 109 | str=message(n).Name; 110 | st=strfind(str,filesep); 111 | if(~isempty(st)) 112 | str=str(st(end)+1:end); 113 | end 114 | if(isempty(strfind(str,'lib'))) 115 | commandList(end+1)={str}; 116 | end 117 | end 118 | end 119 | end 120 | varargout{1}=commandList(:); 121 | else 122 | if(nargin>2) 123 | logLevel=varargin{3}; 124 | end 125 | if(~wfdbloadlib) 126 | %Add classes to dynamic path 127 | wfdbloadlib; 128 | end 129 | javaWfdbExec=org.physionet.wfdb.Wfdbexec(varargin(1),strcmp(config.customArchFlag,'true')); 130 | if(~isempty(logLevel)) 131 | javaWfdbExec.setLogLevel(logLevel); 132 | end 133 | try 134 | %System call 135 | varargout{1}=cell(javaWfdbExec.execToStringList(varargin{2}).toArray); 136 | clear javaWfdbExec; %Clean-up to avoid leaked Java classes 137 | catch exception 138 | clear javaWfdbExec %Clean-up to avoid leaked Java classes 139 | rethrow(exception) 140 | end 141 | 142 | end 143 | -------------------------------------------------------------------------------- /mcode/wfdbjava2mat.m: -------------------------------------------------------------------------------- 1 | function matrix = wfdbjava2mat(array) 2 | % 3 | % [matrix]=wfdbjava2mat(array) 4 | % 5 | % This function takes a one-dimensional or two-dimensional array of 6 | % Java values, and converts it to a matrix or vector. This conversion 7 | % is automatic and implicit in Matlab and is sometimes automatic in 8 | % Octave (depending on the data type and dimensionality) but in other 9 | % cases an explicit conversion is needed. 10 | 11 | if(isnumeric(array)) 12 | matrix=array; 13 | else 14 | if(exist('java_matrix_autoconversion','builtin')) 15 | java_matrix_autoconversion(1,'local'); 16 | else 17 | java_convert_matrix(1,'local'); 18 | end 19 | 20 | if(exist('__java2mat__','builtin')) 21 | matrix=builtin('__java2mat__',array); 22 | else 23 | matrix=java2mat(array); 24 | end 25 | 26 | if(~isnumeric(matrix)) 27 | matrix=javaObject('org.octave.Matrix',array); 28 | if(exist('__java2mat__','builtin')) 29 | matrix=builtin('__java2mat__',matrix); 30 | else 31 | matrix=java2mat(matrix); 32 | end 33 | end 34 | end 35 | 36 | end 37 | -------------------------------------------------------------------------------- /mcode/wfdbtest.m: -------------------------------------------------------------------------------- 1 | function wfdbtest(varargin) 2 | %This script will test the installation of the WFDB Application Toolbox 3 | % 4 | % Written by Ikaro Silva, 2013 5 | % 6 | % Last Modified: October 15, 2014 7 | % 8 | % Version 1.2 9 | % Since 0.0.1 10 | % 11 | % See also wfdb, rdsamp 12 | 13 | %endOfHelp 14 | inputs={'verbose'}; 15 | verbose=1; 16 | for n=1:nargin 17 | if(~isempty(varargin{n})) 18 | eval([inputs{n} '=varargin{n};']) 19 | end 20 | end 21 | 22 | 23 | if(verbose) 24 | fprintf('***Starting test of the WFDB Application Toolbox\n') 25 | fprintf('***If you experience any issues, please see our FAQ at:\n') 26 | fprintf('http://physionet.org/physiotools/matlab/wfdb-app-matlab/faq.shtml\n') 27 | end 28 | 29 | if(usejava('jvm') ) 30 | ROOT=[matlabroot filesep 'sys' filesep 'java' filesep 'jre' filesep]; 31 | JVM_PATH=dir([ROOT '*']); 32 | rm_fl=[]; 33 | for i=1:length(JVM_PATH) 34 | if(~JVM_PATH(i).isdir || strcmp(JVM_PATH(i).name,'.')|| strcmp(JVM_PATH(i).name,'..')) 35 | rm_fl(end+1)=i; 36 | end 37 | end 38 | JVM_PATH(rm_fl)=[]; 39 | if(~isempty(JVM_PATH)) 40 | if(ispc) 41 | %Use quotes to escape white space in Windows 42 | JVM_PATH=['"' ROOT JVM_PATH.name filesep 'jre' filesep 'bin' filesep '"java']; 43 | else 44 | JVM_PATH=[ROOT JVM_PATH.name filesep 'jre' filesep 'bin' filesep 'java']; 45 | end 46 | else 47 | warning(['Could not find Java runtime environment!!']); 48 | end 49 | else 50 | warning('MATLAB JVM is not properly configured for toolbox') 51 | end 52 | 53 | 54 | %Print Configuration settings 55 | if(verbose) 56 | fprintf('**Printing Configuration Settings:\n') 57 | end 58 | wfdbpath=which('wfdbloadlib'); 59 | if(verbose) 60 | fprintf('**\tWFDB App Toolbox Path is:\n'); 61 | fprintf('\t\t%s\n',wfdbpath); 62 | end 63 | [isloaded,config]=wfdbloadlib; 64 | nsm=fieldnames(config); 65 | if(verbose) 66 | config 67 | end 68 | 69 | %Print warning with respect to any unsupported component 70 | if(isempty(strfind(config.MATLAB_VERSION,'2014')) && ~config.inOctave) 71 | warning(['You are using an unsupported version of MATLAB: ' config.MATLAB_VERSION]) 72 | end 73 | if(~isempty(regexp(config.osName,'macosx','once')) && isempty(regexp(config.OSVersion,'10.9','once'))) 74 | warning(['You are using an unsupported Mac OS : ' config.MATLAB_VERSION]) 75 | warning(['The WFDB Toolbox is only supported on Mac OS X 10.9']) 76 | end 77 | 78 | 79 | cur_dir=pwd; 80 | os_dir=findstr(config.WFDB_NATIVE_BIN,filesep); 81 | os_dir=config.WFDB_NATIVE_BIN(os_dir(end-1)+1:end-1); 82 | 83 | sampleLength=10000; 84 | cur_dir=pwd; 85 | data_dir=[config.MATLAB_PATH]; 86 | 87 | %Simple queries to PhysioNet servers 88 | %loaded properly. This should work regardless of the libcurl installation 89 | if(verbose) 90 | fprintf('**Querying PhysioNet for available databases...\n') 91 | end 92 | db_list=physionetdb; 93 | db_size=length(db_list); 94 | if(verbose) 95 | fprintf(['\t' num2str(db_size) ... 96 | ' databases available for download (type ''help physionetdb'' for more info).\n']) 97 | end 98 | 99 | %Test ability to read local data and annotations 100 | if(verbose) 101 | fprintf('**Reading local example data and annotation...\n') 102 | end 103 | sampleLength=10000; 104 | cur_dir=pwd; 105 | data_dir=[config.MATLAB_PATH filesep 'example' filesep]; 106 | fname='a01'; 107 | 108 | try 109 | cd(data_dir) 110 | [signal,Fs,tm]=rdsamp(fname,[],sampleLength); 111 | if(length(tm) ~= sampleLength) 112 | warning( ['Incomplete data! tm is ' num2str(length(tm)) ', expected: ' num2str(sampleLength)]); 113 | end 114 | catch 115 | cd(cur_dir) 116 | if(strfind(lasterr,'Undefined function')) 117 | if(verbose) 118 | fprintf(['ERROR!!! Toolbox is not on the MATLAB path. Add it to MATLAB path by typing:\n ']); 119 | display(['addpath(''' cur_dir ''')']); 120 | end 121 | end 122 | str=['cd(' data_dir ');[signal,Fs,tm]=rdsamp(' fname ',[],' num2str(sampleLength) ');']; 123 | if(verbose) 124 | warning(['Failed running: ' str]); 125 | end 126 | end 127 | cd(cur_dir) 128 | 129 | 130 | try 131 | cd(data_dir) 132 | [ann]=rdann(fname,'fqrs',[],sampleLength); 133 | if(isempty(ann)) 134 | warning('Annotations are empty.'); 135 | end 136 | catch 137 | cd(cur_dir) 138 | warning(lasterr); 139 | end 140 | cd(cur_dir) 141 | 142 | %Test 4- Test ability to write local annotations 143 | if(verbose) 144 | fprintf('**Calculating maternal QRS sample data ...\n') 145 | end 146 | try 147 | cd(data_dir) 148 | wqrs(fname,[],[],1) 149 | [Mann]=rdann(fname,'wqrs',[],sampleLength); 150 | %Remove the generated annotation file 151 | delete([data_dir filesep 'a01.wqrs']); 152 | if(isempty(Mann)) 153 | warning('Annotations are empty.'); 154 | end 155 | catch 156 | cd(cur_dir) 157 | if(verbose) 158 | warning(lasterr); 159 | end 160 | end 161 | cd(cur_dir) 162 | 163 | 164 | %Test ability to read records from PhysioNet servers 165 | if(verbose) 166 | fprintf('**Reading data from PhysioNet...\n') 167 | end 168 | sampleLength=10; 169 | try 170 | %Check if record does not exist already in current directory 171 | recExist=[]; 172 | try 173 | recExist=dir(['mghdb' filesep 'mgh001']); 174 | catch 175 | %Record does not exist, go on 176 | end 177 | if(~isempty(recExist)) 178 | warning('Cannot test because record already exists in current directory. Delete record and repeat.') 179 | end 180 | [signal]=rdsamp('mghdb/mgh001',[1],sampleLength); 181 | if(length(signal) ~= sampleLength) 182 | warning( ['Incomplete data! tm is ' num2str(length(signal)) ', expected: ' num2str(sampleLength)]); 183 | end 184 | catch 185 | if(verbose) 186 | warning(lasterr); 187 | end 188 | end 189 | 190 | 191 | if(verbose) 192 | fprintf('***Finished testing WFDB App Toolbox!\n') 193 | fprintf(['***Note: You currently have access to ' num2str(db_size) ... 194 | ' databases for download via PhysioNet:\n\t Type ''physionetdb'' for a list of the databases or ''help physionetdb'' for more info.\n']) 195 | end 196 | -------------------------------------------------------------------------------- /mcode/wfdbtime.m: -------------------------------------------------------------------------------- 1 | function varargout=wfdbtime(varargin) 2 | % 3 | % [timeStamp,dateStamp]=wfdbtime(recordName,samples) 4 | % 5 | % Wrapper to WFDB WFDBTIME: 6 | % http://www.physionet.org/physiotools/wag/wfdbti-1.htm 7 | % 8 | % Converts sample indices from recordName into timeStamp and dateStamps. 9 | % Returns: 10 | % 11 | % timesStamp 12 | % Nx1 vector of cell Strings representing times stamps with respect to the 13 | % first sample in recordName. 14 | % 15 | % dateStamp 16 | % Nx1 vector of cell Strings representing date stamps with respect to the 17 | % first sample in recordName. 18 | % 19 | % 20 | % Required Parameters: 21 | % 22 | % recorName 23 | % String specifying the name of the record in the WFDB path or 24 | % in the current directory. 25 | % 26 | % samples 27 | % Nx1 vector of integers (indices) of samples from the signal in recordName (indices are 28 | % relative to the first sample). 29 | % 30 | % 31 | %%Example 32 | %[timeStamp,dateStamp]=wfdbtime('challenge/2013/set-a/a01',[1 10 30]') 33 | % 34 | % 35 | % 36 | % Written by Ikaro Silva, 2013 37 | % Last Modified: March 24, 2014 38 | % Version 1.1 39 | % Since 0.0.1 40 | % 41 | % See also RDANN, WFDBDESC 42 | % 43 | 44 | %endOfHelp 45 | 46 | [javaWfdbExec,config]=getWfdbClass('wfdbtime'); 47 | 48 | %Set default pararamter values 49 | inputs={'recordName','samples'}; 50 | outputs={'timeStamp','dateStamp'}; 51 | for n=1:nargin 52 | if(~isempty(varargin{n})) 53 | eval([inputs{n} '=varargin{n};']); 54 | end 55 | end 56 | 57 | %Convert all the annoation to strings and send them as arguments 58 | %TODO: maybe send ast STDIN ? 59 | N=length(samples); 60 | timeStamp=cell(N,1); 61 | dateStamp=cell(N,1); 62 | wfdb_argument=cell(N+2,1); 63 | wfdb_argument{1}='-r'; 64 | wfdb_argument{2}=recordName; 65 | samples=num2str(samples(:)); 66 | for n=1:N 67 | wfdb_argument{n+2}=['s' samples(n,:)]; 68 | end 69 | 70 | data=javaWfdbExec.execToStringList(wfdb_argument).toArray; 71 | if(config.inOctave) 72 | tmpData=data; 73 | data=cell(N,1); 74 | for i=1:N 75 | data(i)=char(tmpData(i)); 76 | end 77 | clear tmpData; 78 | end 79 | for n=1:length(data) 80 | str=regexp(data(n,1),'\s+','split'); 81 | if(config.inOctave) 82 | str=str{:}; 83 | end 84 | timeStamp(n)=str(3); 85 | dateStamp(n)=str(4); 86 | end 87 | 88 | for n=1:nargout 89 | eval(['varargout{n}=' outputs{n} ';']); 90 | end 91 | -------------------------------------------------------------------------------- /mcode/wfdbtool.m: -------------------------------------------------------------------------------- 1 | function varargout=wfdbtool(varargin) 2 | % 3 | % [stat,browser,url]=wfdbtool(recordName,N,N0,systemBrowser) 4 | % 5 | % MATLAB interface to PhysioNet's LightWAVE. LightWAVE is a lightweight 6 | % waveform and annotation viewer and editor. You can use it to view any of 7 | % the recordings of physiologic signals and time series in PhysioNet, 8 | % together with their annotations (event markers). 9 | % 10 | % NOTE: This tool is currently supported only in MATLAB 2013b or higher. On some system 11 | % (such as Linux) the MATLAB default browser may not worker properly 12 | % with LightWAVE. In this case you may want to try setting the 13 | % 'systemBrowser' to 1 (true). 14 | % 15 | % Required Input Parameters: 16 | % 17 | % recorName 18 | % String specifying the name of the record in the WFDB path or 19 | % in the current directory. 20 | % 21 | % Optional Input Parameters are: 22 | % 23 | % N 24 | % A 1x1 integer specifying the sample number at which to stop displaying the 25 | % record file. Default is enough samples to cover 10 seconds. 26 | % N0 27 | % A 1x1 integer specifying the sample number at which to start displaying the 28 | % record file (default 1 = first sample).Default is beginning of 29 | % record. 30 | % 31 | % systemBrowser 32 | % A 1x1 boolean. If true, uses the system browser. Default = 0. 33 | % 34 | % 35 | % Optional Outputs are: 36 | % 37 | % stat 38 | % A returns the status of the web command in the variable STAT. STAT = 0 indicates successful execution. STAT = 1 39 | % indicates that the browser was not found. STAT = 2 indicates that the 40 | % browser was found, but could not be launched. 41 | % 42 | % browser 43 | % Returns a handle to the last active web browser. 44 | % 45 | % url 46 | % Returns the URL of the current location. 47 | % 48 | % %Example 1 49 | % 50 | % 51 | % Written by Ikaro Silva, 2013 52 | % Last Modified: October 30, 2013 53 | % Version 1.0 54 | % 55 | % Since 0.9.4 56 | % 57 | % %Example 1- Read a signal from PhysioNet's Remote server: 58 | %wfdbtool('challenge/2013/set-a/a01') 59 | % 60 | % 61 | % See also WFDBDESC, PHYSIONETDB, RDANN, WFDBTIME 62 | 63 | %endOfHelp 64 | 65 | %Set default pararamter values 66 | inputs={'recordName','N','N0','systemBrowser'}; 67 | outputs={'stat','browser','url'}; 68 | N=[]; 69 | N0=[]; 70 | systemBrowser=0; 71 | SERVER='http://physionet.org/lightwave?db='; 72 | for n=1:nargin 73 | if(~isempty(varargin{n})) 74 | eval([inputs{n} '=varargin{n};']) 75 | end 76 | end 77 | 78 | %If time is specified, convert from samples to record time in seconds 79 | if(~isempty(N) || ~isempty(N0)) 80 | if(isempty(N0)) 81 | N0=0; %Default value put here for lazy initialization purposes 82 | end 83 | [~,Fs]=wfdbdesc(recordName); 84 | N0=round(N0/Fs); 85 | if(isempty(N)) 86 | %If stop time not specified, default to 10 seconds 87 | N=N0+round(Fs*10); 88 | else 89 | N=N0+round(N/Fs); 90 | end 91 | end 92 | 93 | 94 | %Reformat database name into PhysioBank format 95 | sep=strfind(recordName,'/'); 96 | db=recordName(1:sep(end)-1); 97 | rec=recordName(sep(end)+1:end); 98 | record_url=[SERVER db '&record=' rec]; 99 | 100 | record_url 101 | %Launch MATLAB's web browser 102 | if(systemBrowser) 103 | [stat,browser,url]=web(record_url,'-browser'); 104 | else 105 | [stat,browser,url]=web(record_url); 106 | end 107 | 108 | 109 | %Send output, if anyd 110 | for n=1:nargout 111 | eval(['varargout{n}=' outputs{n} ';']) 112 | end 113 | 114 | 115 | -------------------------------------------------------------------------------- /mcode/wqrs.m: -------------------------------------------------------------------------------- 1 | function varargout=wqrs(varargin) 2 | % 3 | % wqrs(recordName,N,N0,signal,threshold,findJ,powerLineFrequency,resample) 4 | % 5 | % Wrapper to WFDB WQRS: 6 | % http://www.physionet.org/physiotools/wag/wqrs-1.htm 7 | % 8 | % Creates a WQRS annotation file at the current MATLAB directory. 9 | % The annotation file will have the same name as the recorName file, 10 | % but followed with the *.wqrs suffix. Use RDANN to read the annoations 11 | % into MATLAB's workspace in order to read the sample QRS locations. 12 | % 13 | % If recordName is the path to a record at PhysioNet's database, then 14 | % the annation files will be stored in a subdirectory with the same relative 15 | % path as recordName and under the current directory. 16 | % 17 | % 18 | % NOTE: In order to read the generated annotation file using RDANN, it is 19 | % necessary to have the WFDB record (*.hea and *.dat) files in the same 20 | % directory as the annotation file. 21 | % 22 | % 23 | % CITING CREDIT: To credit this function, please cite the following paper in your work: 24 | % 25 | % Zong, W., G. B. Moody, and D. Jiang."A robust open-source algorithm to detect onset 26 | % and duration of QRS complexes." Computers in Cardiology, 2003. IEEE, 2003. 27 | % 28 | % 29 | % Required Parameters: 30 | % 31 | % recorName 32 | % String specifying the name of the record in the WFDB path or 33 | % in the current directory. 34 | % 35 | % 36 | % Optional Parameters are: 37 | % 38 | % N 39 | % A 1x1 integer specifying the sample number at which to stop reading the 40 | % record file (default read all = N). 41 | % N0 42 | % A 1x1 integer specifying the sample number at which to start reading the 43 | % annotion file (default 1 = begining of the record). 44 | % 45 | % signal 46 | % A 1x1 integer. Specify the signal to obtain the annotation (default 47 | % = 1, first signal). 48 | % 49 | % threshold 50 | % A 1x1 double. Specify the detection threshold in millivolts 51 | % (default = 100). Use higher values to reduce false detections, or lower values to 52 | % reduce the number of missed beats. 53 | % 54 | % findJ 55 | % A 1x1 boolean. Find and annotate J-points (QRS ends) as well as QRS onsets. 56 | % Default is false. 57 | % 58 | % 59 | % powerLineFrequency 60 | % A 1x1 double. Specify the power line main frequency in Hz (default= 61 | % 60 Hz), wqrs will apply a notch filter of the specified frequency 62 | % to the input signal before length-transforming it. 63 | % 64 | % resample 65 | % A 1x1 boolean. Resample the input at 120 Hz if the power line frequency 66 | % is 60 Hz, or at 150 Hz otherwise (default= false : do not resample). 67 | % 68 | % 69 | % 70 | % Source code written by Wei Zong and George B. Moody. 71 | % 72 | % MATLAB wrapper written by Ikaro Silva, 2013 73 | % Last Modified: - 74 | % Version 1.0 75 | % Since 0.0.1 76 | % 77 | % %Example - Requires write permission to current directory 78 | %wqrs('challenge/2013/set-a/a01'); 79 | 80 | %endOfHelp 81 | 82 | javaWfdbExec=getWfdbClass('wqrs'); 83 | 84 | %Set default pararamter values 85 | inputs={'recordName','N','N0','signal','threshold', ... 86 | 'findJ','powerLineFrequency','resample'}; 87 | N=[]; 88 | N0=1; 89 | signal=[]; %use application default 90 | threshold=[];%use application default 91 | findJ=[]; 92 | powerLineFrequency=[]; 93 | resample=[]; 94 | for n=1:nargin 95 | if(~isempty(varargin{n})) 96 | eval([inputs{n} '=varargin{n};']); 97 | end 98 | end 99 | 100 | N0=num2str(N0-1); %-1 is necessary because WFDB is 0 based indexed. 101 | wfdb_argument={'-r',recordName,'-f',['s' N0]}; 102 | 103 | if(~isempty(N)) 104 | wfdb_argument{end+1}='-t'; 105 | %-1 is necessary because WFDB is 0 based indexed. 106 | wfdb_argument{end+1}=['s' num2str(N-1)]; 107 | end 108 | if(~isempty(signal)) 109 | wfdb_argument{end+1}='-s'; 110 | %-1 is necessary because WFDB is 0 based indexed. 111 | wfdb_argument{end+1}=num2str(signal-1); 112 | end 113 | if(~isempty(threshold)) 114 | wfdb_argument{end+1}='-m'; 115 | %-1 is necessary because WFDB is 0 based indexed. 116 | wfdb_argument{end+1}=num2str(threshold-1); 117 | end 118 | if(~isempty(findJ) && findJ) 119 | wfdb_argument{end+1}='-j'; 120 | end 121 | 122 | if(~isempty(powerLineFrequency)) 123 | wfdb_argument{end+1}='-p'; 124 | %-1 is necessary because WFDB is 0 based indexed. 125 | wfdb_argument{end+1}=num2str(powerLineFrequency); 126 | end 127 | 128 | if(~isempty(resample) && resample) 129 | wfdb_argument{end+1}='-R'; 130 | end 131 | 132 | javaWfdbExec.execToStringList(wfdb_argument); 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /mcode/wrsamp.m: -------------------------------------------------------------------------------- 1 | function varargout=wrsamp(varargin) 2 | % 3 | % wrsamp(tm,data,fileName,Fs,gain,format) 4 | % 5 | % Wrapper to WFDB WRSAMP: 6 | % http://www.physionet.org/physiotools/wag/wrsamp-1.htm 7 | % 8 | % Writes data into a WFDB compatible *.dat and *.hea files. The files will be saved at 9 | % the current directory (if the record is in the current directory) or, if a using 10 | % a PhysioNet web record , a subdirectory in the current directory, with 11 | % the relative path determined by recordName. You can use RDSAMP to 12 | % verify that the write was completed successfully (see example below). For 13 | % detailed information on the parameters described below, please see: 14 | % http://www.physionet.org/physiotools/wag/header-5.htm 15 | % 16 | % 17 | % 18 | % LIMITATIONS: 19 | % The input variables 'tm' and 'data' should be integer values. 20 | % Currently the MATLAB/Octave wrappers do take into account Baseline values. 21 | % Signals that have baseline values will not be converted properly to physical units. 22 | % You will have to edit the generated header files manually to include baseline variables and update the checksums. 23 | % 24 | % 25 | % Required Parameters: 26 | % 27 | % tm 28 | % Nx1 vector of integers representing sample index. 29 | % 30 | % data 31 | % NxM vector of integers (M channels) that will be written to file. 32 | % 33 | % fileName 34 | % 35 | % String specifying the file name. WRSAMP will write the signal file in 36 | % the current directory as "fileName.dat", and create a header file in the 37 | % current directory "fileName.hea" for the specified record. 38 | % 39 | % Optional Parameters: 40 | % 41 | % Fs 42 | % A 1x1 double specifying the sampling frequency (in samples per second per 43 | % signal) for the output signals (default: 250). It affects the output header 44 | % file only. This option has no effect on the output signal file, which 45 | % contains one sample per signal for each line of input. 46 | % 47 | % gain 48 | % A 1x1 or Mx1 vector of doubles specifying gain value in A/D units per millivolt 49 | % for the output signals (default: 200). This option the output header file only. 50 | % This option has no effect on the output signal file. 51 | % 52 | % format 53 | % String specifying the signal's default format (default: "16"). For 54 | % information on the available WFDB formats please see: 55 | % http://www.physionet.org/physiotools/wag/signal-5.htm 56 | % 57 | %%Example- 58 | %%Read signal in raw units 59 | %[signal,Fs,tm]=rdsamp('challenge/2013/set-a/a01',[],[],[],4); 60 | %[siginfo,Fs]=wfdbdesc('challenge/2013/set-a/a01'); 61 | %%Write a copy to file 62 | %wrsamp(tm,signal(:,1),'a01Copy',Fs(1),200,siginfo(1).Format) 63 | %%Check that the signals match 64 | %[signalCopy,Fs,tm]=rdsamp('a01Copy',[],[],[],4); 65 | %err=sum(signalCopy ~= signal(:,1)) 66 | % 67 | % 68 | % Written by Ikaro Silva, 2013 69 | % Last Modified: April 10, 2015 70 | % Since 0.0.1 71 | % 72 | % 73 | % See also rdsamp, wfdbdesc, mat2wfdb 74 | % 75 | 76 | %endOfHelp 77 | 78 | javaWfdbExec=getWfdbClass('wrsamp'); 79 | 80 | %Set default pararamter values 81 | inputs={'tm','data','fileName','Fs','gain','format'}; 82 | Fs=[]; 83 | gain=[]; 84 | format=[]; 85 | for n=1:nargin 86 | if(~isempty(varargin{n})) 87 | eval([inputs{n} '=varargin{n};']); 88 | end 89 | end 90 | 91 | wfdb_argument={'-c','-z','-o',fileName}; 92 | 93 | if(~isempty(Fs)) 94 | wfdb_argument{end+1}='-F'; 95 | wfdb_argument{end+1}=num2str(Fs); 96 | end 97 | 98 | if(~isempty(gain)) 99 | wfdb_argument{end+1}='-G'; 100 | wfdb_argument{end+1}=num2str(gain); 101 | end 102 | 103 | if(~isempty(format)) 104 | wfdb_argument{end+1}='-O'; 105 | wfdb_argument{end+1}=format; 106 | end 107 | 108 | del=repmat([' '],size(tm)); 109 | data=[num2str(tm) del num2str(data)]; 110 | javaWfdbExec.setArguments(wfdb_argument); 111 | javaWfdbExec.execWithStandardInput(cellstr(data)); 112 | 113 | -------------------------------------------------------------------------------- /mcode/xform.m: -------------------------------------------------------------------------------- 1 | function varargout=snip(varargin) 2 | % 3 | % err=snip(inputRecord,outputRecord,beginTime,stopTime,inputAnn,outSignalList,outFs) 4 | % 5 | % Wrapper to WFDB SNIP: 6 | % http://www.physionet.org/physiotools/wag/snip-1.htm 7 | % 8 | % Copy an excerpt of a WFDB record 9 | % 10 | % 11 | %Input Parameters: 12 | % inputRecord 13 | % String specifying the input WFDB record file. 14 | % 15 | % outputRecord 16 | % String specifying the output WFDB record file name that will be generated. 17 | % 18 | % beginTime (Optional) 19 | % Integer specifying start time of the output WFDB record. Default is 20 | % the beginning of the input record. 21 | % 22 | % stopTime (Optional) 23 | % Integer specifying end time of the output WFDB record. Defaut is 24 | % end of input record. 25 | % 26 | % inputAnn (Optional) 27 | % String specifying the annotation files to convert along with the 28 | % given record. Defaults i none (empty). 29 | % 30 | % outSignalList (Optional) 31 | % Array of integers specifying which signals to convert. Default is 32 | % to use all signals. 33 | % 34 | % outFormat (Optional) 35 | % String specifying the output format (see http://www.physionet.org/physiotools/wag/header-5.htm). 36 | % Default is the same as input record. 37 | % 38 | %Output Parameters: 39 | % err (Optional) 40 | % String spefiying any error messages. If empty, conversion was 41 | % sucessfull. 42 | % 43 | % Written by Ikaro Silva, 2015 44 | % Last Modified: - 45 | % Version 1.0 46 | % Since 1.0 47 | % 48 | % See also RDSAMP, RDANN, WFDBDESC 49 | 50 | 51 | %endOfHelp 52 | 53 | javaWfdbExec=getWfdbClass('xform'); 54 | 55 | %Set default pararamter values 56 | 57 | inputs={'inputRecord','outputRecord','beginTime','stopTime','inputAnn','outSignalList','outFs'}; 58 | inputRecord=[]; 59 | outputRecord=[]; 60 | beginTime=[]; 61 | stopTime=[]; 62 | inputAnn=[]; 63 | outSignalList=[]; 64 | outFs=[]; 65 | for n=1:nargin 66 | if(~isempty(varargin{n})) 67 | eval([inputs{n} '=varargin{n};']) 68 | end 69 | end 70 | 71 | wfdb_argument={'-i',inputRecord,'-o',outputRecord}; 72 | 73 | if(~isempty(beginTime)) 74 | wfdb_argument{end+1}='-f'; 75 | wfdb_argument{end+1}=['s ' num2str(beginTime-1)]; 76 | end 77 | if(~isempty(stopTime)) 78 | wfdb_argument{end+1}='-t'; 79 | wfdb_argument{end+1}=['s ' num2str(stopTime-1)]; 80 | end 81 | if(~isempty(inputAnn)) 82 | wfdb_argument{end+1}='-a'; 83 | wfdb_argument{end+1}=inputAnn; 84 | end 85 | 86 | if(~isempty(outSignalList)) 87 | wfdb_argument{end+1}='-s'; 88 | wfdb_argument{end+1}=[num2str(outSignalList-1)]; 89 | end 90 | 91 | err=javaWfdbExec.execToStringList(wfdb_argument); 92 | 93 | if(nargout>0) 94 | vargout{1}=err; 95 | end -------------------------------------------------------------------------------- /src/org/physionet/wfdb/ErrorReader.java: -------------------------------------------------------------------------------- 1 | package org.physionet.wfdb; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.util.logging.Level; 8 | import java.util.logging.Logger; 9 | 10 | public class ErrorReader extends Thread { 11 | InputStream is; 12 | Logger logger; 13 | Level level; 14 | 15 | public ErrorReader(InputStream is, Logger logger, Level level) { 16 | this.is=is; 17 | this.logger = logger; 18 | this.level = level; 19 | } 20 | public ErrorReader(InputStream is, Logger logger) { 21 | this(is, logger, Level.WARNING); 22 | } 23 | public void run(){ 24 | try { 25 | InputStreamReader isr= new InputStreamReader(is); 26 | BufferedReader br = new BufferedReader(isr); 27 | String line = null; 28 | while ( ( line = br.readLine() )!= null ){ 29 | logger.log(level, line); 30 | } 31 | } catch (IOException e) { 32 | e.printStackTrace(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/org/physionet/wfdb/InputWriter.java: -------------------------------------------------------------------------------- 1 | package org.physionet.wfdb; 2 | 3 | import java.io.BufferedWriter; 4 | import java.io.DataOutputStream; 5 | import java.io.IOException; 6 | import java.io.OutputStream; 7 | import java.io.OutputStreamWriter; 8 | 9 | public class InputWriter extends Thread{ 10 | 11 | String[] inputData; 12 | byte[] inputDataBytes; 13 | OutputStream os; 14 | String newLine; 15 | 16 | public InputWriter(OutputStream os, String[] inputData){ 17 | this.os=os; 18 | this.inputData=inputData; 19 | inputDataBytes=null; 20 | newLine = System.getProperty("line.separator"); 21 | } 22 | 23 | public InputWriter(OutputStream os, byte[] inputData){ 24 | this.os=os; 25 | this.inputDataBytes=inputData; 26 | inputData=null; 27 | newLine = System.getProperty("line.separator"); 28 | } 29 | 30 | public void run(){ 31 | try { 32 | if(inputDataBytes == null){ 33 | OutputStreamWriter osw= new OutputStreamWriter(os); 34 | BufferedWriter bw= new BufferedWriter(osw); 35 | for(int i=0;i results; 12 | 13 | public OutputReader(InputStream is){ 14 | this.is=is; 15 | results= new ArrayList(); 16 | } 17 | public void run(){ 18 | try { 19 | InputStreamReader isr= new InputStreamReader(is); 20 | BufferedReader br = new BufferedReader(isr); 21 | String line = null; 22 | while ( ( line = br.readLine() )!= null ){ 23 | results.add(line); 24 | } 25 | } catch (IOException e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | public ArrayList getResults(){ 30 | return results; 31 | } 32 | } -------------------------------------------------------------------------------- /src/org/physionet/wfdb/SystemSettings.java: -------------------------------------------------------------------------------- 1 | package org.physionet.wfdb; 2 | 3 | import java.io.File; 4 | import java.io.UnsupportedEncodingException; 5 | import java.net.URLDecoder; 6 | import java.util.Map; 7 | import java.io.BufferedReader; 8 | import java.io.FileReader; 9 | import java.io.IOException; 10 | 11 | public class SystemSettings { 12 | 13 | static String fsep= System.getProperty("file.separator"); 14 | 15 | public static void loadCurl(Boolean customArch){ 16 | 17 | if(getOsName().contains("windows")){ 18 | //On Windows, load the shipped curl library 19 | System.load(SystemSettings.getWFDB_NATIVE_BIN(customArch) 20 | + "\\bin\\libcurl-4.dll" ); 21 | }else if(getOsName().contains("mac")){ 22 | String libCurlName= SystemSettings.getWFDB_NATIVE_BIN(customArch) 23 | + "bin/libcurl.4.dylib"; 24 | SecurityManager security = System.getSecurityManager(); 25 | if(security != null){ 26 | security.checkLink(libCurlName); 27 | } 28 | System.load(libCurlName); 29 | } 30 | 31 | } 32 | 33 | private static void loadLib(String libName, Boolean customArch){ 34 | if(getOsName().contains("windows")){ 35 | // No RPATH on windows, so library dependencies can't 36 | // be loaded automatically and must be pre-loaded. 37 | 38 | // (Although Windows automatically searches for 39 | // required DLLs in the *application's* directory, it 40 | // doesn't do the same when loading a DLL.) 41 | 42 | // Nasty kludge: list the required libraries in a 43 | // separate text file, so they do not have to be 44 | // hardcoded here. 45 | 46 | String libdir = getWFDB_NATIVE_BIN(customArch) + "bin\\"; 47 | String depfile = libdir + "lib" + libName + ".dep"; 48 | try { 49 | BufferedReader r = new BufferedReader(new FileReader(depfile)); 50 | String name; 51 | while ((name = r.readLine()) != null) { 52 | System.load(libdir + name); 53 | } 54 | } catch (IOException e) { 55 | throw new UnsatisfiedLinkError("error reading " + depfile); 56 | } 57 | System.load(libdir + "lib" + libName + ".dll"); 58 | }else if(getOsName().contains("mac")){ 59 | System.load(SystemSettings.getWFDB_NATIVE_BIN(customArch) 60 | + "/lib/lib" + libName + ".dylib"); 61 | }else{ 62 | //Default to Linux 63 | System.load(SystemSettings.getWFDB_NATIVE_BIN(customArch) 64 | + "/lib/lib" + libName + ".so"); 65 | } 66 | } 67 | 68 | public static void loadLib(String libName){ 69 | try { 70 | loadLib(libName, true); 71 | } 72 | catch (UnsatisfiedLinkError e) { 73 | loadLib(libName, false); 74 | } 75 | } 76 | 77 | public static String getosArch(){ 78 | //Returns the JVM type 79 | return System.getProperty("os.arch"); 80 | } 81 | 82 | public static String getOsName(){ 83 | String osName=System.getProperty("os.name"); 84 | osName=osName.replace(" ",""); 85 | osName=osName.toLowerCase(); 86 | if(osName.startsWith("windows")){ 87 | osName="windows"; //Treat all Windows versions the same for now 88 | } 89 | return osName; 90 | } 91 | 92 | public static String getLD_PATH(boolean customArchFlag){ 93 | ProcessBuilder launcher = new ProcessBuilder(); 94 | Map env = launcher.environment(); 95 | String LD_PATH=""; 96 | String WFDB_NATIVE_BIN=getWFDB_NATIVE_BIN(customArchFlag); 97 | String osName=getOsName(); 98 | String tmp="", pathSep=""; 99 | String OsPathName; 100 | if(osName.contains("windows")){ 101 | LD_PATH=env.get("Path");pathSep=";"; 102 | OsPathName="PATH"; 103 | tmp=WFDB_NATIVE_BIN + "bin" + pathSep + WFDB_NATIVE_BIN + "lib"; 104 | }else if(osName.contains("macosx")){ 105 | LD_PATH=env.get("DYLD_LIBRARY_PATH");pathSep=":"; 106 | OsPathName="DYLD_LIBRARY_PATH"; 107 | tmp=WFDB_NATIVE_BIN + "bin" + pathSep 108 | + WFDB_NATIVE_BIN + "lib64" + pathSep 109 | + WFDB_NATIVE_BIN + "lib"; 110 | }else{ 111 | LD_PATH=env.get("LD_LIBRARY_PATH");pathSep=":"; 112 | OsPathName="LD_LIBRARY_PATH"; 113 | tmp=WFDB_NATIVE_BIN + "bin" + pathSep 114 | + WFDB_NATIVE_BIN + "lib64" + pathSep 115 | + WFDB_NATIVE_BIN + "lib"; 116 | } 117 | 118 | if(LD_PATH == null){ 119 | LD_PATH=tmp; 120 | }else if(LD_PATH.indexOf(tmp) <0){ 121 | //Only add if path is not present already 122 | LD_PATH=tmp+pathSep+LD_PATH; 123 | } 124 | return LD_PATH; 125 | } 126 | 127 | public static int getNumberOfProcessors(){ 128 | return Runtime.getRuntime().availableProcessors(); 129 | } 130 | 131 | public static String getWFDB_JAVA_HOME(){ 132 | String packageDir = null; 133 | try { 134 | packageDir=URLDecoder.decode( 135 | Wfdbexec.class.getProtectionDomain().getCodeSource().getLocation().getPath(),"utf-8"); 136 | packageDir = new File(packageDir).getPath(); 137 | } catch (UnsupportedEncodingException e) { 138 | System.err.println("Could not get path location of WFDB JAR file."); 139 | e.printStackTrace(); 140 | } 141 | int tmp = packageDir.lastIndexOf(fsep); 142 | packageDir=packageDir.substring(0,tmp+1); 143 | packageDir=packageDir.replace("file:",""); 144 | return packageDir.toString(); 145 | } 146 | 147 | public synchronized static String getWFDB_NATIVE_BIN(boolean customArchFlag) { 148 | String WFDB_NATIVE_BIN; 149 | String WFDB_JAVA_HOME=getWFDB_JAVA_HOME(); 150 | //Set path to executables based on system/arch and customArchFlga 151 | if(customArchFlag){ 152 | WFDB_NATIVE_BIN= WFDB_JAVA_HOME+ "nativelibs" + fsep + "custom"+ fsep; 153 | }else{ 154 | WFDB_NATIVE_BIN= WFDB_JAVA_HOME+ "nativelibs" + fsep + 155 | getOsName().toLowerCase()+ fsep ; 156 | } 157 | return WFDB_NATIVE_BIN; 158 | } 159 | 160 | } 161 | -------------------------------------------------------------------------------- /src/org/physionet/wfdb/jni/Rdsamp.java: -------------------------------------------------------------------------------- 1 | /* Wrapper to Java Native Interface implementation of rdsamp.c : 2 | * 3 | *http://www.physionet.org/physiotools/wfdb/app/rdsamp.c 4 | * 5 | *The modification are done in order to make it compatible and 6 | *efficient when called through JNI. 7 | * 8 | *Created by Ikaro Silva 2015 9 | * 10 | * 11 | */ 12 | package org.physionet.wfdb.jni; 13 | 14 | public class Rdsamp { 15 | long nSamples; 16 | int[] baseline; 17 | double[] gain; 18 | double fs; 19 | int nsig; 20 | int[] rawData; 21 | String recordName; 22 | 23 | //Initialize enviroment 24 | static { 25 | org.physionet.wfdb.SystemSettings.loadLib("rdsampjni"); 26 | } 27 | 28 | public static void main(String[] args){ 29 | Rdsamp myRdsamp=new Rdsamp(); 30 | myRdsamp.readData(args); 31 | for(int i=0;i 0) 44 | { 45 | output.write(buffer, 0, n); 46 | } 47 | } 48 | output.close(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/org/physionet/wfdb/physiobank/PhysioNetRecord.java: -------------------------------------------------------------------------------- 1 | /* =========================================================== 2 | * WFDB Java : Interface to WFDB Applications. 3 | * 4 | * =========================================================== 5 | * 6 | * (C) Copyright 2012, by Ikaro Silva 7 | * 8 | * Project Info: 9 | * Code: http://code.google.com/p/wfdb-java/ 10 | * WFDB: http://www.physionet.org/physiotools/wfdb.shtml 11 | * 12 | * This program is free software: you can redistribute it and/or modify 13 | * it under the terms of the GNU Lesser General Public License as published by 14 | * the Free Software Foundation, either version 3 of the License, or 15 | * (at your option) any later version. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | * GNU Lesser General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU Lesser General Public License 23 | * along with this program. If not, see . 24 | * 25 | * 26 | * 27 | * Original Author: Ikaro Silva 28 | * Contributor(s): -; 29 | * 30 | * Changes 31 | * ------- 32 | * Check: http://code.google.com/p/wfdb-java/list 33 | */ 34 | 35 | package org.physionet.wfdb.physiobank; 36 | 37 | import java.util.ArrayList; 38 | import java.util.logging.Logger; 39 | import java.util.regex.Matcher; 40 | import java.util.regex.Pattern; 41 | 42 | import org.physionet.wfdb.Wfdbexec; 43 | 44 | public class PhysioNetRecord { 45 | 46 | private String name=new String(); 47 | private ArrayList signalStringList; 48 | private ArrayList signalList; 49 | private static Logger logger = 50 | Logger.getLogger(PhysioNetRecord.class.getName()); 51 | 52 | public PhysioNetRecord(String RecordName) throws Exception{ 53 | name=RecordName; 54 | signalStringList = new ArrayList(); 55 | signalList=new ArrayList(); 56 | setSignalList(); 57 | } 58 | 59 | public ArrayList getSignalStringList() { 60 | return signalStringList; 61 | } 62 | 63 | public void printRecord(){ 64 | for(PhysioNetSignal sig: signalList){ 65 | sig.printSignalInfo(); 66 | } 67 | } 68 | 69 | public void setSignalList() throws Exception{ 70 | setSignalList(null); 71 | } 72 | 73 | 74 | public void setSignalList(String descFilter) throws Exception { 75 | //Parse information from wfdbdesc to populate the record list 76 | String[] args=new String[1]; 77 | args[0]=name; 78 | Wfdbexec wfdbdesc = new Wfdbexec("wfdbdesc", Wfdbexec.customArchFlag); 79 | wfdbdesc.setArguments(args); 80 | logger.finest("\n\t***Executing wfdb command"); 81 | ArrayList tmpList= wfdbdesc.execToStringList(); 82 | String startTime=null; 83 | String lengthTime=null; 84 | String lengthSample=null; 85 | String samplingFrequency=null; 86 | PhysioNetSignal tmpSignal=null; 87 | 88 | //REGEXP Parsers 89 | String groupRegex="^Group (\\d+), Signal (\\d+):"; 90 | //Regex to parse something like: "Length: 30:05.556 (650000 sample intervals)" 91 | 92 | //TODO: find a way to make one single expression with optional day field 93 | String lengthRegex="Length:\\s+(\\d+:\\d+.\\d+)\\s+\\((\\d+)\\s+sample\\s+intervals\\)"; 94 | String lengthRegex2="Length:\\s+(\\d+:\\d+:\\d+.\\d+)\\s+\\((\\d+)\\s+sample\\s+intervals\\)"; 95 | 96 | Pattern groupPattern = Pattern.compile(groupRegex); 97 | Pattern lengthPattern = Pattern.compile(lengthRegex); 98 | Pattern lengthPattern2 = Pattern.compile(lengthRegex2); 99 | 100 | Matcher groupMatch=null; 101 | Matcher lengthMatch=null; 102 | 103 | logger.fine("parsing list, size= " + tmpList.size()); 104 | 105 | for(String i : tmpList){ 106 | logger.finest("parsing :" + i); 107 | if(i.startsWith("Starting time: ")){ 108 | startTime=i.replace("Starting time: ",""); 109 | } 110 | else if (i.startsWith("Length: ") && !(i.contains("Length: not specified")) ) { 111 | try{ 112 | //String should have a format similar to :Length: 30:05.556 (650000 sample intervals) 113 | lengthMatch=lengthPattern.matcher(i); 114 | if (!lengthMatch.find() ){ 115 | //Attempt second matcher for length 116 | lengthMatch=lengthPattern2.matcher(i); 117 | lengthMatch.find(); 118 | } 119 | if(! lengthMatch.group(1).isEmpty()) 120 | lengthTime=lengthMatch.group(1); 121 | if(! lengthMatch.group(2).isEmpty()) 122 | lengthSample=lengthMatch.group(2); 123 | } catch (IllegalStateException e){ 124 | System.err.println("Could not match : " +i ); 125 | System.err.println("Attempting to continue..."); 126 | } 127 | }else if (i.startsWith("Sampling frequency: ")) { 128 | samplingFrequency=i.replace("Sampling frequency: ",""); 129 | }else if (i.startsWith("Group ")) { 130 | if(tmpSignal != null){ 131 | if(descFilter == null){ 132 | signalList.add(tmpSignal); 133 | }else if(descFilter.equals(tmpSignal.getDescription())){ 134 | signalList.add(tmpSignal); 135 | } 136 | } 137 | tmpSignal=new PhysioNetSignal(signalList.size()+1,name); 138 | tmpSignal.setStartTime(startTime); 139 | tmpSignal.setLengthTime(lengthTime); 140 | tmpSignal.setLengthSamples(lengthSample); 141 | tmpSignal.setSamplingFrequency(samplingFrequency); 142 | 143 | groupMatch=groupPattern.matcher(i); 144 | groupMatch.find(); 145 | if(! groupMatch.group(1).isEmpty()) 146 | tmpSignal.setGroup(groupMatch.group(1)); 147 | if(! groupMatch.group(2).isEmpty()) 148 | tmpSignal.setSignalIndex(groupMatch.group(2)); 149 | 150 | }else if (i.startsWith(" File: ")) { 151 | tmpSignal.setFile(i.replace(" File: ","")); 152 | }else if (i.startsWith(" Description: ")) { 153 | tmpSignal.setDescription(i.replace(" Description: ","")); 154 | }else if (i.startsWith(" Gain: ")) { 155 | tmpSignal.setGain(i.replace(" Gain: ","")); 156 | }else if (i.startsWith(" Initial value: ")) { 157 | tmpSignal.setInitialValue(i.replace(" Initial value: ","")); 158 | }else if (i.startsWith(" Storage format: ")) { 159 | tmpSignal.setFormat(i.replace(" Storage format: ","")); 160 | }else if (i.startsWith(" I/O: ")) { 161 | tmpSignal.setIo(i.replace(" I/O: ","")); 162 | }else if (i.startsWith(" ADC resolution: ")) { 163 | tmpSignal.setAdcResolution(i.replace(" ADC resolution: ","")); 164 | }else if (i.startsWith(" ADC zero: ")) { 165 | tmpSignal.setAdcZero(i.replace(" ADC zero: ","")); 166 | }else if (i.startsWith(" Baseline: ")) { 167 | tmpSignal.setBaseline(i.replace(" Baseline: ","")); 168 | }else if (i.startsWith(" Checksum: ")) { 169 | tmpSignal.setCheckSum(i.replace(" Checksum: ","")); 170 | } 171 | } //end of for loop 172 | 173 | //Add last signal to list 174 | if(tmpSignal != null){ 175 | if(descFilter == null){ 176 | signalList.add(tmpSignal); 177 | }else if(descFilter.equals(tmpSignal.getDescription())){ 178 | signalList.add(tmpSignal); 179 | } 180 | } 181 | logger.fine("Done parsing!"); 182 | 183 | } 184 | 185 | public ArrayList getSignalList() { 186 | return signalList; 187 | } 188 | 189 | public String getRecordName(){ 190 | return name; 191 | } 192 | public static void main(String[] args) throws Exception { 193 | 194 | PhysioNetRecord re = new PhysioNetRecord(args[0]); 195 | ArrayList sg= re.getSignalList(); 196 | for(PhysioNetSignal mysig : sg) 197 | mysig.printSignalInfo(); 198 | } 199 | 200 | } 201 | -------------------------------------------------------------------------------- /src/org/physionet/wfdb/physiobank/PhysioNetSignal.java: -------------------------------------------------------------------------------- 1 | package org.physionet.wfdb.physiobank; 2 | 3 | 4 | 5 | public class PhysioNetSignal { 6 | 7 | private final String recordName; 8 | private Integer recordIndex=null; 9 | private String signalIndex=null; 10 | private String startTime=null; 11 | private String lengthTime=null; 12 | private String lengthSamples=null; 13 | private String samplingFrequency=null; 14 | private String Group=null; 15 | private String file=null; 16 | private String description=null; 17 | private String initialValue=null; 18 | private String gain=null; 19 | private String format=null; 20 | private String io=null; 21 | private String adcResolution=null; 22 | private String adcZero=null; 23 | private String baseline=null; 24 | private String checkSum=null; 25 | private double[][] data=null; //data in physical units 26 | 27 | //TODO: Consider overriding equals() and hashcode! 28 | 29 | public PhysioNetSignal(Integer mrecordIndex, String mrecName){ 30 | setRecordIndex(mrecordIndex); 31 | recordName=mrecName; 32 | } 33 | 34 | public PhysioNetSignal(String mrecName){ 35 | recordName=mrecName; 36 | } 37 | 38 | public void printSignalInfo(){ 39 | System.out.println("DB/Record Name: " + recordName); 40 | System.out.println("\tRecord/Signal Index: " + recordIndex + "/" + signalIndex); 41 | System.out.println("\tGroup: " + Group); 42 | System.out.println("\tStart Time:\t\t" + startTime); 43 | System.out.println("\tLength Time:\t\t" + lengthTime); 44 | System.out.println("\tNumber of Samples:\t" + lengthSamples); 45 | System.out.println("\tSampling Frequency:\t" + samplingFrequency); 46 | System.out.println("\tFile:\t\t\t" + file); 47 | System.out.println("\tDescription:\t\t" + description); 48 | System.out.println("\tInitial Value:\t\t" + initialValue); 49 | System.out.println("\tGain:\t\t\t" + gain); 50 | System.out.println("\tFormat:\t\t\t" + format); 51 | System.out.println("\tI\\O:\t\t\t" + io); 52 | System.out.println("\tADC Resolution:\t\t" + adcResolution); 53 | System.out.println("\tADC Zero:\t\t" + adcZero); 54 | System.out.println("\tBaseline:\t\t" + baseline); 55 | System.out.println("\tChecksum:\t\t" + checkSum); 56 | 57 | } 58 | 59 | /* 60 | public void loadPhysicalData(){ 61 | //Calls RDSAMP to get data for this signal 62 | Rdsamp rdsampexec = new Rdsamp(); 63 | rdsampexec.setArgumentValue(Rdsamp.Arguments.stopTime, "s10"); 64 | rdsampexec.setArgumentValue(Rdsamp.PrintTimeFormatLabel.p); 65 | rdsampexec.setArgumentValue(Rdsamp.Arguments.signalList, 66 | "[1]"); 67 | rdsampexec.setArgumentValue(Rdsamp.Arguments.recordName, 68 | dbName + "/" + recName); 69 | try { 70 | data=rdsampexec.execToDoubleArray(); 71 | }catch (Exception e){ 72 | System.err.println("Could not load data for signal: " + 73 | recName); 74 | e.printStackTrace(); 75 | } 76 | 77 | } 78 | */ 79 | 80 | public double[][] getPhysicalData(){ 81 | return data; 82 | } 83 | 84 | public String getRecordName() { 85 | return recordName; 86 | } 87 | 88 | public Integer getRecordIndex() { 89 | return recordIndex; 90 | } 91 | 92 | public void setRecordIndex(Integer recordIndex) { 93 | this.recordIndex = recordIndex; 94 | } 95 | 96 | public String getStartTime() { 97 | return startTime; 98 | } 99 | 100 | public void setStartTime(String startTime) { 101 | this.startTime = startTime; 102 | } 103 | 104 | public String getLengthTime() { 105 | return lengthTime; 106 | } 107 | 108 | public void setLengthTime(String lengthTime) { 109 | this.lengthTime = lengthTime; 110 | } 111 | 112 | public String getLengthSamples() { 113 | return lengthSamples; 114 | } 115 | 116 | public void setLengthSamples(String lengthSample) { 117 | this.lengthSamples = lengthSample; 118 | } 119 | 120 | public String getSamplingFrequency() { 121 | return samplingFrequency; 122 | } 123 | 124 | public void setSamplingFrequency(String samplingFrequency) { 125 | this.samplingFrequency = samplingFrequency; 126 | } 127 | 128 | public String getGroup() { 129 | return Group; 130 | } 131 | 132 | public void setGroup(String group) { 133 | Group = group; 134 | } 135 | 136 | public String getFile() { 137 | return file; 138 | } 139 | 140 | public void setFile(String file) { 141 | this.file = file; 142 | } 143 | 144 | public String getInitialValue() { 145 | return initialValue; 146 | } 147 | 148 | public void setInitialValue(String initialValue) { 149 | this.initialValue = initialValue; 150 | } 151 | 152 | public String getDescription() { 153 | return description; 154 | } 155 | 156 | public void setDescription(String description) { 157 | this.description = description; 158 | } 159 | 160 | public String getFormat() { 161 | return format; 162 | } 163 | 164 | public void setFormat(String format) { 165 | this.format = format; 166 | } 167 | 168 | public String getGain() { 169 | return gain; 170 | } 171 | 172 | public void setGain(String gain) { 173 | this.gain = gain; 174 | } 175 | 176 | public String getAdcResolution() { 177 | return adcResolution; 178 | } 179 | 180 | public void setAdcResolution(String adcResolution) { 181 | this.adcResolution = adcResolution; 182 | } 183 | 184 | public String getIo() { 185 | return io; 186 | } 187 | 188 | public void setIo(String io) { 189 | this.io = io; 190 | } 191 | 192 | public String getAdcZero() { 193 | return adcZero; 194 | } 195 | 196 | public void setAdcZero(String adcZero) { 197 | this.adcZero = adcZero; 198 | } 199 | 200 | public String getBaseline() { 201 | return baseline; 202 | } 203 | 204 | public void setBaseline(String baseline) { 205 | this.baseline = baseline; 206 | } 207 | 208 | public String getCheckSum() { 209 | return checkSum; 210 | } 211 | 212 | public void setCheckSum(String checksum) { 213 | this.checkSum = checksum; 214 | } 215 | 216 | public String getSignalIndex() { 217 | return signalIndex; 218 | } 219 | 220 | public void setSignalIndex(String string) { 221 | this.signalIndex = string; 222 | } 223 | 224 | } 225 | -------------------------------------------------------------------------------- /wsm-matlab-code-Manifest.txt: -------------------------------------------------------------------------------- 1 | Name: wfdb-app-matlab-code 2 | Specification-Title: WFDB Java App 3 | Specification-Version: 0.9.10 4 | Specification-Vendor: PhysioNet 5 | 6 | 7 | -------------------------------------------------------------------------------- /zipexclude.lst: -------------------------------------------------------------------------------- 1 | *.settings 2 | *.project 3 | *\*.svn\* 4 | *.class 5 | *.jdb 6 | *.id 7 | *.lck 8 | mcode/mxm.m 9 | mcode/challenge/* 10 | mcode/slpdb/* 11 | mcode/*~ 12 | mcode/.__afs* 13 | mcode/nativelibs/*.c 14 | mcode/nativelibs/*.tar.gz 15 | mcode/nativelibs/*/build/* 16 | mcode/nativelibs/*/include/* 17 | mcode/nativelibs/*/database/* 18 | mcode/nativelibs/*/share/* 19 | mcode/nativelibs/*/man/* 20 | mcode/nativelibs/custom/bin/* 21 | mcode/nativelibs/custom/lib/* 22 | mcode/nativelibs/macosx/i686/* 23 | mcode/nativelibs/macosx/x86_64/* 24 | mcode/*.wav 25 | --------------------------------------------------------------------------------