diff -Naur wfdb-10.1.6/INSTALL wfdb-10.2.0/INSTALL --- wfdb-10.1.6/INSTALL Mon Jun 5 16:18:20 2000 +++ wfdb-10.2.0/INSTALL Thu Sep 6 15:14:25 2001 @@ -1,6 +1,12 @@ file: INSTALL G. Moody 30 January 2000 - Last revised: 5 June 2000 + Last revised: 6 September 2001 WFDB Software Package installation notes + +These notes are included here for those who may not have ready access to the +World Wide Web. For those who do, please visit PhysioNet, where quick-start +guides including installation notes for popular operating systems are available +(see http://www.physionet.org/physiotools/wfdb.shtml). + _______________________________________________________________________________ Under UNIX or Linux: @@ -24,13 +30,12 @@ /usr/local/help/html/wug if you wish to read the help from local files; otherwise, edit wave/wave.info and change all occurrences of '/usr/local/help/html/' into 'http://www.physionet.org/physiotools/wug/'. - (The utility 'wget' -- which you can find with a web search -- can be - helpful if you wish to copy an entire directory of a web site, as suggested + (The utility 'wget' -- which you can find on PhysioNet -- can be helpful + if you wish to copy an entire directory of a web site, as suggested here.) 3. In this directory, type: ./configure - make make install You will need root permissions to run 'make install', unless you change WFDBROOT so that the files are installed in a directory that you own (you @@ -40,35 +45,52 @@ make uninstall from this directory. You will need root permissions to uninstall unless you changed WFDBROOT before installing the package. + _______________________________________________________________________________ -Under MS-DOS or MS-Windows: +Under MS-Windows: -If possible, use djgpp (DJ Delorie's MS-DOS port of gcc, free from -http://www.delorie.com/djgpp/) or cygwin (Cygnus Software's MS-Windows port of -gcc, free from http://sourceware.cygnus.com/cygwin/). Both of these include -many of the GNU utilities, including GNU make. In this directory, type: - make -f Makefile-dos-gcc - -If you are using an older version of MS-DOS that cannot handle long filenames, -you will need to rename the 'Makefile-dos-gcc' files here and in each of the -subdirectories, and then you will need to edit the one in this directory to -change each reference to 'Makefile-dos-gcc' appropriately. - -If you use cygwin, please try to download and install the libwww package, from -http://www.physionet.org/physiotools/libwww/, or from the W3C's web site at -http://www.w3.org/Library), and modify lib/Makefile-dos-gcc so that libwww will -be linked together with the WFDB library. Instructions for compiling libwww -with cygwin are provided in the sources and at http://www.w3.org/INSTALL.html. -This should work but has not yet been tested; please let me know what changes -are needed. (Details will be posted on PhysioNet once they are available.) - -The 'Makefile.dos' files in each of the subdirectories of this one (except for -wave, wave-doc, and waverc, which are for UNIX only) can be used with the -'make' utilities provided with most commercial C compilers, although you may -need to customize them for your compiler; your feedback is appreciated. A -version of libwww for MSVC++ 5.0 is available from PhysioNet and from the W3C -web site. If you don't have a 'make' utility, try djgpp or cygwin. +1. If you have not already done so, install the Cygwin development environment + (freely available from http://sources.redhat.com/cygwin/). This includes + gcc (the GNU C/C++ compiler) as well as a comprehensive assortment of other + Unix utilities ported to MS-Windows. Accept the defaults suggested by the + installer. + + IMPORTANT: Although you may be able to compile the WFDB software package + using a proprietary compiler, this is NOT SUPPORTED. The 'Makefile.dos' + files in several of the subdirectories of this one can be used with the + 'make' utilities provided with most commercial C compilers, although you + will need to customize them for your compiler. Your feedback is appreciated. + +2. Download http://www.physionet.org/physiotools/binaries/windows/bin/which.exe + and put it into a directory in your PATH. (This utility is needed by + 'configure' in a later step. The sources for which.exe are available within + http://www.physionet.org/physiotools/utilities/.) + +3. Open a Cygwin terminal window (the Cygwin installer will have added this to + your MS-Windows start menu). Check that 'which' and 'gcc' are accessible by + typing the command: + which gcc + The output of this command should be: + /usr/bin/gcc + If you don't see this output, repeat steps 1 and 2 above as necessary to + correct the problem before continuing. + +4. Install the World Wide Web Consortium's libwww library (you will need both + the library itself and the developer's package; download them from + http://www.physionet.org/physiotools/libwww/, or from the W3C's web site + at http://www.w3.org/Library). You may skip this step if you don't want + support for reading input files from remote web and FTP servers. See + README.NETFILES for further information about this option. + +5. In this directory (the top-level directory of the WFDB software package, + containing the file you are now reading), type: + ./configure + make install + +6. If for any reason you wish to uninstall the WFDB Software Package, type: + make uninstall + from this directory. _______________________________________________________________________________ @@ -79,6 +101,10 @@ users (and on VMS, among other environments). The sources are written in highly portable C and should not be difficult to port to any environment where an ANSI/ISO or K&R C compiler and the standard C library are available. + +Several users have reported that the WFDB library and the applications in the +'app' directory can be compiled successfully using cc (gcc) under MacOS/X +(Darwin). If you find that changes are necessary in order to compile this software successfully, please send details to the author (george@mit.edu) so that diff -Naur wfdb-10.1.6/MANIFEST wfdb-10.2.0/MANIFEST --- wfdb-10.1.6/MANIFEST Sat Jul 28 13:25:22 2001 +++ wfdb-10.2.0/MANIFEST Mon Oct 15 16:20:26 2001 @@ -1,526 +1,583 @@ -wfdb-10.1.6/ -wfdb-10.1.6/app/ -wfdb-10.1.6/app/12lead.pro -wfdb-10.1.6/app/ann2rr.c -wfdb-10.1.6/app/bxb.c -wfdb-10.1.6/app/calsig.c -wfdb-10.1.6/app/cshsetwfdb -wfdb-10.1.6/app/ecgeval.c -wfdb-10.1.6/app/epic.c -wfdb-10.1.6/app/fir.c -wfdb-10.1.6/app/ihr.c -wfdb-10.1.6/app/Makefile -wfdb-10.1.6/app/Makefile.dos -wfdb-10.1.6/app/Makefile-dos-gcc -wfdb-10.1.6/app/Makefile.top -wfdb-10.1.6/app/Makefile.tpl -wfdb-10.1.6/app/mfilt.c -wfdb-10.1.6/app/mrgann.c -wfdb-10.1.6/app/mxm.c -wfdb-10.1.6/app/nst.c -wfdb-10.1.6/app/plotstm.c -wfdb-10.1.6/app/pscgen.c -wfdb-10.1.6/app/pschart.c -wfdb-10.1.6/app/pschart.pro -wfdb-10.1.6/app/psfd.c -wfdb-10.1.6/app/psfd.pro -wfdb-10.1.6/app/rdann.c -wfdb-10.1.6/app/rdsamp.c -wfdb-10.1.6/app/README -wfdb-10.1.6/app/rr2ann.c -wfdb-10.1.6/app/rxr.c -wfdb-10.1.6/app/sampfreq.c -wfdb-10.1.6/app/sample8.hea -wfdb-10.1.6/app/sample.c -wfdb-10.1.6/app/setwfdb -wfdb-10.1.6/app/setwfdb.bat -wfdb-10.1.6/app/sigamp.c -wfdb-10.1.6/app/skewedit.c -wfdb-10.1.6/app/snip.c -wfdb-10.1.6/app/sortann.c -wfdb-10.1.6/app/sqrs125.c -wfdb-10.1.6/app/sqrs.c -wfdb-10.1.6/app/sumann.c -wfdb-10.1.6/app/sumstats.c -wfdb-10.1.6/app/tach.c -wfdb-10.1.6/app/view.c -wfdb-10.1.6/app/vsetup.c -wfdb-10.1.6/app/wfdbcat.c -wfdb-10.1.6/app/wfdbcollate.c -wfdb-10.1.6/app/wfdbdesc.c -wfdb-10.1.6/app/wfdbwhich.c -wfdb-10.1.6/app/wrann.c -wfdb-10.1.6/app/wrsamp.c -wfdb-10.1.6/app/wvscript.c -wfdb-10.1.6/app/xform.c -wfdb-10.1.6/check-manifest -wfdb-10.1.6/conf/ -wfdb-10.1.6/conf/cygwin.def -wfdb-10.1.6/conf/exestrip -wfdb-10.1.6/conf/generic.def -wfdb-10.1.6/conf/generic-slib.def -wfdb-10.1.6/conf/hpux.def -wfdb-10.1.6/conf/hpux-slib.def -wfdb-10.1.6/configure -wfdb-10.1.6/conf/linux.def -wfdb-10.1.6/conf/linux-slib.def -wfdb-10.1.6/conf/solaris.def -wfdb-10.1.6/conf/solaris-slib.def -wfdb-10.1.6/conf/version.def -wfdb-10.1.6/convert/ -wfdb-10.1.6/convert/a2m.c -wfdb-10.1.6/convert/ad2m.c -wfdb-10.1.6/convert/edf2mit.c -wfdb-10.1.6/convert/m2a.c -wfdb-10.1.6/convert/Makefile -wfdb-10.1.6/convert/Makefile.dos -wfdb-10.1.6/convert/Makefile-dos-gcc -wfdb-10.1.6/convert/Makefile.top -wfdb-10.1.6/convert/Makefile.tpl -wfdb-10.1.6/convert/makeid.c -wfdb-10.1.6/convert/md2a.c -wfdb-10.1.6/convert/readid.c -wfdb-10.1.6/convert/README -wfdb-10.1.6/convert/revise.c -wfdb-10.1.6/COPYING -wfdb-10.1.6/data/ -wfdb-10.1.6/data/100s.atr -wfdb-10.1.6/data/100s.dat -wfdb-10.1.6/data/100s.hea -wfdb-10.1.6/data/16.hea -wfdb-10.1.6/data/16l.hea -wfdb-10.1.6/data/16x10.hea -wfdb-10.1.6/data/16x11.hea -wfdb-10.1.6/data/16x12.hea -wfdb-10.1.6/data/16x13.hea -wfdb-10.1.6/data/16x14.hea -wfdb-10.1.6/data/16x15.hea -wfdb-10.1.6/data/16x16.hea -wfdb-10.1.6/data/16x1.hea -wfdb-10.1.6/data/16x2.hea -wfdb-10.1.6/data/16x3.hea -wfdb-10.1.6/data/16x4.hea -wfdb-10.1.6/data/16x5.hea -wfdb-10.1.6/data/16x6.hea -wfdb-10.1.6/data/16x7.hea -wfdb-10.1.6/data/16x8.hea -wfdb-10.1.6/data/16x9.hea -wfdb-10.1.6/data/8.hea -wfdb-10.1.6/data/8l.hea -wfdb-10.1.6/data/8x10.hea -wfdb-10.1.6/data/8x11.hea -wfdb-10.1.6/data/8x12.hea -wfdb-10.1.6/data/8x13.hea -wfdb-10.1.6/data/8x14.hea -wfdb-10.1.6/data/8x15.hea -wfdb-10.1.6/data/8x16.hea -wfdb-10.1.6/data/8x1.hea -wfdb-10.1.6/data/8x2.hea -wfdb-10.1.6/data/8x3.hea -wfdb-10.1.6/data/8x4.hea -wfdb-10.1.6/data/8x5.hea -wfdb-10.1.6/data/8x6.hea -wfdb-10.1.6/data/8x7.hea -wfdb-10.1.6/data/8x8.hea -wfdb-10.1.6/data/8x9.hea -wfdb-10.1.6/data/ahalist -wfdb-10.1.6/data/ahatape.hea -wfdb-10.1.6/data/ahaxlist -wfdb-10.1.6/data/b.hea -wfdb-10.1.6/data/culist -wfdb-10.1.6/data/dblist -wfdb-10.1.6/data/esclist -wfdb-10.1.6/data/Makefile -wfdb-10.1.6/data/Makefile.dos -wfdb-10.1.6/data/Makefile-dos-gcc -wfdb-10.1.6/data/Makefile.top -wfdb-10.1.6/data/Makefile.tpl -wfdb-10.1.6/data/mitlist -wfdb-10.1.6/data/mittape.hea -wfdb-10.1.6/data/mitxlist -wfdb-10.1.6/data/multi.hea -wfdb-10.1.6/data/nstlist -wfdb-10.1.6/data/null.hea -wfdb-10.1.6/data/README -wfdb-10.1.6/data/t10240.hea -wfdb-10.1.6/data/t1024.hea -wfdb-10.1.6/data/t4096.hea -wfdb-10.1.6/data/t512.hea -wfdb-10.1.6/data/wfdbcal -wfdb-10.1.6/data/wfdbpath.mac -wfdb-10.1.6/doc/ -wfdb-10.1.6/doc/a2m.1 -wfdb-10.1.6/doc/ann2rr.1 -wfdb-10.1.6/doc/annot.5 -wfdb-10.1.6/doc/appguide.int -wfdb-10.1.6/doc/bxb.1 -wfdb-10.1.6/doc/calsig.1 -wfdb-10.1.6/doc/coherence.1 -wfdb-10.1.6/doc/cover.ag -wfdb-10.1.6/doc/cover.pg -wfdb-10.1.6/doc/dbag.ht0 -wfdb-10.1.6/doc/dbag.tex -wfdb-10.1.6/doc/dbu.hlp -wfdb-10.1.6/doc/dbu.ht0 -wfdb-10.1.6/doc/dbu.tex -wfdb-10.1.6/doc/dir.db -wfdb-10.1.6/doc/dir.top -wfdb-10.1.6/doc/ecgeval.1 -wfdb-10.1.6/doc/epic.1 -wfdb-10.1.6/doc/eval.tex -wfdb-10.1.6/doc/fft.1 -wfdb-10.1.6/doc/fir.1 -wfdb-10.1.6/doc/fixag.sed -wfdb-10.1.6/doc/fixag.sh -wfdb-10.1.6/doc/fixpg.sed -wfdb-10.1.6/doc/fixpg.sh -wfdb-10.1.6/doc/foot.ht0 -wfdb-10.1.6/doc/header.5 -wfdb-10.1.6/doc/hrfft.1 -wfdb-10.1.6/doc/icons/ -wfdb-10.1.6/doc/icons/contents.png -wfdb-10.1.6/doc/icons/cross_ref.png -wfdb-10.1.6/doc/icons/foot.png -wfdb-10.1.6/doc/icons/next_gr.png -wfdb-10.1.6/doc/icons/next.png -wfdb-10.1.6/doc/icons/prev_gr.png -wfdb-10.1.6/doc/icons/previous.png -wfdb-10.1.6/doc/icons/up_gr.png -wfdb-10.1.6/doc/icons/up.png -wfdb-10.1.6/doc/ihr.1 -wfdb-10.1.6/doc/index.ht0 -wfdb-10.1.6/doc/install.tex -wfdb-10.1.6/doc/intro.ht0 -wfdb-10.1.6/doc/.latex2html-init -wfdb-10.1.6/doc/log10.1 -wfdb-10.1.6/doc/lomb.1 -wfdb-10.1.6/doc/Makefile -wfdb-10.1.6/doc/Makefile.top -wfdb-10.1.6/doc/Makefile.tpl -wfdb-10.1.6/doc/makeinfo.sh -wfdb-10.1.6/doc/manhtml.sh -wfdb-10.1.6/doc/maninst.sh -wfdb-10.1.6/doc/memse.1 -wfdb-10.1.6/doc/mfilt.1 -wfdb-10.1.6/doc/mrgann.1 -wfdb-10.1.6/doc/mxm.1 -wfdb-10.1.6/doc/nst.1 -wfdb-10.1.6/doc/plot2d.1 -wfdb-10.1.6/doc/plotstm.1 -wfdb-10.1.6/doc/pschart.1 -wfdb-10.1.6/doc/psfd.1 -wfdb-10.1.6/doc/rdann.1 -wfdb-10.1.6/doc/rdsamp.1 -wfdb-10.1.6/doc/README -wfdb-10.1.6/doc/rxr.1 -wfdb-10.1.6/doc/sampfreq.1 -wfdb-10.1.6/doc/sample.1 -wfdb-10.1.6/doc/setwfdb.1 -wfdb-10.1.6/doc/sigamp.1 -wfdb-10.1.6/doc/signal.5 -wfdb-10.1.6/doc/skewedit.1 -wfdb-10.1.6/doc/snip.1 -wfdb-10.1.6/doc/sortann.1 -wfdb-10.1.6/doc/sqrs.1 -wfdb-10.1.6/doc/sumann.1 -wfdb-10.1.6/doc/sumstats.1 -wfdb-10.1.6/doc/tach.1 -wfdb-10.1.6/doc/texi2html -wfdb-10.1.6/doc/texindex.c -wfdb-10.1.6/doc/tmac.dif -wfdb-10.1.6/doc/view.1 -wfdb-10.1.6/doc/wave.1 -wfdb-10.1.6/doc/wfdb.3 -wfdb-10.1.6/doc/wfdbcal.5 -wfdb-10.1.6/doc/wfdbcat.1 -wfdb-10.1.6/doc/wfdbcollate.1 -wfdb-10.1.6/doc/wfdbdesc.1 -wfdb-10.1.6/doc/wfdbwhich.1 -wfdb-10.1.6/doc/wrann.1 -wfdb-10.1.6/doc/wrsamp.1 -wfdb-10.1.6/doc/wview.1 -wfdb-10.1.6/doc/xform.1 -wfdb-10.1.6/examples/ -wfdb-10.1.6/examples/dblibver.c -wfdb-10.1.6/examples/example10.c -wfdb-10.1.6/examples/example1.c -wfdb-10.1.6/examples/example2.c -wfdb-10.1.6/examples/example3.c -wfdb-10.1.6/examples/example4.c -wfdb-10.1.6/examples/example5.c -wfdb-10.1.6/examples/example6.c -wfdb-10.1.6/examples/example7.c -wfdb-10.1.6/examples/example8.c -wfdb-10.1.6/examples/example9.c -wfdb-10.1.6/examples/exannstr.c -wfdb-10.1.6/examples/exgetvec.c -wfdb-10.1.6/examples/exputvec.c -wfdb-10.1.6/examples/Makefile -wfdb-10.1.6/examples/Makefile.dos -wfdb-10.1.6/examples/Makefile-dos-gcc -wfdb-10.1.6/examples/Makefile.top -wfdb-10.1.6/examples/Makefile.tpl -wfdb-10.1.6/examples/psamples.c -wfdb-10.1.6/examples/README -wfdb-10.1.6/examples/refhr.c -wfdb-10.1.6/fortran/ -wfdb-10.1.6/fortran/example.f -wfdb-10.1.6/fortran/Makefile -wfdb-10.1.6/fortran/README -wfdb-10.1.6/fortran/wfdbf.c -wfdb-10.1.6/INSTALL -wfdb-10.1.6/install.sh -wfdb-10.1.6/lib/ -wfdb-10.1.6/lib/annot.c -wfdb-10.1.6/lib/calib.c -wfdb-10.1.6/lib/COPYING.LIB -wfdb-10.1.6/lib/db.h -wfdb-10.1.6/lib/ecgcodes.h -wfdb-10.1.6/lib/ecgmap.h -wfdb-10.1.6/lib/Makefile -wfdb-10.1.6/lib/Makefile.dos -wfdb-10.1.6/lib/Makefile-dos-gcc -wfdb-10.1.6/lib/Makefile.top -wfdb-10.1.6/lib/Makefile.tpl -wfdb-10.1.6/lib/makelib -wfdb-10.1.6/lib/README -wfdb-10.1.6/lib/signal.c -wfdb-10.1.6/lib/twfdbdll.def -wfdb-10.1.6/lib/wfdbdll.def -wfdb-10.1.6/lib/wfdb.h -wfdb-10.1.6/lib/wfdbinit.c -wfdb-10.1.6/lib/wfdbio.c -wfdb-10.1.6/lib/wfdblib.h -wfdb-10.1.6/Makefile -wfdb-10.1.6/Makefile.top -wfdb-10.1.6/Makefile.tpl -wfdb-10.1.6/MANIFEST -wfdb-10.1.6/psd/ -wfdb-10.1.6/psd/coherence.c -wfdb-10.1.6/psd/fft.c -wfdb-10.1.6/psd/hrfft -wfdb-10.1.6/psd/hrlomb -wfdb-10.1.6/psd/hrmem -wfdb-10.1.6/psd/hrplot -wfdb-10.1.6/psd/log10.c -wfdb-10.1.6/psd/lomb.c -wfdb-10.1.6/psd/Makefile -wfdb-10.1.6/psd/Makefile.dos -wfdb-10.1.6/psd/Makefile-dos-gcc -wfdb-10.1.6/psd/Makefile.top -wfdb-10.1.6/psd/Makefile.tpl -wfdb-10.1.6/psd/memse.c -wfdb-10.1.6/psd/plot2d -wfdb-10.1.6/psd/plot3d -wfdb-10.1.6/psd/README -wfdb-10.1.6/README -wfdb-10.1.6/README.NETFILES -wfdb-10.1.6/uninstall.sh -wfdb-10.1.6/wave/ -wfdb-10.1.6/wave/analysis.hlp -wfdb-10.1.6/wave/analyze.c -wfdb-10.1.6/wave/annot.c -wfdb-10.1.6/wave/annpan.c -wfdb-10.1.6/wave/anntab -wfdb-10.1.6/wave/bitmaps.h -wfdb-10.1.6/wave/buttons.hlp -wfdb-10.1.6/wave/demo.txt -wfdb-10.1.6/wave-doc/ -wfdb-10.1.6/wave-doc/color/ -wfdb-10.1.6/wave-doc/color/allow-edit.ps -wfdb-10.1.6/wave-doc/color/calibrate.ps -wfdb-10.1.6/wave-doc/color/file-analyze.ps -wfdb-10.1.6/wave-doc/color/file-load.ps -wfdb-10.1.6/wave-doc/color/file-print.ps -wfdb-10.1.6/wave-doc/color/file-save.ps -wfdb-10.1.6/wave-doc/color/find-window.ps -wfdb-10.1.6/wave-doc/color/help-topics.ps -wfdb-10.1.6/wave-doc/color/level-window.ps -wfdb-10.1.6/wave-doc/color/main-control-panel.ps -wfdb-10.1.6/wave-doc/color/main-window.ps -wfdb-10.1.6/wave-doc/color/main-with-hr.ps -wfdb-10.1.6/wave-doc/color/main-with-markers.ps -wfdb-10.1.6/wave-doc/color/Makefile -wfdb-10.1.6/wave-doc/color/mimic.ps -wfdb-10.1.6/wave-doc/color/netscape-new-helper.ps -wfdb-10.1.6/wave-doc/color/print-setup-window.ps -wfdb-10.1.6/wave-doc/color/scope-window.ps -wfdb-10.1.6/wave-doc/color/search-template.ps -wfdb-10.1.6/wave-doc/color/stdev.ps -wfdb-10.1.6/wave-doc/color/titlebar.ps -wfdb-10.1.6/wave-doc/color/title-with-parens.ps -wfdb-10.1.6/wave-doc/color/type-menu.ps -wfdb-10.1.6/wave-doc/color/wave-icon.ps -wfdb-10.1.6/wave-doc/color/wave-menu.ps -wfdb-10.1.6/wave-doc/grey/ -wfdb-10.1.6/wave-doc/grey/allow-edit.ps -wfdb-10.1.6/wave-doc/grey/analysis-commands.ps -wfdb-10.1.6/wave-doc/grey/analyze-window.ps -wfdb-10.1.6/wave-doc/grey/annotation-template.ps -wfdb-10.1.6/wave-doc/grey/attach-to-signals.ps -wfdb-10.1.6/wave-doc/grey/calibrate.ps -wfdb-10.1.6/wave-doc/grey/chart1.ps -wfdb-10.1.6/wave-doc/grey/chart2.ps -wfdb-10.1.6/wave-doc/grey/file-analyze.ps -wfdb-10.1.6/wave-doc/grey/file-load.ps -wfdb-10.1.6/wave-doc/grey/file-print.ps -wfdb-10.1.6/wave-doc/grey/file-save.ps -wfdb-10.1.6/wave-doc/grey/find-window.ps -wfdb-10.1.6/wave-doc/grey/fulldisc.ps -wfdb-10.1.6/wave-doc/grey/help-intro.ps -wfdb-10.1.6/wave-doc/grey/help-topics.ps -wfdb-10.1.6/wave-doc/grey/level-window.ps -wfdb-10.1.6/wave-doc/grey/load-window.ps -wfdb-10.1.6/wave-doc/grey/log-window.ps -wfdb-10.1.6/wave-doc/grey/main-control-panel.ps -wfdb-10.1.6/wave-doc/grey/main-window.ps -wfdb-10.1.6/wave-doc/grey/main-with-hr.ps -wfdb-10.1.6/wave-doc/grey/main-with-markers.ps -wfdb-10.1.6/wave-doc/grey/Makefile -wfdb-10.1.6/wave-doc/grey/mimic.ps -wfdb-10.1.6/wave-doc/grey/netscape-new-helper.ps -wfdb-10.1.6/wave-doc/grey/noedit.ps -wfdb-10.1.6/wave-doc/grey/nomatch.ps -wfdb-10.1.6/wave-doc/grey/notice-quit.ps -wfdb-10.1.6/wave-doc/grey/print-setup-window.ps -wfdb-10.1.6/wave-doc/grey/scope-window.ps -wfdb-10.1.6/wave-doc/grey/search-template.ps -wfdb-10.1.6/wave-doc/grey/spot-help.ps -wfdb-10.1.6/wave-doc/grey/stdev.ps -wfdb-10.1.6/wave-doc/grey/system-menu.ps -wfdb-10.1.6/wave-doc/grey/titlebar.ps -wfdb-10.1.6/wave-doc/grey/title-with-parens.ps -wfdb-10.1.6/wave-doc/grey/type-menu.ps -wfdb-10.1.6/wave-doc/grey/view-window.ps -wfdb-10.1.6/wave-doc/grey/wave-icon.ps -wfdb-10.1.6/wave-doc/grey/wave-menu.ps -wfdb-10.1.6/wave-doc/guide/ -wfdb-10.1.6/wave-doc/guide/chart2.png -wfdb-10.1.6/wave-doc/guide/cover.wug -wfdb-10.1.6/wave-doc/guide/dossify-html -wfdb-10.1.6/wave-doc/guide/example.xws -wfdb-10.1.6/wave-doc/guide/fancybox.perl -wfdb-10.1.6/wave-doc/guide/fixindex -wfdb-10.1.6/wave-doc/guide/fixinfo -wfdb-10.1.6/wave-doc/guide/fixlinks -wfdb-10.1.6/wave-doc/guide/fulldisc.png -wfdb-10.1.6/wave-doc/guide/html.sty -wfdb-10.1.6/wave-doc/guide/icons/ -wfdb-10.1.6/wave-doc/guide/icons/contents.png -wfdb-10.1.6/wave-doc/guide/icons/cross_ref.png -wfdb-10.1.6/wave-doc/guide/icons/foot.png -wfdb-10.1.6/wave-doc/guide/icons/index.png -wfdb-10.1.6/wave-doc/guide/icons/next_gr.png -wfdb-10.1.6/wave-doc/guide/icons/next.png -wfdb-10.1.6/wave-doc/guide/icons/prev_gr.png -wfdb-10.1.6/wave-doc/guide/icons/previous.png -wfdb-10.1.6/wave-doc/guide/icons/up_gr.png -wfdb-10.1.6/wave-doc/guide/icons/up.png -wfdb-10.1.6/wave-doc/guide/icons/wave.png -wfdb-10.1.6/wave-doc/guide/.latex2html-init -wfdb-10.1.6/wave-doc/guide/Makefile -wfdb-10.1.6/wave-doc/guide/manhtml -wfdb-10.1.6/wave-doc/guide/saveroot -wfdb-10.1.6/wave-doc/guide/savewin -wfdb-10.1.6/wave-doc/guide/stdev.c -wfdb-10.1.6/wave-doc/guide/wave2d -wfdb-10.1.6/wave-doc/guide/wug.tex -wfdb-10.1.6/wave-doc/guide/xview.7 -wfdb-10.1.6/wave-doc/guide/xwdtops -wfdb-10.1.6/wave-doc/guide/xwdtops-grey -wfdb-10.1.6/wave-doc/Makefile -wfdb-10.1.6/wave-doc/ppm/ -wfdb-10.1.6/wave-doc/ppm/allow-edit.ppm.gz -wfdb-10.1.6/wave-doc/ppm/attach-to-signals.ppm.gz -wfdb-10.1.6/wave-doc/ppm/calibrate.ppm.gz -wfdb-10.1.6/wave-doc/ppm/file-analyze.ppm.gz -wfdb-10.1.6/wave-doc/ppm/file-load.ppm.gz -wfdb-10.1.6/wave-doc/ppm/file-print.ppm.gz -wfdb-10.1.6/wave-doc/ppm/file-save.ppm.gz -wfdb-10.1.6/wave-doc/ppm/find-window.ppm.gz -wfdb-10.1.6/wave-doc/ppm/help-topics.ppm.gz -wfdb-10.1.6/wave-doc/ppm/level-window.ppm.gz -wfdb-10.1.6/wave-doc/ppm/log-window.ppm.gz -wfdb-10.1.6/wave-doc/ppm/main-control-panel.ppm.gz -wfdb-10.1.6/wave-doc/ppm/main-window.ppm.gz -wfdb-10.1.6/wave-doc/ppm/main-with-markers.ppm.gz -wfdb-10.1.6/wave-doc/ppm/Makefile -wfdb-10.1.6/wave-doc/ppm/mimic.ppm.gz -wfdb-10.1.6/wave-doc/ppm/netscape-new-helper.ppm.gz -wfdb-10.1.6/wave-doc/ppm/print-setup-window.ppm.gz -wfdb-10.1.6/wave-doc/ppm/scope-window.ppm.gz -wfdb-10.1.6/wave-doc/ppm/search-template.ppm.gz -wfdb-10.1.6/wave-doc/ppm/stdev.ppm.gz -wfdb-10.1.6/wave-doc/ppm/titlebar.ppm.gz -wfdb-10.1.6/wave-doc/ppm/title-with-parens.ppm.gz -wfdb-10.1.6/wave-doc/ppm/type-menu.ppm.gz -wfdb-10.1.6/wave-doc/ppm/wave-icon.ppm.gz -wfdb-10.1.6/wave-doc/ppm/wave-menu.ppm.gz -wfdb-10.1.6/wave/edit.c -wfdb-10.1.6/wave/editing.hlp -wfdb-10.1.6/wave/faq.hlp -wfdb-10.1.6/wave/gcc-patches -wfdb-10.1.6/wave/grid.c -wfdb-10.1.6/wave/help.c -wfdb-10.1.6/wave/helppan.c -wfdb-10.1.6/wave/init.c -wfdb-10.1.6/wave/intro.hlp -wfdb-10.1.6/wave/log.hlp -wfdb-10.1.6/wave/logpan.c -wfdb-10.1.6/wave/mainpan.c -wfdb-10.1.6/wave/Makefile -wfdb-10.1.6/wave/Makefile.top -wfdb-10.1.6/wave/Makefile.tpl -wfdb-10.1.6/wave/makewave -wfdb-10.1.6/wave/mglass_mask.xbm -wfdb-10.1.6/wave/mglass.xbm -wfdb-10.1.6/wave/modepan.c -wfdb-10.1.6/wave/nomake -wfdb-10.1.6/wave/printing.hlp -wfdb-10.1.6/waverc/ -wfdb-10.1.6/waverc/Makefile -wfdb-10.1.6/waverc/Makefile.top -wfdb-10.1.6/waverc/Makefile.tpl -wfdb-10.1.6/waverc/urlvhead -wfdb-10.1.6/waverc/wave-remote.c -wfdb-10.1.6/waverc/wave-remote-test.c -wfdb-10.1.6/waverc/wavescript.c -wfdb-10.1.6/wave/README -wfdb-10.1.6/wave/resource.hlp -wfdb-10.1.6/wave/scope.c -wfdb-10.1.6/wave/search.c -wfdb-10.1.6/wave/sig.c -wfdb-10.1.6/wave/soelim.c -wfdb-10.1.6/wave/wave.c -wfdb-10.1.6/wave/wave.h -wfdb-10.1.6/wave/wave.hl0 -wfdb-10.1.6/wave/wave.inf -wfdb-10.1.6/wave/wave.info -wfdb-10.1.6/wave/wavemenu.def -wfdb-10.1.6/wave/wave.prf -wfdb-10.1.6/wave/Wave.res -wfdb-10.1.6/wave/wave.xbm -wfdb-10.1.6/wave/xvwave.c -wfdb-10.1.6/wave/xvwave.h -wfdb-10.1.6/wview/ -wfdb-10.1.6/wview/clean -wfdb-10.1.6/wview/ecg.ico -wfdb-10.1.6/wview/html/ -wfdb-10.1.6/wview/html/addnft1.png -wfdb-10.1.6/wview/html/addnft2.png -wfdb-10.1.6/wview/html/addnft3.png -wfdb-10.1.6/wview/html/addnft4.png -wfdb-10.1.6/wview/html/addnft5.png -wfdb-10.1.6/wview/html/addnft6.png -wfdb-10.1.6/wview/html/example.xws -wfdb-10.1.6/wview/html/wave.png -wfdb-10.1.6/wview/html/wvsetup.ht0 -wfdb-10.1.6/wview/makefile -wfdb-10.1.6/wview/wview.c -wfdb-10.1.6/wview/wview.def -wfdb-10.1.6/wview/wview.h -wfdb-10.1.6/wview/wview.hlp -wfdb-10.1.6/wview/wview.hpj -wfdb-10.1.6/wview/wview.rc -wfdb-10.1.6/wview/wview.rtf -wfdb-10.1.6/wview/wvscript.c +wfdb-10.2.0/ +wfdb-10.2.0/app/ +wfdb-10.2.0/app/12lead.pro +wfdb-10.2.0/app/ann2rr.c +wfdb-10.2.0/app/bxb.c +wfdb-10.2.0/app/calsig.c +wfdb-10.2.0/app/cshsetwfdb +wfdb-10.2.0/app/ecgeval.c +wfdb-10.2.0/app/epic.c +wfdb-10.2.0/app/fir.c +wfdb-10.2.0/app/ihr.c +wfdb-10.2.0/app/Makefile +wfdb-10.2.0/app/Makefile.dos +wfdb-10.2.0/app/Makefile.top +wfdb-10.2.0/app/Makefile.tpl +wfdb-10.2.0/app/mfilt.c +wfdb-10.2.0/app/mrgann.c +wfdb-10.2.0/app/mxm.c +wfdb-10.2.0/app/nst.c +wfdb-10.2.0/app/plotstm.c +wfdb-10.2.0/app/pscgen.c +wfdb-10.2.0/app/pschart.c +wfdb-10.2.0/app/pschart.pro +wfdb-10.2.0/app/psfd.c +wfdb-10.2.0/app/psfd.pro +wfdb-10.2.0/app/rdann.c +wfdb-10.2.0/app/rdsamp.c +wfdb-10.2.0/app/README +wfdb-10.2.0/app/rr2ann.c +wfdb-10.2.0/app/rxr.c +wfdb-10.2.0/app/sampfreq.c +wfdb-10.2.0/app/sample8.hea +wfdb-10.2.0/app/sample.c +wfdb-10.2.0/app/setwfdb +wfdb-10.2.0/app/setwfdb.bat +wfdb-10.2.0/app/sigamp.c +wfdb-10.2.0/app/skewedit.c +wfdb-10.2.0/app/snip.c +wfdb-10.2.0/app/sortann.c +wfdb-10.2.0/app/sqrs125.c +wfdb-10.2.0/app/sqrs.c +wfdb-10.2.0/app/sumann.c +wfdb-10.2.0/app/sumstats.c +wfdb-10.2.0/app/tach.c +wfdb-10.2.0/app/view.c +wfdb-10.2.0/app/vsetup.c +wfdb-10.2.0/app/wfdbcat.c +wfdb-10.2.0/app/wfdbcollate.c +wfdb-10.2.0/app/wfdbdesc.c +wfdb-10.2.0/app/wfdbwhich.c +wfdb-10.2.0/app/wrann.c +wfdb-10.2.0/app/wrsamp.c +wfdb-10.2.0/app/wvscript.c +wfdb-10.2.0/app/xform.c +wfdb-10.2.0/check-manifest +wfdb-10.2.0/checkpkg/ +wfdb-10.2.0/checkpkg/appcheck +wfdb-10.2.0/checkpkg/expected/ +wfdb-10.2.0/checkpkg/expected/100s.a2r +wfdb-10.2.0/checkpkg/expected/100s.mix +wfdb-10.2.0/checkpkg/expected/100s.qrs +wfdb-10.2.0/checkpkg/expected/100s.wra +wfdb-10.2.0/checkpkg/expected/100w.dat +wfdb-10.2.0/checkpkg/expected/100w.hea +wfdb-10.2.0/checkpkg/expected/100x.atr +wfdb-10.2.0/checkpkg/expected/100x.dat +wfdb-10.2.0/checkpkg/expected/100x.hea +wfdb-10.2.0/checkpkg/expected/100z.hea +wfdb-10.2.0/checkpkg/expected/ann2rr.out +wfdb-10.2.0/checkpkg/expected/bxb.out +wfdb-10.2.0/checkpkg/expected/ecgeval.out +wfdb-10.2.0/checkpkg/expected/fir.dat +wfdb-10.2.0/checkpkg/expected/fir.hea +wfdb-10.2.0/checkpkg/expected/ihr.out +wfdb-10.2.0/checkpkg/expected/lcheck.log-NETFILES +wfdb-10.2.0/checkpkg/expected/lcheck.log-no-NETFILES +wfdb-10.2.0/checkpkg/expected/mfilt.dat +wfdb-10.2.0/checkpkg/expected/mfilt.hea +wfdb-10.2.0/checkpkg/expected/pschart.ps +wfdb-10.2.0/checkpkg/expected/psfd.ps +wfdb-10.2.0/checkpkg/expected/rdann.out +wfdb-10.2.0/checkpkg/expected/rdsamp.out +wfdb-10.2.0/checkpkg/expected/rxr.out +wfdb-10.2.0/checkpkg/expected/sampfreq.out +wfdb-10.2.0/checkpkg/expected/sigamp.out +wfdb-10.2.0/checkpkg/expected/snip.atr +wfdb-10.2.0/checkpkg/expected/snip.dat +wfdb-10.2.0/checkpkg/expected/snip.hea +wfdb-10.2.0/checkpkg/expected/sumann.out +wfdb-10.2.0/checkpkg/expected/sumstats.out +wfdb-10.2.0/checkpkg/expected/tach.out +wfdb-10.2.0/checkpkg/expected/udb/ +wfdb-10.2.0/checkpkg/expected/udb/100z.hea +wfdb-10.2.0/checkpkg/expected/wfd00001.dat +wfdb-10.2.0/checkpkg/expected/wfd00001.hea +wfdb-10.2.0/checkpkg/expected/wfd00002.dat +wfdb-10.2.0/checkpkg/expected/wfd00002.hea +wfdb-10.2.0/checkpkg/expected/wfdbcat.out +wfdb-10.2.0/checkpkg/expected/wfdbdesc.out +wfdb-10.2.0/checkpkg/expected/wfdbwhich.out +wfdb-10.2.0/checkpkg/expected/wfd.hea +wfdb-10.2.0/checkpkg/expected/xform-1.out +wfdb-10.2.0/checkpkg/expected/xform-2.out +wfdb-10.2.0/checkpkg/expected/xform.all +wfdb-10.2.0/checkpkg/expected/xform.dat +wfdb-10.2.0/checkpkg/expected/xform.hea +wfdb-10.2.0/checkpkg/input/ +wfdb-10.2.0/checkpkg/input/100x.hea +wfdb-10.2.0/checkpkg/input/ecgeval +wfdb-10.2.0/checkpkg/input/sumstats +wfdb-10.2.0/checkpkg/input/xform +wfdb-10.2.0/checkpkg/lcheck.c +wfdb-10.2.0/checkpkg/libcheck +wfdb-10.2.0/checkpkg/Makefile +wfdb-10.2.0/checkpkg/Makefile.top +wfdb-10.2.0/checkpkg/Makefile.tpl +wfdb-10.2.0/conf/ +wfdb-10.2.0/conf/cygwin.def +wfdb-10.2.0/conf/exestrip +wfdb-10.2.0/conf/generic.def +wfdb-10.2.0/conf/generic-slib.def +wfdb-10.2.0/conf/hpux.def +wfdb-10.2.0/conf/hpux-slib.def +wfdb-10.2.0/configure +wfdb-10.2.0/conf/linux.def +wfdb-10.2.0/conf/linux-slib.def +wfdb-10.2.0/conf/solaris.def +wfdb-10.2.0/conf/solaris-slib.def +wfdb-10.2.0/conf/version.def +wfdb-10.2.0/convert/ +wfdb-10.2.0/convert/a2m.c +wfdb-10.2.0/convert/ad2m.c +wfdb-10.2.0/convert/edf2mit.c +wfdb-10.2.0/convert/m2a.c +wfdb-10.2.0/convert/Makefile +wfdb-10.2.0/convert/Makefile.dos +wfdb-10.2.0/convert/Makefile.top +wfdb-10.2.0/convert/Makefile.tpl +wfdb-10.2.0/convert/makeid.c +wfdb-10.2.0/convert/md2a.c +wfdb-10.2.0/convert/readid.c +wfdb-10.2.0/convert/README +wfdb-10.2.0/convert/revise.c +wfdb-10.2.0/COPYING +wfdb-10.2.0/data/ +wfdb-10.2.0/data/100s.atr +wfdb-10.2.0/data/100s.dat +wfdb-10.2.0/data/100s.hea +wfdb-10.2.0/data/16.hea +wfdb-10.2.0/data/16l.hea +wfdb-10.2.0/data/16x10.hea +wfdb-10.2.0/data/16x11.hea +wfdb-10.2.0/data/16x12.hea +wfdb-10.2.0/data/16x13.hea +wfdb-10.2.0/data/16x14.hea +wfdb-10.2.0/data/16x15.hea +wfdb-10.2.0/data/16x16.hea +wfdb-10.2.0/data/16x1.hea +wfdb-10.2.0/data/16x2.hea +wfdb-10.2.0/data/16x3.hea +wfdb-10.2.0/data/16x4.hea +wfdb-10.2.0/data/16x5.hea +wfdb-10.2.0/data/16x6.hea +wfdb-10.2.0/data/16x7.hea +wfdb-10.2.0/data/16x8.hea +wfdb-10.2.0/data/16x9.hea +wfdb-10.2.0/data/8.hea +wfdb-10.2.0/data/8l.hea +wfdb-10.2.0/data/8x10.hea +wfdb-10.2.0/data/8x11.hea +wfdb-10.2.0/data/8x12.hea +wfdb-10.2.0/data/8x13.hea +wfdb-10.2.0/data/8x14.hea +wfdb-10.2.0/data/8x15.hea +wfdb-10.2.0/data/8x16.hea +wfdb-10.2.0/data/8x1.hea +wfdb-10.2.0/data/8x2.hea +wfdb-10.2.0/data/8x3.hea +wfdb-10.2.0/data/8x4.hea +wfdb-10.2.0/data/8x5.hea +wfdb-10.2.0/data/8x6.hea +wfdb-10.2.0/data/8x7.hea +wfdb-10.2.0/data/8x8.hea +wfdb-10.2.0/data/8x9.hea +wfdb-10.2.0/data/ahalist +wfdb-10.2.0/data/ahatape.hea +wfdb-10.2.0/data/ahaxlist +wfdb-10.2.0/data/b.hea +wfdb-10.2.0/data/culist +wfdb-10.2.0/data/dblist +wfdb-10.2.0/data/esclist +wfdb-10.2.0/data/Makefile +wfdb-10.2.0/data/Makefile.dos +wfdb-10.2.0/data/Makefile.top +wfdb-10.2.0/data/Makefile.tpl +wfdb-10.2.0/data/mitlist +wfdb-10.2.0/data/mittape.hea +wfdb-10.2.0/data/mitxlist +wfdb-10.2.0/data/multi.hea +wfdb-10.2.0/data/nstlist +wfdb-10.2.0/data/null.hea +wfdb-10.2.0/data/README +wfdb-10.2.0/data/t10240.hea +wfdb-10.2.0/data/t1024.hea +wfdb-10.2.0/data/t4096.hea +wfdb-10.2.0/data/t512.hea +wfdb-10.2.0/data/wfdbcal +wfdb-10.2.0/data/wfdbpath.mac +wfdb-10.2.0/doc/ +wfdb-10.2.0/doc/a2m.1 +wfdb-10.2.0/doc/ann2rr.1 +wfdb-10.2.0/doc/annot.5 +wfdb-10.2.0/doc/appguide.int +wfdb-10.2.0/doc/bxb.1 +wfdb-10.2.0/doc/calsig.1 +wfdb-10.2.0/doc/coherence.1 +wfdb-10.2.0/doc/cover.ag +wfdb-10.2.0/doc/cover.pg +wfdb-10.2.0/doc/ctotexi.c +wfdb-10.2.0/doc/dbag.ht0 +wfdb-10.2.0/doc/dbag.tex +wfdb-10.2.0/doc/dbu.hlp +wfdb-10.2.0/doc/dbu.ht0 +wfdb-10.2.0/doc/dbu.tex +wfdb-10.2.0/doc/dir.db +wfdb-10.2.0/doc/dir.top +wfdb-10.2.0/doc/ecgeval.1 +wfdb-10.2.0/doc/epic.1 +wfdb-10.2.0/doc/eval.tex +wfdb-10.2.0/doc/fft.1 +wfdb-10.2.0/doc/fir.1 +wfdb-10.2.0/doc/fixag.sed +wfdb-10.2.0/doc/fixag.sh +wfdb-10.2.0/doc/fixpg.sed +wfdb-10.2.0/doc/fixpg.sh +wfdb-10.2.0/doc/foot.ht0 +wfdb-10.2.0/doc/header.5 +wfdb-10.2.0/doc/hrfft.1 +wfdb-10.2.0/doc/icons/ +wfdb-10.2.0/doc/icons/contents.png +wfdb-10.2.0/doc/icons/cross_ref.png +wfdb-10.2.0/doc/icons/foot.png +wfdb-10.2.0/doc/icons/next_gr.png +wfdb-10.2.0/doc/icons/next.png +wfdb-10.2.0/doc/icons/prev_gr.png +wfdb-10.2.0/doc/icons/previous.png +wfdb-10.2.0/doc/icons/up_gr.png +wfdb-10.2.0/doc/icons/up.png +wfdb-10.2.0/doc/ihr.1 +wfdb-10.2.0/doc/index.ht0 +wfdb-10.2.0/doc/install.tex +wfdb-10.2.0/doc/intro.ht0 +wfdb-10.2.0/doc/.latex2html-init +wfdb-10.2.0/doc/log10.1 +wfdb-10.2.0/doc/lomb.1 +wfdb-10.2.0/doc/Makefile +wfdb-10.2.0/doc/Makefile.top +wfdb-10.2.0/doc/Makefile.tpl +wfdb-10.2.0/doc/makeinfo.sh +wfdb-10.2.0/doc/manhtml.sh +wfdb-10.2.0/doc/maninst.sh +wfdb-10.2.0/doc/memse.1 +wfdb-10.2.0/doc/mfilt.1 +wfdb-10.2.0/doc/mrgann.1 +wfdb-10.2.0/doc/mxm.1 +wfdb-10.2.0/doc/nst.1 +wfdb-10.2.0/doc/plot2d.1 +wfdb-10.2.0/doc/plotstm.1 +wfdb-10.2.0/doc/pschart.1 +wfdb-10.2.0/doc/psfd.1 +wfdb-10.2.0/doc/rdann.1 +wfdb-10.2.0/doc/rdsamp.1 +wfdb-10.2.0/doc/README +wfdb-10.2.0/doc/rxr.1 +wfdb-10.2.0/doc/sampfreq.1 +wfdb-10.2.0/doc/sample.1 +wfdb-10.2.0/doc/setwfdb.1 +wfdb-10.2.0/doc/sigamp.1 +wfdb-10.2.0/doc/signal.5 +wfdb-10.2.0/doc/skewedit.1 +wfdb-10.2.0/doc/snip.1 +wfdb-10.2.0/doc/sortann.1 +wfdb-10.2.0/doc/sqrs.1 +wfdb-10.2.0/doc/sumann.1 +wfdb-10.2.0/doc/sumstats.1 +wfdb-10.2.0/doc/tach.1 +wfdb-10.2.0/doc/texi2html +wfdb-10.2.0/doc/texindex.c +wfdb-10.2.0/doc/tmac.dif +wfdb-10.2.0/doc/view.1 +wfdb-10.2.0/doc/wave.1 +wfdb-10.2.0/doc/wfdb.3 +wfdb-10.2.0/doc/wfdbcal.5 +wfdb-10.2.0/doc/wfdbcat.1 +wfdb-10.2.0/doc/wfdbcollate.1 +wfdb-10.2.0/doc/wfdbdesc.1 +wfdb-10.2.0/doc/wfdbwhich.1 +wfdb-10.2.0/doc/wrann.1 +wfdb-10.2.0/doc/wrsamp.1 +wfdb-10.2.0/doc/wview.1 +wfdb-10.2.0/doc/xform.1 +wfdb-10.2.0/examples/ +wfdb-10.2.0/examples/dblibver.c +wfdb-10.2.0/examples/example10.c +wfdb-10.2.0/examples/example1.c +wfdb-10.2.0/examples/example2.c +wfdb-10.2.0/examples/example3.c +wfdb-10.2.0/examples/example4.c +wfdb-10.2.0/examples/example5.c +wfdb-10.2.0/examples/example6.c +wfdb-10.2.0/examples/example7.c +wfdb-10.2.0/examples/example8.c +wfdb-10.2.0/examples/example9.c +wfdb-10.2.0/examples/exannstr.c +wfdb-10.2.0/examples/exgetvec.c +wfdb-10.2.0/examples/exputvec.c +wfdb-10.2.0/examples/Makefile +wfdb-10.2.0/examples/Makefile.dos +wfdb-10.2.0/examples/Makefile.top +wfdb-10.2.0/examples/Makefile.tpl +wfdb-10.2.0/examples/psamples.c +wfdb-10.2.0/examples/README +wfdb-10.2.0/examples/refhr.c +wfdb-10.2.0/fortran/ +wfdb-10.2.0/fortran/example.f +wfdb-10.2.0/fortran/Makefile +wfdb-10.2.0/fortran/README +wfdb-10.2.0/fortran/wfdbf.c +wfdb-10.2.0/INSTALL +wfdb-10.2.0/install.sh +wfdb-10.2.0/lib/ +wfdb-10.2.0/lib/annot.c +wfdb-10.2.0/lib/calib.c +wfdb-10.2.0/lib/COPYING.LIB +wfdb-10.2.0/lib/db.h +wfdb-10.2.0/lib/ecgcodes.h +wfdb-10.2.0/lib/ecgmap.h +wfdb-10.2.0/lib/Makefile +wfdb-10.2.0/lib/Makefile.dos +wfdb-10.2.0/lib/Makefile.top +wfdb-10.2.0/lib/Makefile.tpl +wfdb-10.2.0/lib/makelib +wfdb-10.2.0/lib/README +wfdb-10.2.0/lib/signal.c +wfdb-10.2.0/lib/twfdbdll.def +wfdb-10.2.0/lib/wfdbdll.def +wfdb-10.2.0/lib/wfdb.h +wfdb-10.2.0/lib/wfdbinit.c +wfdb-10.2.0/lib/wfdbio.c +wfdb-10.2.0/lib/wfdblib.h +wfdb-10.2.0/Makefile +wfdb-10.2.0/Makefile.top +wfdb-10.2.0/Makefile.tpl +wfdb-10.2.0/MANIFEST +wfdb-10.2.0/NEWS +wfdb-10.2.0/psd/ +wfdb-10.2.0/psd/coherence.c +wfdb-10.2.0/psd/fft.c +wfdb-10.2.0/psd/hrfft +wfdb-10.2.0/psd/hrlomb +wfdb-10.2.0/psd/hrmem +wfdb-10.2.0/psd/hrplot +wfdb-10.2.0/psd/log10.c +wfdb-10.2.0/psd/lomb.c +wfdb-10.2.0/psd/Makefile +wfdb-10.2.0/psd/Makefile.dos +wfdb-10.2.0/psd/Makefile.top +wfdb-10.2.0/psd/Makefile.tpl +wfdb-10.2.0/psd/memse.c +wfdb-10.2.0/psd/plot2d +wfdb-10.2.0/psd/plot3d +wfdb-10.2.0/psd/README +wfdb-10.2.0/README +wfdb-10.2.0/README.NETFILES +wfdb-10.2.0/uninstall.sh +wfdb-10.2.0/wave/ +wfdb-10.2.0/wave/analysis.hlp +wfdb-10.2.0/wave/analyze.c +wfdb-10.2.0/wave/annot.c +wfdb-10.2.0/wave/annpan.c +wfdb-10.2.0/wave/anntab +wfdb-10.2.0/wave/bitmaps.h +wfdb-10.2.0/wave/buttons.hlp +wfdb-10.2.0/wave/demo.txt +wfdb-10.2.0/wave-doc/ +wfdb-10.2.0/wave-doc/color/ +wfdb-10.2.0/wave-doc/color/allow-edit.ps +wfdb-10.2.0/wave-doc/color/calibrate.ps +wfdb-10.2.0/wave-doc/color/file-analyze.ps +wfdb-10.2.0/wave-doc/color/file-load.ps +wfdb-10.2.0/wave-doc/color/file-print.ps +wfdb-10.2.0/wave-doc/color/file-save.ps +wfdb-10.2.0/wave-doc/color/find-window.ps +wfdb-10.2.0/wave-doc/color/help-topics.ps +wfdb-10.2.0/wave-doc/color/level-window.ps +wfdb-10.2.0/wave-doc/color/main-control-panel.ps +wfdb-10.2.0/wave-doc/color/main-window.ps +wfdb-10.2.0/wave-doc/color/main-with-hr.ps +wfdb-10.2.0/wave-doc/color/main-with-markers.ps +wfdb-10.2.0/wave-doc/color/Makefile +wfdb-10.2.0/wave-doc/color/mimic.ps +wfdb-10.2.0/wave-doc/color/netscape-new-helper.ps +wfdb-10.2.0/wave-doc/color/print-setup-window.ps +wfdb-10.2.0/wave-doc/color/scope-window.ps +wfdb-10.2.0/wave-doc/color/search-template.ps +wfdb-10.2.0/wave-doc/color/stdev.ps +wfdb-10.2.0/wave-doc/color/titlebar.ps +wfdb-10.2.0/wave-doc/color/title-with-parens.ps +wfdb-10.2.0/wave-doc/color/type-menu.ps +wfdb-10.2.0/wave-doc/color/wave-icon.ps +wfdb-10.2.0/wave-doc/color/wave-menu.ps +wfdb-10.2.0/wave-doc/grey/ +wfdb-10.2.0/wave-doc/grey/allow-edit.ps +wfdb-10.2.0/wave-doc/grey/analysis-commands.ps +wfdb-10.2.0/wave-doc/grey/analyze-window.ps +wfdb-10.2.0/wave-doc/grey/annotation-template.ps +wfdb-10.2.0/wave-doc/grey/attach-to-signals.ps +wfdb-10.2.0/wave-doc/grey/calibrate.ps +wfdb-10.2.0/wave-doc/grey/chart1.ps +wfdb-10.2.0/wave-doc/grey/chart2.ps +wfdb-10.2.0/wave-doc/grey/file-analyze.ps +wfdb-10.2.0/wave-doc/grey/file-load.ps +wfdb-10.2.0/wave-doc/grey/file-print.ps +wfdb-10.2.0/wave-doc/grey/file-save.ps +wfdb-10.2.0/wave-doc/grey/find-window.ps +wfdb-10.2.0/wave-doc/grey/fulldisc.ps +wfdb-10.2.0/wave-doc/grey/help-intro.ps +wfdb-10.2.0/wave-doc/grey/help-topics.ps +wfdb-10.2.0/wave-doc/grey/level-window.ps +wfdb-10.2.0/wave-doc/grey/load-window.ps +wfdb-10.2.0/wave-doc/grey/log-window.ps +wfdb-10.2.0/wave-doc/grey/main-control-panel.ps +wfdb-10.2.0/wave-doc/grey/main-window.ps +wfdb-10.2.0/wave-doc/grey/main-with-hr.ps +wfdb-10.2.0/wave-doc/grey/main-with-markers.ps +wfdb-10.2.0/wave-doc/grey/Makefile +wfdb-10.2.0/wave-doc/grey/mimic.ps +wfdb-10.2.0/wave-doc/grey/netscape-new-helper.ps +wfdb-10.2.0/wave-doc/grey/noedit.ps +wfdb-10.2.0/wave-doc/grey/nomatch.ps +wfdb-10.2.0/wave-doc/grey/notice-quit.ps +wfdb-10.2.0/wave-doc/grey/print-setup-window.ps +wfdb-10.2.0/wave-doc/grey/scope-window.ps +wfdb-10.2.0/wave-doc/grey/search-template.ps +wfdb-10.2.0/wave-doc/grey/spot-help.ps +wfdb-10.2.0/wave-doc/grey/stdev.ps +wfdb-10.2.0/wave-doc/grey/system-menu.ps +wfdb-10.2.0/wave-doc/grey/titlebar.ps +wfdb-10.2.0/wave-doc/grey/title-with-parens.ps +wfdb-10.2.0/wave-doc/grey/type-menu.ps +wfdb-10.2.0/wave-doc/grey/view-window.ps +wfdb-10.2.0/wave-doc/grey/wave-icon.ps +wfdb-10.2.0/wave-doc/grey/wave-menu.ps +wfdb-10.2.0/wave-doc/guide/ +wfdb-10.2.0/wave-doc/guide/chart2.png +wfdb-10.2.0/wave-doc/guide/cover.wug +wfdb-10.2.0/wave-doc/guide/dossify-html +wfdb-10.2.0/wave-doc/guide/example.xws +wfdb-10.2.0/wave-doc/guide/fancybox.perl +wfdb-10.2.0/wave-doc/guide/fixindex +wfdb-10.2.0/wave-doc/guide/fixinfo +wfdb-10.2.0/wave-doc/guide/fixlinks +wfdb-10.2.0/wave-doc/guide/fulldisc.png +wfdb-10.2.0/wave-doc/guide/html.sty +wfdb-10.2.0/wave-doc/guide/icons/ +wfdb-10.2.0/wave-doc/guide/icons/contents.png +wfdb-10.2.0/wave-doc/guide/icons/cross_ref.png +wfdb-10.2.0/wave-doc/guide/icons/foot.png +wfdb-10.2.0/wave-doc/guide/icons/index.png +wfdb-10.2.0/wave-doc/guide/icons/next_gr.png +wfdb-10.2.0/wave-doc/guide/icons/next.png +wfdb-10.2.0/wave-doc/guide/icons/prev_gr.png +wfdb-10.2.0/wave-doc/guide/icons/previous.png +wfdb-10.2.0/wave-doc/guide/icons/up_gr.png +wfdb-10.2.0/wave-doc/guide/icons/up.png +wfdb-10.2.0/wave-doc/guide/icons/wave.png +wfdb-10.2.0/wave-doc/guide/.latex2html-init +wfdb-10.2.0/wave-doc/guide/Makefile +wfdb-10.2.0/wave-doc/guide/manhtml +wfdb-10.2.0/wave-doc/guide/saveroot +wfdb-10.2.0/wave-doc/guide/savewin +wfdb-10.2.0/wave-doc/guide/stdev.c +wfdb-10.2.0/wave-doc/guide/wave2d +wfdb-10.2.0/wave-doc/guide/wug.tex +wfdb-10.2.0/wave-doc/guide/xview.7 +wfdb-10.2.0/wave-doc/guide/xwdtops +wfdb-10.2.0/wave-doc/guide/xwdtops-grey +wfdb-10.2.0/wave-doc/Makefile +wfdb-10.2.0/wave-doc/ppm/ +wfdb-10.2.0/wave-doc/ppm/allow-edit.ppm.gz +wfdb-10.2.0/wave-doc/ppm/attach-to-signals.ppm.gz +wfdb-10.2.0/wave-doc/ppm/calibrate.ppm.gz +wfdb-10.2.0/wave-doc/ppm/file-analyze.ppm.gz +wfdb-10.2.0/wave-doc/ppm/file-load.ppm.gz +wfdb-10.2.0/wave-doc/ppm/file-print.ppm.gz +wfdb-10.2.0/wave-doc/ppm/file-save.ppm.gz +wfdb-10.2.0/wave-doc/ppm/find-window.ppm.gz +wfdb-10.2.0/wave-doc/ppm/help-topics.ppm.gz +wfdb-10.2.0/wave-doc/ppm/level-window.ppm.gz +wfdb-10.2.0/wave-doc/ppm/log-window.ppm.gz +wfdb-10.2.0/wave-doc/ppm/main-control-panel.ppm.gz +wfdb-10.2.0/wave-doc/ppm/main-window.ppm.gz +wfdb-10.2.0/wave-doc/ppm/main-with-markers.ppm.gz +wfdb-10.2.0/wave-doc/ppm/Makefile +wfdb-10.2.0/wave-doc/ppm/mimic.ppm.gz +wfdb-10.2.0/wave-doc/ppm/netscape-new-helper.ppm.gz +wfdb-10.2.0/wave-doc/ppm/print-setup-window.ppm.gz +wfdb-10.2.0/wave-doc/ppm/scope-window.ppm.gz +wfdb-10.2.0/wave-doc/ppm/search-template.ppm.gz +wfdb-10.2.0/wave-doc/ppm/stdev.ppm.gz +wfdb-10.2.0/wave-doc/ppm/titlebar.ppm.gz +wfdb-10.2.0/wave-doc/ppm/title-with-parens.ppm.gz +wfdb-10.2.0/wave-doc/ppm/type-menu.ppm.gz +wfdb-10.2.0/wave-doc/ppm/wave-icon.ppm.gz +wfdb-10.2.0/wave-doc/ppm/wave-menu.ppm.gz +wfdb-10.2.0/wave/edit.c +wfdb-10.2.0/wave/editing.hlp +wfdb-10.2.0/wave/faq.hlp +wfdb-10.2.0/wave/gcc-patches +wfdb-10.2.0/wave/grid.c +wfdb-10.2.0/wave/help.c +wfdb-10.2.0/wave/helppan.c +wfdb-10.2.0/wave/init.c +wfdb-10.2.0/wave/intro.hlp +wfdb-10.2.0/wave/log.hlp +wfdb-10.2.0/wave/logpan.c +wfdb-10.2.0/wave/mainpan.c +wfdb-10.2.0/wave/Makefile +wfdb-10.2.0/wave/Makefile.top +wfdb-10.2.0/wave/Makefile.tpl +wfdb-10.2.0/wave/makewave +wfdb-10.2.0/wave/mglass_mask.xbm +wfdb-10.2.0/wave/mglass.xbm +wfdb-10.2.0/wave/modepan.c +wfdb-10.2.0/wave/nomake +wfdb-10.2.0/wave/printing.hlp +wfdb-10.2.0/waverc/ +wfdb-10.2.0/waverc/Makefile +wfdb-10.2.0/waverc/Makefile.top +wfdb-10.2.0/waverc/Makefile.tpl +wfdb-10.2.0/waverc/urlvhead +wfdb-10.2.0/waverc/wave-remote.c +wfdb-10.2.0/waverc/wave-remote-test.c +wfdb-10.2.0/waverc/wavescript.c +wfdb-10.2.0/wave/README +wfdb-10.2.0/wave/resource.hlp +wfdb-10.2.0/wave/scope.c +wfdb-10.2.0/wave/search.c +wfdb-10.2.0/wave/sig.c +wfdb-10.2.0/wave/soelim.c +wfdb-10.2.0/wave/wave.c +wfdb-10.2.0/wave/wave.h +wfdb-10.2.0/wave/wave.hl0 +wfdb-10.2.0/wave/wave.inf +wfdb-10.2.0/wave/wave.info +wfdb-10.2.0/wave/wavemenu.def +wfdb-10.2.0/wave/wave.prf +wfdb-10.2.0/wave/Wave.res +wfdb-10.2.0/wave/wave.xbm +wfdb-10.2.0/wave/xvwave.c +wfdb-10.2.0/wave/xvwave.h +wfdb-10.2.0/wview/ +wfdb-10.2.0/wview/clean +wfdb-10.2.0/wview/ecg.ico +wfdb-10.2.0/wview/html/ +wfdb-10.2.0/wview/html/addnft1.png +wfdb-10.2.0/wview/html/addnft2.png +wfdb-10.2.0/wview/html/addnft3.png +wfdb-10.2.0/wview/html/addnft4.png +wfdb-10.2.0/wview/html/addnft5.png +wfdb-10.2.0/wview/html/addnft6.png +wfdb-10.2.0/wview/html/example.xws +wfdb-10.2.0/wview/html/wave.png +wfdb-10.2.0/wview/html/wvsetup.ht0 +wfdb-10.2.0/wview/makefile +wfdb-10.2.0/wview/wview.c +wfdb-10.2.0/wview/wview.def +wfdb-10.2.0/wview/wview.h +wfdb-10.2.0/wview/wview.hlp +wfdb-10.2.0/wview/wview.hpj +wfdb-10.2.0/wview/wview.rc +wfdb-10.2.0/wview/wview.rtf +wfdb-10.2.0/wview/wvscript.c diff -Naur wfdb-10.1.6/Makefile wfdb-10.2.0/Makefile --- wfdb-10.1.6/Makefile Wed Aug 1 10:28:34 2001 +++ wfdb-10.2.0/Makefile Mon Oct 15 14:40:00 2001 @@ -39,12 +39,12 @@ # create source archives, type `make tarballs'; or to make a binary archive, # type `make bin-tarball'. Making archives requires PGP, gzip, and GNU tar). # file: version.def G. Moody 24 May 2000 -# Last revised: 28 February 2001 +# Last revised: 14 August 2001 # Each release of the WFDB Software Package is identified by a three-part # version number, defined here: MAJOR = 10 -MINOR = 1 -RELEASE = 6 +MINOR = 2 +RELEASE = 0 VERSION = $(MAJOR).$(MINOR).$(RELEASE) # VDEFS is the set of C compiler options needed to set version number variables @@ -52,7 +52,7 @@ VDEFS = -DWFDB_MAJOR=$(MAJOR) -DWFDB_MINOR=$(MINOR) -DWFDB_RELEASE=$(RELEASE) # _____________________________________________________________________________ -PACKAGE=wfdb-10.1.6 +PACKAGE=wfdb-10.2.0 # file: linux.def G. Moody 31 May 2000 # Last revised: 5 June 2000 # 'make' definitions for compiling the WFDB Software Package under Linux @@ -166,8 +166,8 @@ lib-post-uninstall: echo "Nothing to be done for lib-post-uninstall" # _____________________________________________________________________________ -# file: Makefile.tpl G. Moody 24 May 2000 -# Last revised: 30 May 2001 +# file: Makefile.tpl G. Moody 24 May 2000 +# Last revised: 15 October 2001 # This section of the Makefile should not need to be changed. # ARCH specifies the type of CPU and the operating system (e.g., 'i686-Linux'). @@ -195,6 +195,7 @@ cd psd; $(MAKE) install cd convert; $(MAKE) install cd data; $(MAKE) install + cd doc; $(MAKE) install uninstall: config.cache cd lib; $(MAKE) uninstall @@ -204,11 +205,13 @@ cd psd; $(MAKE) uninstall cd convert; $(MAKE) uninstall cd data; $(MAKE) uninstall + cd doc; $(MAKE) uninstall ./uninstall.sh $(WFDBROOT) # 'make clean': remove binaries, other cruft from source directories clean: cd app; $(MAKE) clean + cd checkpkg; $(MAKE) clean cd convert; $(MAKE) clean cd data; $(MAKE) clean cd doc; $(MAKE) clean @@ -238,6 +241,10 @@ # subdirectories of $(HOME)/wfdb-test test-install: $(TESTDIRS) $(MAKE) WFDBROOT=$(HOME)/wfdb-test install + +# 'make check': test currently installed version of the WFDB software package +check: + cd checkpkg; $(MAKE) all # Create directories for test installation if necessary. TESTDIRS = $(HOME)/wfdb-test/bin $(HOME)/wfdb-test/database \ diff -Naur wfdb-10.1.6/Makefile.tpl wfdb-10.2.0/Makefile.tpl --- wfdb-10.1.6/Makefile.tpl Wed May 30 12:44:09 2001 +++ wfdb-10.2.0/Makefile.tpl Mon Oct 15 13:37:09 2001 @@ -1,5 +1,5 @@ -# file: Makefile.tpl G. Moody 24 May 2000 -# Last revised: 30 May 2001 +# file: Makefile.tpl G. Moody 24 May 2000 +# Last revised: 15 October 2001 # This section of the Makefile should not need to be changed. # ARCH specifies the type of CPU and the operating system (e.g., 'i686-Linux'). @@ -27,6 +27,7 @@ cd psd; $(MAKE) install cd convert; $(MAKE) install cd data; $(MAKE) install + cd doc; $(MAKE) install uninstall: config.cache cd lib; $(MAKE) uninstall @@ -36,11 +37,13 @@ cd psd; $(MAKE) uninstall cd convert; $(MAKE) uninstall cd data; $(MAKE) uninstall + cd doc; $(MAKE) uninstall ./uninstall.sh $(WFDBROOT) # 'make clean': remove binaries, other cruft from source directories clean: cd app; $(MAKE) clean + cd checkpkg; $(MAKE) clean cd convert; $(MAKE) clean cd data; $(MAKE) clean cd doc; $(MAKE) clean @@ -70,6 +73,10 @@ # subdirectories of $(HOME)/wfdb-test test-install: $(TESTDIRS) $(MAKE) WFDBROOT=$(HOME)/wfdb-test install + +# 'make check': test currently installed version of the WFDB software package +check: + cd checkpkg; $(MAKE) all # Create directories for test installation if necessary. TESTDIRS = $(HOME)/wfdb-test/bin $(HOME)/wfdb-test/database \ diff -Naur wfdb-10.1.6/NEWS wfdb-10.2.0/NEWS --- wfdb-10.1.6/NEWS Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/NEWS Mon Oct 15 13:42:22 2001 @@ -0,0 +1,35 @@ +10.2.0: + The 10.2 series differs from all earlier releases in that the WFDB + library no longer imposes any fixed limits on the numbers of annotators + or signals that can be open simultaneously. There is also no + fixed limit on the number of samples per signal per frame. The + constants WFDB_MAXANN, WFDB_MAXSIG, and WFDB_MAXSPF, which determined + these limits in previous versions of the library, are still defined in + lib/wfdb.h for compatibility with older programs that use them, e.g., + to set array sizes. + + In this release, almost all of the WFDB applications, including WAVE, + those in the 'app' and 'examples' directories, and convert/edf2mit, + have been revised so that they can handle arbitrary numbers of signals + and (where applicable) annotation files. The exceptions are: + + sample + limited by the number of channels provided by the ADC/DAC it uses + view, wview + use 'gtkwave' (http://www.physionet.org/physiotools/beta/gtkwave) + + Also please note the new 'checkpkg' directory, which contains a variety + of tests to check the basic functionality of the WFDB library and many + of the WFDB applications. From the base directory, run the tests by: + + make check + + These tests will check the currently installed version of the WFDB + software package. If you use them to check an old version, there may + be minor discrepancies because of changes in the output formats; you + should not encounter any discrepancies if you use these tests after + installing this version of the WFDB software package. + + As always, your comments are welcome! + + George (george@mit.edu) diff -Naur wfdb-10.1.6/README.NETFILES wfdb-10.2.0/README.NETFILES --- wfdb-10.1.6/README.NETFILES Mon Jun 5 16:12:51 2000 +++ wfdb-10.2.0/README.NETFILES Thu Sep 6 13:33:25 2001 @@ -1,16 +1,15 @@ file: README.NETFILES G. Moody 14 September 1999 - Last revised: 5 June 2000 + Last revised: 6 September 2001 This version of the WFDB software package contains experimental NETFILES support in the WFDB library, which is compiled if you have previously installed libwww (see http://www.w3.org/Library/). -NETFILES support is known to work well under Linux (with both 2.0 and 2.2 -series kernels and glibc 2.0 and 2.1). When compiling the WFDB library as -a static library with NETFILES support, it is necessary to allow ld to make -three passes over the libwww libraries to resolve all dependencies; this is -handled automatically by the version of lib/Makefile that is generated by -`configure'. +NETFILES support is known to work well under Linux, Solaris, and MS-Windows. +When compiling the WFDB library as a static library with NETFILES support, it +is necessary to allow ld to make three passes over the libwww libraries to +resolve all dependencies; this is handled automatically by the version of +lib/Makefile that is generated by `configure'. To use NETFILES once this software has been compiled and installed, the WFDB path should contain one or more components that refer to remote files available @@ -40,15 +39,16 @@ of additional path information are necessary) -If you would like to experiment with NETFILES under Linux, install the libwww -and xview packages (available from PhysioNet), then compile and install WAVE -and wavescript (in the waverc directory). This is done by default if you build -the package using './configure' followed by 'make' in the top-level directory -of the source tree. Follow the instructions given in the 'WAVE and the Web' -section of the WAVE User's Guide (in 'wave-doc'; also available on PhysioNet at -http://www.physionet.org/physiotools/wug/) to install wavescript as a helper -application for your web browser. You should now be able to follow the .xws -links in the on-line version of the MIT-BIH Arrhythmia Database Directory +If you would like to experiment with NETFILES under Linux or Solaris, install +the libwww and xview packages (available from PhysioNet), then compile and +install WAVE and wavescript (in the waverc directory). This is done by default +if you build the package using './configure' followed by 'make' in the +top-level directory of the source tree. Follow the instructions given in the +'WAVE and the Web' section of the WAVE User's Guide (in 'wave-doc'; also +available on PhysioNet at http://www.physionet.org/physiotools/wug/) to install +wavescript as a helper application for your web browser. You should now be +able to follow the .xws links in the on-line version of the MIT-BIH Arrhythmia +Database Directory (http://www.physionet.org/physiobank/database/html/mitdbdir/mitdbdir.htm) and in the HTML files included in the MIMIC Database records available on PhysioNet. (Once you have installed the software and configured your browser, diff -Naur wfdb-10.1.6/app/Makefile wfdb-10.2.0/app/Makefile --- wfdb-10.1.6/app/Makefile Wed Aug 1 10:28:34 2001 +++ wfdb-10.2.0/app/Makefile Mon Oct 15 14:40:00 2001 @@ -33,12 +33,12 @@ # type `make listing'. # _____________________________________________________________________________ # file: version.def G. Moody 24 May 2000 -# Last revised: 28 February 2001 +# Last revised: 14 August 2001 # Each release of the WFDB Software Package is identified by a three-part # version number, defined here: MAJOR = 10 -MINOR = 1 -RELEASE = 6 +MINOR = 2 +RELEASE = 0 VERSION = $(MAJOR).$(MINOR).$(RELEASE) # VDEFS is the set of C compiler options needed to set version number variables @@ -46,7 +46,7 @@ VDEFS = -DWFDB_MAJOR=$(MAJOR) -DWFDB_MINOR=$(MINOR) -DWFDB_RELEASE=$(RELEASE) # _____________________________________________________________________________ -PACKAGE=wfdb-10.1.6 +PACKAGE=wfdb-10.2.0 # file: linux.def G. Moody 31 May 2000 # Last revised: 5 June 2000 # 'make' definitions for compiling the WFDB Software Package under Linux diff -Naur wfdb-10.1.6/app/Makefile-dos-gcc wfdb-10.2.0/app/Makefile-dos-gcc --- wfdb-10.1.6/app/Makefile-dos-gcc Wed May 24 22:35:27 2000 +++ wfdb-10.2.0/app/Makefile-dos-gcc Wed Dec 31 19:00:00 1969 @@ -1,147 +0,0 @@ -# file: Makefile-dos-gcc G. Moody 23 April 1997 -# Last revised: 24 May 2000 -# GCC-DOS 'make' description file for WFDB applications -# -# ----------------------------------------------------------------------------- -# WFDB applications: programs for working with annotated signals -# Copyright (C) 2000 George B. Moody -# -# These programs are free software; you can redistribute them and/or modify -# them under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# These programs are distributed in the hope that they will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# these programs; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# You may contact the author by e-mail (george@mit.edu) or postal mail -# (MIT Room E25-505A, Cambridge, MA 02139 USA). For updates to this software, -# please visit PhysioNet (http://www.physionet.org/). -# _____________________________________________________________________________ -# -# This file is used with the UNIX `make' command to cross-compile MS-DOS -# binaries of the standard applications that come with the WFDB software -# package. Before using it for the first time, check that the site-specific -# variables below are appropriate for your system. To build and install the -# applications, just type `make -f Makefile-dos-gcc' (from within this -# directory). - -# Site-specific variables -# ----------------------- - -# CCDIR is the directory containing the cross-compiler and the binary -# file utilities for MSDOS. -CCDIR = /usr/lib/gcc-lib/i386-go32-msdos/2.7.2 - -# CC is the name of the cross-compiler. -CC = $(CCDIR)/gcc - -# CCDEFS is the set of C compiler options needed to set preprocessor variables -# while compiling the WFDB Software Package. You should include definitions of -# the major, minor, and release numbers, and of MSDOS, as shown below. Other -# definitions are needed only for various versions of UNIX and should be -# omitted here. -CCDEFS = -DWFDB_MAJOR=$(MAJOR) -DWFDB_MINOR=$(MINOR) -DWFDB_RELEASE=$(RELEASE)\ - -DMSDOS - -# CFLAGS is the list of C compiler options used when compiling programs in the -# `app', `convert', and `example' directories. Add the following options to -# CFAPP as appropriate (separating them by spaces if you use more than one): -# -g to save symbols for debugging -# -O to use the optimizer -# -I$(INCDIR) needed if INCDIR is not in the normal search path for -# `#include' files; harmless otherwise -# -L$(LIBDIR) needed if LIBDIR is not in the normal library search path; -# harmless if LIBDIR is in the normal library search path -# As noted above, gcc-dos allows you to use both -g and -O if you wish. -CFLAGS = -O -I/usr/local/dos/include $(CCDEFS) -L/usr/local/dos/lib - -# LDFLAGS is appended to the C compiler command line to specify loading the -# WFDB library. Unless you have changed the value of WFDBLIB in the `Makefile' -# for the WFDB library, `-lwfdb' should be correct. -LDFLAGS = -lwfdb - -# BINDIR specifies the directory in which the applications will be installed; -# it should be a directory in the PATH of those who will use the applications. -# You will need to have write permission in BINDIR. Users of this software -# will need to have search (execute) permission in BINDIR. -BINDIR = /usr/local/dos/bin - -# PSPDIR specifies the directory in which PostScript prolog files are kept. -# (You may use any directory for this purpose; if you have other PostScript -# applications, you may wish to keep all of your prolog files in the same -# directory, often /usr/local/lib/ps). You will need to have write permission -# in PSPDIR. Users of this software will need to have search (execute) -# permission in PSPDIR. -PSPDIR = /usr/local/dos/lib/ps - -# STRIP is the command used to compact the compiled binaries by removing their -# symbol tables. The next line is commented out because $(CCDIR)/strip fails. -# STRIP = $(CCDIR)/strip -# To retain the symbol tables for debugging, comment out the previous line, and -# uncomment the next line. -STRIP = : - -# It should not be necessary to modify anything below this line. -# ----------------------------------------------------------------------------- - -CFILES = bxb.c calsig.c ecgeval.c epic.c fir.c ihr.c mfilt.c mrgann.c \ - mxm.c nst.c plotstm.c pschart.c psfd.c rdann.c rdsamp.c rxr.c sample.c \ - sigamp.c skewedit.c snip.c sortann.c sqrs.c sqrs125.c sumann.c sumstats.c \ - tach.c view.c vsetup.c wfdbcollate.c wfdbdesc.c wfdbwhich.c wrann.c wrsamp.c \ - xform.c -XFILES = bxb.exe calsig.exe ecgeval.exe epic.exe fir.exe ihr.exe mfilt.exe \ - mrgann.exe mxm.exe nst.exe plotstm.exe pschart.exe psfd.exe rdann.exe \ - rdsamp.exe rxr.exe sigamp.exe skewedit.exe snip.exe sortann.exe sqrs.exe \ - sqrs125.exe sumann.exe sumstats.exe tach.exe wfdbcol8.exe wfdbdesc.exe \ - wfdbwhic.exe wrann.exe wrsamp.exe xform.exe -PSFILES = pschart.pro psfd.pro - -# General rule for compiling C sources into executable files. -.SUFFIXES: .exe -.c.exe: - $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) - -# `make' or `make install': build and install applications, clean up -install: all - cp $(XFILES) $(BINDIR) - cp $(PSFILES) $(PSPDIR) - $(MAKE) clean - -# `make all': build applications -all: $(XFILES) - $(STRIP) $(XFILES) - -# `make clean': remove intermediate and backup files -clean: - rm -f $(XFILES) *.o *~ - -# Rules for compiling applications that require non-standard options - -bxb.exe: bxb.c - $(CC) $(CFLAGS) bxb.c -o $@ $(LDFLAGS) -lm -calsig.exe: calsig.c - $(CC) $(CFLAGS) calsig.c -o $@ $(LDFLAGS) -wfdbcol8.exe: wfdbcollate.c - $(CC) $(CFLAGS) wfdbcollate.c -o $@ $(LDFLAGS) -wfdbwhic.exe: wfdbwhich.c - $(CC) $(CFLAGS) wfdbwhich.c -o $@ $(LDFLAGS) -mxm.exe: mxm.c - $(CC) $(CFLAGS) mxm.c -o $@ $(LDFLAGS) -lm -nst.exe: nst.c - $(CC) $(CFLAGS) nst.c -o $@ $(LDFLAGS) -lm -plotstm.exe: plotstm.c - $(CC) $(CFLAGS) plotstm.c -o $@ -pschart.exe: pschart.c - $(CC) $(CFLAGS) -DPROLOG=\"$(PSPDIR)/pschart.pro\" pschart.c -o $@ \ - $(LDFLAGS) -psfd.exe: psfd.c - $(CC) $(CFLAGS) -DPROLOG=\"$(PSPDIR)/psfd.pro\" psfd.c -o $@ $(LDFLAGS) -sigamp.exe: sigamp.c - $(CC) $(CFLAGS) sigamp.c -o $@ $(LDFLAGS) -lm diff -Naur wfdb-10.1.6/app/README wfdb-10.2.0/app/README --- wfdb-10.1.6/app/README Wed May 24 16:23:32 2000 +++ wfdb-10.2.0/app/README Mon Oct 8 22:40:31 2001 @@ -1,9 +1,9 @@ file: README G. Moody 1 June 1989 - Last revised: 24 May 2000 + Last revised: 8 October 2001 ------------------------------------------------------------------------------- WFDB applications: programs for working with annotated signals -Copyright (C) 2000 George B. Moody +Copyright (C) 2001 George B. Moody These programs are free software; you can redistribute them and/or modify them under the terms of the GNU General Public License as published by the @@ -44,17 +44,18 @@ application by running it without any command-line arguments. Before using any of the applications, you will need to have database files -for input. The contents of the `microdb' directory, on the same level as this +for input. The contents of the `data' directory, on the same level as this one, will get you started if no others are available. The following files will be found in this directory: Makefile UNIX `make' description file for compiling these applications -Makefile-dos-gcc UNIX `make' description file for compiling these appliccations - for MS-DOS using a gcc cross-compiler under UNIX Makefile.dos MS-DOS `make' description file for compiling these applications using Microsoft `make' or `nmake', Borland `make', etc. +Makefile.top Used by ../configure to construct Makefile (comments only) +Makefile.tpl Used by ../configure to construct Makefile (portable section) README this file +ann2rr.c Converts an annotation file to an RR interval series bxb.c AAMI-standard beat-by-beat annotation comparator calsig.c Calibrates signals of a database record cshsetwfdb Template for C-shell WFDB path initialization script @@ -68,12 +69,15 @@ mxm.c AAMI-standard measurement-by-measurement annotation comparator nst.c Mixes noise with ECGs for noise stress tests plotstm.c Produces a PostScript scatter plot of ST measurement errors +pscgen.c Generate a 'pschart' script from an annotation file pschart.c Makes annotated `chart recordings' on PostScript devices pschart.pro PostScript prolog file for use with `pschart' +12lead.pro Alternate prolog for printing 12-lead ECGs using `pschart' psfd.c Makes annotated `full-disclosure' plots on PostScript devices -pschart.pro PostScript prolog file for use with `psfd' +psfd.pro PostScript prolog file for use with `psfd' rdann.c Reads annotations and prints them rdsamp.c Reads signals and prints them +rr2ann.c Converts an RR interval series into an annotation file rxr.c AAMI-standard run-by-run annotation comparator sampfreq.c Prints the sampling frequency of a record sample.c Digitizes and replays analog signals (MS-DOS only) @@ -92,6 +96,7 @@ annotation file view.c ECG database browser for MS-DOS (using Microsoft C graphics) vsetup.c CRT calibration program for use with `view' (MS-DOS only) +wfdbcat.c Copies a WFDB file to standard output wfdbcollate.c Collates multiple WFDB records into a multi-segment record wfdbdesc.c Describes signals based on header file contents wfdbwhich.c Finds a WFDB file and prints its pathname diff -Naur wfdb-10.1.6/app/calsig.c wfdb-10.2.0/app/calsig.c --- wfdb-10.1.6/app/calsig.c Wed May 24 16:18:23 2000 +++ wfdb-10.2.0/app/calsig.c Tue Oct 9 13:18:30 2001 @@ -1,9 +1,9 @@ /* file: calsig.c G. Moody 4 March 1991 - Last revised: 24 May 2000 + Last revised: 9 October 2001 ------------------------------------------------------------------------------- calsig: measure gains and baselines in a DB record and rewrite header -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -75,29 +75,29 @@ #define UNITSLEN 20 -int nsig; -static char units[WFDB_MAXSIG][UNITSLEN+1]; -static double high[WFDB_MAXSIG], low[WFDB_MAXSIG]; -static int do_cal[WFDB_MAXSIG]; -static int dc[WFDB_MAXSIG]; /* dc[i] is 1 if signal i is DC-coupled */ -static struct info_rec { +int isiglist = 0, ncsig = 0, nsig; +int *vhigh, *vlow; +char **units; +double *high, *low; +int *do_cal; +int *dc; /* dc[i] is 1 if signal i is DC-coupled */ +struct info_rec { struct info_rec *next; char *info_string; } *first_rec, *current_rec, *last_rec; char *pname, *prog_name(); void rewrite_header(), help(); -static WFDB_Siginfo s[WFDB_MAXSIG]; -static WFDB_Sample b[WFDB_MAXSIG]; -static WFDB_Gain g[WFDB_MAXSIG]; +WFDB_Siginfo *s; +WFDB_Sample *b; +WFDB_Gain *g; main(argc, argv) int argc; char *argv[]; { char *cfname=NULL, *p, *record = NULL, *t0p = NULL, *t1p = NULL, *getenv(); - int do_skip = 1, *h[WFDB_MAXSIG], *ho[WFDB_MAXSIG], i, multi_seg = 0, - n = 0, o[WFDB_MAXSIG], qflag = 0, Qflag = 0, v[WFDB_MAXSIG], vflag = 0, - vmax[WFDB_MAXSIG], vmin[WFDB_MAXSIG]; + int do_skip = 1, **h, **ho, i, multi_seg = 0, n = 0, *o, qflag = 0, + Qflag = 0, *v, vflag = 0, *vmax, *vmin; long nsamp, t, t0 = 0L, t1; /* Read and interpret command-line arguments. */ @@ -137,20 +137,14 @@ } record = argv[i]; break; - case 's': - while (++i < argc && *argv[i] != '-') { - int sig; - - sig = atoi(argv[i]); - if (0 <= sig && sig < WFDB_MAXSIG) { - do_cal[sig] = 1; - n++; - } + case 's': /* signal list follows */ + isiglist = i+1; /* index of first argument containing a signal # */ + while (i+1 < argc && *argv[i+1] != '-') { + i++; + ncsig++; /* number of elements in signal list */ } - --i; - if (n < 1) { - (void)fprintf(stderr, - "%s: one or more signal numbers must follow -s\n", + if (ncsig == 0) { + (void)fprintf(stderr, "%s: signal list must follow -s\n", pname); exit(1); } @@ -185,20 +179,51 @@ } /* Open the record. */ - if ((nsig = isigopen(record, s, WFDB_MAXSIG)) < 1) exit(2); + if ((nsig = isigopen(record, NULL, 0)) < 1) exit(2); + if ((s = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL || + (b = malloc(nsig * sizeof(WFDB_Sample))) == NULL || + (g = malloc(nsig * sizeof(WFDB_Gain))) == NULL || + (units = malloc(nsig * sizeof(char **))) == NULL || + (high = malloc(nsig * sizeof(double))) == NULL || + (low = malloc(nsig * sizeof(double))) == NULL || + (do_cal = malloc(nsig * sizeof(int))) == NULL || + (dc = malloc(nsig * sizeof(int))) == NULL || + (vhigh = malloc(nsig * sizeof(int))) == NULL || + (vlow = malloc(nsig * sizeof(int))) == NULL || + (h = malloc(nsig * sizeof(int *))) == NULL || + (ho = malloc(nsig * sizeof(int *))) == NULL || + (o = malloc(nsig * sizeof(int))) == NULL || + (v = malloc(nsig * sizeof(int))) == NULL || + (vmax = malloc(nsig * sizeof(int))) == NULL || + (vmin = malloc(nsig * sizeof(int))) == NULL) { + fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + for (i = 0; i < nsig; i++) + if ((units[i] = malloc((UNITSLEN+1) * sizeof(char))) == NULL) { + fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + if (isigopen(record, s, nsig) != nsig) exit(2); + if (strtim("e") != s[0].nsamp) multi_seg = 1; /* If a signal list was provided, validate it; otherwise, generate one. */ - if (n > 0) { - for (i = nsig; i < WFDB_MAXSIG; i++) - if (do_cal[i]) { do_cal[i] = 0; n--; } + if (isiglist > 0) { + for (i = 0; i < nsig; i++) + do_cal[i] = 0; + for (i = 0; i < ncsig; i++) { + n = atoi(argv[isiglist+i]); + if (0 <= n && n < nsig) + do_cal[i] = 1; + } } else { for (i = 0; i < nsig; i++) do_cal[i] = 1; - n = nsig; + ncsig = nsig; } - if (n < 1) { + if (ncsig < 1) { (void)fprintf(stderr, "%s: no signals to be calibrated\n", pname); exit(2); } @@ -318,7 +343,7 @@ endpoints as representing the high and low values of the calibration pulse. */ if (qflag) { - int vhigh[WFDB_MAXSIG], vlow[WFDB_MAXSIG], vtemp; + int vtemp; if (getvec(vlow) < nsig) exit(2); if (do_skip) { @@ -345,8 +370,6 @@ takes the maximum and minimum sample values as representing the high and low values of the calibration pulse. */ else if (Qflag) { - int vhigh[WFDB_MAXSIG], vlow[WFDB_MAXSIG]; - if (getvec(vlow) < nsig) exit(2); for (i = 0; i < nsig; i++) vhigh[i] = vlow[i]; @@ -375,14 +398,12 @@ for (i = 0; i < nsig; i++) if (do_cal[i]) { if (s[i].adcres < 1) s[i].adcres = WFDB_DEFRES; -#ifndef lint if ((h[i] = (int *)calloc((unsigned)(1<> 8) < 8) wl = 8; -#ifndef lint if ((r = (int *)malloc((unsigned)(wl+1)*sizeof(int))) == NULL){ (void)fprintf(stderr, "%s: insufficient memory\n", pname); exit(3); } -#endif for (jj = 0; jj < wl+1; jj++) r[jj] = (jj >= (wl/2)+1) ? hp[jj-(wl/2)-1] : 0; /* hs is the smoothed histogram value for bin j, and dhs is the @@ -529,7 +548,7 @@ for (p = buf; *p && *p != ' '; p++) ; *p = '\0'; - (void)isigopen(buf, s, -WFDB_MAXSIG); + (void)isigopen(buf, s, -nsig); rewrite_header(buf); wfdbquit(); } diff -Naur wfdb-10.1.6/app/fir.c wfdb-10.2.0/app/fir.c --- wfdb-10.1.6/app/fir.c Sat Mar 11 11:52:29 2000 +++ wfdb-10.2.0/app/fir.c Tue Oct 9 10:35:00 2001 @@ -1,9 +1,9 @@ /* file: fir.c G. Moody 5 January 1987 - Last revised: 11 March 2000 + Last revised: 9 October 2001 ------------------------------------------------------------------------------- fir: General-purpose FIR filter for database records -Copyright (C) 2000 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -30,6 +30,11 @@ #ifndef __STDC__ extern void exit(); #endif +#ifndef NOMALLOC_H +#include +#else +extern char *malloc(), *calloc(), *realloc(); +#endif #include @@ -82,11 +87,10 @@ char *argv[]; { char *irec = "16", *orec = "16"; - char *calloc(), *realloc(); double *tc = NULL, atof(); int i, n = 128, s; long from = 0L, shift = 0L, to = 0L; - static WFDB_Siginfo chin[WFDB_MAXSIG], chout[WFDB_MAXSIG]; + static WFDB_Siginfo *chin, *chout; FILE *ifile; pname = prog_name(argv[0]); @@ -94,10 +98,8 @@ if (*argv[i] == '-') switch (*(argv[i]+1)) { case 'c': /* filter coefficients follow */ flen = argc - (++i); -#ifndef lint if ((c=tc=(double *)calloc((unsigned)flen,sizeof(double))) == NULL) memerr(); -#endif while (i < argc) *tc++ = atof(argv[i++]); break; @@ -110,16 +112,12 @@ (void)fprintf(stderr, "%s: can't open %s\n", pname, argv[i]); exit(1); } -#ifndef lint if ((c = (double *)calloc((unsigned)n,sizeof(double))) == NULL) memerr(); -#endif while (fscanf(ifile, "%lf", &c[flen]) == 1) if (++flen >= n) { n += 128; -#ifndef lint c=(double *)realloc((char *)c,(unsigned)n*sizeof(double)); -#endif if (c == NULL) memerr(); } @@ -201,7 +199,13 @@ help(); exit(1); } - if ((nsig = isigopen(irec, chin, WFDB_MAXSIG)) <= 0) + if ((nsig = isigopen(irec, NULL, 0)) <= 0) + exit(2); + if ((chin = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL || + (chout = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL) { + memerr(); + } + if (isigopen(irec, chin, nsig) != nsig) exit(2); if (nrec) { static char ofname[WFDB_MAXRNL+5]; @@ -228,14 +232,12 @@ if (to > 0L) to = strtim(argv[to]); nsamp = (to > 0L) ? to - from : -1L; -#ifndef lint if ((vout = (int *)calloc((unsigned)nsig, sizeof(int))) == NULL || (vin = (int **)calloc((unsigned)flen, sizeof(int *))) == NULL) memerr(); for (i = 0; i < flen; i++) if ((vin[i] = (int *)calloc((unsigned)nsig, sizeof(int))) == NULL) memerr(); -#endif if (shift > 0) { shift = strtim(argv[shift]); i = flen - (shift % flen); diff -Naur wfdb-10.1.6/app/mfilt.c wfdb-10.2.0/app/mfilt.c --- wfdb-10.1.6/app/mfilt.c Sun Jan 30 04:13:16 2000 +++ wfdb-10.2.0/app/mfilt.c Tue Oct 9 12:44:02 2001 @@ -1,9 +1,9 @@ /* file: mfilt.c G. Moody 27 June 1993 - Last revised: 30 April 1999 + Last revised: 9 October 2001 ------------------------------------------------------------------------------- mfilt: General-purpose median filter for database records -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -29,7 +29,11 @@ #ifndef __STDC__ extern void exit(); #endif - +#ifndef NOMALLOC_H +#include +#else +extern char *malloc(), *calloc(), *realloc(); +#endif #include char *pname; /* name by which this program was invoked */ @@ -39,7 +43,7 @@ int nsig; /* number of signals to be filtered */ int **vin; /* pointers to input vectors */ int *vtemp; /* temporary array for calculating medians */ -int vout[WFDB_MAXSIG]; /* output vector */ +int *vout; /* output vector */ long from = 0L; /* first sample to be processed */ long to = 0L; /* (if > 0) sample following last sample to be processed */ long spm; /* samples per minute */ @@ -104,9 +108,9 @@ int argc; char *argv[]; { - char *irec = "16", ofname[40], *orec = "16", *calloc(); + char *irec = "16", *ofname, *orec = "16"; int format, i; - static WFDB_Siginfo si[WFDB_MAXSIG], so[WFDB_MAXSIG]; + static WFDB_Siginfo *si, *so; pname = prog_name(argv[0]); for (i = 1; i < argc; i++) { @@ -178,19 +182,23 @@ } median = flen/2; - if ((nsig = isigopen(irec, si, WFDB_MAXSIG)) <= 0) + if ((nsig = isigopen(irec, NULL, 0)) <= 0) exit(2); - -#ifndef lint - if ((vtemp = (int *)calloc((unsigned)flen, sizeof(int))) == NULL || - (vin = (int **)calloc((unsigned)flen, sizeof(int *))) == NULL) + if ((si = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo))) == NULL || + (so = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo))) == NULL || + (vtemp = (int *)calloc((unsigned)flen, sizeof(int))) == NULL || + (vin = (int **)calloc((unsigned)flen, sizeof(int *))) == NULL || + (vout = (int *)malloc(nsig * sizeof(int))) == NULL) memerr(); for (i = 0; i < flen; i++) if ((vin[i] = (int *)calloc((unsigned)nsig, sizeof(int))) == NULL) memerr(); -#endif + if (isigopen(irec, si, (unsigned)nsig) != nsig) + exit(2); if (nrec) { + if ((ofname = (char *)malloc(strlen(nrec)+5)) == NULL) + memerr(); (void)sprintf(ofname, "%s.dat", nrec); format = si[0].fmt; for (i = 0; i < nsig; i++) { @@ -200,7 +208,7 @@ if (osigfopen(si, (unsigned)nsig) < nsig) exit(2); } - else if ((nsig = osigopen(orec, so, (unsigned)nsig)) <= 0) + else if (osigopen(orec, so, (unsigned)nsig) != nsig) exit(2); if (from > 0L) { @@ -217,13 +225,11 @@ tt = from + spm; /* time to print next progress indicator */ } -#ifndef lint void memerr() { (void)fprintf(stderr, "%s: insufficient memory\n", pname); exit(2); } -#endif char *prog_name(s) char *s; diff -Naur wfdb-10.1.6/app/nst.c wfdb-10.2.0/app/nst.c --- wfdb-10.1.6/app/nst.c Sun Jan 30 04:13:16 2000 +++ wfdb-10.2.0/app/nst.c Wed Oct 10 12:18:37 2001 @@ -1,9 +1,9 @@ /* file: nst.c G. Moody 8 December 1983 - Last revised: 19 September 1999 + Last revised: 10 October 2001 ------------------------------------------------------------------------------- nst: Noise stress test -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -32,17 +32,20 @@ #else #include #endif +#ifdef NOMKSTEMP +#define mkstemp mktemp +#endif #ifdef __STDC__ # include # if _MSC_VER >= 700 -# define mktemp _mktemp +# define mkstemp _mktemp # define unlink _unlink # endif #else extern double atof(); extern void exit(); # ifdef NOMALLOC_H -extern char *malloc(); +extern char *calloc(), *malloc(), *realloc(); # else # include # endif @@ -50,10 +53,6 @@ #include #include -#ifdef lint -char *mktemp(); /* just to keep lint happy -- return value not used */ -#endif - /* Define the WFDB path component separator (OS-dependent). */ #ifdef MSDOS /* for MS-DOS, OS/2, etc. */ # define PSEP ';' @@ -66,8 +65,9 @@ #endif char *pname, *prog_name(); -int format = 16; /* format for output signal file */ -static WFDB_Siginfo si[WFDB_MAXSIG]; +double *gn; +int format = 16, nisig, nnsig, *nse, *vin, *vout, *z, *zz; +WFDB_Siginfo *si; main(argc, argv) int argc; @@ -75,11 +75,9 @@ { static char answer[10], buf[256], *wfdbp, irec[10], nrec[21], nnrec[20], orec[10], refaname[10], *protocol, tfname[9], *p, *s; - double anoise[WFDB_MAXSIG], asig[WFDB_MAXSIG], nsr, r[WFDB_MAXSIG], - snr = -999999.0; - static double g[WFDB_MAXSIG], nsf, ssf; + double *anoise, *asig, *g, nsf = 0.0, nsr, *r, snr = -999999.0, ssf = 0.0; FILE *ifile; - int i, nisig, nnsig; + int i; long t, t0, tf, dt; WFDB_Anninfo ai; static WFDB_Annotation annot; @@ -160,25 +158,25 @@ } } - /* Make sure that the WFDB path begins with an empty component (otherwise, - nst may not be able to find the protocol file it generates). */ + /* Make sure that the WFDB path begins with a '.' (current directory) + component or an empty component (otherwise, nst may not be able to find + the protocol file it generates). */ wfdbp = getwfdb(); - if (*wfdbp != PSEP) { -#ifndef lint + if (*wfdbp != PSEP && + !(*wfdbp = '.' && ((*wfdbp+1) == PSEP || *(wfdbp+1) == ' '))) { char *nwfdbp; if ((nwfdbp = (char *)malloc(strlen(wfdbp+2))) == NULL) { - fprintf(stderr, "%s: memory allocation error\n", pname); + fprintf(stderr, "%s: insufficient memory\n", pname); exit(1); } (void)sprintf(nwfdbp, "%c%s", PSEP, wfdbp); setwfdb(nwfdbp); -#endif } /* Generate a temporary file name for use below. */ (void)strcpy(tfname, "nsXXXXXX"); - (void)mktemp(tfname); + (void)mkstemp(tfname); /* Set the reference annotator name if it was not specified with -a. */ if (refaname[0] == '\0') @@ -220,6 +218,33 @@ orec[strlen(orec)-1] = '\0'; } + /* Count the input signals. */ + if ((nisig = isigopen(irec, NULL, 0)) < 1) exit(2); + wfdbquiet(); /* suppress warning if sampling frequencies don't match */ + if ((nnsig = isigopen(nrec, NULL, 0)) < 1) { + (void)fprintf(stderr, "%s: can't read record %s\n", pname, nrec+1); + exit(2); + } + wfdbverbose(); + + /* Allocate storage. */ + if ((si = malloc((nisig+nnsig) * sizeof(WFDB_Siginfo))) == NULL || + (anoise = malloc(nnsig * sizeof(double))) == NULL || + (asig = malloc(nisig * sizeof(double))) == NULL || + (r = malloc(nisig * sizeof(double))) == NULL || + (g = malloc(nisig * sizeof(double))) == NULL || + (gn = malloc(nisig * sizeof(double))) == NULL || + (nse = malloc(nisig * sizeof(int))) == NULL || + (vin = malloc(nisig * sizeof(int))) == NULL || + (vout = malloc(nisig * sizeof(int))) == NULL || + (z = calloc(nisig, sizeof(int))) == NULL || + (zz = calloc(nisig, sizeof(int))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + for (i = 0; i < nisig; i++) + g[i] = 0.; + /* If the protocol was unspecified, generate one. */ if (protocol == (char*)NULL) { /* Get the SNR if it was not specified using -s. */ @@ -242,11 +267,11 @@ "%s: can't read temporary file %s\n", pname, tfname); exit(1); } - for (nnsig = 1; fscanf(ifile, "%lf", &anoise[nnsig]) == 1; nnsig++) { - if (anoise[nnsig] == 0.0) { + for (i = 1; fscanf(ifile, "%lf", &anoise[i]) == 1; i++) { + if (anoise[i] == 0.0) { (void)fprintf(stderr, "%s: noise signal %d amplitude is zero -- can't normalize\n", - pname, nnsig); + pname, i); exit(2); } } @@ -263,11 +288,11 @@ tfname); exit(1); } - for (nisig = 1; fscanf(ifile, "%lf", &asig[nisig]) == 1; nisig++) { - if (asig[nisig] == 0.0) { + for (i = 1; fscanf(ifile, "%lf", &asig[i]) == 1; i++) { + if (asig[i] == 0.0) { (void)fprintf(stderr, "%s: ECG signal %d amplitude is zero -- can't normalize\n", - pname, nisig); + pname, i); exit(2); } } @@ -367,7 +392,7 @@ (void)strcpy(nrec+1, nnrec); } else { - if ((nnsig = isigopen(nrec+1, si, -WFDB_MAXSIG)) <= 0) { + if (isigopen(nrec+1, si, -nnsig) != nnsig) { (void)fprintf(stderr, "\n%s: can't read record %s\n", pname, nrec+1); exit(2); @@ -417,21 +442,18 @@ double snr; { char buf[80], ofname[20], *p; - int errct = 0, i, nisig, nnsig, nse[WFDB_MAXSIG-1], vin[WFDB_MAXSIG], - vout[WFDB_MAXSIG-1]; - static int z[WFDB_MAXSIG-1], zz[WFDB_MAXSIG-1]; + int errct = 0, i; long nlen, nend, t = 0L, dt, next_tick; - double gn[WFDB_MAXSIG-1]; WFDB_Annotation annot; WFDB_Anninfo ai; - /* Initialization section. Open ECG signals first. */ - if ((nisig = isigopen(irec, si, WFDB_MAXSIG-1)) < 1) exit(2); + /* Open ECG signals. */ + if (isigopen(irec, si, nisig) != nisig) exit(2); /* Open the noise record. */ wfdbquiet(); - if ((nnsig = isigopen(nrec, si+nisig, WFDB_MAXSIG-nisig)) < 1) { - (void)fprintf(stderr, "%s: can't read record %s\n", nrec+1); + if (isigopen(nrec, si+nisig, nnsig) != nnsig) { + (void)fprintf(stderr, "%s: can't read record %s\n", pname, nrec+1); exit(2); } wfdbverbose(); diff -Naur wfdb-10.1.6/app/pschart.c wfdb-10.2.0/app/pschart.c --- wfdb-10.1.6/app/pschart.c Wed Jan 10 12:36:46 2001 +++ wfdb-10.2.0/app/pschart.c Fri Oct 12 11:42:58 2001 @@ -1,9 +1,9 @@ /* file: pschart.c G. Moody 15 March 1988 - Last revised: 10 January 2001 + Last revised: 12 October 2001 ------------------------------------------------------------------------------- pschart: Produce annotated `chart recordings' on a PostScript device -Copyright (C) 2000 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -43,10 +43,11 @@ #else extern double atof(); extern void exit(); +typedef long time_t; # ifndef NOMALLOC_H # include # else -extern char *calloc(), *malloc(); +extern char *calloc(), *malloc(), *realloc(); # endif #endif #ifndef BSD @@ -164,7 +165,6 @@ bars */ int numberpages = 1; /* if zero, suppress page numbering */ int nosig = 0; /* number of signals to be printed */ -int nosiglist = 1; /* if non-zero, no signal list specified */ int page = 1; /* logical page number */ int pages_written = 0; /* number of pages written already */ int prolog_written = 0; /* if non-zero, prolog has been written */ @@ -173,13 +173,14 @@ int pflag = 0; /* if non-zero, pack strips side-by-side */ int rflag = 0; /* if non-zero, print record names */ int Rflag = 0; /* if non-zero, print record name in header */ -int siglist[WFDB_MAXSIG]; /* list of signals to be printed */ +int sflag = 0; /* if non-zero, a signal list was specified */ +int *siglist; /* list of signals to be printed */ int smode = 1; /* scale mode (0: no scales; 1: mm/unit in footers; 2: units/tick in footers; 3: mm/unit above strips; 4: units/tick above strips; 5: mm/unit within strips; 6: units/ tick within strips) */ - +char *sqstr; /* signal quality string (1 char/signal) */ double tpmv = TPMV; /* grid ticks per millivolt */ double tps = TPS; /* grid ticks per second */ double tscale = TSCALE; /* time scale (mm/second) */ @@ -225,18 +226,12 @@ { char *p, *getenv(); FILE *cfile = NULL; - int i; + int i, j; struct pscolor *colorp; struct tm *now; -#ifdef __STDC__ time_t t, time(); t = time((time_t *)NULL); /* get current time from system clock */ -#else - long t, time(); - - t = time((long *)NULL); -#endif now = localtime(&t); pname = prog_name(argv[0]); @@ -459,22 +454,25 @@ Rflag = 1; break; case 's': /* specify signals to be printed */ - if (++i >= argc || *argv[i] < '0' || *argv[i] > '9') { + sflag = 1; + /* count the number of output signals */ + for (j = 0; ++i < argc && *argv[i] != '-'; j++) + ; + if (j == 0) { (void)fprintf(stderr, "%s: signal list must follow -s\n", pname); exit(1); } - nosig = 0; - while (i < argc && '0' <= *argv[i] && *argv[i] <= '9') { - if (nosig == WFDB_MAXSIG) { - (void)fprintf(stderr, - "%s: too many output signals\n", pname); - exit(1); - } - siglist[nosig++] = atoi(argv[i++]); + /* allocate storage for the signal list and for sqstr */ + if ((siglist=realloc(siglist, (nosig+j) * sizeof(int))) == NULL || + (sqstr = realloc(sqstr, (nosig+j+1) * sizeof(char))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); } + /* fill the signal list */ + for (i -= j; i < argc && *argv[i] != '-'; ) + siglist[nosig++] = atoi(argv[i++]); i--; - nosiglist = 0; break; case 'S': /* set modes for scale and time stamp printing */ if (i >= argc-2 || @@ -559,16 +557,21 @@ /* Parameters set from the WFDB header file */ int nisig; /* number of signals in current record */ +int nimax; /* largest value for nisig seen so far */ int nsig; /* number of signals to be printed */ double sps; /* sampling frequency (samples/second/signal) */ -WFDB_Siginfo s[WFDB_MAXSIG]; /* signal parameters, including gain */ -int uncal[WFDB_MAXSIG]; /* if non-zero, signal is uncalibrated */ +WFDB_Siginfo *s; /* signal parameters, including gain */ +int *uncal; /* if non-zero, signal is uncalibrated */ + +/* Arrays indexed by signal # (allocated by process(), used by printstrip()) */ +int *buflen, *v, *vbase, **vbuf, *vmax, *vmin; +long *vsum; /* Derived parameters */ double dpmm = DPI/25.4; /* pixels per millimeter */ double dppt; /* pixels per PostScript "printer's point" (PostScript "printer's points" are 1/72 inch; true printer's - points are 1/72.27 inch */ + points are 1/72.27 inch) */ double dpsi; /* pixels per sample interval */ int nsamp; /* number of samples/signal/strip */ double sdur; /* strip duration in seconds */ @@ -634,11 +637,35 @@ tstring = strtok((char *)NULL, " \t\n"); title = strtok((char *)NULL, "\n"); for (i = 0; i < nisig; i++) - uncal[siglist[i]] = 0; + uncal[i] = 0; if (tokptr == NULL || tstring == NULL || - (nisig = isigopen(record, s, WFDB_MAXSIG)) < 0) continue; + (nisig = isigopen(record, NULL, 0)) < 0) continue; + if (nisig > nimax) { + if ((s = realloc(s, nisig * sizeof(WFDB_Siginfo))) == NULL || + (buflen = realloc(buflen, nisig * sizeof(int))) == NULL || + (uncal = realloc(uncal, nisig * sizeof(int))) == NULL || + (v = realloc(v, nisig * sizeof(int))) == NULL || + (vbase = realloc(vbase, nisig * sizeof(int))) == NULL || + (vmax = realloc(vmax, nisig * sizeof(int))) == NULL || + (vmin = realloc(vmin, nisig * sizeof(int))) == NULL || + (vsum = realloc(vsum, nisig * sizeof(long))) == NULL || + (vbuf = realloc(vbuf, nisig * sizeof(int *))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + if (!sflag && + ((siglist = realloc(siglist,nisig*sizeof(int))) == NULL || + (sqstr =realloc(sqstr,(nisig+1)*sizeof(char))) == NULL)) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + while (nimax < nisig) + buflen[nimax++] = 0; + } + if (isigopen(record, s, nisig) != nisig) + continue; (void)setpagetitle(0L); - if (nosiglist) { + if (!sflag) { for (i = 0; i < nisig; i++) siglist[i] = i; nsig = nosig = nisig; @@ -648,7 +675,7 @@ if (siglist[i] < 0 || siglist[i] >= nisig) { (void)fprintf(stderr, "record %s doesn't have a signal %d\n", - record, siglist[i]); + record, siglist[i]); wfdbquit(); return; } @@ -708,9 +735,6 @@ double curr_s_top; int i, j; int jmax, tm_y, *vp, x0, y0, ya[2]; - int v[WFDB_MAXSIG], vbase[WFDB_MAXSIG], vmax[WFDB_MAXSIG], vmin[WFDB_MAXSIG]; - long vsum[WFDB_MAXSIG]; - static int buflen[WFDB_MAXSIG], *vbuf[WFDB_MAXSIG]; /* Allocate buffers for the samples to be plotted, and initialize the range variables. */ @@ -724,12 +748,10 @@ vbuf[sig] = NULL; buflen[sig] = 0; } -#ifndef lint if ((vbuf[sig]=(int *)calloc((unsigned)nsamp,sizeof(int)))==NULL) { (void)fprintf(stderr, "insufficient memory\n"); return (0); } -#endif buflen[sig] = nsamp; } } @@ -1056,7 +1078,6 @@ if (aflag) { static WFDB_Annotation annot; int x, y, c; - char buf[WFDB_MAXSIG+1]; unsigned int ia; if (iannsettime(t0) < 0 && nann == 1) return (1); @@ -1090,17 +1111,17 @@ int j = siglist[i]; if (j > 3) - buf[i] = '*'; /* quality of input signal j + sqstr[i] = '*'; /* quality of input signal j is undefined */ else if (annot.subtyp & (0x10 << j)) - buf[i] = 'u'; /* signal j is unreadable */ + sqstr[i] = 'u'; /* signal j is unreadable */ else if (annot.subtyp & (0x01 << j)) - buf[i] = 'n'; /* signal j is noisy */ + sqstr[i] = 'n'; /* signal j is noisy */ else - buf[i] = 'c'; /* signal j is clean */ + sqstr[i] = 'c'; /* signal j is clean */ } - buf[i] = '\0'; - label(buf); + sqstr[i] = '\0'; + label(sqstr); break; case STCH: case TCH: diff -Naur wfdb-10.1.6/app/psfd.c wfdb-10.2.0/app/psfd.c --- wfdb-10.1.6/app/psfd.c Sun Jan 30 04:13:16 2000 +++ wfdb-10.2.0/app/psfd.c Fri Oct 12 11:43:15 2001 @@ -1,9 +1,9 @@ /* file: psfd.c G. Moody 9 August 1988 - Last revised: 14 September 1999 + Last revised: 12 October 2001 ------------------------------------------------------------------------------- psfd: Produces annotated full-disclosure ECG plots on a PostScript device -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -50,10 +50,11 @@ #else extern double atof(); extern void exit(); +typedef long time_t; # ifndef NOMALLOC_H # include # else -extern char *calloc(), *malloc(); +extern char *calloc(), *malloc(), *realloc(); # endif #endif #ifndef BSD @@ -162,15 +163,16 @@ bars */ int numberpages = 1; /* if zero, suppress page numbering */ int nosig = 0; /* number of signals to be printed */ -int nosiglist = 1; /* if non-zero, no signal list specified */ int page = 1; /* logical page number */ int pages_written = 0; /* number of pages written already */ char *pagetitle = NULL; /* if not null, title for page header */ char *pname; /* the name by which this program is invoked */ int rflag = 0; /* if non-zero, print record names */ -int siglist[WFDB_MAXSIG]; /* list of signals to be printed */ +int sflag = 0; /* if non-zero, a signal list was specified */ +int *siglist; /* list of signals to be printed */ int smode = 1; /* scale mode (0: no scales; 1: mm/unit in footers; 2: units/tick in footers) */ +char *sqstr; /* signal quality string (1 char/signal) */ double t_hideal = 7.5; /* ideal value for t_height (see below) */ double tscale = TSCALE; /* time scale (mm/second) */ int tsmode = 2; /* time stamp mode (0: no time stamps; 1: @@ -196,17 +198,11 @@ { char *getenv(); FILE *cfile = NULL; - int i; + int i, j; struct tm *now; -#ifdef __STDC__ time_t t, time(); t = time((time_t *)NULL); /* get current time from system clock */ -#else - long t, time(); - - t = time((long *)NULL); -#endif now = localtime(&t); pname = prog_name(argv[0]); @@ -372,22 +368,25 @@ rflag = 1 - rflag; break; case 's': /* specify signals to be printed */ - if (++i >= argc) { + sflag = 1; + /* count the number of output signals */ + for (j = 0; ++i < argc && *argv[i] != '-'; j++) + ; + if (j == 0) { (void)fprintf(stderr, "%s: signal list must follow -s\n", - argv[0]); + pname); exit(1); } - nosig = 0; - while (i < argc && *argv[i] != '-') { - if (nosig == WFDB_MAXSIG) { - (void)fprintf(stderr, - "%s: too many output signals\n", argv[0]); - exit(1); - } - siglist[nosig++] = atoi(argv[i++]); + /* allocate storage for the signal list and for sqstr */ + if ((siglist=realloc(siglist, (nosig+j) * sizeof(int))) == NULL || + (sqstr = realloc(sqstr, (nosig+j+1) * sizeof(char))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); } + /* fill the signal list */ + for (i -= j; i < argc && *argv[i] != '-'; ) + siglist[nosig++] = atoi(argv[i++]); i--; - nosiglist = 0; break; case 'S': /* set modes for scale and time stamp printing */ if (i >= argc-2 || @@ -476,17 +475,22 @@ /* Parameters set from the WFDB header file */ int nisig; /* number of signals in current record */ +int nimax; /* largest value for nisig seen so far */ int nsig; /* number of signals to be printed */ double sps; /* sampling frequency (samples/second/signal) */ -WFDB_Siginfo s[WFDB_MAXSIG]; /* signal parameters, including gain */ -int uncal[WFDB_MAXSIG]; /* if non-zero, signal is uncalibrated */ +WFDB_Siginfo *s; /* signal parameters, including gain */ +int *uncal; /* if non-zero, signal is uncalibrated */ + +/* Arrays indexed by signal # (allocated by process(), used by printstrip()) */ +int *buflen, *reject, *v, *vbase, **vbuf, *vmax, *vmin; +long *vs, *vsum; /* Derived parameters */ int decf; /* decimation factor (input samples/output sample) */ double dpmm; /* pixels per millimeter */ double dppt; /* pixels per PostScript "printer's point" (PostScript "printer's points" are 1/72 inch; true printer's - points are 1/72.27 inches) */ + points are 1/72.27 inch) */ double dpsi; /* pixels per sample interval */ long nisamp; /* number of input samples/signal/strip */ int nosamp; /* number of output samples/signal/strip */ @@ -558,11 +562,37 @@ continue; (void)strcpy(record, rstring); for (i = 0; i < nisig; i++) - uncal[siglist[i]] = 0; - if ((nisig = isigopen(record, s, WFDB_MAXSIG)) < 1) + uncal[i] = 0; + if ((nisig = isigopen(record, NULL, 0)) < 1) + continue; + if (nisig > nimax) { + if ((s = realloc(s, nisig * sizeof(WFDB_Siginfo))) == NULL || + (buflen = realloc(buflen, nisig * sizeof(int))) == NULL || + (reject = realloc(reject, nisig * sizeof(int))) == NULL || + (uncal = realloc(uncal, nisig * sizeof(int))) == NULL || + (v = realloc(v, nisig * sizeof(int))) == NULL || + (vbase = realloc(vbase, nisig * sizeof(int))) == NULL || + (vmax = realloc(vmax, nisig * sizeof(int))) == NULL || + (vmin = realloc(vmin, nisig * sizeof(int))) == NULL || + (vs = realloc(vs, nisig * sizeof(long))) == NULL || + (vsum = realloc(vsum, nisig * sizeof(long))) == NULL || + (vbuf = realloc(vbuf, nisig * sizeof(int *))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + if (!sflag && + ((siglist = realloc(siglist,nisig*sizeof(int))) == NULL || + (sqstr =realloc(sqstr,(nisig+1)*sizeof(char))) == NULL)) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + while (nimax < nisig) + buflen[nimax++] = 0; + } + if (isigopen(record, s, nisig) != nisig) continue; (void)setpagetitle(0L); - if (nosiglist) { + if (!sflag) { for (i = 0; i < nisig; i++) siglist[i] = i; nsig = nosig = nisig; @@ -572,7 +602,7 @@ if (siglist[i] < 0 || siglist[i] >= nisig) { (void)fprintf(stderr, "record %s doesn't have a signal %d\n", - record, siglist[i]); + record, siglist[i]); wfdbquit(); return; } @@ -663,12 +693,8 @@ char *ts; double curr_s_top; int i, k; - long j, jmax, vs[WFDB_MAXSIG]; + long j, jmax; int nstrips, tm_y, tt, ttmax, *vp, x0, y0, ya[2]; - int v[WFDB_MAXSIG], vbase[WFDB_MAXSIG], vmax[WFDB_MAXSIG], vmin[WFDB_MAXSIG]; - long vsum[WFDB_MAXSIG]; - int reject[WFDB_MAXSIG]; - static int buflen[WFDB_MAXSIG], *vbuf[WFDB_MAXSIG]; /* Allocate buffers for the samples to be plotted, and initialize the range and filter variables. */ @@ -682,13 +708,11 @@ vbuf[sig] = NULL; buflen[sig] = 0; } -#ifndef lint if ((vbuf[sig] = (int *)calloc((unsigned)nosamp, sizeof(int))) == NULL) { (void)fprintf(stderr, "insufficient memory\n"); return (0); } -#endif buflen[sig] = nosamp; } } @@ -937,7 +961,6 @@ if (aflag) { static WFDB_Annotation annot; int x, y, c; - char buf[WFDB_MAXSIG+1]; unsigned int ia; if (iannsettime(t0) < 0 && nann == 1) return (1); @@ -970,17 +993,17 @@ int j = siglist[i]; if (j > 3) - buf[i] = '*'; /* quality of input signal j + sqstr[i] = '*'; /* quality of input signal j is undefined */ else if (annot.subtyp & (0x10 << j)) - buf[i] = 'u'; /* signal j is unreadable */ + sqstr[i] = 'u'; /* signal j is unreadable */ else if (annot.subtyp & (0x01 << j)) - buf[i] = 'n'; /* signal j is noisy */ + sqstr[i] = 'n'; /* signal j is noisy */ else - buf[i] = 'c'; /* signal j is clean */ + sqstr[i] = 'c'; /* signal j is clean */ } - buf[i] = '\0'; - label(buf); + sqstr[i] = '\0'; + label(sqstr); break; case STCH: case TCH: diff -Naur wfdb-10.1.6/app/rdsamp.c wfdb-10.2.0/app/rdsamp.c --- wfdb-10.1.6/app/rdsamp.c Sun Apr 9 17:06:23 2000 +++ wfdb-10.2.0/app/rdsamp.c Fri Oct 5 00:44:12 2001 @@ -1,9 +1,9 @@ /* file: rdsamp.c G. Moody 23 June 1983 - Last revised: 9 April 2000 + Last revised: 5 October 2001 ------------------------------------------------------------------------------- rdsamp: Print an arbitrary number of samples from each signal -Copyright (C) 2000 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -65,11 +65,11 @@ char *argv[]; { char *record = NULL, *prog_name(); - int i, isiglist, nsig, nosig = 0, pflag = 0, s, *sig = NULL, v[WFDB_MAXSIG], + int highres = 0, i, isiglist, nsig, nosig = 0, pflag = 0, s, *sig = NULL, vflag = 0; - int highres = 0; long from = 0L, maxl = 0L, to = 0L; - static WFDB_Siginfo si[WFDB_MAXSIG]; + WFDB_Sample *v; + WFDB_Siginfo *si; void help(); #ifdef WFDBP @@ -175,7 +175,13 @@ help(); exit(1); } - if ((nsig = isigopen(record, si, WFDB_MAXSIG)) <= 0) + if ((nsig = isigopen(record, NULL, 0)) <= 0) exit(2); + if ((v = malloc(nsig * sizeof(WFDB_Sample))) == NULL || + (si = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + if ((nsig = isigopen(record, si, nsig)) <= 0) exit(2); for (i = 0; i < nsig; i++) if (si[i].gain == 0.0) si[i].gain = WFDB_DEFGAIN; @@ -220,11 +226,15 @@ /* Print column headers if '-v' option selected. */ if (vflag) { - char *p, t[40]; + char *p, *t; int l; if (pflag == 0) (void)printf("samp #"); else (void)printf("time"); + if ((t = malloc((strlen(record)+30) * sizeof(char))) == NULL) { + fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } for (i = 0; i < nsig; i++) { (void)sprintf(t, "record %s, signal %d", record, sig[i]); p = si[sig[i]].desc; diff -Naur wfdb-10.1.6/app/sampfreq.c wfdb-10.2.0/app/sampfreq.c --- wfdb-10.1.6/app/sampfreq.c Sun Jan 30 04:13:16 2000 +++ wfdb-10.2.0/app/sampfreq.c Fri Oct 5 01:03:00 2001 @@ -1,9 +1,9 @@ /* file: sampfreq.c G. Moody 7 June 1998 - Last revised: 3 May 1999 + Last revised: 5 October 2001 ------------------------------------------------------------------------------- sampfreq: Print the sampling frequency of a record -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -33,10 +33,8 @@ char **argv; { if (argc == 3 && strcmp(argv[1], "-H") == 0) { - static WFDB_Siginfo s[WFDB_MAXSIG]; - setgvmode(WFDB_HIGHRES); - isigopen(argv[2], s, WFDB_MAXSIG); + (void)isigopen(argv[2], NULL, 0); printf("%g\n", sampfreq(NULL)); exit(0); } diff -Naur wfdb-10.1.6/app/sigamp.c wfdb-10.2.0/app/sigamp.c --- wfdb-10.1.6/app/sigamp.c Sun Jan 30 04:13:16 2000 +++ wfdb-10.2.0/app/sigamp.c Tue Oct 9 10:20:14 2001 @@ -1,9 +1,9 @@ /* file: sigamp.c G. Moody 30 November 1991 - Last revised: 4 May 1999 + Last revised: 9 October 2001 ------------------------------------------------------------------------------- sigamp: Measure signal amplitudes -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -31,6 +31,11 @@ #ifndef __STDC__ extern void exit(); #endif +#ifndef NOMALLOC_H +#include +#else +extern char *malloc(); +#endif #include #define isqrs @@ -47,7 +52,8 @@ int nsig; int pflag; /* if non-zero, print physical units */ int vflag; /* if non-zero, print individual measurements */ -double amp[WFDB_MAXSIG][NMAX]; +int *v0, *vmax, *vmin, *vv; +double **amp, *vmean, *vsum; long dt1, dt2, dtw; main(argc, argv) @@ -55,9 +61,9 @@ char *argv[]; { char *record = NULL, *prog_name(); - int i, j, jlow, jhigh, ampcmp(), getptp(), getrms(); + int i, j, jlow, jhigh, nmax = NMAX, ampcmp(), getptp(), getrms(); long from = 0L, to = 0L, t; - static WFDB_Siginfo si[WFDB_MAXSIG]; + static WFDB_Siginfo *si; static WFDB_Anninfo ai; void help(); @@ -95,6 +101,15 @@ help(); exit(0); break; + case 'n': + if (++i >= argc) { + (void)fprintf(stderr, + "%s: number of measurements must follow -n\n", + pname); + exit(1); + } + if ((nmax = atoi(argv[i])) < 1) nmax = NMAX; + break; case 'p': pflag = 1; break; @@ -144,9 +159,26 @@ help(); exit(1); } - if ((nsig = isigopen(record, si, WFDB_MAXSIG)) <= 0) exit(2); - for (i = 0; i < nsig; i++) + if ((nsig = isigopen(record, NULL, 0)) <= 0) exit(2); + if ((si = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL || + (v0 = malloc(nsig * sizeof(int))) == NULL || + (vmax = malloc(nsig * sizeof(int))) == NULL || + (vmin = malloc(nsig * sizeof(int))) == NULL || + (vv = malloc(nsig * sizeof(int))) == NULL || + (amp = malloc(nsig * sizeof(double *))) == NULL || + (vmean = malloc(nsig * sizeof(double))) == NULL || + (vsum = malloc(nsig * sizeof(double))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(3); + } + if (isigopen(record, si, nsig) != nsig) exit(2); + for (i = 0; i < nsig; i++) { if (si[i].gain == 0.0) si[i].gain = WFDB_DEFGAIN; + if ((amp[i] = malloc(nmax * sizeof(double))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(3); + } + } if (from > 0L) from = strtim(argv[(int)from]); if (to > 0L) to = strtim(argv[(int)to]); if (from < 0L) from = -from; @@ -179,7 +211,7 @@ } if (dt1 == dt2) dt2++; if (iannsettime(from) < 0) exit(2); - while (getann(0, &annot) == 0 && namp < NMAX && + while (getann(0, &annot) == 0 && namp < nmax && (to == 0L || annot.time < to)) { if (map1(annot.anntyp) == NORMAL) { if (getptp(annot.time) < 0) break; @@ -206,7 +238,7 @@ if (dtw == 0L || (dtw = strtim(argv[(int)dtw])) <= 0L) dtw = strtim("1"); if (from > 0L && isigsettime(from) < 0L) exit(2); - for (t = from; namp < NMAX && (to == 0L || t < to); namp++, t += dtw) { + for (t = from; namp < nmax && (to == 0L || t < to); namp++, t += dtw) { if (getrms(t) < 0) break; if (vflag) { (void)printf("%s", mstimstr(t)); @@ -243,9 +275,8 @@ int getrms(t) long t; { - int i, v, vv[WFDB_MAXSIG], v0[WFDB_MAXSIG]; + int i, v; long tt; - double vmean[WFDB_MAXSIG], vsum[WFDB_MAXSIG]; if (getvec(vv) < nsig) return (-1); @@ -289,7 +320,7 @@ int getptp(t) long t; { - int i, vmax[WFDB_MAXSIG], vmin[WFDB_MAXSIG], vv[WFDB_MAXSIG]; + int i; long tt; if (isigsettime(t + dt1) < 0) return (-1); @@ -350,6 +381,8 @@ " DT2 = 0.05 (seconds after annotation)", " -f TIME begin at specified time", " -h print this usage summary", + " -n NMAX make up to NMAX measurements per signal (default: 300)", + /* default NMAX is defined as 300 above */ " -p print results in physical units (default: ADC units)", " -t TIME stop at specified time", " -v verbose mode: print individual measurements", diff -Naur wfdb-10.1.6/app/skewedit.c wfdb-10.2.0/app/skewedit.c --- wfdb-10.1.6/app/skewedit.c Sun Jan 30 04:13:16 2000 +++ wfdb-10.2.0/app/skewedit.c Mon Oct 8 22:24:54 2001 @@ -1,9 +1,9 @@ /* file: skewedit.c G. Moody 10 August 1994 - Last revised: 4 May 1999 + Last revised: 8 October 2001 ------------------------------------------------------------------------------- skewedit: Edit skew fields of header file(s) -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -26,9 +26,17 @@ */ #include +#ifndef __STDC__ +extern void exit(); +#endif +#ifndef NOMALLOC_H +#include +#else +extern char *malloc(); +#endif #include -static int skew[WFDB_MAXSIG]; +static int nskews, *skew; main(argc, argv) int argc; @@ -51,6 +59,11 @@ exit(1); } + nskews = argc-2; + if ((skew = malloc(nskews * sizeof(int))) == NULL) { + fprintf(stderr, "%s: insufficient memory\n", argv[0]); + exit(2); + } for (i = 2; i < argc; i++) { if ((skew[i-2] = atoi(argv[i])) < 0) { fprintf(stderr, "%s: skew cannot be less than zero\n", argv[0]); @@ -135,7 +148,7 @@ } else *p++ = '\0'; - if (i < WFDB_MAXSIG && skew[i]) + if (i < nskews && skew[i]) fprintf(tfile, "%s:%d %s", buf, skew[i], p); else fprintf(tfile, "%s %s", buf, p); diff -Naur wfdb-10.1.6/app/snip.c wfdb-10.2.0/app/snip.c --- wfdb-10.1.6/app/snip.c Sun Jan 30 04:13:16 2000 +++ wfdb-10.2.0/app/snip.c Thu Oct 4 13:48:22 2001 @@ -1,8 +1,8 @@ /* file: snip.c G. Moody 30 July 1989 - Last revised: 4 May 1999 + Last revised: 4 October 2001 ------------------------------------------------------------------------------- snip: Copy an excerpt of a database record -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -28,6 +28,11 @@ #ifndef __STDC__ extern void exit(); #endif +#ifndef NOMALLOC_H +#include +#else +extern char *malloc(); +#endif #include char *pname; @@ -36,14 +41,14 @@ int argc; char *argv[]; { - char *irec = NULL, *nrec = NULL, *prog_name(); - int i, j, nsig, v[WFDB_MAXSIG]; + char *info, *irec = NULL, *nrec = NULL, *ofname, *orec, *startp = "0:0", + *xinfo, *prog_name(); + int a, i, nann = 0, nsig; long from = 0L, to = 0L, nsamp; - unsigned int nann = 0; - static char desc[WFDB_MAXSIG][40], ofname[32], orec[32]; - static WFDB_Siginfo si[WFDB_MAXSIG]; - static WFDB_Anninfo ai[WFDB_MAXANN]; - static WFDB_Annotation annot[WFDB_MAXANN]; + WFDB_Anninfo *ai; + WFDB_Annotation annot; + WFDB_Sample *v; + WFDB_Siginfo *si; void help(); pname = prog_name(argv[0]); @@ -59,15 +64,10 @@ /* Accept the next argument unconditionally as an annotator name; accept additional arguments until we find one beginning with `-', or the end of the argument list. */ + a = i; do { - if (nann >= WFDB_MAXANN) { - (void)fprintf(stderr, - "%s: no more than %d annotators may be processed at once\n", - pname, WFDB_MAXANN); - exit(1); - } - ai[nann].name = argv[i++]; ai[nann++].stat = WFDB_READ; - } while (i < argc && *argv[i] != '-'); + nann++; + } while (i < argc && *argv[++i] != '-'); i--; break; case 'f': /* starting time */ @@ -75,7 +75,7 @@ (void)fprintf(stderr, "%s: time must follow -f\n", pname); exit(1); } - from = i; + startp = argv[i]; break; case 'h': /* help requested */ help(); @@ -120,56 +120,108 @@ exit(1); } - if ((nsig = isigopen(irec, si, WFDB_MAXSIG)) < 0) exit(2); - if (nann != 0 && annopen(irec, ai, nann) < 0) exit(2); + /* Verify that the output record can be written. */ if (newheader(nrec) < 0) exit(2); - (void)sprintf(ofname, "%s.dat", nrec); - for (i = 0; i < nsig; i++) { - si[i].fname = ofname; - si[i].group = 0; - if (i > 0) si[i].fmt = si[0].fmt; - (void)sprintf(desc[i], "record %s, signal %d", irec, i); - if (si[i].desc == NULL || strcmp(si[i].desc, desc[i]) == 0) { - (void)sprintf(desc[i], "record %s, signal %d", nrec, i); - si[i].desc = desc[i]; - } - } - if (osigfopen(si, (unsigned)nsig) < nsig) exit(2); - (void)sprintf(orec, "+%s", nrec); - if (from > 0L) { - if ((from = strtim(argv[from])) < 0L) + + /* Determine the number of signals. */ + if ((nsig = isigopen(irec, NULL, 0)) < 0) exit(2); + + /* Evaluate the time limits. */ + if ((from = strtim(startp)) < 0L) from = -from; - if (isigsettime(from) < 0) - exit(2); - for (i = 0; i < nann; i++) - (void)getann((unsigned)i, &annot[i]); - } if (to > 0L) { if ((to = strtim(argv[to])) < 0L) to = -to; } - nsamp = (to == 0L) ? -1L : to - from; - for (j = 0; j < nann; j++) - ai[j].stat = WFDB_WRITE; - if (nann != 0 && annopen(orec, ai, nann) < 0) exit(2); - - /* Copy selected segment of signals. */ - while ((nsamp == -1L || nsamp-- > 0L) && - getvec(v) == nsig && putvec(v) == nsig) - ; - - /* Copy selected segment of annotations. */ - for (i = 0; i < nann; i++) { - do { - annot[i].time -= from; - if (annot[i].time >= 0L && putann((unsigned)i, &annot[i]) < 0) - break; - } while (getann((unsigned)i, &annot[i]) == 0 && - (to == 0L || annot[i].time < to)); + + /* Copy the signals, if any. */ + if (nsig > 0) { + /* Allocate data structures for nsig signals. */ + if ((v = malloc(nsig * sizeof(WFDB_Sample))) == NULL || + (si = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL || + (ofname = malloc((strlen(nrec)+5) * sizeof(char))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + + /* Open the input signals. */ + if (isigopen(irec, si, (unsigned)nsig) != nsig) exit(2); + + /* Open the output signals. */ + (void)sprintf(ofname, "%s.dat", nrec); + for (i = 0; i < nsig; i++) { + si[i].fname = ofname; + si[i].group = 0; + if (i > 0) si[i].fmt = si[0].fmt; + } + if (osigfopen(si, (unsigned)nsig) != nsig) exit(2); + + /* Copy the selected segment. */ + if (isigsettime(from) < 0) exit(2); + nsamp = (to == 0L) ? -1L : to - from; + while ((nsamp == -1L || nsamp-- > 0L) && + getvec(v) == nsig && putvec(v) == nsig) + ; + free(ofname); + free(si); + free(v); + } + + /* Copy the annotations, if any. */ + if (nann > 0) { + /* Allocate data structures for nann annotators. */ + if ((ai = malloc(nann * sizeof(ai))) == NULL || + (orec = malloc((strlen(nrec)+2) * sizeof(char))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + for (i = 0; i < nann; i++) { + ai[i].name = argv[a++]; + ai[i].stat = WFDB_READ; + } + + /* Open the input annotators. */ + if (annopen(irec, ai, nann) < 0) exit(2); + + /* Open the output annotators. */ + (void)sprintf(orec, "+%s", nrec); + for (i = 0; i < nann; i++) + ai[i].stat = WFDB_WRITE; + if (annopen(orec, ai, nann) < 0) exit(2); + + /* Copy the selected segment. */ + for (i = 0; i < nann; i++) { + while (getann((unsigned)i, &annot) == 0) { + if (annot.time >= from && (to == 0L || annot.time < to)) { + annot.time -= from; + if (putann((unsigned)i, &annot) < 0) break; + } + } + } + free(orec); + free(ai); } /* Clean up. */ (void)newheader(nrec); + + /* Copy info strings from the input header file into the new one. + Suppress error messages from the WFDB library. */ + wfdbquiet(); + if (info = getinfo(irec)) + do { + (void)putinfo(info); + } while (info = getinfo((char *)NULL)); + + /* Append additional info summarizing what snip has done. */ + if (xinfo = + malloc((strlen(pname)+strlen(irec)+strlen(startp)+50)* sizeof(char))) { + (void)sprintf(xinfo, "Produced by %s from record %s, beginning at %s", + pname, irec, startp); + (void)putinfo(xinfo); + free(xinfo); + } + wfdbverbose(); wfdbquit(); exit(0); /*NOTREACHED*/ } diff -Naur wfdb-10.1.6/app/sqrs.c wfdb-10.2.0/app/sqrs.c --- wfdb-10.1.6/app/sqrs.c Sun Jan 30 04:13:17 2000 +++ wfdb-10.2.0/app/sqrs.c Mon Oct 8 21:35:31 2001 @@ -1,9 +1,9 @@ /* file: sqrs.c G. Moody 27 October 1990 - Last revised: 4 May 1999 + Last revised: 8 October 2001 ------------------------------------------------------------------------------- sqrs: Single-channel QRS detector -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -74,7 +74,11 @@ #ifndef __STDC__ extern void exit(); #endif - +#ifndef NOMALLOC_H +#include +#else +extern char *malloc(); +#endif #include #include @@ -90,11 +94,11 @@ int filter, i, minutes = 0, nsig, time = 0, slopecrit, sign, maxslope = 0, nslope = 0, qtime, maxtime, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, - ms160, ms200, s2, scmax, scmin = 500, signal = 0, v[WFDB_MAXSIG]; + ms160, ms200, s2, scmax, scmin = 500, signal = 0, *v; long from = 0L, next_minute, now, spm, to = 0L; WFDB_Anninfo a; WFDB_Annotation annot; - static WFDB_Siginfo s[WFDB_MAXSIG]; + static WFDB_Siginfo *s; void help(); pname = prog_name(argv[0]); @@ -158,8 +162,14 @@ exit(1); } + if ((nsig = isigopen(record, NULL, 0)) < 1) exit(2); + if ((s = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL || + (v = malloc(nsig * sizeof(WFDB_Sample))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } a.name = "qrs"; a.stat = WFDB_WRITE; - if ((nsig = wfdbinit(record, &a, 1, s, WFDB_MAXSIG)) < 1) exit(2); + if ((nsig = wfdbinit(record, &a, 1, s, nsig)) < 1) exit(2); if (sampfreq((char *)NULL) < 200. || sampfreq((char *)NULL) > 300.) { (void)fprintf(stderr, "warning: %s is designed for 250 Hz input\n", argv[0]); diff -Naur wfdb-10.1.6/app/sqrs125.c wfdb-10.2.0/app/sqrs125.c --- wfdb-10.1.6/app/sqrs125.c Sun Jan 30 04:13:17 2000 +++ wfdb-10.2.0/app/sqrs125.c Mon Oct 8 21:51:19 2001 @@ -1,9 +1,9 @@ /* file: sqrs125.c G. Moody 27 October 1990 - Last revised: 4 May 1999 + Last revised: 8 October 2001 ------------------------------------------------------------------------------- sqrs125: Single-channel QRS detector for data sampled at 100 - 150 Hz -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -81,7 +81,11 @@ #ifndef __STDC__ extern void exit(); #endif - +#ifndef NOMALLOC_H +#include +#else +extern char *malloc(); +#endif #include #include @@ -97,11 +101,11 @@ int filter, i, minutes = 0, nsig, time = 0, slopecrit, sign, maxslope = 0, nslope = 0, qtime, maxtime, t0, t1, t2, t3, t4, t5, - ms160, ms200, s2, scmax, scmin = 250, signal = 0, v[WFDB_MAXSIG]; + ms160, ms200, s2, scmax, scmin = 250, signal = 0, *v; long from = 0L, next_minute, now, spm, to = 0L; WFDB_Anninfo a; WFDB_Annotation annot; - static WFDB_Siginfo s[WFDB_MAXSIG]; + static WFDB_Siginfo *s; void help(); pname = prog_name(argv[0]); @@ -165,8 +169,14 @@ exit(1); } + if ((nsig = isigopen(record, NULL, 0)) < 1) exit(2); + if ((s = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL || + (v = malloc(nsig * sizeof(WFDB_Sample))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } a.name = "qrs"; a.stat = WFDB_WRITE; - if ((nsig = wfdbinit(record, &a, 1, s, WFDB_MAXSIG)) < 1) exit(2); + if ((nsig = wfdbinit(record, &a, 1, s, nsig)) < 1) exit(2); if (sampfreq((char *)NULL) < 100. || sampfreq((char *)NULL) > 150.) { (void)fprintf(stderr, "warning: %s is designed for 125 Hz input\n", argv[0]); diff -Naur wfdb-10.1.6/app/wfdbcollate.c wfdb-10.2.0/app/wfdbcollate.c --- wfdb-10.1.6/app/wfdbcollate.c Sun Jan 30 04:13:17 2000 +++ wfdb-10.2.0/app/wfdbcollate.c Tue Oct 9 09:43:35 2001 @@ -1,9 +1,9 @@ /* file: wfdbcollate.c G. Moody 28 April 1994 - Last revised: 14 October 1999 + Last revised: 9 October 2001 ------------------------------------------------------------------------------- wfdbcollate: Collate WFDB records into a multi-segment record -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -79,8 +79,15 @@ changes simply by recompiling them and linking them with the current WFDB library. */ - #include +#ifndef __STDC__ +extern void exit(); +#endif +#ifndef NOMALLOC_H +#include +#else +extern char *malloc(); +#endif #include #define DEFSEGLEN "10:0" /* segments are 10 minutes long by default */ @@ -89,8 +96,8 @@ char *pname, *prog_name(); WFDB_Anninfo ai; WFDB_Annotation annot; -WFDB_Sample v[WFDB_MAXSIG*WFDB_MAXSPF]; -WFDB_Siginfo si[WFDB_MAXSIG]; +WFDB_Sample *v; +WFDB_Siginfo *si; int collate(); void help(), splitrecord(); @@ -107,7 +114,7 @@ int argc; char *argv[]; { - int i, segnumber = 0, nsig; + int framelen, i, segnumber = 0, nsig; static char *irecname, *orecname, segname[10], sigfname[15]; static char irecbase[30], segbase[30]; static WFDB_Time seglen, t, tf; @@ -147,8 +154,24 @@ help(); exit(1); } - if ((nsig = isigopen(irecname, si, WFDB_MAXSIG)) <= 0) + /* Determine the number of signals in the record. */ + if ((nsig = isigopen(irecname, NULL, 0)) <= 0) + exit(2); + /* Allocate storage for the signal information structures. */ + if ((si = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL) { + fprintf(stderr, "%s: insufficient memory\n", pname); + exit(3); + } + /* Open the input signals. */ + if (isigopen(irecname, si, nsig) != nsig) exit(2); + /* Allocate storage for the sample frame. */ + for (i = framelen = 0; i < nsig; i++) + framelen += si[i].spf; + if ((v = malloc(framelen * sizeof(WFDB_Sample))) == NULL) { + fprintf(stderr, "%s: insufficient memory\n", pname); + exit(3); + } if (newheader(orecname) < 0) exit(2); if (seglen > 0) { @@ -182,7 +205,8 @@ isigsettime(t = tf = 0L); strcpy(irecbase, timstr(0L)); - irecbase[strlen(irecbase)-1] = '\0'; + if (*irecbase == '[') + irecbase[strlen(irecbase)-1] = '\0'; while (getframe(v) > 0) { if (t >= tf) { @@ -193,7 +217,8 @@ osigfopen(NULL, 0); /* close output signal file */ } strcpy(segbase, timstr(-t)); - segbase[strlen(segbase)-1] = '\0'; + if (*segbase == '[') + segbase[strlen(segbase)-1] = '\0'; sprintf(segname, "%s%05d", orecname, ++segnumber); sprintf(sigfname, "%s.dat", segname); if (osigfopen(si, nsig) < nsig) { @@ -214,7 +239,7 @@ wfdbquit(); fprintf(stderr, " done\ncollating segments ..."); - /* build argument list for main() */ + /* build argument list for collate() */ sprintf(lastsegstr, "%d", segnumber); cargv[0] = pname; cargv[1] = orecname; @@ -316,6 +341,18 @@ if (annopen(orecname, &ai, 1) < 0) exit(3); ai.stat = WFDB_READ; + /* Determine the number of signals in the first segment of the + record. (We assume this is constant for all segments.) */ + if ((nsig = isigopen(irecname[0], NULL, 0)) <= 0) + exit(2); + /* Allocate storage for the signal information structures. */ + if ((si = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL) { + fprintf(stderr, "%s: insufficient memory\n", pname); + exit(3); + } + /* Assume that segments are of the default length unless the + header tells us otherwise (after invoking isigopen below). */ + si[0].nsamp = strtim(DEFSEGLEN); for (i = 0; i < nsegments; i++) { sprintf(buf, "+%s", irecname[i]); if (annopen(buf, &ai, 1) == 0) { @@ -325,11 +362,13 @@ } iannclose(0); /* close input file, leave output file open */ } - (void)isigopen(irecname[i], si, -WFDB_MAXSIG); - /* If isigopen fails, the contents of si are undisturbed. In this - case, we need to guess the length of the segment. A good guess - is that it is the same length as the previous segment -- so we - can use si[0].nsamp irrespective of the success of isigopen! */ + /* Fill the signal info structures without opening the signals. */ + (void)isigopen(irecname[i], si, -nsig); + /* If isigopen fails, the previous contents of si are undisturbed. + In this case, we need to guess the length of the segment. A + good guess is that it is the same length as the previous segment + -- so we can use si[0].nsamp irrespective of the success of + isigopen! */ t0 += si[0].nsamp; } wfdbquit(); diff -Naur wfdb-10.1.6/app/wfdbdesc.c wfdb-10.2.0/app/wfdbdesc.c --- wfdb-10.1.6/app/wfdbdesc.c Sun Jan 30 04:13:17 2000 +++ wfdb-10.2.0/app/wfdbdesc.c Fri Oct 5 01:00:13 2001 @@ -1,9 +1,9 @@ /* file: wfdbdesc.c G. Moody June 1989 - Last revised: 5 May 1999 + Last revised: 5 October 2001 ------------------------------------------------------------------------------- wfdbdesc: Describe signal specifications -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -29,8 +29,15 @@ */ #include -#ifndef __STDC__ +#ifdef __STDC__ +# include +#else extern void exit(); +# ifndef NOMALLOC_H +# include +# else +extern char *malloc(); +# endif #endif #include @@ -39,9 +46,9 @@ char *argv[]; { char *info, *p, *pname, *prog_name(); - static WFDB_Siginfo s[WFDB_MAXSIG]; int i, msrec = 0, nsig; FILE *ifile; + WFDB_Siginfo *s; WFDB_Time t; pname = prog_name(argv[0]); @@ -49,13 +56,22 @@ (void)fprintf(stderr, "usage: %s RECORD [-readable]\n", pname); exit(1); } + /* Discover the number of signals defined in the header. */ + if ((nsig = isigopen(argv[1], NULL, 0)) < 1) exit(2); + + /* Allocate storage for nsig signal information structures. */ + if ((s = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL) { + fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + /* If the `-readable' option is given, report only on signals which can be opened. Otherwise, report on all signals named in the header file, without attempting to open them. */ if (argc > 2 && strncmp(argv[2], "-readable", strlen(argv[2])) == 0) - nsig = isigopen(argv[1], s, WFDB_MAXSIG); + nsig = isigopen(argv[1], s, nsig); else - nsig = isigopen(argv[1], s, -(WFDB_MAXSIG)); + nsig = isigopen(argv[1], s, -nsig); if (nsig < 1) exit(2); (void)printf("Record %s", argv[1]); t = strtim("e"); diff -Naur wfdb-10.1.6/app/wrsamp.c wfdb-10.2.0/app/wrsamp.c --- wfdb-10.1.6/app/wrsamp.c Sun Jan 30 04:13:17 2000 +++ wfdb-10.2.0/app/wrsamp.c Fri Oct 5 00:43:57 2001 @@ -1,8 +1,8 @@ /* file: wrsamp.c G. Moody 10 August 1993 - Last revised: 5 May 1999 + Last revised: 5 October 2001 ------------------------------------------------------------------------------- wrsamp: Select fields or columns from a file and generate a WFDB record -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -46,20 +46,20 @@ int argc; char *argv[]; { - char **ap, *cp, **fp = NULL, fsep = '\0', *ifname, *l = NULL, ofname[40], - *p, *record = NULL, rsep = '\n', *prog_name(); - static char desc[WFDB_MAXSIG][80]; + char **ap, *cp, **desc, **fp = NULL, fsep = '\0', *ifname = "(stdin)", + *l = NULL, ofname[40], *p, *record = NULL, rsep = '\n', *prog_name(); double freq = WFDB_DEFFREQ, gain = WFDB_DEFGAIN, scale = 1.0, v; #ifndef atof double atof(); #endif - int c, cf = 0, *fv = NULL, i, lmax = 1024, mf, vout[WFDB_MAXSIG]; + int c, cf = 0, *fv = NULL, i, lmax = 1024, mf; FILE *ifile = stdin; long t = 0L, t0 = 0L, t1 = 0L; #ifndef atol long atol(); #endif - static WFDB_Siginfo si[WFDB_MAXSIG]; + WFDB_Sample *vout; + WFDB_Siginfo *si; unsigned int nf = 0; void help(); @@ -184,17 +184,18 @@ nf++; } - if (nf > WFDB_MAXSIG) { - (void)fprintf(stderr, "%s: no more than %d columns may be selected\n", - WFDB_MAXSIG); - exit(1); - } - if (nf < 1) { help(); exit(1); } + if ((vout = malloc(nf * sizeof(WFDB_Sample))) == NULL || + (si = malloc(nf * sizeof(WFDB_Siginfo))) == NULL || + (desc = malloc(nf * sizeof(char *))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + /* open output file */ if (record == NULL) (void)sprintf(ofname, "-"); @@ -202,6 +203,10 @@ (void)sprintf(ofname, "%s.dat", record); for (i = 0; i < nf; i++) { si[i].fname = ofname; + if ((desc[i] = malloc((strlen(ifname)+20) * sizeof(char))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } if (ifile == stdin) (void)sprintf(desc[i], "column %d", fv[i]); else diff -Naur wfdb-10.1.6/app/xform.c wfdb-10.2.0/app/xform.c --- wfdb-10.1.6/app/xform.c Mon Feb 26 14:04:09 2001 +++ wfdb-10.2.0/app/xform.c Sun Oct 14 22:34:15 2001 @@ -1,9 +1,9 @@ /* file: xform.c G. Moody 8 December 1983 - Last revised: 26 February 2001 + Last revised: 14 October 2001 ------------------------------------------------------------------------------- xform: Sampling frequency, amplitude, and format conversion for WFDB records -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -52,20 +52,18 @@ int argc; char *argv[]; { - char *irec = NULL, *orec = NULL, *nrec = NULL, *startp = "0:0"; - int clip = 0, fflag = 0, gflag = 0, Hflag = 0, ifreq, i, j, m, Mflag = 0, - mn, n, nann = 0, nisig, nminutes = 0, nosig = -1, ofreq = 0, - reopen = 0, spf = 1, use_irec_desc = 1; - static char btstring[30]; - static double gain[WFDB_MAXSIG]; - static int deltav[WFDB_MAXSIG], msiglist[WFDB_MAXSIG], - siglist[WFDB_MAXSIG], v[WFDB_MAXSIG], vin[WFDB_MAXSIG*WFDB_MAXSPF], - vmax[WFDB_MAXSIG], vmin[WFDB_MAXSIG], vout[WFDB_MAXSIG*WFDB_MAXSPF], - vv[WFDB_MAXSIG]; - static long it, ot, from, to, nsamp = -1L, spm, nsm = 0L; - static WFDB_Siginfo dfin[WFDB_MAXSIG], dfout[WFDB_MAXSIG]; - static WFDB_Anninfo ai[WFDB_MAXANN]; - static WFDB_Annotation annot; + char btstring[30], **description, **filename, *irec = NULL, *orec = NULL, + *nrec = NULL, *script = NULL, *startp = "0:0", **units; + double *gain; + int clip = 0, *deltav, fflag = 0, gflag = 0, Hflag = 0, i, iframelen, + ifreq, j, m, Mflag = 0, mn, *msiglist, n, nann = 0, nisig, + nminutes = 0, nosig = 0, oframelen, ofreq = 0, reopen = 0, sflag = 0, + *siglist = NULL, spf, uflag = 0, use_irec_desc = 1, *v, *vin, *vmax, + *vmin, *vout, *vv; + long from = 0L, it = 0L, nsamp = -1L, nsm = 0L, ot = 0L, spm, to = 0L; + WFDB_Anninfo *ai = NULL; + WFDB_Annotation annot; + WFDB_Siginfo *dfin, *dfout; pname = prog_name(argv[0]); @@ -73,23 +71,27 @@ for (i = 1; i < argc; i++) { if (*argv[i] == '-') switch (*(argv[i]+1)) { case 'a': /* annotator(s) */ - if (++i >= argc) { + /* Count the number of annotators. Accept the next argument + unconditionally as an annotator name; accept additional arguments + until we find one beginning with `-', or the end of the argument + list. */ + for (j = 0; ++i < argc && (j == 0 || *argv[i] != '-'); j++) + ; + if (j == 0) { (void)fprintf(stderr, "%s: annotator(s) must follow -a\n", pname); exit(1); } - /* Accept the next argument unconditionally as an annotator name; - accept additional arguments until we find one beginning with - `-', or the end of the argument list. */ - do { - if (nann >= WFDB_MAXANN) { - (void)fprintf(stderr, - "%s: no more than %d annotators may be processed at once\n", - pname, WFDB_MAXANN); - exit(1); - } - ai[nann].name = argv[i++]; ai[nann++].stat = WFDB_READ; - } while (i < argc && *argv[i] != '-'); + /* allocate storage */ + if ((ai = realloc(ai, (nann+j) * sizeof(WFDB_Anninfo))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + /* fill the annotator information structures */ + for (i -= j, j=0; i= argc) { + sflag = 1; + /* count the number of output signals */ + for (j = 0; ++i < argc && *argv[i] != '-'; j++) + ; + if (j == 0) { (void)fprintf(stderr, "%s: signal list must follow -s\n", pname); exit(1); } - nosig = 0; - while (i < argc && *argv[i] != '-') { - if (nosig == WFDB_MAXSIG) { - (void)fprintf(stderr, "%s: too many output signals\n", - pname); - exit(1); - } - siglist[nosig++] = atoi(argv[i++]); + /* allocate storage for the signal list */ + if ((siglist=realloc(siglist, (nosig+j) * sizeof(int))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); } + /* fill the signal list */ + for (i -= j; i < argc && *argv[i] != '-'; ) + siglist[nosig++] = atoi(argv[i++]); i--; break; + case 'S': /* script name follows */ + if (++i >= argc) { + (void)fprintf(stderr, "%s: script name must follow -S\n", + pname); + exit(1); + } + script = argv[i]; + break; case 't': /* end time */ if (++i >= argc) { (void)fprintf(stderr, "%s: time must follow -t\n", pname); @@ -170,6 +183,9 @@ } to = i; break; + case 'u': /* make annotation times unique */ + uflag = 1; + break; default: (void)fprintf(stderr, "%s: unrecognized option %s\n", pname, argv[i]); @@ -188,58 +204,150 @@ exit(1); } - /* Get input signal information and sampling frequency to use as defaults - for output. */ - nisig = isigopen(irec, dfin, WFDB_MAXSIG); - if (Hflag) { - setgvmode(WFDB_HIGHRES); - spf = getspf(); + /* Determine the number of input signals. If isigopen returns a negative + value, quit (isigopen will have emitted an error message). */ + if ((nisig = isigopen(irec, NULL, 0)) < 0) exit(2); + + /* If the input record contains no signals, we won't write any -- but + we might still read and write annotations. */ + if (nisig == 0) nosig = 0; + + /* Otherwise, prepare to read and write signals. */ + else { + /* Allocate storage for variables related to the input signals. */ + if ((dfin = malloc(nisig * sizeof(WFDB_Siginfo))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + + /* If a signal list was specified using -s, check that the specified + signal numbers are legal. */ + if (sflag) { + for (i = 0; i < nosig && nosig > 0; i++) + if (siglist[i] < 0 || siglist[i] >= nisig) { + (void)fprintf(stderr, + "%s: warning: signal %d can't be read from record %s\n", + pname, siglist[i], irec); + /* Delete illegal signal numbers from the list. */ + for (j = i; j+1 < nosig; j++) + siglist[j] = siglist[j+1]; + nosig--; + i--; + } + /* If the signal list contained no valid signal numbers, treat + this situation as if no signal list was specified. */ + if (nosig == 0) + sflag = 0; + } + + /* If the signal list was not specified using -s, initialize it now. */ + if (sflag == 0) { + nosig = nisig; + if ((siglist = malloc(nosig * sizeof(int))) != NULL) + for (i = 0; i < nosig; i++) + siglist[i] = i; + } + + /* Allocate storage for variables related to the output signals. */ + if ((siglist == NULL) || + (dfout = malloc(nosig * sizeof(WFDB_Siginfo))) == NULL || + (gain = malloc(nosig * sizeof(double))) == NULL || + (deltav = malloc(nosig * sizeof(int))) == NULL || + (msiglist = malloc(nosig * sizeof(int))) == NULL || + (v = malloc(nosig * sizeof(int))) == NULL || + (vmax = malloc(nosig * sizeof(int))) == NULL || + (vmin = malloc(nosig * sizeof(int))) == NULL || + (vv = malloc(nosig * sizeof(int))) == NULL || + (filename = malloc(nosig * sizeof(char *))) == NULL || + (description = malloc(nosig * sizeof(char *))) == NULL || + (units = malloc(nosig * sizeof(char *))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } } + + /* Determine the input sampling frequency. */ + if (Hflag) + setgvmode(WFDB_HIGHRES); + spf = getspf(); ifreq = strtim("1") * spf; (void)setsampfreq(0.); - /* If no output record was specified, get the specifications - interactively. */ - if (orec == NULL) { - char answer[32], directory[32]; - static char filename[WFDB_MAXSIG][32], description[WFDB_MAXSIG][32], - record[8], units[WFDB_MAXSIG][22]; - static int formats[WFDB_NFMTS] = WFDB_FMT_LIST; /* see */ - FILE *ttyin = NULL; + if (isigopen(irec, dfin, nisig) != nisig) exit(2); + if (Mflag) { + for (i = iframelen = 0; i < nisig; i++) + iframelen += dfin[i].spf; + for (i = oframelen = 0; i < nosig; i++) + oframelen += dfin[siglist[i]].spf; + } + else { + iframelen = nisig; + oframelen = nosig; + } + if ((vin = malloc(iframelen * sizeof(int))) == NULL || + (vout = malloc(oframelen * sizeof(int))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + + if (orec != NULL) { /* an output record was specified */ + /* If a new record name was specified, check that it can be created. */ + if (nrec && newheader(nrec) < 0) exit(2); + + /* Determine the output sampling frequency. */ + if (orec) ofreq = sampfreq(orec); + (void)setsampfreq(ifreq/spf); + + if (ifreq != ofreq) { + if (Mflag != 0) { + (void)fprintf(stderr, + "%s: -M option may not be used if sampling frequency is to be changed\n", + pname); + wfdbquit(); + exit(1); + } + } + } + + /* If no output record was specified, get signal specs interactively. */ + else { + static char answer[32], directory[32], record[WFDB_MAXRNL+2]; + static int formats[WFDB_NFMTS] = WFDB_FMT_LIST; /* see */ + int format; + FILE *ttyin; #ifndef MSDOS - ttyin = fopen("/dev/tty", "r"); -#endif -#ifdef MSDOS - ttyin = fopen("CON", "rt"); + ttyin = fopen(script ? script : "/dev/tty", "r"); +#else + ttyin = fopen(script ? script : "CON", "rt"); #endif if (ttyin == NULL) ttyin = stdin; if (nrec == NULL) { do { (void)fprintf(stderr, - "Choose a name for the output record (up to 6 characters): "); - (void)fgets(record, 8, ttyin); record[strlen(record)-1] = '\0'; + "Choose a name for the output record (up to %d characters): ", + WFDB_MAXRNL); + (void)fgets(record, WFDB_MAXRNL+2, ttyin); + record[strlen(record)-1] = '\0'; } while (record[0] == '\0' || newheader(record) < 0); nrec = record; } - if (nosig == -1) { + if (sflag == 0) { do { nosig = nisig; (void)fprintf(stderr, "Number of signals to be written (1-%d) [%d]: ", - WFDB_MAXSIG, nosig); - (void)fgets(answer, 32, ttyin); + nisig, nosig); + (void)fgets(answer, sizeof(answer), ttyin); (void)sscanf(answer, "%d", &nosig); if (nosig == 0) { (void)fprintf(stderr, "No signals will be written. Are you sure? [n]: "); - (void)fgets(answer, 32, ttyin); + (void)fgets(answer, sizeof(answer), ttyin); if (*answer != 'y' && *answer != 'Y') nosig = -1; } - } while (nosig < 0 || nosig > WFDB_MAXSIG); - for (i = 0; i < nosig; i++) - siglist[i] = i; + } while (nosig < 0 || nosig > nisig); } if (Mflag) { ofreq = ifreq; @@ -252,7 +360,8 @@ (void)fprintf(stderr, "Output sampling frequency (Hz per signal, > 0) [%d]: ", ofreq); - (void)fgets(answer, 32, ttyin); (void)sscanf(answer, "%d", &ofreq); + (void)fgets(answer, sizeof(answer), ttyin); + (void)sscanf(answer, "%d", &ofreq); } while (ofreq < 0); if (ofreq == 0) ofreq = WFDB_DEFFREQ; if (nosig > 0) { @@ -261,7 +370,7 @@ (void)fprintf(stderr, " signals should be written, or press to write\n"); (void)fprintf(stderr, " them in the current directory: "); - (void)fgets(directory, 31, ttyin); + (void)fgets(directory, sizeof(directory)-1, ttyin); if (*directory == '\n') *directory = '\0'; else directory[strlen(directory)-1] = '/'; (void)fprintf(stderr,"Any of these output formats may be used:\n"); @@ -279,20 +388,28 @@ (void)fprintf(stderr, " 311 3 10-bit amplitudes bit-packed in 30 LS bits of 4 bytes\n"); do { - dfout[0].fmt = dfin[0].fmt; + format = dfin[0].fmt; (void)fprintf(stderr, "Choose an output format (8/16/61/80/160/212/310/311) [%d]: ", - dfout[0].fmt); - (void)fgets(answer, 32, ttyin); - (void)sscanf(answer, "%d", &dfout[0].fmt); + format); + (void)fgets(answer, sizeof(answer), ttyin); + (void)sscanf(answer, "%d", &format); for (i = 0; i < WFDB_NFMTS; i++) - if (dfout[0].fmt == formats[i]) break; + if (format == formats[i]) break; } while (i >= WFDB_NFMTS); if (nosig > 1) { (void)fprintf(stderr, "Save all signals in one file? [y]: "); - (void)fgets(answer, 32, ttyin); + (void)fgets(answer, sizeof(answer), ttyin); } + /* Use the input signal specifications as defaults for output. */ + for (i = 0; i < nosig; i++) + dfout[i] = dfin[siglist[i]]; if (nosig <= 1 || (answer[0] != 'n' && answer[0] != 'N')) { + filename[0] = malloc(strlen(directory)+strlen(nrec)+10); + if (filename[0] == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } (void)sprintf(filename[0], "%s%s.dat", directory, nrec); for (i = 0; i < nosig; i++) { dfout[i].fname = filename[0]; @@ -301,6 +418,12 @@ } else { for (i = 0; i < nosig; i++) { + filename[i] = malloc(strlen(directory)+strlen(nrec)+10); + if (filename[i] == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", + pname); + exit(2); + } (void)sprintf(filename[i], "%s%s.d%d", directory, nrec, i); dfout[i].fname = filename[i]; dfout[i].group = i; @@ -308,23 +431,28 @@ } } for (i = 0; i < nosig; i++) { - dfout[i].fmt = dfout[0].fmt; dfout[i].bsize = 0; - dfout[i].gain = dfin[siglist[i]].gain; - dfout[i].adcres = dfin[siglist[i]].adcres; - dfout[i].adczero = dfin[siglist[i]].adczero; - dfout[i].units = dfin[siglist[i]].units; - if (Mflag) dfout[i].spf = dfin[siglist[i]].spf; + /* Make sure output signals are written in the chosen format. */ + dfout[i].fmt = format; + if (Mflag == 0) dfout[i].spf = 1; + dfout[i].bsize = 0; /* no block size is defined */ if (!use_irec_desc) { char *p; + if ((description[i] = malloc(WFDB_MAXDSL+2)) == NULL || + (units[i] = malloc(WFDB_MAXUSL+2)) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } (void)fprintf(stderr, - "Signal %d description (up to 30 characters): ", i); - (void)fgets(description[i], 32, ttyin); + "Signal %d description (up to %d characters): ", + i, WFDB_MAXDSL); + (void)fgets(description[i], WFDB_MAXDSL+2, ttyin); description[i][strlen(description[i])-1] = '\0'; dfout[i].desc = description[i]; (void)fprintf(stderr, - "Signal %d units (up to 20 characters): ", i); - (void)fgets(units[i], 22, ttyin); + "Signal %d units (up to %d characters): ", + i, WFDB_MAXUSL); + (void)fgets(units[i], WFDB_MAXUSL+2, ttyin); for (p = units[i]; *p; p++) { if (*p == ' ' || *p == '\t') *p = '_'; else if (*p == '\n') { *p = '\0'; break; } @@ -335,7 +463,7 @@ (void)fprintf(stderr, " Signal %d gain (adu/%s) [%g]: ", i, dfout[i].units ? dfout[i].units : "mV", dfout[i].gain); - (void)fgets(answer, 32, ttyin); + (void)fgets(answer, sizeof(answer), ttyin); (void)sscanf(answer, "%lf", &dfout[i].gain); } while (dfout[i].gain < 0.); do { @@ -360,40 +488,21 @@ (void)fprintf(stderr, " Signal %d ADC resolution in bits (8-16) [%d]: ", i, dfout[i].adcres); - (void)fgets(answer, 32, ttyin); + (void)fgets(answer, sizeof(answer), ttyin); (void)sscanf(answer, "%d", &dfout[i].adcres); } while (dfout[i].adcres < 8 || dfout[i].adcres > 16); (void)fprintf(stderr, " Signal %d ADC zero level (adu) [%d]: ", i, dfout[i].adczero); - (void)fgets(answer, 32, ttyin); + (void)fgets(answer, sizeof(answer), ttyin); (void)sscanf(answer, "%d", &dfout[i].adczero); } } - /* Check that the output record can be created. */ - if (nrec && newheader(nrec) < 0) exit(2); - - /* Determine the output sampling frequency. */ - if (orec) ofreq = sampfreq(orec); - (void)setsampfreq(ifreq/spf); - - if (ifreq != ofreq) { - if (Mflag != 0) { - fprintf(stderr, - "%s: -M option may not be used if sampling frequency is to be changed\n", - pname); - wfdbquit(); - exit(1); - } - } - /* Check the starting and ending times. */ - if (from) { - startp = argv[(int)from]; - from = strtim(startp); - if (from < 0L) from = -from; - strcpy(btstring, timstr(-from)); - } + if (from) startp = argv[(int)from]; + from = strtim(startp); + if (from < 0L) from = -from; + strcpy(btstring, timstr(-from)); if (to) { to = strtim(argv[(int)to]); if (to < 0L) to = -to; @@ -404,7 +513,6 @@ exit(1); } } - spm = strtim("1:0"); /* Process the annotation file(s), if any. */ @@ -441,12 +549,14 @@ while (getann((unsigned)i, &annot) == 0 && (to == 0L || annot.time <= to)) { annot.time = (annot.time - from) * ((double)ofreq*spf) / ifreq; - /* Make sure that the corrected annotation time is positive - and that it is later than the previous annotation time - (exception: if it matches the previous annotation time, - but the chan field is greater than that of the previous - annotation, no time adjustment is performed). */ - if (annot.time < tt || (annot.time == tt && annot.chan <= cc)) + /* If the -u option was specified, make sure that the corrected + annotation time is positive and that it is later than the + previous annotation time (exception: if it matches the + previous annotation time, but the chan field is greater than + that of the previous annotation, no time adjustment is + performed). */ + if (uflag && (annot.time < tt || + (annot.time == tt && annot.chan <= cc))) annot.time = ++tt; else tt = annot.time; cc = annot.chan; @@ -465,81 +575,24 @@ if (nosig == 0) exit(0); /* Check that the input signals are readable. */ - fprintf(stderr, "Checking input signals ..."); + (void)fprintf(stderr, "Checking input signals ..."); if (isigsettime(from) < 0) exit(2); - fprintf(stderr, " done\n"); - - /* If no signal list was specified, generate one. */ - if (nosig == -1) - for (nosig = 0; nosig < nisig; nosig++) - siglist[nosig] = nosig; - - /* Otherwise, check that the signal numbers are legal. */ - else { - for (i = 0; i < nosig && nosig > 0; i++) - if (siglist[i] < 0 || siglist[i] >= nisig) { - (void)fprintf(stderr, - "%s: warning: signal %d can't be read from record %s\n", - pname, siglist[i], irec); - /* Delete illegal signal numbers from the list. */ - for (j = i; j+1 < nosig; j++) - siglist[j] = siglist[j+1]; - nosig--; - i--; - } - if (nosig == 0) { - (void)fprintf(stderr, "%s: no output signals written\n", pname); - exit(2); - } - } + (void)fprintf(stderr, " done\n"); /* If an output record was specified using `-o', check that the output - signals are writable. */ - if (orec) { - /* Temporarily suppress WFDB library error messages. */ - wfdbquiet(); - - n = nosig; - while ((i = osigopen(orec, dfout, (unsigned)n)) != n) { - if (i == -1) { - (void)fprintf(stderr, - "%s: can't read header file for record %s\n", - pname, orec); - exit(2); - } - else if (i == -2) { - (void)fprintf(stderr, - "%s: incorrect header file format for record %s\n", - pname, orec); - exit(2); - } - else if (--n <= 0) { - (void)fprintf(stderr, - "%s: can't open any output signals for record %s\n", - pname, orec); - exit(2); - } - } - - /* If some but not all outputs can be written, print a warning and - reduce the number of outputs as necessary. */ - if (n < nosig) { - (void)fprintf(stderr, - "%s: warning: writing only the first %d of %d signals\n", - pname, n, nosig); - nosig = n; - for (nisig = i = 0; i < nosig; i++) - if (nisig <= siglist[i]) nisig = siglist[i]+1; - } - - /* Re-enable WFDB library error messages. */ - wfdbverbose(); + signals are writable. Suppress warning messages about possible + sampling frequency differences. */ + wfdbquiet(); + if (orec && (osigopen(orec, dfout, (unsigned)nosig) != nosig)) { + (void)fprintf(stderr, "%s: can't write output signals\n", pname); + exit(2); } + wfdbverbose(); /* If the `-n' option was specified, copy the signal descriptions from the - input record header file into the siginfo structures for the output - record (for eventual storage in the new output header file.) To make + input record header file into the WFDB_Siginfo structures for the output + record (for eventual storage in the new output header file). To make the changes effective, the output signals must be (re)opened using osigfopen. */ if (nrec && use_irec_desc) { @@ -556,10 +609,10 @@ /* A signal may be rescaled by xform depending on the gains and ADC resolutions specified. The rules for doing so are as follows: 1. If the output gain has not been specified, the signal is scaled - only if the input and output ADC resolutions have been specified - and differ. In this case, the scale factor (gain[]) is - determined so that the appropriate number of bits will be - dropped from or added to each signal. + only if the input and output ADC resolutions differ. In this + case, the scale factor (gain[]) is determined so that the + appropriate number of bits will be dropped from or added to each + signal. 2. If the output gain has been specified, the signal is scaled by the ratio of the output and input gains. If the input gain is not specified explicitly, the value WFDB_DEFGAIN is assumed. @@ -882,7 +935,7 @@ /* Generate a new header file, if so requested. */ if (nrec) { - char *info, xinfo[80]; + char *info, *xinfo; (void)setsampfreq((double)ofreq); if (btstring[0] == '[') { @@ -900,19 +953,28 @@ } while (info = getinfo((char *)NULL)); /* Append additional info summarizing what xform has done. */ - (void)sprintf(xinfo, "Produced by %s from record %s, beginning at %s", - pname, irec, startp); - (void)putinfo(xinfo); - for (i = 0; i < nosig; i++) - if (siglist[i] != i) { - (void)sprintf(xinfo, + if (xinfo = malloc(strlen(pname)+strlen(irec)+strlen(startp)+80)) { + (void)sprintf(xinfo, + "Produced by %s from record %s, beginning at %s", + pname, irec, startp); + (void)putinfo(xinfo); + for (i = 0; i < nosig; i++) + if (siglist[i] != i) { + (void)sprintf(xinfo, "record %s, signal %d <- record %s, signal %d", - nrec, i, irec, siglist[i]); - (void)putinfo(xinfo); - } + nrec, i, irec, siglist[i]); + if (gain[i] != 1.) + (void)sprintf(xinfo+strlen(xinfo), + " * %g", gain[i]); + if (deltav[i] != 0) + (void)sprintf(xinfo+strlen(xinfo), + " %c %d", deltav[i] > 0 ? '+' : '-', + deltav[i] > 0 ? deltav[i] : -deltav[i]); + (void)putinfo(xinfo); + } + } wfdbverbose(); } - wfdbquit(); exit(0); /*NOTREACHED*/ } @@ -964,12 +1026,14 @@ " -o OREC produce output signal file(s) as specified by the header file", " for record OREC", " -s SIGNAL [SIGNAL ...] write only the specified signal(s)", + " -S SCRIPT take answers to prompts from SCRIPT (a text file)", " -t TIME stop at specified time", + " -u adjust annotation times if needed to make them unique", "Unless you use `-o' to specify an *existing* header that describes the", "desired signal files, you will be asked for output specifications. Use", "`-n' to name the record to be created. Use `-s' to select a subset of the", "input signals, or to re-order them in the output file; arguments that", - "follow `-s' are *input* signal numbers (0-31).", /* WFDB_MAXSIG-1 = 31 */ + "follow `-s' are *input* signal numbers (0,1,2,...).", NULL }; diff -Naur wfdb-10.1.6/checkpkg/Makefile wfdb-10.2.0/checkpkg/Makefile --- wfdb-10.1.6/checkpkg/Makefile Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/Makefile Mon Oct 15 14:40:00 2001 @@ -0,0 +1,172 @@ +# file: Makefile G. Moody 7 September 2001 +# +# UNIX 'make' description file for checking the WFDB software package +# +# ----------------------------------------------------------------------------- +# Copyright (C) 2000 George B. Moody +# +# These programs are free software; you can redistribute them and/or modify +# them under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# These programs are distributed in the hope that they will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# these programs; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# You may contact the author by e-mail (george@mit.edu) or postal mail +# (MIT Room E25-505A, Cambridge, MA 02139 USA). For updates to this software, +# please visit PhysioNet (http://www.physionet.org/). +# _____________________________________________________________________________ +# +# This file is used with the UNIX `make' command to check the functionality of +# the WFDB library and applications. Before using it for the first time, check +# that the site-specific variables below are appropriate for your system. To +# build and install the applications, just type `make' (from within this +# directory). To print a set of source listings, type `make listing'. +# _____________________________________________________________________________ +# file: version.def G. Moody 24 May 2000 +# Last revised: 14 August 2001 +# Each release of the WFDB Software Package is identified by a three-part +# version number, defined here: +MAJOR = 10 +MINOR = 2 +RELEASE = 0 +VERSION = $(MAJOR).$(MINOR).$(RELEASE) + +# VDEFS is the set of C compiler options needed to set version number variables +# while compiling the WFDB Software Package. +VDEFS = -DWFDB_MAJOR=$(MAJOR) -DWFDB_MINOR=$(MINOR) -DWFDB_RELEASE=$(RELEASE) +# _____________________________________________________________________________ + +PACKAGE=wfdb-10.2.0 +# file: linux.def G. Moody 31 May 2000 +# Last revised: 5 June 2000 +# 'make' definitions for compiling the WFDB Software Package under Linux + +# Choose a value for WFDBROOT to determine where the WFDB Software Package will +# be installed. One of the following is usually a reasonable choice. +# Installing in /usr generally requires root permissions, but will be easiest +# for future software development (no special -I or -L options will be needed +# to compile software with the WFDB library, since the *.h files and the +# library will be installed in the standard directories). +WFDBROOT = /usr +# Installing in /usr/local usually requires root permissions. On a multi-user +# system where it is desirable to keep the OS vendor's software separate from +# other software, this is a good choice. Another common choice in such cases +# is /opt . +# WFDBROOT = /usr/local +# To install without root permissions, a good choice is to set WFDBROOT to the +# name of your home directory, as in the example below (change as needed). +# WFDBROOT = /home/frodo + +# If the W3C's libwww library of HTTP and FTP client code is available, and +# you wish to compile a WFDB library with NETFILES support, set LWC to +# 'libwww-config' (a utility supplied with libwww). Otherwise set LWC to ':' +# (a program that does nothing, successfully). +LWC = libwww-config + +# LDLIBWWW, which is appended to LDFLAGS below, is the set of options needed +# to link with libwww. If libwww is not installed, or if libwfdb is a shared +# library, LDLIBWWW can be empty (if there is a '#' immediately after the '=' +# below, the remainder of the line is ignored, so LDLIBWWW is empty in this +# case). Otherwise, it is generated from the output of LWC. Note that up to +# three passes through the option list are necessary to satisfy all +# dependencies when linking to the static libwww libraries. +LDLIBWWW = # `$(LWC) --libs` `$(LWC) --libs` `$(LWC) --libs` + +# BINDIR specifies the directory in which the applications will be installed; +# it should be a directory in the PATH of those who will use the applications. +BINDIR = $(WFDBROOT)/bin + +# DBDIR specifies the name of a directory in which to install the contents +# of the `data' directory. +DBDIR = $(WFDBROOT)/database + +# INCDIR specifies the name of a directory in which to install the WFDB +# library's #include <...> files. +INCDIR = $(WFDBROOT)/include + +# LIBDIR specifies the name of a directory in which to install the WFDB +# library. +LIBDIR = $(WFDBROOT)/lib + +# PSPDIR specifies the name of a directory in which to install the PostScript +# prolog (*.pro) files from the 'app' directory. +PSPDIR = $(WFDBROOT)/lib/ps + +# CC is the name of your C compiler. +CC = gcc + +# CFLAGS is the set of C compiler options. CFLAGS should always include +# VDEFS. +CFLAGS = -g -O $(VDEFS) `$(LWC) --cflags` -I$(INCDIR) + +# LDFLAGS is appended to the C compiler command line to specify loading the +# WFDB library. +LDFLAGS = -L$(LIBDIR) -lwfdb $(LDLIBWWW) + +# WFDBLIB is the name of the standard WFDB library. In order to access it via +# `-lwfdb', WFDBLIB should be `libwfdb.a'. +WFDBLIB = libwfdb.a + +# BUILDLIB is the command that creates the static WFDB library once its +# components have been compiled separately; the list of *.o files that +# make up the library will be appended to BUILDLIB. +BUILDLIB = $(AR) $(ARFLAGS) $(WFDBLIB) + +# PRINT is the name of the program used to produce listings (including any +# options for the desired formatting). +PRINT = lpr + +# SETPERMISSIONS is the command needed to make the installed files accessible +# to those who will use them. The value given below makes them readable by +# everyone, and writeable by the owner only. (If you perform the installation +# as `root', `root' is the owner of the installed files.) +SETPERMISSIONS = chmod 644 + +# SETDPERMISSIONS is similarly used to make directories created during the +# installation accessible. +SETDPERMISSIONS = chmod 755 + +# SETLPERMISSIONS is the command needed to make the WFDB library usable by +# programs linked to it. +SETLPERMISSIONS = chmod 644 + +# SETXPERMISSIONS is the command needed to make the applications accessible. +SETXPERMISSIONS = chmod 755 + +# STRIP is the command used to compact the compiled binaries by removing their +# symbol tables. +STRIP = strip +# To retain the symbol tables for debugging, comment out the previous line, and +# uncomment the next line. +# STRIP = : + +# `make' (with no target specified) will be equivalent to `make all'. +make-all: all + +# `make lib-post-install' should be run after installing the WFDB library. +lib-post-install: + ranlib $(LIBDIR)/$(WFDBLIB) + +lib-post-uninstall: + echo "Nothing to be done for lib-post-uninstall" +# _____________________________________________________________________________ +all: + @rm -f lcheck + @make lcheck + @./libcheck + @./appcheck + +lcheck: lcheck.c + @echo Compiling WFDB library test application ... + @$(CC) $(CFLAGS) lcheck.c -o $@ $(LDFLAGS) && echo " Succeeded" + +clean: + rm -f *~ lcheck diff -Naur wfdb-10.1.6/checkpkg/Makefile.top wfdb-10.2.0/checkpkg/Makefile.top --- wfdb-10.1.6/checkpkg/Makefile.top Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/Makefile.top Fri Sep 7 11:35:58 2001 @@ -0,0 +1,32 @@ +# file: Makefile G. Moody 7 September 2001 +# +# UNIX 'make' description file for checking the WFDB software package +# +# ----------------------------------------------------------------------------- +# Copyright (C) 2000 George B. Moody +# +# These programs are free software; you can redistribute them and/or modify +# them under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# These programs are distributed in the hope that they will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# these programs; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# You may contact the author by e-mail (george@mit.edu) or postal mail +# (MIT Room E25-505A, Cambridge, MA 02139 USA). For updates to this software, +# please visit PhysioNet (http://www.physionet.org/). +# _____________________________________________________________________________ +# +# This file is used with the UNIX `make' command to check the functionality of +# the WFDB library and applications. Before using it for the first time, check +# that the site-specific variables below are appropriate for your system. To +# build and install the applications, just type `make' (from within this +# directory). To print a set of source listings, type `make listing'. +# _____________________________________________________________________________ diff -Naur wfdb-10.1.6/checkpkg/Makefile.tpl wfdb-10.2.0/checkpkg/Makefile.tpl --- wfdb-10.1.6/checkpkg/Makefile.tpl Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/Makefile.tpl Tue Sep 11 09:54:00 2001 @@ -0,0 +1,12 @@ +all: + @rm -f lcheck + @make lcheck + @./libcheck + @./appcheck + +lcheck: lcheck.c + @echo Compiling WFDB library test application ... + @$(CC) $(CFLAGS) lcheck.c -o $@ $(LDFLAGS) && echo " Succeeded" + +clean: + rm -f *~ lcheck diff -Naur wfdb-10.1.6/checkpkg/appcheck wfdb-10.2.0/checkpkg/appcheck --- wfdb-10.1.6/checkpkg/appcheck Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/appcheck Wed Sep 12 14:33:35 2001 @@ -0,0 +1,257 @@ +#!/bin/sh +# file: appcheck G. Moody 7 September 2001 +# +# This script checks the functionality of the WFDB applications in the 'app' +# directory. +# +# Suggestions for additional checks are welcome; please send them to the +# author (george@mit.edu). + +WFDB=". ../data http://www.physionet.org/physiobank/database" +export WFDB + +echo Testing wfdbwhich ... +F=wfdbwhich.out +wfdbwhich 100s.atr >$F 2>&1 +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) + +echo Testing wfdbcat ... +F=wfdbcat.out +wfdbcat 100s.atr >$F 2>&1 +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) + +echo Testing rdann ... +F=rdann.out +rdann -r 100s -a atr >$F +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + ) + +echo Testing wrann ... +F=100s.wra +wrann -r 100s -a wra $F +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + ) + +echo Testing wrsamp ... +F=100w.dat +wrsamp -o 100w -f 2 -F 360 -x 200 1 2 $F +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + ) + +echo Testing rr2ann ... +F=100s.a2r +rr2ann -r 100s -a a2r /dev/null +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + ) + +echo Testing bxb ... +F=bxb.out +bxb -r 100s -a atr qrs -f 0 >$F 2>&1 +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) + +echo Testing rxr ... +F=rxr.out +rxr -r 100s -a atr qrs -f 0 >$F 2>&1 +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) + +rm 100s.qrs + +echo Testing ecgeval ... +F=ecgeval.out +ecgeval $F 2>&1 +grep -v file: eval-qrs-mit >>$F +grep -v file: qrs-mit-evaluation >>$F +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F eval-qrs-mit qrs-mit-evaluation bxb.out sd.out ) + +echo Testing fir ... +fir -i 100s -n fir -f 10 -t 15 -c -1 1 +for F in fir.dat fir.hea +do + diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) +done + +echo Testing ihr ... +F=ihr.out +ihr -r 100s -a atr >$F +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) + +echo Testing mfilt ... +mfilt -l 5 -i 100s -n mfilt -f 10 -t 15 2>/dev/null +for F in mfilt.dat mfilt.hea +do + diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) +done + +echo Testing pschart ... +F=pschart.ps +pschart -a atr -c "" -g -l -T Test - >$F <$F <$F +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) + +echo Testing sigamp ... +F=sigamp.out +sigamp -r 100s -a atr >$F +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) + +echo Testing snip ... +snip -i 100s -n snip -a atr -f 10 -t 15 +for F in snip.atr snip.dat snip.hea +do + diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) +done + +echo Testing sortann ... +rdann -r 100s -a atr -f 30 >foo +rdann -r 100s -a atr -t 30 >>foo +( WFDBNOSORT=1; export WFDBNOSORT; wrann -r 100s -a mix /dev/null ) +rm -f foo +sortann -r 100s -a mix +F=100s.mix +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) + +echo Testing sumann ... +F=sumann.out +sumann -r 100s -a atr >$F +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) + +echo Testing sumstats ... +F=sumstats.out +sumstats input/sumstats >$F +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) + +echo Testing tach ... +F=tach.out +tach -r 100s -a atr >$F +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) + +echo Testing wfdbcollate ... +wfdbcollate -s 100s -o wfd -l 30 2>/dev/null +for F in wfd*hea wfd*dat +do + diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) +done + +echo Testing wfdbdesc ... +F=wfdbdesc.out +wfdbdesc 100s >$F +diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) + +echo Testing xform ... +xform -i 100s -a atr -n 100x -o input/100x >xform-1.out 2>&1 +for F in xform-1.out 100x.atr 100x.dat 100x.hea +do + diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) +done + +grep -q "WFDB_NETFILES 1" /usr/include/wfdb/wfdb.h && +( echo "Testing xform (with NETFILES) ..." + xform -i mimicdb/237/237 -s 1 2 0 3 -f 9:19:45 -t "[22:01:23 20/07/1995]" \ + -a all -M -n xform -S input/xform >xform-2.out 2>&1 + for F in xform-2.out xform.hea xform.dat xform.all + do + diff -q $F expected && + ( echo " Files $F and expected/$F match: test succeeded" + rm -f $F ) + done +) + +cat <>qrs-mit-evaluation +echo >>qrs-mit-evaluation +sumstats bxb.out >>qrs-mit-evaluation +echo >>qrs-mit-evaluation +echo Analysis shutdowns >>qrs-mit-evaluation +echo >>qrs-mit-evaluation +sumstats sd.out >>qrs-mit-evaluation +echo >>qrs-mit-evaluation +echo Ventricular ectopic run detection performance >>qrs-mit-evaluation +echo >>qrs-mit-evaluation +sumstats vruns.out >>qrs-mit-evaluation +echo >>qrs-mit-evaluation +echo Supraventricular ectopic run detection performance >>qrs-mit-evaluation +echo >>qrs-mit-evaluation +sumstats sruns.out >>qrs-mit-evaluation +echo >>qrs-mit-evaluation +echo Heart rate measurement number 0 performance >>qrs-mit-evaluation +echo >>qrs-mit-evaluation +sumstats hr0.out >>qrs-mit-evaluation +echo >>qrs-mit-evaluation +echo Ventricular fibrillation detection performance >>qrs-mit-evaluation +echo >>qrs-mit-evaluation +sumstats vf.out >>qrs-mit-evaluation +echo >>qrs-mit-evaluation +echo Atrial fibrillation detection performance >>qrs-mit-evaluation +echo >>qrs-mit-evaluation +sumstats af.out >>qrs-mit-evaluation +echo >>qrs-mit-evaluation +echo Ischemic ST detection performance >>qrs-mit-evaluation +echo >>qrs-mit-evaluation +sumstats st.out >>qrs-mit-evaluation +echo >>qrs-mit-evaluation +: Generate PostScript scatter plot of ST measurements +plotstm stm.out >stm.ps +echo The evaluation is complete. Print text file qrs-mit-evaluation +echo and PostScript file stm.ps to get the results. +Evaluation of `qrs' on the MIT-BIH Arrhythmia Database + diff -Naur wfdb-10.1.6/checkpkg/expected/fir.dat wfdb-10.2.0/checkpkg/expected/fir.dat --- wfdb-10.1.6/checkpkg/expected/fir.dat Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/fir.dat Mon Sep 10 14:59:42 2001 @@ -0,0 +1,6 @@ +²3Éÿðüýÿýðÿÿÿþþÿÿýðþüÿÿÿðþÿÿÿðþþÿÿÿðüÿÿþÿðýðÿþÿÿüþðþÿÿýÿÿýðþþÿÿýþÿüÿÿþþðþðüþýÿýüÿþðÿþÿþýÿðÿÿþðþÿðÿÿðÿÿðþðþÿðÿðýþþðÿýÿþýþÿÿýÿýþþÿüÿðÿÿþÿÿðþþÿÿÿÿÿÿÿþÿðüÿÿÿýÿýþðþýÿýþðýüðÿðþýÿýþÿÿþÿÿðþþýÿþðþÿðþþðÿÿÿÿÿÿÿÿðþÿÿþÿÿÿÿÿþðþþÿÿÿÿþðþþðÿðþÿðþÿÿÿÿÿðýÿðþþþþÿÿþÿûûðÿðÿýÿþüÿÿùÿÿýÿÿÿýüýÿüüþÿþðýÿðþÿðÿýÿýðÿþðýþÿÿðÿúðþðÿþÿþýÿþðÿÿÿýþÿùúÿüøÿûûÿûüý ûÿ  #05-ðâ +ðÅìÿÄÂÿÛ¯ÿýºÙúÿÿðüÿÿÿþÿðýýÿÿýþÿÿÿðþýÿþÿðýÿþÿþðÿýðÿðýðþþÿÿÿþÿþÿÿðþÿÿýýÿðýÿÿÿüðþýÿýþÿÿÿÿüþÿÿÿðüðþþÿÿðþÿÿýðûþÿÿýÿÿÿÿÿþðüýÿÿÿÿÿþþÿþþðþþðÿýðþðþÿðþýÿðþÿÿýþÿþÿþÿÿþÿýýðÿðþÿÿÿþÿÿþÿÿðÿÿÿþüÿÿÿðþþÿþþÿÿÿÿýþÿýÿÿÿþðýÿÿþýþÿýýÿÿðüÿðÿüÿþþðþÿýÿüþðÿðýýÿýÿÿðÿþÿÿðþýðûüýðüþÿüþðÿðÿüÿÿÿðþÿÿþðÿýþÿÿðüýðýÿþÿþðþÿÿÿþÿýþÿÿÿÿþðýþýÿÿðÿðýúÿüøÿÿüÿÿþÿÿÿþýþÿüýÿÿÿðÿýÿÿÿÿþþÿþðþðþüÿÿÿÿþÿÿüðÿþÿþðþðýÿÿûþÿûúÿûüÿþùÿþþÿÿþÿüðûûÿøÿúø û $-0+ðãð½àÿÄÃÿà®Äâý +ðüðÿðýþýðþÿðþþÿÿþÿÿÿðþüÿÿÿÿþÿÿÿýýðÿÿþÿüýþÿÿüÿÿÿÿýþÿþðýðÿþÿþðÿðÿüÿþðþýÿÿþÿÿýÿðÿÿÿüÿûðþðüûÿþûÿÿðÿðýÿÿüþðÿÿÿþðþþÿýþÿÿðþÿÿþþþÿýðÿðÿðþûþþðýþÿðýðûýðýþðþÿÿÿÿÿÿþðþðýþÿÿýÿÿÿÿýÿûýÿÿÿðþÿÿþðþýÿýýÿüþðÿüðÿüÿýðÿðÿþÿÿúÿþðþðýýÿýýðþÿÿÿÿÿÿþðþÿðýüÿðþþýðÿðÿþþÿþðüüðýýðÿüðÿÿÿþýÿûðÿðüÿðÿÿÿÿÿÿÿüýþÿýÿÿðýÿýÿÿðýÿÿüþÿüûÿÿûÿþýÿÿðÿðÿüÿþúÿúýÿðþÿÿþýÿÿþÿþðÿÿÿÿþþðýðÿüÿþþðýÿÿüüÿûýÿúûÿÿúüÿúúÿýö û   +60ðé ðÑíÿËÌÿÝ»ÿþÈ +Ûìüÿÿðþðþþÿþþÿÿÿÿÿýðýÿÿÿðýýþðþÿÿÿÿðÿþÿýðýÿüÿýðÿÿðÿýÿÿðÿðÿÿÿýþÿþÿðýðÿÿÿÿðÿÿÿýüÿÿðÿÿÿÿþÿÿþðÿðÿþÿÿÿÿþÿÿüðþþÿþýÿûÿÿüðÿýÿýýÿýüÿÿðþÿÿþþÿýÿðþþÿüÿðýÿÿýþÿÿÿÿýÿüþðÿðýðÿÿÿþþðþðÿÿÿýýðþðýüÿÿÿÿÿðÿþÿþÿÿÿÿðÿüðþþÿþðûÿýýÿþÿðþðÿýÿþðÿðýýðÿðÿÿðýÿÿýþÿðÿðþÿÿþþÿÿÿðÿðÿþþÿûðýýðüðÿÿÿþÿþðÿþÿüÿÿÿÿðýþÿþýÿÿðþðþðþÿðýýÿÿÿðÿðþýþÿÿÿÿÿÿþÿÿÿÿÿüðþðÿðýÿýüÿÿþÿÿÿúÿùüðÿÿýÿýÿþÿÿþþðýýýÿÿÿÿÿðÿþÿþþÿÿþðÿðüþÿûûÿüøÿúüýÿÿÿø ú *1.ðîðÆìÿÇËÿܵÿûÀ +Üòûþÿýÿÿÿðþþÿÿûüðþÿÿÿðüúþÿþýÿýþÿÿþþÿÿýÿÿðÿðþþÿýðÿþÿþþþÿýþÿýýðþðÿÿÿÿÿýðÿÿÿÿÿÿüýðþðüðÿþÿÿÿðÿðýðþüÿþÿðþðÿýÿûðþÿþÿýüÿÿÿÿüþÿþðþÿÿüüðÿÿÿðÿþÿýÿþÿÿþÿþÿðþðÿðÿÿÿüýðÿþþÿúþðÿüÿüþðÿþýÿÿÿðÿÿÿýþÿÿýÿÿðÿÿÿýþÿÿüÿðÿûÿýðÿðüýüÿÿðýýÿüüðÿüÿüðÿþÿüðÿþðÿÿÿÿþÿÿþðÿðþüðÿþÿÿþÿÿÿÿÿþðýðÿðûÿÿÿðýðþðÿþÿþþýÿýðÿþüÿüðþðýøúÿþþÿÿüþÿýÿÿÿýýÿüÿÿÿðÿðÿûÿÿðÿüÿÿðþûÿÿðþðÿüÿþþÿþÿýÿÿþÿüÿÿúðüýÿþúÿûùÿúüù +ù!27-ðýðÚð½ØÿÅ»ÿè²Æåÿüüÿÿ ðÿÿÿÿþÿþÿÿÿÿýÿþðÿÿÿþþðþðýüÿÿðÿÿüÿÿÿþÿÿýÿüÿÿÿðþþÿþÿðþþÿÿýðþðÿÿÿþýÿðÿðÿþÿþþðþþÿþþÿýýðþðÿþÿýþÿÿðüðûþþÿþðþÿÿýÿÿýûþðÿýÿýýÿþþÿÿÿÿüÿÿðýþÿÿÿÿÿÿýðÿðýÿÿÿýðþðýýÿÿþÿÿÿþÿÿþÿþÿÿÿÿðþýÿýþÿðÿðÿþÿþÿýÿþðýýÿþûÿûÿÿÿþüÿþýÿÿÿðÿüÿÿðÿðþþðÿðüþÿýÿÿÿûÿüÿðÿðþþýðþðþûÿÿðÿðýÿÿýþÿÿðÿðÿþÿðÿþÿþþÿÿýðþðÿþÿþüðÿðûðÿþÿýúûÿþÿþþÿÿúÿüýÿÿÿÿÿýðþðÿþÿýÿðþýÿþþþÿÿÿðÿýÿÿðüðùýÿû÷ÿúùÿýüÿþýú øÿ#,20ðßð¼ÛÿÇÀÿè²Êëðþðþðÿþÿÿýðÿÿÿýþýðüýÿþÿÿðþÿÿýþÿþðÿþÿýþÿÿÿýðÿþÿÿÿÿýþÿþ \ No newline at end of file diff -Naur wfdb-10.1.6/checkpkg/expected/fir.hea wfdb-10.2.0/checkpkg/expected/fir.hea --- wfdb-10.1.6/checkpkg/expected/fir.hea Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/fir.hea Mon Sep 10 14:59:42 2001 @@ -0,0 +1,3 @@ +fir 2 360 1800 +fir.dat 212 200 11 1024 946 949 0 MLII +fir.dat 212 200 11 1024 969 972 0 V5 diff -Naur wfdb-10.1.6/checkpkg/expected/ihr.out wfdb-10.2.0/checkpkg/expected/ihr.out --- wfdb-10.1.6/checkpkg/expected/ihr.out Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/ihr.out Sun Sep 9 23:14:21 2001 @@ -0,0 +1,69 @@ +1.02778 73.9726 1 +1.83889 76.0563 0 +2.62778 75.7895 0 +3.41944 76.0563 0 +4.20833 73.4694 0 +7.51667 73.9726 1 +8.32778 76.0563 0 +9.11667 77.6978 0 +9.88889 71.5232 0 +10.7278 70.1299 0 +11.5833 72.973 0 +12.4056 72.4832 0 +13.2333 72.973 0 +14.0556 75.5245 0 +14.85 75.2613 0 +15.6472 75.7895 0 +16.4389 72.973 0 +17.2611 69.0096 0 +18.1306 72.973 0 +18.9528 76.3251 0 +19.7389 75.7895 0 +20.5306 77.4194 0 +21.3056 76.3251 0 +22.0917 73.9726 0 +22.9028 73.4694 0 +23.7194 72.4832 0 +24.5472 71.0526 0 +25.3917 74.4828 0 +26.1972 77.4194 0 +26.9722 75 0 +27.7722 76.0563 0 +28.5611 69.9029 0 +29.4194 71.2871 0 +30.2611 72.7273 0 +31.0861 74.7405 0 +31.8889 71.7608 0 +32.725 75.7895 0 +33.5167 76.0563 0 +34.3056 73.2203 0 +35.125 71.0526 0 +35.9694 68.1388 0 +36.85 72.973 0 +37.6722 77.1429 0 +38.45 74.7405 0 +39.2528 73.9726 0 +40.0639 75.2613 0 +40.8611 71.7608 0 +41.6972 72.2408 0 +42.5278 72.7273 0 +43.3528 73.9726 0 +44.1639 76.0563 0 +44.9528 76.8683 0 +45.7333 74.2268 0 +46.5417 71.2871 0 +47.3833 72 0 +48.2167 72.2408 0 +49.0472 74.4828 0 +49.8528 77.1429 0 +50.6306 75.2613 0 +51.4278 76.8683 0 +52.2083 75.7895 0 +53 70.1299 0 +53.8556 70.8197 0 +54.7028 72.973 0 +55.525 76.5957 0 +56.3083 76.3251 0 +57.0944 76.3251 0 +57.8806 73.4694 0 +58.6972 73.9726 0 diff -Naur wfdb-10.1.6/checkpkg/expected/lcheck.log-NETFILES wfdb-10.2.0/checkpkg/expected/lcheck.log-NETFILES --- wfdb-10.1.6/checkpkg/expected/lcheck.log-NETFILES Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/lcheck.log-NETFILES Tue Sep 11 10:03:44 2001 @@ -0,0 +1,99 @@ +[OK]: Library version matches +[OK]: WFDB supports NETFILES +[OK]: WFDB_MAXANN = 2 +[OK]: WFDB_MAXSIG = 32 +[OK]: WFDB_MAXSPF = 4 +[OK]: WFDB_MAXRNL = 11 +[OK]: WFDB_MAXUSL = 20 +[OK]: WFDB_MAXDSL = 60 +[OK]: Signal formats = {0, 8, 16, 61, 80, 160, 212, 310, 311} +[OK]: WFDB_DEFFREQ = 250 +[OK]: WFDB_DEFGAIN = 200 +[OK]: WFDB_DEFRES = 12 +[OK]: Default WFDB path = . http://www.physionet.org/physiobank/database +[OK]: WFDB path modified successfully +[OK]: sampfreq(NULL) returned 0 +[OK]: setsampfreq changed sampling frequency successfully +[OK]: sampfreq(100s) returned 360 +[OK]: annopen of 1 file succeeded +[OK]: annopen of 2 files succeeded +[OK]: strtim returned 1800 +[OK]: iannsettime skipping forward to 0:05 +[OK]: getann read: {N 0 0 0} at 0:05.025 (1809) +[OK]: getann read: {A 0 0 0} at 0:05.677 (2044) +[OK]: getann read: {N 0 0 0} at 0:06.672 (2402) +[OK]: getann read: {N 0 0 0} at 0:07.516 (2706) +[OK]: getann read: {N 0 0 0} at 0:08.327 (2998) +[OK]: iannsettime skipping backward to 0:00 +[OK]: 75 annotations read, 75 written +[OK]: isigopen((null), NULL, 0) succeeded +[OK]: (at 0:00.000) getframe returned { 995, 1011} +[OK]: (at 0:00.002) getframe returned { 995, 1011} +[OK]: (at 0:00.005) getframe returned { 995, 1011} +[OK]: (at 0:00.008) getframe returned { 995, 1011} +[OK]: (at 0:00.011) getframe returned { 995, 1011} +[OK]: sampfreq returned 360 +[OK]: strtim returned 7200 +[OK]: isigsettime skipping forward to 0:20 +[OK]: (at 0:20.000) getvec returned { 943, 946} [-0.405, -0.390] +[OK]: (at 0:20.002) getvec returned { 942, 945} [-0.410, -0.395] +[OK]: (at 0:20.005) getvec returned { 942, 946} [-0.410, -0.390] +[OK]: (at 0:20.008) getvec returned { 942, 945} [-0.410, -0.395] +[OK]: (at 0:20.011) getvec returned { 942, 949} [-0.410, -0.375] +[OK]: isigsettime skipping backward to 0:19.997 +[OK]: (at 0:19.997) getframe returned { 940, 944} +[OK]: (at 0:20.000) getframe returned { 943, 946} +[OK]: (at 0:20.002) getframe returned { 942, 945} +[OK]: (at 0:20.005) getframe returned { 942, 946} +[OK]: (at 0:20.008) getframe returned { 942, 945} +[OK]: (at 0:20.011) getframe returned { 942, 949} +[OK]: isigsettime skipping backward to 0:00.000 +[OK]: osigfopen returned 2 +[OK]: getframe read 21600 samples +[OK]: putvec wrote 21600 samples +[OK]: newheader created header for output record 100z +[OK]: 3 info strings copied to record 100z header +[OK]: Repeating tests using NETFILES (reverting to default WFDB path) +[OK]: sampfreq(NULL) returned 0 +[OK]: setsampfreq changed sampling frequency successfully +[OK]: sampfreq(udb/100s) returned 360 +[OK]: annopen of 1 file succeeded +[OK]: annopen of 2 files succeeded +[OK]: strtim returned 1800 +[OK]: iannsettime skipping forward to 0:05 +[OK]: getann read: {N 0 0 0} at 0:05.025 (1809) +[OK]: getann read: {A 0 0 0} at 0:05.677 (2044) +[OK]: getann read: {N 0 0 0} at 0:06.672 (2402) +[OK]: getann read: {N 0 0 0} at 0:07.516 (2706) +[OK]: getann read: {N 0 0 0} at 0:08.327 (2998) +[OK]: iannsettime skipping backward to 0:00 +[OK]: 75 annotations read, 75 written +[OK]: isigopen((null), NULL, 0) succeeded +[OK]: (at 0:00.000) getframe returned { 995, 1011} +[OK]: (at 0:00.002) getframe returned { 995, 1011} +[OK]: (at 0:00.005) getframe returned { 995, 1011} +[OK]: (at 0:00.008) getframe returned { 995, 1011} +[OK]: (at 0:00.011) getframe returned { 995, 1011} +[OK]: sampfreq returned 360 +[OK]: strtim returned 7200 +[OK]: isigsettime skipping forward to 0:20 +[OK]: (at 0:20.000) getvec returned { 943, 946} [-0.405, -0.390] +[OK]: (at 0:20.002) getvec returned { 942, 945} [-0.410, -0.395] +[OK]: (at 0:20.005) getvec returned { 942, 946} [-0.410, -0.390] +[OK]: (at 0:20.008) getvec returned { 942, 945} [-0.410, -0.395] +[OK]: (at 0:20.011) getvec returned { 942, 949} [-0.410, -0.375] +[OK]: isigsettime skipping backward to 0:19.997 +[OK]: (at 0:19.997) getframe returned { 940, 944} +[OK]: (at 0:20.000) getframe returned { 943, 946} +[OK]: (at 0:20.002) getframe returned { 942, 945} +[OK]: (at 0:20.005) getframe returned { 942, 946} +[OK]: (at 0:20.008) getframe returned { 942, 945} +[OK]: (at 0:20.011) getframe returned { 942, 949} +[OK]: isigsettime skipping backward to 0:00.000 +[OK]: osigfopen returned 2 +[OK]: getframe read 21600 samples +[OK]: putvec wrote 21600 samples +[OK]: newheader created header for output record udb/100z +[OK]: 3 info strings copied to record udb/100z header +[OK]: no WFDB library errors +no errors: test succeeded diff -Naur wfdb-10.1.6/checkpkg/expected/lcheck.log-no-NETFILES wfdb-10.2.0/checkpkg/expected/lcheck.log-no-NETFILES --- wfdb-10.1.6/checkpkg/expected/lcheck.log-no-NETFILES Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/lcheck.log-no-NETFILES Tue Sep 11 10:03:57 2001 @@ -0,0 +1,57 @@ +[OK]: Library version matches +[OK]: WFDB does not support NETFILES +[OK]: WFDB_MAXANN = 2 +[OK]: WFDB_MAXSIG = 32 +[OK]: WFDB_MAXSPF = 4 +[OK]: WFDB_MAXRNL = 11 +[OK]: WFDB_MAXUSL = 20 +[OK]: WFDB_MAXDSL = 60 +[OK]: Signal formats = {0, 8, 16, 61, 80, 160, 212, 310, 311} +[OK]: WFDB_DEFFREQ = 250 +[OK]: WFDB_DEFGAIN = 200 +[OK]: WFDB_DEFRES = 12 +[OK]: Default WFDB path = . http://www.physionet.org/physiobank/database +[OK]: WFDB path modified successfully +[OK]: sampfreq(NULL) returned 0 +[OK]: setsampfreq changed sampling frequency successfully +[OK]: sampfreq(100s) returned 360 +[OK]: annopen of 1 file succeeded +[OK]: annopen of 2 files succeeded +[OK]: strtim returned 1800 +[OK]: iannsettime skipping forward to 0:05 +[OK]: getann read: {N 0 0 0} at 0:05.025 (1809) +[OK]: getann read: {A 0 0 0} at 0:05.677 (2044) +[OK]: getann read: {N 0 0 0} at 0:06.672 (2402) +[OK]: getann read: {N 0 0 0} at 0:07.516 (2706) +[OK]: getann read: {N 0 0 0} at 0:08.327 (2998) +[OK]: iannsettime skipping backward to 0:00 +[OK]: 75 annotations read, 75 written +[OK]: isigopen((null), NULL, 0) succeeded +[OK]: (at 0:00.000) getframe returned { 995, 1011} +[OK]: (at 0:00.002) getframe returned { 995, 1011} +[OK]: (at 0:00.005) getframe returned { 995, 1011} +[OK]: (at 0:00.008) getframe returned { 995, 1011} +[OK]: (at 0:00.011) getframe returned { 995, 1011} +[OK]: sampfreq returned 360 +[OK]: strtim returned 7200 +[OK]: isigsettime skipping forward to 0:20 +[OK]: (at 0:20.000) getvec returned { 943, 946} [-0.405, -0.390] +[OK]: (at 0:20.002) getvec returned { 942, 945} [-0.410, -0.395] +[OK]: (at 0:20.005) getvec returned { 942, 946} [-0.410, -0.390] +[OK]: (at 0:20.008) getvec returned { 942, 945} [-0.410, -0.395] +[OK]: (at 0:20.011) getvec returned { 942, 949} [-0.410, -0.375] +[OK]: isigsettime skipping backward to 0:19.997 +[OK]: (at 0:19.997) getframe returned { 940, 944} +[OK]: (at 0:20.000) getframe returned { 943, 946} +[OK]: (at 0:20.002) getframe returned { 942, 945} +[OK]: (at 0:20.005) getframe returned { 942, 946} +[OK]: (at 0:20.008) getframe returned { 942, 945} +[OK]: (at 0:20.011) getframe returned { 942, 949} +[OK]: isigsettime skipping backward to 0:00.000 +[OK]: osigfopen returned 2 +[OK]: getframe read 21600 samples +[OK]: putvec wrote 21600 samples +[OK]: newheader created header for output record 100z +[OK]: 3 info strings copied to record 100z header +[OK]: no WFDB library errors +no errors: test succeeded diff -Naur wfdb-10.1.6/checkpkg/expected/mfilt.dat wfdb-10.2.0/checkpkg/expected/mfilt.dat --- wfdb-10.1.6/checkpkg/expected/mfilt.dat Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/mfilt.dat Mon Sep 10 15:01:43 2001 @@ -0,0 +1,2 @@ +±3DZ3DZ3Ç°3Ç°3Ç°3Dz3Ȳ3Ȳ3Ȳ3Ȳ3Ȳ3Ȳ3Ȳ3Ç°3Ç°3Ç°3DZ3DZ3DZ3Ʊ3Æ°3Æ°3Æ°3ű3ű3ű3ñ3ñ3ñ3ô3Ä´3Ä´3ij3³3³3Á³3Á³3Á³3¾²3¼²3¼°3»°3º¯3º­3¶¬3µ«3´«3´ª3³ª3¯ª3¯§3­§3­§3­¨3­¨3­¨3«¨3«¨3«¨3¯«3²«3³«3³«3³«3´­3º­3À³3Á³3Áµ3ö3ø3ʺ3ν3Ͻ3п3Ñ¿3ÑÀ3ÑÃ3ÔÄ3ÔÅ3ÔÅ3ÔÆ3ÔÆ3ÕÆ3ÕÇ3ÕÇ3ÕÇ3ÕÇ3ÕÇ3ÕÇ3ÖÈ3×È3×È3×È3×È3×É3×É3×É3×Æ3ÖÄ3ÖÄ3ÖÄ3×Ä3×Ä3×Ã3×Ã3×Ã3ØÄ3ØÄ3ØÄ3ÕÃ3ÕÃ3ÕÃ3ÖÃ3ÖÃ3ÖÃ3ÕÃ3ÕÂ3ÕÂ3ÕÂ3ÕÃ3ÕÃ3ÔÃ3ÔÃ3ÔÃ3ÔÃ3ÔÃ3ÔÃ3ÓÁ3ÒÀ3ÒÀ3ÒÀ3ÓÀ3ÓÀ3Ó¿3Ó¿3Ó¿3ÓÀ3ÓÀ3ÓÀ3Ó¿3Ó¿3Ó¿3ÔÂ3ÔÂ3ÔÂ3ÔÀ3ÔÀ3ÕÀ3ÕÂ3ÕÂ3ÕÂ3ÓÁ3Ó¾3Ó¾3Ó¾3Ó¿3Ó¿3Ó¿3Ó¿3Ô¿3ÔÁ3ÔÁ3ÔÁ3ÔÁ3ÔÁ3ÔÁ3ÕÂ3ÕÂ3ÕÂ3ÓÁ3ÓÁ3ÓÁ3ÓÂ3ÕÃ3ÕÃ3ÕÄ3ÔÄ3ÔÄ3ÓÈ3ÓÉ3ÔÉ3ÔÉ3ÔË3ÔÌ3×Ð3ØÐ3ØÐ3ØÑ3ØÑ3ÙÓ3ÚÕ3ÜÖ3ÜÖ3ÜÖ3ÜÕ3ÜÕ3ÜÔ3ÝÔ3ÝÔ3ÝÔ3ÝÒ3ÝÒ3ÞÒ3áÒ3áÒ3áÒ3ÞÒ3ÝÒ3ÜÖ3ÜÖ3ÜÖ3ÚÓ3ÚÌ3ÚÉ3ÙÈ3ÙÇ3ÙÃ3ØÁ3ØÀ3Ø¿3׿3׿3׿3Õ¿3Ô¿3Ô¿3ÕÀ3ÖÀ3ÖÀ3ÖÀ3ÕÀ3ÕÀ3ÕÀ3Õ¾3Õ¾3Õ¾3Õ¾3Ö¾3Ö¾3Ö¾3Ö¾3Õ½3Ó¼3Ñ»3к3͹3Ƴ3«3½¦3½¢3½Ÿ3ÇŸ3ÝŸ3ö¥C¿C&ßC?DV2DmgDm”Dm§De§D*§4îi4Ë4ËÒ3ˬ3ͬ3ά3δ3ε3ε3η3η3ζ3ζ3ζ3ε3ε3ε3ζ3ζ3ζ3Ͷ3Ͷ3Ͷ3Ͷ3Ͷ3͵3Ͷ3Ͷ3Í·3͸3͸3͸3͸3͹3ι3Ϲ3Ϻ3Ϻ3Ϻ3ϸ3ϸ3ϸ3ϸ3ϸ3ϸ3ϸ3ϸ3Ϲ3Ϲ3Ϲ3ι3θ3θ3и3к3к3ͺ3͹3͹3͹3͹3͹3̸3ɸ3ɸ3ɸ3ȸ3ȸ3È·3È·3È·3È·3ȸ3Ÿ3ù3¹3¹3º3Àº3Àº3»¹3º¹3º¸3º·3¹·3¹·3¸·3´µ3´µ3´µ3´µ3´µ3´µ3³³3³³3³´3´´3´³3´´3µ´3¶´3½¶3Á¸3º3½3ľ3ÇÁ3ÌÅ3ÓÆ3ÓÆ3ÓÆ3ÔÇ3ÕÈ3×È3ÙÊ3ÙÊ3ÚÌ3ÛÌ3ÜÌ3ÞÎ3ÞÎ3ÞÎ3ÝÎ3ÝÎ3ÝÏ3ÞÏ3ßÏ3ßÏ3ßÎ3ÞÎ3ÞÎ3ÞÎ3ÞÎ3ÞÎ3ÜÍ3ÜÍ3ÜÍ3ÞÎ3ßÎ3ßÎ3ßÎ3ÞË3ÞË3ÞË3ÞË3ÞÊ3ÝÉ3ÛÉ3ÛÉ3ÚÊ3ÚÊ3ÚÊ3ÚÈ3ÚÈ3ÜÇ3ÚÇ3ÚÇ3ÚÇ3×Ç3ÖÇ3ÖÇ3ÖÇ3ØÇ3ØÇ3ØÆ3×Æ3×Æ3×Æ3×Æ3×Å3×Ã3×Â3×Â3ÖÂ3ÖÂ3ÖÂ3ÖÂ3ÕÂ3ÕÂ3ÕÂ3ÕÂ3ÔÂ3ÔÁ3ÔÁ3ÔÁ3ÔÁ3ÔÄ3ÔÄ3ÔÄ3ÔÄ3ÔÄ3ÔÄ3ÔÄ3ÔÄ3ÔÂ3ÔÂ3ÔÂ3ÔÃ3ÔÃ3ÔÃ3ÔÁ3ÓÁ3ÓÁ3ÓÂ3ÔÂ3ÔÂ3ÕÃ3ÕÃ3ÕÃ3ÖÄ3ÖÅ3ÖÅ3ÔÅ3ÓÅ3ÓÅ3ÓÅ3ÖÅ3ÖÅ3ÖÅ3ÕÅ3ÕÅ3ÕÇ3ÕÈ3ÕÈ3ÓÉ3ÓË3ÓÏ3ÖÐ3ÖÐ3ÖÐ3ÖÐ3ÖÐ3ÖÔ3ÚÔ3ÚÕ3ÛÖ3Û×3ÛØ3Û×3Û×3Þ×3ÞÖ3àÕ3àÕ3àÕ3àÖ3àÖ3ßÖ3ßÖ3ßÖ3ßÙ3ßÙ3ÞÙ3Ý×3ÙÏ3ÙË3ÙÉ3ØÈ3ØÇ3ØÄ3×Â3ÔÀ3ÔÀ3Ô¿3Ô¿3Ô¿3Ô¾3Ô¾3Ô¾3Ó¾3Ó¾3Ó¾3Ѽ3Ѽ3Ѽ3Ò½3Ò½3Ò½3Ò½3Ò½3Ò½3Ò½3Ò½3Ò½3Í»3ȵ3ñ3Áª3¿¨3¾¦3º¦3µ¡3µ 3µš3µ“3À“3Ñ“3çžCµCÎC)èC? DT9DiiDi”Di”D^”D’4ßU4Ê4ÊÇ3Ê©3Ì©3Ì©3̳3Ì´3̶3ʶ3ʶ3ʶ3ʶ3Ê·3Ê·3Ê·3Ê·3Ê·3Ê·3Ê·3Ê·3Ë·3Ë·3Ë·3ʵ3ʵ3ʵ3ʸ3˸3˸3Ë·3Ë·3Ë·3˹3̹3̹3Ì·3Ì·3Ì·3Ì·3Ì·3Ì·3̵3̵3̵3Ì·3̸3̸3Ë·3˸3˹3˹3̹3̹3̸3ʸ3ʸ3ʸ3É·3É·3È·3È·3ȸ3ȸ3ɸ3É·3È·3Å·3Å·3Ÿ3ĸ3ĸ3¸3µ3µ3Áµ3Á·3Á·3¾·3º·3º·3º¸3º¸3¹¸3¹¸3¶·3µ¶3´¶3³¶3²´3²´3±´3±´3±¶3±¶3±¶3°¶3°¶3°¶3³¶3µ·3··3·¸3·¸3¹º3¿¼3Å¿3Å¿3ÈÀ3ÉÁ3ËÂ3ÏÅ3ÒÆ3ÓÆ3ÕÇ3ÕÉ3ÖÊ3ÖË3ÖË3ÙË3ÙÉ3ÙÉ3ÙÉ3ÚË3ÚË3ÚË3ÙÊ3ÙÊ3ÙÊ3ÚÍ3ÚÍ3ÚÍ3ÙÍ3ÙÍ3ÙÍ3ÙÌ3ÙÌ3ÙË3ÙÈ3ÖÈ3ÖÈ3ÖÈ3ÖÈ3ÖÈ3ÕÈ3ÕÈ3ÕÈ3ÕÇ3ÕÇ3ÕÇ3ÔÄ3ÔÄ3ÔÄ3ÔÄ3ÕÆ3ÕÆ3ÕÄ3ÔÄ3ÔÅ3ÓÅ3ÓÅ3ÓÅ3ÒÅ3ÒÂ3ÒÂ3ÒÂ3ÒÂ3ÒÂ3ÏÁ3ÎÀ3ÎÀ3ÎÀ3ÏÀ3ÏÀ3Ï¿3Ï¿3Ï¿3Ï¿3ÐÁ3ÐÁ3ÏÁ3ÎÁ3ÎÁ3ÎÁ3ÎÁ3ÎÁ3ÎÀ3ο3ο3Ï¿3ÐÀ3ÐÀ3ÐÀ3ÐÀ3ÐÀ3ÐÀ3ÎÀ3;3̾3̾3;3;3;3Ͼ3о3о3о3ÐÁ3ÐÁ3ÏÁ3ÏÁ3ÎÁ3ÎÁ3ÍÄ3ÎÇ3ÎÈ3ÍË3ÍË3ÎÌ3ÎÌ3ÐÌ3ÑÍ3ÑÍ3ÑÎ3ÑÐ3ÒÒ3ÒÓ3ÓÓ3ÓÓ3ÔÓ3ÔÓ3×Ó3×Ó3×Ò3×Ò3ÖÑ3ÖÐ3ÖÐ3ÖÎ3ÖÎ3ÕÎ3ÓÑ3ÓÔ3ÒÔ3ÒÔ3ÏÐ3ÎË3ÎÊ3ÎÊ3ÐÈ3ÐÈ3ÐÆ3ÎÀ3˾3˾3˽3˽3˽3ɺ3ɺ3ɺ3ɺ3ʺ3ʺ3ʹ3ʹ3ʹ3ȹ3ȹ3ȹ3Ǹ3Ǹ3Ǹ3ȹ3ȹ3ȹ3Ķ3¿³3¹®3¹¨3¸¤3¸ž3¹”3¹”3Ê”3ÞŸ3ñ·3þÍC +çCD3HD7xD7ŒD7ŒDŒ4ÓX4¸4¸Û3¸¶3»¢3»¢3»¢3¼¨3¾«3Á®3Á®3Á®3¿®3¿¯3¿¯3À¯3À¯3À¯3À¯3À±3À±3À±3¿±3¾±3¾°3¾°3À°3À°3À¯3À®3À¯3À¯3Á°3Á°3Á°3Á±3Á±3Á±3Á²3ò3ò3î3À®3À®3À®3À®3À­3À¬3À¬3À¬3Á­3Á­3Á­3¾¬3¾«3¾«3À¬3À¬3À­3À®3¿®3¿®3À®3¿¯3¿¯3¿¯3¿®3¿®3¾®3¾®3¾®3½®3½®3½®3¼®3»®3»®3º®3¸®3¸®3·°3¶°3¶°3´­3¯­3¯­3®­3¬­3¬­3«ª3¨¨3¨¨3¨¨3¨¨3¨¨3¨©3¨¨3¨¨3§¨3§¨3§¨3§¨3§¨3§¨3¬©3°¬3³­3´®3´¯3µ´3·µ3»¶3¼¶3¼¶3¿¸3ù3Æ¿3ÆÀ3ÆÀ3ÃÀ3ÃÀ3ÃÀ3ÆÁ3ÈÁ3ÈÁ3ÈÀ3ÇÀ3ÇÀ3ÆÂ3ÆÂ3ÆÂ3ÆÂ3ÆÂ3ÆÃ3ÈÃ3ÈÃ3ÈÃ3ÇÃ3ÇÁ3ÇÁ3ÇÁ3ÇÁ3ÇÁ3ľ3ľ3ľ3ÅÀ3ÅÀ3ÅÀ3Å¿3ÿ3ÿ3ÃÀ3ÄÀ3ÄÀ3ÄÀ3ÄÀ3ÄÀ3ÂÀ3À¿3¿¿3¿¼3¿»3¿»3¿»3¿»3¿º3¿»3¿»3¿»3¾»3¾»3¾º3¾º3½º3½º3½¼3½¼3½¼3¼º3¼¹3¼¹3¾¹3¾º3¾º3¼º3¼¸3¼¸3½¸3¾¸3¾¸3¾¸3¾¸3¾¸3½º3½º3½º3½»3½»3½¼3½¼3¼¼3¼¼3¼»3¼º3¼º3¿º3¿º3¿º3»º3»º3»º3»¼3¾¼3¾¼3¾¼3¼¼3¼¼3¼¾3¼Á3¼Á3½Á3½Á3½Ä3¿Ä3ÀÈ3ÁÈ3ÁÈ3ÁË3ÁË3ÂÑ3ÃÑ3ÃÑ3ÃÏ3ÃÏ3ÃÎ3ÅÎ3ÇÎ3ÇÍ3ÇË3ÆÊ3ÆÉ3ÆÉ3ÅÉ3ÅÌ3ÄÌ3ÃÌ3ÃÉ3ÃÅ3ÃÄ3ÃÃ3½3½º3½º3½º3½º3½¹3½¸3¼·3¼·3¼·3½·3½·3½µ3¾µ3¾µ3¿µ3¿µ3¿µ3¿³3¾³3¾³3¾¶3¾¶3¿¶3¿´3¿´3¾´3¾´3½´3º´3µ¯3±§3«£3« 3«Ÿ3«—3·—3Ê—3ߦ3ó¿CÛCûC$%D;VD?„D?–D?–D–4Ìa4­4­Ö3­²3µ¤3¸¤3º¤3º¦3º«3½­3½­3¾­3¾­3¾­3¾°3¾±3¿±3¿±3½°3¼°3¼°3¼¯3¿¯3¿¯3¿¯3¾®3¾®3¾­3À­3À­3Àª3¿ª3¿ª3¿ª3¿¬3¿¬3¿«3¿«3¿¬3À¬3À¬3À¬3À¬3À¬3À¬3Á®3Á®3Á®3À¬3À¬3À¬3Á­3Á­3Á­3À­3½¬3½¬3½¬3¾¬3¾¬3¾«3¾«3¾«3¾«3¾«3¾«3½«3ºª3ºª3ºª3º«3º«3¸«3·«3·«3·«3·­3¶­3¶­3´­3´¬3³¬3²¬3²¬3±©3¬©3¬©3¬©3«¨3«¦3ª¥3§£3¦£3¦£3¦£3¦£3¥¢3¤¢3¤¢3¤¤3§¤3¨¥3©¥3¬¥3°¨3´«3·­3·¯3¹°3»°3¼³3À·3Ä·3Å·3Æ·3Ǹ3ȹ3ʼ3̾3;3;3ξ3ξ3ÏÀ3ÏÀ3ÏÀ3ÏÀ3ÐÀ3ÐÀ3ÐÁ3ÐÁ3ÐÁ3ÐÁ3ÐÀ3ÐÀ3ÐÀ3ÑÀ3ÑÀ3Ѿ3;3;3Í¿3ο3ο3μ3ͼ3ͼ3Í¿3Í¿3Í¿3ͼ3ͼ3ͼ3ͼ3ͼ3ͼ3Ê»3Ê»3Ê»3ͼ3ͼ3ͼ3Ê»3ʺ3ʺ3ʺ3˺3˺3˼3˼3˼3˽3˽3˽3ɽ3É»3É»3Ê»3Ë»3Ë»3ʺ3ʹ3ʹ3ʹ3˹3˹3˸3ʸ3ʸ3ʹ3ʹ3ɹ3ɹ3ɹ3ɹ3ʺ3˺3˺3˹3˹3̹3̺3̺3Ì»3ʼ3ʼ3ʼ3˼3̼3Ì»3̺3˺3˺3˽3˾3̾3̾3̾3ÌÃ3ÌÇ3ÌÇ3ÎÇ3ÎÈ3ÎÈ3ÎÉ3ÐÌ3ÒÏ3ÒÐ3ÓÐ3ÓÐ3ÓÑ3ÔÒ3ÖÒ3ØÒ3ØÐ3ØÐ3ØÐ3ÙÎ3ÙÎ3ÙÎ3ÙÎ3ØÎ3ÖÐ3ÖÐ3ÖÐ3ÔË3ÓÅ3ÓÃ3ÓÁ3Ò¿3Ñ¿3Ò¾3Ñ»3й3Ϲ3Ϲ3Ï»3Ï»3Ï»3Ï»3Ï»3й3к3к3Ϲ3Í·3Í·3Í·3Ï·3Ï·3Ï·3Ͷ3Ͷ3Ͷ3ζ3ζ3δ3ʳ3ij3À°3¾ª3¹£3¹Ÿ3¹˜3À˜3Ú˜3ö©CÃC&áC=DW4DrkDr˜Dr˜D[˜D4ÝH4Íú3ÌÀ3ɨ3ɨ3ɨ3ȱ3ȳ3ȳ3ȳ3DZ3Ʊ3Æ°3Å°3ű3ű3ů3ı3ı3ű3ű3ı3Ä°3Ä°3Ä°3Ƴ3Ƴ3Ƴ3Æ°3Æ°3Æ°3Ʊ3Ʊ3Ʊ3Ư3Ư3Ư3DZ3DZ3DZ3DZ3Æ°3Æ°3Æ°3È°3ȱ3ȱ3ű3ų3ų3Ç´3Ç´3Ç´3ų3ų3ų3ų3Ų3IJ3IJ3IJ3IJ3ij3ó3Á³3¿²3¿²3¿²3¿³3¿³3¾´3»´3»´3»¶3º¶3¹¶3µµ3µµ3µµ3µµ3´µ3´µ3±µ3¯±3¯±3¯±3¯±3¯°3¬°3¬°3¬°3¬±3®³3®³3¯³3¯³3¯³3³µ3¶¶3¹·3»·3½¹3Àº3ÄÀ3ÈÂ3ÊÂ3ËÂ3ËÃ3ÎÆ3ÓÈ3ÓÈ3ÓÈ3ÓÈ3ÓÈ3ÓÈ3ÓÈ3ÕÉ3ÖÉ3ÖÉ3ÖÉ3ÖÉ3ÖÉ3ÖÉ3ÖÉ3ÕÉ3ÕÇ3ÕÇ3×Ç3×É3×É3ÔÉ3ÔÉ3ÔÉ3ÖÉ3ÖÉ3ÖÈ3ÕÆ3ÔÆ3ÔÆ3ÔÈ3ÔÈ3ÔÈ3ÔÆ3ÓÆ3ÓÆ3ÓÇ3ÓÇ3ÓÇ3ÓÅ3ÒÅ3ÒÅ3ÒÅ3ÓÅ3ÓÅ3ÓÅ3ÑÄ3ÑÄ3ÑÄ3ÑÄ3ÑÄ3ÑÃ3ÑÃ3ÑÃ3ÑÃ3ÑÃ3ÑÃ3ÐÀ3ÐÀ3ÐÀ3ÐÀ3ÐÁ3ÐÁ3ÏÁ3ÏÁ3ÏÂ3ÏÂ3ÏÂ3ÏÂ3ÍÁ3ÍÁ3ÍÁ3ÎÃ3ÏÃ3ÏÃ3ÎÂ3ÎÂ3ÏÂ3ÐÂ3ÒÂ3ÒÂ3Ò¿3п3п3ÐÀ3ÐÁ3ÐÁ3ÑÁ3ÑÁ3ÑÁ3ÒÂ3ÒÃ3ÒÃ3ÑÃ3ÒÄ3ÒÄ3ÒÄ3ÒÉ3ÒÊ3ÒÌ3ÒÎ3ÒÑ3ÒÒ3ÓÒ3ÓÒ3ÓÒ3ÓÒ3ÓÒ3ÕÓ3Ö×3Ö×3××3×Ø3ØØ3ÚØ3ÚØ3ÚØ3ÙÖ3ÙÔ3ÙÔ3ÛÔ3ÞÔ3ÞÔ3ÞÒ3ÝÒ3ÝÒ3ÜÒ3Ü×3Û×3Ú×3ÙÓ3ÙÎ3ØÍ3ØË3ØÉ3×Ã3ÓÀ3Ó¿3Ó¿3Ó¿3Ó¾3Ó¾3Ò½3Ò½3Ò½3ѽ3Ò½3Ò»3Òº3Òº3Óº3Óº3Óº3Óº3Ó»3Ó¼3Ó¼3Ò¼3ϼ3ȹ3ð3½©3º¥3º¢3ºœ3Áœ3Ôœ3í£C¹CÖC1ùCI%D]WD]‡D]‡DS‡D€4Ö@4Êò3ʼ3Ê®3Ì®3Ì®3Ì´3̵3͵3̶3̶3̶3̶3̶3̶3̸3̸3̸3É·3ɶ3ɶ3̶3̶3̶3É´3É´3É´3Ë´3Ì´3Ì´3Ì´3É´3É´3ɵ3͵3͵3Ͷ3Í·3Í·3͸3͹3͹3ι3͹3͸3η3η3Í·3Í·3Í·3Í·3Í \ No newline at end of file diff -Naur wfdb-10.1.6/checkpkg/expected/mfilt.hea wfdb-10.2.0/checkpkg/expected/mfilt.hea --- wfdb-10.1.6/checkpkg/expected/mfilt.hea Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/mfilt.hea Mon Sep 10 15:01:43 2001 @@ -0,0 +1,3 @@ +mfilt 2 360 1800 +mfilt.dat 212 200 11 1024 945 25203 0 MLII +mfilt.dat 212 200 11 1024 967 -18115 0 V5 diff -Naur wfdb-10.1.6/checkpkg/expected/pschart.ps wfdb-10.2.0/checkpkg/expected/pschart.ps --- wfdb-10.1.6/checkpkg/expected/pschart.ps Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/pschart.ps Wed Sep 12 14:32:20 2001 @@ -0,0 +1,153 @@ +%!PS-Adobe-1.0 +%%Creator: pschart +%%Title: Chart Recording +%%Pages: (atend) +%%DocumentFonts: Times-Roman Times-Italic Courier Symbol +%%BoundingBox: 47 27 516 743 +%%EndComments +%%EndProlog +%%Page: 1 1 +matrix defaultmatrix setmatrix newpath clippath +pathbbox newpath pop pop translate + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % If this message appears in your printout, you may be using a buggy version % + % of Adobe TranScript. Try using pschart with the -u option as a workaround. % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +save 100 dict begin /pschart exch def +/dpi 300 def +/lw 0 def +/lwmm 0 def +/tm matrix currentmatrix def +/gm matrix currentmatrix def +/mm {72 mul 25.4 div}def +/I {/Times-Italic findfont exch scalefont setfont}def +/R {/Times-Roman findfont exch scalefont setfont}def +/C {/Courier findfont exch scalefont setfont}def +/grid { newpath 0 setlinecap + /dy1 exch dpi 25.4 div mul lw sub def /dy2 dy1 lw add 5 mul def + /dx1 exch dpi 25.4 div mul lw sub def /dx2 dx1 lw add 5 mul def + /y1 exch def /x1 exch def /y0 exch def /x0 exch def + dpi 100 idiv setlinewidth x0 y0 moveto x1 y0 lineto x1 y1 lineto x0 y1 lineto + closepath stroke lw setlinewidth [lw dx1] 0 setdash + y0 dy2 add dy2 y1 {newpath dup x0 exch moveto x1 exch lineto stroke}for + [lw dy1] 0 setdash + x0 dx2 add dx2 x1 {newpath dup y0 moveto y1 lineto stroke }for + [] 0 setdash +}bind def +/Grid { newpath 0 setlinecap + /dy1 exch dpi 25.4 div mul lw sub def /dy2 dy1 lw add 5 mul def + /dx1 exch dpi 25.4 div mul lw sub def /dx2 dx1 lw add 5 mul def + /y1 exch def /x1 exch def /y0 exch def /x0 exch def + dpi 100 idiv setlinewidth x0 y0 moveto x1 y0 lineto x1 y1 lineto x0 y1 lineto + closepath stroke lw setlinewidth + y0 dy2 add dy2 y1 {newpath dup x0 exch moveto x1 exch lineto stroke}for + x0 dx2 add dx2 x1 {newpath dup y0 moveto y1 lineto stroke }for +}bind def +/prpn { mm exch mm exch moveto 10 R /pn exch def /str 10 string def + pn str cvs stringwidth exch -.5 mul exch rmoveto + (- ) stringwidth exch neg exch rmoveto + (- ) show + pn str cvs show + ( -) show } def +/prco { mm exch mm exch moveto + 6 R (Copyright ) show + /Symbol findfont 6 scalefont setfont (\323) show + 6 R show } def +/newpage {/dpi exch def tm setmatrix newpath [] 0 setdash + 1 setlinecap /lw lwmm mm def mark } def +/ss {72 dpi div dup scale /gm matrix currentmatrix def lw setlinewidth} def +/t {tm setmatrix show gm setmatrix}def +/b {tm setmatrix dup stringwidth exch neg exch rmoveto currentpoint 3 -1 roll + show moveto gm setmatrix}def +/m {newpath moveto}def +/N {rlineto currentpoint stroke moveto}bind def +/z {{counttomark 2 ge{79 sub rlineto}{126 exch sub}ifelse}forall + currentpoint stroke moveto}bind def +/ay 0 def +/Ay {/ay exch def}def +/ya 0 def +/yb 0 def +/yc 0 def +/yd 0 def +/sb {/yd exch def /yc exch def /yb exch def /ya exch def}def +/Sb {/yb exch def /ya exch def /yc yb def /yd yb def}def +/mb { dup ya newpath moveto dup yb lineto dup yc moveto yd lineto +stroke}bind def +/a {ya yb ne {dup mb}if ay m t}bind def +/A {ya yb ne {dup mb}if ay m (\267) t}bind def +/endpschart {cleartomark showpage pschart end restore}def +300 newpage +0 setgray +1 104.31 259.61 prpn +ss +862 2440 1601 2912 0.5 0.5 grid +12 R +862 2924 m +851 2660 m +(0:10)b +1612 2660 m +(0:15)t +10 I +851 2782 m +(MLII)b +1612 2782 m +(MLII)t +862 2790 m +(~O~O}N~O}O~Q~N}O~O}O~O~O}O~N}O~O~P}O~O}O~N}O~O~P}O~O}N~O~P}O~P}N~O~O}O~O}O~O~O}O~N}O~O}N~O~N}O~P}O~N~O}M~P}P~P~N}N~P}O~P}O~O~N}O~P}O~Q~P}N~P}P~O~P}O~P}O~O~P}O~O}P~N}P~O~O}O~O}O~O~O}P~O}N~O~O}P~O}O~N}N~O~O}P~O}N~N~P}O~P}N~O~O}O~O}O~O~O}N~P}O~O}O~O~O}O) z +(~O}O~O~N}O~O}O~O~P}N~N}O~P}O~P~M}O~P}P~O~O}N~N}P~P~O}O~N}N~O~O}P~O}O~N}P~O~P}N~O}O~O~P}O~O}N~O~O}P~O}O~O~O}O~P}P~O}O~O~P}P~O}O~O~O}P~O}P~O~N}O~O}O~O}O~O~N}O~O}P~O~N}N~P}P~Q~N}N~M}N~N~O}N~N}O~N}P~N~P}O~O}O~O~P}O~N}O~N~P}O~N}O~N}O~P~P}O~N}N~P~N}O~M}M~M) z +(~N}N~N}N~S~W}X~Y}^~^}]~W~R}I~=}7~:~D}M~Q}Q~Q~N}O~N}Q~O}N~O~N}O~P}O~O~O}N~P}O~O~O}N~P}O~P~O}O~O}N~O}P~O~O}O~O}O~O~O}O~N}O~P~O}O~O}O~N}O~P~O}O~O}N~O~P}O~O}O~N~O}P~O}O~N~O}O~O}P~O}O~O~O}O~O}O~O~N}O~P}O~N~O}N~O}P~O~O}N~O}P~N}O~P~N}O~O}P~P~O}P~O}P~P~P}O~O) z +(}O~O}O~Q~O}N~O}P~O~O}O~O}N~P~P}N~P}N~N~P}O~O}O~O}N~P~P}N~O}O~N~O}O~O}O~O~N}P~O}O~O}N~O~O}O~O}O~O~N}P~O}P~N~N}P~O}N~P~O}N~N}P~O}P~N~O}N~O}P~O~O}N~O}O~O~Q}N~O}N~P}O~O~P}N~N}O~P~O}O~N}O~O~P}O~O}N~O~P}O~P}N~O}O~O~O}P~N}O~O~O}P~O}P~N~P}P~P}O~O}O~N~Q}O~O}P) z +(~O~N}P~O}O~N~O}O~O}P~O~N}O~O}P~P}P~M~L}N~O}N~O~N}O~N}O~O~P}N~N}O~O~O}P~O}N~N}P~O~O}O~O}O~O~O}O~O}N~N~N}L~O}N~O}N~O~M}L~N}Q~R~V}V~W}Y~]~]}\\~V}P~F~=}7~=}F~N}P~R~O}P~O}O~P~O}N~N}P~P~N}O~O}N~Q}N~P~N}N~P}P~O~O}N~N}P~P~O}O~N}N~P~P}O~N}N~O}P~P~N}P~O}N~O~P}O) z +(~O}N~P~N}P~O}N~O}O~P~O}O~N}N~O~P}P~P}N~O~M}O~P}P~O~N}O~O}P~O}O~O~N}O~O}O~N~O}O~O}P~O~O}O~N}P~O}P~N~P}N~P}P~P~O}O~O}P~O~P}O~O}P~O~O}P~O}N~O}N~Q~O}N~O}N~P~P}O~O}O~O~O}O~O}N~N~N}P~P}N~O}O~O~O}O~P}N~N~O}O~P}O~N~P}N~O}O~P}O~N~N}O~P}O~O~N}N~P}O~O~O}O~N}O~P) z +(~P}N~O}N~P}P~N~P}N~N}P~O~O}P~N}N~P~O}P~M}O~N}P~O~P}O~N}O~O~Q}O~N}N~P~O}P~P}O~P~P}N~P}O~O}O~O~P}O~Q}N~O~N}P~O}N~P~N}O~O}O~N}O~O~P}P~P}N~N~M}N~O}P~O~N}M~N}O~O~O}O~N}O~O}O~O~O}O~N}P~O~O}P~N}N~O~P}O~O}N~N~N}M~N}M~L}M~P~S}V~V}V~\\~_}]~X}R~I~@}:~?}D~I}N~P~Q) z +(}P~P}O~O~N}P~P}N~O~O}N~Q}O~O~O}O~N}O~O}O~O~O}O~O}O~P~O}N~O}P~O~O}O~N}O~O}N~P~O}N~O}O~O~P}N~O}O~O~O}O~P}O~N~P}O~O}O~O}N~O~P}O~O}N~O~P}O~O}O~N~O}P~O}P~N}N~O~O}O~P}N~N~N}P~O}O~O~O}N~P}O~O~O}O~O}O~O}P~O~P}O~P}P~O~O}O~P}O~Q~P}O~N}O~O}O~P~O}N~N}O~Q~O}O~O}O) z +(~N~P}O~O}O~N~O}O~O}P~M}O~O~P}O~O}O~N~O}P~P}O~N~O}N~P}O~O~N}N~O}O~O}O~O~O}O~P}O~N~O}O~O}P~O~O}N~O}O~O}O~O~O}O~N}O~P~O}O~N}P~O~P}N~O}O~P~O}O~O}N~O}O~O~P}N~O}O~O~P}O~O}O~N~O}P~P}O~O}O~P~O}P~P}N~O~P}Q~O}O~N~O}O~O}O~O~N}O~N}O~P}P~O~O}N~M}O~O~M}N~O}O~O~O}N) z +(~O}P~N}P~N~O}N~O}P~P~N}N~O}O~P~P}N~N}O~O~P}O~N}N~M}M~O~N}M~M}P~T~W}W~X}\\~]~]}X~Q}I~@}8~<~E}K~M}P~P~Q}O~P}N~O~O}P~P}O~O~N}N~P}O~O}O~O~M}P~P}O~N~N}O~O}P~O~N}P~N}P~O~O}O~O}O~O}P~O~O}N~N}P~O~Q}N~N}N~P~O}O~O}O~N}O~P~O}O~O}N~O~O}P~O}O~O~N}P~O}P~O~N}O~O}O~O) z +(}N~O~O}P~N}N~O~N}O~O}O~O~O}N~O}Q~O}O~O~O}P~P}O~P~O}O~P}P~O~P}N~O}P~P~O}O~O}O~O}P~P~N}O~O}O~O~P}O~N}N~P~O}P~N}N~O}O~P~O}O~N}N~P~P}O~O}N~N~O}P~O}O~N~O}O~P}O~O}N~N~O}P~P}O~N~O}P~O}O~P~N}N~O}O~P}O~N~N}P~O}O~O~N}P~O}O~O~O}O~N}P~O~O}O~O}O~O}O~P~O}N~O}P~O~O) z +(}N~O}O~O~P}O~O}O~O~Q}P~P}N~O}O~P~P}O~P}O~O~O}P~O}N~O~N}O~P}O~N}N~O~Q}O~P}L~M~O}N~O}O~N~N}O~N}P~O~P}O~N}O~O}P~N~O}N~O}O~O~P}N~N}P~O~P}N~N}O~O}N~M~M}N~M}M~Q~T}W~X}X~^~_}]~V}P~C~;}8~>}G~N}Q~R~O}O~O}O~N~O}P~N}P~O~N}O~P}O~O}N~O~O}P~O}O~N~O}O~P}O~O~N}O~O}P) z +(~O~O}O~N}O~O}P~O~N}P~O}O~P~O}N~O}O~O~O}O~O}N~O}P~P~O}N~N}O~P~O}P~N}O~O~P}O~O}O~N~P}O~O}O~O}M~P~N}Q~N}N~O~O}P~P}N~O~N}P~P}O~O~O}P~O}Q~P}O~O~O}P~O}O~P~N}O~O}O~P~O}O~N}O~P}O~O~O}N~O}O~Q~O}N~N}P~O~O}N~O}N~O~P}O~P}N~N}O~P~O}O~N}O~O~O}P~N}P~N~O}O~P}O~N}N~P) z +(~O}O~O}N~N~P}O~P}N~P~M}P~P}O~O~N}O~O}P~O}O~O~O}O~O}O~O~N}O~N}P~P~O}N~N}P~P}O~O~O}N~P}O~Q~O}P~O}P~O~P}N~O}O~O~P}P~O}O~N}P~O~P}N~N}O~O~O}O~O}N~N~O}P~Q}P~N~N}M~O}N~O}M~N~O}O~N}O~P~N}O~O}P~N~N}O~O}O~O}O~P~N}O~P}O~O~N}L~M}N~N~M}M~O}S~V~W}Z~\\}^~]}W~P~D}<~8) z +(}?~I~O}Q~P}P~O~O}O~P}N~O}O~P~O}O~N}N~O~P}O~O}N~O~O}O~P}O~N~O}O~P}O~O}O~N~P}P~O}O~O~N}O~P}O~N~O}O~O) z +851 2546 m +(V5)b +1612 2546 m +(V5)t +862 2557 m +(~O~N}N~O}P~P~N}P~N}O~O~O}O~O}O~O~N}Q~N}O~N}O~P~P}M~O}O~N~P}O~O}O~N~O}P~O}N~N~N}O~P}O~N}N~N~O}P~N}N~O~N}N~P}P~N~O}O~O}P~P}O~O~O}O~Q}Q~O~O}P~O}Q~P~P}O~N}P~O~P}O~O}O~O}O~P~N}O~O}O~O~Q}N~N}P~O~O}O~O}O~N}O~O~P}O~O}N~O~P}O~O}N~O~O}O~O}O~O~O}N~P}O~O}O~N~P}P) z +(~O}N~O~N}O~O}P~O~O}N~P}O~O}O~O~O}N~P}O~O~O}N~O}P~O~O}O~O}N~O~P}O~O}N~P}O~O~O}O~O}O~O~P}N~O}N~O~P}P~N}O~O~N}P~O}O~O}O~O~P}O~O}O~O~O}P~P}O~N~O}O~P}O~N}P~N~P}O~P}O~O~M}O~P}O~N~O}N~O}P~O~N}O~N}O~P}O~O~N}O~O}O~O~P}N~O}N~P~P}N~O}O~O}O~P~N}O~O}N~O~N}M~N}M~N) z +(~O}S~V}V~V~V}V~V}V~V}O~F~=}>~D}N~P~P}O~P}O~N~O}O~O}P~N}O~N~P}O~P}N~O~O}N~Q}O~N~O}N~P}O~O~O}O~O}O~O}Q~N~N}O~O}O~O~O}P~N}O~O~P}O~N}N~P}P~O~O}N~O}O~O~O}O~O}N~N~O}P~O}N~O~O}O~P}M~O}O~O~N}P~N}M~O~O}O~O}O~O~M}O~O}O~P~N}O~O}O~O}O~O~P}O~Q}P~P~O}O~P}Q~Q~O}O~N) z +(}P~P}O~P~N}P~O}P~P~N}O~N}P~O~O}O~O}N~P~O}O~O}N~O}O~P~P}N~O}O~N~P}O~O}O~N~O}O~P}N~O}N~O~P}O~O}N~N~O}O~Q}O~N~O}N~P}O~O~O}N~O}P~O}N~O~N}P~O}P~O~N}N~P}O~O~O}O~N}P~O}O~O~N}P~O}O~P~N}O~N}O~P~O}O~O}O~O~O}P~N}O~O}O~O~O}P~N}N~P~O}O~O}O~O~O}P~O}N~O}O~O~Q}O~O}O) z +(~O~N}P~P}O~P~N}O~O}O~O~O}O~O}O~O}O~M~O}O~O}O~O~O}N~O}O~O~O}O~N}O~P~O}O~N}O~N}P~Q~N}N~O}N~P~P}N~N}M~N~N}O~N}N~N}L~O~R}R~T}U~W~V}T~U}V~U~T}O~G};~=~F}P~Q}P~O}O~N~O}P~O}N~O~O}O~O}P~N~O}N~O}P~P}O~N~O}N~P}O~O~P}N~O}O~P~O}O~N}O~P~O}O~O}N~N}Q~P~N}N~O}N~P~P}O) z +(~O}N~N~P}P~N}N~O}O~P~N}P~O}M~O~O}P~N}O~O~N}O~P}N~N~N}O~O}P~N}O~N~O}N~O}O~O~N}O~P}O~O~N}O~O}P~P}O~O~O}P~Q}P~O~Q}N~P}P~P~P}O~O}O~O~P}P~M}P~N}Q~O~O}N~O}O~P~P}N~N}O~N~P}O~P}O~M~O}O~P}O~N}O~O~O}P~O}N~N~O}P~O}O~O~O}N~P}O~O}N~O~N}Q~O}N~N~O}O~O}P~O~N}O~O}P~O) z +(~N}P~N}O~O}O~O~O}O~O}O~P~O}O~O}N~P~O}N~O}N~O}P~O~P}N~P}O~N~P}O~N}N~P~O}O~O}O~N~O}P~P}O~O}O~O~O}P~O}N~P~O}P~O}O~O~N}O~O}P~O}N~N~O}P~O}M~O~O}N~Q}O~O~N}M~P}O~P~N}O~N}O~P}O~O~O}N~O}P~O~N}O~N}O~P~P}N~N}N~M~O}O~M}N~R}T~U~T}S~S}T~V~U}Q~H}A~@~D}O~R}O~P}N~O~P) z +(}Q~N}O~O~N}O~Q}N~O~O}O~O}P~N~N}N~P}P~P}O~N~O}O~O}P~O~N}N~P}O~Q~N}O~N}O~O}O~O~O}O~N}P~P~N}N~O}O~P~P}N~O}O~O~N}P~P}N~O}N~P~N}O~O}O~N~P}O~N}O~O~M}P~P}N~N}N~N~O}P~O}N~N~O}O~O}O~O~N}N~Q}O~O~M}P~P}P~P}P~O~O}P~O}P~P~O}P~P}P~P~N}N~O}O~P}O~O~P}N~O}O~P~N}N~P}N) z +(~P~P}N~O}N~P~O}P~N}N~O}O~O~O}P~N}O~O~O}O~O}O~O~O}N~P}N~O~O}N~O}Q~N}O~N~O}P~O}N~O~O}O~O}P~N~N}P~O}O~P}N~O~N}O~P}P~O~N}O~N}P~P~N}O~O}N~P~O}O~O}N~O}Q~O~O}M~O}O~O~P}P~N}O~N~P}P~N}O~N}P~P~P}O~N}O~O~P}P~N}O~O~O}O~P}O~O~O}N~P}O~N}O~N~O}P~O}O~O~L}P~O}O~O~O}N) z +(~O}P~O}O~O~O}O~P}P~N~O}N~O}O~P~O}N~P}N~P~N}N~N}N~M}O~N~P}R~U}U~U~T}S~T}V~U~P}I~>}?~D}M~R~R}P~O}O~O~P}P~O}N~O~O}P~O}N~P~M}P~O}Q~N}O~M~P}O~P}P~N~N}O~P}O~O~N}P~N}P~O~P}N~N}O~P}O~O~O}N~O}P~P~O}N~N}O~N~Q}N~O}O~O}O~P~N}O~N}O~O~P}O~N}N~O~O}P~O}N~N~O}O~O}O~O) z +(}M~N~P}P~N}N~N~O}P~N}O~O~N}O~P}P~O}O~P~P}P~P}O~P~P}N~Q}P~P~O}N~P}P~P~O}O~O}O~O}O~P~N}P~N}P~O~O}O~N}O~P~O}O~O}M~O}P~O~O}O~N}O~P~O}O~O}O~O~O}O~O}N~O~N}Q~O}O~N}O~O~O}P~O}N~N~O}P~P}O~M~P}N~P}P~N}O~N~O}P~P}N~P~M}P~O}O~P~N}N~P}O~P~N}P~N}N~Q}O~O~N}O~O}O~P~O) z +(}O~N}O~O~P}O~N}P~N~P}P~N}O~O}O~P~P}O~N}O~P~O}P~O}N~P~N}Q~N}O~P}M~O~P}N~O}O~N~O}P~O}N~O~O}N~O}O~P~N}O~O}P~O}O~N~O}O~O}P~O~N}O~N}O~P~O}O~N}M~N}N~N~M}P~R}W~W~V}V~V}W~W~T}N~D};~>~G}R~O}N~N}O~P~N}O~O}N~O~P}O~N}O~O~O}O~P}O~N}O~O~P}O~O}O~N~P}O~O}O~O~N}O~P}O) z +(~O~O}N~O}P~P}N~O~N}O~O}P~O~O}N~O}O~P~N}O~O}O~O}O~O~N}N~P}O~O~O}N~N}O~O~P}N~M}P~N~P}O~N}O~N}O~O~O}O~N}N~O~P}P~O}O~O~O}P~P}P~O~P}P~P}P~P}O~O~P}Q~O}O~N~P}O~O}O~O~O}O~O}O~P}O~N~O}O~P}O~O~N}O~O}O~P~N}O~O}N~P~O}O~O}N~O}P~O~O}O~N}O~O~P}O~O}N~N~P}O~O}O~N}O~P) z +(~O}O~O}N~O~P}O~O}N~O~O}O~P}N~O~O}O~O}P~N}O~O~O}P~O}P~N~N}O~P}O~O~N}P~O}P~N}O~O~O}N~P}P~O~N}N~P}O~P~O}O~O}N~P~P}O~N}O~P}P~O~O}N~O}O~P~Q}N~O}N~P~N}P~N}O~N~O}O~P}N~O}N~N~P}P~N}O~N~N}P~P}O~N~O}O~P}O~O}O~O~N}P~O}M~M~N}M~N}O~O~Q}U~V}V~V~U}V~U}U~P}E~;~>}H~Q) z +(}Q~P~O}O~N}O~P~O}O~N}P~N}P~O~O}N~O}O~P~O}O~N}N~O~P}P~O}O~N~N}P~P}O~O}N~O~P}O~O}O~O~O}O~P}O~N~O}N~P) z +10 R +12 R +2651 Ay +969 A +1095 A +1217 A +1339 A +1460 A +1578 A +12 R +346 3066 m +(T)t +9.6 R +(E)t +(S)t +(T)t +12 R +7.5 R +2117 147 m +(12.5 mm/sec, 5 mm/mV)b +endpschart +%%Trailer +%%Pages: 1 diff -Naur wfdb-10.1.6/checkpkg/expected/psfd.ps wfdb-10.2.0/checkpkg/expected/psfd.ps --- wfdb-10.1.6/checkpkg/expected/psfd.ps Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/psfd.ps Wed Sep 12 14:33:45 2001 @@ -0,0 +1,197 @@ +%!PS-Adobe-1.0 +%%Creator: psfd +%%Title: Full Disclosure +%%Pages: (atend) +%%DocumentFonts: Times-Roman Times-Italic Helvetica Symbol +%%BoundingBox: 47 27 516 743 +%%EndComments +%%EndProlog +%%Page: 1 1 +matrix defaultmatrix setmatrix newpath clippath +pathbbox newpath pop pop translate + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % If this message appears in your printout, you may be using a buggy version % + % of Adobe TranScript. Try using psfd with the -u option as a workaround. % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +save 100 dict begin /psfd exch def +/dpi 300 def +/lw 0 def +/tm matrix currentmatrix def +/gm matrix currentmatrix def +/mm {72 mul 25.4 div}def +/I {/Times-Italic findfont exch scalefont setfont}def +/R {/Times-Roman findfont exch scalefont setfont}def +/S {/Helvetica findfont exch scalefont setfont}def +/grid { /nt exch def /y1 exch def /x1 exch def /y0 exch def /x0 exch def + /dx x1 x0 sub nt div def + /dy1 dpi 12.7 div def /dy2 dpi 25.4 div def + x0 y0 moveto x1 y0 lineto x0 y1 moveto x1 y1 lineto stroke + 0 1 nt cvi { dup 5 mod 0 eq {/dy dy1 def} {/dy dy2 def} ifelse + dx mul x0 add /xx exch def newpath + xx y0 moveto xx y0 dy sub lineto + xx y1 moveto xx y1 dy add lineto stroke }for +}bind def +/prpn { mm exch mm exch moveto 10 R /pn exch def /str 10 string def + pn str cvs stringwidth exch -.5 mul exch rmoveto + (- ) stringwidth exch neg exch rmoveto + (- ) show + pn str cvs show + ( -) show } def +/prco { mm exch mm exch moveto + 6 R (Copyright ) show + /Symbol findfont 6 scalefont setfont (\323) show + 6 R show } def +/newpage {/dpi exch def tm setmatrix newpath [] 0 setdash 0 setgray + 1 setlinecap dpi 600 idiv /lw exch def mark } def +/ss {72 dpi div dup scale /gm matrix currentmatrix def lw setlinewidth} def +/t {tm setmatrix show gm setmatrix}def +/b {tm setmatrix dup stringwidth exch neg exch rmoveto currentpoint 3 -1 roll + show moveto gm setmatrix}def +/m {newpath moveto}def +/N {rlineto currentpoint stroke moveto}bind def +/z {{33 sub dup 1 and exch 2 idiv 23 sub rlineto}forall + currentpoint stroke moveto}bind def +/ay 0 def +/Ay {/ay exch def}def +/ya 0 def +/yb 0 def +/yc 0 def +/yd 0 def +/ye 0 def +/sb {/yd exch def /yc exch def /yb exch def /ya exch def + /ye dpi 50.8 div lw sub def}def +/Sb {/yb exch def /ya exch def /yc yb def /yd yb def + /ye dpi 50.8 div lw sub def}def +/mb { dup ya newpath moveto dup yb lineto dup yc moveto yd lineto +[lw ye] 0 setdash stroke [] 0 setdash}bind def +/a {ya yb ne {dup mb}if ay m t}bind def +/A {ya yb ne {dup mb}if ay m (\267) t}bind def +/endpsfd {cleartomark showpage psfd end restore}def +300 newpage +1 104.31 259.61 prpn +ss +8 R +328 2866 m +(0:00)b +2135 2866 m +(1:00)t +6 I +328 2915 m +(MLII)b +2135 2915 m +(MLII)t +346 2929 m +(OONPPL`BPPPPPPPPRPPPNPPPPRPNPN^HJPPPPPPPRPPPPPPPPPRPNNP^BPPPPPPPQPPPPPPPPRPNNN\\JLPPPPPPRRNPPPPPPRPPNPN^BPPPPPPPPRPPPPPPPRPPNPN^BOPPPPPPRPRNPPPPPRPPNPN^FLPPPPPPPRRPPPPNPPN`@PPPPPPPPRPPPPPPPPPPOPPRPNNPR^@PPPPPPNPRRPPPPPPPPRPNNNb@PPPPPPPPRRNPPPPPPRPNPN) z +(^FLPPPQNPRRPPPNPPPRRNNPN`@RPPPPPPPRPPNPPPRPPNPN`@PPPPPPPPRRNPPPPPPRPPMPPZJLPPPPPPPRPPPPNPPPRPPPNPLd>RPPPPPNRRPPNPPPPPRPPNPPZDPPPPPPPPQPPPPPPPPRPNPNVTFPPPPPPNRRPPPPPPPPRPNPN`BNPPPPPPRRPPNPPPPRPPNPN_@RNRPPPPPRPNPPPPPRPPNPNf:PPPPPPPPRPPPPPPPRPPNPP\\BPPP) z +(PPPPRPRNPPPOPRPPNPN\\JLNRNPRNPRRPPNPPPPPRPPNPNZLLNPPPRNPRRNPPPPPPRPPNPLb@PPOPPPNRRPPPPPPPRPNPNR\\BPPPPPPPRRPPNPPPRPPNPN^NFNRNRPNRRPPNPPPPRPPMPPZDPPPPPPPRPPPPPPPRPPNPN^DNPPPPPNRRPPPPNRPPRPNNPR\\BPPPPPPPPRPOPNPPPRPPNPN`@PPPPPPPPRPPPPPPPPRPPNNNb@PPPPPPP) z +(PRPPPPPPPPRPPNNP^DMPPPPPPPRPPPPPPPRPPPNPZPDPRPPPNRRPPPNRNRPRNPNP\\DPPPPPPPRPPPPNPPQPRNNPPZFPNRPPNPRRPPNPPPRPPNPN\\JLNPPRPNPRRPPPNRPNRRPNNPLf>PPPPPPOPRPPPPNPPPRRNPNN\\JLPPPPPPPPRPPNPPPPRPPNPN`@PRNRPNPRRPPPNPPPRRPKPNb@PPPPPPNRRPPPPPPPPPRPNPNb@NPPPPPPRP) z +(PPPPPPPRPPNNN`BPPPPPPPRPPONPPPRPPNPNTZBPPPPPPPRPPPPPPPPRPPNPN`BNPPPPPPPRRNPPPPPPRPPPNPRZCNPPRNPPRRPPPPNPPPRPRNNPLd>RPPPPPPPPRPPNPPPPRPPNPP\\DPPPPPNPRRPPPOPPPRPNPLb>RPPPPPPRPPPPPPPPRPPNPLb@PPPPPPPPRPPPPPPPPRPPNNXLLPPPOPPPPRNPPPPPPRPNPNZJLPPPPPPPRRPNPP) z +(PPPRPPNPPXNJPPPPPPPRPPPPPPPPRPONPN\\HLPPPPPPPRPPPPPPPPRPPNPLb@PPPPPPPPRPPPPPPPPRPNNPXNJPPPPPNRQPPPPPPPPRPNPLfPPPRPPPPRPPNPOPPPRRNNPPf8RPPPPPNRPPPPPPPPR) z +(PPLPN`BPPPPPNPRRPPNPPPRPPPNN\\LJPPPPONRRPPPPPPPPRPLPN^FNPPPPPPPRPPNPPPRPPPNPP^BPPPPPNPRRPPNPPPPRPNPOTTFRPPPPNPRRPPPPPPPPRPPNPNb@NPRPPPPPPRPPPPNRPPRPNNPVVDPPPPPPPRPOPPPPPPPRPNNP\\DPPPPPPNRRPPPNPPPRRNNPP^BPPPPPNRRPPPPPPPPRPNPN\\HLOPPPPPRRPNPPPPPRPPNPN`) z +(BPPPPPPNRRPPNPPPPRPPNPNXNJPPPPPPPRPPPPPPPPQPPNPN`@PPPPPPPPRRPN) z +328 2825 m +(V5)b +2135 2825 m +(V5)t +346 2839 m +(OOPNPPVJPPPPNPNRRPPPPNPPPRPNPPZDRPPPPNNPTRPPPNPPPPRPNPTRJPPPNPNRQRPNPPPPPRPNPN^DPPPPPNNTPRNPPPPPPRNPPNXHPRPNPNPRRPPPPPPPPPPPPRRLOPPPPNPRRPPPPPPPPRPNPP\\DPPPPNPNRRRPPPNPPPRVHPPPPNPNRRPPPPPPPPPPONPRPPNPTPLPPPPPNPPRRPPNRNPRPPPPPPXFPPPPPNPRRPPPPPPPPPPPPN) z +(\\DPPPPONPRRPPPPPPPPPRNPPXHPPPPNNPTPPPNPPPPRPNPPVHRPPPNPNRRPPPPPPPPPRPMPP\\DPPPPPNNRTPPPPNPPPPRPPNPPZFPPPPNPNRRRNPPPPPPPPPPNVNLPPPPPNPRQPNPPPPPPPPPPPXJNPPPPPNPRRPPPPPPPPPPPPN^DNPRNPNPRRPPPPPPPPRPNPPYFPPPPNPNRRPPPPPPPPPPNPRXFPPPPNPNRRPPPPPPPPRNPPTPLPP) z +(PPNPPRRPPNPROPPPPPPN^DNPPPPPNPRRPPPPPPPPPRPNPN^DPPPPNPNPTPPPPNRNPRPPNPPXHPPOPPNNTRPPNPRPPPRNPPVNLPPPPNNRRRPPNPPRPPPPPN`DLPPPNPNRRPPPPPPPRPPMPTNNPPPNPNPRRPPPNPPRPPNPPXHPPPPPNPPTPPPPPPPPPRPNPXNJPPPPNNPTRPMPPPPPPRPNPP\\DPPPPPNNRRRNPPPPPPPRPNPPVHPPPPPPNP) z +(RRPNPPPPPPRPNPPZDQPPPPNPRRPPPPPPPPRPPNP^DNPPPNPNRRRNPPPPPPRPNPTPLPPPPNNRRPPPPPPPOPPPPNTPLPPPPPNPRRPNPPPPPRPNPN\\FPPPPPPNPTPPPPPPPPPPRNPPP\\DNPPPPNOPRRPPPNPPRNRPPPN\\DPPPPPPNPRRPPPNPPPRPPNPPXHPPPPPNPPRRPNPPPPRPPOPNZFRPPPNPNRRRPPNPPPPPRPPPN`@PPPPNPPRRP) z +(PNPPRPPPPPPNZFPPPPPNPRRPMPPPPPPRNPNVNLPPPPNNRRPPPPPPPPPRPNPPZFPPPPPNPPRRPPPPPPPPPPPPNZLIPPPPPNPPTPPPPPPPPPPRNPPPZFPPPPPNPPRPPPPPPPPPRNPPTNNPPPPNPPRRPPPOPPPRPPNPZFPPPPPNPRRPPPPPPPPRPNPP\\DPPPPNPNRRPPPPPPPPPRNPNZFPPPPONPPRPPPPPPPPPPPPNXHPPPPPNPPTPPPPPP) z +(PPPRPNPN\\FPPPNPPNPTPPPPPPPPPPQNPN\\DPPPPPNPPRRPPPPPPPPPPPNPXHPPPPNPNRRPPPPPPPPPPPPNZFPPRPNPNRQPPPPPPPPRPNPP^@PPRNPNPRRRNPPPPPPRPNPZJLPPPPNNRRPPPPPPPPPPPPNTPLOPPPPNPPRRPPNPPPPRPPPPPVHRPPPNPNRRRNPPPPPPPRPPNPZFPPPPPNNRTPPPNOPPPRPPPNTXDPPPPPNPRPPPPPPPPP) z +(PPPNPXHPPPPPNPRRPPNPPRPPPPPN\\DPPRPNONRRPPPPPPPPRPNPN^DPPPNPNPRRPPPPPPPPRNPNVPJPPPPPNPRPPPPPPPPPPPPOVJNPPRPNPNTRPPPPNRPPPPPPPN^DPPPNPPNPTPPPPPPPPPRPPNPZJLPPPPNNRRPQNPPPPPPRPNPNZFRPPPNPNRRPPPPPPPPPPPPRRLPPPPNNRTPPPPPPPPRPNPP\\DPOPPNNPRRRNPPPRPPPPPPPXF) z +(PPPPPNPRRPPPNPRPPPPPNPXHPPPPNPNPRRPPPPPPNQPPNPTRJPRPPNPNRRPPP) z +4.5 S +2873 Ay +347 2853 m +(\(N)t +352 A +376 A +400 A +423 A +446 A +470 A +494 A +(A) 513 a +543 A +567 A +591 A +615 A +637 A +662 A +688 A +712 A +736 A +761 A +784 A +808 A +831 A +855 A +881 A +905 A +928 A +952 A +975 A +998 A +1022 A +1046 A +1070 A +1095 A +1119 A +1142 A +1166 A +1189 A +1214 A +1239 A +1263 A +1287 A +1312 A +1335 A +1358 A +1383 A +1408 A +1434 A +1458 A +1481 A +1505 A +1528 A +1552 A +1577 A +1601 A +1626 A +1650 A +1673 A +1696 A +1720 A +1745 A +1769 A +1794 A +1818 A +1840 A +1864 A +1887 A +1910 A +1936 A +1961 A +1985 A +2008 A +2031 A +2055 A +2079 A +2103 A +10 R +346 3066 m +(T)t +8 R +(E)t +(S)t +(T)t +10 R +346 2793 2117 2971 60 grid +6 R +2117 147 m +(2.5 mm/sec, 1 mm/mV)b +endpsfd +%%Trailer +%%Pages: 1 diff -Naur wfdb-10.1.6/checkpkg/expected/rdann.out wfdb-10.2.0/checkpkg/expected/rdann.out --- wfdb-10.1.6/checkpkg/expected/rdann.out Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/rdann.out Mon Sep 10 00:07:51 2001 @@ -0,0 +1,75 @@ + 0:00.050 18 + 0 0 0 (N + 0:00.213 77 N 0 0 0 + 0:01.027 370 N 0 0 0 + 0:01.838 662 N 0 0 0 + 0:02.627 946 N 0 0 0 + 0:03.419 1231 N 0 0 0 + 0:04.208 1515 N 0 0 0 + 0:05.025 1809 N 0 0 0 + 0:05.677 2044 A 0 0 0 + 0:06.672 2402 N 0 0 0 + 0:07.516 2706 N 0 0 0 + 0:08.327 2998 N 0 0 0 + 0:09.116 3282 N 0 0 0 + 0:09.888 3560 N 0 0 0 + 0:10.727 3862 N 0 0 0 + 0:11.583 4170 N 0 0 0 + 0:12.405 4466 N 0 0 0 + 0:13.233 4764 N 0 0 0 + 0:14.055 5060 N 0 0 0 + 0:14.850 5346 N 0 0 0 + 0:15.647 5633 N 0 0 0 + 0:16.438 5918 N 0 0 0 + 0:17.261 6214 N 0 0 0 + 0:18.130 6527 N 0 0 0 + 0:18.952 6823 N 0 0 0 + 0:19.738 7106 N 0 0 0 + 0:20.530 7391 N 0 0 0 + 0:21.305 7670 N 0 0 0 + 0:22.091 7953 N 0 0 0 + 0:22.902 8245 N 0 0 0 + 0:23.719 8539 N 0 0 0 + 0:24.547 8837 N 0 0 0 + 0:25.391 9141 N 0 0 0 + 0:26.197 9431 N 0 0 0 + 0:26.972 9710 N 0 0 0 + 0:27.772 9998 N 0 0 0 + 0:28.561 10282 N 0 0 0 + 0:29.419 10591 N 0 0 0 + 0:30.261 10894 N 0 0 0 + 0:31.086 11191 N 0 0 0 + 0:31.888 11480 N 0 0 0 + 0:32.725 11781 N 0 0 0 + 0:33.516 12066 N 0 0 0 + 0:34.305 12350 N 0 0 0 + 0:35.125 12645 N 0 0 0 + 0:35.969 12949 N 0 0 0 + 0:36.850 13266 N 0 0 0 + 0:37.672 13562 N 0 0 0 + 0:38.450 13842 N 0 0 0 + 0:39.252 14131 N 0 0 0 + 0:40.063 14423 N 0 0 0 + 0:40.861 14710 N 0 0 0 + 0:41.697 15011 N 0 0 0 + 0:42.527 15310 N 0 0 0 + 0:43.352 15607 N 0 0 0 + 0:44.163 15899 N 0 0 0 + 0:44.952 16183 N 0 0 0 + 0:45.733 16464 N 0 0 0 + 0:46.541 16755 N 0 0 0 + 0:47.383 17058 N 0 0 0 + 0:48.216 17358 N 0 0 0 + 0:49.047 17657 N 0 0 0 + 0:49.852 17947 N 0 0 0 + 0:50.630 18227 N 0 0 0 + 0:51.427 18514 N 0 0 0 + 0:52.208 18795 N 0 0 0 + 0:53.000 19080 N 0 0 0 + 0:53.855 19388 N 0 0 0 + 0:54.702 19693 N 0 0 0 + 0:55.525 19989 N 0 0 0 + 0:56.308 20271 N 0 0 0 + 0:57.094 20554 N 0 0 0 + 0:57.880 20837 N 0 0 0 + 0:58.697 21131 N 0 0 0 + 0:59.508 21423 N 0 0 0 diff -Naur wfdb-10.1.6/checkpkg/expected/rdsamp.out wfdb-10.2.0/checkpkg/expected/rdsamp.out --- wfdb-10.1.6/checkpkg/expected/rdsamp.out Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/rdsamp.out Sun Sep 9 23:42:45 2001 @@ -0,0 +1,362 @@ +time MLII V5 +(sec) (mV) (mV) + 10.000 -0.390 -0.275 + 10.003 -0.395 -0.265 + 10.006 -0.390 -0.285 + 10.008 -0.405 -0.300 + 10.011 -0.405 -0.305 + 10.014 -0.400 -0.285 + 10.017 -0.375 -0.270 + 10.019 -0.380 -0.280 + 10.022 -0.390 -0.275 + 10.025 -0.395 -0.290 + 10.028 -0.395 -0.280 + 10.031 -0.390 -0.290 + 10.033 -0.390 -0.280 + 10.036 -0.385 -0.280 + 10.039 -0.405 -0.285 + 10.042 -0.400 -0.285 + 10.044 -0.405 -0.285 + 10.047 -0.395 -0.295 + 10.050 -0.390 -0.275 + 10.053 -0.395 -0.280 + 10.056 -0.390 -0.290 + 10.058 -0.400 -0.295 + 10.061 -0.405 -0.295 + 10.064 -0.405 -0.285 + 10.067 -0.390 -0.275 + 10.069 -0.390 -0.295 + 10.072 -0.395 -0.305 + 10.075 -0.400 -0.305 + 10.078 -0.400 -0.320 + 10.081 -0.395 -0.305 + 10.083 -0.380 -0.295 + 10.086 -0.370 -0.300 + 10.089 -0.380 -0.300 + 10.092 -0.385 -0.320 + 10.094 -0.395 -0.320 + 10.097 -0.390 -0.310 + 10.100 -0.380 -0.305 + 10.103 -0.380 -0.315 + 10.106 -0.385 -0.330 + 10.108 -0.390 -0.345 + 10.111 -0.390 -0.355 + 10.114 -0.400 -0.340 + 10.117 -0.400 -0.335 + 10.119 -0.405 -0.350 + 10.122 -0.415 -0.370 + 10.125 -0.420 -0.380 + 10.128 -0.430 -0.380 + 10.131 -0.430 -0.375 + 10.133 -0.425 -0.385 + 10.136 -0.420 -0.405 + 10.139 -0.430 -0.405 + 10.142 -0.445 -0.420 + 10.144 -0.465 -0.430 + 10.147 -0.455 -0.415 + 10.150 -0.440 -0.410 + 10.153 -0.425 -0.415 + 10.156 -0.435 -0.425 + 10.158 -0.450 -0.425 + 10.161 -0.440 -0.425 + 10.164 -0.445 -0.405 + 10.167 -0.425 -0.385 + 10.169 -0.425 -0.390 + 10.172 -0.425 -0.385 + 10.175 -0.430 -0.385 + 10.178 -0.430 -0.380 + 10.181 -0.415 -0.350 + 10.183 -0.415 -0.320 + 10.186 -0.385 -0.315 + 10.189 -0.375 -0.315 + 10.192 -0.385 -0.305 + 10.194 -0.370 -0.305 + 10.197 -0.360 -0.270 + 10.200 -0.350 -0.250 + 10.203 -0.335 -0.235 + 10.206 -0.335 -0.235 + 10.208 -0.325 -0.245 + 10.211 -0.320 -0.240 + 10.214 -0.325 -0.235 + 10.217 -0.305 -0.215 + 10.219 -0.295 -0.220 + 10.222 -0.300 -0.220 + 10.225 -0.290 -0.225 + 10.228 -0.295 -0.220 + 10.231 -0.290 -0.215 + 10.233 -0.290 -0.205 + 10.236 -0.285 -0.215 + 10.239 -0.285 -0.215 + 10.242 -0.285 -0.225 + 10.244 -0.290 -0.225 + 10.247 -0.290 -0.215 + 10.250 -0.285 -0.190 + 10.253 -0.270 -0.195 + 10.256 -0.270 -0.210 + 10.258 -0.280 -0.205 + 10.261 -0.290 -0.205 + 10.264 -0.285 -0.200 + 10.267 -0.275 -0.205 + 10.269 -0.275 -0.205 + 10.272 -0.275 -0.205 + 10.275 -0.290 -0.215 + 10.278 -0.305 -0.210 + 10.281 -0.305 -0.210 + 10.283 -0.300 -0.200 + 10.286 -0.280 -0.200 + 10.289 -0.290 -0.205 + 10.292 -0.305 -0.220 + 10.294 -0.315 -0.210 + 10.297 -0.310 -0.200 + 10.300 -0.295 -0.200 + 10.303 -0.290 -0.195 + 10.306 -0.300 -0.215 + 10.308 -0.305 -0.215 + 10.311 -0.305 -0.220 + 10.314 -0.310 -0.210 + 10.317 -0.300 -0.210 + 10.319 -0.295 -0.210 + 10.322 -0.305 -0.215 + 10.325 -0.305 -0.225 + 10.328 -0.315 -0.230 + 10.331 -0.310 -0.215 + 10.333 -0.310 -0.215 + 10.336 -0.295 -0.215 + 10.339 -0.300 -0.220 + 10.342 -0.305 -0.230 + 10.344 -0.310 -0.220 + 10.347 -0.305 -0.205 + 10.350 -0.305 -0.200 + 10.353 -0.295 -0.220 + 10.356 -0.300 -0.225 + 10.358 -0.315 -0.240 + 10.361 -0.325 -0.230 + 10.364 -0.320 -0.230 + 10.367 -0.320 -0.215 + 10.369 -0.315 -0.225 + 10.372 -0.310 -0.220 + 10.375 -0.325 -0.235 + 10.378 -0.335 -0.225 + 10.381 -0.330 -0.225 + 10.383 -0.320 -0.210 + 10.386 -0.320 -0.225 + 10.389 -0.310 -0.225 + 10.392 -0.330 -0.225 + 10.394 -0.330 -0.230 + 10.397 -0.325 -0.220 + 10.400 -0.310 -0.210 + 10.403 -0.305 -0.220 + 10.406 -0.305 -0.215 + 10.408 -0.320 -0.230 + 10.411 -0.330 -0.235 + 10.414 -0.325 -0.215 + 10.417 -0.300 -0.210 + 10.419 -0.310 -0.215 + 10.422 -0.305 -0.225 + 10.425 -0.315 -0.225 + 10.428 -0.330 -0.235 + 10.431 -0.330 -0.230 + 10.433 -0.330 -0.215 + 10.436 -0.320 -0.225 + 10.439 -0.325 -0.220 + 10.442 -0.325 -0.230 + 10.444 -0.335 -0.225 + 10.447 -0.325 -0.220 + 10.450 -0.315 -0.210 + 10.453 -0.310 -0.215 + 10.456 -0.315 -0.220 + 10.458 -0.320 -0.220 + 10.461 -0.325 -0.225 + 10.464 -0.315 -0.210 + 10.467 -0.310 -0.205 + 10.469 -0.305 -0.215 + 10.472 -0.310 -0.225 + 10.475 -0.315 -0.230 + 10.478 -0.320 -0.240 + 10.481 -0.315 -0.225 + 10.483 -0.310 -0.205 + 10.486 -0.295 -0.215 + 10.489 -0.295 -0.215 + 10.492 -0.305 -0.220 + 10.494 -0.310 -0.230 + 10.497 -0.300 -0.225 + 10.500 -0.280 -0.215 + 10.503 -0.275 -0.225 + 10.506 -0.265 -0.220 + 10.508 -0.275 -0.220 + 10.511 -0.275 -0.225 + 10.514 -0.260 -0.195 + 10.517 -0.240 -0.195 + 10.519 -0.240 -0.205 + 10.522 -0.235 -0.200 + 10.525 -0.240 -0.200 + 10.528 -0.235 -0.195 + 10.531 -0.225 -0.190 + 10.533 -0.215 -0.170 + 10.536 -0.205 -0.170 + 10.539 -0.205 -0.180 + 10.542 -0.210 -0.180 + 10.544 -0.215 -0.185 + 10.547 -0.220 -0.170 + 10.550 -0.220 -0.165 + 10.553 -0.215 -0.180 + 10.556 -0.220 -0.175 + 10.558 -0.220 -0.185 + 10.561 -0.230 -0.175 + 10.564 -0.230 -0.170 + 10.567 -0.240 -0.150 + 10.569 -0.210 -0.150 + 10.572 -0.220 -0.155 + 10.575 -0.230 -0.180 + 10.578 -0.255 -0.180 + 10.581 -0.235 -0.170 + 10.583 -0.210 -0.175 + 10.586 -0.190 -0.180 + 10.589 -0.205 -0.190 + 10.592 -0.225 -0.195 + 10.594 -0.260 -0.200 + 10.597 -0.275 -0.190 + 10.600 -0.280 -0.185 + 10.603 -0.285 -0.200 + 10.606 -0.305 -0.195 + 10.608 -0.320 -0.215 + 10.611 -0.315 -0.210 + 10.614 -0.335 -0.200 + 10.617 -0.325 -0.195 + 10.619 -0.335 -0.205 + 10.622 -0.320 -0.220 + 10.625 -0.325 -0.215 + 10.628 -0.320 -0.225 + 10.631 -0.325 -0.225 + 10.633 -0.325 -0.210 + 10.636 -0.310 -0.205 + 10.639 -0.305 -0.210 + 10.642 -0.320 -0.225 + 10.644 -0.320 -0.230 + 10.647 -0.330 -0.215 + 10.650 -0.320 -0.200 + 10.653 -0.320 -0.215 + 10.656 -0.330 -0.220 + 10.658 -0.330 -0.225 + 10.661 -0.360 -0.210 + 10.664 -0.355 -0.210 + 10.667 -0.330 -0.200 + 10.669 -0.325 -0.210 + 10.672 -0.325 -0.215 + 10.675 -0.335 -0.225 + 10.678 -0.350 -0.235 + 10.681 -0.340 -0.240 + 10.683 -0.345 -0.255 + 10.686 -0.355 -0.290 + 10.689 -0.385 -0.310 + 10.692 -0.425 -0.335 + 10.694 -0.450 -0.360 + 10.697 -0.470 -0.350 + 10.700 -0.485 -0.285 + 10.703 -0.510 -0.175 + 10.706 -0.515 -0.050 + 10.708 -0.455 0.075 + 10.711 -0.325 0.190 + 10.714 -0.165 0.315 + 10.717 0.010 0.430 + 10.719 0.250 0.545 + 10.722 0.515 0.655 + 10.725 0.740 0.655 + 10.728 0.885 0.505 + 10.731 0.935 0.210 + 10.733 0.835 -0.090 + 10.736 0.525 -0.275 + 10.739 0.120 -0.290 + 10.742 -0.230 -0.265 + 10.744 -0.425 -0.250 + 10.747 -0.455 -0.255 + 10.750 -0.420 -0.230 + 10.753 -0.380 -0.230 + 10.756 -0.360 -0.250 + 10.758 -0.365 -0.255 + 10.761 -0.375 -0.255 + 10.764 -0.380 -0.250 + 10.767 -0.355 -0.235 + 10.769 -0.355 -0.250 + 10.772 -0.370 -0.250 + 10.775 -0.375 -0.265 + 10.778 -0.385 -0.255 + 10.781 -0.380 -0.250 + 10.783 -0.365 -0.240 + 10.786 -0.370 -0.245 + 10.789 -0.370 -0.255 + 10.792 -0.365 -0.255 + 10.794 -0.380 -0.265 + 10.797 -0.370 -0.240 + 10.800 -0.375 -0.240 + 10.803 -0.365 -0.255 + 10.806 -0.370 -0.255 + 10.808 -0.380 -0.265 + 10.811 -0.375 -0.260 + 10.814 -0.365 -0.250 + 10.817 -0.360 -0.255 + 10.819 -0.360 -0.255 + 10.822 -0.355 -0.255 + 10.825 -0.355 -0.255 + 10.828 -0.370 -0.250 + 10.831 -0.365 -0.245 + 10.833 -0.355 -0.225 + 10.836 -0.350 -0.230 + 10.839 -0.350 -0.245 + 10.842 -0.350 -0.255 + 10.844 -0.360 -0.260 + 10.847 -0.360 -0.245 + 10.850 -0.360 -0.245 + 10.853 -0.350 -0.245 + 10.856 -0.355 -0.240 + 10.858 -0.365 -0.250 + 10.861 -0.370 -0.245 + 10.864 -0.360 -0.245 + 10.867 -0.350 -0.240 + 10.869 -0.355 -0.240 + 10.872 -0.350 -0.250 + 10.875 -0.355 -0.265 + 10.878 -0.370 -0.255 + 10.881 -0.375 -0.240 + 10.883 -0.360 -0.240 + 10.886 -0.350 -0.240 + 10.889 -0.345 -0.255 + 10.892 -0.350 -0.260 + 10.894 -0.370 -0.260 + 10.897 -0.370 -0.255 + 10.900 -0.355 -0.255 + 10.903 -0.350 -0.250 + 10.906 -0.345 -0.260 + 10.908 -0.360 -0.275 + 10.911 -0.370 -0.280 + 10.914 -0.365 -0.280 + 10.917 -0.360 -0.270 + 10.919 -0.350 -0.265 + 10.922 -0.355 -0.285 + 10.925 -0.365 -0.290 + 10.928 -0.365 -0.280 + 10.931 -0.370 -0.280 + 10.933 -0.365 -0.275 + 10.936 -0.350 -0.295 + 10.939 -0.350 -0.305 + 10.942 -0.360 -0.310 + 10.944 -0.360 -0.310 + 10.947 -0.355 -0.320 + 10.950 -0.345 -0.305 + 10.953 -0.350 -0.320 + 10.956 -0.345 -0.345 + 10.958 -0.355 -0.350 + 10.961 -0.370 -0.355 + 10.964 -0.365 -0.355 + 10.967 -0.355 -0.350 + 10.969 -0.360 -0.350 + 10.972 -0.365 -0.360 + 10.975 -0.365 -0.380 + 10.978 -0.380 -0.385 + 10.981 -0.385 -0.380 + 10.983 -0.375 -0.380 + 10.986 -0.370 -0.375 + 10.989 -0.375 -0.385 + 10.992 -0.385 -0.395 + 10.994 -0.395 -0.380 + 10.997 -0.375 -0.390 diff -Naur wfdb-10.1.6/checkpkg/expected/rxr.out wfdb-10.2.0/checkpkg/expected/rxr.out --- wfdb-10.1.6/checkpkg/expected/rxr.out Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/rxr.out Sun Sep 9 23:11:23 2001 @@ -0,0 +1,39 @@ +rxr: (warning) nonstandard comparison selected +VE run-by-run comparison results for record 100s +Reference annotator: atr + Test annotator: qrs + + Algorithm Run Length + 0 1 2 3 4 5 >5 + ____________________________________ + 0 | 0 0 0 0 0 0 + 1 | 0 0 0 0 0 0 0 + 2 | 0 0 0 0 0 0 0 + 3 | 0 0 0 0 0 0 0 + 4 | 0 0 0 0 0 0 0 + 5 | 0 0 0 0 0 0 0 + >5 | 0 0 0 0 0 0 0 + + (Run Sensitivity Summary Matrix) + + + Algorithm Run Length + 0 1 2 3 4 5 >5 + ____________________________________ + 0 | 0 0 0 0 0 0 + 1 | 0 0 0 0 0 0 0 + 2 | 0 0 0 0 0 0 0 + 3 | 0 0 0 0 0 0 0 + 4 | 0 0 0 0 0 0 0 + 5 | 0 0 0 0 0 0 0 + >5 | 0 0 0 0 0 0 0 + + (Run Positive Predictivity Summary Matrix) + + Couplet sensitivity: - (0/0) + Couplet positive predictivity: - (0/0) + Short run sensitivity: - (0/0) +Short run positive predictivity: - (0/0) + Long run sensitivity: - (0/0) + Long run positive predictivity: - (0/0) + diff -Naur wfdb-10.1.6/checkpkg/expected/sampfreq.out wfdb-10.2.0/checkpkg/expected/sampfreq.out --- wfdb-10.1.6/checkpkg/expected/sampfreq.out Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/sampfreq.out Mon Sep 10 00:26:31 2001 @@ -0,0 +1 @@ +360 diff -Naur wfdb-10.1.6/checkpkg/expected/sigamp.out wfdb-10.2.0/checkpkg/expected/sigamp.out --- wfdb-10.1.6/checkpkg/expected/sigamp.out Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/sigamp.out Sun Sep 9 23:16:50 2001 @@ -0,0 +1 @@ + 294.221 195.279 diff -Naur wfdb-10.1.6/checkpkg/expected/snip.atr wfdb-10.2.0/checkpkg/expected/snip.atr --- wfdb-10.1.6/checkpkg/expected/snip.atr Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/snip.atr Mon Sep 10 14:23:26 2001 @@ -0,0 +1 @@ +4(*( \ No newline at end of file diff -Naur wfdb-10.1.6/checkpkg/expected/snip.dat wfdb-10.2.0/checkpkg/expected/snip.dat --- wfdb-10.1.6/checkpkg/expected/snip.dat Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/snip.dat Mon Sep 10 14:23:26 2001 @@ -0,0 +1,2 @@ +²3ɱ3˲3ǯ3į3ð3ǵ3Ê´3Ȳ3ɱ3Ʊ3Ȳ3Ʋ3ȳ3ȯ3Ç°3ǯ3DZ3Ų3ɱ3Ȳ3Æ°3ů3ů3Dz3ɲ3ű3ð3ð3À±3ô3Ŷ3Ä´3ij3À±3À²3´3ô3Á³3¾²3»²3¹°3¼°3½¯3º­3¶¬3´ª3´ª3µ«3³¬3¯ª3¯§3¬£3ª¥3­¨3®«3­©3«¦3«¨3«§3¯«3³«3²«3³ª3³ª3´­3º­3À³3Áµ3Á³3ö3ø3ʺ3ν3ѽ3Ñ¿3ÏÀ3п3ÑÃ3ÕÅ3ÔÄ3ÔÆ3ÓÅ3ÔÆ3ÕÆ3×Ç3ÕÇ3ÕÇ3ÓÆ3ÓÆ3ÕÇ3ÚÊ3ÙÊ3ÖÈ3×Æ3×Ç3ØÉ3×É3×É3×Æ3ÕÃ3ÖÃ3ÖÄ3ØÈ3ØÆ3×Ã3ÔÁ3ÖÂ3ØÅ3ØÆ3ÙÄ3ÕÃ3ÕÃ3ÔÂ3ÖÄ3ÖÅ3ÖÃ3ÕÃ3ÓÁ3ÒÂ3ÕÂ3ÕÅ3ÕÄ3ÔÃ3ÒÂ3ÔÃ3×Ã3ØÅ3ÔÄ3ÓÁ3п3ÒÀ3ÒÀ3ÕÁ3ÓÂ3Ô¿3ѽ3Ó¾3ÓÀ3ÖÀ3ÓÂ3Ó¾3Ó¾3Ò¿3ÔÂ3ÖÃ3ÔÃ3ÕÀ3Ò¾3Ñ¿3ÕÄ3ÖÂ3ÕÃ3ÓÁ3Ó¾3Ѿ3Ò¾3ÕÀ3Ó¿3Ô¿3Ò½3Ó¿3ÔÁ3ÖÂ3ÕÁ3ÔÀ3Ô¿3ÓÁ3ÖÂ3×Ã3ÕÂ3ÓÁ3ÒÀ3ÐÁ3ÓÂ3×Å3ÕÅ3ÕÃ3ÔÂ3ÒÄ3ÓÈ3ÕÉ3ÓË3ÔÉ3ÔÉ3ÓÌ3ÙÐ3ÙÐ3×Ñ3ØÐ3ØÑ3ÙÓ3ÚÕ3Þ×3Þ×3ÜÖ3ÜÕ3ÛÔ3ÞÔ3ßÕ3ÜÔ3ÝÔ3ÛÒ3ÝÒ3ÞÐ3âÖ3âÔ3áÒ3ÜÍ3ÜÑ3ÞÖ3ÝÚ3Ü×3ÚÓ3ÙÌ3ØÉ3ÚÈ3ÛÇ3ØÃ3ÙÀ3ÕÁ3Ö½3Ø¿3Ù½3×À3Ô¿3ÕÀ3Ó¿3Ó¿3ÖÂ3×Ã3ÖÀ3ÓÀ3Ò¾3ÕÀ3ØÀ3Õ¾3Ô¾3Ó¸3Ö¹3Ö¾3Ø¿3Ö¿3Õ½3Óº3Ѽ3л3͹3Ƴ3«3½¦3¸¢3ºŸ3Çš3Ý™3ö¥C¿C&ßC?DV2DmgDƒ”Dƒ±De»D*§4îi4É4ÆÒ3Ë«3Î¥3ͬ3Ò´3Ò¸3η3͵3Í´3ι3ѹ3ζ3ε3˳3Í´3η3ж3϶3Í·3Í´3˶3е3з3Ͷ3Í´3˵3Ì·3θ3͸3͹3͹3Ͷ3η3Ϲ3Óº3Òº3Ϻ3͸3̸3ϸ3Ϻ3Ϲ3з3ζ3ϸ3Ϻ3й3к3ι3˶3͵3и3к3л3ͺ3̶3̶3͹3ͺ3λ3̸3ɶ3È·3ȸ3ʺ3˹3Ç·3Æ·3ȶ3È·3ɺ3ź3ø3¸3¹3À»3ú3À»3»¹3º¶3¹·3¹¹3º¸3º·3¸·3´´3³³3´µ3´¶3µµ3³³3±±3´µ3²³3´´3³¶3´³3µ³3¶´3½¶3Á¸3º3Ľ3¾3ÇÁ3ÌÅ3ÓÆ3ÓÆ3ÔÇ3ÒÆ3ÕÈ3×È3ÙÌ3ÛÍ3ÙÊ3ÚÉ3ÜÌ3ÞÎ3âÏ3àÎ3ÝÌ3ÛË3ÝÏ3ÞÑ3àÏ3ßÐ3ßÎ3ÜË3ÝÎ3ÞÎ3ßÎ3ÞÎ3ÜÍ3ÛË3ÚÌ3ÞÐ3áÎ3àÏ3ßÎ3ÝÊ3ÜË3ÞÊ3ßË3ßË3ÝÉ3ÛÇ3ÚÉ3ÚË3ÝÊ3ÚÊ3ÜÈ3ÙÇ3ÙÇ3ÜÈ3ÜÇ3ÚÈ3×Ç3ÕÄ3ÕÆ3ÖÇ3ÚÊ3ÛÈ3ØÅ3×Æ3ÓÆ3×Å3ØÆ3×Ç3×Ã3ÕÁ3ÕÂ3ØÂ3ØÆ3ÖÅ3ÖÂ3ÒÀ3ÕÁ3ÔÂ3×Ä3×Ä3ÔÁ3ÑÀ3ÓÁ3ÔÀ3ÖÆ3ÕÄ3ÔÄ3ÒÁ3ÔÂ3ÔÄ3ÕÄ3ÖÆ3ÑÂ3Ó¿3ÔÁ3ÔÃ3ØÃ3ÔÃ3ÕÁ3Ñ¿3ÒÀ3ÓÂ3ÖÄ3ÕÅ3ÔÁ3ÓÀ3ÕÃ3ÖÄ3ØÆ3ÖÅ3ÔÅ3ÓÂ3ÓÅ3ÓÅ3ÖÇ3×Å3ÖÅ3ÒÂ3ÓÄ3ÕÇ3ÖÈ3ÖÉ3ÓÈ3ÓË3ÓÏ3×Ò3ØÐ3ÖÐ3ÔÐ3ÖÏ3ÕÔ3ÚÔ3ÚÕ3ÛØ3ÛØ3ÛÖ3Ø×3ÛÙ3Þ×3ÞÖ3áÕ3àÓ3àÓ3ÝØ3ßØ3àÖ3àÓ3ßÔ3ÞÙ3ßÜ3àÝ3Ý×3ÙÏ3ØË3×É3ÙÈ3ÙÇ3×Ä3ØÂ3Ô¿3ÓÀ3Ô¿3ÖÂ3Õ¿3Ô¾3Ò¼3н3Õ¾3Õ¿3ÓÀ3Ѽ3л3μ3Ò¾3×½3Ó¾3Ò¼3м3ν3Ò½3Õ¾3Ò½3Í»3ȵ3ñ3Áª3¿¨3¾¦3º¦3µ¡3­ 3­š3µ’3À3Ñ“3çžCµCÎC)èC? DT9DiiDz”D{¬D^²D’4ßU4¿4ÃÇ3Ê©3̦3Ì©3γ3Ê´3ɶ3̶3̶3ɸ3ʸ3ʶ3ʳ3Ë·3̸3Ê·3Ê·3ȵ3dz3˸3Í·3̹3ʵ3É´3ǵ3ʹ3˹3˸3Ì·3É´3ʶ3˹3ͺ3̹3Í·3É´3Ë·3̹3͹3Í·3̳3˲3ȵ3̹3з3θ3˹3Ê·3È·3˹3λ3Í»3Ì·3ʸ3ȵ3ɹ3̸3Ê·3Ç·3ȶ3ȸ3ɹ3ȸ3É·3ʳ3Å´3÷3Ź3Ƚ3ĸ3¸3³3Á´3Áµ3¸3Á¸3¾·3ºµ3º·3¹¹3½¸3»º3¹¸3¶¶3µ¶3³·3´¶3²´3²²3¯³3®´3±¶3±¶3±·3°·3®²3¯µ3³¶3µ¹3··3·¸3·¶3¹º3¿¼3Å¿3ÅÀ3ËÁ3È¿3ÉÂ3ÏÅ3ÒÇ3ÕÆ3ÖÆ3ÓÉ3ÕÊ3ÖË3ÙÌ3ÚÌ3ÕÉ3ÙÉ3ÖÇ3ÜÌ3ÜÌ3ÚË3ÙÊ3ØÈ3ØÉ3ÚÍ3ÞÍ3ÜÏ3ÙÍ3ÙÌ3ÖÍ3ØÍ3ÙÌ3ÛË3ÚÈ3ÕÅ3ÖÆ3ÖÉ3ØÈ3×È3ÕÈ3ÕÇ3ÓÇ3ÕÈ3ÙÊ3×Ç3ÔÄ3ÐÂ3ÐÄ3ÔÆ3ÖÈ3ÕÄ3ÕÆ3ÔÂ3ÑÄ3ÓÅ3ÔÆ3ÓÇ3ÒÅ3Ñ¿3ÏÁ3ÓÂ3ÔÃ3ÒÄ3ÏÁ3̾3ÌÀ3ÎÀ3ÒÁ3ÐÀ3Ï¿3ν3ξ3п3ÑÂ3ÏÁ3ÐÁ3ͽ3ÍÀ3ÎÂ3ÎÁ3ÎÂ3ÌÀ3̽3ο3Ï¿3ÒÁ3ÑÂ3ÐÀ3о3ÎÀ3ÐÀ3ÐÂ3̾3;3Ê»3ʼ3;3ÍÀ3ÐÁ3Ͻ3н3о3ÏÂ3ÑÂ3ÑÁ3Ͼ3ÊÀ3ÌÁ3ÎÄ3ÎÇ3ÍÈ3ÎË3ÊÌ3ÊË3ÎÌ3ÒÍ3ÑÌ3ÐÎ3ÑÍ3ÑÐ3ÒÒ3Ó×3ÕÖ3ÑÓ3ÓÑ3ÔÓ3×Ó3×Ò3×Ó3×Ð3ÖÐ3ÓÒ3ÖÑ3ÙÎ3ØÎ3ÕÍ3ÑÑ3ÒÔ3Ó×3ÓÕ3ÏÐ3ÎË3ÌÈ3ËÈ3ÒÊ3ÑÊ3ÐÆ3ÎÀ3Ƚ3ʼ3˾3;3˽3ɺ3ȸ3ƺ3ɺ3Ë»3ʺ3ʹ3È·3ȸ3ʹ3˺3ȼ3Ǹ3Ŷ3Ŷ3ȹ3Ë»3Ⱥ3Ķ3¿³3¹®3¸¨3¹¤3³ž3°”3¹3Ê’3ÞŸ3ñ·3þÍC +çCD3HDHxDN–D7ŸDŒ4ÓX4°4®Û3¸¶3»¢3¼ž3»¢3»¨3¾«3î3Á®3Á®3¿¬3½°3¾±3¯3Á®3À¯3À¬3À±3À±3²3¿±3¾±3»®3¼°3À°3®3°3À¯3¿®3¿®3Á°3²3²3Á°3¾°3À±3Á²3Ƴ3ò3î3À®3À®3¿­3À®3Á¯3À¬3¿¬3¾¬3Á­3®3Á­3¾«3¼«3½¬3Á«3ì3À®3¿®3À­3¿®3¾®3À°3¯3¿¯3¿«3¾¬3¿®3¾°3¾¯3½­3½¬3»®3½®3¼°3»®3º­3¸¬3´®3·°3¸²3¶°3´­3¯¬3«­3¬­3¯°3®­3«ª3¨¦3§¨3¨¨3ª©3ª©3¨¨3¦¦3£©3¨¨3©ª3§¨3£§3¦§3§¨3¬©3°¬3³­3´®3´¯3µ´3·µ3»¶3¼¶3¼¶3¿¸3ù3È¿3ÉÃ3ÆÂ3ÃÀ3¿3ÿ3ÆÁ3ÈÄ3ÈÃ3ÊÀ3ƾ3Ǿ3ÆÂ3ÉÂ3ÆÂ3ÅÃ3ÆÂ3ÄÀ3ÈÃ3ÊÄ3ÈÄ3ÇÃ3ÄÀ3ÆÀ3ÇÁ3ÉÁ3ÇÂ3ľ3ý3½3ÅÀ3ÅÁ3ÆÁ3Å¿3þ3½3ÃÀ3ÅÄ3ÅÄ3ÄÀ3ÄÀ3¾3ÀÀ3ÄÀ3¿¿3¿¼3¿¹3½»3¾º3»3À»3¿¸3½¸3¼»3¿¼3Á¼3¾¹3¾º3½º3¼¹3½¼3Á½3¾¼3»º3¼¹3¼¹3¾¹3¿»3¾»3¼º3º¸3¹·3½·3Àº3¿º3¾¸3¾¶3¹¸3¼º3À½3½º3½º3¾»3º¼3½¼3½¼3¼¼3¼»3ºº3»¸3¿º3À½3¿»3»º3ºº3º¹3»¼3¾½3Á¾3¾¼3¼¹3»¹3¼¾3ÀÁ3¾Á3¼Á3ºÀ3½Ä3¿Ä3ÂÈ3ÃË3ÀÈ3ÁÇ3ÀË3ÂÑ3ÆÒ3ÅÒ3ÃÏ3ÃÍ3ÂÎ3ÅÏ3ÈÎ3ÈÍ3ÇË3ÆÊ3ÅÆ3ÆÈ3ÇÉ3ÅÌ3ÄÍ3ÁÌ3ÁÉ3ÃÅ3ÅÄ3ÃÃ3½3»¹3½º3¼º3½º3¾¹3¾¶3»¶3»¸3¼·3½¹3¾·3½µ3½³3¾´3¿µ3¹3¿¶3¿³3¾²3½²3½¶3Á¸3À¶3¾´3¿³3½´3¿µ3¾¶3º´3µ¯3±§3«£3« 3ªŸ3«—3·‘3Ê•3ߦ3ó¿CÛCûC$%D;VDN„DQ£D?ªD–4Ìa4¨4£Ö3­²3µ¤3¸Ÿ3º¢3º¦3º«3½­3¿¯3¿­3¼­3¾¬3½°3¿±3¿³3½±3¿°3º¬3¼®3¼°3°3À¯3¿¯3»©3¼¬3¾®3Á¯3­3Àª3½¨3½©3¿­3Á¬3¿ª3¾­3¿ª3¾«3Á¬3À¬3­3À«3½«3¾¬3Á®3Á®3Á®3À¬3¾ª3¾¬3Á­3±3ï3À­3½ª3½¬3»¬3¿­3¾¬3¾«3½¨3½ª3¾«3¿­3¾¬3½«3¹¨3¹ª3ºª3¾«3¼¬3¸­3·«3·ª3¶«3º­3¹¯3¶¯3´«3²­3³¬3´¬3²¬3±©3¬©3ª¨3¬¬3®ª3«¦3ª¥3¦£3¤£3§£3¥£3¦£3¦¢3¢ž3£Ÿ3¤¤3¨¥3§¤3©¥3¬¥3°¨3´«3·­3·°3¹¯3¼°3»³3À·3Ä·3Ƹ3ȶ3ŵ3ǹ3ʼ3̾3;3ξ3μ3ͽ3ÏÀ3ÏÃ3ÑÁ3ÏÀ3ÐÀ3ÎÀ3ÐÁ3ÒÂ3ÑÂ3ÐÁ3̾3ÎÀ3ÐÀ3ÒÂ3ÑÀ3Ѿ3˼3˾3Í¿3Ï¿3ÏÀ3μ3ʺ3ʼ3ÍÀ3ÎÁ3Í¿3ͼ3Ì»3Í»3ͼ3ξ3ͽ3Ê»3ɸ3ȹ3μ3ξ3ͽ3Ê»3É·3ɶ3ʺ3̼3̽3˸3ȹ3ȼ3˽3ͽ3ÌÀ3Ƚ3ɹ3Ⱥ3Ë»3ͼ3ʽ3˺3Ƕ3Ǹ3ʹ3̺3Ë»3Ì·3ȸ3ʸ3ɺ3Ë»3͹3ɹ3È·3ɸ3Ê»3Ì»3˺3̹3ʸ3ȹ3̺3ͽ3̽3ʹ3Ê»3ɼ3˾3μ3λ3̺3˹3ɺ3˽3;3ξ3˾3̾3ËÃ3ÎÇ3ÑÉ3ÌÈ3ÌÇ3ÎÆ3ÎÉ3ÐÌ3ÔÏ3ÕÐ3ÒÐ3ÐÐ3ÓÑ3ÔÓ3ÙÔ3ØÒ3ÖÐ3ØÍ3ÕÍ3ÚÐ3ÙÐ3ÙÎ3ÚÊ3ÖÊ3ÖÐ3ØÒ3ÖÓ3ÓË3ÔÅ3ÒÃ3Ñ¿3ÓÁ3Ô¿3Ѿ3л3Ò¸3η3͹3Ï»3м3Ͻ3θ3͹3л3ѽ3й3Ϻ3͵3̵3Í·3Ò·3к3϶3Í´3Ë·3˶3ι3϶3δ3ʳ3ij3À°3¾ª3¹£3³Ÿ3¶˜3À‘3Ú—3ö©CÃC&áC=DW4DrkD„˜D²D[µD4ÝH4Åú3ÌÀ3Í¥3É¡3Ȩ3ȱ3É´3È´3ȳ3DZ3Å°3į3Ʊ3Ç®3Ų3ı3¯3ů3ñ3Ƴ3dz3į3ï3Ä°3Ƴ3Ç´3Ƴ3Ư3Å®3Æ°3Ʊ3dz3DZ3Æ®3¯3ï3DZ3Ȳ3ȱ3DZ3ů3î3Æ°3ʳ3ȱ3È°3ű3ó3ų3ȵ3ȵ3Ç´3ű3ų3Ų3Ƴ3Å´3IJ3°3Ä°3IJ3Å·3õ3Á³3¾°3¿°3¿²3Á´3¿µ3¾³3»±3º´3»¶3½·3¹·3´µ3µ³3³µ3µµ3¶·3´¶3±µ3®°3®±3¯¯3°¶3¯³3¬°3ª®3ª°3¬±3®µ3¯´3¯³3®¯3¯³3³µ3¶¶3¹·3»·3½º3À¹3ÄÀ3ÈÂ3ÊÂ3ËÃ3ËÂ3ÎÆ3ÓÈ3ÕÈ3ÕÊ3ÒÈ3ÓÇ3ÓÈ3ÓÇ3ÖË3ÖÊ3ÕÉ3ÖÆ3ÖÆ3ÖÉ3ÙÉ3ØÊ3ÕÉ3ÔÆ3ÕÇ3×Ç3ÙÌ3×Ì3ÔÉ3ÓÇ3ÔÉ3ÖË3×Ê3ÖÈ3ÕÆ3ÓÅ3ÒÄ3ÔÈ3ÖÈ3ÔÉ3ÔÆ3ÑÄ3ÑÃ3ÓÇ3ÕÇ3ÔÇ3ÓÅ3ÑÄ3ÑÄ3ÒÅ3ÕÈ3ÕÅ3ÓÆ3ÐÃ3ÎÃ3ÑÄ3ÑÇ3ÑÇ3ÑÂ3ÌÁ3ÎÃ3ÑÃ3ÑÅ3ÒÄ3ÐÀ3ν3ÏÀ3ÐÀ3ÐÂ3ÐÁ3ÏÂ3ξ3ÍÀ3ÏÂ3ÐÃ3ÏÃ3ÍÁ3ÍÁ3ÌÁ3ÏÃ3ÒÃ3ÎÄ3ÏÂ3ÌÂ3ÌÂ3ÐÂ3ÒÅ3ÓÄ3Ò¿3ο3ξ3ÐÀ3ÒÂ3ÑÃ3ÏÁ3о3ÒÀ3ÓÂ3ÑÃ3ÒÄ3ÒÅ3ÐÀ3ÏÂ3ÒÄ3ÓÉ3ÓÊ3ÒÌ3ÏÎ3ÐÑ3ÒÒ3ÕÓ3ÖÒ3ÓÒ3ÓÐ3ÒÒ3ÕÓ3Ø×3××3ÖØ3ÖÖ3ØÙ3ÚØ3ÜÚ3ÛØ3ÙÖ3ØÓ3ÙÓ3ÛÔ3áÔ3ßÔ3ÞÒ3ÜÎ3ÝÏ3ÜÒ3à×3ÛÛ3ÚÙ3×Ó3×Î3ÙÍ3ÚË3ØÉ3×Ã3ÓÀ3Ò¿3Ó¿3ؾ3Õ¾3Ó¿3Ò½3ϼ3ѽ3ÕÀ3Ó½3Ñ»3Ò¹3Ѻ3Ô¹3Ôº3Ó»3Ó¼3Ó¹3Òº3Ó¼3Ó¼3ϼ3ȹ3ð3½©3º¥3¸¢3¸œ3Á”3Ô“3í£C¹CÖC1ùCI%D]WDq‡Dt¤DS¥D€4Ö@4¾ò3ļ3ʧ3̧3Ì®3Í´3˵3˵3Ͷ3η3̸3˶3̵3ɶ3͸3ͺ3̹3É·3É´3É´3̶3Ì·3Í·3É´3dz3Ȳ3Ë´3ε3ε3Ì´3ɲ3Ç´3ɵ3ζ3Í·3͵3ʳ3Ê·3͸3κ3ι3͹3Ͷ3η3ͺ3Ѹ3з3Í·3͵3˵3Ì \ No newline at end of file diff -Naur wfdb-10.1.6/checkpkg/expected/snip.hea wfdb-10.2.0/checkpkg/expected/snip.hea --- wfdb-10.1.6/checkpkg/expected/snip.hea Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/snip.hea Thu Oct 4 13:48:51 2001 @@ -0,0 +1,7 @@ +snip 2 360 1800 +snip.dat 212 200 11 1024 946 25307 0 MLII +snip.dat 212 200 11 1024 969 -18062 0 V5 +# 69 M 1085 1629 x1 +# Aldomet, Inderal +#Produced by xform from record 100, beginning at 0:0 +#Produced by snip from record 100s, beginning at 10 diff -Naur wfdb-10.1.6/checkpkg/expected/sumann.out wfdb-10.2.0/checkpkg/expected/sumann.out --- wfdb-10.1.6/checkpkg/expected/sumann.out Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/sumann.out Mon Sep 10 00:23:47 2001 @@ -0,0 +1,7 @@ +N 73 +A 1 ++ 1 + +N 1 episode 1:00 + +Both signals clean 1 episode 1:00 diff -Naur wfdb-10.1.6/checkpkg/expected/sumstats.out wfdb-10.2.0/checkpkg/expected/sumstats.out --- wfdb-10.1.6/checkpkg/expected/sumstats.out Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/sumstats.out Mon Sep 10 17:48:59 2001 @@ -0,0 +1,12 @@ +Record Nn' Vn' Fn' On' Nv Vv Fv' Ov' No' Vo' Fo' Q Se Q +P V Se V +P V FPR + 200 1415 27 1 14 29 667 0 27 22 6 1 98.66 98.12 95.29 92.25 3.769 + 201 1271 0 1 0 0 198 1 0 50 0 0 96.71 100.00 100.00 100.00 0.000 + 202 1846 1 1 0 5 14 0 0 4 0 0 99.79 100.00 93.33 73.68 0.270 + 203 2035 8 1 19 59 359 4 13 9 6 0 99.40 98.72 96.25 83.29 3.385 +______________________________________________________________________________________ +Sum 6567 36 4 33 93 1238 5 40 85 12 1 +Gross 98.78 99.09 96.27 90.30 1.974 +Average 98.64 99.21 96.22 87.31 1.856 +Total QRS complexes: 8041 Total VEBs: 1286 + +Summary of results from 4 records diff -Naur wfdb-10.1.6/checkpkg/expected/tach.out wfdb-10.2.0/checkpkg/expected/tach.out --- wfdb-10.1.6/checkpkg/expected/tach.out Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/tach.out Sun Sep 9 23:15:14 2001 @@ -0,0 +1,119 @@ +73.7201 +73.7201 +73.8394 +74.3013 +75.3502 +75.957 +75.8451 +75.9444 +75.3018 +74.0083 +82.231 +81.2781 +65.9494 +63.8481 +69.2069 +72.464 +74.2828 +75.3733 +76.6856 +76.8203 +73.9244 +71.1439 +70.4472 +71.3145 +72.6898 +72.6818 +72.6138 +72.8587 +74.107 +75.3433 +75.3534 +75.4476 +75.5396 +74.2091 +72.0262 +70.0445 +70.4738 +72.6138 +74.8073 +76.1852 +75.9174 +76.5546 +77.1568 +76.6594 +75.3645 +74.1393 +73.6721 +73.1927 +72.6996 +71.8355 +71.4918 +73.1393 +75.3719 +76.773 +76.1425 +75.2406 +75.7688 +73.3557 +70.3905 +70.7065 +71.6312 +72.3512 +73.5605 +74.236 +72.9196 +72.8687 +74.883 +75.9185 +75.5004 +74.0869 +72.4074 +71.2346 +69.5067 +68.8639 +71.281 +74.3398 +76.3046 +75.8216 +74.5506 +74.1667 +74.5346 +74.6928 +73.0249 +71.9061 +72.1461 +72.4705 +72.8971 +73.5333 +74.673 +75.7532 +76.5007 +76.1639 +74.8432 +72.8795 +71.4928 +71.7267 +72.0682 +72.1886 +73.2559 +74.7685 +76.2044 +76.4477 +75.623 +76.1809 +76.5537 +76.0142 +72.9597 +70.2295 +70.5744 +71.4597 +72.5363 +74.6938 +76.4533 +76.4085 +76.3251 +75.984 +74.5561 +73.6218 +73.8734 diff -Naur wfdb-10.1.6/checkpkg/expected/udb/100z.hea wfdb-10.2.0/checkpkg/expected/udb/100z.hea --- wfdb-10.1.6/checkpkg/expected/udb/100z.hea Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/udb/100z.hea Wed Sep 12 14:40:06 2001 @@ -0,0 +1,6 @@ +udb/100z 2 360 21600 +udb/100z.dat 212 200 11 1024 995 21537 0 MLII +udb/100z.dat 212 200 11 1024 1011 -3962 0 V5 +# 69 M 1085 1629 x1 +# Aldomet, Inderal +#Produced by xform from record 100, beginning at 0:0 diff -Naur wfdb-10.1.6/checkpkg/expected/wfd.hea wfdb-10.2.0/checkpkg/expected/wfd.hea --- wfdb-10.1.6/checkpkg/expected/wfd.hea Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/wfd.hea Mon Sep 10 16:50:32 2001 @@ -0,0 +1,3 @@ +wfd/2 2 360 21600 +wfd00001 10800 +wfd00002 10800 diff -Naur wfdb-10.1.6/checkpkg/expected/wfd00001.dat wfdb-10.2.0/checkpkg/expected/wfd00001.dat --- wfdb-10.1.6/checkpkg/expected/wfd00001.dat Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/wfd00001.dat Mon Sep 10 16:50:32 2001 @@ -0,0 +1,7 @@ +ã3óã3óã3óã3óã3óã3óã3óã3óè3ðå3ðã3ïâ3ïà3ñá3òà3òÝ3óÜ3õÛ3öÞ3öá3øÝ3øÜ3õÚ3ñÜ3ðá3ïå3òá3ðÚ3ð×3îÑ3íÓ3îÏ3íÎ3êÌ3èÉ3ãÉ3åÉ3ëË3íÍ3ëË3èÉ3åÆ3çÆ3çÆ3éÆ3éÇ3çÅ3äÃ3äÇ3æÉ3çÉ3äÈ3ãÇ3âÃ3âÆ3æÄ3éÈ3çÆ3åÄ3àÁ3ÙÀ3ؽ3׸3Ó³3ͳ3į3Æ¥3ÑŸ3æŸ3ù«C +¾CÔC(òC>DWKDk|DtœD_¨D*™4ïh4Ò"4Îß3Õ·3Ü©3Û«3à¶3â¾3â¿3ܽ3Ü»3à¾3ß¿3ÞÁ3ßÂ3ÛÀ3Û½3Û¼3Þ¿3à»3á½3ݾ3Ù½3Û¾3Û¿3ݾ3ݾ3Ù»3Ú¹3ܽ3ß¿3ÞÃ3ÞÀ3ÞÀ3Ú¾3Û¼3ܽ3Þ¼3Ý»3Ú¹3ع3Ù¼3Û¾3Þ¾3Þ¾3Û¼3Ùº3Ý¿3Ø¿3Û¾3ܾ3Û½3×½3Ú¼3ܾ3Û¼3غ3Õ¹3׺3Ö»3ؾ3ÛÀ3×½3ؾ3Ö»3×¾3Û½3Û½3Ø»3Õ»3Ó¹3Ô¼3ؼ3ؽ3Õ¾3Óº3Ѻ3Ï»3н3н3н3Ϻ3̹3̹3Ë»3Ë»3Ƚ3Ǻ3Ÿ3Ÿ3ĸ3Æ·3ĸ3Á¶3Á³3Á¶3Á¸3¹3¸3¿µ3¾µ3¿·3Á·3ø3ø3Æ·3ƶ3ɹ3ʾ3Ï¿3п3ν3μ3ÑÁ3ÔÄ3ÙÄ3ÚÆ3ÚÅ3ÚÆ3ÜÇ3àÉ3ãÍ3âÎ3àÎ3àË3áÍ3ãÏ3äÒ3àÏ3âÏ3ÝÍ3ÞÍ3àÐ3àÎ3âÍ3áÏ3àÍ3ÞÎ3áÎ3áË3âÌ3ßÌ3ÝË3ßÊ3ßË3àÌ3àÉ3ÜÈ3ÝÆ3ÛÉ3ßÊ3âÌ3âÈ3ÞÈ3ÛÇ3ÙÉ3ÚÉ3ÚË3ÛÊ3ÚÇ3ÖÆ3ÙÈ3ÚÉ3ÜÇ3×È3ÕÄ3ÓÄ3ÖÃ3×Å3ÙÄ3ØÂ3ÙÂ3ÖÃ3ÕÅ3×Ç3ÛÇ3ÙÆ3ÙÅ3ÔÂ3ÔÆ3ÖÅ3ÕÄ3ÔÃ3ÔÂ3Ó¿3ÖÂ3ØÄ3ÖÆ3ÓÂ3Ò¿3Ó¾3ÔÁ3ÒÄ3ÖÃ3ÕÂ3ÕÀ3Ò¾3Õ¿3ÔÁ3×Â3×Ã3ÖÃ3ÕÂ3ÓÄ3ÕÃ3ÕÆ3ÕÄ3ÓÄ3ÓÃ3ÓÃ3×Æ3ÙÈ3ÖÅ3ÖÃ3ÕÁ3ÑÃ3ÒÅ3ÔÆ3ÔÈ3ÒÊ3ÓÉ3ÒÉ3ÕÊ3ÙÎ3ÙÎ3ÚÍ3ØÓ3ÙÔ3Ü×3ÞØ3Ü×3ÝÕ3ÙÒ3ÙÔ3ÞÓ3ÝÓ3ÝÓ3ÜÒ3ÛÑ3ÛÐ3ÝÑ3ÝÔ3ÝÖ3Ú×3×Ï3ØÇ3×Ç3×Ä3ÕÂ3Õ¾3Ó¾3Õ¿3ÖÁ3ØÀ3ÕÁ3Ó¿3ϼ3Ï»3μ3Ó¼3Òº3Ñ»3й3Ѿ3ѽ3Ô¾3ÒÀ3л3й3ϼ3Ó¾3Ó¿3Ѿ3κ3Ê·3ȸ3Æ´3Ä«3¾§3¸¡3¹š3Õ3×›3ð­CÄC àCýC&/D to write + them in the current directory: Any of these output formats may be used: + 8 8-bit first differences + 16 16-bit two's complement amplitudes (LSB first) + 61 16-bit two's complement amplitudes (MSB first) + 80 8-bit offset binary amplitudes + 160 16-bit offset binary amplitudes + 212 2 12-bit amplitudes bit-packed in 3 bytes + 310 3 10-bit amplitudes bit-packed in 15 LS bits of each of 2 words + 311 3 10-bit amplitudes bit-packed in 30 LS bits of 4 bytes +Choose an output format (8/16/61/80/160/212/310/311) [212]: Save all signals in one file? [y]: Signal 0 gain (adu/mV) [2456]: Signal 0 ADC resolution in bits (8-16) [12]: Signal 0 ADC zero level (adu) [0]: Signal 1 gain (adu/mmHg) [13.335]: Signal 1 ADC resolution in bits (8-16) [12]: Signal 1 ADC zero level (adu) [0]: Signal 2 gain (adu/mV) [1053]: Signal 2 ADC resolution in bits (8-16) [12]: Signal 2 ADC zero level (adu) [0]: Signal 3 gain (adu/mmHg) [39.8]: Signal 3 ADC resolution in bits (8-16) [12]: Signal 3 ADC zero level (adu) [0]: Checking input signals ... done +. diff -Naur wfdb-10.1.6/checkpkg/expected/xform.all wfdb-10.2.0/checkpkg/expected/xform.all --- wfdb-10.1.6/checkpkg/expected/xform.all Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/xform.all Wed Aug 15 15:44:32 2001 @@ -0,0 +1 @@ +ìXüALARM: ** MULTIFORM VPBs €XüALARM: ** RUN VPBs > 2 \ No newline at end of file diff -Naur wfdb-10.1.6/checkpkg/expected/xform.dat wfdb-10.2.0/checkpkg/expected/xform.dat --- wfdb-10.1.6/checkpkg/expected/xform.dat Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/xform.dat Wed Aug 15 15:33:37 2001 @@ -0,0 +1,79 @@ +ÝÇÝÇD ÇDZ±A ìÿììÖÇÇÇÇ> 3ÇÝÝÝ; ­ÝÝÝÝ8  ÝÝÝÝ8  'ÝÝÝó9  ÝÝÝóB ×óó  [ Ì   ‹ Ó   Ï ---C×   CCCCì pCCCC ´YCCC V5JìCYYo k55oooY X5555;YYYC HJ555\CYCY Q5555CCCC dJJ55£YYYY iJ555ÅYYYo d5 çoooo ]   ………… T óóÝ…››› 7ÝÝÝÝ'››±± ÝÝÝÇ0±ÇÇÝÉÇÇDZ4ÝÝÝݦ±±±±3óó °››››, ì››……!55!X›o……5555!×………oü55JJ1 o…ooâJJJJ!î……››Ã`JJ`!C››››Ÿ`````››››x````™››››M````&››››````››››ñ``JJB›±±±ÆJJ`J†±±±± ````ë±ÇÇÇ…````lÇÝÝÝs````ÂÝÝÝÝh````ŸÝÇÇÇ`````ÇÇÇÇT````ˆÇÝÝÝFvv`v4ÝÝÝÝ8vvvvÇÇÝÇ*vvvvÇÇÇÇvvvŒ=ݱÇÇŒŒŒŒnDZ±±ŒŒŒŒ¢±±›±üŒ¢¢¢À››››ô¢¢ŒŒÀ››››ìŒ¢¢¢§››››åŒ¢¢¢›±±±Ý¢¢¢¸\±››±Õ¸ÎÎÎ6±±±±Îäääú±±››Æäúúú +››…o¾-"&&…ooo¸-&&"&oooo²-&&"&& ooYY¬-&&"&&YYYC§-&"&&YCYY¢-&&" +YooožúúäÎo………˜Îθ¸ñõ››››“¸¸¢¢ñé››››Ž¢¢¢Œñß››±±ˆŒvvvñÛ±±Çǃv```ñÖÇÇÇÝ~````ñÑÝÝÇÝz````ñÈÝÝÝÇv````ñ¸ÝÇÇÇr```JñªÇÇÝÝn`JJ`ñ£ÇDZ›k`vvŒñ£…ooYh¢Îäúñ¥YCC-d-&<"<&òž`-&<"<&òðìÖÿ”[-&&"R}òx<ïÎwî V-Õ-3°4ôc›Ý”¼ûQM¸QUë„öS»aa»£M}JwJ÷LåËSÝÇJmÜnV}`ôGþ”G=Y“ä`ñIC›ÇóE ó±……ðUJ`vB ……ooðxvŒ¢¢A YCCY𮢢¢¢> ooo…ðÛ¢Œ¢¢: ›…››ð碢¢¢6 ››››ðÆ¢¢¢¢3 ›››±ð†¢¢¢Œ/ ±±±±ðj¢ŒŒŒ, ±±±±ðºŒŒŒŒ( ±±±±YŒŒvŒ$ ±±±±Àvvvv! ±±±±svvŒŒ ±±±±ð™ŒŒŒ¢ ±±±±à¿ŒŒŒŒ ±±±±àAŒvvv ±±±Çà"ŒvvŒ ±Ç±±àaŒŒŒŒ ±±ÇÇðŒŒŒŒ$ ÇÇÇÇ!ŒŒŒvD ±±ÇÇvvvv} ±±±±¤vŒŒŒÐ ±±±±ŒvŒv0±±±±8ŒvvvŒ±±±±·vvvvر±±±GvvvŒ±±±±ŒŒŒŒ?±±±ÇŒvvŒe±±±±@vvŒŒ›››…¢ŒŒŒŒµ…………ýŒŒŒŒß…………6vvvv……›…Dvvvv,››››1v```N››±±``JJi±±±±íJJJJ|±±ÇÇÑJ55ŠÇÇÇÇÅ   ’ÇÝÝóÊ   ”óó ÅóÝÝÝ  §ÝÝÝLJ555eÇÇÇÇx5JJJÇÇDZeJ```ñ ±±±±L````ñ_±±›±0`vvvñt±±±±vvvvÇ›±›ìvvvv6››››Ãvvvvý›±ÇÝ—````ÉÝÝÝÇi```JÌÇÝÝÝ9JJJJñÈÝÝÝÝ JJJJñ;ÝÝÝÝãJJJ`ñÝÝÝÝÃ`JJJñ>ÝÝÇÝ®JJJJñ†ÝÝÝÝ 5555ñëÝÝÝÝ”5555KÝÝÝlj5JJJ}DZ±±|JJJJl±±ÇÇn```J2ÝÝÝÝ`JJJJñëÝݱÇPJJJ`ñ±ÇDZ±B````ñ‹Ç±±±5```Jñ‚››››*````ñ”›››› ````ñµ››±›````ñß›…››vvŒŒ››››ŒŒŒ¢››››þ¢¢¢¢›…oo÷¢¸¸¸oYYYðÎÎÎÎñÝYYYYéÎÎÎÎñ¸CYYYáääääñ™CC--ÚäÎÎÎñ‹----ÒÎÎÎÎñ‹-CC-ÌÎÎ΢ñ”YYYoÆ¢Œvvñžoooo¿vv``ñ¥oo…›¹````ñ£››››´`JJJñ—››››®55ñ‰››…›©  ñ{››››£  ño››±›ž  ñh››››™  ñc±›››”  ñc››››  ñf›…oo‹ 5ñ\YC--†`vŒ¸ñL--‚Îθ¸ñ>ÖÿÖÖÿÖ|¸¸¢¢ñ>Àÿª~ÿ&w¢¢ä&ò@¹îw Þ›q-“3…ô4Í”å»wlM¢QUënö5» K»£hmÆÜfÆnæú̪píem;EãåÎþRÀb-<Œ ›àîo›ÝÝ^ YC--ðó J\ CC-ðfJ```Y ðœ````V ð£```vR -ð‰vv``O -CCCðj`J``K CCCCðoJJJJH CCCCð®JJ5JE CCCY!JJ``A YYYY†`JJJ= YYYC`J`JJ8 YCCCðhJJJJ4 CCCCÐøJJJJ0 CCCCÀÚJJJJ- YYYYÀÀJJ`J* YYYCЭJJJJ) YCCCð +J55J, CCYY@JJ5J4 YoooJJJJJ ooYYbJJJJw YCCCTJJJJ¾ CYYYòJJJJYCYYeJJJJrYYYYðõJ555ÁCCCCðÆJJJJÿCCCCðØJJJJ/CCCCJJ`JWCCCCjJJJ5}CCCC¾5555£CCYYý5JJJÉCCCCJJJJðCCCCJ5CCCCØ   4CCCC·  óNCCCC°óóóócCCYY¾ÝÝÝÇso………ÖDZ±±|››››Ú››››€››±±À››››|±±±±†›››…t±ÇÇÇ-……ooeÝÝÝÝðµo…ooQÝóóóð;oooo:óó ñoooo  ñoooo…ý  }…ooo×  ¦oYoo®  !ooooƒ  “………›S óóó‹››››%óóóóð ››±›ûÝÝÝÝð±±››ÖÝÝÝÝàî››››¼óÝÝÝð ›±››«Ýóóóðm›››› óóÝÝðî››››–óÝÝÝY›…›…ŒÝÝÝÝ‹›…››€ÝÝóó››……tóóóóN››……f   +…oooX  ñÈooo…L  ñœoooo@  ñ”oooo7 óóóðªoooo. ó óðÍoooo&óó ñéoYYYñüYCYY YYYY Yooo  ñòoooY  ñÑYCYYø  ñªYoYYð ñYYCYè55J5ñ‚YYYYàJJJJñ‚ooYoÙJ``vñ„Y--ÓvvŒŒñ‚Ì¢ŒŒvñ}Çvvvvñ}-ÂŒvŒvñ}½vvvvñ{¸ŒŒvvñq²v``Jñh¬JJJJñf--CC¨J555ñoCC-C£J5ñ{CCCCŸ óóÝðCYYYš ÝÇÇÇð†Yooo— ÝÝÝÝð………o“ ÝÝÝÝð”oooo ÝÝÝÇð”oYYYŒ ÇÇÇÇð‰oYYoˆ ÇÇÇÇðxYYC-† ÇÇÝÝðh‚ 5`ñUÖÿÖÖÿÖvŒŒŒñLÀÿ””ÿ”|Œ¢¢ŒñS”ÿ”~ÿ Ðå  ; ภ  : -ðâóóó 9 ---¾   : ----,   > ----Y  óM --b  óón ---:ó  « ----ä  ---ˆ  ód\ó ó ¿j     @ß   j---! óóó--Yóóóݳz ó  Ù   ÿs óóÝ&[óÝÝÝHFÇÇDZh--A±ÇDZ--C-Y±››…“CCYC|››…›žCCYC››……¢CYYY~oooo Yoo…FoooY—……››íYCCC‰›››±}CYYYv±±±±C---^±ÇÇÇðâ----BÇÇÇÝ6- ÝÝÝÝ----ûÝÝDZè-CCYѱ±±± TYYCC¤›±±Ç CYoouÇDZ±TooYoE±±±±›ooYo±ÇÇÇ!YoYo÷ÇÇÝÇðéoYCCÞÇÇÝÝðð--CCÎÝÇÇÇ-CYCYñ±±±ˆYYoY¹±±±›ÖooYC¯±±ÇÇöYYYY£±±±ÇëYYCC–ÇÇÝÝÃCCCCˆÝÝÝÇC---{ÝÝÝÝ`---pÝóÝÝG--eÝÝÝÝG----\ÝDZÇ^C---TÇÝÝÝ}----LÝÝÝÝ–--DÝÝÝݤ-<ÝÝÝݤ----5ÝÝóó.Ýóóó&óÝÝÝÝóÝóqóóóÝeóóó \--- + W---C5R----þ55JJPùJ```PôJJJJNðììÿìîJJJJKìÿÖÖÿÖêJJ``GÖÿÖÖÿÖå```J@ÖÿÖÖÿÖàJJJJ;ÖÿÀÖÿÖÛJJ56Öÿì×  ó4Ó óóóó4--CCÏ óÝDZ9CCC-Ë ››››=----Ç ±±±±B---Cà ±±››GCC-C¿ ››››I----¼ ±±±±D----º ±›››=----· ››±±4--´ ÇÇÇÝ(ìÿÖ° ó 5JÖÿÖÀÿ”¬J555”ÿ””ÿ~©5hÿ<äî£5vÎKÞ݆Ýž-<©2-Æ~¼åw»5™MvU©öé »5w»Ï”mBVÕ}õ¼SܱíKM¸°#¿äñªÎþRÀ5±YðÈCo›±‹  +ÇÝÝ Š ìÿÖÀK   ˆýÀªÿÀÀg   ˆýÖÖÿìc  † R   ‚ D   ~ =   | B  óóx Wóóó t U   o ðüóóó k ð\   h àç   d ð  óób ðºÝóÝÝ_ --”ó ó^ -T óÝÝ_ ÕÝÝóób  ó  j ö ~ ´   § p   ì A óóóF(ó  ¤*   ö----M óóó5----ˆÝÝÝÝc-ÀÝÝó …å   ¤ö  Ãø óóÝåêÝÝóóÐóÝÝÇ+»ÇDZ±K±±±Çe--á››……x--CC oooo‚C-CC oooo†CCCY Yoooƒooo…ÓYYYCzoo…›wCCYYj››››ýC---U››››-CC-<›±±±eC-CC±±±±¾YYYoû±±±›…oYYCÔ›±±± QCCCC©±ÇDZ ¡CCCC}±±±± TCCYCQ±›››²YYCY%››››oYoo±±±±®ooYCåÇÇÇÇzCYYYÒDZ±±xooooȱ±±Ç©oooo¿ÇÝÝÝôYC--·ÝÝÝÝ8--C-®ÝÇDZY-CCY¢±ÇDZRYYCY–±±±±1oYYYŠ±±Ç±C-C-~ÇÇÇÇäC---sÝÝÝÝÑ---CjÝÝÝÝÑCC--aÝÝÝÝß---ZóÝÝóôRóóÝÝ ----KÝÇÇÇ-CC-DDZ±ÇCC-C<ÝÝÇÝ----5ÝÝÝÝ----.óóóÝï----&ÝÝÝÝÚ-- ÝÝÝÝÈ---Ýóóó¼---óÝÝó¹---Có  ¹CYCC +5555°C-55JJ§J``v©ìÿììÿìùvvvv·ÖÿÖìÿìô`J55Àìÿììÿìî ¼ìÿìè  «â  ó Þ óóóó–-Ú óóóÝ----Õ ÝÝÇÇ‹----Ð ±››±ˆ---CÌ ±±±›‹C---É ›››…-C--Å …………‹CCC- …………„--CY¾ …………xYYC-¼ ……››l-¸ ±ÇÝÝ`ìÿÖ´ óó WÖÿÀªÿ”°  N~ÿ~~ÿh¬ óÝDhÿ<ú Ýóv=KÞó†Ý¤äh"ë›4”¼û»5žM4ãT}ë&5»5w»£šmÕU©QÌÀ†í5—MÎÜ#¿ä¹þRÀ”5›-ì-Co…›ýÀªÿÀì`DZÝÝŽýììÿìÖ’ÝÝÝÝŒýÖÖÿÖÖ ÝÝÝÝŠýì‹ÝÝÝó‡ ìÿììj   „ýÖìÿììU   ýìðììN  ó} RóóóÝyýììÿìsÝÝÝóu ©Ýóó q ›  ól ðòóÝÝóg àìó ób àLóóóó\ à‡ óóÝU ðNÝÝÝÝO ÝóóóH  ÝÝÝC °ÝÝÝÝ? ----²ÝÝÝÝB CCCCÝÝóóP !óóóÝv ðìðºÝÝÇǵ ðjÇÝÝÝ ð;ÝÝÝÝ_ð+ÝÝÝݦðEÝÝÇÝÚð‚ÝÝÝÝùð¸ÝÝÝÝð¿ÇÝDZ#ð±±±±7ìÿQDZÇÇOÿìÖÿÖìÿDZ±±iÿìðììÿ›±±›€ÿììÿììï÷›››…–ÿììàó…›››¨àõ……››µàü………oº-àóoYYC¹CCCCàÆCCCC²CCCCàfCCCo¥YYC-Ðóoooo’---CлoYooyCoo…àYYoo[………›à¿C-CC9›››±ðZCCC-±±±±ðm----í±±±±ð--CYÆ››››à‰YYYC¡››±±à)CCYo‚››ooÐöoooomoYYYÐåoooY_o…››ÐøYYYYU›››…à)YCCCN……ooà]CC--E…›››àp----<›…››àa-CYo2…oooàQoYYo(…›……àOoYYY…››±àQCCCo±±››àJYYYC››››àCCC--››……àH-…››±àZ---ý ÇÇÇÇàh----ø ±›oYàp---Cô oYYYàkCCC-ï YYooàd----ê …››…àd-å ooooàtà …………à•---Ü ………oàÄ----× ooo…àî----Ò …›±±àú--Î ››››àç----È ››…›àÄ-à ››±±àž¾ ±±±Çà…ðÖº ÇÝó ápÖÿÖÖÿÖ¶ ÝÝÝàaÖÿÀÖÿÀ² DZ±Çà]ÀÿªªÿÀ® ÇÝÝÝàaÀÿÖÖÿìª ÝÝÇÇàmÖ§ DZ±›àw¤ ›››oà€  YYCCàŒ- CC-à—š --à—---˜ --à•----— -àœ----— à±---— àÉ— à×-— --Cààðììÿì˜ ---àõÖÿÖÖÿÀ™ -CC-ðªÿ”hÿh™ CCYYðEhÿ<&ÿ&˜ Yo…›ðhúîä£îK– ±ó5Œñ‚ Þ±pÝ”-&“2…ó—”ÌS'Ì’=ò4D``ô£'ÌSÀÜpM4ò3…©ò£ îúþh‘Î oð™À--’ýÖªÿªªÿ—YYo…”ýÀÀÿÀªÿ§›±ÇÇ•ý”hÿR&ÿ¿ÝÝÝÝ—ý&&ÿ&&ÿÈÝÝÝݘýRRÿRhÿ±ÝÝÝݘýh~ÿ~”ÿÝÝÝݘý””ÿ””ÿSÝÇÇÇ—ýªªÿ””ÿoÝÝÝÇ•ý””ÿªªÇÇÇÝ’ýªÀÿÀÀÓÇÇÇÝýªªÿªÀlÝÇÇÇŠýÀÀÿÖÖwÇÇÝÝ…ýÖÖÿÀª(ÝDZ±ý””ÿ””äDZ››zý””ÿªÀر›±ÇvýÖìÿììöÝÝÇÇrýÖÀÿÀÖ*ÇÇÇÇnýÖìÿìÖÇÇÇÇjýìÖÿÖÖôDZ±›gýÖÖÿÀÖ/V±±±±dýÖÖÿÖÀ/{±±±±cýÀÖÿÀÀ/_±±±±fýÀÀÿÖÀ/)±±±›pýÀÀÿÀÖ/›ooo†ýìÿo……›° ìÿÖÀ/››ÇÇìýÀÀÿªª/CÝÝÝÝ6þª”ÿ””/~DZDZ€þª”ÿªÀ/»±±±›¾þªªÿªÀ/ñ›››±ìþÖìÿÖÀ?››…o ÿÀªÿ””/üYYYo%ÿ””ÿ””/»ooo…7ÿ””ÿ”ª/b………oHÿª”ÿ””/ooooXÿ”ªÿÀÀÐooYYiÿÖÖÿìì¦CC--vÿììÿììˆ----ÿÖÀÿÖÖn--‡ÿÖÖÿÖìT‡1 ----sô--_äG----·*--YYI ooooð åYCCCð +À-ð›-Cð¥yCC--_CCC-ô-L--CCØ@CYCCu5CCYY*ooooðžYCCYð)YooYàÐþ YYYYà¿ï YYCCàçà CCYCð--Ô CCCCð0É CCCCð)ðì¾ CCCCð¶ CCCYàü® Yoo…àÛðÖ§ …oooà¬ìÿìì¡ YYYCà€š CCCCà_” CCCCàSŒ YYYoàX† YCCCàh ---Cà~| CYYYàŒu ooooàŽìp oo……à‰l …………à‚g ›››±àtìÿììc ±±±±à_ðìÖÿÖ_ ±±±ÇàJÖÿÖÖÿÖ\ ÇÇDZà>ÖÿÀ”ÿ”Y ±±±Ýà<”ÿ”~ÿ~V ÝóóóàE”ÿ””ÿ”T ÝÝDZàZªÿÖÖÿÖQ ›…ooà~ÖP oYYoàªO oo…oàÐN YYC-àâL ---àÞK --àË--J --à»----G à¶----F à»----F àÂ---D ----àÍB ---CàÛðì? CYooàéÖÿÖÀÿ”; oYYYàóhÿhhÿh6 YoYYàõRÿ<&ïú2 Yo›Ýàú¹îK Þ±-5¢!&“òDÍì~Ì=)=-›CJôÌ'Ì”&M`JDÆã÷ݱKîä$=<v±àÛRÿª-" CðÀªï¿Coo›!ý””ÿ””ï±›±ÝÝý”~ÿhRï¶ óóÝýRRÿRhï¿óóóóýhhÿh”ï¿ÝÝÝÝý””ÿ”ªïªÝÝÝÇýªªÿÀÀï•ÝÇÇÇýÀÀÿÀÀïªÇÇÝÇýªªÿÀÀÿÇÝÇÇýÀÀÿÀÀÿxÇÇÇÇýÀÀÿÀÀÿ¼±±±± ýÀÀÿÀÀÿ ›±±±ýÀÀÿÀÀÿX±±››ýÖÀÿÖÖÿG±±ÇÇýÀÀÿÀÀÿÇÇÇÇýüÀÀÿÀÀDZÇÇúüÀÖÿÖÖ„DZ››öüÖÖÿÖÖý›››±ôüÖÖÿÖÖlÇDZ±ñüÖìÿÖÖ°±›››ðüìÖÿÖÖ·››±±ôüÖÖÿÖÖƒ››››þüÖÖÿÖÖ:›…›…ýÖÖÿÖÖ …››±CýÖÖÿÀÖÇÇÇdžýÀÀÿÀÀ*DZDZÖýÀÀÿÀÀn±›±›&þÖÀÿÀÀ¾››››jþÀÀÿÀÀ/›››› þÀÀÿÀÖ/:››››ÉþÀÀÿÀÀ/O››››êþÀÀÿÀª/F››……ÿªªÿªª/%…………%ÿªªÿªªÿ………oAÿªªÿÀÀè……oo^ÿÀÖÿìÖãooYYwÿÖÀÿÀÀìYYYCŽÿÀÀÿÀÖûCC--ŸÿÖÖÿÖì/--¬ÿìÿ±ñ±ÞªÅž-CŒCCCC`ðìuCCYYÖÿìÖÿÖZYoooìÿììÿì;ooYY9ìÿììYYooNñYYCCÚÊCCCC|¤CCCYÉ‚YYoo­foooo^SooooFoooo·ì=oooou5ooooW-ooooc#oooo„ìÿìoooo¢ìÿÖÖÿÖ…………²ÖÿÖÖÿÖ…………¹ÖÿìÖÿÖý …o…›Àìÿììÿìô ›………¾ìÿìÖÿÖì ……›…©ìÿìÖÿìå …………ìðìÞ oooosìÿìØ ooooeìÿììÿìÓ …………cìÿììÿÖÎ ››……jÖÿÖÖÿÖÈ ………›nÖÿÖÖÿÖà ›………uìÿÖìÿì¾ …………zìÿìÖÿÖ¹ …›››zìÿììÿìµ ››››qìÿììÿì° ››››cÖÿììÿì¬ ››±±UÖÿÖìÿì§ ±±±±K£ ±ÇÇÝDž ÝóóóDðÖÖÿÀš óó GÖÿÀÀÿª— ó  óKªÿ””ÿ”“ ó  P”ÿ””ÿ” óóóR”ÿ””ÿ”Œ óÝÝÝR”ÿ~”ÿ”ˆ ÝóÝÝP”ÿ””ÿ”† ÝÝDZKªÿªªÿªƒ ±±±±DªÿÀÀÿÖ€ ±±±±=Öÿììÿì} ›…oo;z YYYY=x CCCC;u CCYC2s YCCC(p C---#o CCCC#m CCYYìÿìÖÿÖl ooooªÿªªÿ”k oo…±ð÷”ÿ”~ÿhj ÇÇÇÇðü<ÿRRÿhh ±±›…Rÿ<ïÎg oYo›/î5Ý݆d ÝJÎ<6Í~å»wa-Õ…C¢ » 5»]]EãŒôþûË”Dí YMY#hŒñòþhÿÖV ÝoÀ-CYTýª”ÿ”ªo…››QýÀÀÿª”±±±›Pý””ÿ””#±±±±Ný””ÿ””&±±±±Lýªªÿªª-±±››KýªªÿÀÀ@››››JýÖÖÿÖìe›±››HýÖÖÿÖÀ™››±›FýÀªÿªªÏ››››CýÀÀÿÀÖë››››AýÖÀÿÀÀ²………›>ýÖÀÿÀÀÿþ››››;ýªªÿÀÀÿ………o8ýÖÖÿÖÖï]o………5ýÖÖÿÖÖï•››››3ýÖÖÿÀÀÿ™›………0ýÖÖÿìÖØ…›……0ýÖìÿììÌ……›…0ýììÿìì/C››……5ýììÿìì/To………Cýììÿìì/…………býììÿì줅…››šýììÿìì,…›……ìýììÿììß……››KþìÖÿìÖÖ›››…¥þììÿìì………›íþììÿÖÖe››››!ÿÖÖÿÖÖ²›………EÿÖÖÿÖÖÜ…………cÿÖÖÿÀÀå…oo…|ÿÀÀÿÀÀÕ………o—ÿÖÖÿÀÖ·oooY²ÿììÿììYYYoËÿÖÖÿÀÀlooooâÿÀÀÿÀÀVoooYõÿÀÀÿÀÀRYCC-ðÀÖÿÖì[----ðììÿììb-ðìì^8Ýìÿììÿì-Kìÿììÿì-CCCðÊÖÿÖÖÿÖðCCCCðÖÖÿÖÖÿì×CCCYˆÖÿÖì»Yooo^˜oooo·ìÿììÿìsoooopìKoo……íðÖ ……oo„ðììöoo……GÌ……oo#¨ooooŠ…oo…*ðììÿìvooo…cÖÿÖÖÿìh……oo”^oYYo¢TooYY†JooooYðì>oooo6ìÿììÿì2oooo!ìÿÖÖÿÖ&ooooÖÿììÿìooo…!ìÿÖÖÿÖ……››9ÖÿììÿÖ››››`ÖÿÖÖÿÖü ›……›ÖÿÖÖÿÖó ›………µÖÿÖÀÿªë …›±±Àªÿª”ÿ”ä ÝÝó «~ÿhhÿRÜ55J<ÿ<&ÿ&Ö`vŒ¢Iúîä¹îÏÎú!&haî5 ÞÝÉ-©ë2-Yóþ›Ý†ZÝ.Â=›Æ3òôòÝÀ̪¼MJŒD¸ùôù”Ì~SÌS·]%}U¿ +=Ì''¼û±mn°vuå»Ï£»w¬}·ãwùÿ-a»K5»5§}ÿÿwÿÿ(5»Ka»w¢}ÿÿwÿÿ £»£Ï»åž}ÿÿwÿÿ÷çÌhÀÜDš}ÿÍwJšöƱí5î¹–]¿ùDJ°ó®úþ&hÿ”“=-“"&Œñ£Ö-Y›”ÿ¥›ÇÝÝý<äî£þ±Ý ŒíwaîaaþÃ55J‹íKKîK5þÔ`vvŒŠí î þßvvvvˆí î þëvv`J†í5î þ÷JJ``…í óÝóóýþvvvvƒÝóóÝóÝýþvvvv‚ÝÝÝÝóóýþv```í óí JJJJí î JJJ5~í Þóó *5 ~ÝóÝÝÝÝ 5JJ}ÝÇÇݱ±ýÖJv``|Ý›†Ý†pýœ`JJJ|Ýpp݆†ýJJJ5|ÝppÝpZýÁ555JzÝp†Ý†p 5J55zÝZDÝDD \55JJyÝ.Ý –JJJJzÝÖÌÖÖ À``vJzÍÀÀÌÀÀ áJJ5}ÍÀªÌªª ò5JJ`‚ͪ~Ìhh ô``J`ŒÍS=Ì=' ívvvvžÍ¼ûå ëvvvv¹½ûû»ûû ù```Jݽåå»Ïå5555¾åå»ÏÏ855 2¾Ï¹»¹¹O   Y¾åå»ååO ÝÝÝx¾ûÌ'D±±››Î==Ìhh8oooYŸÎ~”ÌÀÖ1---©ÎÖìÌì#±Þ.ÝDD ðì¶Þ.DÝZp òÖÿª”ÿ”¸Þ±óíKØ”ÿ”~ÿh¹îaaîKKÈhÿ<&ÿ&¶îKKîawÊ&ÿ&&ÿ&¯î£î££ï&ÿ&ïú¥î£¹îÎú1äîä¹î¹˜þ&ÿ<<e¹î¹¹î£‡þ<<ÿ<<p¹îîtþ<<ÿ&<baîwî_þ<<ÿCC--Ù ›……›°/--CCÕ ››……°+CYCCÑ …………°$-C-CÎ ………›°---Ë ››››°ðìÉ ±±ÇÇ°(ìÿÖªÿ~Ç ÇÇÝó°;hÿh<ÿRÇ ±@RÿR&ïúÇ5JŒÎ±+¹îw5ÞóÇ+&“2›³›ÝpÝÆKvD¸ã¤ÛÝÝ.ÅKã¸DŒ`¤Ë›í5¹þ<Ã;°Õä¡Ôªÿì-o¿ ±Cì¯î›±ÇݽûÖÖÿÖì¿ ÝÝÝó»ûìÖÿÀª¿2   ºû””ÿªª¿\óóóó¹ûÀÀÿÀÀ¿ÝÝóó¹ûÖìÿìì¿”ÝÝóݸûììÿìì¿—Ýóóݸ ðì°—óÝÝÝ· °®ÝÝÝݵ °ÝÝÝÝݳ ìÀÝÝÝݱ ÀÝÝÝݯ À1ÝÝÝݬ ÀsÝÝÝݪ ðììÏÎÝÝÝÇ©ûìÐ8ÝÝÝݨ СÝÝÝݧ ÐøÇÝÝǧ à,ÝÝÇݧ à7ÝÇÇÇ© à5ÇDZǭ à3DZ±±¹ à>ÇÇÇÝ× ðììïOÝÇÇÇ üìàaÇÝÇÇ^ àk±±Ç±º àhÇDZ› àd±ÇÇÝX ðììïkÇÇÇÇ„ýììàr±±ÇÇœ àp±Ç±Ç§ à]±ÇÇDZ ìà<ÇÇÇǾ ìÿììïÇÇÇÇÎýììÿììßÕÇÇ››Þýììÿììß¡››››ð ðììß“›››…þ ðììßË………… +à:ooooìïžoooYþììÿìà¸CC--Càr-CYC-Ðì--CC +ìßbYYYCþììÿììÏöYYYCðýììÿìÀ²C---Ü À‘--à --À--§ CCooÀqˆ oo……Àjj …………À›K ››››Ð0 ›››±Ð´ ››±±Ðú ±±±±ÐÇ ÇÇDZÐV- ±±±›Àñ ±±±±À«ü ±±ÇÝÀuðÖÖÿÖô ó  ÁRÖÿÖªÿ”ê55J`ÁWhÿ<ïúàv¸úˆ¹îaîKÖ,&R"}“ÂÇî îÏ,¿Õ"ëëÂïî ÝݱÈ<C3…ÆÃö†ÝD.ÝÃLŒTQÅèÖÌÀìܾ\©¿U};ÅÊDÝ›ÝíKºLÎ`4òYùîúhÿÀ¶,“ä`óÀ=--o² ›YC°í…›››¯ Ö¿ÊÝÝÝÝ«üÀ”ÿ~~¿ßÝÝÇǦü””ÿªÀ¿þ±±±Ç¢üÖÖÿÖÖ¿äÝÇÇÇüÖìÿìÖ¿ ÇDZ±—üÖìÿì쿬›ÇÇÇ’üìÖÿÖÖÏeDZ±ÇŽüìÖÿÖÖ߀ÇÇÇljüÖÖÿÖÖï,ÇDZ›…üÖÖÿÖìßï›±ÇÇ‚üÖÖÿÀÀß3ÇÇÇÇ~üÀÀÿÀÀϼÇÝÝÝyüÀÀÿªÀÏÚÇDZ±tüÀÖÿÖÖßM±ÇDZpüÖÀÿÀÀßÇÇÇÝÝküÀÀÿÀÀï<ÇÇÝÝgüÀÀÿÀÀï¸ÝÝÝÝcüª”ÿ””ÿ0ÝÝÝÝ_üªªÿªÀÿ„ÝÇÇÇ[üÀÀÿÀÀÿ¥ÇÝÝÝYüÀÀÿªªÿ¥ÝÝÝÝWüªªÿ””ÿ£ÝÝÝÝUü””ÿ””ÿ¬ÝÝÝÝRü””ÿ””ÿ¼ÝÝÝÝOü””ÿ””ÿÑÝÝóÝMü”~ÿhhÿîóÝÝÝMühhÿhhÝÝÝÝMühhÿhh6ÝÝÝÝQühhÿhRRóÝÝÝYüRRÿRhWÝDZÝdühhÿhhGÇÇÇÇsühhÿhh-±±››ˆü~~ÿ~”›››…žü””ÿªÀ +…oooµüÀÀÿÀÖooooÊüÖÖÿììYYYCÛ CYYCè -CC-Cñ ----CCCCö CCCCððCC-Cù CCYYðß----ú ooooðÊ----ú ooooð®-CCCø ooYoð†-C--õ ooooð\-CCCð ooooð-CCCCè ooooààCYCYß ooooàdYYCCÔ ooooÐãYYYYÈ YYYYÐêYYYo» YoooàÆYYYY± oYooðõYYYY© oooo‹YYCY¥ oooo4YYYY¤ ooooð{YYYY¤ ooooàîoYYY¤ ooooà£CCYY¢ ooooàtYYoož ooooàkoYYY˜ ooooàœoYYY’ ………›àìYYCYŒ ››››ð&YYYY† ›±›±ð0YCC-‚ ±±ÇÇð--- ÇÝÝÝð} ÝÝÝÝàâz óó óà¿y ÝÝÝÇà£w ÇÇÇÇàžu DZ±›à³---Cs ›››…àÒYYYYr …………àéYYYop ooooà÷oooop ooYCà÷oo……n CC-Càç…………m ----àË…………l ----à±›››…j ----à¡……››i --ज़›…›h ඛ›››g àË›…ooe ---CàÙoYYCd CCYoà×--c …›››àÉìÿÖÀÿ”b ±±±±à³”ÿ”~ÿh` ÇÝÝ á¥&ïú£îK\JŒäh⥠ޱpÝY,ÕY3ÜJä¯ÀÌ””Ì”ULŒ¸D¸Œä¶ÀÜ›íKQLJÜ3&â½äþhÖNJ›Öï¿o›ÝÝLü”hÿhhï½ó5Küh~ÿhhïÄJJJJIüRRÿ<<ïÞJJJJIüRRÿRhÿJ`J`Kühhÿh~ÿQJJJJKü~”ÿ””ÿ†JJJJKü””ÿ””ÿ JJJJIü””ÿ””ÿ†JJJJGü””ÿ””ÿJJJJDü””ÿª”ï_JJJJ@ü”ªÿ””ßÐJJJJ=ü”ªÿªªßÚJJ5J:üªªÿªªï•JJJJ7üªªÿªªÿ¼55556üªªÿªªë5555üªªÿªªÌ4üªªÿªª/'5üÀÀÿÀÀö  ;üÀÀÿÀÀg   OüÀÀÿÀÀÏ   {üÀÀÿÀÀl   ÄüÀÀÿÀÀW   &ýÀÀÿÀÀˆ   ýÀÀÿÀÀë ó óêýÀÀÿÀÀ`   .þÀÀÿÀÀÅ   \þÀÀÿÀÀö   {þÀÀÿÀÀï   ”þÀÀÿÀÀÇ   ­þÀªÿªªŸ   Æþªªÿª”Œ  àþ””ÿ””ˆ   ûþ””ÿ””…   ÿ””ÿ””|   (ÿª”ÿ””nóóó 7ÿ””ÿ”ª[ÝóÝÝAÿªªÿªªRÝÝÝÇEÿÀÀÿÀÀRÇDZ±DÿÖÖÿÖìV±±››>ÿììÿììV››››2ÿìK……oo#6ooooooooøûoooYÞ---ÃYYYYÂ--CCeYYCC£CCCCðßCYYY‚CCCCð_YYCC`CCCCð>CYYY<CCCCðªYYYYCCCCRoYYYõ CCCC¼oYYo× CC--ÀooYY¾ CC--’Yooo¬ C---\oYCC  C---CYYY– ----ð¸CCCCŒ ----ðhCCCCƒ ---CðICCCCy --CCðaCCCCn C--Cð”CCCCe CCCCðÆC-CCZ CCCCðçCCCCQ CCCCðõ---CH CCCYðîCC--A YYYoðÍ----9 ooooð ----2 o………ðv----, …›››ð\-$ ›±±±ðQìÿÖ ±±±±ðNÖÿÖÖÿÖ ±±±±ðQÖÿÖÖÿÖ ±±±›ðSÖÿììÿì ››››ðQìÿììÿì ›››…ðI …oooð>-û YYYYð-----ö YCCCð----ñ CCC-ð--CYì -ðCCCCç ðYYYYã àõYYYCÞ àçYYCoÚ àÛYYYYÖ àÔYYYYÒ àÔCC--Ï àÐ-Ë -CYàÄìÿÖÈ o››…à»Àÿ””ÿ”Ä ›…oYดÿ””ÿh¿ CC-Cà¸&ïäî5º o±Œá¯Ý݆Í~´,}2°ãŒ¼Ï£»Ï®L4ŒD¸ŒädûËSÖÜ›¨L`ò3C<âQKîÎRÿª¤`›ÀïZ-o… ühRÿ<<ïk›±ÝÝŸüRRÿRRïmó  žü<&ÿ&&ïd   œü&&ÿ----K …………ð+--E ›››±ð&> ±±±±ð+ðì8 ±±±±ð0ìÿÖìÿÖ2 ÇÇÇÇð-ÖÿÖÖÿì, DZ±±ð$ÖÿÖÖÿÖ& ±±±±ðÖÿÖÖÿÖ ±±±›ð ›………àõ ooooàé ooYYàâ---- YCC-ààC-CC -ààC-C- àÞCCCCÿ àÐYCCCú à½YYYCö à¬YCCCò à¡CCCCð à—--ì CàŽðìè Co…›à‰ìÿÖÀÿ”æ ±›››à”ÿ””ÿ”â ›…oYàž”ÿh<ïúÝ CYo±à¥£îKó݆ØŒ!hâš.Í”'¼¹Ò<›CŒä{»¹ËÍL¸¸DŒJä]~Ü.ÝíÉ<°¿Î áVúþhÖÆ Yìÿ”hïdCo…›ÄüR<ÿRRïr±ÝÝóÃühRÿR<ïy   Âü<<ÿ<<ïw ó  ÀüRRÿRhï{   ¾ühhÿ~~ïš   ½ü~~ÿ~~ï×  óºü~~ÿ””ÿ" óóó¶ü””ÿ””ÿcóó ó´ü””ÿ””ÿtóóóó°ü””ÿ””ÿÝóÝÝ«ü””ÿ”ªßýÝóóó§ü””ÿ””ÏÅóóóó¤ü””ÿ”ªÏIóóóó¢üª”ÿ””ÏûóóÝÝ üªªÿªªïhÝóÝÝŸüªªÿªªÿÍóÝÝÝ üªªÿª”¹ÝÝÝݤü””ÿ””/ÝÝÝݲü””ÿ””:ÝÇÝÝÔü””ÿ””äÝÝÝÝý””ÿ””DÝÝÇÝfý””ÿ””ÿ ÇÇÇÇÈý””ÿ””ÿ9ÝÇÇÇ#þ””ÿ””ÿ)ÇÇÇÝkþ””ÿ””ÿcÝÝÇÝ þ””ÿ””ÿÆÇÇݱÆþ~~ÿ~~/ÝÇÇÇæþ””ÿ”~ÇÇÇÇÿ~~ÿ~~µÇÇÇÇ&ÿ~~ÿ~~ÅÇDZ±Fÿ~~ÿ~~«±±±Çeÿ”~ÿ””u››››ƒÿ~”ÿ~”6››››ÿ””ÿ””…………³ÿ””ÿ””ÿî››……Äÿ””ÿ”ªÿõooooÏÿªªÿÀÀYYoYÕÿÀÀÿÀÀ-YCCCÕÿÀÀÿÖÖ4C---ÏÿÖÖÿìì----ÄÿììÿììÿÑ----µÿììða-¡àÛ-‰àŒnà¬Nð*ð{ð‹Øð\«ð~ìÿììï¶Rþììÿììï_*ðììï þììÿììïõýììÿÖÖïæýìÖÿÖìï ÜýììÿììïÐýììÿììßóÄýìÖÿÖÖßÜì¶ýììÿììß»§ýììÿììߘì˜ýììÿììßyŠýììÿììßdìÿì~ýììÿììßYìÿÖìÿìr ìÿììßVììhýììÿììßVìÿì^ýììÿìÐTìÿììÿìU ÐKìÿììÿìL Ð?ìÿìÖÿìC Ð,ìÿììÿÖ: --ÐÖÿÖÖÿÀ3 CCCCÀêªÿªªÿª+ YYCCÀÇ”ÿ””ÿ”$ CCYYÀ©~ÿ~”ÿ~ ooYCÀ‘~ÿhhÿh YYYYÀhÿhhÿh ooooÀuhÿ~~ÿ” ooYCÀn”ÿªÀÿÀ C-ÀjÖÿÖÖÿìú ÀeÖÿììÿìõ ÀcÖÿÖìÿìð ìÏ^êüììÿÖÖÏWæüìÖÿÖÖÏIâüÖìÿììÏ1ÞüììÿÖÖÏÚüÖÖÿÖÖÏÖüììÿììÏ#ÒüììÿììÏ?ðìÖÿÖÎüÖÖÿìÀIÀÿ””ÿ~Ë -CCÀ4hÿR<ÿ&Ç CCYCÀ&ÿ&&ÿà CCCYÀúîä¹îw¿ o±ó`Á ÞdžÝ.ºÎ<"©-ÃÀÌhSÌ'¶<›DJ`Ä!'Ì=hܲLJ4ÆÛí5¹þ&¯,&5…À~ÿÖ-­üªhÿ<&ÏCYoo¬ü&ÿ&&Ï-…›››ªü&&ÿÏ=››››¨üÿ&Ï&››››¥ü&<ÿR<¿ð››››¢ü<<ÿo…ooxü””ÿ””ï€o………uü””ÿ~h﬛›……tüh~ÿ~”ï±…………yü””ÿ”ªï‰o………ˆüÀÀÿÀªïX…›››ªüªªÿªªï>›››±âüªÀÿììïE±±±±.ýììÿììïaDZ±± à‡ÇÇÇÇÌ ðììï±±±±Ç þìàâ±±››4ìÿììÿ±›Ç±Vþììÿììÿ±±±±tþììÿììïå±±±±’þÖÖÿÖÖï½Ç±±›²þÖÖÿìÖïž››››ÒþÖìÿÖÖ›››ðþÖìÿìÖïy›››… ÿÀÀÿÖìïh……››&ÿììÿìÖïV…ooo;ÿÖìÿììïJoooYJÿììàŠ---CdC---V-;---- -------#----â----ðI----¶--à¿----àr---CkàX--CCRà…C---BàéC--C6ðN-CC-+ð}---- ðq-----ðB----ð----ø ---àÐ---ê ----à¥---Þ ----à—-Ó ----à¥--Ê ----àÆ-À ----àé¸ -CCCð° CCCCð© CYYYð¡ ooooàî----š ooooàË’ …›››à¨Š ››››àŽìÿÖÖÿÖ‚ ±›±±à…ÖÿÖÖÿÖ| ±±±±à‡ÖÿÖÖÿÖu ±›››àŽÖÿÖÖÿÖn ›±±±à—ÖÿÖÖÿÖh ±››…àœÖÿììb oooYàœ\ YYYCà•V CCCCà‰-R --ày----M àm----H àf----C àdCC--? àdC--C; à_--CC8 àS----4 àA--0 -à0ðìÖÿÖ, CY……à.ÖÿÖªÿ”( ›………à7”ÿ””ÿ”$ oYCCàA~ÿRï¹ -Y…Ýà>wî ±Ý.JÎ!<¿â,ÀÌ=廣=YÜC`¸ä»£åËSM¸ŒDJÆã ݱaîä =úoàhÿÀ- + ªÿh<ï)o…›±ý&<ÿRRï>ÇÝÝÝýRRÿ<&ïEó  ý&&ÿ&<ï<  óýÝÝÝÝ þ””ÿ””ï÷ÝÝÝÝnþ””ÿ””ï÷ÝÝÝÝ©þ””ÿ””ÿ)ÝÝÝÝÖþ””ÿ””ÿxÝÝÝÝûþ””ÿ””ÿÔÝÝÝÝÿ””ÿ”~(ÝÝÝÝ@ÿ~~ÿ””\ÝÝÇÇcÿ”~ÿ””cÇÇÇÇ…ÿ~~ÿ~~DÇDZ›§ÿ~~ÿ”~ +±›››Äÿ~~ÿ””ÿÍ››››Þÿ~”ÿ””ÿ ›………òÿ””ÿ””ÿ……ooðªªÿªÀÿ”ooooðÀÀÿÀÀÿ§ooYY +ðÖÖÿÖÖÿ±CC--ðìÖÿììÿœ----þÿììðL----ïàÆ----Üàa--ÅàŒ-©ð@-‰ðé----d--- +----;--ðº-----ðQ----âàü--CC´à»C---ŠàŽ----hà‡CCCCPà¥CCCC@àÐ----4àì----*àó----àì-----àÙ----à¸---ø ---à“---ê ---àyÞ ----àtÔ ----à€Ê ----à•À --CCॸ --C-௱ CCCC೪ CCCCà±£ CCYYࣜ YYooà-” ooooà{Œ o……›àmìÿÖ† ››››àaÖÿÖÖÿÖ ±±±±àXÀÿÀÀÿÀx ±±±±àVÀÿÀªÿªq ±›››àSªÿªªÿªk ›››±àQªÿªªÿªe ›››…àLÀÿÖÖÿì_ …ooYàHìÿìZ YYYCàAT C-CCà:P --à5J à.-F à)B à = à9 à6 à2 ðìÐýðì/ ÐøÖÿÀÀÿª, CCÐñªÿ””ÿh( YCCCÐêhÿhhÿh$ C-ÐãhÿR&ïä YÐãî5ÝÝp ±ŒúÑÞÍ”¼¹-}3…òÓλ£»åM444ò°Ó¶SÜÇía =-hv›Ð¤äþR”ÿì ”ÿRߦCYoíúúîú߯o…››ûü&&ÿúÞ¯›±±›öìääîääÞ±±±±òìääîäúÞŠ››±±íìúÿß“±±±±èüÿß»±±›±ãü&ÿ&ßá±±››Þü&ÿ&&ßÕ››››×ü&&ÿ&&߀››››Ñü<<ÿ&&Ïö››››Ëü&&ÿ&&ÏK›››…Äü&&ÿ<<¿™›o…›¾ü<<ÿ<<¿/››…›¹ü<<ÿ<<¿j…›……´ü&&ÿ&&ÏI›…oo°üRRÿRRßg……››¬ü<<ÿ&<ïL……o…ªü ±±››°Öìì: ›………°äìÿììÿì5 ……oo°ô0 YYYC°ù, CCYY°ë( CCCC°Ñðì$ CCYo°Åì YYCC°Ê CCYY°ÔðììÿÖ YCCC°ÏÖÿÖÀÿÀ Yooo°Ã”ÿ”~ÿh …››±°¼&ÿúîä ÇÝó±ÁÎîιî5Jv¸±¼aîÝÝ›úR"¿C³§ZÝÀÌhý<ÆJD¸µ‹SÌSSÌSú\;;Uã´z”Ü›íKöLŒÆ#¿ä±¹þ<”ÿìô…À¿ -CCðü”~ÿ”ª¿Íoo…›íüÀªÿ”~¿ô››››éühhÿhhÏ ›››±äühhÿhhÏ ±››…àüh”ÿªÀ¿÷…o……ÛüÀÀÿÖÖ¿ð…››…ÖüÖÀÿªÀÏ……››ÒüÀÀÿÀÀÏF››››ÎüÀÀÿªÀÏW…oo…ËüÀÖÿÖÖÏK………oÇüÀÀÿÖÖÏeoo……ÃüììÿÖÀÏÑ…………¿üÀÀÿÀÀßb………oºüÀÖÿÖÖßã…………µüÖÖÿÖìï---àX-C--à'è----à º---à3‘àCn---àZVC---àšGàõ>ð&6----ð--àª!à_-àH----àXû ---àtî --à—ä ----àÂÛ CCCCàçÓ CCCCàõÌ CCCCàéÇ CYYYàÐÁ ooo…฼ …………ࣵ …›››à•ìÿìÖÿÖ¯ ››››àÖÿÖÖÿÖ© ››±±àšÖÿÀÀÿÀ¢ ±±±±à¨ÀÿªªÿÀœ ±±±±à±ªÿªªÿª— ±±±Çà±ÀÿªªÿÀ‘ ±±±›àªÖÿÖÖŒ ›………à£ì‡ ooYYàœƒ YYYCà•~ CC--à•z à•-v à---q à…----m àp----j àa----f àd----d àw-b à•ìÿì^ -Coà±ÖÿÖÀÿ”[ o………à¿~ÿhhÿRX ……o…à»Rÿ&ïäS …›Ç á¬îKóÝ›N`¸!<¿âžDÍì”Ì=J=-°Cvä£ÌÌSFM¢ŒDv4ä³ÀÜZ îC=°ÕÎ á¶&ÿ~Ö@ Yð”hï“Co…›>ýR<ÿRRïf±ÇÝÝ;ýRRÿ<&ïaóó  9ýÿ&ï£óóóó6ý&&ÿ<<ÿ ó ó4ýRRÿRhÿcóóóó0ýhhÿhhÿ‰ óóó,ýhhÿh~ÿ‰óóóÝ(ý~~ÿ~~ÿ\óóóÝ$ý~~ÿ~~ïóóóÝÝ ý”~ÿ~”ï]ÝóóÝý””ÿ””ßãóÝÝóý””ÿ””ßÒóÝÝóý””ÿ””ïHóÝÝÝý””ÿ””ÿÝÝÝÝý””ÿ””ÝÝóÝ ý””ÿ””ÝÝÝÝ ý””ÿ””‘ÝÝÝÝý””ÿ””¦ÝÝÝÝý””ÿ””TóóÝÝ2ý””ÿ””ÓÝÝÝÝaý~”ÿ””eÝÝÝݦý””ÿ””-ÝÝÝÝúý””ÿ””2ÝÝÝÝNþ””ÿ””jÝÝÝÝ™þ””ÿ””ÌÝÝÝÝÖþ””ÿ””8ÝÝÝÝ ÿ””ÿ””…ÝÝÝÝ3ÿ””ÿ””¤ÝÝÇÇ[ÿ~~ÿ~~¤ÝÇÝÝ„ÿ~~ÿ~~“ÝÇÇÇ­ÿ~~ÿ~~~ÇÇÇÇÖÿ~~ÿ~~eDZ±›üÿ~~ÿ~~K››››ð~~ÿ””8››››:ð””ÿ””3›››…Qð””ÿ””:…ooobðªªÿªªFoooYlðÀÀÿÀÀMYYCCpðÖÖÿÖìKC---oðììÿìì:---h]ýLè7Ö----©û--IÕ---ðϬ---ðv------ðx--Q-ðÊ----!-----öq---CÏCCCC²CCCCœICCCC‹ðüCYCC}ð³----pð‹----bð----Sð†----Dð™----6ð³---)ðÊ----ðÖ---ðÖ-- +----ðÍ----ð¿ú ----ðªò ---ð’ë -CCCð{ã CCCCðcÜ YYYYðQÔ YoooðBðìÌ ……››ð4ìÿìÖÿÖÆ ››››ð)ÖÿÖÖÿÖ¾ ›››±ðÀÿÀÀÿÀ¸ ››››ðÀÿÀªÿª± ››››ðªÿªªÿª« ››››ð +ªÿÀÀÿÖ¥ ››……ðÖÿÖìž oYYCàú™ YCCCàó” C--àìŽ àéˆ ðììïçƒýììÿììïÞ~ýììÿììïÍyýììÿììï¶uýìÖÿÖÖïœqýÖÖÿÀÖï‰nýÖÖÿÖìï‚ìÿÖÀÿªjýìà‡ªÿ””ÿ~f Coooà“hÿhRÿRb oYYCàžRÿRRÿ<\ -à£ïÎwîV C± ážÝÝpÍ~PŒú!}ã‰û»£a»KL=›Dvväpw»£ÌÀGM`4›¿â]pí £þ&D¸Ý-Àï]hÿÖ-Býh&ïúäîmCoo…>íúúîúú›±Ç<íúúîúäî‰ÇDZ±9íäúîúúîŽÇÇÇÇ5ýÿ&&ï•ÇÇÇÇ2ý&&ÿ&&ï¨ÇÇÇÇ.ý<<ÿRRïͱ±±±)ýRRÿRRÿÇÇÇÇ&ýRRÿRRÿEÇÇ›±!ýRRÿR<ÿ_±ÇÇÇýRRÿRRÿÇDZ±ýRRÿRRï"±±±±ýRRÿRRß±±±±ýRRÿRRϼ››±›ýRhÿRhßT±±››ýhRÿRR›±±ýRRÿRRÿ®±±››ýRRÿRRu››±›ýhRÿRhر›››4ýhhÿhhä…›››fýhhÿh~ ››››°ýhhÿhh!›››±þhhÿhhÿ¥±›±±aþhhÿhhÿX±›››¯þhhÿhhÿS±›››íþhhÿhhÿ„›››› ÿhhÿhhÿÔ››››KÿhhÿRR*››››sÿRRÿRRx›››››ÿRRÿRR®››››ÅÿRRÿRR¹››››íÿRRÿRR”››……ðRRÿRRRoooo3ðRRÿRRoooYPðRRÿRRÿßoooYgðR<ÿRRÿÈYYC-xðRRÿhRÿÆ----‚ðhhÿhhÿ͇ð~~ÿ~~ÿÔ…ð~~ÿ””ÿÆ}ð””ÿ”ªÿ—ìpðÀÀÿÀÀÿEðìðì]ðÀÀÿÀÀïÍðììFðÖÖÿÖìïLìÿììÿì*ðììÿììïìÿììðììÿììïJðìäÿììÿììï¬ììºÿììÿììïìŒÿììÿììïóZÿììÿììïÛ'ÿììÿììïªöþììÿììïaÊþììÿììï¨þììÿììßìþììÿììßã€þììÿìÖßèrþììÿìÖßêeþÖÖÿÖÖßåVþÖÖÿÖìßãFþììÿììßá7þììÿììß×'þììÿììßÉðììþìд þììÿììߤìÿìþýììÿììߘìÿìðìô ðìÐìÿìðìê ЇìÿìÖÿÖâ ЀÖÿÖìÿìØ ÐyìÿììÿìÐ ÐnðìÇ ÐYìÿì¾ -CÐ5ÖÿÖÖÿÀ¶ CCYYЪÿª”ÿ”® ooooÀí”ÿ”~ÿ~§ ooooÀØ~ÿ~~ÿ~  ooooÀÎ~ÿ~hÿh˜ YoooÀÎ~ÿhhÿh‘ ooooÀÑ~ÿ~”ÿ”‹ oYYCÀΔÿ””ÿ”„ CCC-ÀʪÿªÖÿÀ~ -ÀÇÖÿÖÖÿìx ÀÇÖÿÖìÿìr ìÏÀìÿìlýììÿìÖÏ®hýÖÖÿÖìÏ‘býÖÖÿÀÀÏqðì^ýÖÀÿÖìÏ`ðìYýìÖÿÖÀÏeUýÀÀÿÀÀÏsðììÿÖQýÖÖÿììÏÖÿÖÀÿÀLýììÿìÀ|ªÿ””ÿ”H --Àq~ÿh<ÿ&D -CCYÀc&ÿ&&ÿ&> YYYYÀ[ïä¹îa8 …±óJÁ` ÞÇpÝ3¸<"©-Ã`ÀÌSÌ-=ÆD`vÄRÌ'hÜ)M`4°ëÂB›íK¹þ&&úoÀ?~ÿÖ-$ý”Rÿ&ÏPCYoo"ý&&ÿ&&Ïeo……›ý&ïúúÎn››››íúúþ&Ïe…………ý&<ÿ<<ÏP››…›ýRRÿRRÏ?›……… ýRRÿRRÏD…oo…ýhhÿhhÏeoo…oýhhÿhhÏ…oooýühhÿh~Ï‘o…o…øühhÿhhÏ………oôühRÿhhϤooooðü~~ÿ~~ßo……›ìühhÿhhß²›…ooèühhÿ~~ï'ooooäü~~ÿ~~ïyooooáü~”ÿ””ï»ooooÝü”~ÿ~~ïåooooÞü~~ÿ”~ïå…………çü~hÿhhïÆ…oooÿü~”ÿ””ï±o…oo+ý”~ÿ~”ï³……ooký””ÿ””ï¿oooo·ý””ÿ””ïËo…o…þ””ÿ””ïÞooooFþ””ÿ””ïü››……~þ~”ÿ””ÿ………o­þ~~ÿ~~ÿ&……oo×þ~”ÿ””ÿ0ooooÿþ””ÿ””ÿ4o……›'ÿ~~ÿ~~ÿ4››››Oÿ””ÿªªÿ$››››vÿªªÿÀÀÿ……›››ÿÖÖÿÀÀïÞ…›››½ÿª”ÿ”ªï¯›……oÛÿªªÿÀÀï…ooooõÿÀÀÿÖÖïtYYYYðììÿÖìïŽCC-CðììàÍ---ðð>---CðCCCCà½ùCCYYàOâYoooÐöÇooooж¥ooooЀooooÐŒWooooй)ooooÐáûooooÐÐÎoooYЦ¨YYCCЯ----‹CCCCÐÿ--xCCCCàQlYYYYàf---bYCC-à:---WCCCYàKYYYYÐÜ>CYYYÐÇ/YCCCй!CCCYЯYYYYÐÀYYYYÐìû YYYoàñ YYooà0é oYooà:â ooooà:Ü ………›à.Õ ››››àðìÏ ±±±±ÐñìÿÖÖÿÖÈ ÇÇÇÝÐÒÖÿÖÀÿªÀ ÇÇÇÇÐÀªÿª”ÿ”¸ ÝÝÝÝжªÿ””ÿª² ÝÝÝÝж”ÿ””ÿ”¬ ÇÇÇÝÐÉ”ÿ””ÿ”¦ ÝÝÝÝÐê”ÿ”ÀÿÀ¢ ݱ±±à ÖÿÖÖÿÖœ ±›››à"ìÿììÿì˜ ……ooà)” oooYà, YCC-à,Œ ----à,Š -à,† à.„ à<‚ àL€ -àS~ ----àOðì| C-CYàJÖÿÖÖÿÀy o›››àS”ÿhhÿhv ›±±›àmRÿ<<ÿ&r ±±±Ýà…úîÎî5m JŒâŒÝÝ›.Íìh-}ë2oòã…”Ì='Ì'eM`¢D¸¢ä{=Ì~Ý›aMv4o}ârKî¹&ÿ”^¢ÝCìïfÖCoZý”hÿRRïV…›±ÇVýhhÿhhïXÇÇÝÝTýR<ÿ&<ïŒóÝÝÝPý<<ÿRRïìÝÝÇÝLýhhÿh~ÿLÝÝÝÝHý~~ÿ””ÿ}ÝÝÝÝDý~”ÿ””ÿvÝÝÝÝ?ý””ÿ””ÿLÝÝÝÝ:ý””ÿ””ïþÝÝÝÝ4ý””ÿ””ïÝÝÝÝ0ý””ÿª”ï"ÝÝÝÝ,ý””ÿ”ªßöÝÝÝÇ(ýªªÿªªï>ÝÝÝÝ&ýªªÿªªïîÝÝÝÝ$ýªªÿªªÿÏÇÝÝÝ"ýªªÿªª©ÝÝÇÝ"ýªªÿªªMÝÝÝÝ"ýªªÿªª˜ÝÝÝÝ(ýªªÿªª|ÝÝÝÝ9ýªªÿªªÝÇÝÇ\ýªªÿªª°ÇÇÝÝ—ýªªÿªªeÝÝÝÝäýªªÿ”ªUÝÝÝÝ8þ””ÿ”ª}ÝÝÇLjþªªÿªªÑÇÝÇÝÌþª”ÿ””6ÝÝÇÇÿªªÿ””…ÇÇÝÝ2ÿ””ÿ””²ÇÇÇÇ\ÿ””ÿ””¹ÇÇÇÇ…ÿ””ÿ””«ÇÇÇǯÿ””ÿ””ŒÇDZÇÙÿ~~ÿ~~iÇDZ›ð”~ÿ””R››››%ð””ÿ””O››››Eð””ÿ””b…………^ð””ÿªªw……oorðªªÿªÀ…oYYY~ðÀÀÿÀÀ~YYCC†ðÖÖÿÖìgCC--‡ðììÿììH----ƒ1-z%kV-:----ØCCCC÷CC--4Í----ðÊ--¡---ðv----r--ðh----Cð³-----/---Cî›CCC-ÎÀCCYC¶ CCC-¤R-C--”ðùCC-C†ð®----xð----iðo----Zð{----Kðž--=-ðÊ2---ðë'---ð÷--ðò--ðß--ðÆ----ð¥þ ----ð‚÷ CC-Cðfî CCCYðN-æ YYYYð;Þ Yoo…ð0ìÿì× ……››ð&ÖÿÖÖÿÖÐ ››››ð$ÖÿÖÀÿÖÊ ››››ð"ÀÿÀÀÿÀÄ ››››ðªÿª”ÿ”¾ ››››ð”ÿ””ÿª¹ ››››ðÀÿÖÖÿÖ´ ……ooðÖÿÖìÿì® YYCCàú§ CCCCàð¡ C--àçš àâ• àÛ-- àÍ--‹ à¸---† àž-‚ à‡ ày| à~ìÿÖÖÿÀx -Yoàªÿ””ÿ”t ›±››à£~ÿhhÿ~p ›…oYà±hÿhhÿ&j C--Yà¯úî£KÞód …Ý5¢áž›Ý.ÀÌ=^-&“2-Æã‚Ï»»£ZMJ¢D¸ŒäfåË=ìÜ›VMJÆ3úáS5î¹&ÿ”SYðì”ïSÖ-YPýR&ÿ&ïfo…›±Mý&&ÿ&&ï{±±ÇÇJý&ÿïŒÇÇÇÇFý&&ÿ&&ïÝÇÝÝBý<<ÿR<ï•ÝÝÝÝ>ýRRÿRRïªÝÇÇÇ:ýRRÿRhïÐÇÇÇÇ6ýhhÿRRÿDZDZ3ýRRÿRRÿG±±±›.ýRRÿRRÿc±±±±*ýRRÿRRïõ±›››&ýR<ÿRRßÿ››››"ýRRÿRRß››››ýRRÿ…ooo¹ÿ””ÿ””ÿ2ooooÜÿ””ÿ””ÿooooüÿ””ÿ””ÿoYYYð””ÿªªïéYC--*ðªªÿªªïì----9ðÀÀÿÀÖÿAðÖìÿììÿ"Cð"@ð +7àçðì'àÆðì-à¡ðì÷--CCàmìÿììÖCCYCà)°CCCCÐã…CCCCЯXCCCCП)CCCCжùCC--ÐñÎ----àA­----à“–C--Cà͈---à×~à£t---àSj--à ]-C--ÐêO----ÐïACCCCà4CCCCàE'CCCCà€CCCCà¯---Cà¿ì +CCCCà¯ìÿìCCCCàŽìÿììÿìû CCCYàtìÿììÿìô ooooàaìÿììÿìî ooooàSðììÿìè o……›àOìÿÖÖÿÖá ›››±àVÖÿÀÀÿªÚ ±±±±àmªÿ””ÿ”Ó ±±ÇÇà…”ÿ””ÿ”Ì ÇDZ±à”ÿ””ÿ”Ç ±±±±à“”ÿ””ÿ” ±±ÇÇà“”ÿªªÿÀ½ ±±±›à“ÀÿÖÖÿÖ¸ ›………à•Öÿììÿì³ ooooàðì® oYYCàŽª CCC-àŽ¥ àŽ¡ à‡ à{š àm— àm“ à€ àšŒ -à¯ìÿÖÖÿÀˆ CY……à¸Àÿª”ÿhƒ ››››à³hÿhRÿR~ ›………à¥<ÿ&úî¹y ›±Ý5áKî ±ÝZt¢"}ã€Í”=Ìn=…òC`Œä{Ì=Ì”jMŒvD4Æã‰.ÝÝwîúg-ëúoàœhÿÀ-d ªÿhRï±Yo…›aý<<ÿRRï½±±ÝÝ^ýRRÿ<&ïÄÝÝÝÝZý&&ÿ&<ïÍÝÝÝÝUýRRÿhhïÞÝÝÝÝQýhhÿ~hïúóÝÝÝMý~~ÿ~~ÿ$ÝÝÝÝHý~~ÿ~~ÿUÝÝÝÝEý””ÿ””ÿNÝÝÝÝ@ý””ÿ””ï×ÝÝÝÝ<ý””ÿ””ï ÇÝÝÝ9ý””ÿ””ßyÝÝÝÇ6ý””ÿ””ßšÝÇÇÇ4ý””ÿ””ïfÇÇÝÇ2ý””ÿ””ÿxÇÇÇÇ/ý””ÿ””uÇÇÝÝ,ý””ÿ””3ÇÇÇÇ,ý””ÿ””šÇDZ±3ý””ÿ””“±›±±Cý””ÿ””1±±±±fý””ÿ””«ÇDZ± ý””ÿ””G±±±±ìý””ÿ””#DZ±±Bþ””ÿ””B±±±±’þ””ÿ””’±±±±Øþ””ÿ””±±±±ÿ”~ÿ””n±±±±Cÿ””ÿ”~¾±±±±oÿ~~ÿ~~Ú±±±›šÿ~~ÿ~~››››Äÿ~~ÿ~~“›±››îÿ~~ÿ~~g››››ð~hÿhhO››……=ðh~ÿ~~D…ooo^ð~~ÿ~~Ao…oozð~~ÿ””MoYYYð””ÿ””bYCYCžð”ªÿªªn----¨ðÀÀÿÀÀe---«ðÀÖÿÖìM©ðììÿìì8 (“€fÏH--%----ý--ð¸Ñ----ð£ð¸r--C\---†----ò----Øs----Ä6----´ðò----¥ðÁ---–ð®†ð¬-vð±fðÁXðØLðëAðð7ðë.ðä&ðØðÃð§ð‰ìÿìðì---ðmìþ -CCCðUö CCCCðBðììÿìî YYooð2ÖÿÖÀÿÀæ …………ð+Àÿªªÿªà …o……ð&”ÿ””ÿ”Ù ›››…ð$”ÿ””ÿ~Ò ›……oð”ÿ”~ÿ~Ì o………ð~ÿ~~ÿ”Å o…ooð”ÿªªÿÀ¾ YYCCðÀÿÀÖÿÖ¸ C---à÷ÖÿÖÖÿÖ² ---àîÖÿÖÖÿì¬ àé§ ìÿììïé¢ýÖÖÿÀÀïåýÀÀÿÀÀïÙ˜ýÀÀÿÀÀïÄ”ýÀÀÿÀÀïªýÀÀÿÀÀï—ŒýÀÀÿÀÀïŒìÿÖÖÿªˆýÖÖÿìàŽªÿ”~ÿ~… CYàš~ÿhRÿ<€ oYYCà¨&ÿ&<ÿ¨ðL™ð\ŠðhyðciðNZð4ðììÿìLðìÿìì@ðìÿììÿì4ðÖÿììÿÖ*ð"ÖÿÖÖÿì"ð0ìÿììÿìð9ìÿÖÖÿÖð9ÖÿÖÖÿÖ-ð"ÖÿÖÖÿìþ ---CàúÖÿìÖÿÖô C--CàÆÖÿÖÖÿÖê CCCYà“ÖÿÀªÿ”á ooooàf”ÿ”~ÿ”Ø ooooàC~ÿh~ÿhÏ o………à.hÿhhÿhÇ …oooà%hÿhhÿh¿ ooooà"hÿhhÿh¸ ooooàhÿh~ÿ”± YYCCà”ÿ””ÿÀª CCC-àªÿÀÀÿÖ¤ -ÐêÖÿÖÀÿÖž ÐÒÖÿììÿì˜ýììÿììß»ììÿì“ýÖÖÿÖìߨìÿììÿìŒýììÿÖÖߘðììÿì‡ýÖÖÿÖÀ߃‚ýÀÀÿÀÀßkì}ýÀÀÿÀÀßTðìyýÖÖÿÖÖßAðìÖÿÖtýÖÖÿÖìß3Àÿª”ÿ”pýì-Ð3hÿhhÿRj YYYYÐA<ÿ&<ÿðhhÿhhï³-Pðhhÿh~ï¸]ð””ÿ””ï¬cðª”ÿªÀï‡ðìbðªªÿªÀïJìÿììÿì]ðÀÀÿÀÀïÖÿÖÖÿÖRðÖÖÿÖìßÒÖÿÖÖÿÖBðÖìÿìйÀÿÖÖÿÖ+ÐÀÿÖÀÿÖÐkÖÿÖÖÿÖïÐHÖÿÖÖÿÖÉÐ`ÖÿÖÖÿÖžКÖÿÖÖÿÖoÐÄÖÿÖÖÿì=ÐÂìÿììÿì СìÿììÞÐ|¹Ð]ìì ÐDŽÐ*ìÿìì‚ÐxÐðìjÐìÿÖìÿì\Ð'ÖÿÖÖÿÖNÐ8ìÿììÿÖ=Ð?ÖÿÖÖÿÖ.Ð<ÖÿÖÖÿÖ Ð5ÖÿÀÖÿÖÐ.ÖÿÖÖÿÖÐ*ÖÿÖÀÿÀþ -Ð#ÀÿÀÖÿÖö -ÐÀÿÀÀÿÀï --CCÐÀÿÖÖÿÖç CCCCÐÖÿÖÖÿÀà CCCYÐÖÿÀÀÿÀØ ooo…Ъÿ””ÿ~Ð ››››Ð ~ÿhhÿhÊ ›››±Àùhÿhhÿh ±±±±ÀíhÿhhÿR¼ ±±±±ÀãRÿRRÿh´ ±±±±ÀßRÿhhÿh® ±±±›ÀÜ~ÿ~~ÿ~§ ››……Àá”ÿ””ÿª¢ …oooÀæÀÿÀÀÿÖœ YYCCÀêÀÿÖÖÿÖ— CCCCÀêÖÿÖÖÿÖ CC-ÀãÖÿÖÖÿÖŒ ÀØìÿììÿì† ÀÊìÿììÿì‚ ÀÃìÿììÿì~ ÀÅìÿììÿìz ÀÌììv ÀÌìÿìr -CÀÀðìÖÿÖn CYo…À¼Öÿª”ÿ”j ±±ÇÇÀÎ~ÿhRÿhd ÝóóóÀæRÿýªªÿÀÀß ÇÇÇÇ:ýÀÀÿÀÖß5±Ç±±6ýÖÖÿììßb±±±›2ýììÿìì߃±›±±/ýìÖÿÖìß~±±±±,ýÖÖÿÖÖßnÇDZ±(ýÖÖÿÖÖß‘±ÇDZ$ýÖÖÿÖÖï DZ±±"ýÖÖÿÖìï»›±±±ýììÿììÿo±±›±ýììÿìì±±±±ýÖÖÿÖÖ±±±±ýÖÖÿÖÖϱ›±±ýÖÖÿÖÖß±›±±ýÖÖÿÖÖ²±±±› ýÖÖÿÖÖ}›±±±6ýÖÖÿÖÖe±±±›^ýÖÖÿÖÀz±›››œýÖÖÿÖÖ§››››êýÖÖÿÖÖÚ››››:þÖÖÿÖÖ››››†þÖÖÿÖÀK››››ÆþÀÀÿÀÀl›››±ýþÀÀÿÀÀn›±±›*ÿÀÀÿÀÀ[±›››SÿÀÀÿªªF›±››{ÿªªÿª”6››››¤ÿªªÿªª6››››Ëÿªªÿªª?››……ñÿªªÿªªR……ooðªªÿªªboooo0ðÀÀÿÀÀloYCCGðÀÀÿÀÖsCCC-XðÖÖÿììu----bðììp---fbcOZ--8K--CC!7CCCCCCCCßüYYYY²ÖYCCCu«CCCC}CCCCð¬-NCCCCðm CCCCð”öCCCC -ÖCCCC¿CCCC²----®CCCC°--- CCCC-’CCCCK‚CCCCð÷rCCCCðªbCCCCð„SCCCCð‹ECCCCð±9CCCCðä/CCCC&CCCC-CCCC(CCCC +CCCCðÔCCCCð™ý CCCCðfõ CCCCðBì CYYYð2æ YYooð0Þ ooo…ð9Ø ……››ðEðìÖÿÖÑ ›±±±ðLÖÿÖÀÿÀË ±±±±ðLÀÿª”ÿ”Å ±±±Çð@”ÿ””ÿ”¾ ±±±±ð-”ÿ””ÿ”¸ ±›››ð”ÿ””ÿ”± ±›››ðªÿÀÖÿÀ« ››…oàóÖÿÖÖÿÖ¦ ooooàéìÿì  oooYàåìÿìš YCCCàâ• --àâ àÞŒ àÔˆ àÆ… à³ à¡~ à“z à•ìÿìÖÿÀw -Coà£Àÿ””ÿ”s …›±›à¶~ÿhhÿhn ››…oàÂhÿhRÿ&j oYCYà½úîÎaî d …Ç5¢á¯ÇÝpÍ~^-}2›ã•û»¹£»£ZMvD¢ŒäwåË'ÀÜpVM`ò3CRâ] î£ÿhT`›ÀïXÖ-YPý~Rÿ&<ïpo…›±Mý±››±6ýªªÿªªÿB±±››3ýªªÿªªï¬±±±±/ýªªÿªªß¨›››±,ýªªÿªªÏñ›±±±*ýªªÿªªß,››››(ýªªÿªªï)››››'ýªªÿªÀÿN››››&ýÀÀÿªª6››››&ýªªÿªÀÊ››››,ýÀªÿªª ›››±?ýªªÿªªí››››fýªªÿªª†››››¥ýªªÿÀª ››››öýªªÿªªÿ¿››››Nþªªÿªªÿº››››Ÿþªªÿªªÿî››››äþªªÿªª;››››ÿªªÿªª››››Mÿªªÿ””Ú››››wÿ””ÿ””›…››¡ÿ””ÿ””!›………Ëÿ””ÿ””›………öÿ”~ÿ””èoooo ð””ÿª”ÀooooGð””ÿ””¤oooojð””ÿ””YYYC†ð”~ÿ””©CC--œð””ÿªª¼----ªðªªÿÀÀÊ---²ðÀÀÿÀÀÈ´ðÖÖÿÖì°¯ðììÿìì†ìÿì¥PðÖìÿì”ìÿÖÖÿÖ€ðÊìÿììÿÖeðtìÿììÿìEð"ìðì ðìì÷ð&Êðo™ð£fð¬3ð’ðmÝðEÂð±àé¤àË—àŠàËzàÔjàÙZàÙJàÔ<àÒììÿì/àËìÿììÿì%àÂìÿììÿÖà³ìÿìÖÿÖàžÖÿìÖÿÖ +à€Öÿìðìà]ìÿÖÖÿÖù -à:ÖÿÖÖÿÖð ----àÖÿÖÖÿÀè CCCCÐúÖÿÖÖÿÖà CCCCÐáÀÿÀÖÿÀØ CYYYÐɪÿ””ÿ~Ï oo…›Ð»~ÿhhÿRÇ ›››…дRÿRRÿh¿ ……ooвhÿ~~ÿ”¸ oYYCЫ”ÿ””ÿ”± CCCCС”ÿ””ÿ”ª CCCCЖ”ÿ””ÿª¤ CCCCÐ…ªÿªªÿÀž CCC-ÐrÀÿÀÖÿÖ˜ ---Ð`ÖÿÖÖÿÖ‘ ÐOÖÿììÿìŒ Ð?ìðì† Ð3ìÿììÿì ðììß'ììÿì| Ðìÿìx ìßtýììÿììß oýììÿììßjýììÿììÏíìÿÖeýììÿìÀÎÖÿª”ÿ”_ CÀ·”ÿ~hÿhY YoooÀ¹<ÿ<<ÿ-}3…ÜþSÌ''ÌS:MDÜæªÜ.ÇíK6=…¿Î Á–Îþ&~ÿÖ4 oðÀ~ÏŠ-CC1ýR<ÿýRRÿhhïÙÇÇÇÝ:ýhhÿhhïÔÝÇÇÇ6ýh~ÿ~~ïàDZ±Ç2ý~~ÿ~~ÿÇÇÇÇ/ý~~ÿ~~ÿIÇÇDZ+ý~~ÿ~~ÿ‚DZDZ&ý~”ÿ””ÿm±±±Ç"ý~”ÿ””ï×ÇÇÇÇý””ÿ””ßøDZ››ý””ÿ””ßp››››ý””ÿ””߶››››ý””ÿ””ïž››››ý””ÿ””ÿ ››››ý””ÿ””Y››››"ý””ÿ””¾››››:ý””ÿ””Ý››››hý””ÿ””¾››››°ý””ÿ””n››››þ””ÿ””››››_þ””ÿ””ÿâ›…››®þ””ÿ””ÿâ…›››îþ””ÿ”” +››››#ÿ””ÿ””D››››Nÿ””ÿ~~››››xÿ~~ÿ~~Ø››››¢ÿ~~ÿ~~››››Íÿ~~ÿ~~,›››…÷ÿ~~ÿ~~#ooooð~~ÿ~~ooooBðh~ÿ~~ßoooYbð~~ÿ~~ÃooCY|ð~”ÿ””·----ð””ÿ”ª¼---œðÀªÿÀÀÅ¢ðÀÀÿÀÀÊ¢ðÀÖÿììÃðììÿìì©ðììÿì’sìÿìÖÿì‚ìÿìÖÿÖnð±ÖÿÖìÿìRðaìÿììÿì3ðcìÿììÿìð±ìÿìç-ðììÿì¹K‰UV*$ðäõð Îð}±ðxžð‚’ð†ð™yð£jð£[ð‹Jðjðìì:--ðQìðì+ðLìÿìðXìÿììÿìðcììÿì ðfìÿÖìÿÖð_ìÿÖìÿìû ðLÖÿÖÖÿÖò ð+ÖÿìÖÿÖé -àúìÿÖìÿÖà ----àÄìÿììÿìÖ CC-Cà•ÖÿÖÖÿÖÌ CC--àpÖÿÀªÿ”à CCCCàV”ÿ~~ÿhº CYCCàEhÿhhÿh³ CCCCà --Ð%&ïú¹î6 -o±Ð*Kî ±Ýp0 väRÒ#Í”'¼û*-ÕY3ÆÔ å»åÌS&Mò3ÆYÃæÝ›Kî¹"-“¢Ç-ÀÅÿhªÿìýÀhÿ&ϼ--íúúþ&ÏÊYoo…ý&&ÿúÎè…›……íúúîúúÞ………oýÿ&&ß?…oo… ý<<ÿ&<ßi…oo…ýRRÿRRßro……oÿüRRÿRRßHoo…oúüRRÿRRß…oooõüRRÿhhϹooooðühhÿhhÏjooo…ìühhÿhhÏ#………oèühhÿhhÏ/ooooæüh~ÿ~~Ï·o…ooâü~hÿhhß‘ooooÞü~~ÿ~~ï_ooooÜü~~ÿ~~ïçooooÚü~~ÿ~~ÿ)ooooßü~~ÿ~~ÿ7…………ðü””ÿªªÿ…………ýÀÀÿÀÀïÄ……›…NýÀÀÿÀªïd››……šýªªÿªªï)……ooìýªªÿªÀï0oooo9þÀÀÿÀÀïm……››zþªªÿªªï¿›o……¯þªªÿª”ÿ +o………Ûþ””ÿ””ÿ>ooooÿ””ÿªªÿQooo…*ÿª”ÿ””ÿG…oooQÿ””ÿ””ÿ)oooozÿ””ÿ~~ÿoooo£ÿ~~ÿ~~ïìoYYYÇÿ~~ÿ~”ïàYYYCèÿ””ÿ””ïàC-C-ð””ÿ””ïâC---ð””ÿ””ïà--(ð””ÿªªïÒ2ðªÀÿÀÀï¸5ðÖÖÿÖìïŽðì3ðÖìÿììïaìÿÖÖÿÖ*à:ÖÿÖÖÿÖàìÿÖÖÿÖ +ÐñÖÿÀÖÿÖò--СÖÿÀÀÿÖÕ---CÐAÀÿÀÀÿÀ³CCCCÐÀÿÖÖÿÖŒCC--Ð:ÖÿìÖÿÖ`--ЇÖÿÖÖÿÖ1--CCÐÀìÿÖÖÿÖÿC---ÐÎÖÿìÖÿÖÎCCC-ÐÂìÿììÿì£---ШìÿÖìÿì‚-CC-Ð…Öÿììk-ÐVðì]Ð#SÀýðììÿìG--ÀñÖÿÖÖÿÖ:CCCCÀýìÿììÿì+---ÐÖÿÖÖÿÖ--Ð#ìÿììÿì ÐÖÿÖÖÿÖü -ÐÖÿÖÀÿÖî -CCCÀýÀÿÀÀÿÀá CCC-ÀûÀÿÖÖÿÖÖ ----ÀùÖÿÖÖÿÖÎ ----ÀûÖÿÖÖÿÖÆ CCCCÐÖÿÖÀÿÀ¿ YYYYÐÖÿÖÖÿÖ¹ YoooÐÖÿÖÖÿÖ³ oo……Ð ÖÿÖÖÿÖ¬ ……››ÀïÀÿª”ÿ”¤ ±±±±ÀØ”ÿ~”ÿ~ž ±±±±ÀÌ~ÿhhÿh˜ ÇÇÝÇÀÓhÿhhÿh’ ÇÇÇÇÀæRÿRRÿRŒ ÝÝÝÝÐRÿRRÿh‡ ÝÝÝÝÐhÿhhÿ~ƒ DZ±±Ð,~ÿ””ÿ”~ ››……Ð<”ÿ”ªÿªz ooooÐFªÿÀÀÿÖw YYCCÐKÖÿÖÖÿÖs CC--ÐHÖÿÖÖÿÖp ÐFÖÿÖÖÿÖl ÐMÖÿÖÖÿÖj ÐYÖÿÖÖÿÖh Ðgìÿììÿìg Ðnìÿììÿìf ÐrÖÿÖÖÿÖf --ÐyÀÿª”ÿ”e -CCoБ~ÿhhÿRc …›››Ð¹<ÿ&&ÿ&a ±±±±ÐêïúúîÎ^ ±ÇÝ á ¹îwÞÇZJ¢úhâLpÝ.ÀÌ~X-ëo3ÜJäh'ÌÌVMŒ¸D¸ŒähS̪DÝÝTMJ°#ÕäáZwîä&ÿ”S oÖïQÖ-Qý”~ÿh~ïVCCYoPý~”ÿ”~ïfoo……LýhRÿRR›››JýRhÿh~›››Fý~”ÿ””ïÒ››››Cýªªÿªªÿ ››››?ýªªÿÀÀÿ9…›››;ýÀÀÿÀÀÿ9››››6ýÀÀÿÀªÿ›…››1ýÀÀÿÀÀ福……›,ýÀÀÿÀÀï_……›…(ýÀÀÿÀÀïd›………$ýÀÀÿÀÀïÐ……o…"ýÀÀÿÀÀÿ”…………ýÀÀÿÀÀz…………ýÀÀÿÀÀ?…………ýÀÀÿÀÀ©››…›ýÀÀÿÀÀ«››››ýÀÀÿÀÀi››››,ýÀÀÿÀÀ›…››LýÀÀÿÀÀä››……ƒýÀÀÿÀÀÊ…………ÐýÀÀÿÀÀÅ…o……&þÀÀÿÀÀä…›››yþÀÀÿªª/››››¾þªªÿªªŒ››››õþªªÿªªÓ››››!ÿªªÿªªì›…o…Hÿªªÿªªê›…›omÿªªÿ””ã……›…•ÿª”ÿ””×…………»ÿ””ÿ””Ìooooãÿª”ÿ””ÅooYYð””ÿªªÇYYYo%ðªªÿªªÐoYYC>ðªªÿÀÀÕCC--PðÀÀÿÀÖÓ---]ðÖÖÿÖìÌbðììÿììÂa²Y¤L–ðììÿì:----…ìÿìðì"--CCiìÿììCCCC:ìÿììÿìåCCCCëìÿììÿì¾YYYYq“CCCCðÑeCCCCðc7CCCCðžCCCC„Þ----[¼CCCCŒ¤C-C-8’CCC-Ö„----‹w----6iCCCCðÔZCCCCð™KC-CCðª<CCCCðéìÿì.CCCC&"CCCCIìCCCCYCCCC^ìÿììCCCCPìÿìCCCC-ìÿììÿìø CCCCðüìÿììÿìï CCCCðÔìÿìÖÿÖç CCYYðºìÿììÿìÞ YYYCð®ìÿììÿì× CCCCð§ìÿììÿìÐ CYYoð ìÿìÖÿÖÉ ooooð™ìÿììÿì oo……ð—ìÿìì¼ ………›ð’ìÿìÖÿÖ´ ››±±ð‰ÀÿÀªÿª® ±±±±ð{ªÿªªÿ”§ ±±±±ðj”ÿ””ÿ”¡ ±Ç±±ð\”ÿ”ªÿ”š ±›››ðS”ÿ””ÿ”” ›±±±ðG”ÿ””ÿ” ±±±›ð@”ÿªÀÿÀŠ ›…ooð9ÖÿÖÖÿÖ„ ooYYð4ÖÿÖÖÿÖ YYYCð0ÖÿÖÖÿìz CC--ð+ìÿììv --ð&r ð"n ðj ð f à÷c àÞìÿì` àÆìÿÖÖÿª^ -CoàÄ”ÿ”~ÿ~Z …±ÝÝààhÿR&ÿ&V ÇÇDZð +&ÿ&&ÿ&Q ›…YCð"&ïúÎîL --Y…ð wîKÞóF ±ó 5á×›ÝZÝA`¢ú&â¡ÝDÝ›=-&äŒá‰ îwÎþ: …ìï—hÿ”Ö8ýª~ÿhRï¿--Y5ýhhÿ~”ïðoo…›2ý”~ÿ~hÿ››››/ýh~ÿ~~ÿ0››››,ý””ÿªªÿ+››››(ýªÀÿÀÀÿ››››$ýÀÀÿÀÀÿ››››"ýÀÀÿÀÀÿ7››››ýÀÀÿÀÀÿ››››ýÀÀÿÀÀÿé››››ýÀÖÿÀÀÿé››››ýÀÀÿÀÀÿN››››ýÀÀÿÀÀï5›››› ýÀÀÿÖÖß?››››ýÖÖÿÀÀß›………ýÖÀÿÖÖßè………oýÖÖÿÖÖÿ$…›…› ýÖÖÿÖÖD…………ýÖÀÿÀÖ››››1ýÖÖÿÖÖp››o…eýÖÖÿÖÖioooo±ýÖÖÿÖÖý…………þìÖÿÖÖ\…›››mþÖÖÿÖÖÿÔ››››¾þÖÖÿÖÖÿ™›…›…ÿþììÿììÿ®…ooo/ÿììÿììÿþooooWÿììÿììeoooo}ÿììÿììÌoooo£ÿìÖÿììooYYÊÿììÿìì:YYYYóÿììÿìì/YYYCðìðììCC--<ÓC---Z¤---sˆ„ˆ–‘§Ž¤ƒ„t(_ðF-ðì(ðìð÷ß----æµ----%ˆ----¾W-='ðäøð™ÏðN±ð)œðEð‰†ðÁ|ðÖoðÖaðÆRð§Að2ðc%ð_ðtì--ðìÿììÿì-ð¬ìÿìì-ð¼ú ð¿ðìó --ð±ìÿÖìÿìë ---ðâ ðhÚ ---ðEÒ -CCCð-ðìË CYCYð$Å YYYoð"ðììÿÖ¾ o………ð"ÖÿÀÖÿÀ¸ ›…›…ð&ÀÿÀªÿª± ››››ð&”ÿ””ÿ”« ››››ð$”ÿ””ÿ”¦ ›››…ð~ÿ~~ÿ~Ÿ ››››ð +~ÿ””ÿ”š ›…ooàþªÿÀÖÿÖ” YYCCàúÖÿÖìÿìŽ CCC-à÷Öÿììÿìˆ ----àõì„ àõ~ àóy àîu ààq ìïÐm ìÿìà»j ðìà£ðìf à‡ìÿÖÖÿÀb CàyÀÿ””ÿ”^ Yo……à‡~ÿhhÿRZ ……ooà³RÿRRÿRT C-àÞ&ïú£îKO -Y±áÛóÝ›.ÍÀJ¢"“㬼£a»KD=ÆJD¸ãäta»åË~?M¸ŒDYã].ÝÝaîä;-hv›àrRÿ”ì8ýªhÿ<&ï—--Yo6ý&&ÿRRï±›››±4ý<<ÿ&&￱DZÇ3ý&&ÿ&&ïËÇÇÇÇ0ý&<ÿR<ï×±ÇÝÝ,ýRRÿRRïÙÝÇÇÇ(ýhhÿhhïâ±±±±$ýhhÿhhÿDZÇÇ ýhhÿhhÿaÇÇDZý~~ÿ~~ÿªÇ±±±ý~~ÿ~~ÿœ±±›±ý~~ÿ~~ïú±±±±ý~~ÿ~~ßê±±±± ý~~ÿh~Ïý±±›› ý~~ÿ~~ÏÕ››››ý”~ÿ””ߌ››››ý”~ÿ~”ï»±±±± ý””ÿ~~ÿÖ±±±±ý~~ÿ”~¢±±±›$ý”~ÿ~~±›››Ký~”ÿ””››››Œý””ÿ””Ï››±±âý””ÿ””B›±±›Aþ””ÿ””ÿ¼››±±˜þ~~ÿ~~ÿv››±›àþ~~ÿ~~ÿx›±›±ÿ~~ÿ~~ÿ®±±±±Aÿ~~ÿhhÿþ±±±Çgÿhhÿhh\ÇDZ›Œÿ~~ÿ~hµ››››±ÿ~~ÿhhë››››×ÿhhÿhhí››››ýÿhhÿhhÛ›…… ðhhÿh~†…ooo?ð~hÿhhRooooXð~~ÿ~~9oYYYjð~~ÿ~”/CC--vð””ÿ””/----zðªªÿªª2xðÀÀÿÀÖ(pðììÿììÿ÷bðììÿììÿ}PàÙ:àŒðþRìÿìÙ6­(xOðÃðGðàçÈ࣪ॖàð‡ðN-|ð‰pð”bð‚-CTþìÖÿ”hÿao…±ÝEþ&äî5þ7 J`5Þ݆ÝDývŒ¸Î'ÎÀ~ÌSûëìäú&"R¾¹w» Þêç}"©Õ"뮜Zªêúë23žìì™ìú33-ù­ª.Dú+3ë"Õñ­pœªÞ +û7©"““"hé½5a»¹û7<"ä¸áÍh̪ý-¢v`JÙÝ.DÝp›ý5 óÑÝÇÝí Kîüݱo-ÊíÎþ&ªïåðÖ”ÿ~ C›Ýà×hÿhhÿh¼J`váÍhÿhRÿ<´Œ¢¸ÎáÆ<ÿ&ïú®ääúúá¸úîúúîä¨-"â¨äîääîú¢-&"&&â¡äîääîäœ-&&"â»äîääîä–-úúúáõäîÎÎîÎ-"úñ&äîääîúŠúúääñúþÿ„äääÎá¿ÿÿäÎÎÎákÿ&&ÿ<|ÎÎÎÎá_&ÿ&&ÿ&x¸¸¸¸á¬&ÿ&&ÿ&s¸¸¸¸ñ +&ÿ&ÿo¸¸ÎÎñÿïújääúúá¿úîúäîÎeú"&âAäîιî¹a-&<"Kîaaîwç-¿¿"©“âZîî£î-}h"R<â{¹î¹¹îÎñ-&úäá—úîúúþòθ¢vá¨&ÿ&&ÿ<ð``55á¬Rÿhhÿ~ê óÝ௔ÿ”ªÿÀâ DZ›…à±ÀÿÀÖÿÖ× ooYCà¶ÖÿìÖÊ C-à±¹ ધ ìÿìÖï£----”ýÖÀÿÀÀï¥---CýÀªÿªªï¬CCYCmýª”ÿ””ï¶CCCY^ý””ÿ~hï½CCCCTýhhÿ~”ï½CYYCNý”~ÿhhï»Yo…›JýRRÿ&úî»±ÝÝ Gí¹î5óí¸5JvŒBÝ›Dݪ춸¸Îú>Í~SÌÏë¯"&R"}8½5«ô²ê¥©"Õ3C3­ZšÁé£Y3o…3°-S'™骰3°°3°('™''鶰3°°3…$=i™«×é»Y3-3!­Zª†²ê»Õ"©“"h­ô5»åë³<"&úÍ=hÌ~ªì¨Î¸¢ŒÍÖìÜ.íœvJ5 Ýp›ÝÝîŒÝ…Y-íúþRªï€ÖÿÖ YoàwÖÿÖÀÿÖ ››±±àpÀÿÀÀÿª ÇÇÝÝàdªÿªªÿª ÝóóóàSªÿªªÿ”  áC”ÿ””ÿ”  áL”ÿª”ÿ”  á‚”ÿ””ÿ”  áÒ”ÿ””ÿ”ü ñ”ÿ””ÿ”÷5áç”ÿ””ÿ”ò5555᎔ÿ~hÿhï5555áHhÿhhÿhìJJ``áEhÿhhÿhê``vvámhÿhhÿhèvvvŒáthÿhRÿR猌¢¢á><ÿ<<ÿ&䢢¸¸á&ÿ&&ÿ&â¸ÎÎäÑìÿúþâäúúúáïúúîäæ,&&"<<â äîÎÎîÎô,RR"hhâ>¹î¹¹î£ -}}"““â_£îîw3-©¿"¿¿â{îwwîab-ÕÕ"ëëâ‚aîwaîa“-ë3ãmKîKKîK¿=3ãHKî5Kî5á=3ã'KîKKîKù=3ãKîawîw.ëÕ"Õ¿âwîî.¿¿"©“â.£î£î¹.}h"hRâC¹î¹Îîä.<&"&âVäîúúîúúäθá_ÿ&ÿ&¢ŒvváX&ÿ<<ÿR`J5áEhÿh~ÿ” óóà"”ÿ”ªÿªÝÇDZÐñÀÿÖÖÿì±››…Цìÿìî oooYÐ[Ú YYYYÐHìÿììà YCC-Эðììÿì¬ -àkìÿìì” ð€ ìÿììÿpýìðììï¸dýììÿÖÀïA---\ýÀªÿª”ßó-CCYVý””ÿ~~ßÐooYYPý~hÿhhßÂYYYYJýhhÿhRßÇooooBý<&ÿ&ßê›±Ýó;íä£îa5î Jv4ÝÝ›ÝDí>Œ¢¸Î/ͪhÌ=åëHú!&<"h*½¹»5 +ë:“"©Õ2&­²†ªDê%3--3C#Á•™éC3CC3C!™••éC3CY3o•Á™Áìéo3CC3­.ªpœê#ëÕ"¿­Èôº +Kë“"hR"<½ÏË'Sì&"&&"Íh~Ì”ªì úúäÎ ÍÀÖÜ.Ýø¸¸Œ`ÝZ†ÝÇ ÞÜ Ý…CíwÎþ<”ßÄýì-CдìÿììÿÖ oo……ЭÖÿÖÖÿÖ ›››±Ð¶ÖÿÖÖÿÖ ±±ÇÇÐ×ÖÿÖÀÿÀþ ÇÇDZà'ÖÿÖÀÿÀû ÇÇÇÇàœÀÿÀÖÿÖö ÝÝÝÝðÖÿÀÀÿÀð ÝÝÝÝð7ÀÿÀªÿÀê ÝÝÝÝàÞÀÿÀªÿÀä óóóóàÀÿÀªÿªá óó ѪÿÀ”ÿ”Ý ÁW”ÿ””ÿ~Ú55Á/~ÿ~”ÿ”Ø5555Á¾~ÿ~~ÿhÚJJ``ÑÀ~ÿ~hÿhá``vváÂhÿR<ÿ<ôvŒŒ¢ñ}<ÿ&&ÿ&¢¸ÎÎñß&ÿúîúUääúúñîúîúúîä -&"&<ò®Îî¹¹î¹î-3óaîaaîaÏ>#ëëòjKîaaîaà.ëÕ"ÕÕòªaîawîañ.¿¿"¿©òÏîwî/©“"}}òÑ£î¹¹î¹ /hR"<<ò³ÎîÎäîú/&úúäñ„úîúÿθ¢Œñ_&ÿ&&ÿR +v``5ñNRÿhhÿhû5 ñLhÿh~ÿ”æÝÝDZðU”ÿªªÿÀͱ›……ðcÖÿÖÖÿÖ°oYCCðhìÿìì-ðUmð$--JþììÿÖÀïÐ----'þÀÀÿÀªïhCCCY +þªªÿ””ï"YYYYñý””ÿ””ïCooYYàý~~ÿ~~ï×YYYYÔý~hÿhhÿoooooÌýhhÿhhÿ”ooooÅýhhÿhRÿLoooo½ýRRÿRRïó…oo…´ýRRÿ<<ï½……››ªý&&ÿ&›››¡ýúîúäîZ±›››˜íäÎîÎÎî>±±Ç±ŽíÎÎîιîV±ÇÇÇ‡í¹¹î¹¹î•Ç±±Ç€í¹ÎîÎÎîÐÇÇÇÇzíääîäúîé±±±±uíúÿ&&ïç±›››pýïÎwî/ oÝ`á±Ý.”Ì*äh2…ãÏ»¹åË'&=òò3Æ…Óú~ܱíK"=-©ÎóàäþRª CÖÿh<ï -Yo…ýúîúï›±ÇÇý&<ÿ<&ïÝÝÝÝý&ÿï"ÝÝÝÝýÿ&ï,ÝÝÝÝý&&ÿ&&ï,ÝÝÝó ý<<ÿRRï'ÝÝÝÝýRRÿRRï3ÝÝÝÝýRRÿRRïXÝÝÝÝýRRÿRRï{ÝÝÝÝþühRÿRRïtÝÝÇÝúühhÿhhï,ÝÝÝÝöüRRÿRRß¹ÝÝÝÝñühRÿRRß]ÝÝÝÝíüRRÿRRßnÝÝóÝëüRRÿRRßýóÝÝÝéüRRÿR<ïÂÝÝÝÝêü<<ÿR<ÿjÝÝÝÝîü<<ÿ<&ÿÔóóóóúü&&ÿ&&ÿùó óóý&&ÿ&&ÿäóóóóTý&&ÿ&&ÿ£óóóó¬ý&&ÿÿX óóÝþÿÿÝÝÝÝ{þÿÿÝÝÝÝËþÿÿÝÝóÝÿúîúúþóóóó-ïúúîúúþ-óóóóKïúúîúäþ-óÝÝÝfïúäîäúþÝÝÝÝïúäîääîõÝÝÝÝŸïääîääî¿ÝÝÝݽïäÎîÎÎî{DZ±›×ïÎÎîääî7±±››ëïääîääî›››…÷ïäúîúúÞê›………ûÿÿß×ooooôÿÿ&ßÄooYYãÿ&<ÿ<<ßYCCCËÿRRÿRRßMCC--«ÿRhÿh~Ïß---…ÿ~~ÿ~”Ï–----[ÿ””ÿ””ÏÃ----.ÿ””ÿ”ªßA----ÿþªªÿªÀß‘--ÌþÀÀÿÀÖßwšþÖÀÿÀÀß3kþÀÀÿÀÀß ---DþÀÀÿÀÀÏù---&þÖÖÿÖÖÏÚ--þÖÖÿÖÀϦ---- þÀÀÿÀÀÏz--þÀÀÿÀÀÏjùýÖÖÿÖÖÏgîýÀÀÿÀÀÏ`áýÀÖÿÖìÏTÔýÖÖÿÖÖÏIÆýÖÖÿÖÖÏ?ðì¹ýÖìÿììÏ8¬ýìÀ1¢ýììÿìÖÏ*ìÿÖ—ýììÿììÏ&ÖÿÖìÿìýììÿììÏìÿììÿì„ýììÿììÏìÿÖìÿì|ýììÿììÏìÿìÖÿÖtýìÀÖÿÖÖÿìl °òÖÿÖÖÿÖe °âÖÿÖÖÿÖ^ °ÖÖÿÖÖÿÖV °ÏÖÿÖìÿÖP ðìì¿ÍìÿÖÖÿÖJýì°ÊÖÿÖÖÿÖB °ÃÖÿÖÖÿÖ; °·ÖÿÖÖÿÀ4 °§ÖÿÀÖÿÖ/ °™ÖÿÖÖÿÖ) °’ÖÿÖÀÿÖ$ °’ÖÿÖÀÿÀ °ÀÿÀÀÿÖ °}ÖÿÖÖÿÖ ì°qÖÿÖÀÿÀ °oÖÿÖÖÿÀ °zÀÿÀÀÿÖ °‰ÀÿÀÀÿÀ °’ÀÿªªÿÀ °”ÖÿÖÖÿÖþ °‹ÖÿÖÖÿÖú °vÖÿÀÀÿÀö °cÖÿÀÀÿÀò °ZÀÿÀÀÿÖð °ZÀÿÀÖÿÖì °ZÖÿÖÀÿÀè °WÀÿÀÀÿÀæ °WÀÿÖÖÿÖâ °^ÖÿÖÀÿÀÞ °jÀÿÀÀÿÀÚ °qÀÿÖÖÿÖÖ °jÖÿÀÖÿÖÒ °\ÖÿÖÖÿÖÏ °PÖÿÖÖÿÖÌ °NÖÿÖÖÿÖÈ --CC°LÖÿÖÖÿÖÅ CCCY°GÖÿÖÀÿ”à oo……°E”ÿ””ÿ”À ……oo°N”ÿ~~ÿ~½ o……›°Zhÿ~~ÿ~º ››››°\~ÿhhÿh¶ ››±±°Whÿhhÿh´ ±±±›°Phÿhhÿ~° ›…oo°N”ÿ””ÿ”¬ YYYY°N”ÿªÀÿÀ© YYCC°IÀÿÖÖÿÖ¦ -°EÖÿìÖÿÖ£ °@ÖÿÖÖÿÖ  °BÖÿÖÖÿÖž °Eì› ðìì¿G™üìì°Bìÿìì— °@ìÿÖ– °BÖÿÖÖÿÀ“ °EÀÿÀ”ÿ”’ -C°I~ÿh&ÿ Yo…›°LúîäÎ ›±Ýó°L¹î£îKˆ 5vä±PÞdžÝ.„,<Õ2YƳ\ͪSÌ'~L4¢Dù%µsÌ'=Ì~z\%ùDÎv´—ÝÇKîÎv<›“¢Ý°Á&ÿ~Ör YðÀ~¿é-YYoqüRRÿRRÏoo……nüR<ÿ<&Ï›››…lü&&ÿý~~ÿ~~ÿòÝÝÝdžý~~ÿ~~ÿ³ÇÝÇÇÜý””ÿ~~ÿºÇÝÝÝ0þ~”ÿ”~ÝÇÇÇxþ””ÿ”~sÝÇÇDZþ~~ÿh~ÝÇDZ±Üþ~~ÿhh±±ÇÇÿhhÿhh%ÇÇDZ#ÿhhÿhh±Ç±ÇDÿhhÿhhôDZ±±gÿhhÿhhÖ››››‰ÿhhÿhh¾›››…©ÿhhÿhh®›……oÅÿhhÿ~~©ooooÜÿ~~ÿ””²oooYíÿ””ÿ””ÃYYYC÷ÿªªÿÀÀÌC---ûÿÀÀÿÀÖÃ----úÿÖÖÿìì©-ñÿììÿì„ã\Í*³ðâ•ð{rðLð!ðGöðž-ÉðÈ----ðÏ---wðÑ----XðÊ----Dð£----8ðZ----0ð---'àõ----àúððù ðì ð0à ð9Ö ð7Ì ð&ìÄ ð¼ àþµ àì® àÛ§ àËðì  àÂìš ----པ -CCCඎ CCCYàªðìˆ YYooà¡ÖÿÖÖÿÀ‚ oo……à—Àÿªªÿ”} ………›àªÿ””ÿ~x ›››…à‰”ÿ””ÿ”s …oooà…”ÿ~~ÿ~m oo……à€~ÿ~”ÿ”h …ooYà{ªÿªÀÿÀb YYCCàwªÿÀÖÿÀ^ CC--àpÖÿÖÖÿìX -àkìT àfO ìÿììïdKýììÿììïaFýììÿììïVCýììÿÖÖïA?ýììÿììï,<ýììÿìÖï9ýÖìÿììïìÿÖÖÿÀ6ýìàªÿ””ÿ”2 Cooà%”ÿ~hÿ<. YYYCà.RÿRRÿ<* -à5&ïú£îK& C…óà0 Þ±ZÍÖ `ä!RÕâS¼Ïw»K=oòC`¢Ôý5»wÏËSMŒJ4òYÓèÝÇKîä-Rv±Ðì<ÿ”ìýÀhÿ&ï-CYoý&ÿ&<ï)……›› ý<&ÿï:±±±± ýÿïA±±±± ý&&ÿ&<ïHDZ±±ý<<ÿRRï_±±±±ýRRÿRR±±±ÿüRRÿRRï±±±±±úüRRÿRRïƱ±››öüRRÿRh缾›››ðühhÿhhï.››››ìühhÿhhß[››››çühhÿhhÏ›››››ãühhÿhhÏ|±›››ßühhÿhhß.››››ÝühhÿhhïO››››Üühhÿhhÿ\››››Üühhÿh~ +››››àüh~ÿhhU››››îü~hÿh~K››››ý~~ÿ~~ÿõ››››Jý~hÿh~ÿv››››œý~~ÿhhÿ››››úýhhÿ~~ïÉ›…››Rþ~~ÿ~~ïÙ››››™þhhÿhhÿ››››Ñþhhÿhhÿ››››üþhhÿhhÿÛ››››#ÿhhÿhR››…›HÿRRÿRR9›………nÿRRÿRR4…………•ÿRRÿRRooooºÿRRÿRRÿØooooÝÿRRÿRRÿ¬…YooûÿRRÿhhÿžYCCCðhhÿhhÿªCCC-&ðh~ÿ~~ÿ¼---3ð~~ÿ””ÿÊ9ð””ÿªªÿÔ9ðªÀÿÀÀÿÍ2ðÀÀÿÀÖÿž&ðÖÖÿììÿ;ðìðììÿìàÄìÿììÿÖàŽìÿìðìåàÂìÿÖìÿÖÅð0ì¡ð‚wð—Lð„ðXïðÄàåŸàÄ‚ìï¿pàÉbàÔXàâLàî@àð2àå#àÒàÂà½ü à¿ìÿììÿìð àÄðììÿìç àÆÖÿÖìÿìÞ àËìÿÖìÿìÕ àÐÖÿÖÖÿÖÎ àÐÖÿÖÖÿÖÆ ----àÉÖÿÖìÿì¾ -C-Cà½ìÿìðì¶ CCCYà¬ìÿÖÖÿÀ® ooooàœÀÿÀªÿÀ§ …………àŒ”ÿ””ÿ~  ………›à€~ÿ~hÿ~š ›››…àw~ÿhhÿh“ ……ooàthÿhhÿ~Œ o…o…àr~ÿ~~ÿ”‡ oooYàp”ÿ”ªÿª CC--àpªÿÀÀÿÀ| ----àkÀÿÀÀÿÀu -àfÖÿÖÖÿÖn à_ìÿÖìÿìh ìÿììïZìcýììÿììïS^ýììÿììïJXýììÿììï>ðììTýììÿììï5PýÖÖÿÖÖï,ðììÿìLýÖÖÿììï ÖÿÖªÿ”Hýììà”ÿ”~ÿ~C -CYYà~ÿhhÿR? YCCCà"<ÿ<&ÿ&; à.ïäîK6 C…óà,óÝ›.ͪ0`Î!RÕâ'¼¹w»a+=…òC`vÔöw»£ûË”&M`4ÆÓåDÝÝwîä"-5oìßñ<ÿ”Öý”Rÿ&ï -Coý&&ÿ&<ïo…››ý&&ÿ&ï ››››ýÿ&ï±›››ý&<ÿ<<ï'››››ýRRÿRRïA››››ýRRÿRhïk›››› ýhhÿRRïš›››› ýhRÿhhï»››››ýhhÿhh拏›››ýhhÿhhï'››››ûühhÿhhßH››››öühhÿhhφ››››ôühhÿhhÏs››››ðühhÿhhß,››……îühhÿhhïJ…›››íühhÿ~~ÿS››››ìü~hÿhh +››››ðühhÿh~c››››øühhÿhh^››››ýh~ÿ~h›…››>ýhhÿhhÿ‰››››†ýhhÿhhÿ"››››Ýýhhÿhhïú››››6þhhÿhhÿ ››››„þhhÿhhÿE››››Áþhhÿhhÿ‹››››ðþhhÿRRÿÍ›››…ÿhhÿhRÿþ››››;ÿhhÿRR………›_ÿRRÿRR››……ƒÿRRÿRR…ooo¨ÿRRÿRRÿßooooËÿRRÿRRÿºoooYëÿRhÿhhÿ§YYCCðhhÿhhÿ¥CC--ðh~ÿ””ÿ¬----&ð””ÿ””ÿ³--ðªªÿªªÿ¼.ðÀÀÿÀÖÿ¼(ðÖÖÿÖìÿ—ðìðììÿììÿE +ðììÿìàÔìôàŽ×ॷð“ðUkðo?ð\ð2áàþ´àÍ---Žàª---ràž--_à¡--Sà¨-Jà¬@à¶5à»)à¶à¥à—à÷ à“ì à•ðìâ à•Ú à•Ó à“Ì --CàÄ CCCCà‡½ CCCYà~ìÿÖµ YoooàtÖÿÖÖÿÀ® …………àkÀÿÀ”ÿ”§ ………›àa”ÿ””ÿ”¡ ›››…àV”ÿ””ÿ”š ……ooàL”ÿ~”ÿ”” …o……àE”ÿ””ÿ” …ooYàAÀÿÀÖÿÖŠ YCCCà>ÖÿÖìÿÖ„ ----à<ìÿìì à:z à7t ðììï5pýììÿììï0kýììÿììï%gýììÿììïcýììÿììï^ýììÿììï ZýììàðìÖÿÖV ÐÿÀÿª”ÿ”T CYooÐö”ÿ~hÿhP YYCCÐóhÿhhÿhK ÐóRÿÎîF oÇÐó5ÞÝpÍì@5¢!&¿Òêh¼å£»:=CÆCJÔÜ£»¹'̪6M4ò3›ëÒÚpí îú3úoìßèhÿÀ-0ý”hÿ<&ßú-Yo…-ý&<ÿRRßÿ›››±,ýR<ÿ<&ßú±±±Ç)ý&&ÿ<<ßöÇÇÇÇ'ý››3››·óÝóÝí $>››3……Ñ î î 9>……3ooï î îJ>YY3CCî5KîKW>--3 KîKwîwa.ëÕ"¿¿wîî£i.©“"}hï¹î¹Îîäo.R<"&Ñúîúÿrúäθ°&ÿ&<ÿY-C-xðRRÿRRÿ+---jðRhÿhhï÷Xð~~ÿ~~ï¡-?ð””ÿªªï)"ðªªÿªÀߤðÀÀÿÀÀßTÚÿÀÀÿÖÀßn°ÿÖÖÿÖìßÉÿÖìÿììïOÿììÿììïÿììÿììßÿèþììÿììßζþììÿììß–ŒþìÖÿììßgoþÖÖÿÖÖßK^þììÿììßDTþìÖÿììßFKþììÿìÖß<@þììÿÖìß'3þììÿìÖß%þÖìÿÖÖßþÀÖÿÖìßþììÿììßìøýììÿììßìýììßìÿììÿìá ðìÀùìÿÖÖÿÖÖ ÀèÖÿÖìÿìÌ ÀÚìÿìÖÿÖà ÀØÖÿÖÖÿÖ¼ ÀÜÖÿÖÖÿÖ³ ÀØÖÿÖÖÿÀ« ÀÅÀÿÀÀÿÀ¤ ---CÀ¦ÖÿÖÖÿÖ -CCCÀÀÿªªÿª– YYYoÀ”ÿ””ÿ” ooooÀu~ÿ~hÿRˆ ……››ÀjRÿ<<ÿR ›……oÀ[hÿRRÿýÖÖÿÖìÏÀÿÖÀÿÀ:ýììÿììϪÿ””ÿ~6ýììÀ~ÿhRÿ<2 -CCÀ &ÿúîú- YoooÀúîääîÎ( ooo›°ù£îK ÞÇ# Çvä±í†Ý.ìÌ~-hë2oò³æ'¼åÏ»ÏM`¸D¸¢´éåË'À܆M`4-²ðî£ÿhoª¿ùªÿì-ýh<ÿ&&Ï --CYýKÞÝ›ÝDCäh"ÕYã<ìÌ”'¼û>=ÜJD¸ãä.å»ûÌh:Mã¸DŒäݱKîÎ6=C<`±àhÿ”ì-3 -ìÿª~ïCoo…0ýhhÿh~ï›±ÇÝ-ý~hÿRRï0ÝÝÝÝ*ýRRÿ=ÜúáawîúRÿª; oìÿ”<ï{-C8ý&úþ&ï‡Y…››5ý&&ÿ&ï‚›±±±3ýúîúúîyÇÇÇÇ0ýÿ&&ïy±Ç±±,ý<<ÿ<<ï~±±ÝÇ(ýRRÿRRïŒÇÇÇÇ$ýRRÿRRï³ÝDZÇ"ýRRÿRRïúÇÇDZýRRÿRRÿ4DZ±±ýRRÿRRÿ±±±ÇýRRÿRRÇDZýRRÿRhß´±±±± ýRRÿhhß±±±± ýhhÿRRß,±±±±ýhhÿhhßá±±±±ýhRÿRRïͱ±±›ýRhÿhhÿ—›››› +ýhhÿhh››››ýhRÿhh`››››8ýhhÿhh\››››pýhhÿh~››…›Âýhhÿhhÿ³›››› þhhÿhhÿh……›…zþhhÿhRÿZ……›…ÈþRRÿRRÿ{…›››ÿRRÿRRÿ±››››6ÿRRÿRRÿé››…›`ÿRRÿRR!›…››‰ÿRRÿRRU››…›±ÿRRÿðìú„Õù©lzðIàÆ-àV----ëà----ÆÐý---«à0----™ìÿììï----Žàå----‚þììÿììÿ----vð--iàç-[à»---Mà‡-?à]2àJ&àVàràŒ àœà¡ù àšð à‡ê àpâ à]Ú àQÓ àJÌ àHÅ àH¾ àH¸ àE² ----à>¬ CCCCà7¦ CCYYà.ðìÖÿÖ¡ ooooà'ÖÿÖÀÿÀœ ooooà"ªÿª”ÿ”– o………à”ÿ””ÿ” ooooà”ÿ””ÿ”Œ ooooà”ÿ””ÿ”† ooooàªÿ”ªÿÀ‚ YYCCàÀÿÖÖÿÖ| --àÖÿììw àr à n ìÿììïjýììÿÖÖï-fýÖÖÿÖÖßÿbýÖìÿìÖßö^ýÖÖÿÖÖßêZýÖÖÿÖÖßÚVýÖÖÿÖÖßÉðÖTýÖìÿììß»ÖÿÖÀÿªP -Cй”ÿª”ÿ”M YYCCÐÄ~ÿhhÿhH C-ÐÕhÿh<ïúD Ðá£îKÝÝ›> …Ý`äÑá.Í”¼9-hë2…ÔÐK»5a»£4MvŒDv4Ô¶åË”DÝó/=Ü-#&JѨþhÿÀ, …ð”Rß­-Yo)ý&ÿ&ßÂ…›±Ç'ý<&ÿ&&ßÎÝÝÝÝ&ýúîúßÐÝÝÝÝ#ýÿ&&ßÕóóÝÝ ý<<ÿ<<ßèÝÝÝÝýRRÿRRï ÝÝÝÝýRRÿRRï>ÝÝÝÝýRRÿRRïtÝÝÝÝýRRÿRRïŽÝÇÇÇ ýRRÿhhï]ÝÝÇÇýhhÿhhßÀDZ±±ýhhÿhhÏÜÇÇÇÇýhhÿhhÏ8ÇÇDZýühhÿhRÏW±±±±úühhÿhhß<›››±ùühhÿhhïf±±±ÇùühhÿhhÿZDZ±±úühRÿRhÿ뱱DZþüRRÿhh#±±±›ýhhÿhh ›±±±0ýhhÿhhÿ³±±±±lýhhÿhhÿ>±±±›ÁýhhÿhhïÛ±±›± þhhÿhhﶛ±±±{þhhÿhhïË››››Æþhhÿhhÿ››±±ÿhhÿhhÿE±›››1ÿhhÿRRÿ„›±±±XÿRRÿRRÿ¸±±›±~ÿRRÿRRÿÖ±››±¥ÿRRÿRRÿÝ››››ÍÿhRÿRRÿÍ…o……ôÿRRÿRRÿª………oðRRÿRRÿxoooo8ðRRÿhhÿSYYYYRðhhÿhhÿICC--fðhhÿ~~ÿU---Cqð~”ÿ””ÿfC--vð”ªÿªªÿh-sðÀªÿÀÀÿXiðÀÀÿÀÀÿ"XðÖÖÿÖìï½BðììÿììïX'ðìàVàÔäð\»ð{ð;[àó*àÄûà¡Ïà~®àf˜àfŠày€ðìà‰tìïŽiþììÿììï‡\þìàyNþììÿììïa?þìàE0à)"àþììÿììï  +àðììÿìþýììÿììïìÿìðìôýììÐøìÿììÿÖêýììÿìÐèÖÿììÿìâ ÐÒìÿÖÖÿÖØ нÖÿÖìÿÖÐ ìЦìÿìÖÿìÆ ìÿììߊìÿììÿì½ýììÿììßkìÿìðì´ ììßHðììÿì¬ýììÿìÐ'ìÿìÖÿÖ¥ Ð Öÿììÿì Àôìÿììÿì— ÀÜìì -ÀÊðììÿÖˆ ----À¼ÖÿÖÀÿÀ‚ CCCCÀ·ªÿª”ÿª| CYYYÀµ”ÿ~~ÿ”u YoooÀ°~ÿh~ÿhn oYoYÀ¦hÿhhÿ~h YYYoÀ›~ÿ~hÿ~b oYYCÀŠ~ÿ~”ÿ”\ C-ÀuªÿªÀÿÀV ÀcÀÿÀÀÿÖP ÀPÖÿììÿìJ ðììÏBìÿìðìEýìÖÿÀÀÏ4?ýÀÀÿÀÀÏ#:ýÀÀÿÀÀÏ6ýÀÀÿÀÀ¿ù2ýÀÀÿÀÀ¿ë.ýÀÀÿÀÀ¿ÛìÿìÖÿì*ýÀÀÿÖÀ¿ÍìÿììÿÖ&ýÀÖÿÖÖ¿ÁÖÿÀªÿ”"ýÖÖÿì°Á”ÿ”~ÿh -°È&ÿ&ÿ& C---°Ñÿ&ïä --Y›°Ö£îK Þ› ÝJÎ<²ÖpÝ”Ì=-©-3Æ´Ïû»ååËM`vDJ´¼=Ìì†í5=Æú5±¢¹þ&~ÿÖý oðªR¿™-Yúü&ÿ&¿¥oooo÷ü&<ÿ&&¿·o›…›õüúîúú¾Á››››òìúÿ&¿º››››îü<<ÿ&&¿©››››êü&<ÿ<<¿›››……æüooYY'ÿ<<ÿÿ””ÿ””b›………^ÿ””ÿ””`……oo~ÿ””ÿ””YoooYÿ””ÿªªToooY¹ÿªÀÿÀÀeYC--ÎÿÖÖÿÖÖˆ----ÞÿÖìÿìì¦åÿìì¦ç…àOÓ-¿C---ö¥----ä‡---CØc--C-¹;CCCCsCCCCäCCCCð™¸C--ða“----ðwðÝe4Z\RYGB:,ðÃðvðIðGø ðhî ðæ ðªðÖìà ð¸ðììÿìÙ -ð±Ñ ð—ìÊ -ðo ----ðGìÿììÿì¼ ----ð)ìÿìÖÿì´ ----ðìÿìì¬ --ð +¦ --ðŸ ---Cð +™ CCCCð ” CYYYð +Ž ooooððììÿÖˆ o……›àúÖÿÖÖÿÀ‚ ››››àîÀÿª”ÿ”} ›››±àà”ÿ””ÿ”x ±±±±à×”ÿ””ÿ”t ››››àÍ”ÿ”~ÿ”n ››››àÆ”ÿ””ÿ”j ››…o࿪ÿÀÖÿÖe ooYYà¸ÖÿÖÖÿÖa YCCCà³ÖÿÖì\ CCC-à¬X -à¨T à¥P àžL àJ ðìà‚F ìïtD àhB àaðìÖÿÖ> -àaÀÿ””ÿ”< Co……àd”ÿ~hÿh8 …oooàhRÿh<ÿ<4 YCC-àkïäîK/ Co±áfóÝ›ZÍÀ(¢"“ã]=¼Ïw»5$=ÆJD¸ãäJ5»w¹Ë=MÎŒD4…ã:ÝÇaîä-“ŒÇ-à3RÿªýÖ~ÿR&ï:Co…›ý&<ÿ<<ïH±ÇÇÝý<<ÿ&&ïVÝÝÝÝýÿïZÝÝÝóý&<ÿ °ØhÿhRÿ&: -CCY°Ôïúäî¹5 oo…›°Ö¹î¹£î0 ±Ýó5±ÔKî ±Ýp+vÎ!RÕ²ÁÍÀhÌ&=YÜC`δ§å»¹Ï»û"MùùD㢴›'ÌÀpí MJo#}v±¬îúRÿª Ç-ðÖ~¿Ï-ýRRÿRR¿ô--CoýRRÿR<Ïo…››ý<&ÿ&&Ï›………ý&&ÿ&<Ï&………o ýìÿìÐ CCCCð$ðììÿìÊ CCCCððÖìÿìà CYCYð ½ YYooð ¶ ooooð° o……›ððìÖÿÖª ›±±±ð ÀÿÖÀÿÀ¤ ±±±±ðªÿªªÿªž ±±ÇÇàüÀÿªªÿª˜ DZ±±àðªÿª”ÿ”’ ±±±±àå”ÿ””ÿ”Œ ±±±±àÙªÿ”Àÿª‡ ››…oàÐÖÿÖÖÿÖ‚ ooooàÉÖÿÖìÿì} oYYYàÂx CCC-à»t -à±o àªk à¡h à•d à‰-a à~--^ àtZ àkìÿÖÖÿÀX --YàkªÿªªÿªT o…›…ày”ÿ~hÿhP ………oàŽhÿR<ÿ&L YYCYàœúî£KÞóF …Ç5¢á±ÝZÍh@-}2›ãpû»£w»w;MŒDÎÎäJ£»åSÜ8MŒJ4°¿â3±íKäþ<4¸óCìï0”ÿÖ-2ý”Rÿ<&ïAYo…›0ý±ÇÇÇý~~ÿ~~ÿ>ÝÇDZý~”ÿ””±±± ý””ÿ””߇±ÇÇÇý””ÿ~”ϦÇÇÇÇý~”ÿ””ϼÇÇÇÇý””ÿ””ßÄÇÇDZý””ÿ””ÿ±±›±ý””ÿ”~(±±±±ý””ÿ””ñ±±± ý””ÿ~~ù±±±±!ý~~ÿ~~ر±±±Lý”~ÿ””n±±±±’ý””ÿ~”ÿç›±±±ëý””ÿ”~ÿ}±›±±Iþ~~ÿ~~ÿZ±±±›þ~~ÿ~~ÿ››››âþ~~ÿ~~ÿÑ››››ÿ~~ÿ~~4››››Gÿ~~ÿhh››››qÿhhÿhhÌ›››››ÿhhÿhhä››››ÅÿhhÿhhÚ››››ðÿhRÿhh¼››››ðhhÿhh…………>ðhhÿhh^oooo^ðhhÿhhBoYYYxðhhÿh~DCYC-Œð~~ÿ””\----™ð””ÿ”ªx--- ðªªÿÀÀ‹ ðÀÖÿÖÖ™ðÖÖÿììxŒBìzðîìÿìÖÿìcð„ÖÿììÿìHð"ìÿìÖÿÖ'à÷ÖÿÖÖÿÖð&ÖÿÖìÿìÚ-ð‹­ðÝ}ð÷LðÛð¬íð}ÉðS±ð0¡ð–ðŠð&-~ð4pð>að>Rð7ìÿìBð+4ððì)ððððð&ðììð&ðììù ðìÿììÿìñ ð ðììÿìê àõìÿìâ ---àÛìÚ C-CCàÄÓ CCCCà¶Ì YYooà¬ìÿÖÖÿÀÅ ooo…ਪÿª”ÿ”¾ …………॔ÿ~”ÿ~¸ ››››à¥”ÿ””ÿ~± ››››à¡~ÿ~hÿh¬ …………àœhÿ~~ÿ”¦ ………oà•”ÿ”ªÿÖ  oYCCàŽÖÿÖÖÿÀš C-CCà…Àÿªªÿ”– CCCCà€”ÿ”~ÿ~ CCYoà~hÿhRÿ<Œ oo…›à{&ÿ&&ÿ† ››…oà{úîúÎ YCàtîwKî }ýìÖÿÀ”ïdÝݱ›Ýpxýh<ïúäîLDÝ..Ý.uíΣîaî5.Ý.DÝZqíK5î î,pÝ››ÝÇní î î,ÝÝó î jíî55î5î55î5fí55îKaîAîîaí¹îÎúîJîKKîaZý&ÿ&RïOwîîUý~ªÿìàA£î£¹î¹P Cooà%äþ<ÿ~J ……oYàÀ-oF Cìßø›ÇÝóDýììÿììï  Býììÿììï0?ýììÿììïm=ýììÿììï³5:ýììÿììïà6ýììÿììïÂ2 ðììïJ.ýììÿìЯ  ) ÐT55$ Ði! ÐÎ àH5555 à±5555 ð5555 ð45555 ð;J55J ðJJJJ" àìJ`J`< àÆ``J`l à¶JJJJ° --à»`JJJ---CàÔ``J`PCCCCàú```J–YYYYðJJJJÎYYYYð+J`JJûYoooð&JJJJ#o………ðJJJ5F››››ð  i›››±ð  óó‹±±±±ðÝÝÝÇ­±±±±ðÇDZ›Ê±±±±ð››…oå±±±±ðooYYù±±±±ðYYC-±›››àì---- ›››…àÄ ……ooà…ooooàCðì÷YYCCà.ìÿììÿìåC---à]ìÿììÿìÍ--àªÖÿÖìÿÖ±à×ÖÿÖÖÿÖà×ÖÿÖÖÿÖiàÄìÿììÿÖ@à¬ìÿììà‰ðìÖÿìêþìðììïaìÿìðìÂþììÿììïEìÿì þììÿììïAì…þÖÖÿÖÖïEsþÖÖÿÖÖïHfþÖÖÿÖÖïL[þÖÖÿÖÖïQOþÖÖÿÖÖïVðìDþÖÖÿÖÖïQìÿìÖÿì8þÖÖÿÖÀïCì*þÀÀÿÀÀï3ðììÿìþÀÀÿÖÀï'ìÿÖìÿÖþÀÀÿÀÀïÖÿÖÖÿÖþÀÀÿÀÀïÖÿÖÖÿÖûýÀÖÿÖÖï ÖÿÖÖÿÖðýÖÖÿÀÀïÖÿÖÖÿÖæýÀÀÿÀÖßúÖÿÖÖÿÖÝýÖÖÿÖÖßñÖÿÖÀÿÖÔýÖÀÿÖÖßåÖÿÖÖÿÀÌýÖÖÿÖÖßÚªÿÀÀÿÖÄýÖÖÿÀÀßÎÖÿÖÖÿÖ¼ýÀÀÿÀÀßÄÖÿÖÖÿÖ´ýÀÀÿÀÀß»ÖÿÖÖÿÖ¬ýÀÖÿÀÀ߯ÖÿÖÖÿÖ¥ýÀÀÿÀÀߟÖÿÖÖÿÖýÀÀÿÀÖߌÖÿÖÖÿÖ—ýÖÖÿÖìßyÖÿÖìÿÖýììÿììßi \ No newline at end of file diff -Naur wfdb-10.1.6/checkpkg/expected/xform.hea wfdb-10.2.0/checkpkg/expected/xform.hea --- wfdb-10.1.6/checkpkg/expected/xform.hea Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/expected/xform.hea Mon Oct 8 19:03:23 2001 @@ -0,0 +1,9 @@ +xform 4 125 7500 22:00:23 20/07/1995 +xform.dat 212x4 2456/mV 12 0 221 31380 0 V +xform.dat 212 13.335(-1600)/mmHg 12 0 -700 26762 0 ABP +xform.dat 212x4 1053/mV 12 0 2 -15184 0 II +xform.dat 212 39.8(-1605)/mmHg 12 0 141 -17199 0 PAP +#Produced by xform from record mimicdb/237/237, beginning at 9:19:45 +#record xform, signal 0 <- record mimicdb/237/237, signal 1 +#record xform, signal 1 <- record mimicdb/237/237, signal 2 +#record xform, signal 2 <- record mimicdb/237/237, signal 0 diff -Naur wfdb-10.1.6/checkpkg/input/100x.hea wfdb-10.2.0/checkpkg/input/100x.hea --- wfdb-10.1.6/checkpkg/input/100x.hea Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/input/100x.hea Mon Sep 10 17:55:23 2001 @@ -0,0 +1,6 @@ +100x 2 120 +100x.dat 212 200 11 1024 995 21537 0 MLII +100x.dat 212 200 11 1024 1011 -3962 0 V5 +# 69 M 1085 1629 x1 +# Aldomet, Inderal +#Produced by xform from record 100, beginning at 0:0 diff -Naur wfdb-10.1.6/checkpkg/input/ecgeval wfdb-10.2.0/checkpkg/input/ecgeval --- wfdb-10.1.6/checkpkg/input/ecgeval Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/input/ecgeval Mon Sep 10 12:07:19 2001 @@ -0,0 +1,27 @@ + + +MIT DB +qrs +thr +1 +y +y +y +y +y +n +eval-qrs-mit +qrs-mit-evaluation +bxb.out +sd.out +vruns.out +sruns.out +vf.out +af.out +st.out +stm.out +stm.ps +hr%d.out +n +n + diff -Naur wfdb-10.1.6/checkpkg/input/sumstats wfdb-10.2.0/checkpkg/input/sumstats --- wfdb-10.1.6/checkpkg/input/sumstats Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/input/sumstats Mon Sep 10 17:45:56 2001 @@ -0,0 +1,5 @@ +Record Nn' Vn' Fn' On' Nv Vv Fv' Ov' No' Vo' Fo' Q Se Q +P V Se V +P V FPR + 200 1415 27 1 14 29 667 0 27 22 6 1 98.66 98.12 95.29 92.25 3.769 + 201 1271 0 1 0 0 198 1 0 50 0 0 96.71 100.00 100.00 100.00 0.000 + 202 1846 1 1 0 5 14 0 0 4 0 0 99.79 100.00 93.33 73.68 0.270 + 203 2035 8 1 19 59 359 4 13 9 6 0 99.40 98.72 96.25 83.29 3.385 diff -Naur wfdb-10.1.6/checkpkg/input/xform wfdb-10.2.0/checkpkg/input/xform --- wfdb-10.1.6/checkpkg/input/xform Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/input/xform Wed Aug 15 15:17:09 2001 @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Naur wfdb-10.1.6/checkpkg/lcheck.c wfdb-10.2.0/checkpkg/lcheck.c --- wfdb-10.1.6/checkpkg/lcheck.c Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/lcheck.c Wed Sep 12 14:21:35 2001 @@ -0,0 +1,581 @@ +/* file: wfdbcheck.c G. Moody 7 September 2001 + Last revised: 11 September 2001 +------------------------------------------------------------------------------- +wfdbcheck: test WFDB library +Copyright (C) 2001 George B. Moody + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place - Suite 330, Boston, MA 02111-1307, USA. + +You may contact the author by e-mail (george@mit.edu) or postal mail +(MIT Room E25-505A, Cambridge, MA 02139 USA). For updates to this software, +please visit PhysioNet (http://www.physionet.org/). +_______________________________________________________________________________ + +*/ + +#include +#ifdef __STDC__ +# include +#else +extern void exit(); +# ifndef NOMALLOC_H +# include +# else +extern char *malloc(); +# endif +#endif +#ifndef BSD +# include +#else +# include +#endif + +#include + +char *info, *pname, *prog_name(); +int n, nsig, i, j, framelen, errors = 0, stat, vflag = 0; +char headerversion[40]; +char *libversion; +char *p, *defpath, *dbpath; +WFDB_Anninfo aiarray[2]; +WFDB_Annotation annot; +WFDB_Siginfo *si; +WFDB_Sample *vector; +void help(), list_untested(); + +main(argc, argv) +int argc; +char *argv[]; +{ + + pname = prog_name(argv[0]); + if (argc > 1) { + if (strcmp(argv[1], "-v") == 0) vflag = 1; + else if (strcmp(argv[1], "-V") == 0) vflag = 2; + else { help(); exit(1); } + } + + if ((p = wfdberror()) == NULL) { + printf("Error: wfdberror() did not return a version string\n"); + p = "unknown version of the WFDB library"; + errors++; + } + libversion = calloc(sizeof(char), strlen(p)+1); + strcpy(libversion, p); + + /* Print the library version number and date. */ + fprintf(stderr, "Testing %s", libversion = wfdberror()); + + /* Check that the installed matches the library. */ + sprintf(headerversion, "WFDB library version %d.%d.%d", + WFDB_MAJOR, WFDB_MINOR, WFDB_RELEASE); + if (strncmp(libversion, headerversion, strlen(headerversion))) { + printf("Error: Library version does not match \n" + " ( is from %s)\n", headerversion); + errors++; + } + else if (vflag) + printf("[OK]: Library version matches \n"); + + /* If in verbose mode, print library defaults. */ + if (vflag) { + static int format[WFDB_NFMTS] = WFDB_FMT_LIST; + + printf("[OK]: WFDB %s NETFILES\n", WFDB_NETFILES ? "supports" : + "does not support"); + printf("[OK]: WFDB_MAXANN = %d\n", WFDB_MAXANN); + printf("[OK]: WFDB_MAXSIG = %d\n", WFDB_MAXSIG); + printf("[OK]: WFDB_MAXSPF = %d\n", WFDB_MAXSPF); + printf("[OK]: WFDB_MAXRNL = %d\n", WFDB_MAXRNL); + printf("[OK]: WFDB_MAXUSL = %d\n", WFDB_MAXUSL); + printf("[OK]: WFDB_MAXDSL = %d\n", WFDB_MAXDSL); + printf("[OK]: Signal formats = {"); + for (i = 0; i < WFDB_NFMTS; i++) + printf("%d%s", format[i], (i < WFDB_NFMTS-1) ? ", " : "}\n"); + printf("[OK]: WFDB_DEFFREQ = %g\n", WFDB_DEFFREQ); + printf("[OK]: WFDB_DEFGAIN = %g\n", WFDB_DEFGAIN); + printf("[OK]: WFDB_DEFRES = %d\n", WFDB_DEFRES); + } + + /* Test the WFDB library functions. */ + aiarray[0].name = "atr"; aiarray[0].stat = WFDB_READ; + aiarray[1].name = "chk"; aiarray[1].stat = WFDB_WRITE; + + /* *** getwfdb *** */ + if ((p = getwfdb()) == NULL) { + printf("Error: No default WFDB path defined\n"); + defpath = ""; + errors++; + } + else { + defpath = calloc(sizeof(char), strlen(p)+1); + strcpy(defpath, p); + + if (vflag) + printf("[OK]: Default WFDB path = %s\n", defpath); + } + + /* *** setwfdb *** */ + dbpath = calloc(sizeof(char), strlen(defpath)+10); + sprintf(dbpath, "../data %s\n", defpath); + setwfdb(dbpath); + if ((p = getwfdb()) == NULL || strcmp(p, dbpath)) { + printf("Error: Could not set WFDB path\n"); + errors++; + } + else if (vflag) + printf("[OK]: WFDB path modified successfully\n"); + + /* Test I/O using the local record first. */ + check("100s", "100z"); + + /* Test I/O again using the remote record. */ + if (WFDB_NETFILES) { + if (vflag) + printf("[OK]: Repeating tests using NETFILES"); + if (strstr(defpath, "http://") == NULL) { + fprintf(stderr, + "\nWarning: default WFDB path does not include an http:// component\n"); + setwfdb(". http://www.physionet.org/physiobank/database"); + printf("WFDB path has been set to: %s\n", getwfdb()); + } + else if (vflag) { + printf(" (reverting to default WFDB path)\n"); + setwfdb(defpath); + } + check("udb/100s", "udb/100z"); + } + + /* If there were any errors detected by the WFDB library but not by this + program, this test will pick them up. */ + if (errors == 0) { + if ((p = wfdberror()) == NULL) { + printf("Error: wfdberror() did not return a version string\n"); + p = "unknown version of the WFDB library"; + errors++; + } + if (strcmp(libversion, p)) { + printf("Error: WFDB library error(s) not detected by %s\n", + pname); + printf(" Last library error was: '%s'\n", p); + errors++; + } + else if (vflag) + printf("[OK]: no WFDB library errors\n"); + } + + /* Summarize the results and exit. */ + if (errors) + printf("%d error%s: test failed\n", errors, errors > 1 ? "s" :""); + else if (vflag) + printf("no errors: test succeeded\n"); + if (vflag == 2) + list_untested(); + exit(errors); +} + +int check(char *record, char *orec) +{ + WFDB_Frequency f; + WFDB_Time t, tt; + + /* *** sampfreq *** */ + if ((f = sampfreq(NULL)) != 0.0) { + printf("Error: sampfreq(NULL) returned %g (should have been 0)\n", f); + errors++; + } + else if (vflag) + printf("[OK]: sampfreq(NULL) returned %g\n", f); + + /* *** setsampfreq *** */ + if (stat = setsampfreq(100.0)) { + printf("Error: setsampfreq returned %d (should have been 0)\n", stat); + errors++; + } + if (sampfreq(NULL) != 100.0) { + printf("Error: failed to set sampling frequency using setsampfreq\n"); + errors++; + } + else if (vflag) + printf("[OK]: setsampfreq changed sampling frequency successfully\n"); + + /* *** sampfreq, again *** */ + if ((f = sampfreq(record)) != 360.0) { + printf("Error: sampfreq(%s) returned %g (should have been 360)\n", + record, f); + errors++; + } + else if (vflag) + printf("[OK]: sampfreq(%s) returned %g\n", record, f); + + /* *** annopen *** */ + stat = annopen(record, aiarray, 1); + if (stat) { + fprintf(stderr, + "Error: annopen of 1 file returned %d (should have been 0)\n", stat); + errors++; + } + else if (vflag) + printf("[OK]: annopen of 1 file succeeded\n"); + + stat = annopen(record, aiarray, 2); + if (stat) { + fprintf(stderr, + "Error: annopen of 2 files returned %d (should have been 0)\n", stat); + errors++; + } + else if (vflag) + printf("[OK]: annopen of 2 files succeeded\n"); + + /* *** strtim *** */ + t = strtim("0:5"); + if (t != (WFDB_Time)(5.0 * f)) { + printf("Error: strtim returned %ld (should have been %ld)\n", t, + (WFDB_Time)(5.0 * f)); + errors++; + } + else if (vflag) + printf("[OK]: strtim returned %ld\n", t); + + /* *** iannsettime *** */ + stat = iannsettime(t); + if (stat) { + printf("Error: iannsettime returned %d (should have been 0)\n", + stat); + errors++; + } + else if (vflag) + printf("[OK]: iannsettime skipping forward to %s\n", + timstr(t)); + + /* *** getann, annstr, mstimstr *** */ + for (i = 0; i < 5; i++) { + stat = getann(0, &annot); + if (stat != 0 && stat != -1) { + printf("Error: getann returned %d (should have been 0 or -1)\n", + stat); + errors++; + } + else if (vflag) + printf("[OK]: getann read: {%s %d %d %d} at %s (%ld)\n", + annstr(annot.anntyp), annot.subtyp, annot.chan, annot.num, + mstimstr(annot.time), annot.time); + } + + /* *** iannsettime, again *** */ + stat = iannsettime(0L); + if (stat) { + printf("Error: iannsettime returned %d (should have been 0)\n", + stat); + errors++; + } + else if (vflag) + printf("[OK]: iannsettime skipping backward to %s\n", + timstr(0L)); + + /* *** getann, putann *** */ + i = j = stat = 0; + while (stat == 0) { + stat = getann(0, &annot); + if (stat != 0 && stat != -1) { + printf("Error: getann returned %d (should have been 0 or -1)\n", + stat); + errors++; + } + else if (stat == 0) { + i++; + stat = putann(0, &annot); + if (stat != 0) { + printf("Error: putann returned %d (should have been 0)\n", + stat); + errors++; + } + else j++; + } + } + if (vflag) + printf("[OK]: %d annotations read, %d written\n", i, j); + + /* *** isigopen *** */ + /* Get the number of signals without opening any signal files. */ + n = isigopen(record, NULL, 0); + if (n != 2) { + fprintf(stderr, + "Error: isigopen(%s, NULL, 0) returned %d (should have been 2)\n", + record, n); + errors++; + } + else if (vflag) + printf("[OK]: isigopen(%s, NULL, 0) succeeded\n"); + + /* Allocate WFDB_Siginfo structures before calling isigopen again. */ + si = calloc(n, sizeof(WFDB_Siginfo)); + nsig = isigopen(record, si, n); + /* Note that nsig equals n only if all signals were readable. */ + + /* Get the number of samples per frame. */ + for (i = framelen = 0; i < nsig; i++) + framelen += si[i].spf; + /* Allocate WFDB_Samples before calling getframe. */ + vector = calloc(framelen, sizeof(WFDB_Sample)); + + for (t = 0L; t < 5L; t++) { + if ((n = getframe(vector)) != nsig) { + printf("Error: getframe returned %d (should have been %d)\n", + n, nsig); + errors++; + break; + } + else if (vflag) { + printf("[OK]: (at %s) getframe returned {", mstimstr(t)); + for (i = 0; i < framelen; i++) + printf("%5d%s", vector[i], i < framelen-1 ? ", " : "}\n"); + } + } + + /* *** sampfreq *** */ + f = sampfreq(NULL); + if (f != 360.0) { + printf("Error: sampfreq returned %g (should have been 360)\n", f); + errors++; + } + else if (vflag) + printf("[OK]: sampfreq returned %g\n", f); + + /* *** strtim *** */ + t = strtim("0:20"); + if (t != (WFDB_Time)(20.0 * f)) { + printf("Error: strtim returned %ld (should have been %ld)\n", t, + (WFDB_Time)(20.0 * f)); + errors++; + } + else if (vflag) + printf("[OK]: strtim returned %ld\n", t); + + /* *** isigsettime *** */ + stat = isigsettime(t); + if (stat) { + printf("Error: isigsettime returned %d (should have been 0)\n", + stat); + errors++; + } + else if (vflag) + printf("[OK]: isigsettime skipping forward to %s\n", + timstr(t)); + + /* *** getvec *** */ + for (tt = t; t < tt+5L; t++) { + if ((n = getvec(vector)) != nsig) { + printf("Error: getvec returned %d (should have been %d)\n", + n, nsig); + errors++; + break; + } + else if (vflag) { + printf("[OK]: (at %s) getvec returned {", mstimstr(t)); + for (i = 0; i < nsig; i++) + printf("%5d%s", vector[i], i < nsig-1 ? ", " : "} ["); + for (i = 0; i < nsig; i++) + printf("%5.3lf%s", aduphys(i, vector[i]), i < nsig-1?", ":"]\n"); + } + } + + /* *** isigsettime *** */ + t = tt-1; /* try a backward skip, to one sample before the previous set */ + stat = isigsettime(t); + if (stat) { + printf("Error: isigsettime returned %d (should have been 0)\n", + stat); + errors++; + } + else if (vflag) + printf("[OK]: isigsettime skipping backward to %s\n", + mstimstr(t)); + + /* *** getframe, again *** */ + for ( ; t < tt+5L; t++) { + if ((n = getframe(vector)) != nsig) { + printf("Error: getframe returned %d (should have been %d)\n", + n, nsig); + errors++; + break; + } + else if (vflag) { + printf("[OK]: (at %s) getframe returned {", mstimstr(t)); + for (i = 0; i < framelen; i++) + printf("%5d%s", vector[i], i < framelen-1 ? ", " : "}\n"); + } + } + + /* Now return to the beginning of the record and copy it. */ + stat = isigsettime(t = 0L); + if (stat) { + printf("Error: isigsettime returned %d (should have been 0)\n", + stat); + errors++; + } + else if (vflag) + printf("[OK]: isigsettime skipping backward to %s\n", + mstimstr(t)); + + /* *** osigfopen *** */ + for (i = 0; i < nsig; i++) { + si[i].fname = realloc(si[i].fname, strlen(orec) + 5); + sprintf(si[i].fname, "%s.dat", orec); + } + stat = osigfopen(si, nsig); + if (stat != nsig) { + printf("Error: osigfopen returned %d (should have been %d)\n", + stat, nsig); + errors++; + } + else if (vflag) + printf("[OK]: osigfopen returned %d\n", stat); + + /* *** getframe (again), putvec *** */ + while ((n = getframe(vector)) == nsig) { + t++; + if ((stat = putvec(vector)) != nsig) { + printf("Error: putvec returned %d (should have been %d)\n", + stat, nsig); + errors++; + break; + } + } + if (n != -1) { /* some error occurred while reading samples */ + printf("Error: getframe returned %d (should have been %d) at %s\n", + n, nsig, mstimstr(t)); + errors++; + } + else if (vflag) /* getframe reached EOF, checksums OK */ + printf("[OK]: getframe read %ld samples\n", t); + if (stat != nsig) { /* some error occurred while writing samples */ + printf("Error: putvec returned %d (should have been %d) at %s\n", + stat, nsig, mstimstr(t)); + errors++; + } + else if (vflag) /* putvec wrote all samples without apparent error */ + printf("[OK]: putvec wrote %ld samples\n", t); + + /* *** newheader *** */ + stat = newheader(orec); + if (stat) { /* some error occurred while writing the header */ + printf("Error: newheader returned %d (should have been 0)\n", stat); + errors++; + } + else if (vflag) /* putvec wrote all samples without apparent error */ + printf("[OK]: newheader created header for output record %s\n", orec); + + /* *** getinfo, putinfo *** */ + n = 0; + if (info = getinfo(record)) { + do { + stat = putinfo(info); + if (stat) { + printf("Error: putinfo returned %d (should have been 0)\n", stat); + errors++; + } + else + n++; + } while (info = getinfo(NULL)); + if (vflag) + printf("[OK]: %d info strings copied to record %s header\n", n, orec); + } + + wfdbquit(); +} + +char *prog_name(s) +char *s; +{ + char *p = s + strlen(s); + +#ifdef MSDOS + while (p >= s && *p != '\\' && *p != ':') { + if (*p == '.') + *p = '\0'; /* strip off extension */ + if ('A' <= *p && *p <= 'Z') + *p += 'a' - 'A'; /* convert to lower case */ + p--; + } +#else + while (p >= s && *p != '/') + p--; +#endif + return (p+1); +} + +static char *help_strings[] = { + "usage: %s [OPTIONS ...]\n", + " -v verbose mode", + " -V verbose mode, also list untested functions", + NULL +}; + +void help() +{ + int i; + + (void)fprintf(stderr, help_strings[0], pname); + for (i = 1; help_strings[i] != NULL; i++) + (void)fprintf(stderr, "%s\n", help_strings[i]); +} + +void list_untested() +{ + printf( + "This program does not (yet) test the following WFDB library functions:\n"); + printf("osigopen\n"); + printf("wfdbinit\n"); + printf("getspf\n"); + printf("setgvmode\n"); + printf("ungetann\n"); + printf("isgsettime\n"); + printf("ecgstr\n"); + printf("strecg\n"); + printf("setecgstr\n"); + printf("strann\n"); + printf("setannstr\n"); + printf("anndesc\n"); + printf("setanndesc\n"); + printf("iannclose\n"); + printf("oannclose\n"); + printf("datstr\n"); + printf("strdat\n"); + printf("adumuv\n"); + printf("muvadu\n"); + printf("physadu\n"); + printf("calopen\n"); + printf("getcal\n"); + printf("putcal\n"); + printf("newcal\n"); + printf("flushcal\n"); + printf("setheader\n"); + printf("setmsheader\n"); + printf("wfdbgetskew\n"); + printf("wfdbsetskew\n"); + printf("wfdbgetstart\n"); + printf("wfdbsetstart\n"); + printf("getcfreq\n"); + printf("setcfreq\n"); + printf("getbasecount\n"); + printf("setbasecount\n"); + printf("setbasetime\n"); + printf("wfdbquiet\n"); + printf("wfdbverbose\n"); + printf("setibsize\n"); + printf("setobsize\n"); + printf("wfdbfile\n"); + printf("wfdbflush\n"); +} diff -Naur wfdb-10.1.6/checkpkg/libcheck wfdb-10.2.0/checkpkg/libcheck --- wfdb-10.1.6/checkpkg/libcheck Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/checkpkg/libcheck Wed Sep 12 15:23:13 2001 @@ -0,0 +1,51 @@ +#!/bin/sh +# file: libcheck G. Moody 8 September 2001 +# Last revised: 12 September 2001 +# +# This script checks the functionality of the WFDB library by comparing the +# outputs of 'lcheck' with expected outputs. See 'lcheck.c' for details of +# the tests performed, or examine the output of 'lcheck -v'. Note that +# 'lcheck' must be run within this directory to ensure that its local input +# files (in ../data) are available. +# +# Suggestions for additional checks are welcome; please send them to the +# author (george@mit.edu). + +if [ \! -s ../data/100s.hea ] +then + echo "Run this program from the 'checkpkg' directory of the WFDB sources." + echo "The 'data' directory, including record 100s, must also be present." + exit +fi + +test -s Makefile || ( cd ..; ./configure ) +test -s lcheck || make lcheck +./lcheck -v >lcheck.log +cp ../data/100s.atr expected/100s.chk +cp ../data/100s.dat expected/100z.dat +CF="lcheck.log 100s.chk 100z.dat 100z.hea" +if grep -q "WFDB supports NETFILES" lcheck.log +then + CF="$CF udb/100s.chk udb/100z.dat udb/100z.hea" + cp ../data/100s.atr expected/udb/100s.chk + cp ../data/100s.dat expected/udb/100z.dat + cp expected/lcheck.log-NETFILES expected/lcheck.log +else + cp expected/lcheck.log-no-NETFILES expected/lcheck.log +fi + +for i in $CF +do + case $i in + *.hea) diff -q $i expected/$i && + ( echo " Files $i and expected/$i match: test succeeded" + rm -f $i ) ;; + *) diff -q $i expected/$i && + ( echo " Files $i and expected/$i match: test succeeded" + rm -f $i expected/$i ) ;; + esac +done + +# rmdir will fail if 'udb' is not empty. This is a *feature*, not a bug -- +# don't fix it! +test -d udb && rmdir udb diff -Naur wfdb-10.1.6/conf/version.def wfdb-10.2.0/conf/version.def --- wfdb-10.1.6/conf/version.def Wed Feb 28 13:18:59 2001 +++ wfdb-10.2.0/conf/version.def Tue Aug 14 10:07:14 2001 @@ -1,10 +1,10 @@ # file: version.def G. Moody 24 May 2000 -# Last revised: 28 February 2001 +# Last revised: 14 August 2001 # Each release of the WFDB Software Package is identified by a three-part # version number, defined here: MAJOR = 10 -MINOR = 1 -RELEASE = 6 +MINOR = 2 +RELEASE = 0 VERSION = $(MAJOR).$(MINOR).$(RELEASE) # VDEFS is the set of C compiler options needed to set version number variables diff -Naur wfdb-10.1.6/configure wfdb-10.2.0/configure --- wfdb-10.1.6/configure Tue May 29 16:59:02 2001 +++ wfdb-10.2.0/configure Fri Sep 7 11:35:59 2001 @@ -187,7 +187,7 @@ else cat lib/Makefile.top conf/site.def lib/Makefile.tpl >lib/Makefile fi -for D in app convert data doc examples fortran psd wave wave-doc waverc . +for D in app checkpkg convert data doc examples fortran psd wave wave-doc waverc . do if [ -s $D/Makefile.top ] then diff -Naur wfdb-10.1.6/convert/Makefile wfdb-10.2.0/convert/Makefile --- wfdb-10.1.6/convert/Makefile Wed Aug 1 10:28:34 2001 +++ wfdb-10.2.0/convert/Makefile Mon Oct 15 14:40:00 2001 @@ -33,12 +33,12 @@ # type `make listing'. # _____________________________________________________________________________ # file: version.def G. Moody 24 May 2000 -# Last revised: 28 February 2001 +# Last revised: 14 August 2001 # Each release of the WFDB Software Package is identified by a three-part # version number, defined here: MAJOR = 10 -MINOR = 1 -RELEASE = 6 +MINOR = 2 +RELEASE = 0 VERSION = $(MAJOR).$(MINOR).$(RELEASE) # VDEFS is the set of C compiler options needed to set version number variables @@ -46,7 +46,7 @@ VDEFS = -DWFDB_MAJOR=$(MAJOR) -DWFDB_MINOR=$(MINOR) -DWFDB_RELEASE=$(RELEASE) # _____________________________________________________________________________ -PACKAGE=wfdb-10.1.6 +PACKAGE=wfdb-10.2.0 # file: linux.def G. Moody 31 May 2000 # Last revised: 5 June 2000 # 'make' definitions for compiling the WFDB Software Package under Linux diff -Naur wfdb-10.1.6/convert/Makefile-dos-gcc wfdb-10.2.0/convert/Makefile-dos-gcc --- wfdb-10.1.6/convert/Makefile-dos-gcc Wed May 24 22:35:27 2000 +++ wfdb-10.2.0/convert/Makefile-dos-gcc Wed Dec 31 19:00:00 1969 @@ -1,86 +0,0 @@ -# file: Makefile-dos-gcc G. Moody 24 April 1997 -# Last revised: 7 May 1999 -# GCC-DOS 'make' description file for DB format-conversion applications -# - -# This file is used with the UNIX `make' command to cross-compile MSDOS -# binaries of the format-conversion applications which come with the ECG DB -# software package. Before using it for the first time, check that the -# site-specific variables below are appropriate for your system. To build and -# install the applications, just type `make -f Makefile-dos-gcc' (from within -# this directory). - -# Site-specific variables -# ----------------------- - -# CCDIR is the directory containing the cross-compiler and the binary -# file utilities for MSDOS. -CCDIR = /usr/lib/gcc-lib/i386-go32-msdos/2.7.2 - -# CC is the name of the cross-compiler. -CC = $(CCDIR)/gcc - -# CCDEFS is the set of C compiler options needed to set preprocessor variables -# while compiling the DB Software Package. You should include definitions of -# the major, minor, and release numbers, and of MSDOS, as shown below. Other -# definitions are needed only for various versions of UNIX and should be -# omitted here. -CCDEFS = -DDB_MAJOR=$(MAJOR) -DDB_MINOR=$(MINOR) -DDB_RELEASE=$(RELEASE) -DMSDOS - -# CFLAGS is the list of C compiler options used when compiling programs in the -# `app', `convert', and `example' directories. Add the following options to -# CFLAGS as appropriate (separating them by spaces if you use more than one): -# -g to save symbols for debugging -# -O to use the optimizer -# -I$(INCDIR) needed if INCDIR is not in the normal search path for -# `#include' files; harmless otherwise -# -L$(LIBDIR) needed if LIBDIR is not in the normal library search path; -# harmless if LIBDIR is in the normal library search path -# As noted above, gcc-dos allows you to use both -g and -O if you wish. -CFLAGS = -O -I/usr/local/dos/include $(CCDEFS) -L/usr/local/dos/lib - -# LDFLAGS is appended to the C compiler command line to specify loading the -# WFDB library. Unless you have changed the value of WFDBLIB in the `Makefile' -# for the WFDB library, `-lwfdb' should be correct. -LDFLAGS = -lwfdb - -# BINDIR specifies the directory in which the applications will be installed; -# it should be a directory in the PATH of those who will use the applications. -# You will need to have write permission in BINDIR. Users of this software -# will need to have search (execute) permission in BINDIR. -BINDIR = /usr/local/dos/bin - -# STRIP is the command used to compact the compiled binaries by removing their -# symbol tables. The next line is commented out because $(CCDIR)/strip fails. -# STRIP = $(CCDIR)/strip -# To retain the symbol tables for debugging, comment out the previous line, and -# uncomment the next line. -STRIP = : - -# It should not be necessary to modify anything below this line. -# ----------------------------------------------------------------------------- - -CFILES = a2m.c ad2m.c m2a.c md2a.c readid.c makeid.c edf2mit.c revise.c -XFILES = a2m.exe ad2m.exe m2a.exe md2a.exe readid.exe makeid.exe edf2mit.exe \ - revise.exe - -# General rule for compiling C sources into executable files. -.SUFFIXES: .exe -.c.exe: - $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) - -revise.exe: revise.c - $(CC) $(CFLAGS) -I../lib revise.c -o revise $(LDFLAGS) - -# `make' or `make install': build and install applications, clean up -install: all - cp $(XFILES) $(BINDIR) - $(MAKE) clean - -# `make all': build applications -all: $(XFILES) - $(STRIP) $(XFILES) - -# `make clean': remove intermediate and backup files -clean: - rm -f $(XFILES) *.o *~ diff -Naur wfdb-10.1.6/convert/README wfdb-10.2.0/convert/README --- wfdb-10.1.6/convert/README Thu Jun 24 11:38:29 1999 +++ wfdb-10.2.0/convert/README Thu Oct 4 14:01:51 2001 @@ -1,16 +1,16 @@ file: README G. Moody 28 July 1989 - Last revised: 7 May 1999 + Last revised: 4 October 2001 -This directory contains sources for DB applications which convert database +This directory contains sources for WFDB applications which convert database files in various unsupported formats to and from MIT format, including to and from AHA DB formats. -Note that many commonly used formats are supported by the DB library. The +Note that many commonly used formats are supported by the WFDB library. The program `xform' (in the `app' directory) is a flexible application for converting between any pair of supported formats, in addition to offering other capabilities such as resampling (to change the sampling frequency), -deletion or rearrangement of signals, and removal of unwanted material at -the beginning or end of a record. +deletion or rearrangement of signals, rescaling (to change signal amplitudes), +and removal of unwanted material at the beginning or end of a record. Programs `rdsamp' and `wrsamp' in the `app' directory convert signals between supported (binary) formats and text; programs `rdann' and `wrann', also in @@ -21,10 +21,10 @@ AHA DB tape distribution format was used for both the AHA DB and the MIT-BIH DB between 1980 and 1990. AHA DB tape distribution format requires more space -than the other formats supported by the DB library and applications, however, +than the other formats supported by the WFDB library and applications, however, so it is not recommended for on-line storage. Programs `a2m' and `ad2m' can -also convert AHA DB diskette distribution format files into standard DB files; -the reverse conversion is not supported, however. +also convert AHA DB diskette distribution format files into standard WFDB +files; the reverse conversion is not supported, however. European Data Format (EDF) has been used for storage of multiparameter, multifrequency data (such as polysomnograms) since 1990. Program `edf2mit' @@ -48,7 +48,7 @@ brief usage summary for each application by running it without command-line arguments. -Note that you must set the DB environment variable (the database path) before +Note that you must set the WFDB environment variable (the database path) before using these applications. Select and customize the appropriate script for doing so from among the templates in the `app' directory on the same level as this one. diff -Naur wfdb-10.1.6/convert/edf2mit.c wfdb-10.2.0/convert/edf2mit.c --- wfdb-10.1.6/convert/edf2mit.c Sun Jul 29 16:37:17 2001 +++ wfdb-10.2.0/convert/edf2mit.c Fri Oct 12 13:13:08 2001 @@ -1,5 +1,5 @@ /* file: edf2mit.c G. Moody 16 October 1996 - Last revised: 29 July 2001 + Last revised: 12 October 2001 ------------------------------------------------------------------------------- Convert EDF (European Data Format) file to MIT format header and signal files @@ -26,6 +26,11 @@ */ #include +#ifndef NOMALLOC_H +# include +#else +extern char *calloc(), *malloc(), *realloc(); +#endif #include char *pname; @@ -34,21 +39,18 @@ int argc; char **argv; { - static FILE *ifile; - static char buf[81], record[20]; - int big_endian = 0, fpb, h, i, j, k, l, nsig, nosig = 0, - siglist[WFDB_MAXSIG], spb[WFDB_MAXSIG], tspb = 0, tspf = 0, - vflag = 0; - char **vi, **vin; + char buf[81], record[WFDB_MAXRNL+1], **vi, **vin; + double *sigpmax, *sigpmin, *sampfreq, spr, sps; + FILE *ifile = NULL; + int big_endian = 0, fpb, h, i, j, k, l, nsig, nosig = 0, *siglist, *spb, + tspb = 0, tspf = 0, vflag = 0, day, month, year, hour, minute, second; + long adcrange, *sigdmax, *sigdmin; WFDB_Sample *vo, *vout; - int day, month, year, hour, minute, second; - long adcrange, sigdmax[WFDB_MAXSIG], sigdmin[WFDB_MAXSIG]; - double sigpmax[WFDB_MAXSIG], sigpmin[WFDB_MAXSIG], sampfreq[WFDB_MAXSIG], - spr, sps; - static WFDB_Siginfo si[WFDB_MAXSIG], so[WFDB_MAXSIG]; + WFDB_Siginfo *si, *so; void help(); pname = argv[0]; + record[0] = '\0'; for (i = 1; i < argc; i++) { if (*argv[i] == '-') switch (argv[i][1]) { case 'b': /* input is in big-endian byte order */ @@ -67,21 +69,48 @@ fprintf(stderr, "%s: can't read %s\n", pname, argv[i]); exit(1); } + if (record[0] == 0) { + for (j = 0; j < WFDB_MAXRNL; j++) { + char c = argv[i][j]; + + if (('0' <= c && c <= '9') || + ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z')) + record[j] = c; + else if (c == '.') break; + else record[j] = '_'; + } + record[j] = '\0'; + } } } break; case 'r': /* record name follows */ if (++i < argc) - strncpy(record, argv[i], 19); + strncpy(record, argv[i], WFDB_MAXRNL); else { fprintf(stderr, "%s: record name must follow -r\n", pname); exit(1); } break; case 's': /* signal list follows */ - while (++i < argc && argv[i][0] != '-') - siglist[nosig++] = atoi(argv[i]); - --i; + /* count the number of output signals */ + for (j = 0; ++i < argc && *argv[i] != '-'; j++) + ; + if (j == 0) { + (void)fprintf(stderr, "%s: signal list must follow -s\n", + pname); + exit(1); + } + /* allocate storage for the signal list */ + if ((siglist=realloc(siglist, (nosig+j) * sizeof(int))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + /* fill the signal list */ + for (i -= j; i < argc && *argv[i] != '-'; ) + siglist[nosig++] = atoi(argv[i++]); + i--; break; case 'v': /* select verbose mode */ vflag = 1; @@ -110,11 +139,6 @@ for (j = 80; j >= 0 && buf[j] == ' '; j--) buf[j] = '\0'; if (vflag) printf("Recording ID: '%s'\n", buf); - if (record[0] == 0) { - strncpy(record, buf, 19); - for (j = 0; j < 20; j++) - if (record[j] == ' ') { record[j] = '\0'; break; } - } fread(buf, 1, 8, ifile); buf[8] = ' '; @@ -167,8 +191,29 @@ sscanf(buf, "%d", &nsig); if (nsig < 1) exit(1); - if (nsig > WFDB_MAXSIG) { - fprintf(stderr, "Too many signals!\n"); + + if ((si = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL || + (spb = malloc(nsig * sizeof(int))) == NULL || + (sigdmax = malloc(nsig * sizeof(long))) == NULL || + (sigdmin = malloc(nsig * sizeof(long))) == NULL || + (sigpmax = malloc(nsig * sizeof(double))) == NULL || + (sigpmin = malloc(nsig * sizeof(double))) == NULL || + (sampfreq = malloc(nsig * sizeof(double))) == NULL) { + fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + + if (nosig == 0) { /* initialize signal list if necessary */ + if ((siglist = malloc(nsig * sizeof(int))) == NULL) { + fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + for ( ; nosig < nsig; nosig++) + siglist[nosig] = nosig; + } + + if ((so = malloc(nosig * sizeof(WFDB_Siginfo))) == NULL) { + fprintf(stderr, "%s: insufficient memory\n", pname); exit(2); } @@ -283,10 +328,6 @@ printf("Signal %d free space: '%s'\n", i, buf); } - if (nosig == 0) /* initialize signal list if necessary */ - for ( ; nosig < nsig; nosig++) - siglist[nosig] = nosig; - /* Determine the base sampling frequency (the lowest sampling frequency for any signal in the signal list) */ sps = 0; @@ -307,7 +348,7 @@ for (i = 0; i < nosig; i++) { si[siglist[i]].fname = buf; si[siglist[i]].fmt = 16; - tspf += si[siglist[i]].spf = sampfreq[siglist[i]]/sps; + tspf += si[siglist[i]].spf = (int)(sampfreq[siglist[i]]/sps + 0.5); so[i] = si[siglist[i]]; } @@ -315,30 +356,12 @@ printf("\nOUTPUT:\nBase sampling frequency: %g Hz\n", sps); for (i = j = k = 0; i < nosig; i++) { - if ((j = si[siglist[i]].spf) > k) - k = j; + if ((j = si[siglist[i]].spf) > k) { + k = j; l = siglist[i]; + } if (vflag) printf(" Signal %d samples per second: %g (%d sample%s per frame)\n", i, sampfreq[siglist[i]], j, j > 1 ? "s" : ""); - } - if (k > WFDB_MAXSPF) { - fprintf(stderr, "%s: too many samples of signal %d per frame\n\n", - pname, i); - fprintf(stderr, -" There can be at most %d samples per signal per frame, and you would need\n", - WFDB_MAXSPF); - fprintf(stderr, -" at least %d samples per signal per frame in order to convert this record.\n", - k); - fprintf(stderr, -"\n You may avoid this problem by using the '-s' option to exclude one or\n"); - fprintf(stderr, -" more signals, or you can change WFDB_MAXSPF to a value of %d or more\n", k); - fprintf(stderr, -" in wfdb.h, and then recompile the WFDB library and any applications\n"); - fprintf(stderr, -" that depend on WFDB_MAXSPF, including this one.\n\n"); - exit(2); } vin = (char **)malloc(nsig * sizeof(char *)); diff -Naur wfdb-10.1.6/data/100s.hea wfdb-10.2.0/data/100s.hea --- wfdb-10.1.6/data/100s.hea Thu Jun 24 11:38:28 1999 +++ wfdb-10.2.0/data/100s.hea Fri Sep 7 17:20:03 2001 @@ -1,6 +1,6 @@ 100s 2 360 21600 -100s.dat 212 200(0) 11 1024 995 21537 0 MLII -100s.dat 212 200(0) 11 1024 1011 -3962 0 V5 +100s.dat 212 200 11 1024 995 21537 0 MLII +100s.dat 212 200 11 1024 1011 -3962 0 V5 # 69 M 1085 1629 x1 # Aldomet, Inderal #Produced by xform from record 100, beginning at 0:0 diff -Naur wfdb-10.1.6/data/Makefile wfdb-10.2.0/data/Makefile --- wfdb-10.1.6/data/Makefile Wed Aug 1 10:28:34 2001 +++ wfdb-10.2.0/data/Makefile Mon Oct 15 14:40:00 2001 @@ -33,12 +33,12 @@ # listing'. # _____________________________________________________________________________ # file: version.def G. Moody 24 May 2000 -# Last revised: 28 February 2001 +# Last revised: 14 August 2001 # Each release of the WFDB Software Package is identified by a three-part # version number, defined here: MAJOR = 10 -MINOR = 1 -RELEASE = 6 +MINOR = 2 +RELEASE = 0 VERSION = $(MAJOR).$(MINOR).$(RELEASE) # VDEFS is the set of C compiler options needed to set version number variables @@ -46,7 +46,7 @@ VDEFS = -DWFDB_MAJOR=$(MAJOR) -DWFDB_MINOR=$(MINOR) -DWFDB_RELEASE=$(RELEASE) # _____________________________________________________________________________ -PACKAGE=wfdb-10.1.6 +PACKAGE=wfdb-10.2.0 # file: linux.def G. Moody 31 May 2000 # Last revised: 5 June 2000 # 'make' definitions for compiling the WFDB Software Package under Linux diff -Naur wfdb-10.1.6/data/Makefile-dos-gcc wfdb-10.2.0/data/Makefile-dos-gcc --- wfdb-10.1.6/data/Makefile-dos-gcc Wed May 24 22:35:27 2000 +++ wfdb-10.2.0/data/Makefile-dos-gcc Wed Dec 31 19:00:00 1969 @@ -1,23 +0,0 @@ -# file: Makefile-dos-gcc G. Moody 24 April 1997 -# Last revised: 7 May 1999 -# GCC-DOS `make' description file for `micro-database' -# -# This file is used with the UNIX `make' command to install the micro-database -# that comes with the WFDB software package. Before using it for the first -# time, check that the site-specific variables below are appropriate for your -# system. To install the micro-database, just type `make -f Makefile-dos-gcc' -# (from within this directory). - -# Site-specific variables -# ----------------------- - -# DBDIR specifies the name of a directory in which to install the contents -# of the `microdb' directory. -DBDIR = /usr/local/dos/database - -# It should not be necessary to modify anything below this line. -# ----------------------------------------------------------------------------- - -install: - -cp 100s.* multi.hea null.hea $(DBDIR) - diff -Naur wfdb-10.1.6/doc/Makefile wfdb-10.2.0/doc/Makefile --- wfdb-10.1.6/doc/Makefile Wed Aug 1 10:28:34 2001 +++ wfdb-10.2.0/doc/Makefile Mon Oct 15 14:40:00 2001 @@ -101,12 +101,12 @@ # all freely available (see `../SOURCES'). # _____________________________________________________________________________ # file: version.def G. Moody 24 May 2000 -# Last revised: 28 February 2001 +# Last revised: 14 August 2001 # Each release of the WFDB Software Package is identified by a three-part # version number, defined here: MAJOR = 10 -MINOR = 1 -RELEASE = 6 +MINOR = 2 +RELEASE = 0 VERSION = $(MAJOR).$(MINOR).$(RELEASE) # VDEFS is the set of C compiler options needed to set version number variables @@ -114,7 +114,7 @@ VDEFS = -DWFDB_MAJOR=$(MAJOR) -DWFDB_MINOR=$(MINOR) -DWFDB_RELEASE=$(RELEASE) # _____________________________________________________________________________ -PACKAGE=wfdb-10.1.6 +PACKAGE=wfdb-10.2.0 # file: linux.def G. Moody 31 May 2000 # Last revised: 5 June 2000 # 'make' definitions for compiling the WFDB Software Package under Linux @@ -274,7 +274,7 @@ # package, specify the command needed to format them from the texinfo source # files. If you have the GNU `makeinfo' utility (the preferred formatter), # uncomment the next line. -MAKEINFO = makeinfo +MAKEINFO = makeinfo --force # Otherwise, you can use GNU emacs to do the job by uncommenting the next line. # MAKEINFO = ./makeinfo.sh diff -Naur wfdb-10.1.6/doc/Makefile.tpl wfdb-10.2.0/doc/Makefile.tpl --- wfdb-10.1.6/doc/Makefile.tpl Tue Dec 12 13:15:59 2000 +++ wfdb-10.2.0/doc/Makefile.tpl Mon Oct 15 14:39:48 2001 @@ -44,7 +44,7 @@ # package, specify the command needed to format them from the texinfo source # files. If you have the GNU `makeinfo' utility (the preferred formatter), # uncomment the next line. -MAKEINFO = makeinfo +MAKEINFO = makeinfo --force # Otherwise, you can use GNU emacs to do the job by uncommenting the next line. # MAKEINFO = ./makeinfo.sh diff -Naur wfdb-10.1.6/doc/appguide.int wfdb-10.2.0/doc/appguide.int --- wfdb-10.1.6/doc/appguide.int Tue Dec 12 13:38:03 2000 +++ wfdb-10.2.0/doc/appguide.int Mon Oct 15 17:51:15 2001 @@ -1,5 +1,5 @@ \" file: appguide.int G. Moody July 1989 -\" Last revised: 12 December 2000 +\" Last revised: 15 October 2001 \" Table of contents and introduction to the WFDB Applications Guide. \" \" To print this document using GNU groff, use: @@ -74,7 +74,7 @@ wfdbwhich find a WFDB file and print its pathname 84 wrann write a WFDB annotation file 85 wrsamp write WFDB signal files 86 -wview WFDB browser for MS Windows 87 +wview WFDB browser for MS Windows 88 xform sampling frequency, amplitude, and format conversion for WFDB records 92 @@ -91,7 +91,7 @@ \fBAppendices\fP \fIInstalling the WFDB Software Package\fP 109 - \fIEvaluating ECG Analyzers\fP 112 + \fIEvaluating ECG Analyzers\fP 113 .TE .LP diff -Naur wfdb-10.1.6/doc/ctotexi.c wfdb-10.2.0/doc/ctotexi.c --- wfdb-10.1.6/doc/ctotexi.c Wed Dec 31 19:00:00 1969 +++ wfdb-10.2.0/doc/ctotexi.c Mon Oct 15 11:20:04 2001 @@ -0,0 +1,22 @@ +#include + +main() +{ + char ibuf[120], *p; + int col, line = 0; + + while (fgets(ibuf, sizeof(ibuf), stdin)) { + if (++line < 10) printf(" "); + printf("@i{%d} ", line); + for (col = 0, p = ibuf; *p; p++, col++) { + if (*p == '{' || *p == '}' || *p == '@') + putchar('@'); + else if (*p == '\t') { + *p = ' '; + while (++col % 8) + putchar(' '); + } + putchar(*p); + } + } +} diff -Naur wfdb-10.1.6/doc/dbu.tex wfdb-10.2.0/doc/dbu.tex --- wfdb-10.1.6/doc/dbu.tex Tue Dec 19 08:22:18 2000 +++ wfdb-10.2.0/doc/dbu.tex Mon Oct 15 17:35:41 2001 @@ -9,7 +9,7 @@ @sp 5 @center @titlefont{WFDB Programmer's Guide} @sp 4 -@center Tenth Edition (revised and with additions for WFDB library version 10.1.4) +@center Tenth Edition (revised and with additions for WFDB library version 10.2.0) @center @today @sp 5 @center George B. Moody @@ -17,7 +17,7 @@ @center Harvard-MIT Division of Health Sciences and Technology @page @vskip 0pt plus 1filll -Copyright @copyright{} 1989 -- 2000 George B. Moody +Copyright @copyright{} 1989 -- 2001 George B. Moody @sp 2 The most recent versions of the software described in this guide may be downloaded from @code{http://www.physionet.org/}. For further @@ -65,7 +65,7 @@ This guide documents the Waveform Database interface library (the WFDB library). This file contains the text of the Tenth Edition of the @cite{WFDB Programmer's Guide} (January, 2000), with -additional material for release 10.1.1 of the WFDB library. +additional material for release 10.2.0 of the WFDB library. @end ifinfo @menu @@ -484,9 +484,84 @@ This section contains a brief summary of changes to the WFDB library and to this guide since the first printing of the ninth edition of this guide in July, -1995. See @file{NEWS.TXT} and @file{NEWNEWS.TXT}, in the top-level directory -of the WFDB Software Package distribution, for details on these changes, and -for information on any more recent changes that may not be described here. +1995. See @file{NEWS}, in the top-level directory of the WFDB Software +Package distribution, for details on these changes, and for information on any +more recent changes that may not be described here. + +@unnumberedsubsec Changes in version 10.2.0 + +There are no longer any fixed limits on the numbers of signals or annotation +files that can be opened simultaneously, or on the number of samples per signal +per frame. In previous versions of the WFDB library, the symbols +@code{WFDB_MAXSIG}, @code{WFDB_MAXANN}, and @code{WFDB_MAXSPF} (all defined in +@file{}) specified limits on these parameters that could be +modified only by recompiling the WFDB library. These symbols are still defined +for compatibility with older applications that use them (typically to determine +the size of statically allocated arrays). + +Since version 10.1.1, record names may include path information (see the notes +for version 10.1.1 below), but if such names are used to generate names of WFDB +output files, the user has been required to ensure that the target directory +exists. This requirement is eliminated in version 10.2.0. If an output file +is specified to be located in a non-existent directory, the WFDB library will +attempt to create the directory (including, if necessary, any non-existent +parent directories). This feature simplifies the use of record names that +include directory information, as is common when reading data from a CD-ROM or +a web server such as PhysioNet. For example, using the default WFDB path +(@file{. http://@-www.@-physio@-net.@-org/@-physio@-bank/@-data@-base}), if the +current directory, @file{.}, does not contain a subdirectory named +@file{mitdb}, the command: + +@example +sqrs -r mitdb/100 +@end example + +@noindent +will read its input from +@file{http://@-www.@-physio@-net.@-org/@-physio@-bank/@-data@-base/@-mitdb/}, +will create a directory named @file{mitdb} within the current directory, and +will write its output annotation file (@file{100.qrs}) into this newly-created +directory. If we then use the command: + +@example +rdann -r mitdb/100 -a qrs +@end example + +@noindent +the header file is still read from the remote directory, but the annotation +file is read from @file{./mitdb}. (The programs @file{sqrs} and @file{rdann} +are standard applications that use the WFDB library; see the @cite{WFDB +Applications Guide} for details.) + +Also new is the WFDB test suite (located in the @file{checkpkg} directory of +the WFDB source tree, at the same level as the @file{lib} directory containing +the WFDB library sources). This set of programs can be used to help verify +that a newly-installed version of the WFDB library behaves properly. + +@unnumberedsubsec Changes in version 10.1.6 + +The WFDB library requires that the record name specified in the first line +of a header file must match the name of the record with which the header file +is associated (this is done in order to detect corrupted or erroneously +renamed header files). Version 10.1.6 requires that only the final portion of +the record name (stripped of any path information) must match. + +@unnumberedsubsec Changes in version 10.1.5 + +More changes in the @file{make} description files, for Cygwin compatibility. + +@unnumberedsubsec Changes in version 10.1.4 + +The symbol @code{WFDB_NETFILES} replaces the old @code{NETFILES}. + +@unnumberedsubsec Changes in version 10.1.3 + +More changes in the @file{make} description files, to support a configuration +script. + +@unnumberedsubsec Changes in version 10.1.2 + +Changes in the @file{make} description files. @unnumberedsubsec Changes in version 10.1.1 @@ -659,7 +734,8 @@ @unnumberedsubsec Changes in version 9.5 The number of signals that may be read simultaneously, @code{WFDB_MAXSIG}, -was increased from 16 to 32. +was increased from 16 to 32. [This limit has been eliminated entirely as of +version 10.2.0.] @unnumberedsubsec Changes in version 9.4.2 @@ -1245,10 +1321,7 @@ (@pxref{WFDB_Anninfo structures}), @end ifinfo one for each annotator to be opened. @var{nann} is the number of -@code{WFDB_Anninfo} structures in @var{aiarray}; @var{nann} must be no -greater than twice @code{WFDB_MAXANN} (a constant defined in -@file{}), and no more than @code{WFDB_MAXANN} input and -@code{WFDB_MAXANN} output annotators may be open at once. The caller must +@code{WFDB_Anninfo} structures in @var{aiarray}. The caller must fill in the @code{WFDB_Anninfo} structures to specify the names of the annotators, and to indicate which annotators are to be read, and which are to be written. Input and output annotators may be listed in any @@ -1336,49 +1409,72 @@ @ifinfo (@pxref{WFDB_Siginfo structures}), @end ifinfo -one for each signal to be opened. The number of -@code{WFDB_Siginfo} structures in @var{siarray}, @var{nsig}, need never be -greater than @code{WFDB_MAXSIG} (a constant defined in @file{}); -@code{isigopen} normally returns the number of input signals it actually -opened, which may be less than @var{nsig} but is never greater than -@var{nsig}. The caller must allocate storage for the @code{WFDB_Siginfo} -structures; @code{isigopen} will fill them in with information about the -signals. @dfn{Signal numbers} are assigned in the order in which -signals are specified in the @file{header} file for the record; on -return from @code{isigopen}, information for signal @var{i} will be -found in @var{siarray[i]}. For example, we can read the @code{gain} -attributes of each signal in record @file{100s} like this: +one for each signal to be opened. + +As a special case, if @var{nsig} is 0, @var{siarray} can be @code{NULL}. +In this case, @code{isigopen} closes any open input signals, then +returns the number of signals in @var{record} without opening them. Use +this feature to determine the amount of storage needed for +signal-related variables, as in the example below, or to force open +input signal files to be closed without closing open annotation or +output signal files. This action also sets internal WFDB library +variables that record the base time and date, the length of the record, +and the sampling and counter frequencies, so that time conversion +functions such as @code{strtim} that depend on these quantities will +work properly. + +If @code{nsig} is greater than 0, @code{isigopen} normally returns the +number of input signals it actually opened, which may be less than +@var{nsig} but is never greater than @var{nsig}. The caller must +allocate storage for the @code{WFDB_Siginfo} structures; @code{isigopen} +will fill them in with information about the signals. @dfn{Signal +numbers} are assigned in the order in which signals are specified in the +@file{header} file for the record; on return from @code{isigopen}, +information for signal @var{i} will be found in @var{siarray[i]}. For +example, we can read the @code{gain} attributes of each signal in record +@file{100s} like this: @c @group @example -@dots{} -static WFDB_Siginfo s[WFDB_MAXSIG]; -int i, nsig; +#include +#include +#include -nsig = isigopen("100s", s, WFDB_MAXSIG); -for (i = 0; i < nsig; i++) - printf("signal %d gain = %g\n", i, s[i].gain); -@dots{} +main() +@{ + int i, nsig; + WFDB_Siginfo *siarray; + + nsig = isigopen("100s", NULL, 0); + if (nsig < 1) + exit(1); + siarray = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); + nsig = isigopen("100s", siarray, nsig); + for (i = 0; i < nsig; i++) + printf("signal %d gain = %g\n", i, siarray[i].gain); + exit(0); +@} @end example @c @end group @noindent -Notice that the @code{for} loop is never executed if @code{isigopen} -encounters an error, since @code{nsig} is less than 1 in such cases. -The array of @code{WFDB_Siginfo} structures is declared @code{static}, a -practice that is recommended for all arrays and data structures of any -substantial size, to avoid run-time stack overflow. +This program, unlike the example in the previous chapter, does not +assume that the number of signals is known. The first invocation of +@code{isigopen} determines this number (and the program quits if there +are no signals). Next, the program allocates the array for the signal +information, and then it opens the signals using the second +invocation of @code{isigopen}, passing in the pointer @code{siarray} and the +number of signals determined from the first call (@code{nsig}). An error message is produced if @code{isigopen} is unable to open @emph{any} of the signals listed in the @file{header} file. It is not considered an error if only some of the signals can be opened, however. A signal will not be opened if its signal file is unreadable, if an input buffer cannot be allocated for it, or if opening all of the -signals in its group would exceed the limits defined by @var{nsig} or -@code{WFDB_MAXSIG}. (On existing CD-ROMs containing database records, there is -only one signal group for each record; as a consequence, @code{isigopen} -fails if @var{nsig} is less than the number of available signals while -attempting to read a CD-ROM record.) If necessary, the caller can +signals in its group would exceed the limits defined by @var{nsig}. +(Note, however, that most records have only one signal group; as a +consequence, @code{isigopen} fails if @var{nsig} is less than the +total number of signals in such cases.) If necessary, the caller can inspect the file names and signal descriptions in @var{siarray} to determine which signals were opened; @iftex @@ -1391,7 +1487,7 @@ illustrate the use of @code{isigopen}; for example, @pxref{Example 5}. -If @var{nsig} is not positive, @code{isigopen} fills in up to +If @var{nsig} is less than 0, @code{isigopen} fills in up to @iftex @minus{}@var{nsig} @end iftex @@ -1406,10 +1502,6 @@ The features described in this paragraph were first introduced in version 4.4 of the WFDB library. -As a special case, if @var{nsig} is 0, @var{siarray} can be @code{NULL}. -This can be useful to force open input signal files to be closed without -closing open annotation or output signal files. - @c @group @node osigopen, osigfopen, isigopen, selecting @unnumberedsubsec osigopen @@ -1517,8 +1609,7 @@ (@pxref{WFDB_Siginfo structures}), @end ifinfo one for each signal to be opened. @var{nsig} is the number of -@code{WFDB_Siginfo} structures in @var{siarray}; @var{nsig} must be no -greater than @code{WFDB_MAXSIG} (a constant defined in @file{}). +@code{WFDB_Siginfo} structures in @var{siarray}. Before invoking @code{osigfopen}, the caller must fill in the fields of the @code{WFDB_Siginfo} structures in @var{siarray} (@pxref{Data Types}; @@ -1644,24 +1735,29 @@ allocate storage for an array of WFDB_Samples (integers) and pass a pointer to this array to @code{getvec}. (The length of the array must be no less than the number of input signals, as obtained from -@code{isigopen} or @code{wfdbinit}; this number will never exceed -@code{WFDB_MAXSIG}, defined in @file{}.) On return, -@var{vector[i]} contains the next sample from signal @var{i}. For -example, this modified version of the example from chapter 1 reads and -prints the first ten samples of each available input signal: +@code{isigopen} or @code{wfdbinit}.) On return, @var{vector[i]} +contains the next sample from signal @var{i}. For example, this +modified version of the example from chapter 1 reads and prints the +first ten samples of each available input signal: @example +#include +#include #include main() @{ int i, j, nsig; - WFDB_Sample v[WFDB_MAXSIG]; - static WFDB_Siginfo s[WFDB_MAXSIG]; + WFDB_Sample *v; + WFDB_Siginfo *s; - nsig = isigopen("100s", s, WFDB_MAXSIG); + nsig = isigopen("100s", NULL, 0); if (nsig < 1) exit(1); + s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); + if (isigopen("100s", s, nsig) != nsig) + exit(1); + v = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); for (i = 0; i < 10; i++) @{ if (getvec(v) < 0) break; @@ -1673,13 +1769,10 @@ @} @end example -Notice how the value returned by @code{isigopen} is used to determine -how many input signals there are. The array of @code{WFDB_Siginfo} -structures is declared @code{static}, a practice that is recommended -for all arrays and data structures of any substantial size, to avoid -run-time stack overflow. Several of the example programs in chapter 6 -illustrate the use of @code{getvec}; for example, @pxref{Example -6}. +Notice how the value returned by the first invocation of @code{isigopen} +is used to determine how many input signals there are. Several of the +example programs in chapter 6 illustrate the use of @code{getvec}; for +example, @pxref{Example 6}. @c @group @node getframe, putvec, getvec, signal and annotation I/O @@ -1758,8 +1851,7 @@ fill an array of WFDB_Samples with the samples and pass a pointer to this array to @code{putvec}. (The length of the array must be no less than the number of output signals, as given to @code{osigfopen} or -@code{osigopen}; this number must never exceed @code{WFDB_MAXSIG}, defined in -@file{}.) On entry, @var{vector[i]} contains the next sample +@code{osigopen}.) On entry, @var{vector[i]} contains the next sample from signal @var{i}. For example, this modified version of the previous example @iftex @@ -1771,17 +1863,23 @@ copies the first ten samples of each available input signal: @example +#include #include main() @{ - int i, nsig; - WFDB_Sample v[WFDB_MAXSIG]; - static WFDB_Siginfo s[WFDB_MAXSIG]; + int i, j, nsig; + WFDB_Sample *v; + WFDB_Siginfo *s; - if ((nsig = isigopen("100s", s, WFDB_MAXSIG)) < 1 || - osigopen("8l", s, nsig) < 1) + nsig = isigopen("100s", NULL, 0); + if (nsig < 1) + exit(1); + s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); + if (isigopen("100s", s, nsig) != nsig || + osigopen("8l", s, nsig) != nsig) exit(1); + v = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); for (i = 0; i < 10; i++) if (getvec(v) < 0 || putvec(v) < 0) break; @@ -2893,9 +2991,11 @@ @example @dots{} int nsig, status; -WFDB_Siginfo s[WFDB_MAXSIG]; +WFDB_Siginfo *s; -nsig = isigopen("old", s, -WFDB_MAXSIG); +nsig = isigopen("old", NULL, 0); +s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); +nsig = isigopen("old", s, -nsig); if (nsig > 0) @{ s[0].gain = 100.0; status = setheader("new", s, (unsigned int)nsig); @@ -3750,11 +3850,14 @@ char *record; int nsig; WFDB_Signal s; -static WFDB_Siginfo siarray[WFDB_MAXSIG]; +static WFDB_Siginfo *si; @dots{} -if ((nsig = isigopen(record, siarray, WFDB_MAXSIG)) < 1) +if ((nsig = isigopen(record, NULL, 0)) < 1) + exit(1); +si = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); +if (si == NULL || isigopen(record, siarray, nsig)!= nsig) exit(1); for (s = 0; s < nsig; s++) @{ wfdbsetskew(s, wfdbgetskew(s)); @@ -4022,11 +4125,10 @@ @cindex signals (oversampled) @cindex samples per frame the number of samples per frame. This is 1, for all except oversampled -signals in multi-frequency records, for which @code{spf} may be between -2 and @code{WFDB_MAXSPF} (defined in @file{}). Note that -non-integer values are not permitted (thus the frame rate must be chosen -such that all sampling frequencies used in the record are integer -multiples of the frame rate). +signals in multi-frequency records, for which @code{spf} may be any +positive integer. Note that non-integer values are not permitted (thus +the frame rate must be chosen such that all sampling frequencies used in +the record are integer multiples of the frame rate). @item int bsize @cindex block size @@ -4095,9 +4197,7 @@ which the signals are given in @var{siarray}. Note that input signal 0 and output signal 0 are distinct. Input signal numbers are supplied to @code{aduphys}, @code{physadu}, @code{adumuv}, and @code{muvadu} in -their first arguments. There may be no more than @code{WFDB_MAXSIG} -(defined in @file{}) input signals and @code{WFDB_MAXSIG} output -signals open at once. @xref{Example 5}, for an illustration of how to +their first arguments. @xref{Example 5}, for an illustration of how to read signal specifications from @code{WFDB_Siginfo} structures. @node WFDB_Calinfo structures, WFDB_Anninfo structures, WFDB_Siginfo structures, Data Types @@ -4227,9 +4327,7 @@ array of @code{WFDB_Anninfo} objects. Output annotator numbers used by @code{putann} also start at 0; note that input annotator 0 and output annotator 0 are distinct. Annotator numbers are supplied to -@code{getann} and @code{putann} in their first arguments. There may be -no more than @code{WFDB_MAXANN} (defined in @file{}) input -annotators and @code{WFDB_MAXANN} output annotators open at once. +@code{getann} and @code{putann} in their first arguments. @iftex @xref{annopen, , @code{annopen}}, @end iftex @@ -4545,7 +4643,9 @@ Thus, for example, record 100 of the MIT-BIH Arrhythmia Database consists of the files named @file{100.hea}, @file{100.dat}, and @file{100.atr} in the @file{mitdb} directory of the MIT-BIH Arrhythmia -Database CD-ROM, together with any additional files in other directories +Database CD-ROM (or in PhysioBank, within +@code{http://@-www.@-physio@-net.@-org/@-physio@-bank/@-data@-base/@-mitdb/}), +together with any additional files in other directories that you may have associated with record 100 (such as your own annotation file). All files associated with a given record include the record name in their file names, either as the first part of the name @@ -4936,18 +5036,19 @@ specifications. Piped records for reading or writing other numbers of signals also exist; they are named @file{8x@var{n}} and @file{16x@var{n}}, where @var{n} is the number of signals (@var{n} = 1, -2, @dots{}, @code{WFDB_MAXSIG}). +2, @dots{}, 16; piped record header files can be created with larger +numbers of signals (use the existing files as a model). @cindex local record @cindex signal file (local) Application programs may also read or write signal files in the current directory using @dfn{local record} @file{header} files. Record -@file{16l} (``one-six-ell'') specifies up to @code{WFDB_MAXSIG} format 16 +@file{16l} (``one-six-ell'') specifies up to sixteen format 16 files, and record @file{8l} (``eight-ell'') specifies up to -@code{WFDB_MAXSIG} format 8 files, named @file{data0}, @file{data1}, +sixteen format 8 files, named @file{data0}, @file{data1}, @file{data2}, @dots{}, @file{data@var{n}} in the current directory. When opened using @code{isigopen} or @code{wfdbinit}, these signal files -will be readable by @code{getvec} as signals 0, 1, 2, @dots{} @var{n} +will be readable by @code{getvec} as signals 0, 1, 2, @dots{} 16 respectively. These files should be created by the user, with the use of @code{putvec}. It is necessary to create only as many signal files as will be used; if, for example, only one signal is needed, only @@ -5427,81 +5528,92 @@ @i{5} int argc; @i{6} char *argv[]; @i{7} @{ - @i{8} static WFDB_Siginfo s[WFDB_MAXSIG]; + @i{8} WFDB_Siginfo *s; @i{9} int i, nsig; @i{10} @i{11} if (argc < 2) @{ @i{12} fprintf(stderr, "usage: %s record\n", argv[0]); @i{13} exit(1); @i{14} @} -@i{15} nsig = isigopen(argv[1], s, WFDB_MAXSIG); +@i{15} nsig = isigopen(argv[1], NULL, 0); @i{16} if (nsig < 1) exit(2); -@i{17} printf("Record %s\n", argv[1]); -@i{18} printf("Starting time: %s\n", timstr(0L)); -@i{19} printf("Sampling frequency: %g Hz\n", sampfreq(argv[1])); -@i{20} printf("%d signals\n", nsig); -@i{21} for (i = 0; i < nsig; i++) @{ -@i{22} printf("Group %d, Signal %d:\n", s[i].group, i); -@i{23} printf(" File: %s\n", s[i].fname); -@i{24} printf(" Description: %s\n", s[i].desc); -@i{25} printf(" Gain: "); -@i{26} if (s[i].gain == 0.) -@i{27} printf("uncalibrated; assume %g", WFDB_DEFGAIN); -@i{28} else printf("%g", s[i].gain); -@i{29} printf(" adu/%s\n", s[i].units ? s[i].units : "mV"); -@i{30} printf(" Initial value: %d\n", s[i].initval); -@i{31} printf(" Storage format: %d\n", s[i].fmt); -@i{32} printf(" I/O: "); -@i{33} if (s[i].bsize == 0) printf("can be unbuffered\n"); -@i{34} else printf("%d-byte blocks\n", s[i].bsize); -@i{35} printf(" ADC resolution: %d bits\n", s[i].adcres); -@i{36} printf(" ADC zero: %d\n", s[i].adczero); -@i{37} if (s[i].nsamp > 0L) @{ -@i{38} printf(" Length: %s (%ld sample intervals)\n", -@i{39} timstr(s[i].nsamp), s[i].nsamp); -@i{40} printf(" Checksum: %d\n", s[i].cksum); -@i{41} @} -@i{42} else printf(" Length undefined\n"); -@i{43} @} -@i{44} exit(0); -@i{45} @} +@i{17} s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); +@i{18} if (s == NULL) @{ +@i{19} fprintf(stderr, "insufficient memory\n"); +@i{20} exit(3); +@i{21} @} +@i{22} if (isigopen(argv[1], s, nsig) != nsig) exit(2); +@i{23} printf("Record %s\n", argv[1]); +@i{24} printf("Starting time: %s\n", timstr(0L)); +@i{25} printf("Sampling frequency: %g Hz\n", sampfreq(argv[1])); +@i{26} printf("%d signals\n", nsig); +@i{27} for (i = 0; i < nsig; i++) @{ +@i{28} printf("Group %d, Signal %d:\n", s[i].group, i); +@i{29} printf(" File: %s\n", s[i].fname); +@i{30} printf(" Description: %s\n", s[i].desc); +@i{31} printf(" Gain: "); +@i{32} if (s[i].gain == 0.) +@i{33} printf("uncalibrated; assume %g", WFDB_DEFGAIN); +@i{34} else printf("%g", s[i].gain); +@i{35} printf(" adu/%s\n", s[i].units ? s[i].units : "mV"); +@i{36} printf(" Initial value: %d\n", s[i].initval); +@i{37} printf(" Storage format: %d\n", s[i].fmt); +@i{38} printf(" I/O: "); +@i{39} if (s[i].bsize == 0) printf("can be unbuffered\n"); +@i{40} else printf("%d-byte blocks\n", s[i].bsize); +@i{41} printf(" ADC resolution: %d bits\n", s[i].adcres); +@i{42} printf(" ADC zero: %d\n", s[i].adczero); +@i{43} if (s[i].nsamp > 0L) @{ +@i{44} printf(" Length: %s (%ld sample intervals)\n", +@i{45} timstr(s[i].nsamp), s[i].nsamp); +@i{46} printf(" Checksum: %d\n", s[i].cksum); +@i{47} @} +@i{48} else printf(" Length undefined\n"); +@i{49} @} +@i{50} exit(0); +@i{51} @} @end example @noindent @strong{Notes:} @table @emph -@item Line 8: -There might be as many as @code{WFDB_MAXSIG} signals, so we allocate enough -@code{WFDB_Siginfo} objects to accommodate them all. - @item Line 15: The command-line argument, @code{argv[1]}, is the record name. The -number of readable signals is @code{nsig}. This program will give -specifications for each of them, but not for any signals that are named -in the @file{header} file but are not readable. If @code{nsig} < 1, -@code{isigopen} will print an error message; in this case the program -can't do anything useful, so it exits. +number of signals listed in the header file for the record is returned by +@code{isigopen} as @code{nsig}. If @code{nsig} < 1, @code{isigopen} will +print an error message; in this case the program can't do anything useful, +so it exits. -@item Line 18: +@item Line 17: +We allocate @code{nsig} signal information (@code{WFDB_Siginfo}) objects. + +@item Line 22: +On the second invocation of @code{isigopen}, we pass the pointer to the +signal information objects and the number of signals we expect to open. +@code{isigopen} returns the number of signals it is able to open; if +any of those named in the header file are unreadable, the return value +will not match @code{nsig}, and the program exits. + +@item Line 24: Invoking @code{timstr} with an argument of zero (here written @samp{0L} to emphasize to the compiler that the argument is a @code{long} integer) will obtain the starting time of the record. If no starting time is defined, @code{timstr} will return ``@code{0:00:00}''. -@item Lines 25--28: +@item Lines 31--34: Notice how a zero value for @code{gain} is interpreted. -@item Line 29: +@item Line 35: If the @code{units} field is NULL, the physical units are assumed to be millivolts (``mV''). -@item Lines 32--34: +@item Lines 38--40: If @code{bsize} is zero, I/O can be performed in blocks of any reasonable size; otherwise it must be performed in blocks of exactly the specified @code{bsize}. -@item Lines 37--42: +@item Lines 43--48: If the length of the record is defined, it is printed in both hours, minutes, and seconds, and in sample intervals. Since the argument of @code{timstr} in line 39 is positive, it is interpreted as a time @@ -5523,59 +5635,67 @@ @example @i{1} #include @i{2} #include - @i{3} + @i{3} @i{4} main(argc, argv) @i{5} int argc; @i{6} char *argv[]; @i{7} @{ - @i{8} static WFDB_Siginfo s[WFDB_MAXSIG]; - @i{9} int i, nsig, nsamp = 1000; -@i{10} WFDB_Sample vin[WFDB_MAXSIG], vout[WFDB_MAXSIG]; -@i{11} + @i{8} WFDB_Siginfo *s; + @i{9} int i, nsig, nsamp=1000; +@i{10} WFDB_Sample *vin, *vout; +@i{11} @i{12} if (argc < 2) @{ @i{13} fprintf(stderr, "usage: %s record\n", argv[0]); exit(1); @i{14} @} -@i{15} if ((nsig = isigopen(argv[1], s, WFDB_MAXSIG)) <= 0) exit(2); -@i{16} if (osigopen("8l", s, nsig) <= 0) exit(3); -@i{17} while (nsamp-- > 0 && getvec(vin) > 0) @{ -@i{18} for (i = 0; i < nsig; i++) -@i{19} vout[i] -= vin[i]; -@i{20} if (putvec(vout) < 0) break; -@i{21} for (i = 0; i < nsig; i++) -@i{22} vout[i] = vin[i]; -@i{23} @} -@i{24} (void)newheader("dif"); -@i{25} wfdbquit(); -@i{26} exit(0); -@i{27} @} +@i{15} if ((nsig = isigopen(argv[1], NULL, 0)) <= 0) exit(2); +@i{16} s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); +@i{17} vin = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); +@i{18} vout = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); +@i{19} if (s == NULL || vin == NULL || vout == NULL) @{ +@i{20} fprintf(stderr, "insufficient memory\n"); +@i{21} exit(3); +@i{22} @} +@i{23} if (isigopen(argv[1], s, nsig) != nsig) exit(2); +@i{24} if (osigopen("8l", s, nsig) <= 0) exit(3); +@i{25} while (nsamp-- > 0 && getvec(vin) > 0) @{ +@i{26} for (i = 0; i < nsig; i++) +@i{27} vout[i] -= vin[i]; +@i{28} if (putvec(vout) < 0) break; +@i{29} for (i = 0; i < nsig; i++) +@i{30} vout[i] = vin[i]; +@i{31} @} +@i{32} (void)newheader("dif"); +@i{33} wfdbquit(); +@i{34} exit(0); +@i{35} @} @end example @noindent @strong{Notes:} @table @emph -@item Line 16: +@item Line 24: Here we attempt to open as many output signals as there are input signals; if we cannot do so, the program exits after @code{osigopen} prints an error message. -@item Line 17: +@item Line 25: The main loop of the program begins here. If 1000 samples can be read from each signal, the loop will end normally; if @code{getvec} fails before 1000 samples have been read, the loop ends prematurely. -@item Lines 18--19: +@item Lines 26--27: For each signal, we compute the negated first difference by subtracting the new sample from the previous sample. -@item Line 20: +@item Line 28: One sample of each output signal is written here. -@item Lines 21--22: +@item Lines 29--30: The new input samples are copied into the output sample vector in preparation for the next iteration. -@item Line 24: +@item Line 32: This step is optional. It creates a @file{header} file for a new record to be called @file{dif}, which we can then open with another program if we want to read the signals that this program has written. Since the @@ -5585,7 +5705,7 @@ not necessarily indicate the proper sampling frequency for these signals. -@item Line 25: +@item Line 33: Since the program writes output signals, it must invoke @code{wfdbquit} to close the files properly. @end table @@ -5616,85 +5736,96 @@ @i{1} #include @i{2} #include @i{3} #define BUFLN 512 - @i{4} int sample_ok = 1; - @i{5} - @i{6} WFDB_Sample sample(s, t) - @i{7} WFDB_Signal s; - @i{8} WFDB_Time t; - @i{9} @{ -@i{10} static WFDB_Sample sbuf[BUFLN][WFDB_MAXSIG]; -@i{11} static WFDB_Time tt = -1L; -@i{12} + @i{4} int nsig, sample_ok = 1; + @i{5} WFDB_Sample *sbuf; + @i{6} + @i{7} sample(s, t) + @i{8} int s; + @i{9} long t; +@i{10} @{ +@i{11} static long tt = -1L; +@i{12} @i{13} if (t <= tt - BUFLN) @i{14} fprintf(stderr, "sample: buffer too short\n"); @i{15} while (t > tt) -@i{16} if (getvec(sbuf[(++tt)&(BUFLN-1)]) < 0) sample_ok = 0; -@i{17} return (sbuf[t&(BUFLN-1)][s]); -@i{18} @} -@i{19} -@i{20} main(argc, argv) -@i{21} int argc; -@i{22} char *argv[]; -@i{23} @{ -@i{24} double *c, one = 1.0, vv, atof(); -@i{25} int i, j, nc = argc - 4, nsig, v[WFDB_MAXSIG]; -@i{26} long nsamp, t; -@i{27} static WFDB_Siginfo s[WFDB_MAXSIG]; -@i{28} -@i{29} if (argc < 4) @{ -@i{30} fprintf(stderr, -@i{31} "usage: %s record start duration [ coefficients ... ]\n", -@i{32} argv[0]); -@i{33} exit(1); -@i{34} @} -@i{35} if (nc < 1) @{ -@i{36} nc = 1; c = &one; -@i{37} @} -@i{38} else if (nc >= BUFLN || -@i{39} (c = (double *)calloc(nc, sizeof(double))) == NULL) @{ -@i{40} fprintf(stderr, "%s: too many coefficients\n", argv[0]); -@i{41} exit(2); -@i{42} @} -@i{43} for (i = 0; i < nc; i++) -@i{44} c[i] = atof(argv[i+4]); -@i{45} if ((nsig = isigopen(argv[1], s, WFDB_MAXSIG)) < 1) -@i{46} exit(3); -@i{47} if (isigsettime(strtim(argv[2])) < 0) -@i{48} exit(4); -@i{49} if ((nsamp = strtim(argv[3])) < 1) @{ -@i{50} fprintf(stderr, "%s: inappropriate value for duration\n", -@i{51} argv[0]); -@i{52} exit(5); -@i{53} @} -@i{54} if (osigopen("16l", s, nsig) != nsig) -@i{55} exit(6); -@i{56} -@i{57} for (t = 0; t < nsamp && sample_ok; t++) @{ -@i{58} for (j = 0; j < nsig; j++) @{ -@i{59} for (i = 0, vv = 0.; i < nc; i++) -@i{60} if (c[i] != 0.) vv += c[i]*sample(j, t+i); -@i{61} v[j] = (int)vv; -@i{62} @} -@i{63} if (putvec(v) < 0) break; +@i{16} if (getvec(sbuf + nsig * ((++tt)&(BUFLN-1))) < 0) +@i{17} sample_ok = 0; +@i{18} return (*(sbuf + nsig * (t&(BUFLN-1)) + s)); +@i{19} @} +@i{20} +@i{21} main(argc, argv) +@i{22} int argc; +@i{23} char *argv[]; +@i{24} @{ +@i{25} double *c, one = 1.0, vv, atof(); +@i{26} int i, j, nc = argc - 4; +@i{27} long nsamp, t; +@i{28} static WFDB_Sample *v; +@i{29} static WFDB_Siginfo *s; +@i{30} +@i{31} if (argc < 4) @{ +@i{32} fprintf(stderr, +@i{33} "usage: %s record start duration [ coefficients ... ]\n", +@i{34} argv[0]); +@i{35} exit(1); +@i{36} @} +@i{37} if (nc < 1) @{ +@i{38} nc = 1; c = &one; +@i{39} @} +@i{40} else if (nc >= BUFLN || +@i{41} (c = (double *)calloc(nc, sizeof(double))) == NULL) @{ +@i{42} fprintf(stderr, "%s: too many coefficients\n", argv[0]); +@i{43} exit(2); +@i{44} @} +@i{45} for (i = 0; i < nc; i++) +@i{46} c[i] = atof(argv[i+4]); +@i{47} if ((nsig = isigopen(argv[1], NULL, 0)) < 1) +@i{48} exit(3); +@i{49} s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); +@i{50} v = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); +@i{51} sbuf = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)*BUFLN); +@i{52} if (s == NULL || v == NULL || sbuf == NULL) @{ +@i{53} fprintf(stderr, "insufficient memory\n"); +@i{54} exit(3); +@i{55} @} +@i{56} if (isigopen(argv[1], s, nsig) != nsig) +@i{57} exit(3); +@i{58} if (isigsettime(strtim(argv[2])) < 0) +@i{59} exit(4); +@i{60} if ((nsamp = strtim(argv[3])) < 1) @{ +@i{61} fprintf(stderr, "%s: inappropriate value for duration\n", +@i{62} argv[0]); +@i{63} exit(5); @i{64} @} -@i{65} -@i{66} (void)newheader("out"); -@i{67} wfdbquit(); -@i{68} exit(0); -@i{69} @} +@i{65} if (osigopen("16l", s, nsig) != nsig) +@i{66} exit(6); +@i{67} +@i{68} for (t = 0; t < nsamp && sample_ok; t++) @{ +@i{69} for (j = 0; j < nsig; j++) @{ +@i{70} for (i = 0, vv = 0.; i < nc; i++) +@i{71} if (c[i] != 0.) vv += c[i]*sample(j, t+i); +@i{72} v[j] = (int)vv; +@i{73} @} +@i{74} if (putvec(v) < 0) break; +@i{75} @} +@i{76} +@i{77} (void)newheader("out"); +@i{78} wfdbquit(); +@i{79} exit(0); +@i{80} @} @end example @noindent @strong{Notes:} @table @emph -@item Line 4: -@code{BUFLN} must be a power of 2 (why? see lines 16 and 17), and it +@item Line 3: +@code{BUFLN} must be a power of 2 (why? see lines 16 and 18), and it should be larger than the length of the filter (i.e., the caller should not look back further than @code{BUFLN-1} samples into the past, relative to the most recent sample that has been read). -@item Lines 6--18: +@item Lines 7--19: This function supplies input samples to the @code{main} routine as needed, and frees the @code{main} routine of the need to read them in strict time order. The @code{sample} function returns the sample from @@ -5707,46 +5838,47 @@ the most recently read sample. In this program, the test in line 13 is redundant (why?) and might be removed for efficiency's sake. -@item Lines 35--37: +@item Lines 37--39: If no coefficients are provided on the command line, the program will simply copy the selected segment of the input signals. -@item Lines 38--44: +@item Lines 40--46: If there are more coefficients than there are samples in the circular buffer, or if memory cannot be allocated for the coefficient vector, the program cannot work properly, so it exits with an error message. In -lines 43 and 44, the ASCII strings that represent the coefficients are +lines 45 and 46, the ASCII strings that represent the coefficients are converted to @code{double} format and stored in the coefficient vector. -@item Lines 45--48: +@item Lines 47--59: The record name is @code{argv[1]}, and the start time is @code{argv[2]}; if the record can't be opened, or the start time is inappropriate, the -program exits. +program exits. See the previous example for details on how @code{isigopen} +is used. -@item Lines 49--53: +@item Lines 60--64: The @var{duration} argument should be a time interval in @var{HH:MM:SS} format; @code{strtim} converts it to the appropriate number of samples. -@item Lines 54--55: +@item Lines 65--66: The output signals will be written to files in the current directory according to the specifications for record @file{16l} (@pxref{Piped and Local Records}). If we can't write as many output signals as there are input signals, the program exits. -@item Lines 57--64: +@item Lines 68--75: Here's where the work is done. The outer loop is executed once per sample vector, the middle loop once per signal, and the inner loop -once per coefficient. In line 60, we retrieve an input sample, +once per coefficient. In line 71, we retrieve an input sample, multiply it by a filter coefficient, and add it to a running sum. -The sum is initialized to zero in line 59 before we begin, and is -converted to an @code{int} in line 61 when we are finished. Once -an entire sample vector has been filtered, it is written out in line 63. +The sum (@code{vv}) is initialized to zero in line 70 before we begin, and is +converted to an @code{int} in line 72 when we are finished. Once +an entire sample vector has been filtered, it is written out in line 74. The entire process is repeated up to @code{nsamp} times, or until we run out of input samples. -@item Line 66: +@item Line 77: The program creates a @file{header} file for record @file{out}, using the signal specifications from record @file{16l} and the sampling frequency from the input record. @@ -5763,103 +5895,120 @@ data acquisition are hardware-dependent and are not shown here. @example - @i{1} #include - @i{2} #include - @i{3} - @i{4} main() - @i{5} @{ - @i{6} char answer[32], record[8], directory[32]; - @i{7} int i, nsig = 0, v[WFDB_MAXSIG]; - @i{8} long nsamp, t; - @i{9} double freq = 0.; -@i{10} static char filename[WFDB_MAXSIG][32], -@i{11} description[WFDB_MAXSIG][32], units[WFDB_MAXISIG][22]; -@i{12} static WFDB_Siginfo s[WFDB_MAXSIG]; -@i{13} -@i{14} do @{ -@i{15} printf("Choose a record name [up to 6 characters]: "); -@i{16} fgets(record, 8, stdin); record[strlen(record)-1] = '\0'; -@i{17} @} while (newheader(record) < 0); -@i{18} do @{ -@i{19} printf("Number of signals to be recorded [1-%d]: ", -@i{20} WFDB_MAXSIG); -@i{21} fgets(answer, 32, stdin); sscanf(answer, "%d", &nsig); -@i{22} @} while (nsig < 1 || nsig > WFDB_MAXSIG); -@i{23} do @{ -@i{24} printf("Sampling frequency [Hz per signal, > 0]: "); -@i{25} fgets(answer, 32, stdin); sscanf(answer, "%lf", &freq); -@i{26} @} while (setsampfreq(freq) < 0); -@i{27} do @{ -@i{28} printf("Length of record (H:M:S): "); -@i{29} fgets(answer, 32, stdin); -@i{30} @} while ((nsamp = strtim(answer)) < 1L); -@i{31} printf("Directory for signal files [up to 30 characters]: "); -@i{32} fgets(directory, 32, stdin); -@i{33} directory[strlen(directory)-1] = '\0'; -@i{34} printf("Save signals in difference format? [y/n]: "); -@i{35} fgets(answer, 32, stdin); -@i{36} s[0].fmt = (answer[0] == 'y') ? 8 : 16; -@i{37} printf("Save all signals in one file? [y/n]: "); -@i{38} fgets(answer, 32, stdin); -@i{39} if (answer[0] == 'y') @{ -@i{40} sprintf(filename[0], "%s/d.%s", directory, record); -@i{41} for (i = 0; i < nsig; i++) @{ -@i{42} s[i].fname = filename[0]; -@i{43} s[i].group = 0; -@i{44} @} -@i{45} @} -@i{46} else @{ -@i{47} for (i = 0; i < nsig; i++) @{ -@i{48} sprintf(filename[i], "%s/d%d.%s", directory,i,record); -@i{49} s[i].fname = filename[i]; -@i{50} s[i].group = i; -@i{51} @} -@i{52} @} -@i{53} for (i = 0; i < nsig; i++) @{ -@i{54} s[i].fmt = s[0].fmt; s[i].bsize = 0; -@i{55} printf("Signal %d description [up to 30 characters]: ", i); -@i{56} fgets(description[i], 32, stdin); -@i{57} description[i][strlen(description[i])-1] = '\0'; -@i{58} s[i].desc = description[i]; -@i{59} printf("Signal %d units [up to 20 characters]: ", i); -@i{60} fgets(units[i], 22, stdin); -@i{61} units[i][strlen(units[i])-1] = '\0'; -@i{62} s[i].units = (*units[i]) ? units[i] : "mV"; -@i{63} do @{ -@i{64} printf(" Signal %d gain [adu/%s]: ", i, s[i].units); -@i{65} fgets(answer, 32, stdin); -@i{66} sscanf(answer, "%lf", &s[i].gain); -@i{67} @} while (s[i].gain < 0.); -@i{68} do @{ -@i{69} printf(" Signal %d ADC resolution in bits [8-16]: ", i); -@i{70} fgets(answer, 32, stdin); -@i{71} sscanf(answer, "%d", &s[i].adcres); -@i{72} @} while (s[i].adcres < 8 || s[i].adcres > 16); -@i{73} printf(" Signal %d ADC zero level [adu]: ", i); -@i{74} fgets(answer, 32, stdin); -@i{75} sscanf(answer, "%d", &s[i].adczero); -@i{76} @} -@i{77} if (osigfopen(s, nsig) < nsig) exit(1); -@i{78} printf("To begin sampling, press RETURN; to specify a\n"); -@i{79} printf(" start time other than the current time, enter\n"); -@i{80} printf(" it in H:M:S format before pressing RETURN: "); -@i{81} fgets(answer, 32, stdin); answer[strlen(answer)-1] = '\0'; -@i{82} setbasetime(answer); -@i{83} -@i{84} @var{initialize ADC here} -@i{85} -@i{86} for (t = 0; t < nsamp; t++) @{ -@i{87} for (i = 0; i < nsig; i++) -@i{88} v[i] = @var{sample from ADC channel i} -@i{89} if (putvec(v) < 0) break; -@i{90} @} -@i{91} -@i{92} @var{stop ADC here} -@i{93} -@i{94} (void)newheader(record); -@i{95} wfdbquit(); -@i{96} exit(0); -@i{97} @} + @i{1} #include + @i{2} #include + @i{3} + @i{4} main() + @i{5} @{ + @i{6} char answer[32], record[8], directory[32]; + @i{7} int i, nsig = 0; + @i{8} long nsamp, t; + @i{9} double freq = 0.; + @i{10} char **filename, **description, **units; + @i{11} WFDB_Sample *v; + @i{12} WFDB_Siginfo *s; + @i{13} + @i{14} do @{ + @i{15} printf("Choose a record name [up to 6 characters]: "); + @i{16} fgets(record, 8, stdin); record[strlen(record)-1] = '\0'; + @i{17} @} while (newheader(record) < 0); + @i{18} do @{ + @i{19} printf("Number of signals to be recorded [>0]: "); + @i{20} fgets(answer, 32, stdin); sscanf(answer, "%d", &nsig); + @i{21} @} while (nsig < 1); + @i{22} s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); + @i{23} v = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); + @i{24} filename = (char **)malloc(nsig * sizeof(char *)); + @i{25} description = (char **)malloc(nsig * sizeof(char *)); + @i{26} units = (char **)malloc(nsig * sizeof(char *)); + @i{27} if (s == NULL || v == NULL || filename == NULL || + @i{28} description == NULL || units == NULL) @{ + @i{29} fprintf(stderr, "insufficient memory\n"); + @i{30} exit(1); + @i{31} @} + @i{32} for (i = 0; i < nsig; i++) @{ + @i{33} if ((filename[i] = (char *)malloc(32)) == NULL || + @i{34} (description[i] = (char *)malloc(32)) == NULL || + @i{35} (units[i] = (char *)malloc(32)) == NULL) @{ + @i{36} fprintf(stderr, "insufficient memory\n"); + @i{37} exit(1); + @i{38} @} + @i{39} @} + @i{40} do @{ + @i{41} printf("Sampling frequency [Hz per signal, > 0]: "); + @i{42} fgets(answer, 32, stdin); sscanf(answer, "%lf", &freq); + @i{43} @} while (setsampfreq(freq) < 0); + @i{44} do @{ + @i{45} printf("Length of record (H:M:S): "); + @i{46} fgets(answer, 32, stdin); + @i{47} @} while ((nsamp = strtim(answer)) < 1L); + @i{48} printf("Directory for signal files [up to 30 characters]: "); + @i{49} fgets(directory, 32, stdin); + @i{50} directory[strlen(directory)-1] = '\0'; + @i{51} printf("Save signals in difference format? [y/n]: "); + @i{52} fgets(answer, 32, stdin); + @i{53} s[0].fmt = (answer[0] == 'y') ? 8 : 16; + @i{54} printf("Save all signals in one file? [y/n]: "); + @i{55} fgets(answer, 32, stdin); + @i{56} if (answer[0] == 'y') @{ + @i{57} sprintf(filename[0], "%s/d.%s", directory, record); + @i{58} for (i = 0; i < nsig; i++) @{ + @i{59} s[i].fname = filename[0]; + @i{60} s[i].group = 0; + @i{61} @} + @i{62} @} + @i{63} else @{ + @i{64} for (i = 0; i < nsig; i++) @{ + @i{65} sprintf(filename[i], "%s/d%d.%s", directory,i,record); + @i{66} s[i].fname = filename[i]; + @i{67} s[i].group = i; + @i{68} @} + @i{69} @} + @i{70} for (i = 0; i < nsig; i++) @{ + @i{71} s[i].fmt = s[0].fmt; s[i].bsize = 0; + @i{72} printf("Signal %d description [up to 30 characters]: ", i); + @i{73} fgets(description[i], 32, stdin); + @i{74} description[i][strlen(description[i])-1] = '\0'; + @i{75} s[i].desc = description[i]; + @i{76} printf("Signal %d units [up to 20 characters]: ", i); + @i{77} fgets(units[i], 22, stdin); + @i{78} units[i][strlen(units[i])-1] = '\0'; + @i{79} s[i].units = (*units[i]) ? units[i] : "mV"; + @i{80} do @{ + @i{81} printf(" Signal %d gain [adu/%s]: ", i, s[i].units); + @i{82} fgets(answer, 32, stdin); + @i{83} sscanf(answer, "%lf", &s[i].gain); + @i{84} @} while (s[i].gain < 0.); + @i{85} do @{ + @i{86} printf(" Signal %d ADC resolution in bits [8-16]: ",i); + @i{87} fgets(answer, 32, stdin); + @i{88} sscanf(answer, "%d", &s[i].adcres); + @i{89} @} while (s[i].adcres < 8 || s[i].adcres > 16); + @i{90} printf(" Signal %d ADC zero level [adu]: ", i); + @i{91} fgets(answer, 32, stdin); + @i{92} sscanf(answer, "%d", &s[i].adczero); + @i{93} @} + @i{94} if (osigfopen(s, nsig) < nsig) exit(1); + @i{95} printf("To begin sampling, press RETURN; to specify a\n"); + @i{96} printf(" start time other than the current time, enter\n"); + @i{97} printf(" it in H:M:S format before pressing RETURN: "); + @i{98} fgets(answer, 32, stdin); answer[strlen(answer)-1] = '\0'; + @i{99} setbasetime(answer); +@i{100} +@i{101} adinit(); +@i{102} +@i{103} for (t = 0; t < nsamp; t++) @{ +@i{104} for (i = 0; i < nsig; i++) +@i{105} v[i] = adget(i); +@i{106} if (putvec(v) < 0) break; +@i{107} @} +@i{108} +@i{109} adquit(); +@i{110} +@i{111} (void)newheader(record); +@i{112} wfdbquit(); +@i{113} exit(0); +@i{114} @} @end example @noindent @@ -5869,29 +6018,29 @@ This code uses @code{newheader} to determine if a legal record name was entered (since we don't want to digitize the signals and then find out that we can't create the @file{header} file). The @file{header} file -created in line 17 will be overwritten in line 94. +created in line 17 will be overwritten in line 111. -@item Lines 39--45: +@item Lines 57--62: This code generates a file name and initializes the @code{fname} and @code{group} fields of the array of @code{WFDB_Siginfo} objects so that all signals will be saved in one file. -@item Lines 46--52: +@item Lines 63--69: This code generates unique file names and groups for each signal. -@item Lines 53--76: +@item Lines 70--93: Here, information specific to individual signals is gathered. -@item Line 77: +@item Line 94: If the signal files can't be created, this program can do nothing else useful, so it quits with an error message from @code{osigfopen}. -@item Lines 78--82: +@item Lines 95--99: Just before sampling begins, we set the base time. Note that an empty string argument for @code{setbasetime} gives us the current time read from the system clock. -@item Line 84: +@item Line 101: What goes here will be hardware dependent. Typically it is necessary to set up a timer for the ADC, allocate DMA buffers, specify interrupt vectors, and initiate the first conversion(s). This program might also be used to @@ -5899,7 +6048,7 @@ in this case, we might simply open the file containing the prerecorded data here. -@item Lines 86--90: +@item Lines 103--107: Here is where the samples are acquired (using hardware-dependent code not shown here) and recorded (using @code{putvec}). At high sampling frequencies, it is critical to make this code as fast as possible. It @@ -5909,18 +6058,18 @@ since it is only a small fraction of the entire program, doing so is within reason. -@item Line 92: +@item Line 109: This final piece of hardware-dependent code typically clears the ADC control register, stops the timer, and frees any system resources such as DMA channels or interrupts. -@item Line 94: +@item Line 111: All of the information needed to generate the @file{header} file has been stored in WFDB library internal data structures by @code{osigfopen} and @code{putvec}; we call @code{newheader} here (before @code{wfdbquit}) to create the new @file{header} file. -@item Line 95: +@item Line 112: It is still necessary to use @code{wfdbquit} to close the signal file(s), even after calling @code{newheader}. (In fact, it would be possible, though not likely to be useful, to record more samples and to generate @@ -5943,19 +6092,19 @@ @i{1} #include @i{2} #include @i{3} #include - @i{4} + @i{4} @i{5} main(argc, argv) @i{6} int argc; @i{7} char *argv[]; @i{8} @{ @i{9} int btype, i, j, nbeats = 0, nsig, hwindow, window; -@i{10} WFDB_Sample v[WFDB_MAXSIG], vb[WFDB_MAXSIG]; -@i{11} long stoptime = 0L, *sum[WFDB_MAXSIG]; -@i{12} WFDB_Anninfo a; -@i{13} WFDB_Annotation annot; -@i{14} static WFDB_Siginfo s[WFDB_MAXSIG]; +@i{10} long stoptime = 0L, **sum; +@i{11} WFDB_Anninfo a; +@i{12} WFDB_Annotation annot; +@i{13} WFDB_Sample *v, *vb; +@i{14} WFDB_Siginfo *s; @i{15} void *calloc(); -@i{16} +@i{16} @i{17} if (argc < 3) @{ @i{18} fprintf(stderr, @i{19} "usage: %s annotator record [beat-type from to]\n", @@ -5963,108 +6112,117 @@ @i{21} exit(1); @i{22} @} @i{23} a.name = argv[1]; a.stat = WFDB_READ; -@i{24} if ((nsig = wfdbinit(argv[2],&a,1,s,WFDB_MAXSIG)) < 1) exit(2); -@i{25} hwindow = strtim(".05"); window = 2*hwindow + 1; -@i{26} btype = (argc > 3) ? strann(argv[3]) : NORMAL; -@i{27} if (argc > 4) iannsettime(strtim(argv[4])); -@i{28} if (argc > 5) @{ -@i{29} if ((stoptime = strtim(argv[5])) < 0L) -@i{30} stoptime = -stoptime; -@i{31} if (s[0].nsamp > 0L && stoptime > s[0].nsamp) -@i{32} stoptime = s[0].nsamp; -@i{33} @} -@i{34} else stoptime = s[0].nsamp; -@i{35} if (stoptime > 0L) stoptime -= hwindow; -@i{36} for (i = 0; i < nsig; i++) -@i{37} if ((sum[i]=(long *)calloc(window,sizeof(long))) == NULL) @{ -@i{38} fprintf(stderr, "%s: insufficient memory\n", argv[0]); -@i{39} exit(3); -@i{40} @} -@i{41} while (getann(0, &annot) == 0 && annot.time < hwindow) -@i{42} ; -@i{43} do @{ -@i{44} if (annot.anntyp != btype) continue; -@i{45} isigsettime(annot.time - hwindow - 1); -@i{46} (void)getvec(vb); -@i{47} for (j = 0; j < window && getvec(v) > 0; j++) -@i{48} for (i = 0; i < nsig; i++) -@i{49} sum[i][j] += v[i] - vb[i]; -@i{50} nbeats++; -@i{51} @} while (getann(0, &annot) == 0 && -@i{52} (stoptime == 0L || annot.time < stoptime)); -@i{53} if (nbeats < 1) @{ -@i{54} fprintf(stderr, "%s: no `%s' beats found\n", -@i{55} argv[0], annstr(btype)); -@i{56} exit(4); -@i{57} @} -@i{58} printf("Average of %d `%s' beats:\n", nbeats, annstr(btype)); -@i{59} for (j = 0; j < window; j++) -@i{60} for (i = 0; i < nsig; i++) -@i{61} printf("%g%c", (double)sum[i][j]/nbeats, -@i{62} (i == nsig-1) ? '\n' : '\t'); -@i{63} exit(0); -@i{64} @} +@i{24} if ((nsig = isigopen(argv[2], NULL, 0)) < 1) exit(2); +@i{25} s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); +@i{26} v = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); +@i{27} vb = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); +@i{28} sum = (long **)malloc(nsig * sizeof(long *)); +@i{29} if (s == NULL || v == NULL || vb == NULL || sum == NULL) @{ +@i{30} fprintf(stderr, "%s: insufficient memory\n", argv[0]); +@i{31} exit(2); +@i{32} @} +@i{33} for (i = 0; i < nsig; i++) +@i{34} if ((sum[i]=(long *)calloc(window,sizeof(long))) == NULL) @{ +@i{35} fprintf(stderr, "%s: insufficient memory\n", argv[0]); +@i{36} exit(2); +@i{37} @} +@i{38} if (wfdbinit(argv[2], &a, 1, s, nsig) != nsig) exit(3); +@i{39} hwindow = strtim(".05"); window = 2*hwindow + 1; +@i{40} btype = (argc > 3) ? strann(argv[3]) : NORMAL; +@i{41} if (argc > 4) iannsettime(strtim(argv[4])); +@i{42} if (argc > 5) @{ +@i{43} if ((stoptime = strtim(argv[5])) < 0L) +@i{44} stoptime = -stoptime; +@i{45} if (s[0].nsamp > 0L && stoptime > s[0].nsamp) +@i{46} stoptime = s[0].nsamp; +@i{47} @} +@i{48} else stoptime = s[0].nsamp; +@i{49} if (stoptime > 0L) stoptime -= hwindow; +@i{50} while (getann(0, &annot) == 0 && annot.time < hwindow) +@i{51} ; +@i{52} do @{ +@i{53} if (annot.anntyp != btype) continue; +@i{54} isigsettime(annot.time - hwindow - 1); +@i{55} getvec(vb); +@i{56} for (j = 0; j < window && getvec(v) > 0; j++) +@i{57} for (i = 0; i < nsig; i++) +@i{58} sum[i][j] += v[i] - vb[i]; +@i{59} nbeats++; +@i{60} @} while (getann(0, &annot) == 0 && +@i{61} (stoptime == 0L || annot.time < stoptime)); +@i{62} if (nbeats < 1) @{ +@i{63} fprintf(stderr, "%s: no `%s' beats found\n", +@i{64} argv[0], annstr(btype)); +@i{65} exit(4); +@i{66} @} +@i{67} printf("Average of %d `%s' beats:\n", nbeats, annstr(btype)); +@i{68} for (j = 0; j < window; j++) +@i{69} for (i = 0; i < nsig; i++) +@i{70} printf("%g%c", (double)sum[i][j]/nbeats, +@i{71} (i == nsig-1) ? '\n' : '\t'); +@i{72} exit(0); +@i{73} @} @end example @noindent @strong{Notes:} @table @emph -@item Line 25: +@item Lines 33--37: +Here we allocate memory for the @code{sum} vectors that will be used to +store the running totals. See @cite{K&R}, page 167, for a description +of @code{calloc}. + +@item Line 39: The ``half-window'' is 50 milliseconds wide, and the ``window'' (the duration of a segment to be entered into the average) is one sample more than twice that amount (i.e., 50 milliseconds to either side of the fiducial point defined by the annotation). -@item Line 26: +@item Line 40: If a third argument is present on the command line, it is taken as an annotation code mnemonic for the desired beat type; otherwise, the program will average @code{NORMAL} QRS complexes. -@item Line 27: +@item Line 41: If a fourth argument is present on the command line, it is taken as the start time; we arrange for the first annotation to be read by @code{getann} to be the first annotation that occurs after the chosen start time. -@item Lines 28--35: +@item Lines 42--49: This code similarly determines when the averaging should stop. Unless no stop time was specified on the command line and the signal length is not defined in the @file{header} file for the record, @code{stoptime} -will have a positive value in line 35, which makes a tiny adjustment so +will have a positive value in line 49, which makes a tiny adjustment so that if a beat annotation occurs within 50 milliseconds of the end of the averaging period, the beat will not be included in the average. -@item Lines 36--40: -Here we allocate memory for the @code{sum} vectors that will be used to -store the running totals. See @cite{K&R}, page 167, for a description -of @code{calloc}. - -@item Lines 41-42: +@item Lines 50-51: This code addresses the (admittedly unlikely) prospect that the first annotation(s) might occur within the first 50 milliseconds of the record; any such annotations will be excluded from the average. -@item Lines 43--52: +@item Lines 52--61: Here we read annotations (the first is already in @code{annot} when we -enter the loop, and subsequent annotations are read in line 51); select -the desired ones (line 44); skip to the correct spot in the signals (line -45; the sample selected there is the one just before the beginning of -the window); read a sample from each signal (line 46) into the @code{vb} +enter the loop, and subsequent annotations are read in line 60); select +the desired ones (line 53); skip to the correct spot in the signals (line +54; the sample selected there is the one just before the beginning of +the window); read a sample from each signal (line 55) into the @code{vb} vector, which will be used as a crude baseline estimate; read -@code{window} samples from each signal (line 47), subtracting the +@code{window} samples from each signal (line 56), subtracting the baseline from each and adding the result into the running totals; update -a beat counter (line 50); and check for loop termination conditions -(line 52). +a beat counter (line 59); and check for loop termination conditions +(line 61). -@item Lines 53--62: +@item Lines 62--71: This is the output section. If no beats of type @code{btype} were found, obviously no average can be printed; note that the message goes to the standard error output, so the user will notice it even if the standard output has been redirected to a file. In the usual case, the averages are printed out as a table, with a column allocated to each -signal. Note the cast in line 61 (necessary to preserve precision), and -the trick used in line 62 to print a tab after each column but the last +signal. Note the cast in line 70 (necessary to preserve precision), and +the trick used in line 71 to print a tab after each column but the last in each line. @end table @@ -6086,85 +6244,94 @@ @i{2} #include @i{3} #include @i{4} - @i{5} #define abs(A) ((A) >= 0 ? (A) : -(A)) + @i{5} #define abs(A) ((A) >= 0 ? (A) : -(A)) @i{6} @i{7} main(argc, argv) @i{8} int argc; @i{9} char *argv[]; @i{10} @{ -@i{11} int filter, time=0, slopecrit, sign, maxslope=0, nslope=0, +@i{11} int filter, time=0, slopecrit, sign, maxslope=0, nsig, nslope=0, @i{12} qtime, maxtime, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, -@i{13} ms160, ms200, s2, scmax, scmin = 0, v[WFDB_MAXSIG]; +@i{13} ms160, ms200, s2, scmax, scmin = 0; @i{14} WFDB_Anninfo a; @i{15} WFDB_Annotation annot; -@i{16} static WFDB_Siginfo s[WFDB_MAXSIG]; -@i{17} -@i{18} if (argc < 2) @{ -@i{19} fprintf(stderr, "usage: %s record [threshold]\n", argv[0]); -@i{20} exit(1); -@i{21} @} -@i{22} a.name = argv[0]; a.stat = WFDB_WRITE; -@i{23} if (wfdbinit(argv[1], &a, 1, s, WFDB_MAXSIG) < 1) exit(2); -@i{24} if (sampfreq(NULL) != 250.) -@i{25} fprintf(stderr,"warning: %s is designed for 250 Hz input\n", -@i{26} argv[0]); -@i{27} if (argc > 2) scmin = muvadu(0, atoi(argv[2])); -@i{28} if (scmin < 1) scmin = muvadu(0, 1000); -@i{29} slopecrit = scmax = 10 * scmin; -@i{30} ms160 = strtim("0.16"); ms200 = strtim("0.2"); s2 = strtim("2"); -@i{31} annot.subtyp = annot.chan = annot.num = 0; annot.aux = NULL; -@i{32} (void)getvec(v); -@i{33} t9 = t8 = t7 = t6 = t5 = t4 = t3 = t2 = t1 = v[0]; -@i{34} -@i{35} do @{ -@i{36} filter = (t0 = v[0]) + 4*t1 + 6*t2 + 4*t3 + t4 -@i{37} - t5 - 4*t6 - 6*t7 - 4*t8 - t9; -@i{38} if (time % s2 == 0) @{ -@i{39} if (nslope == 0) @{ -@i{40} slopecrit -= slopecrit >> 4; -@i{41} if (slopecrit < scmin) slopecrit = scmin; -@i{42} @} -@i{43} else if (nslope >= 5) @{ -@i{44} slopecrit += slopecrit >> 4; -@i{45} if (slopecrit > scmax) slopecrit = scmax; -@i{46} @} -@i{47} @} -@i{48} if (nslope == 0 && abs(filter) > slopecrit) @{ -@i{49} nslope = 1; maxtime = ms160; -@i{50} sign = (filter > 0) ? 1 : -1; -@i{51} qtime = time; -@i{52} @} -@i{53} if (nslope != 0) @{ -@i{54} if (filter * sign < -slopecrit) @{ -@i{55} sign = -sign; -@i{56} maxtime = (++nslope > 4) ? ms200 : ms160; -@i{57} @} -@i{58} else if (filter * sign > slopecrit && -@i{59} abs(filter) > maxslope) -@i{60} maxslope = abs(filter); -@i{61} if (maxtime-- < 0) @{ -@i{62} if (2 <= nslope && nslope <= 4) @{ -@i{63} slopecrit += ((maxslope>>2) - slopecrit) >> 3; -@i{64} if (slopecrit < scmin) slopecrit = scmin; -@i{65} else if (slopecrit > scmax) slopecrit = scmax; -@i{66} annot.time = strtim("i") - (time - qtime) - 4; -@i{67} annot.anntyp = NORMAL; (void)putann(0, &annot); -@i{68} time = 0; -@i{69} @} -@i{70} else if (nslope >= 5) @{ -@i{71} annot.time = strtim("i") - (time - qtime) - 4; -@i{72} annot.anntyp = ARFCT; (void)putann(0, &annot); -@i{73} @} -@i{74} nslope = 0; -@i{75} @} -@i{76} @} -@i{77} t9 = t8; t8 = t7; t7 = t6; t6 = t5; t5 = t4; -@i{78} t4 = t3; t3 = t2; t2 = t1; t1 = t0; time++; -@i{79} @} while (getvec(v) > 0); -@i{80} -@i{81} wfdbquit(); -@i{82} exit(0); -@i{83} @} +@i{16} WFDB_Sample *v; +@i{17} WFDB_Siginfo *s; +@i{18} +@i{19} if (argc < 2) @{ +@i{20} fprintf(stderr, "usage: %s record [threshold]\n", argv[0]); +@i{21} exit(1); +@i{22} @} +@i{23} a.name = "qrs"; a.stat = WFDB_WRITE; +@i{24} +@i{25} if ((nsig = isigopen(argv[1], NULL, 0)) < 1) exit(2); +@i{26} s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); +@i{27} v = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); +@i{28} if (s == NULL || v == NULL) @{ +@i{29} fprintf(stderr, "%s: insufficient memory\n", argv[0]); +@i{30} exit(2); +@i{31} @} +@i{32} if (wfdbinit(argv[1], &a, 1, s, nsig) != nsig) exit(2); +@i{33} if (sampfreq(NULL) != 250.) +@i{34} fprintf(stderr,"warning: %s is designed for 250 Hz input\n", +@i{35} argv[0]); +@i{36} if (argc > 2) scmin = muvadu(0, atoi(argv[2])); +@i{37} if (scmin < 1) scmin = muvadu(0, 1000); +@i{38} slopecrit = scmax = 10 * scmin; +@i{39} ms160 = strtim("0.16"); ms200 = strtim("0.2"); s2 = strtim("2"); +@i{40} annot.subtyp = annot.chan = annot.num = 0; annot.aux = NULL; +@i{41} (void)getvec(v); +@i{42} t9 = t8 = t7 = t6 = t5 = t4 = t3 = t2 = t1 = v[0]; +@i{43} +@i{44} do @{ +@i{45} filter = (t0 = v[0]) + 4*t1 + 6*t2 + 4*t3 + t4 +@i{46} - t5 - 4*t6 - 6*t7 - 4*t8 - t9; +@i{47} if (time % s2 == 0) @{ +@i{48} if (nslope == 0) @{ +@i{49} slopecrit -= slopecrit >> 4; +@i{50} if (slopecrit < scmin) slopecrit = scmin; +@i{51} @} +@i{52} else if (nslope >= 5) @{ +@i{53} slopecrit += slopecrit >> 4; +@i{54} if (slopecrit > scmax) slopecrit = scmax; +@i{55} @} +@i{56} @} +@i{57} if (nslope == 0 && abs(filter) > slopecrit) @{ +@i{58} nslope = 1; maxtime = ms160; +@i{59} sign = (filter > 0) ? 1 : -1; +@i{60} qtime = time; +@i{61} @} +@i{62} if (nslope != 0) @{ +@i{63} if (filter * sign < -slopecrit) @{ +@i{64} sign = -sign; +@i{65} maxtime = (++nslope > 4) ? ms200 : ms160; +@i{66} @} +@i{67} else if (filter * sign > slopecrit && +@i{68} abs(filter) > maxslope) +@i{69} maxslope = abs(filter); +@i{70} if (maxtime-- < 0) @{ +@i{71} if (2 <= nslope && nslope <= 4) @{ +@i{72} slopecrit += ((maxslope>>2) - slopecrit) >> 3; +@i{73} if (slopecrit < scmin) slopecrit = scmin; +@i{74} else if (slopecrit > scmax) slopecrit = scmax; +@i{75} annot.time = strtim("i") - (time - qtime) - 4; +@i{76} annot.anntyp = NORMAL; (void)putann(0, &annot); +@i{77} time = 0; +@i{78} @} +@i{79} else if (nslope >= 5) @{ +@i{80} annot.time = strtim("i") - (time - qtime) - 4; +@i{81} annot.anntyp = ARFCT; (void)putann(0, &annot); +@i{82} @} +@i{83} nslope = 0; +@i{84} @} +@i{85} @} +@i{86} t9 = t8; t8 = t7; t7 = t6; t6 = t5; t5 = t4; +@i{87} t4 = t3; t3 = t2; t2 = t1; t1 = t0; time++; +@i{88} @} while (getvec(v) > 0); +@i{89} +@i{90} wfdbquit(); +@i{91} exit(0); +@i{92} @} @end example @noindent @@ -6177,58 +6344,58 @@ @item Lines 11--12: The names of these variables match those in the original Pascal program. -@item Lines 24--26: +@item Lines 33--35: Most of this program is independent of sampling frequency, but the filter -(lines 36--37) and the threshold are as specified by the authors +(lines 45--46) and the threshold are as specified by the authors of the original program for human ECGs sampled at 250 Hz (e.g., the AHA DB). The program will work for MIT DB records sampled at 360 Hz, but better results can be obtained if the filter is optimized for the correct sampling frequency. -@item Lines 27--29: +@item Lines 36--38: The threshold is actually a slope criterion (with units of amplitude/time); these lines normalize the threshold with respect to the signal gain. The default value is used unless the user supplies an acceptable alternative. The variables @code{scmin} and @code{scmax} are lower and upper bounds for the adaptive threshold @code{slopecrit}. -@item Lines 32--33: +@item Lines 41--42: Here we read the first sample and copy it into the variables that will be used to store the ten most recent samples. @cindex digital filter @cindex filter (digital) -@item Lines 36--37: +@item Lines 45--46: This FIR filter differentiates and low-pass filters the input signal. -@item Lines 38--47: +@item Lines 47--56: Here we adjust the threshold if more than two seconds have elapsed since -a QRS was detected. In line 40, @code{slopecrit} is set to 15/16 of its -previous value if no slopes have been found; in line 45, it is set to +a QRS was detected. In line 49, @code{slopecrit} is set to 15/16 of its +previous value if no slopes have been found; in line 53, it is set to 17/16 of its previous value if 5 or more slopes were found (suggesting the presence of noise). -@item Lines 48--52: +@item Lines 57--61: If the condition in line 48 is satisfied, we may have found the beginning of a QRS complex. We record that a slope has been found, set the timer @code{maxtime} to 160 msec, and save the sign of the slope and the current time relative to the previous beat. -@item Lines 53--76: +@item Lines 62--85: This code is executed once we have found a slope. Each time the filter output crosses the threshold, we record another slope and begin looking -for a threshold crossing of the opposite sign (lines 54--57), which must +for a threshold crossing of the opposite sign (lines 63--66), which must occur within a specified time. We record the maximum absolute value of -the filter in @code{maxslope} (lines 58--60) for eventual use in updating -the threshold (lines 63--65). Once a sufficient interval has elapsed -following the last threshold crossing (line 61), if there were between +the filter in @code{maxslope} (lines 67--69) for eventual use in updating +the threshold (lines 72--74). Once a sufficient interval has elapsed +following the last threshold crossing (line 70), if there were between 2 and 4 slopes, we have (apparently) found a QRS complex, and the program -records a @code{NORMAL} annotation (lines 66--67). If there were 5 or more -slopes, the program records an artifact annotation (lines 71--72). If +records a @code{NORMAL} annotation (lines 75--76). If there were 5 or more +slopes, the program records an artifact annotation (lines 80--81). If only 1 slope was found, it is assumed to represent a baseline shift and no output is produced. -@item Lines 77--79: +@item Lines 86--88: At the end of the loop, the samples are shifted through the @code{t@var{n}} variables and another sample is read. @end table @@ -6249,9 +6416,9 @@ record @file{100s}, input annotator @file{atruth}, and output annotator @file{normal}. The program should finish in five seconds or less. The annotations will have been written into a file called -@file{100s.normal} (under MS-DOS, @file{100s.nor}) in the current -directory. Now type ``@code{rdann -r 100s -a atruth}'' and observe the output -for a few seconds, then try ``@code{rdann -r 100s -a normal}'' and notice the +@file{100s.nor} in the current directory. Now type +``@code{rdann -r 100s -a atruth}'' and observe the output +for a few seconds, then try ``@code{rdann -r 100s -a nor}'' and notice the difference. @item @@ -6372,14 +6539,13 @@ @item This exercise assumes that you have access to the MIT-BIH Arrhythmia -Database. Since the 360 Hz sampling frequency used in that database is -an integer multiple of 60 Hz, it is quite easy to design a 60 Hz notch -filter that can be applied to the database. Write a program that -filters two input signals and writes out the filtered data using -@code{putvec} (@pxref{Example 7}, for a model program). Try it out on -MIT-BIH record @file{122}. Caution: signal files are quite large. In -order to avoid using too much disk space for this exercise, limit the -program to writing 10 seconds' worth of samples. Use your programs from +Database, either on a CD-ROM or via PhysioNet. Since the 360 Hz sampling +frequency used in that database is an integer multiple of 60 Hz, it is +quite easy to design a 60 Hz notch filter that can be applied to the +database. Write a program that filters two input signals and writes +out the filtered data using @code{putvec} (@pxref{Example 7}, for a +model program). Try it out on MIT-BIH record @file{122} (or use record +@file{mitdb/x_mitdb/x_122} from PhysioNet). Use your programs from the previous exercises to display your output. @item @@ -6497,10 +6663,7 @@ @cindex annotator number (defined) An integer by which an annotation file, once opened, is known. Input annotators and output annotators each have their own series of annotator -numbers assigned in serial order beginning with 0. Since at most -@code{WFDB_MAXANN} (defined in @file{}) input or output -annotation files may be open at once, the largest valid annotator number -is @code{WFDB_MAXANN - 1}. +numbers assigned in serial order beginning with 0. @item Application program In this guide, a program that uses the WFDB library to do @@ -6715,7 +6878,7 @@ and may have their own annotation files as well (annotation files for the constituent segments of a multi-segment record are @emph{not} concatenated automatically when the record is read). The WFDB Software -Package includes @code{wfdbcollate} (under MS-DOS, @code{wfdbcoll}), an +Package includes @code{wfdbcollate}, an application that can create multi-segment records from sets of single-segment records. Version 9.1 and later versions of the WFDB library support reading and writing multi-segment records. @@ -6781,7 +6944,7 @@ read as samples. Signal files created using the WFDB library do not contain prologs, but signal files created using other means may contain prologs. To read such a signal file using the WFDB library, provided that -the sample data is in a supported format, it is sufficient to record the +the sample data are in a supported format, it is sufficient to record the length of the prolog (in bytes) in the appropriate locations in a @file{header} file that names the signal file. If you need to create such a @file{header} file, refer to the description of the byte offset @@ -6795,7 +6958,7 @@ files, and a @file{header} file, all of which are associated with the same original signals. Only the @file{header} file is mandatory. Although records are sometimes called tapes for historical reasons, -records are now more commonly maintained on optical or magnetic disks +records are now more commonly maintained on CD-ROMs or magnetic disks than on tape. @item Record name @@ -6873,9 +7036,7 @@ @cindex signal number (defined) An integer by which a signal, once opened, is known. Input and output signals each have their own series of signal numbers assigned in serial -order beginning with 0. Since at most @code{WFDB_MAXSIG} (defined in -@file{}) input or output signals may be open at once, the -largest valid signal number is @code{WFDB_MAXSIG - 1}. +order beginning with 0. @item Skew @cindex skew @@ -6928,8 +7089,8 @@ @menu * Distribution:: How to obtain the latest version of the WFDB Software Package. -* UNIX installation:: Installing the WFDB Software Package on UNIX, Linux, - and similar systems. +* UNIX installation:: Installing the WFDB Software Package on UNIX, + GNU/Linux, and similar systems. * MS-DOS installation:: Installing the WFDB Software Package on MS-DOS PCs. * Other installation:: Installing the WFDB Software Package on other systems. @end menu @@ -6969,18 +7130,18 @@ @file{software} directory). @node UNIX installation, MS-DOS installation, Distribution, Installation -@unnumberedsec UNIX, Linux, and similar operating systems +@unnumberedsec UNIX, GNU/Linux, and similar operating systems Before beginning the installation of the WFDB Software Package, obtain and install the @code{libwww} package from @code{http://www.w3.org/Library/} or from @code{http://www.physionet.org/physiotools/libwww/}. This package is -provided with most current versions of Linux. (If you have a program called -@code{libwww-config}, then @code{libwww} is installed already.) You may +provided with most current versions of GNU/Linux. (If you have a program +called @code{libwww-config}, then @code{libwww} is installed already.) You may omit this step if you do not wish to have NETFILES support. Also obtain and install the @code{XView} software from @code{http://www.physio@-net.org/physio@-tools/xview/}. Sources are available, -as are binaries for several versions of Linux. If you are using SunOS or +as are binaries for several versions of GNU/Linux. If you are using SunOS or Solaris, XView binaries are available in the Open Look Software Development package and may be installed already. (If you have a program called @code{textedit}, then @code{XView} is installed already.) If you are able to @@ -6991,8 +7152,10 @@ Select an existing directory in a writable file system for the WFDB Software Package installation; @file{/usr/local/src} is a good choice in most cases. -Make sure that at least 6 megabytes are available (most of this space can be -recovered after the installation is complete). +Make sure that at least 6 megabytes are available; most of this space can be +recovered after the installation is complete. [Obviously, this was written +in ancient times -- the early 1990s -- when 6 Mb was still enough space for +most computer users to notice!] If you have downloaded the software from PhysioNet or another source, you will have a @code{gzip}-compressed @code{tar} archive. Unpack it using @@ -7003,12 +7166,12 @@ tar xfv wfdb.tar @end example -(If you have GNU @code{tar}, as on Linux, you can combine these into a +(If you have GNU @code{tar}, as on GNU/Linux, you can combine these into a single command: @samp{tar xfvz wfdb.tar.gz}.) This will create a directory with a name of the form @code{wfdb-}@var{m.n.r}, where @var{m.n.r} is the version number of the included WFDB library (e.g., -@code{10.1.1}). Enter this directory. +@code{10.2.0}). Enter this directory. If you are installing the software from a CD-ROM, copy the contents of the @file{src/wfdb} directory to your writable file system and then enter that @@ -7163,12 +7326,18 @@ @unnumberedsec Annotation File Processing @example +ann2rr -a @var{annotator} -r @var{record [ options ... ]} +rr2ann -a @var{annotator} -r @var{record [ options ... ]} rdann -a @var{annotator} -r @var{record [} -f @var{from} -t @var{to} -p @var{type ... ]} wrann -a @var{annotator} -r @var{record} sumann -a @var{annotator} -r @var{record} tach -a @var{annotator} -r @var{record [ options ... ]} @end example +Programs @file{ann2rr} and @file{rr2ann} respectively list RR (inter-beat) +intervals in text format from an annotation file, and create an annotation +file from a text-format list of RR intervals. + The program @file{rdann} is an annotation printer similar to the one shown in chapter 6 (@pxref{Example 3}). The optional @var{from} and @var{to} arguments (in standard time format) specify a portion of the @@ -7451,13 +7620,6 @@ system's @file{include} directory after installing the modified WFDB library. -If you wish to increase the number of simultaneously accessible signals or -annotators, simply change @code{WFDB_MAXSIG} or @code{WFDB_MAXANN} in -@file{wfdb.h}, and recompile the WFDB library and your applications. Your -operating system's limit on the number of simultaneously open files may require -you to use multiplexed signal files if you increase @code{WFDB_MAXSIG} -substantially. - The cleanest mechanism for adding additional fields to @file{header} files is to include them in `info' strings @iftex @@ -7591,11 +7753,8 @@ @appendix Sources This section is a compendium of sources for databases and related -materials that may be useful to readers of this guide. If you have -installed the WFDB Software Package, you may find an updated version of -this list in @file{SOURCES.TXT}, in the @file{wfdb} directory that was -created during the installation. Please send any corrections to the -author (@code{george@@mit.edu}). +materials that may be useful to readers of this guide. Please send any +corrections to the author (@code{george@@mit.edu}). @table @emph @cindex MIT DB @@ -7617,22 +7776,18 @@ recorded physiologic signals and related open-source software. PhysioNet is a public service of the Research Resource for Complex Physiologic Signals, funded by the National Center for -Research Resources of the National Institutes of Health. +Research Resources of the National Institutes of Health. The +master PhysioNet web server is located at MIT in Cambridge, Massachusetts; +about ten public mirrors are located elsewhere in the US and around +the world (see @code{http://@-www.@-physio@-net.@-org/@-mirrors/} for a list). @sp 1 @cindex CD-ROM @cindex MIT DB @cindex waveform editor -@item WFDB Programmer's Guide -@itemx WFDB Applications Guide -@itemx WAVE User's Guide @itemx MIT-BIH Arrhythmia Database CD-ROM -@itemx MIT-BIH Arrhythmia Database Directory @itemx MIT-BIH Polysomnographic Database CD-ROM -@itemx MIT-BIH Polysomnographic Database Directory -@itemx Samples of Physiologic Databases CD-ROM @itemx Software for Physiologic Databases with Samples CD-ROM -@itemx MIMIC Database CD-ROMs @display MIT-BIH Database Distribution MIT Room E25-505A @@ -7720,7 +7875,7 @@ odd-numbered years. The deadline for submission of abstracts is 1 May each year. Proceedings of the conferences are published by the IEEE, and usually appear about 3 months after the date of the conference. CinC will be -in Cambridge, Massachusetts in 2000, and in Rotterdam in 2001. +in Memphis, Tennessee in 2002, and in Thessaloniki in 2003. @sp 1 @item Proceedings of Computers in Cardiology (ISSN 0276-6574) @@ -7777,7 +7932,7 @@ The UNIX @TeX{} distribution is also distributed on CD-ROM and in other tape formats by the Free Software Foundation (address above) and others. It is -also included with most Linux distributions (see below). +also included with most GNU/Linux distributions (see below). Several commercial implementations of @TeX{} for MS-DOS are widely available. @@ -7836,37 +7991,27 @@ @end display There are also many low-cost (typically US$10 to US$30) distributions of -Linux on CD-ROMs widely available. Among the more popular are: +GNU/Linux on CD-ROMs widely available. Among the more popular are: @display Caldera Systems, Inc. 240 West Center Street Orem, UT 84057 USA -e-mail: @code{info@@calderasystems.com} -WWW: @code{http://www.calderasystems.com/} +e-mail: @code{info@@caldera.com} +WWW: @code{http://www.caldera.com/} telephone: +1 801 765 4999 telefax: +1 801 765 1313 -Corel Corporation -1600 Carling Ave. -Ottawa, Ontario -K1Z 8R7 -Canada - -WWW: @code{http://linux.corel.com/} -telephone: +1 613 728 0826 - - Debian WWW: @code{http://www.debian.org/} Red Hat -P.O. Box 13588 -RTP, NC 27709 USA +2600 Meridian Parkway +Durham, NC 27713 e-mail: @code{orders@@redhat.com} WWW: @code{http://www.redhat.com/} @@ -7875,14 +8020,8 @@ Slackware -Walnut Creek CD-ROM -4041 Pike Lane, Suite E -Concord, CA 94520 USA - -e-mail: @code{info@@slackware.com}, @code{info@@cdrom.com} -WWW: @code{http://www.slackware.com/}, @code{http://www.cdrom.com/} -telephone: 1 800 786 9907 (USA and Canada) or +1 510 674 0783 -telefax: +1 510 674 0821 + +WWW: @code{http://www.slackware.com/} S.u.S.E. GmbH @@ -7897,6 +8036,18 @@ @end display @sp 1 +@cindex Cygwin +@item Cygwin + +WWW: @code{http://source.redhat.com/cygwin/} + +This is a free software development platform for MS-Windows 9x/NT/2000/ME/XP, +based on GNU @code{gcc} and a large set of UNIX utilities ported by Cygnus +Software (now part of Red Hat, see above). Cygwin itself is open-source +software and is highly recommended in preference to commercial C/C++ compilers +if you must work in the MS-Windows environment. The WFDB Software Package +binaries available via PhysioNet are created using Cygwin. + @item Borland C++ @itemx Turbo C/C++ @display @@ -8067,11 +8218,11 @@ @ifinfo WFDB Programmer's Guide -Tenth Edition (revised for WFDB library version 10.0.0) +Tenth Edition (revised and with additions for WFDB library version 10.2.0) George B. Moody -Copyright (C) 1989 -- 1999 George B. Moody +Copyright (C) 1989 -- 2001 George B. Moody Permission is granted to make and distribute verbatim copies of this guide provided that the copyright notice and this permission notice are diff -Naur wfdb-10.1.6/doc/eval.tex wfdb-10.2.0/doc/eval.tex --- wfdb-10.1.6/doc/eval.tex Tue Dec 12 13:38:00 2000 +++ wfdb-10.2.0/doc/eval.tex Mon Oct 15 17:45:07 2001 @@ -9,7 +9,7 @@ \date{} \begin{document} -\setcounter{page}{112} +\setcounter{page}{113} \maketitle diff -Naur wfdb-10.1.6/doc/install.tex wfdb-10.2.0/doc/install.tex --- wfdb-10.1.6/doc/install.tex Tue Dec 12 13:37:42 2000 +++ wfdb-10.2.0/doc/install.tex Thu Sep 6 15:35:27 2001 @@ -18,10 +18,12 @@ new system. The package includes C-language sources for the WFDB library and for the applications described in this manual; \LaTeX{}, {\tt texinfo}, and {\tt troff} sources for this and other manuals; and a one-minute sample record -({\tt 100s}). Except for UNIX-specific and MS-DOS-specific visualization -programs and an MS-DOS-specific digitization/replay program, all of the -software is portable between UNIX and MS-DOS, and is usable under VMS and on -the Macintosh with only minor modifications. +({\tt 100s}). + +These notes are included here for those who may not have ready access to the +World Wide Web. For those who do, please visit PhysioNet, where quick-start +guides including installation notes for popular operating systems are available +(see {\tt http://www.physio\-net.org/physio\-tools/wfdb.shtml} \section*{Obtaining the WFDB Software Package} The latest version of the WFDB Software Package can always be downloaded in @@ -55,15 +57,15 @@ omit this step if you do not wish to have NETFILES support. Also download and install the {\tt XView} software packages from {\tt -http://www.\-physio\-net.org/\-physio\-tools/xview/}. Sources are available, -as are binaries for several versions of Linux. If you are using SunOS or -Solaris, XView binaries are available in the Open Look Software Development -package and may be installed already. (If you have a program called {\tt -textedit}, then {\tt XView} is installed already.) If you are able to use an -existing set of binaries, these are recommended, since the sources may take a -{\em long} time to compile. Be sure that the directory containing {\tt -textedit}, usually {\tt /usr/openwin/bin}, is in your {\tt PATH}. You may omit -this step if you do not wish to use {\em WAVE}. +http://www.\-physio\-net.org/\-physio\-tools/xview/} if you wish to use WAVE. +Sources are available, as are binaries for several versions of Linux. If you +are using SunOS or Solaris, XView binaries are available in the Open Look +Software Development package and may be installed already. (If you have a +program called {\tt textedit}, then {\tt XView} is installed already.) If you +are able to use an existing set of binaries, these are recommended, since the +sources may take a {\em long} time to compile. Be sure that the directory +containing {\tt textedit}, usually {\tt /usr/openwin/bin}, is in your +{\tt PATH}. You may omit this step if you do not wish to use {\em WAVE}. Select an existing directory in a writable file system for the WFDB Software Package installation; {\tt /usr/local/src} is a good choice in most cases. @@ -84,7 +86,7 @@ This will create a directory with a name of the form {\tt wfdb-}{\em m.n.r}, where {\em m.n.r} is the version number of the included WFDB library (e.g., -{\tt 10.1.1}). Enter this directory. +{\tt 10.2.0}). Enter this directory. If you are installing the software from a CD-ROM, copy the contents of the {\tt src/wfdb} directory to your writable file system and then enter that @@ -120,36 +122,100 @@ Depending on the speed of your system and of your C compiler, {\tt make} will generally require between 1 and 10 minutes. -\subsection*{MS-DOS and MS-Windows} +\subsection*{MS-Windows} -Install your C compiler if you have not already done so, and make sure that -your hard disk has at least 6 megabytes of free space remaining. (Most of -this space can be reclaimed after the installation is complete.) +If you have not already done so, install the Cygwin development environment +(freely available from {\tt http://sources.redhat.com/cygwin/}). This includes +{\tt gcc} (the GNU C/C++ compiler) as well as a comprehensive assortment of +other Unix utilities ported to MS-Windows. Accept the defaults suggested by +the installer. + +{\emph Important:} Although you may be able to compile the WFDB software +package using a proprietary compiler, this is {\emph not supported}. The +{\tt Makefile.dos} files in several of the subdirectories of the package's +source tree can be used with the {\tt make} utilities provided with most +commercial C compilers, although you will need to customize them for your +compiler. Your feedback is appreciated. -If you have Microsoft or Turbo C or C++, and a Microstar Laboratories DAP 1200- -or 2400-series analog interface board, you can instruct the {\tt install} -procedure to compile {\tt sample} (a program for creating database records -from analog signals, and for replaying them in analog form). To do so -successfully, you must first have installed the Microstar {\tt \#include} files -and DAP interface library on your system. Specifically, files {\tt c\_lib.c}, -{\tt clock.h}, and {\tt ioutil.h} must be installed in your {\tt include} -directory, and file {\tt cdapl.lib} must be installed in a directory in which -libraries are found by your linker. (If you are using Microsoft C, copy -{\tt cdapl5.lib} from the Microstar distribution diskettes into your library -directory, and rename it {\tt cdapl.lib}.) - -If you have downloaded the {\tt gzip}-compressed {\tt tar} archive of WFDB -sources, rename it if necessary (your browser may have changed its name to -{\tt wfdb\_tar.gz}; its name must be {\tt wfdb.tar.gz} in order to be -unpacked successfully). Either GNU/Cygnus {\tt gzip} and {\tt tar}, other -versions of these utilities, or WinZip can be used to unpack the source -archive. +Before beginning the installation of the WFDB Software Package, obtain and +install the {\tt libwww} package from {\tt http://www.w3.org/Library/} or +from {\tt http://\-www.physio\-net.org/physio\-tools/libwww/}. You may +omit this step if you do not wish to have NETFILES support. + +Download +{\tt http://www.physio\-net.org/physio\-tools/binaries/win\-dows/bin/which.exe} +and put it into a directory in your PATH. (This utility is needed by +{\tt configure} in a later step. The sources for {\tt which.exe} are available +within {\tt http://www.physio\-net.org/physio\-tools/util\-ities/}.) + +Open a Cygwin terminal window (the Cygwin installer will have added this to +your MS-Windows start menu). Perform the remaining steps by typing the +commands given below into the terminal window. + +Check that {\tt which} and {\tt gcc} are accessible by typing the command: + +\begin{verbatim} +which gcc +\end{verbatim} + +The output of this command should be: + +\begin{verbatim} +/usr/bin/gcc +\end{verbatim} + +If you don't see this output, repeat steps 1 and 2 above as necessary to +correct the problem before continuing. + +If you have downloaded the WFDB software package from PhysioNet or another +source, you will have a {\tt gzip}-compressed {\tt tar} archive. Unpack it +using the {\tt tar} command included with the Cygwin package: + +\begin{verbatim} +tar xfvz wfdb.tar.gz +\end{verbatim} + +If your browser decompressed the file during the download, use this command +instead: + +\begin{verbatim} +tar xfv wfdb.tar +\end{verbatim} + +This will create a directory with a name of the form {\tt wfdb-}{\em m.n.r}, +where {\em m.n.r} is the version number of the included WFDB library (e.g., +{\tt 10.2.0}). Enter this directory. If you are installing the software from a CD-ROM, copy the contents of the -{\tt wfdb} directory to a writable directory on your hard drive. +{\tt src/wfdb} directory to your writable file system and then enter that +directory. One way to do this is to change to the {\tt src} directory on the +CD-ROM and then to type: -Enter the directory containing the sources and run {\tt install} to compile -and install the WFDB Software Package. +\begin{verbatim} +tar cfv - wfdb | ( cd c:/usr/local/src; tar xfv - ) +cd wfdb +\end{verbatim} + +In either case, you should now be ready to configure, compile, and install +the software, using the commands: + +\begin{verbatim} +./configure +make install +\end{verbatim} + +If you have Microsoft or Turbo C or C++, and a Microstar Laboratories DAP 1200- +or 2400-series analog interface board, you can compile {\tt sample} (a program +for creating database records from analog signals, and for replaying them in +analog form). To do so successfully, you must first have installed the +Microstar {\tt \#include} files and DAP interface library on your system. +Specifically, files {\tt c\_lib.c}, {\tt clock.h}, and {\tt ioutil.h} must be +installed in your {\tt include} directory, and the version of the file +{\tt cdapl.lib} that is compatible with your compiler must be installed in a +directory in which libraries are found by your linker. Read and customize +{\tt lib/Makefile.dos} and {\tt app/Makefile.dos} as appropriate for your +compiler, and use your compiler's {\tt make} utility to generate {\tt wfdb.lib} +and then {\tt sample.exe}. \subsection*{Other systems} diff -Naur wfdb-10.1.6/doc/sigamp.1 wfdb-10.2.0/doc/sigamp.1 --- wfdb-10.1.6/doc/sigamp.1 Wed May 24 16:35:17 2000 +++ wfdb-10.2.0/doc/sigamp.1 Tue Oct 9 10:19:41 2001 @@ -1,4 +1,4 @@ -.TH SIGAMP 1 "24 May 2000" "WFDB software 10.1.4" "WFDB applications" +.TH SIGAMP 1 "9 October 2001" "WFDB software 10.2.0" "WFDB applications" .SH NAME sigamp \- measure signal amplitudes of a WFDB record .SH SYNOPSIS @@ -7,10 +7,10 @@ .PP \fIsigamp\fR measures either baseline-corrected RMS amplitudes or (for suitably annotated ECG signals) normal QRS peak-to-peak amplitudes -for all signals of the specified \fIrecord\fR. It makes up to 250 -measurements for each signal and calculates trimmed means (by -discarding the largest and smallest 5% of the measurements and taking -the mean of the remaining 90%). +for all signals of the specified \fIrecord\fR. It makes up to 300 +measurements (but see \fB-n\fR below) for each signal and calculates +trimmed means (by discarding the largest and smallest 5% of the measurements +and taking the mean of the remaining 90%). .PP \fIOptions\fR include: .TP @@ -29,6 +29,9 @@ .TP \fB-h\fR Print a usage summary. +.TP +\fB-n\fI nmax\fR +Make up to \fInmax\fR measurements on each signal (default: 300). .TP \fB-p\fR Print results in physical units (default: ADC units). diff -Naur wfdb-10.1.6/doc/xform.1 wfdb-10.2.0/doc/xform.1 --- wfdb-10.1.6/doc/xform.1 Mon Apr 10 09:22:23 2000 +++ wfdb-10.2.0/doc/xform.1 Mon Oct 8 21:06:37 2001 @@ -1,4 +1,4 @@ -.TH XFORM 1 "10 April 2000" "WFDB software 10.1.3" "WFDB applications" +.TH XFORM 1 "8 October 2001" "WFDB software 10.2.0" "WFDB applications" .SH NAME xform \- sampling frequency, amplitude, and format conversion for WFDB records .SH SYNOPSIS @@ -71,6 +71,12 @@ \fB-t\fI time\fR Process until the specified \fItime\fR in the input record (default: continue to the end of the record). +.TP +\fB-u\fR +Adjust annotation times as needed so that they are unique. If the output +sampling frequency is less than that of the input, the times of closely-spaced +annotations may coincide in the output, which may cause problems for some +older WFDB applications. The \fB-u\fR option avoids this. .PP If a \fInew-record\fR is specified, a new header file is created after the signal file transformation is complete. The new header file, diff -Naur wfdb-10.1.6/examples/Makefile wfdb-10.2.0/examples/Makefile --- wfdb-10.1.6/examples/Makefile Wed Aug 1 10:28:34 2001 +++ wfdb-10.2.0/examples/Makefile Mon Oct 15 14:40:00 2001 @@ -34,12 +34,12 @@ # `make clean' to remove them. # _____________________________________________________________________________ # file: version.def G. Moody 24 May 2000 -# Last revised: 28 February 2001 +# Last revised: 14 August 2001 # Each release of the WFDB Software Package is identified by a three-part # version number, defined here: MAJOR = 10 -MINOR = 1 -RELEASE = 6 +MINOR = 2 +RELEASE = 0 VERSION = $(MAJOR).$(MINOR).$(RELEASE) # VDEFS is the set of C compiler options needed to set version number variables @@ -47,7 +47,7 @@ VDEFS = -DWFDB_MAJOR=$(MAJOR) -DWFDB_MINOR=$(MINOR) -DWFDB_RELEASE=$(RELEASE) # _____________________________________________________________________________ -PACKAGE=wfdb-10.1.6 +PACKAGE=wfdb-10.2.0 # file: linux.def G. Moody 31 May 2000 # Last revised: 5 June 2000 # 'make' definitions for compiling the WFDB Software Package under Linux diff -Naur wfdb-10.1.6/examples/Makefile-dos-gcc wfdb-10.2.0/examples/Makefile-dos-gcc --- wfdb-10.1.6/examples/Makefile-dos-gcc Wed May 24 22:35:27 2000 +++ wfdb-10.2.0/examples/Makefile-dos-gcc Wed Dec 31 19:00:00 1969 @@ -1,84 +0,0 @@ -# file: Makefile-dos-gcc G. Moody 24 April 1997 -# Last revised: 7 May 1999 -# GCC-DOS 'make' description file for WFDB example programs -# -# This file is used with the UNIX `make' command to cross-compile the example -# programs from the WFDB Programmer's Guide, for which the sources can be -# found in this directory. Since these programs are intended for instruction -# rather than `production' use, this `makefile' does not include a procedure -# for installing them. To compile the examples, just type -# `make -f Makefile-dos-gcc' (from within this directory); the executable files -# will be left in this directory. Type `make clean' to remove them. - -# Site-specific variables -# ----------------------- - -# CCDIR is the directory containing the cross-compiler and the binary -# file utilities for MSDOS. -CCDIR = /usr/lib/gcc-lib/i386-go32-msdos/2.7.2 - -# CC is the name of the cross-compiler. -CC = $(CCDIR)/gcc - -# CCDEFS is the set of C compiler options needed to set preprocessor variables -# while compiling the WFDB Software Package. You should include definitions of -# the major, minor, and release numbers, and of MSDOS, as shown below. Other -# definitions are needed only for various versions of UNIX and should be -# omitted here. -CCDEFS = -DWFDB_MAJOR=$(MAJOR) -DWFDB_MINOR=$(MINOR) -DWFDB_RELEASE=$(RELEASE) -DMSDOS - -# CFLAGS is the list of C compiler options used when compiling programs in the -# `app', `convert', and `example' directories. Add the following options to -# CFAPP as appropriate (separating them by spaces if you use more than one): -# -g to save symbols for debugging -# -O to use the optimizer -# -I$(INCDIR) needed if INCDIR is not in the normal search path for -# `#include' files; harmless otherwise -# -L$(LIBDIR) needed if LIBDIR is not in the normal library search path; -# harmless if LIBDIR is in the normal library search path -# As noted above, gcc-dos allows you to use both -g and -O if you wish. -CFLAGS = -O -I/usr/local/dos/include $(CCDEFS) -L/usr/local/dos/lib - -# LDFLAGS is appended to the C compiler command line to specify loading the -# WFDB library. Unless you have changed the value of WFDBLIB in the `Makefile' -# for the WFDB library, `-lwfdb' should be correct. -LDFLAGS = -lwfdb - -# BINDIR specifies the directory in which the applications will be installed; -# it should be a directory in the PATH of those who will use the applications. -# You will need to have write permission in BINDIR. Users of this software -# will need to have search (execute) permission in BINDIR. -BINDIR = /usr/local/dos/bin - -# STRIP is the command used to compact the compiled binaries by removing their -# symbol tables. The next line is commented out because $(CCDIR)/strip fails. -# STRIP = $(CCDIR)/strip -# To retain the symbol tables for debugging, comment out the previous line, and -# uncomment the next line. -STRIP = : - -# It should not be necessary to modify anything below this line. -# ----------------------------------------------------------------------------- - -CFILES = psamples.c exgetvec.c exputvec.c exannstr.c example1.c example2.c \ - example3.c example4.c example5.c example6.c example7.c example8.c example9.c \ - example10.c refhr.c -XFILES = psamples.exe exgetvec.exe exputvec.exe exannstr.exe example1.exe \ - example2.exe example3.exe example4.exe example5.exe example6.exe \ - example7.exe example8.exe example9.exe exampl10.exe refhr.exe - -# General rule for compiling C sources into executable files. -.SUFFIXES: .exe -.c.exe: - $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) - -# `make' or `make compile': compile the examples -compile: $(XFILES) - -exampl10.exe: - $(CC) $(CFLAGS) example10.c -o $@ $(LDFLAGS) - -# `make clean': remove executable, intermediate and backup files -clean: - rm -f $(XFILES) *.o *~ core - diff -Naur wfdb-10.1.6/examples/example10.c wfdb-10.2.0/examples/example10.c --- wfdb-10.1.6/examples/example10.c Thu Jun 24 11:38:29 1999 +++ wfdb-10.2.0/examples/example10.c Mon Oct 15 12:17:27 2001 @@ -8,19 +8,28 @@ int argc; char *argv[]; { - int filter, time=0, slopecrit, sign, maxslope=0, nslope=0, + int filter, time=0, slopecrit, sign, maxslope=0, nsig, nslope=0, qtime, maxtime, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, - ms160, ms200, s2, scmax, scmin = 0, v[WFDB_MAXSIG]; + ms160, ms200, s2, scmax, scmin = 0; WFDB_Anninfo a; WFDB_Annotation annot; - static WFDB_Siginfo s[WFDB_MAXSIG]; + WFDB_Sample *v; + WFDB_Siginfo *s; if (argc < 2) { fprintf(stderr, "usage: %s record [threshold]\n", argv[0]); exit(1); } - a.name = argv[0]; a.stat = WFDB_WRITE; - if (wfdbinit(argv[1], &a, 1, s, WFDB_MAXSIG) < 1) exit(2); + a.name = "qrs"; a.stat = WFDB_WRITE; + + if ((nsig = isigopen(argv[1], NULL, 0)) < 1) exit(2); + s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); + v = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); + if (s == NULL || v == NULL) { + fprintf(stderr, "%s: insufficient memory\n", argv[0]); + exit(2); + } + if (wfdbinit(argv[1], &a, 1, s, nsig) != nsig) exit(2); if (sampfreq(NULL) != 250.) fprintf(stderr, "warning: %s is designed for 250 Hz input\n", argv[0]); diff -Naur wfdb-10.1.6/examples/example5.c wfdb-10.2.0/examples/example5.c --- wfdb-10.1.6/examples/example5.c Thu Jun 24 11:38:29 1999 +++ wfdb-10.2.0/examples/example5.c Sun Oct 14 19:28:45 2001 @@ -5,15 +5,21 @@ int argc; char *argv[]; { - static WFDB_Siginfo s[WFDB_MAXSIG]; + WFDB_Siginfo *s; int i, nsig; if (argc < 2) { fprintf(stderr, "usage: %s record\n", argv[0]); exit(1); } - nsig = isigopen(argv[1], s, WFDB_MAXSIG); + nsig = isigopen(argv[1], NULL, 0); if (nsig < 1) exit(2); + s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); + if (s == NULL) { + fprintf(stderr, "insufficient memory\n"); + exit(3); + } + if (isigopen(argv[1], s, nsig) != nsig) exit(2); printf("Record %s\n", argv[1]); printf("Starting time: %s\n", timstr(0L)); printf("Sampling frequency: %g Hz\n", sampfreq(argv[1])); diff -Naur wfdb-10.1.6/examples/example6.c wfdb-10.2.0/examples/example6.c --- wfdb-10.1.6/examples/example6.c Thu Jun 24 11:38:29 1999 +++ wfdb-10.2.0/examples/example6.c Mon Oct 15 11:05:22 2001 @@ -5,13 +5,22 @@ int argc; char *argv[]; { - static WFDB_Siginfo s[WFDB_MAXSIG]; - static int i, nsig, nsamp=1000, vin[WFDB_MAXSIG], vout[WFDB_MAXSIG]; + WFDB_Siginfo *s; + int i, nsig, nsamp=1000; + WFDB_Sample *vin, *vout; if (argc < 2) { fprintf(stderr, "usage: %s record\n", argv[0]); exit(1); } - if ((nsig = isigopen(argv[1], s, WFDB_MAXSIG)) <= 0) exit(2); + if ((nsig = isigopen(argv[1], NULL, 0)) <= 0) exit(2); + s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); + vin = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); + vout = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); + if (s == NULL || vin == NULL || vout == NULL) { + fprintf(stderr, "insufficient memory\n"); + exit(3); + } + if (isigopen(argv[1], s, nsig) != nsig) exit(2); if (osigopen("8l", s, nsig) <= 0) exit(3); while (nsamp-- > 0 && getvec(vin) > 0) { for (i = 0; i < nsig; i++) diff -Naur wfdb-10.1.6/examples/example7.c wfdb-10.2.0/examples/example7.c --- wfdb-10.1.6/examples/example7.c Thu Jun 24 11:38:29 1999 +++ wfdb-10.2.0/examples/example7.c Sun Oct 14 19:50:36 2001 @@ -1,20 +1,21 @@ #include #include #define BUFLN 512 -int sample_ok = 1; +int nsig, sample_ok = 1; +WFDB_Sample *sbuf; sample(s, t) int s; long t; { - static int sbuf[BUFLN][WFDB_MAXSIG]; static long tt = -1L; if (t <= tt - BUFLN) fprintf(stderr, "sample: buffer too short\n"); while (t > tt) - if (getvec(sbuf[(++tt)&(BUFLN-1)]) < 0) sample_ok = 0; - return (sbuf[t&(BUFLN-1)][s]); + if (getvec(sbuf + nsig * ((++tt)&(BUFLN-1))) < 0) + sample_ok = 0; + return (*(sbuf + nsig * (t&(BUFLN-1)) + s)); } main(argc, argv) @@ -22,9 +23,10 @@ char *argv[]; { double *c, one = 1.0, vv, atof(); - int i, j, nc = argc - 4, nsig, v[WFDB_MAXSIG]; + int i, j, nc = argc - 4; long nsamp, t; - static WFDB_Siginfo s[WFDB_MAXSIG]; + static WFDB_Sample *v; + static WFDB_Siginfo *s; if (argc < 4) { fprintf(stderr, @@ -42,7 +44,16 @@ } for (i = 0; i < nc; i++) c[i] = atof(argv[i+4]); - if ((nsig = isigopen(argv[1], s, WFDB_MAXSIG)) < 1) + if ((nsig = isigopen(argv[1], NULL, 0)) < 1) + exit(3); + s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); + v = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); + sbuf = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample) * BUFLN); + if (s == NULL || v == NULL || sbuf == NULL) { + fprintf(stderr, "insufficient memory\n"); + exit(3); + } + if (isigopen(argv[1], s, nsig) != nsig) exit(3); if (isigsettime(strtim(argv[2])) < 0) exit(4); diff -Naur wfdb-10.1.6/examples/example8.c wfdb-10.2.0/examples/example8.c --- wfdb-10.1.6/examples/example8.c Thu Jun 24 11:38:29 1999 +++ wfdb-10.2.0/examples/example8.c Sun Oct 14 20:13:11 2001 @@ -4,22 +4,39 @@ main() { char answer[32], record[8], directory[32]; - int i, nsig = 0, v[WFDB_MAXSIG]; + int i, nsig = 0; long nsamp, t; double freq = 0.; - static char filename[WFDB_MAXSIG][32], description[WFDB_MAXSIG][32], - units[WFDB_MAXSIG][22]; - static WFDB_Siginfo s[WFDB_MAXSIG]; + char **filename, **description, **units; + WFDB_Sample *v; + WFDB_Siginfo *s; do { printf("Choose a record name [up to 6 characters]: "); fgets(record, 8, stdin); record[strlen(record)-1] = '\0'; } while (newheader(record) < 0); do { - printf("Number of signals to be recorded [1-%d]: ", - WFDB_MAXSIG); + printf("Number of signals to be recorded [>0]: "); fgets(answer, 32, stdin); sscanf(answer, "%d", &nsig); - } while (nsig < 1 || nsig > WFDB_MAXSIG); + } while (nsig < 1); + s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); + v = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); + filename = (char **)malloc(nsig * sizeof(char *)); + description = (char **)malloc(nsig * sizeof(char *)); + units = (char **)malloc(nsig * sizeof(char *)); + if (s == NULL || v == NULL || filename == NULL || + description == NULL || units == NULL) { + fprintf(stderr, "insufficient memory\n"); + exit(1); + } + for (i = 0; i < nsig; i++) { + if ((filename[i] = (char *)malloc(32)) == NULL || + (description[i] = (char *)malloc(32)) == NULL || + (units[i] = (char *)malloc(32)) == NULL) { + fprintf(stderr, "insufficient memory\n"); + exit(1); + } + } do { printf("Sampling frequency [Hz per signal, > 0]: "); fgets(answer, 32, stdin); sscanf(answer, "%lf", &freq); diff -Naur wfdb-10.1.6/examples/example9.c wfdb-10.2.0/examples/example9.c --- wfdb-10.1.6/examples/example9.c Thu Jun 24 11:38:29 1999 +++ wfdb-10.2.0/examples/example9.c Mon Oct 15 12:07:14 2001 @@ -6,11 +6,12 @@ int argc; char *argv[]; { - int btype,i,j,nbeats=0,nsig,hwindow,window,v[WFDB_MAXSIG],vb[WFDB_MAXSIG]; - long stoptime = 0L, *sum[WFDB_MAXSIG]; + int btype, i, j, nbeats = 0, nsig, hwindow, window; + long stoptime = 0L, **sum; WFDB_Anninfo a; WFDB_Annotation annot; - static WFDB_Siginfo s[WFDB_MAXSIG]; + WFDB_Sample *v, *vb; + WFDB_Siginfo *s; void *calloc(); if (argc < 3) { @@ -20,7 +21,21 @@ exit(1); } a.name = argv[1]; a.stat = WFDB_READ; - if ((nsig = wfdbinit(argv[2], &a, 1, s, WFDB_MAXSIG)) < 1) exit(2); + if ((nsig = isigopen(argv[2], NULL, 0)) < 1) exit(2); + s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); + v = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); + vb = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); + sum = (long **)malloc(nsig * sizeof(long *)); + if (s == NULL || v == NULL || vb == NULL || sum == NULL) { + fprintf(stderr, "%s: insufficient memory\n", argv[0]); + exit(2); + } + for (i = 0; i < nsig; i++) + if ((sum[i]=(long *)calloc(window,sizeof(long))) == NULL) { + fprintf(stderr, "%s: insufficient memory\n", argv[0]); + exit(2); + } + if (wfdbinit(argv[2], &a, 1, s, nsig) != nsig) exit(3); hwindow = strtim(".05"); window = 2*hwindow + 1; btype = (argc > 3) ? strann(argv[3]) : NORMAL; if (argc > 4) iannsettime(strtim(argv[4])); @@ -32,11 +47,6 @@ } else stoptime = s[0].nsamp; if (stoptime > 0L) stoptime -= hwindow; - for (i = 0; i < nsig; i++) - if ((sum[i]=(long *)calloc(window,sizeof(long))) == NULL) { - fprintf(stderr, "%s: insufficient memory\n", argv[0]); - exit(3); - } while (getann(0, &annot) == 0 && annot.time < hwindow) ; do { diff -Naur wfdb-10.1.6/examples/exgetvec.c wfdb-10.2.0/examples/exgetvec.c --- wfdb-10.1.6/examples/exgetvec.c Thu Jun 24 11:38:29 1999 +++ wfdb-10.2.0/examples/exgetvec.c Sun Oct 14 19:32:20 2001 @@ -1,13 +1,19 @@ +#include #include main() { - int i, j, nsig, v[WFDB_MAXSIG]; - static WFDB_Siginfo s[WFDB_MAXSIG]; + int i, j, nsig; + WFDB_Sample *v; + WFDB_Siginfo *s; - nsig = isigopen("100s", s, WFDB_MAXSIG); + nsig = isigopen("100s", NULL, 0); if (nsig < 1) + exit(1); + s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); + if (isigopen("100s", s, nsig) != nsig) exit(1); + v = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); for (i = 0; i < 10; i++) { if (getvec(v) < 0) break; diff -Naur wfdb-10.1.6/examples/exputvec.c wfdb-10.2.0/examples/exputvec.c --- wfdb-10.1.6/examples/exputvec.c Thu Jun 24 11:38:29 1999 +++ wfdb-10.2.0/examples/exputvec.c Sun Oct 14 19:32:00 2001 @@ -1,13 +1,20 @@ +#include #include main() { - int i, nsig, v[WFDB_MAXSIG]; - static WFDB_Siginfo s[WFDB_MAXSIG]; + int i, j, nsig; + WFDB_Sample *v; + WFDB_Siginfo *s; - if ((nsig = isigopen("100s", s, WFDB_MAXSIG)) < 1 || - osigopen("8l", s, nsig) < 1) + nsig = isigopen("100s", NULL, 0); + if (nsig < 1) + exit(1); + s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo)); + if (isigopen("100s", s, nsig) != nsig || + osigopen("8l", s, nsig) != nsig) exit(1); + v = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample)); for (i = 0; i < 10; i++) if (getvec(v) < 0 || putvec(v) < 0) break; diff -Naur wfdb-10.1.6/fortran/Makefile wfdb-10.2.0/fortran/Makefile --- wfdb-10.1.6/fortran/Makefile Wed May 24 22:35:27 2000 +++ wfdb-10.2.0/fortran/Makefile Tue Oct 9 00:14:17 2001 @@ -1,9 +1,9 @@ # file: Makefile G. Moody 23 August 1995 -# Last revised: 7 May 1999 +# Last revised: 8 October 2001 # # ----------------------------------------------------------------------------- # UNIX 'make' description file for compiling the Fortran example program -# Copyright (C) 1999 George B. Moody +# Copyright (C) 2001 George B. Moody # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software @@ -32,7 +32,7 @@ # `make clean' to remove it. example: example.f wfdbf.c - f77 -o example example.f wfdbf.c -lwfdb + f77 -o example -fwritable-strings example.f wfdbf.c -lwfdb # If you have `f2c', but not `f77', use `make example-alt' instead of `make'. example-alt: example.f wfdbf.c diff -Naur wfdb-10.1.6/fortran/README wfdb-10.2.0/fortran/README --- wfdb-10.1.6/fortran/README Sun Jan 30 04:13:19 2000 +++ wfdb-10.2.0/fortran/README Tue Oct 9 00:13:59 2001 @@ -1,8 +1,8 @@ file: README G. Moody 28 July 1995 - Last revised: 19 November 1999 + Last revised: 8 October 2001 _______________________________________________________________________________ Fortran wrappers for the WFDB library -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody These wrappers are free software; you can redistribute them and/or modify them under the terms of the GNU Library General Public License as published by the @@ -87,17 +87,13 @@ getvec(v) the first element of v, namely v(1), contains a sample of the first signal (signal 0). An attempt to reference v(0) in your Fortran program is illegal. -If this discussion is not clear, refer to the ECG Database Programmer's Guide, +If this discussion is not clear, refer to the WFDB Programmer's Guide, especially to the Glossary entries for Annotator number and Signal number. Certain parameters are defined in `wfdb.h' (in the `lib' directory at the same level as this one; a copy of this file is referenced by the C statement #include -near the top of most of the *.c files in the `app' directory). Among these -parameters are the maximum number of signals that can be open at once -(WFDB_MAXSIG, currently 32) and the maximum number of input (or output) -annotators open at once (WFDB_MAXANN, currently 2). If you need to increase -these parameters, modify wfdb.h and recompile the WFDB library. +near the top of most of the *.c files in the `app' directory). If you are using a UNIX Fortran compiler, or a Fortran-to-C translator, note that the trailing `_' in the names of the functions defined in wfdbf.c should @@ -151,40 +147,17 @@ Note to users of g77 (the GNU Fortran compiler) ----------------------------------------------- -There appear to be two incompatibilities between these wrappers and g77, at -least under Linux. The first is easily avoided (g77 chokes on wfdbf.c); to -work around this, just compile wfdbf.c using gcc: - gcc -c wfdbf.c -then compile your Fortran code with g77 linking with wfdbf.o and the WFDB -library: - g77 -o myprogram myprogram.f wfdbf.o -lwfdb -The more serious problem is that the values returned by the wrapper functions -don't appear to be in the formats expected by the Fortran code. The example -program in this directory, e.g., produces this output when compiled as above: - - init: can't open header for record 100s - Number of signals in record 100s = -1 - init: can't open header for record 100s - Sampling frequency = -1.00 - v(1) = **** v(2) = **** - v(1) = **** v(2) = **** - v(1) = **** v(2) = **** - v(1) = **** v(2) = **** - v(1) = **** v(2) = **** - v(1) = **** v(2) = **** - v(1) = **** v(2) = **** - v(1) = **** v(2) = **** - v(1) = **** v(2) = **** - v(1) = **** v(2) = **** - -If you understand what's happening, please send me a note and suggest a fix. -Otherwise, I recommend that you use the Fortran-to-C translator (f2c, supplied -with Red Hat Linux and most other Linux distributions) to compile your Fortran -programs with these wrappers. For example, produce an executable from -example.f as follows: - f2c example.f - cc -o example example.c wfdbf.c -lf2c -lm -lwfdb -The executable generated this way yields the correct output: +When compiling the wrappers, use the option -fwritable-strings, as in: + g77 -c -DFIXSTRINGS -fwritable-strings wfdbf.c + +You should also be sure to use -fwritable-strings when compiling your +Fortran code. For example: + g77 -o myprogram -fwritable-strings myprogram.f wfdbf.o -lwfdb + +If you use the older 'f2c' (Fortran-to-C translator), it is not necessary to +use -fwritable-strings. + +If you compile and run the example program, its output should be: Number of signals in record 100s = 2 Sampling frequency = 360.00 diff -Naur wfdb-10.1.6/fortran/example.f wfdb-10.2.0/fortran/example.f --- wfdb-10.1.6/fortran/example.f Sun Jan 30 04:13:19 2000 +++ wfdb-10.2.0/fortran/example.f Mon Oct 8 22:42:36 2001 @@ -1,9 +1,9 @@ C file: example.f G. Moody 23 August 1995 -C Last revised: 7 May 1999 +C Last revised: 8 October 2001 (comments only) C C ----------------------------------------------------------------------------- C Sample program illustrating use of Fortran wrappers for the WFDB library -C Copyright (C) 1999 George B. Moody +C Copyright (C) 2001 George B. Moody C C This program is free software; you can redistribute it and/or modify it under C the terms of the GNU General Public License as published by the Free Software @@ -26,7 +26,7 @@ C C This program is a slightly elaborated version of the C example shown in C section 1.1 of the WFDB Programmer's Guide. It uses the WFDB library to open -C record 100s (a sample record, provided in the `microdb' directory at the same +C record 100s (a sample record, provided in the `data' directory at the same C level as this one). The program prints the number of signals, the sampling C frequency, and the first ten samples from each signal. C @@ -48,8 +48,7 @@ real f C Open up to 32 signals from record 100s. (There are only 2 signals in this -C record, however.) To open more than 32 signals in any record, you will need -C to modify WFDB_MAXSIG in , and recompile the DB library. +C record, however.) i = isigopen("100s", 32) write (6,1) i 1 format("Number of signals in record 100s = ", i2) diff -Naur wfdb-10.1.6/fortran/wfdbf.c wfdb-10.2.0/fortran/wfdbf.c --- wfdb-10.1.6/fortran/wfdbf.c Sun Jan 30 04:13:20 2000 +++ wfdb-10.2.0/fortran/wfdbf.c Mon Oct 8 23:58:43 2001 @@ -208,8 +208,6 @@ char *record; long *nsig; { - int i; - fcstring(record); return (osigopen(record, sinfo, (unsigned int)(*nsig))); } @@ -400,7 +398,7 @@ long *code; char *string; { - fcstring(string) + fcstring(string); return (setannstr((int)(*code), string)); } diff -Naur wfdb-10.1.6/lib/Makefile wfdb-10.2.0/lib/Makefile --- wfdb-10.1.6/lib/Makefile Wed Aug 1 10:28:34 2001 +++ wfdb-10.2.0/lib/Makefile Mon Oct 15 14:40:00 2001 @@ -33,12 +33,12 @@ # type `make slib'. # _____________________________________________________________________________ # file: version.def G. Moody 24 May 2000 -# Last revised: 28 February 2001 +# Last revised: 14 August 2001 # Each release of the WFDB Software Package is identified by a three-part # version number, defined here: MAJOR = 10 -MINOR = 1 -RELEASE = 6 +MINOR = 2 +RELEASE = 0 VERSION = $(MAJOR).$(MINOR).$(RELEASE) # VDEFS is the set of C compiler options needed to set version number variables diff -Naur wfdb-10.1.6/lib/Makefile-dos-gcc wfdb-10.2.0/lib/Makefile-dos-gcc --- wfdb-10.1.6/lib/Makefile-dos-gcc Wed May 24 22:35:27 2000 +++ wfdb-10.2.0/lib/Makefile-dos-gcc Wed Dec 31 19:00:00 1969 @@ -1,143 +0,0 @@ -# file: Makefile-dos-gcc G. Moody 23 April 1997 -# Last revised: 21 January 2000 Version 10.1.1 -# GCC-DOS 'make' description file for compiling the WFDB library - -# _____________________________________________________________________________ -# wfdb: a library for reading and writing annotated waveforms(time series data) -# Copyright (C) 2000 George B. Moody -# -# This library is free software; you can redistribute it and/or modify it under -# the terms of the GNU Library General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) any -# later version. -# -# This library is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for -# more details. -# -# You should have received a copy of the GNU Library General Public License -# along with this library; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# You may contact the author by e-mail (george@mit.edu) or postal mail -# (MIT Room E25-505A, Cambridge, MA 02139 USA). For updates to this software, -# please visit PhysioNet (http://www.physionet.org/). -# _____________________________________________________________________________ - -# This file is used with the UNIX `make' command to cross-compile the WFDB -# library. Before using it for the first time, check that the site-specific -# variables below are appropriate for your system. To build and install the -# MS-DOS WFDB library, just type `make -f Makefile-dos-gcc' (from within this -# directory). - -# Version numbers -# --------------- - -# Each release of the WFDB Software Package is identified by a three-part -# version number, defined in this section (unless overridden by settings in -# the top-level Makefile for the WFDB Software Package). See the top-level -# Makefile (in the parent of this directory) for details. -MAJOR = 10 -MINOR = 1 -RELEASE = 1 -VERSION = $(MAJOR).$(MINOR).$(RELEASE) - -# Site-specific variables -# ----------------------- - -# CCDIR is the directory containing the cross-compiler and the binary -# file utilities for MSDOS. -CCDIR = /usr/lib/gcc-lib/i386-go32-msdos/2.7.2 - -# CC is the name of the cross-compiler. -CC = $(CCDIR)/gcc - -# INCDIR should be one of the directories searched by CC for #include <...> -# files. -INCDIR = /usr/local/dos/include - -# CCDEFS is the set of C compiler options needed to set preprocessor variables -# while compiling the WFDB Software Package. You should include definitions of -# the major, minor, and release numbers, and of MSDOS as shown below. Other -# definitions are needed only for various versions of UNIX and should be -# omitted here. -CCDEFS = -DWFDB_MAJOR=$(MAJOR) -DWFDB_MINOR=$(MINOR) -DWFDB_RELEASE=$(RELEASE) -DMSDOS - -# CFLAGS is the set of C compiler options. CFLAGS should always include -# CCDEFS. Add the following options to CFLAGS as appropriate (separating them -# by spaces if you use more than one): -# -g to save symbols for debugging -# -O if you trust your C compiler's optimizer -# -I$(INCDIR) needed if INCDIR is not in the normal search path for -# `#include' files; harmless otherwise -# `gcc-dos' is able to accept both -g and -O simultaneously; using a debugger -# on optimized code can be tricky, though, and you may prefer to compile with -# -g and not -O if you need to use a symbolic debugger. For normal use, -# optimized code is preferable (the gcc optimizer is solid and effective). -CFLAGS = -O -I$(INCDIR) $(CCDEFS) - -# LIBDIR should be one of the directories searched by CC's loader for -l... -# libraries. You will also need to have write permission in LIBDIR. If you -# plan to make a shared WFDB library (see below), note that WFDB application -# users will need to have read permission in LIBDIR. -LIBDIR = /usr/local/dos/lib - -# WFDBLIB is the name of the standard WFDB library. In order to access it via -# `-lwfdb', WFDBLIB should be `libwfdb.a'. -WFDBLIB = libwfdb.a - -# MAKE is the name of the `make' utility itself, in this case with an option -# to use the special gcc-dos Makefiles by default when running a recursive -# make. -MAKE = make -f Makefile-dos-gcc - -# AR is the name of the command used to build a `.a' library from `.o' -# files, and ARFLAGS is the set of options used when doing so. -AR = $(CCDIR)/ar -# ARFLAGS = rv - -# BUILDLIB is the command to be used to create WFDBLIB once all of its -# components have been compiled separately. This will not usually need to be -# changed. -BUILDLIB = $(AR) $(ARFLAGS) $(WFDBLIB) $(OFILES) - -# It should not be necessary to modify anything below this line. -# ----------------------------------------------------------------------------- - -HEADERS = $(INCDIR)/ecg/wfdb.h $(INCDIR)/ecg/ecgcodes.h $(INCDIR)/ecg/ecgmap.h -HFILES = wfdb.h ecgcodes.h ecgmap.h wfdblib.h -CFILES = wfdbinit.c annot.c signal.c calib.c wfdbio.c -OFILES = wfdbinit.o annot.o signal.o calib.o wfdbio.o -MFILES = Makefile makefile.dos - -# `make' or `make install': build and install the WFDB library and headers -install: $(LIBDIR)/$(WFDBLIB) -$(LIBDIR)/$(WFDBLIB): $(HEADERS) $(OFILES) - $(BUILDLIB) - cp $(WFDBLIB) $(LIBDIR) - -# `make lib': build the library in the current directory -lib: $(HEADERS) $(OFILES) - $(BUILDLIB) - -# `make clean': remove intermediate and backup files -clean: - rm -f $(OFILES) *~ - -# Rules for installing the header files -$(INCDIR)/ecg: - mkdir $(INCDIR)/ecg -$(INCDIR)/ecg/wfdb.h: $(INCDIR)/ecg wfdb.h - cp -p wfdb.h $(INCDIR)/ecg -$(INCDIR)/ecg/ecgcodes.h: $(INCDIR)/ecg ecgcodes.h - cp -p ecgcodes.h $(INCDIR)/ecg -$(INCDIR)/ecg/ecgmap.h: $(INCDIR)/ecg ecgmap.h - cp -p ecgmap.h $(INCDIR)/ecg - -# Prerequisites for the library modules -wfdbinit.o: $(INCDIR)/ecg/wfdb.h wfdblib.h wfdbinit.c -annot.o: $(HEADERS) wfdblib.h annot.c -signal.o: $(INCDIR)/ecg/wfdb.h wfdblib.h signal.c -calib.o: $(INCDIR)/ecg/wfdb.h wfdblib.h calib.c -wfdbio.o: $(INCDIR)/ecg/wfdb.h wfdblib.h wfdbio.c diff -Naur wfdb-10.1.6/lib/annot.c wfdb-10.2.0/lib/annot.c --- wfdb-10.1.6/lib/annot.c Sun Jan 30 04:13:20 2000 +++ wfdb-10.2.0/lib/annot.c Tue Sep 11 10:53:53 2001 @@ -1,10 +1,10 @@ /* file: annot.c G. Moody 13 April 1989 - Last revised: 15 September 1999 wfdblib 10.1.0 + Last revised: 11 September 2001 wfdblib 10.2.0 WFDB library functions for annotations _______________________________________________________________________________ wfdb: a library for reading and writing annotated waveforms (time series data) -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free @@ -29,6 +29,8 @@ visible outside of this file: get_ann_table (reads tables used by annstr, strann, and anndesc) put_ann_table (writes tables used by annstr, strann, and anndesc) + allociann (sets max number of simultaneously open input annotators) + allocoann (sets max number of simultaneously open output annotators) This file also contains definitions of the following WFDB library functions: annopen (opens annotation files) @@ -100,33 +102,39 @@ #define EOAF 0377 /* padding for end of AHA annotation files */ /* Shared local data */ -static unsigned niaf; /* number of open input annotators */ -static WFDB_FILE *iaf[WFDB_MAXANN]; /* file pointers for open input - annotators */ -static WFDB_Anninfo iafinfo[WFDB_MAXANN]; /* input annotator information */ -static WFDB_Annotation iann[WFDB_MAXANN];/* next annotation from each input */ -static unsigned iaword[WFDB_MAXANN]; /* next word from each input file */ -static int ateof[WFDB_MAXANN]; /* EOF-reached indicator for each input */ -static WFDB_Time iantime[WFDB_MAXANN]; /* annotation time (MIT format only). - This equals iann[].time unless a SKIP - follows iann; in such cases, it is - the time of the SKIP (i.e., the time - of the annotation following iann) */ - -static unsigned noaf; /* number of open output annotators */ -static WFDB_FILE *oaf[WFDB_MAXANN]; /* file pointers for open output - annotators */ -static WFDB_Anninfo oafinfo[WFDB_MAXANN]; /* output annotator information */ -static WFDB_Annotation oann[WFDB_MAXANN];/* latest annotation in each output */ -static int oanum[WFDB_MAXANN]; /* output annot numbers (AHA format only) */ -static char out_of_order[WFDB_MAXANN]; /* if >0, one or more annotations - written by putann are not in the - canonical (time, chan) order */ -static char oarec[WFDB_MAXANN][WFDB_MAXRNL+1]; - /* record with which each output annotator is associated */ +static unsigned maxiann; /* max allowed number of input annotators */ +static unsigned niaf; /* number of open input annotators */ +static struct iadata { + WFDB_FILE *file; /* file pointer for input annotation file */ + WFDB_Anninfo info; /* input annotator information */ + WFDB_Annotation ann; /* next annotation to be returned by getann */ + WFDB_Annotation pann; /* pushed-back annotation from ungetann */ + unsigned word; /* next word from the input file */ + int ateof; /* EOF-reached indicator */ + char auxstr[1+255+1]; /* aux string buffer (byte count+data+null) */ + unsigned index; /* next available position in auxstr */ + WFDB_Time tt; /* annotation time (MIT format only). This + equals ann.time unless a SKIP follows ann; + in such cases, it is the time of the SKIP + (i.e., the time of the annotation following + ann) */ +} **iad; + +static unsigned maxoann; /* max allowed number of output annotators */ +static unsigned noaf; /* number of open output annotators */ +static struct oadata { + WFDB_FILE *file; /* file pointer for output annotation file */ + WFDB_Anninfo info; /* output annotator information */ + WFDB_Annotation ann; /* most recent annotation written by putann */ + int seqno; /* annotation serial number (AHA format only)*/ + char rname[WFDB_MAXRNL+1]; /* record with which annotator is associated */ + char out_of_order; /* if >0, one or more annotations written by + putann are not in the canonical (time, chan) + order */ +} **oad; -static int tmul; /* `time' fields in annotations are - tmul * times in annotation files */ +static int tmul; /* `time' fields in annotations are + tmul * times in annotation files */ /* Local functions (for the use of other functions in this module only). */ @@ -191,6 +199,60 @@ return (0); } +/* Allocate workspace for up to n input annotators. */ +static int allociann(n) +unsigned n; +{ + if (maxiann < n) { /* allocate input annotator data structures */ + unsigned m = maxiann; + struct iadata **iadnew = realloc(iad, n*sizeof(struct iadata *)); + + if (iadnew == NULL) { + wfdb_error("annopen: too many (%d) input annotators\n", n); + return (-1); + } + iad = iadnew; + while (m < n) { + if ((iad[m] = calloc(1, sizeof(struct iadata))) == NULL) { + wfdb_error("annopen: too many (%d) input annotators\n", n); + while (--m > maxiann) + free(iad[m]); + return (-1); + } + m++; + } + maxiann = n; + } + return (maxiann); +} + +/* Allocate workspace for up to n output annotators. */ +static int allocoann(n) +unsigned n; +{ + if (maxoann < n) { /* allocate output annotator data structures */ + unsigned m = maxoann; + struct oadata **oadnew = realloc(oad, n*sizeof(struct oadata *)); + + if (oadnew == NULL) { + wfdb_error("annopen: too many (%d) output annotators\n", n); + return (-1); + } + oad = oadnew; + while (m < n) { + if ((oad[m] = calloc(1, sizeof(struct oadata))) == NULL) { + wfdb_error("annopen: too many (%d) output annotators\n", n); + while (--m > maxoann) + free(oad[m]); + return (-1); + } + m++; + } + maxoann = n; + } + return (maxoann); +} + /* WFDB library functions (for general use). */ FINT annopen(record, aiarray, nann) @@ -199,7 +261,7 @@ unsigned int nann; { int a; - unsigned int i; + unsigned int i, niafneeded, noafneeded; if (*record == '+') /* don't close open annotation files */ record++; /* discard the '+' prefix */ @@ -208,48 +270,71 @@ tmul = getspf(); } + /* Prescan aiarray to see how large maxiann and maxoann must be. */ + niafneeded = niaf; + noafneeded = noaf; + for (i = 0; i < nann; i++) + switch (aiarray[i].stat) { + case WFDB_READ: /* standard (MIT-format) input file */ + case WFDB_AHA_READ: /* AHA-format input file */ + niafneeded++; + break; + case WFDB_WRITE: /* standard (MIT-format) output file */ + case WFDB_AHA_WRITE: /* AHA-format output file */ + noafneeded++; + break; + default: + wfdb_error( + "annopen: illegal stat %d for annotator %s, record %s\n", + aiarray[i].stat, aiarray[i].name, record); + return (-5); + } + /* Allocate workspace. */ + if (allociann(niafneeded) < 0 || allocoann(noafneeded) < 0) + return (-3); + for (i = 0; i < nann; i++) { /* open the annotation files */ + struct iadata *ia; + struct oadata *oa; + switch (aiarray[i].stat) { case WFDB_READ: /* standard (MIT-format) input file */ case WFDB_AHA_READ: /* AHA-format input file */ + ia = iad[niaf]; wfdb_setirec(record); - if (niaf >= WFDB_MAXANN) { - wfdb_error("annopen: too many (> %d) input annotators\n", - WFDB_MAXANN); - return (-3); - } - if ((iaf[niaf] = wfdb_open(aiarray[i].name,record,WFDB_READ)) == + if ((ia->file=wfdb_open(aiarray[i].name,record,WFDB_READ)) == NULL) { wfdb_error("annopen: can't read annotator %s for record %s\n", aiarray[i].name, record); return (-3); } - if ((iafinfo[niaf].name = + if ((ia->info.name = (char *)malloc((unsigned)(strlen(aiarray[i].name)+1))) == NULL) { wfdb_error("annopen: insufficient memory\n"); return (-3); } - (void)strcpy(iafinfo[niaf].name, aiarray[i].name); + (void)strcpy(ia->info.name, aiarray[i].name); /* Try to figure out what format the file is in. AHA-format files begin with a null byte and an ASCII character which is one of the legal AHA annotation codes other than '[' or ']'. MIT annotation files cannot begin in this way. */ - iaword[niaf] = (unsigned)wfdb_g16(iaf[niaf]); - a = (iaword[niaf] >> 8) & 0xff; - if ((iaword[niaf]&0xff) || ammap(a)==NOTQRS || a=='[' || a==']') { + ia->word = (unsigned)wfdb_g16(iad[niaf]->file); + a = (ia->word >> 8) & 0xff; + if ((ia->word & 0xff) || + ammap(a) == NOTQRS || a == '[' || a == ']') { if (aiarray[i].stat != WFDB_READ) { wfdb_error("warning (annopen, annotator %s, record %s):\n", aiarray[i].name, record); wfdb_error(" file appears to be in MIT format\n"); wfdb_error(" ... continuing under that assumption\n"); } - iafinfo[niaf].stat = WFDB_READ; + (ia->info).stat = WFDB_READ; /* read any initial null annotation(s) */ - while ((iaword[niaf] & CODE) == SKIP) { - iantime[niaf] += wfdb_g32(iaf[niaf]); - iaword[niaf] = (unsigned)wfdb_g16(iaf[niaf]); + while ((ia->word & CODE) == SKIP) { + ia->tt += wfdb_g32(ia->file); + ia->word = (unsigned)wfdb_g16(ia->file); } } else { @@ -259,194 +344,184 @@ wfdb_error(" file appears to be in AHA format\n"); wfdb_error(" ... continuing under that assumption\n"); } - iafinfo[niaf].stat = WFDB_AHA_READ; + ia->info.stat = WFDB_AHA_READ; } - iann[niaf].anntyp = 0; /* any pushed-back annot is invalid */ + ia->ann.anntyp = 0; /* any pushed-back annot is invalid */ niaf++; (void)get_ann_table(niaf-1); break; case WFDB_WRITE: /* standard (MIT-format) output file */ case WFDB_AHA_WRITE: /* AHA-format output file */ - if (noaf >= WFDB_MAXANN) { - wfdb_error("annopen: too many (> %d) output annotators\n", - WFDB_MAXANN); - return (-4); - } + oa = oad[noaf]; /* Quit (with message from wfdb_checkname) if name is illegal */ if (wfdb_checkname(aiarray[i].name, "annotator")) return (-4); - if ((oaf[noaf]=wfdb_open(aiarray[i].name,record,WFDB_WRITE)) == + if ((oa->file=wfdb_open(aiarray[i].name,record,WFDB_WRITE)) == NULL) { wfdb_error("annopen: can't write annotator %s for record %s\n", aiarray[i].name, record); return (-4); } - if ((oafinfo[noaf].name = + if ((oa->info.name = (char *)malloc((unsigned)(strlen(aiarray[i].name)+1))) == NULL) { wfdb_error("annopen: insufficient memory\n"); return (-4); } - (void)strcpy(oafinfo[noaf].name, aiarray[i].name); - (void)strncpy(oarec[noaf], record, WFDB_MAXRNL); - oann[noaf].time = 0L; - oafinfo[noaf].stat = aiarray[i].stat; - out_of_order[noaf] = 0; + (void)strcpy(oa->info.name, aiarray[i].name); + (void)strncpy(oa->rname, record, WFDB_MAXRNL); + oa->ann.time = 0L; + oa->info.stat = aiarray[i].stat; + oa->out_of_order = 0; (void)put_ann_table(noaf++); break; - - default: - wfdb_error( - "annopen: illegal stat %d for annotator %s, record %s\n", - aiarray[i].stat, aiarray[i].name, record); - return (-5); } } return (0); } -static WFDB_Annotation ungotten[WFDB_MAXANN]; /* pushed-back annotations */ - -FINT getann(an, annot) /* read an annotation from iaf[an] into *annot */ -WFDB_Annotator an; /* annotator number */ +FINT getann(n, annot) /* read an annotation from annotator n into *annot */ +WFDB_Annotator n; /* annotator number */ WFDB_Annotation *annot; /* address of structure to be filled in */ { - static char auxstr[WFDB_MAXANN][1+255+1]; /* byte count + data + null */ - static unsigned ai[WFDB_MAXANN]; int a, len; + struct iadata *ia; - if (an >= niaf || iaf[an] == NULL) { - wfdb_error("getann: can't read annotator %d\n", an); + if (n >= niaf || (ia = iad[n]) == NULL || ia->file == NULL) { + wfdb_error("getann: can't read annotator %d\n", n); return (-2); } - if (ungotten[an].anntyp) { - *annot = ungotten[an]; - ungotten[an].anntyp = 0; + if (ia->pann.anntyp) { + *annot = ia->pann; + ia->pann.anntyp = 0; return (0); } - if (ateof[an]) { - if (ateof[an] != -1) + if (ia->ateof) { + if (ia->ateof != -1) return (-1); /* reached logical EOF */ wfdb_error("getann: unexpected EOF in annotator %s\n", - iafinfo[an].name); + ia->info.name); return (-3); } - *annot = iann[an]; + *annot = ia->ann; - switch (iafinfo[an].stat) { + switch (ia->info.stat) { case WFDB_READ: /* MIT-format input file */ default: - if (iaword[an] == 0) { /* logical end of file */ - ateof[an] = 1; + if (ia->word == 0) { /* logical end of file */ + ia->ateof = 1; return (0); } - iantime[an] += iaword[an]&DATA; /* annotation time */ - iann[an].time = iantime[an] * tmul; - iann[an].anntyp = (iaword[an]&CODE) >> CS; /* set annotation type */ - iann[an].subtyp = 0; /* reset subtype field */ - iann[an].aux = NULL; /* reset aux field */ - while (((iaword[an] = (unsigned)wfdb_g16(iaf[an]))&CODE) >= PAMIN && - !wfdb_feof(iaf[an])) - switch (iaword[an] & CODE) { /* process pseudo-annotations */ - case SKIP: iantime[an] += wfdb_g32(iaf[an]); break; - case SUB: iann[an].subtyp = DATA & iaword[an]; break; - case CHN: iann[an].chan = DATA & iaword[an]; break; - case NUM: iann[an].num = DATA & iaword[an]; break; + ia->tt += ia->word & DATA; /* annotation time */ + ia->ann.time = ia->tt * tmul; + ia->ann.anntyp = (ia->word & CODE) >> CS; /* set annotation type */ + ia->ann.subtyp = 0; /* reset subtype field */ + ia->ann.aux = NULL; /* reset aux field */ + while (((ia->word = (unsigned)wfdb_g16(ia->file))&CODE) >= PAMIN && + !wfdb_feof(ia->file)) + switch (ia->word & CODE) { /* process pseudo-annotations */ + case SKIP: ia->tt += wfdb_g32(ia->file); break; + case SUB: ia->ann.subtyp = DATA & ia->word; break; + case CHN: ia->ann.chan = DATA & ia->word; break; + case NUM: ia->ann.num = DATA & ia->word; break; case AUX: /* auxiliary information */ - len = iaword[an] & 0377; /* length of auxiliary data */ - if (ai[an] >= 256 - len) ai[an] = 0; /* buffer index */ - iann[an].aux = auxstr[an]+ai[an]; /* save buffer pointer */ - auxstr[an][ai[an]++] = len; /* save length byte */ + len = ia->word & 0377; /* length of auxiliary data */ + if (ia->index >= 256 - len) + ia->index = 0; /* buffer index */ + ia->ann.aux = ia->auxstr + ia->index; /* save pointer */ + ia->auxstr[ia->index++] = len; /* save length byte */ /* Now read the data. Note that an extra byte may be present in the annotation file to preserve word alignment; if so, this extra byte is read and then overwritten by the null in the second statement below. */ - (void)wfdb_fread(auxstr[an]+ai[an], 1, (len+1)&~1, iaf[an]); - auxstr[an][ai[an]+len] = '\0'; /* add a null */ - ai[an] += len+1; /* update buffer pointer */ + (void)wfdb_fread(ia->auxstr+ia->index,1,(len+1)&~1,ia->file); + ia->auxstr[ia->index + len] = '\0'; /* add a null */ + ia->index += len+1; /* update buffer index */ break; default: break; } break; case WFDB_AHA_READ: /* AHA-format input file */ - if ((iaword[an]&0377) == EOAF) { /* logical end of file */ - ateof[an] = 1; + if ((ia->word&0377) == EOAF) { /* logical end of file */ + ia->ateof = 1; return (0); } - a = iaword[an] >> 8; /* AHA annotation code */ - iann[an].anntyp = ammap(a); /* convert to MIT annotation code */ - iann[an].time = wfdb_g32(iaf[an]) * tmul; /* time of annotation */ - if (wfdb_g16(iaf[an]) <= 0) /* serial number (starts at 1) */ - wfdb_error("getann: unexpected annot number in file %d\n", an); - iann[an].subtyp = wfdb_getc(iaf[an]); /* MIT annotation subtype */ - if (a == 'U' && iann[an].subtyp == 0) - iann[an].subtyp = -1; /* unreadable (noise subtype -1) */ - iann[an].chan = wfdb_getc(iaf[an]); /* MIT annotation code */ - if (ai[an] >= 256 - (AUXLEN+2)) ai[an] = 0; - (void)wfdb_fread(auxstr[an]+ai[an]+1,1,AUXLEN,iaf[an]); /* read aux - data */ + a = ia->word >> 8; /* AHA annotation code */ + ia->ann.anntyp = ammap(a); /* convert to MIT annotation code */ + ia->ann.time = wfdb_g32(ia->file) * tmul; /* time of annotation */ + if (wfdb_g16(ia->file) <= 0) /* serial number (starts at 1) */ + wfdb_error("getann: unexpected annot number in annotator %s\n", + ia->info.name); + ia->ann.subtyp = wfdb_getc(ia->file); /* MIT annotation subtype */ + if (a == 'U' && ia->ann.subtyp == 0) + ia->ann.subtyp = -1; /* unreadable (noise subtype -1) */ + ia->ann.chan = wfdb_getc(ia->file); /* MIT annotation code */ + if (ia->index >= 256 - (AUXLEN+2)) ia->index = 0; + /* read aux data */ + (void)wfdb_fread(ia->auxstr + ia->index + 1, 1, AUXLEN, ia->file); /* There is very limited space in AHA format files for auxiliary information, so no length byte is recorded; instead, we assume that if the first byte of auxiliary data is not null, that up to AUXLEN bytes may be significant. */ - if (auxstr[an][ai[an]+1]) { - auxstr[an][ai[an]] = AUXLEN; - iann[an].aux = auxstr[an]+ai[an]; /* save buffer pointer */ - auxstr[an][ai[an]+1+AUXLEN] = '\0'; /* add a null */ - ai[an] += AUXLEN+2; /* update buffer pointer */ + if (ia->auxstr[ia->index+1]) { + ia->auxstr[ia->index] = AUXLEN; + ia->ann.aux = ia->auxstr + ia->index; /* save buffer pointer */ + ia->auxstr[ia->index + 1 + AUXLEN] = '\0'; /* add a null */ + ia->index += AUXLEN+2; /* update buffer index */ } else - iann[an].aux = NULL; - iaword[an] = (unsigned)wfdb_g16(iaf[an]); + ia->ann.aux = NULL; + ia->word = (unsigned)wfdb_g16(ia->file); break; } - if (wfdb_feof(iaf[an])) - ateof[an] = -1; + if (wfdb_feof(ia->file)) + ia->ateof = -1; return (0); } -FINT ungetann(an, annot) /* push back an annotation into an input stream */ -WFDB_Annotator an; /* annotator number */ +FINT ungetann(n, annot) /* push back an annotation into an input stream */ +WFDB_Annotator n; /* annotator number */ WFDB_Annotation *annot; /* address of annotation to be pushed back */ { - if (an >= niaf) { - wfdb_error("ungetann: annotator %d is not initialized\n", an); + if (n >= niaf || iad[n] == NULL) { + wfdb_error("ungetann: annotator %d is not initialized\n", n); return (-2); } - if (ungotten[an].anntyp) { + if (iad[n]->pann.anntyp) { wfdb_error("ungetann: pushback buffer is full\n"); wfdb_error( "ungetann: annotation at %ld, annotator %d not pushed back\n", - annot->time, an); + annot->time, n); return (-1); } - ungotten[an] = *annot; + iad[n]->pann = *annot; return (0); } -FINT putann(an, annot) /* write annotation addressed by annot to oaf[an] */ -WFDB_Annotator an; /* annotator number */ +FINT putann(n, annot) /* write annotation at annot to annotator n */ +WFDB_Annotator n; /* annotator number */ WFDB_Annotation *annot; /* address of annotation to be written */ { unsigned annwd; char *ap; int i, len; long delta, t; + struct oadata *oa; - if (an >= noaf || oaf[an] == NULL) { - wfdb_error("putann: can't write annotation file %d\n", an); + if (n >= noaf || (oa = oad[n]) == NULL || oa->file == NULL) { + wfdb_error("putann: can't write annotation file %d\n", n); return (-2); } t = annot->time / tmul; - if (((delta = t - oann[an].time) < 0L || - (delta == 0L && annot->chan <= oann[an].chan)) && - (annot->time != 0L || oann[an].time != 0L)) { - out_of_order[an] = 1; + if (((delta = t - oa->ann.time) < 0L || + (delta == 0L && annot->chan <= oa->ann.chan)) && + (annot->time != 0L || oa->ann.time != 0L)) { + oa->out_of_order = 1; } - switch (oafinfo[an].stat) { + switch (oa->info.stat) { case WFDB_WRITE: /* MIT-format output file */ default: if (annot->anntyp == 0) { @@ -454,56 +529,57 @@ must not write a word of zeroes that would be interpreted as an EOF. To avoid this, putann writes a SKIP to the location just before the desired one; thus annwd (below) is never 0. */ - wfdb_p16(SKIP, oaf[an]); wfdb_p32(delta-1, oaf[an]); delta = 1; + wfdb_p16(SKIP, oa->file); wfdb_p32(delta-1, oa->file); delta = 1; } else if (delta > MAXRR || delta < 0L) { - wfdb_p16(SKIP, oaf[an]); wfdb_p32(delta, oaf[an]); delta = 0; + wfdb_p16(SKIP, oa->file); wfdb_p32(delta, oa->file); delta = 0; } annwd = (int)delta + ((int)(annot->anntyp) << CS); - wfdb_p16(annwd, oaf[an]); + wfdb_p16(annwd, oa->file); if (annot->subtyp != 0) { annwd = SUB + (DATA & annot->subtyp); - wfdb_p16(annwd, oaf[an]); + wfdb_p16(annwd, oa->file); } - if (annot->chan != oann[an].chan) { + if (annot->chan != oa->ann.chan) { annwd = CHN + (DATA & annot->chan); - wfdb_p16(annwd, oaf[an]); + wfdb_p16(annwd, oa->file); } - if (annot->num != oann[an].num) { + if (annot->num != oa->ann.num) { annwd = NUM + (DATA & annot->num); - wfdb_p16(annwd, oaf[an]); + wfdb_p16(annwd, oa->file); } if (annot->aux != NULL && *annot->aux != 0) { annwd = AUX+(unsigned)(*annot->aux); - wfdb_p16(annwd, oaf[an]); - (void)wfdb_fwrite(annot->aux + 1, 1, *annot->aux, oaf[an]); + wfdb_p16(annwd, oa->file); + (void)wfdb_fwrite(annot->aux + 1, 1, *annot->aux, oa->file); if (*annot->aux & 1) - (void)wfdb_putc('\0', oaf[an]); + (void)wfdb_putc('\0', oa->file); } break; case WFDB_AHA_WRITE: /* AHA-format output file */ - (void)wfdb_putc('\0', oaf[an]); - (void)wfdb_putc(mamap(annot->anntyp, annot->subtyp), oaf[an]); - wfdb_p32(annot->time, oaf[an]); - wfdb_p16((unsigned int)(++oanum[an]), oaf[an]); - (void)wfdb_putc(annot->subtyp, oaf[an]); - (void)wfdb_putc(annot->anntyp, oaf[an]); + (void)wfdb_putc('\0', oa->file); + (void)wfdb_putc(mamap(annot->anntyp, annot->subtyp), oa->file); + wfdb_p32(annot->time, oa->file); + wfdb_p16((unsigned int)(++(oa->seqno)), oa->file); + (void)wfdb_putc(annot->subtyp, oa->file); + (void)wfdb_putc(annot->anntyp, oa->file); if (ap = annot->aux) len = (*ap < AUXLEN) ? *ap : AUXLEN; else len = 0; for (i = 0, ap++; i < len; i++, ap++) - (void)wfdb_putc(*ap, oaf[an]); + (void)wfdb_putc(*ap, oa->file); for ( ; i < AUXLEN; i++) - (void)wfdb_putc('\0', oaf[an]); + (void)wfdb_putc('\0', oa->file); break; } - if (wfdb_ferror(oaf[an])) { - wfdb_error("putann: write error on annotation file %d\n",an); + if (wfdb_ferror(oa->file)) { + wfdb_error("putann: write error on annotation file %s\n", + oa->info.name); return (-1); } - oann[an] = *annot; - oann[an].time = t; + oa->ann = *annot; + oa->ann.time = t; return (0); } @@ -518,23 +594,26 @@ if (t < 0L) t = -t; for (i = 0; i < niaf && stat == 0; i++) { - if (iann[i].time >= t) { /* "rewind" the annotation file */ - ungotten[i].anntyp = 0; /* flush pushback buffer */ - if (wfdb_fseek(iaf[i], 0L, 0) == -1) { + struct iadata *ia; + + ia = iad[i]; + if (ia->ann.time >= t) { /* "rewind" the annotation file */ + ia->pann.anntyp = 0; /* flush pushback buffer */ + if (wfdb_fseek(ia->file, 0L, 0) == -1) { wfdb_error("iannsettime: improper seek\n"); return (-1); } - iann[i].subtyp = iann[i].chan = iann[i].num = ateof[i] = 0; - iann[i].time = iantime[i] = 0L; - iaword[i] = wfdb_g16(iaf[i]); - if (iafinfo[i].stat == WFDB_READ) - while ((iaword[i] & CODE) == SKIP) { - iantime[i] += wfdb_g32(iaf[i]); - iaword[i] = wfdb_g16(iaf[i]); + ia->ann.subtyp = ia->ann.chan = ia->ann.num = ia->ateof = 0; + ia->ann.time = ia->tt = 0L; + ia->word = wfdb_g16(ia->file); + if (ia->info.stat == WFDB_READ) + while ((ia->word & CODE) == SKIP) { + ia->tt += wfdb_g32(ia->file); + ia->word = wfdb_g16(ia->file); } (void)getann(i, &tempann); } - while (iann[i].time < t && (stat = getann(i, &tempann)) == 0) + while (ia->ann.time < t && (stat = getann(i, &tempann)) == 0) ; } return (stat); @@ -726,69 +805,56 @@ } } -FVOID iannclose(an) /* close input annotation file 'an' */ -WFDB_Annotator an; +FVOID iannclose(n) /* close input annotation file n */ +WFDB_Annotator n; { - if (an < WFDB_MAXANN && iaf[an] != NULL) { - (void)wfdb_fclose(iaf[an]); - (void)free(iafinfo[an].name); - while (an < niaf-1) { - iaf[an] = iaf[an+1]; - iafinfo[an] = iafinfo[an+1]; - iann[an] = iann[an+1]; - iaword[an] = iaword[an+1]; - ateof[an] = ateof[an+1]; - iantime[an] = iantime[an+1]; - ungotten[an] = ungotten[an+1]; - an++; - } - iaf[an] = NULL; - ungotten[an].anntyp = iann[an].subtyp = iann[an].chan = - iann[an].num = ateof[an] = 0; - iantime[an] = 0L; + struct iadata *ia; + + if (n < niaf && (ia = iad[n]) != NULL && ia->file != NULL) { + (void)wfdb_fclose(ia->file); + (void)free(ia->info.name); + (void)free(ia); + while (n < niaf-1) { + iad[n] = iad[n+1]; + n++; + } + iad[n] = NULL; niaf--; + maxiann--; } } -FVOID oannclose(an) /* close output annotation file 'an' */ -WFDB_Annotator an; +FVOID oannclose(n) /* close output annotation file n */ +WFDB_Annotator n; { int i; char cmdbuf[256]; + struct oadata *oa; - if (an < WFDB_MAXANN && oaf[an] != NULL) { - switch (oafinfo[an].stat) { - case WFDB_WRITE: /* write logical EOF for MIT-format files */ - wfdb_p16(0, oaf[an]); + if (n < noaf && (oa = oad[n]) != NULL && oa->file != NULL) { + switch (oa->info.stat) { + case WFDB_WRITE: /* write logical EOF for MIT-format files */ + wfdb_p16(0, oa->file); break; - case WFDB_AHA_WRITE: /* write logical EOF for AHA-format files */ - i = ABLKSIZ - (unsigned)(wfdb_ftell(oaf[an])) % ABLKSIZ; + case WFDB_AHA_WRITE: /* write logical EOF for AHA-format files */ + i = ABLKSIZ - (unsigned)(wfdb_ftell(oa->file)) % ABLKSIZ; while (i-- > 0) - (void)wfdb_putc(EOAF, oaf[an]); + (void)wfdb_putc(EOAF, oa->file); break; } - (void)wfdb_fclose(oaf[an]); - while (an < noaf-1) { - oaf[an] = oaf[an+1]; - oafinfo[an] = oafinfo[an+1]; - oann[an] = oann[an+1]; - oanum[an] = oanum[an+1]; - an++; - } - oaf[an] = NULL; - oann[an].subtyp = oann[an].chan = oann[an].num = oanum[an] = 0; - oann[an].time = 0L; - if (out_of_order[an]) { + (void)wfdb_fclose(oa->file); + if (oa->out_of_order) { (void)sprintf(cmdbuf, "sortann -r %s -a %s", - oarec[an], oafinfo[an].name); + oa->rname, oa->info.name); #ifndef WFDBNOSORT if (getenv("WFDBNOSORT") == NULL) { if (system(NULL) != 0) { wfdb_error( - "Rearranging annotations for output annotator %d ...", an); + "Rearranging annotations for output annotator %s ...", + oa->info.name); if (system(cmdbuf) == 0) { wfdb_error("done!"); - out_of_order[an] = 0; + oa->out_of_order = 0; } else wfdb_error( @@ -796,13 +862,20 @@ } } } - if (out_of_order[an]) { + if (oa->out_of_order) { #endif wfdb_error("Use the command:\n %s\n", cmdbuf); wfdb_error("to rearrange annotations in the correct order.\n"); } - (void)free(oafinfo[an].name); + (void)free(oa->info.name); + (void)free(oa); + while (n < noaf-1) { + oad[n] = oad[n+1]; + n++; + } + oad[n] = NULL; noaf--; + maxoann--; } } @@ -813,7 +886,7 @@ unsigned int i; for (i = 0; i < noaf; i++) - (void)wfdb_fflush(oaf[i]); + (void)wfdb_fflush(oad[i]->file); } void wfdb_anclose() diff -Naur wfdb-10.1.6/lib/signal.c wfdb-10.2.0/lib/signal.c --- wfdb-10.1.6/lib/signal.c Tue Jul 17 11:09:21 2001 +++ wfdb-10.2.0/lib/signal.c Sun Oct 14 18:38:40 2001 @@ -1,10 +1,10 @@ /* file: signal.c G. Moody 13 April 1989 - Last revised: 17 July 2001 wfdblib 10.1.6 + Last revised: 14 October 2001 wfdblib 10.2.0 WFDB library functions for signals _______________________________________________________________________________ wfdb: a library for reading and writing annotated waveforms (time series data) -Copyright (C) 2000 George B. Moody +Copyright (C) 2001 George B. Moody This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free @@ -27,8 +27,14 @@ This file contains definitions of the following functions, which are not visible outside of this file: + allocisig (sets max number of simultaneously open input signals) + allocigroup (sets max number of simultaneously open input signal groups) + allocosig (sets max number of simultaneously open output signals) + allocogroup (sets max number of simultaneously open output signal groups) isfmt (checks if argument is a legal signal format type) + copysi (deep-copies a WFDB_Siginfo structure) readheader (reads a header file) + hsdfree (deallocates memory used by readheader) isigclose (closes input signals) osigclose (closes output signals) isgsetframe (skips to a specified frame number in a specified signal group) @@ -112,8 +118,43 @@ the same frequency) are supported by version 9.0 and later versions. Multi- segment records (constructed by concatenating single-segment records) and null (format 0) signals are supported by version 9.1 and later versions. + +Beginning with version 10.2, there are no longer any fixed limits on the +number of signals in a record or the number of samples per signal per frame. +Older applications used the symbols WFDB_MAXSIG and WFDB_MAXSPF (which are +still defined in wfdb.h for compatibility) to determine the sizes needed for +arrays of WFDB_Siginfo structures passed into, e.g., isiginfo, and the lengths +of arrays of WFDB_Samples passed into getvec and getframe. Newly-written +applications should use the methods illustrated immediately below instead. */ +#if 0 +/* This is sample code to show how to allocate signal information and sample + vector arrays in an application -- it is *not* compiled into this module! */ +example() +{ + int n, nsig, i, framelen; + WFDB_Siginfo *si; + WFDB_Sample *vector; + + /* Get the number of signals without opening any signal files. */ + n = isigopen("record", NULL, 0); + if (n < 1) { /* no signals -- quit or try another record, etc. */ } + + /* Allocate WFDB_Siginfo structures before calling isigopen again. */ + si = calloc(n, sizeof(WFDB_Siginfo)); + nsig = isigopen("record", si, n); + /* Note that nsig equals n only if all signals were readable. */ + + /* Get the number of samples per frame. */ + for (i = framelen = 0; i < nsig; i++) + framelen += si[i].spf; + /* Allocate WFDB_Samples before calling getframe. */ + vector = calloc(framelen, sizeof(WFDB_Sample)); + getframe(vector); +} +#endif + #include "wfdblib.h" #ifdef iAPX286 @@ -125,46 +166,30 @@ #endif /* Shared local data */ -static unsigned ispfmax; /* max number of samples of any open signal - per input frame */ -static unsigned nisig; /* number of open input signals */ -static WFDB_Time istime; /* time of next input sample */ -static int ibsize; /* default input buffer size */ -static char *isbuf[WFDB_MAXSIG];/* pointers to input buffers */ -static char *isbp[WFDB_MAXSIG]; /* pointers to next locations in isbuf[] */ -static char *isbe[WFDB_MAXSIG]; /* pointers to input buffer endpoints */ -static WFDB_Sample ivec[WFDB_MAXSIG]; /* most recent samples read */ -static char icount[WFDB_MAXSIG];/* input counters for bit-packed signals */ -static WFDB_FILE *isf[WFDB_MAXSIG]; /* file pointers for open input signals */ -static WFDB_Siginfo isinfo[WFDB_MAXSIG]; /* input signal information */ -static char iseek[WFDB_MAXSIG]; /* flags to indicate if seeks are permitted */ -static int istat[WFDB_MAXSIG]; /* signal file status flags */ -static long istart[WFDB_MAXSIG];/* signal file byte offsets to sample 0 */ -static long ostart[WFDB_MAXSIG];/* byte offsets to be written by setheader() */ -static int iskew[WFDB_MAXSIG]; /* intersignal skew (in frames) */ -static int oskew[WFDB_MAXSIG]; /* skews to be written by setheader() */ -static unsigned skewmax; /* max skew (frames) between any 2 signals */ -static WFDB_Sample *dsbuf; /* deskewing buffer */ -static int dsbi; /* index to oldest sample in dsbuf (if < 0, - dsbuf does not contain valid data) */ -static unsigned dsblen; /* capacity of dsbuf, in samples */ -static unsigned framelen; /* total number of samples per frame */ -static int gvmode = WFDB_LOWRES;/* getvec mode (WFDB_HIGHRES or WFDB_LOWRES) */ -static int gvc; /* getvec sample-within-frame counter */ -static unsigned nosig; /* number of open output signals */ -static WFDB_Time ostime; /* time of next output sample */ -static int obsize; /* default output buffer size */ -static char *osbuf[WFDB_MAXSIG];/* pointers to output buffers */ -static char *osbp[WFDB_MAXSIG]; /* pointers to next locations in osbuf[]; */ -static char *osbe[WFDB_MAXSIG]; /* pointers to output buffer endpoints */ -static WFDB_Sample ovec[WFDB_MAXSIG]; /* most recent samples written */ -static char ocount[WFDB_MAXSIG];/* output counters for bit-packed signals */ -static WFDB_FILE *osf[WFDB_MAXSIG]; /* file pointers for open output signals */ -static WFDB_Siginfo osinfo[WFDB_MAXSIG]; /* output signal information */ - -static WFDB_FILE *iheader; /* file pointer for input header file */ -static WFDB_FILE *oheader; /* file pointer for output header file */ +/* These variables are set by readheader, and contain information about the + signals described in the most recently opened header file. +*/ +static unsigned maxhsig; /* # of hsdata structures pointed to by hsd */ +static WFDB_FILE *hheader; /* file pointer for header file */ +static struct hsdata { + WFDB_Siginfo info; /* info about signal from header */ + long start; /* signal file byte offset to sample 0 */ + int skew; /* intersignal skew (in frames) */ +} **hsd; + +/* Variables in this group are also set by readheader, but may be reset (by, + e.g., setsampfreq, setbasetime, ...). These are used by strtim, timstr, + etc., for converting among sample intervals, counter values, elapsed times, + and absolute times and dates; they are recorded when writing header files + using newheader, setheader, and setmsheader. Changing these variables has + no effect on the data read by getframe (or getvec) or on the data written by + putvec (although changes will affect what is written to output header files + by setheader, etc.). An application such as xform can use independent + sampling frequencies and different base times or dates for input and output + signals, but only one set of these parameters is available at any given time + for use by the strtim, timstr, etc., conversion functions. +*/ static WFDB_Frequency ffreq; /* frame rate (frames/second) */ static WFDB_Frequency sfreq; /* sampling frequency (samples/second) */ static WFDB_Frequency cfreq; /* counter frequency (ticks/second) */ @@ -172,13 +197,31 @@ static WFDB_Date bdate; /* base date (Julian date) */ static WFDB_Time nsamples; /* duration of signals (in samples) */ static double bcount; /* base count (counter value at sample 0) */ -static WFDB_Siginfo tsinfo[WFDB_MAXSIG]; /* WFDB_Siginfos for temporary use */ -static long tstart[WFDB_MAXSIG];/* signal file byte offsets to sample 0 */ +/* The next set of variables contains information about multi-segment records. + The first two of them ('segments' and 'in_msrec') are used primarily as + flags to indicate if a record contains multiple segments. Unless 'in_msrec' + is set already, readheader sets 'segments' to the number of segments + indicated in the header file it has most recently read (0 for a + single-segment record). If it reads a header file for a multi-segment + record, readheader also sets the variables 'msbtime', 'msbdate', and + 'msnsamples'; allocates and fills 'segarray'; and sets 'segp' and 'segend'. + Note that readheader's actions are not restricted to records opened for + input. + + If isigopen finds that 'segments' is non-zero, it sets 'in_msrec' and then + invokes readheader again to obtain signal information from the header file + for the first segment, which must be a single-segment record (readheader + refuses to open a header file for a multi-segment record if 'in_msrec' is + set). + + When creating a header file for a multi-segment record using setmsheader, + the variables 'msbtime', 'msbdate', and 'msnsamples' are filled in by + setmsheader based on btime and bdate for the first segment, and on the + sum of the 'nsamp' fields for all segments. */ +static int segments; /* number of segments found by readheader() */ static int in_msrec; /* current input record is: 0: a single-segment record; 1: a multi-segment record */ -static int segments; /* number of segments in current multi-segment - input record (0: single-segment record) */ static WFDB_Time msbtime; /* base time for multi-segment record */ static WFDB_Date msbdate; /* base date for multi-segment record */ static WFDB_Time msnsamples; /* duration of multi-segment record */ @@ -188,8 +231,182 @@ WFDB_Time samp0; /* sample number of first sample in segment */ } *segarray, *segp, *segend; /* beginning, current segment, end pointers */ +/* These variables relate to open input signals. */ +static unsigned maxisig; /* max number of input signals */ +static unsigned maxigroup; /* max number of input signal groups */ +static unsigned nisig; /* number of open input signals */ +static unsigned nigroups; /* number of open input signal groups */ +static unsigned maxspf; /* max allowed value for ispfmax */ +static unsigned ispfmax; /* max number of samples of any open signal + per input frame */ +static struct isdata { /* unique for each input signal */ + WFDB_Siginfo info; /* input signal information */ + WFDB_Sample samp; /* most recent sample read */ + int skew; /* intersignal skew (in frames) */ +} **isd; +static struct igdata { /* shared by all signals in a group (file) */ + int data; /* raw data read by r*() */ + int datb; /* more raw data used for bit-packed formats */ + WFDB_FILE *fp; /* file pointer for an input signal group */ + long start; /* signal file byte offset to sample 0 */ + int bsize; /* if non-zero, all reads from the input file + are in multiples of bsize bytes */ + char *buf; /* pointer to input buffer */ + char *bp; /* pointer to next location in buf[] */ + char *be; /* pointer to input buffer endpoint */ + char count; /* input counter for bit-packed signal */ + char seek; /* flag to indicate if seeks are permitted */ + int stat; /* signal file status flag */ +} **igd; +static WFDB_Sample *tvector; /* getvec workspace */ +static WFDB_Sample *uvector; /* isgsettime workspace */ +static WFDB_Time istime; /* time of next input sample */ +static int ibsize; /* default input buffer size */ +static unsigned skewmax; /* max skew (frames) between any 2 signals */ +static WFDB_Sample *dsbuf; /* deskewing buffer */ +static int dsbi; /* index to oldest sample in dsbuf (if < 0, + dsbuf does not contain valid data) */ +static unsigned dsblen; /* capacity of dsbuf, in samples */ +static unsigned framelen; /* total number of samples per frame */ +static int gvmode = WFDB_LOWRES;/* getvec mode (WFDB_HIGHRES or WFDB_LOWRES) */ +static int gvc; /* getvec sample-within-frame counter */ + +/* These variables relate to output signals. */ +static unsigned maxosig; /* max number of output signals */ +static unsigned maxogroup; /* max number of output signal groups */ +static unsigned nosig; /* number of open output signals */ +static unsigned nogroups; /* number of open output signal groups */ +static WFDB_FILE *oheader; /* file pointer for output header file */ +static struct osdata { /* unique for each output signal */ + WFDB_Siginfo info; /* output signal information */ + WFDB_Sample samp; /* most recent sample written */ + int skew; /* skew to be written by setheader() */ +} **osd; +static struct ogdata { /* shared by all signals in a group (file) */ + int data; /* raw data to be written by w*() */ + int datb; /* more raw data used for bit-packed formats */ + WFDB_FILE *fp; /* file pointer for output signal */ + long start; /* byte offset to be written by setheader() */ + int bsize; /* if non-zero, all writes to the output file + are in multiples of bsize bytes */ + char *buf; /* pointer to output buffer */ + char *bp; /* pointer to next location in buf[]; */ + char *be; /* pointer to output buffer endpoint */ + char count; /* output counter for bit-packed signal */ +} **ogd; +static WFDB_Time ostime; /* time of next output sample */ +static int obsize; /* default output buffer size */ + /* Local functions (not accessible outside this file). */ +/* Allocate workspace for up to n input signals. */ +static int allocisig(n) +unsigned n; +{ + if (maxisig < n) { + unsigned m = maxisig; + struct isdata **isdnew = realloc(isd, n*sizeof(struct isdata *)); + + if (isdnew == NULL) { + wfdb_error("init: too many (%d) input signals\n", n); + return (-1); + } + isd = isdnew; + while (m < n) { + if ((isd[m] = calloc(1, sizeof(struct isdata))) == NULL) { + wfdb_error("init: too many (%d) input signals\n", n); + while (--m > maxisig) + free(isd[m]); + return (-1); + } + m++; + } + maxisig = n; + } + return (maxisig); +} + +/* Allocate workspace for up to n input signal groups. */ +static int allocigroup(n) +unsigned n; +{ + if (maxigroup < n) { + unsigned m = maxigroup; + struct igdata **igdnew = realloc(igd, n*sizeof(struct igdata *)); + + if (igdnew == NULL) { + wfdb_error("init: too many (%d) input signal groups\n", n); + return (-1); + } + igd = igdnew; + while (m < n) { + if ((igd[m] = calloc(1, sizeof(struct igdata))) == NULL) { + wfdb_error("init: too many (%d) input signal groups\n", n); + while (--m > maxigroup) + free(igd[m]); + return (-1); + } + m++; + } + maxigroup = n; + } + return (maxigroup); +} + +/* Allocate workspace for up to n output signals. */ +static int allocosig(n) +unsigned n; +{ + if (maxosig < n) { + unsigned m = maxosig; + struct osdata **osdnew = realloc(osd, n*sizeof(struct osdata *)); + + if (osdnew == NULL) { + wfdb_error("init: too many (%d) output signals\n", n); + return (-1); + } + osd = osdnew; + while (m < n) { + if ((osd[m] = calloc(1, sizeof(struct osdata))) == NULL) { + wfdb_error("init: too many (%d) output signals\n", n); + while (--m > maxosig) + free(osd[m]); + return (-1); + } + m++; + } + maxosig = n; + } + return (maxosig); +} + +/* Allocate workspace for up to n output signal groups. */ +static int allocogroup(n) +unsigned n; +{ + if (maxogroup < n) { + unsigned m = maxogroup; + struct ogdata **ogdnew = realloc(ogd, n*sizeof(struct ogdata *)); + + if (ogdnew == NULL) { + wfdb_error("init: too many (%d) output signal groups\n", n); + return (-1); + } + ogd = ogdnew; + while (m < n) { + if ((ogd[m] = calloc(1, sizeof(struct ogdata))) == NULL) { + wfdb_error("init: too many (%d) output signal groups\n", n); + while (--m > maxogroup) + free(ogd[m]); + return (-1); + } + m++; + } + maxogroup = n; + } + return (maxogroup); +} + static int isfmt(f) int f; { @@ -201,9 +418,41 @@ return (0); } -static int readheader(record, siarray) +static int copysi(to, from) +WFDB_Siginfo *to, *from; +{ + if (to == NULL || from == NULL) return (0); + *to = *from; + /* The next line works around an optimizer bug in gcc (version 2.96, maybe + others). */ + to->fname = to->desc = to->units = NULL; + if (from->fname) { + to->fname = (char *)malloc((size_t)strlen(from->fname)+1); + if (to->fname == NULL) return (-1); + (void)strcpy(to->fname, from->fname); + } + if (from->desc) { + to->desc = (char *)malloc((size_t)strlen(from->desc)+1); + if (to->desc == NULL) { + (void)free(to->fname); + return (-1); + } + (void)strcpy(to->desc, from->desc); + } + if (from->units) { + to->units = (char *)malloc((size_t)strlen(from->units)+1); + if (to->units == NULL) { + (void)free(to->desc); + (void)free(to->fname); + return (-1); + } + (void)strcpy(to->units, from->units); + } + return (1); +} + +static int readheader(record) char *record; -WFDB_Siginfo *siarray; { char linebuf[256], *p, *q; WFDB_Frequency f; @@ -213,10 +462,10 @@ static char sep[] = " \t\n\r"; /* If another input header file was opened, close it. */ - if (iheader) (void)wfdb_fclose(iheader); + if (hheader) (void)wfdb_fclose(hheader); /* Try to open the header file. */ - if ((iheader = wfdb_open("header", record, WFDB_READ)) == NULL) { + if ((hheader = wfdb_open("hea", record, WFDB_READ)) == NULL) { wfdb_error("init: can't open header for record %s\n", record); return (-1); } @@ -224,7 +473,7 @@ /* Get the first token (the record name) from the first non-empty, non-comment line. */ do { - if (wfdb_fgets(linebuf, 256, iheader) == NULL) { + if (wfdb_fgets(linebuf, 256, hheader) == NULL) { wfdb_error("init: can't find record name in record %s header\n", record); return (-2); @@ -248,8 +497,8 @@ if not, the header file may have been renamed in error or its contents may be corrupted. The requirement for a match is waived for remote files since the user may not be able to make any corrections to them. */ - if (iheader->type == WFDB_LOCAL && - iheader->fp != stdin && strcmp(p, record) != 0) { + if (hheader->type == WFDB_LOCAL && + hheader->fp != stdin && strcmp(p, record) != 0) { /* If there is a mismatch, check to see if the record argument includes a directory separator (whether valid or not for this OS); if so, compare only the final portion of the argument against the name in @@ -271,483 +520,516 @@ another token from the line which contains the record name. (Old-style headers have only one token on the first line, but new-style headers have two or more.) */ - if (p = strtok((char *)NULL, sep)) { + if ((p = strtok((char *)NULL, sep)) == NULL) { + /* The file appears to be an old-style header file. */ + wfdb_error("init: obsolete format in record %s header\n", record); + return (-2); + } + + /* The file appears to be a new-style header file. The second token + specifies the number of signals. */ + nsig = (unsigned)atoi(p); - /* The file appears to be a new-style header file. - The second token specifies the number of signals. */ - if ((nsig = (unsigned)atoi(p)) > WFDB_MAXSIG) { + /* Determine the frame rate, if present and not set already. */ + if (p = strtok((char *)NULL, sep)) { + if ((f = (WFDB_Frequency)atof(p)) <= (WFDB_Frequency)0.) { wfdb_error( - "init: number of signals in record %s header is incorrect\n", - record); + "init: sampling frequency in record %s header is incorrect\n", + record); return (-2); } - - /* Determine the frame rate, if present and not set already. */ - if (p = strtok((char *)NULL, sep)) { - if ((f = (WFDB_Frequency)atof(p)) <= (WFDB_Frequency)0.) { - wfdb_error( - "init: sampling frequency in record %s header is incorrect\n", - record); - return (-2); - } - if (ffreq > (WFDB_Frequency)0. && f != ffreq) { - wfdb_error("warning (init):\n"); - wfdb_error(" record %s sampling frequency differs", record); - wfdb_error(" from that of previously opened record\n"); - } - else - ffreq = f; + if (ffreq > (WFDB_Frequency)0. && f != ffreq) { + wfdb_error("warning (init):\n"); + wfdb_error(" record %s sampling frequency differs", record); + wfdb_error(" from that of previously opened record\n"); } - else if (ffreq == (WFDB_Frequency)0.) - ffreq = WFDB_DEFFREQ; - - /* Set the sampling rate to the frame rate for now. This may be - changed later by isigopen or by setgvmode, if this is a multi- - frequency record and WFDB_HIGHRES mode is in effect. */ - sfreq = ffreq; + else + ffreq = f; + } + else if (ffreq == (WFDB_Frequency)0.) + ffreq = WFDB_DEFFREQ; - /* Determine the counter frequency and the base counter value. */ - cfreq = bcount = 0.0; - if (p) { - for ( ; *p && *p != '/'; p++) + /* Set the sampling rate to the frame rate for now. This may be + changed later by isigopen or by setgvmode, if this is a multi- + frequency record and WFDB_HIGHRES mode is in effect. */ + sfreq = ffreq; + + /* Determine the counter frequency and the base counter value. */ + cfreq = bcount = 0.0; + if (p) { + for ( ; *p && *p != '/'; p++) + ; + if (*p == '/') { + cfreq = atof(++p); + for ( ; *p && *p != '('; p++) ; - if (*p == '/') { - cfreq = atof(++p); - for ( ; *p && *p != '('; p++) - ; - if (*p == '(') - bcount = atof(++p); - } + if (*p == '(') + bcount = atof(++p); } - if (cfreq <= 0.0) cfreq = ffreq; + } + if (cfreq <= 0.0) cfreq = ffreq; - /* Determine the number of samples per signal, if present and not - set already. */ - if (p = strtok((char *)NULL, sep)) { - if ((ns = (WFDB_Time)atol(p)) < 0L) { - wfdb_error( + /* Determine the number of samples per signal, if present and not + set already. */ + if (p = strtok((char *)NULL, sep)) { + if ((ns = (WFDB_Time)atol(p)) < 0L) { + wfdb_error( "init: number of samples in record %s header is incorrect\n", - record); - return (-2); - } - if (nsamples == (WFDB_Time)0L) + record); + return (-2); + } + if (nsamples == (WFDB_Time)0L) + nsamples = ns; + else if (ns > (WFDB_Time)0L && ns != nsamples && !in_msrec) { + wfdb_error("warning (init):\n"); + wfdb_error(" record %s duration differs", record); + wfdb_error(" from that of previously opened record\n"); + /* nsamples must match the shortest record duration. */ + if (nsamples > ns) nsamples = ns; - else if (ns > (WFDB_Time)0L && ns != nsamples && !in_msrec) { - wfdb_error("warning (init):\n"); - wfdb_error(" record %s duration differs", record); - wfdb_error(" from that of previously opened record\n"); - /* nsamples must match the shortest record duration. */ - if (nsamples > ns) - nsamples = ns; - } } - else - ns = (WFDB_Time)0L; - - /* Determine the base time and date, if present and not set already. */ - if ((p = strtok((char *)NULL,"\n\r")) != NULL && - btime == (WFDB_Time)0L && setbasetime(p) < 0) - return (-2); /* error message will come from setbasetime */ + } + else + ns = (WFDB_Time)0L; - /* Special processing for master header of a multi-segment record. */ - if (segments && !in_msrec) { - msbtime = btime; - msbdate = bdate; - msnsamples = nsamples; - /* Read the names and lengths of the segment records. */ -#ifndef lint - segarray = (struct segrec *) - malloc((unsigned)(sizeof(struct segrec) * segments)); -#endif - if (segarray == (struct segrec *)NULL) { - wfdb_error("init: insufficient memory\n"); - segments = 0; - return (-2); - } - segp = segarray; - for (i = 0, ns = (WFDB_Time)0L; i < segments; i++, segp++) { - /* Get next segment spec, skip empty lines and comments. */ - do { - if (wfdb_fgets(linebuf, 256, iheader) == NULL) { - wfdb_error( - "init: unexpected EOF in header file for record %s\n", - record); -#ifndef lint - (void)free(segarray); -#endif - segarray = (struct segrec *)NULL; - segments = 0; - return (-2); - } - } while ((p = strtok(linebuf, sep)) == NULL || *p == '#'); - if (strlen(p) > WFDB_MAXRNL) { + /* Determine the base time and date, if present and not set already. */ + if ((p = strtok((char *)NULL,"\n\r")) != NULL && + btime == (WFDB_Time)0L && setbasetime(p) < 0) + return (-2); /* error message will come from setbasetime */ + + /* Special processing for master header of a multi-segment record. */ + if (segments && !in_msrec) { + msbtime = btime; + msbdate = bdate; + msnsamples = nsamples; + /* Read the names and lengths of the segment records. */ + segarray = (struct segrec *)calloc(segments, sizeof(struct segrec)); + if (segarray == (struct segrec *)NULL) { + wfdb_error("init: insufficient memory\n"); + segments = 0; + return (-2); + } + segp = segarray; + for (i = 0, ns = (WFDB_Time)0L; i < segments; i++, segp++) { + /* Get next segment spec, skip empty lines and comments. */ + do { + if (wfdb_fgets(linebuf, 256, hheader) == NULL) { wfdb_error( - "init: `%s' is too long for a segment name in record %s\n", - p, record); -#ifndef lint + "init: unexpected EOF in header file for record %s\n", + record); (void)free(segarray); -#endif segarray = (struct segrec *)NULL; segments = 0; return (-2); } - (void)strcpy(segp->recname, p); - if ((p = strtok((char *)NULL, sep)) == NULL || - (segp->nsamp = (WFDB_Time)atol(p)) <= 0L) { - wfdb_error( + } while ((p = strtok(linebuf, sep)) == NULL || *p == '#'); + if (strlen(p) > WFDB_MAXRNL) { + wfdb_error( + "init: `%s' is too long for a segment name in record %s\n", + p, record); + (void)free(segarray); + segarray = (struct segrec *)NULL; + segments = 0; + return (-2); + } + (void)strcpy(segp->recname, p); + if ((p = strtok((char *)NULL, sep)) == NULL || + (segp->nsamp = (WFDB_Time)atol(p)) <= 0L) { + wfdb_error( "init: length must be specified for segment %s in record %s\n", - segp->recname, record); -#ifndef lint - (void)free(segarray); -#endif - segarray = (struct segrec *)NULL; - segments = 0; - return (-2); - } - segp->samp0 = ns; - ns += segp->nsamp; + segp->recname, record); + (void)free(segarray); + segarray = (struct segrec *)NULL; + segments = 0; + return (-2); } - segend = --segp; - segp = segarray; - if (msnsamples == 0L) - msnsamples = ns; - else if (ns != msnsamples) { - wfdb_error("warning (init): sum of segment lengths (%ld)\n", ns); - wfdb_error(" does not match stated record length (%ld)\n", - msnsamples); + segp->samp0 = ns; + ns += segp->nsamp; + } + segend = --segp; + segp = segarray; + if (msnsamples == 0L) + msnsamples = ns; + else if (ns != msnsamples) { + wfdb_error("warning (init): sum of segment lengths (%ld)\n", ns); + wfdb_error(" does not match stated record length (%ld)\n", + msnsamples); + } + return (0); + } + + /* Allocate workspace. */ + if (maxhsig < nsig) { + unsigned m = maxhsig; + struct hsdata **hsdnew = realloc(hsd, nsig*sizeof(struct hsdata *)); + + if (hsdnew == NULL) { + wfdb_error("init: too many (%d) signals in header file\n", nsig); + return (-2); + } + hsd = hsdnew; + while (m < nsig) { + if ((hsd[m] = calloc(1, sizeof(struct hsdata))) == NULL) { + wfdb_error("init: too many (%d) signals in header file\n", + nsig); + while (--m > maxhsig) + free(hsd[m]); + return (-2); } - return (0); + m++; } + maxhsig = nsig; + } - /* Now get information for each signal. */ - for (s = 0; s < nsig; s++) { - int nobaseline; + /* Now get information for each signal. */ + for (s = 0; s < nsig; s++) { + struct hsdata *hp, *hs; + int nobaseline; - /* Get the first token (the signal file name) from the next - non-empty, non-comment line. */ - do { - if (wfdb_fgets(linebuf, 256, iheader) == NULL) { - wfdb_error( + hs = hsd[s]; + if (s) hp = hsd[s-1]; + /* Get the first token (the signal file name) from the next + non-empty, non-comment line. */ + do { + if (wfdb_fgets(linebuf, 256, hheader) == NULL) { + wfdb_error( "init: unexpected EOF in header file for record %s\n", - record); - return (-2); - } - } while ((p = strtok(linebuf, sep)) == NULL || *p == '#'); + record); + return (-2); + } + } while ((p = strtok(linebuf, sep)) == NULL || *p == '#'); - /* Determine the signal group number. The group number for signal - 0 is zero. For subsequent signals, if the file name does not - match that of the previous signal, the group number is one - greater than that of the previous signal. */ - if (s == 0 || strcmp(p, siarray[s-1].fname)) { - siarray[s].group = (s == 0) ? 0 : siarray[s-1].group + 1; - if ((siarray[s].fname = - (char *)malloc((unsigned)(strlen(p)+1))) + /* Determine the signal group number. The group number for signal + 0 is zero. For subsequent signals, if the file name does not + match that of the previous signal, the group number is one + greater than that of the previous signal. */ + if (s == 0 || strcmp(p, hp->info.fname)) { + hs->info.group = (s == 0) ? 0 : hp->info.group + 1; + if ((hs->info.fname =(char *)malloc((unsigned)(strlen(p)+1))) == NULL) { wfdb_error("init: insufficient memory\n"); return (-2); } - (void)strcpy(siarray[s].fname, p); - } - /* If the file names of the current and previous signals match, - they are assigned the same group number and share a copy of the - file name. All signals associated with a given file must be - listed together in the header in order to be identified as - belonging to the same group; readheader does not check that - this has been done. */ - else { - siarray[s].group = siarray[s-1].group; - siarray[s].fname = siarray[s-1].fname; - } - - /* Determine the signal format. */ - if ((p = strtok((char *)NULL, sep)) == NULL || - !isfmt(siarray[s].fmt = atoi(p))) { - wfdb_error("init: illegal format for signal %d, record %s\n", - s, record); - return (-2); - } - siarray[s].spf = 1; - iskew[s] = 0; - tstart[s] = 0L; - while (*(++p)) { - if (*p == 'x' && *(++p)) - if ((siarray[s].spf = atoi(p)) < 1) siarray[s].spf = 1; - if (*p == ':' && *(++p)) - if ((iskew[s] = atoi(p)) < 0) iskew[s] = 0; - if (*p == '+' && *(++p)) - if ((tstart[s] = atol(p)) < 0L) tstart[s] = 0L; - } - /* The resolution for deskewing is one frame. The skew in samples - (given in the header) is converted to skew in frames here. */ - iskew[s] = (int)(((double)iskew[s])/siarray[s].spf + 0.5); - - /* Determine the gain in ADC units per physical unit. This number - may be zero or missing; if so, the signal is uncalibrated. */ - if (p = strtok((char *)NULL, sep)) - siarray[s].gain = (WFDB_Gain)atof(p); - else - siarray[s].gain = (WFDB_Gain)0.; - - /* Determine the baseline if specified, and the physical units - (assumed to be millivolts unless otherwise specified). */ - nobaseline = 1; - if (p) { - for ( ; *p && *p != '(' && *p != '/'; p++) - ; - if (*p == '(') { - siarray[s].baseline = atoi(++p); - nobaseline = 0; - } - while (*p) - if (*p++ == '/' && *p) - break; - } - if (p && *p) { - if ((siarray[s].units=(char *)malloc(WFDB_MAXUSL+1)) == NULL) { + (void)strcpy(hs->info.fname, p); + } + /* If the file names of the current and previous signals match, + they are assigned the same group number and share a copy of the + file name. All signals associated with a given file must be + listed together in the header in order to be identified as + belonging to the same group; readheader does not check that + this has been done. */ + else { + hs->info.group = hp->info.group; + if ((hs->info.fname = (char *)malloc(strlen(hp->info.fname)+1)) + == NULL) { wfdb_error("init: insufficient memory\n"); return (-2); } - (void)strncpy(siarray[s].units, p, WFDB_MAXUSL); - } - else - siarray[s].units = NULL; + (void)strcpy(hs->info.fname, hp->info.fname); + } - /* Determine the ADC resolution in bits. If this number is - missing and cannot be inferred from the format, the default - value (from wfdb.h) is filled in. */ - if (p = strtok((char *)NULL, sep)) - i = (unsigned)atoi(p); - else switch (siarray[s].fmt) { - case 80: i = 8; break; - case 160: i = 16; break; - case 212: i = 12; break; - case 310: i = 10; break; - case 311: i = 10; break; - default: i = WFDB_DEFRES; break; + /* Determine the signal format. */ + if ((p = strtok((char *)NULL, sep)) == NULL || + !isfmt(hs->info.fmt = atoi(p))) { + wfdb_error("init: illegal format for signal %d, record %s\n", + s, record); + return (-2); + } + hs->info.spf = 1; + hs->skew = 0; + hs->start = 0L; + while (*(++p)) { + if (*p == 'x' && *(++p)) + if ((hs->info.spf = atoi(p)) < 1) hs->info.spf = 1; + if (*p == ':' && *(++p)) + if ((hs->skew = atoi(p)) < 0) hs->skew = 0; + if (*p == '+' && *(++p)) + if ((hs->start = atol(p)) < 0L) hs->start = 0L; + } + /* The resolution for deskewing is one frame. The skew in samples + (given in the header) is converted to skew in frames here. */ + hs->skew = (int)(((double)hs->skew)/hs->info.spf + 0.5); + + /* Determine the gain in ADC units per physical unit. This number + may be zero or missing; if so, the signal is uncalibrated. */ + if (p = strtok((char *)NULL, sep)) + hs->info.gain = (WFDB_Gain)atof(p); + else + hs->info.gain = (WFDB_Gain)0.; + + /* Determine the baseline if specified, and the physical units + (assumed to be millivolts unless otherwise specified). */ + nobaseline = 1; + if (p) { + for ( ; *p && *p != '(' && *p != '/'; p++) + ; + if (*p == '(') { + hs->info.baseline = atoi(++p); + nobaseline = 0; + } + while (*p) + if (*p++ == '/' && *p) + break; + } + if (p && *p) { + if ((hs->info.units=(char *)malloc(WFDB_MAXUSL+1)) == NULL) { + wfdb_error("init: insufficient memory\n"); + return (-2); } - siarray[s].adcres = i; + (void)strncpy(hs->info.units, p, WFDB_MAXUSL); + } + else + hs->info.units = NULL; + + /* Determine the ADC resolution in bits. If this number is + missing and cannot be inferred from the format, the default + value (from wfdb.h) is filled in. */ + if (p = strtok((char *)NULL, sep)) + i = (unsigned)atoi(p); + else switch (hs->info.fmt) { + case 80: i = 8; break; + case 160: i = 16; break; + case 212: i = 12; break; + case 310: i = 10; break; + case 311: i = 10; break; + default: i = WFDB_DEFRES; break; + } + hs->info.adcres = i; - /* Determine the ADC zero (assumed to be zero if missing). */ - siarray[s].adczero = (p = strtok((char *)NULL, sep)) ? atoi(p) : 0; + /* Determine the ADC zero (assumed to be zero if missing). */ + hs->info.adczero = (p = strtok((char *)NULL, sep)) ? atoi(p) : 0; - /* Set the baseline to adczero if no baseline field was found. */ - if (nobaseline) siarray[s].baseline = siarray[s].adczero; + /* Set the baseline to adczero if no baseline field was found. */ + if (nobaseline) hs->info.baseline = hs->info.adczero; - /* Determine the initial value (assumed to be equal to the ADC - zero if missing). */ - siarray[s].initval = (p = strtok((char *)NULL, sep)) ? - atoi(p) : siarray[s].adczero; - - /* Determine the checksum (assumed to be zero if missing). */ - if (p = strtok((char *)NULL, sep)) { - siarray[s].cksum = atoi(p); - siarray[s].nsamp = ns; - } - else { - siarray[s].cksum = 0; - siarray[s].nsamp = (WFDB_Time)0L; - } + /* Determine the initial value (assumed to be equal to the ADC + zero if missing). */ + hs->info.initval = (p = strtok((char *)NULL, sep)) ? + atoi(p) : hs->info.adczero; - /* Determine the block size (assumed to be zero if missing). */ - siarray[s].bsize = (p = strtok((char *)NULL, sep)) ? atoi(p) : 0; + /* Determine the checksum (assumed to be zero if missing). */ + if (p = strtok((char *)NULL, sep)) { + hs->info.cksum = atoi(p); + hs->info.nsamp = ns; + } + else { + hs->info.cksum = 0; + hs->info.nsamp = (WFDB_Time)0L; + } - /* Check that formats and block sizes match for signals belonging - to the same group. */ - if (s && siarray[s].group == siarray[s-1].group && - (siarray[s].fmt != siarray[s-1].fmt || - siarray[s].bsize != siarray[s-1].bsize)) { - wfdb_error("init: error in specification of signal %d or %d\n", - s-1, s); - return (-2); - } + /* Determine the block size (assumed to be zero if missing). */ + hs->info.bsize = (p = strtok((char *)NULL, sep)) ? atoi(p) : 0; + + /* Check that formats and block sizes match for signals belonging + to the same group. */ + if (s && hs->info.group == hp->info.group && + (hs->info.fmt != hp->info.fmt || + hs->info.bsize != hp->info.bsize)) { + wfdb_error("init: error in specification of signal %d or %d\n", + s-1, s); + return (-2); + } - /* Get the signal description. If missing, a description of - the form "record xx, signal n" is filled in. */ - if ((siarray[s].desc = (char *)malloc(WFDB_MAXDSL+1)) == NULL) { - wfdb_error("init: insufficient memory\n"); - return (-2); - } - if (p = strtok((char *)NULL, "\n\r")) - (void)strncpy(siarray[s].desc, p, WFDB_MAXDSL); - else - (void)sprintf(siarray[s].desc, - "record %s, signal %d", record, s); + /* Get the signal description. If missing, a description of + the form "record xx, signal n" is filled in. */ + if ((hs->info.desc = (char *)malloc(WFDB_MAXDSL+1)) == NULL) { + wfdb_error("init: insufficient memory\n"); + return (-2); } + if (p = strtok((char *)NULL, "\n\r")) + (void)strncpy(hs->info.desc, p, WFDB_MAXDSL); + else + (void)sprintf(hs->info.desc, + "record %s, signal %d", record, s); } + return (s); /* return number of available signals */ +} - else { - /* We come here if there were no other tokens on the line which - contained the record name. The file appears to be an old-style - header file. */ - wfdb_error("init: obsolete format in record %s header\n", record); - return (-2); - } +static void hsdfree() +{ + struct hsdata *hs; - return (s); /* return number of available signals */ + while (maxhsig) + if (hs = hsd[--maxhsig]) { + if (hs->info.fname) (void)free(hs->info.fname); + if (hs->info.units) (void)free(hs->info.units); + if (hs->info.desc) (void)free(hs->info.desc); + (void)free(hs); + } + (void)free(hsd); + hsd = NULL; + maxhsig = 0; } static void isigclose() { - while (nisig) { - if (--nisig == 0 || isinfo[nisig].group != isinfo[nisig-1].group) { - (void)wfdb_fclose(isf[nisig]); - isf[nisig] = NULL; - if (isbuf[isinfo[nisig].group]) { -#ifndef lint - (void)free(isbuf[isinfo[nisig].group]); -#endif - isbuf[isinfo[nisig].group] = NULL; - } - if (isinfo[nisig].fname) { -#ifndef lint - (void)free(isinfo[nisig].fname); -#endif - isinfo[nisig].fname = NULL; - } - } - icount[nisig] = 0; - } + struct isdata *is; + struct igdata *ig; + + if (nisig == 0) return; + while (nisig) + if (is = isd[--nisig]) { + if (is->info.fname) (void)free(is->info.fname); + if (is->info.units) (void)free(is->info.units); + if (is->info.desc) (void)free(is->info.desc); + (void)free(is); + } + (void)free(isd); + isd = NULL; + maxisig = 0; + + while (nigroups) + if (ig = igd[--nigroups]) { + if (ig->fp) wfdb_fclose(ig->fp); + if (ig->buf) (void)free(ig->buf); + (void)free(ig); + } + (void)free(igd); + igd = NULL; + maxigroup = 0; + istime = 0L; gvc = ispfmax = 1; - if (iheader) { - (void)wfdb_fclose(iheader); - iheader = NULL; + if (hheader) { + (void)wfdb_fclose(hheader); + hheader = NULL; } + if (nosig == 0 && maxhsig != 0) + hsdfree(); } static void osigclose() { - WFDB_Group g; + struct osdata *os; + struct ogdata *og; - while (nosig) { - if (--nosig == 0 || osinfo[nosig].group != osinfo[nosig-1].group) { - g = osinfo[nosig].group; - /* Null-pad special files only, if anything was written. */ - if (osinfo[nosig].bsize != 0 && ocount[nosig]) - while (osbp[g] != osbe[g]) - *(osbp[g]++) = '\0'; - /* Flush the last block. */ - if (osbp[g] != osbuf[g]) - (void)wfdb_fwrite(osbuf[g], 1, osbp[g]-osbuf[g], osf[nosig]); - /* Don't close standard output (this will be done on exit). */ - if (strcmp(osinfo[nosig].fname, "-")) { - (void)wfdb_fclose(osf[nosig]); - osf[nosig] = NULL; - } -#ifndef lint - (void)free(osbuf[g]); - (void)free(osinfo[nosig].fname); -#endif - osbuf[g] = osinfo[nosig].fname = NULL; - } - if (osinfo[nosig].desc) { -#ifndef lint - (void)free(osinfo[nosig].desc); -#endif - osinfo[nosig].desc = NULL; - } - if (osinfo[nosig].units) { -#ifndef lint - (void)free(osinfo[nosig].units); -#endif - osinfo[nosig].units = NULL; + if (nosig == 0) return; + while (nosig) + if (os = osd[--nosig]) { + if (os->info.fname) (void)free(os->info.fname); + if (os->info.units) (void)free(os->info.units); + if (os->info.desc) (void)free(os->info.desc); + (void)free(os); + } + (void)free(osd); + osd = NULL; + maxosig = 0; + + while (nogroups) + if (og = ogd[--nogroups]) { + if (og->fp) { + /* If a block size has been defined, null-pad the buffer. */ + if (og->bsize) + while (og->bp != og->be) + *(og->bp++) = '\0'; + /* Flush the last block unless it's empty. */ + if (og->bp != og->buf) + (void)wfdb_fwrite(og->buf, 1, og->bp - og->buf, + og->fp); + /* Close file (except stdout, which will be closed on exit). */ + if (og->fp->fp != stdout) { + (void)wfdb_fclose(og->fp); + og->fp = NULL; + } + } + if (og->buf) (void)free(og->buf); + (void)free(og); } - ocount[nosig] = 0; - } + (void)free(ogd); + ogd = NULL; + maxogroup = 0; + ostime = 0L; if (oheader) { (void)wfdb_fclose(oheader); oheader = NULL; } + if (nisig == 0 && maxhsig != 0) + hsdfree(); } /* Low-level I/O routines. The input routines each get a single argument (the -signal number). The output routines get two arguments (the value to be written -and the signal number). */ +signal group pointer). The output routines get two arguments (the value to be +written and the signal group pointer). */ -static WFDB_Group _g; /* macro temporary storage for group number */ static int _l; /* macro temporary storage for low byte of word */ static int _n; /* macro temporary storage for byte count */ -#define r8(S) ((char)(_g = isinfo[S].group, \ - ((isbp[_g] < isbe[_g]) ? *(isbp[_g]++) : \ - ((_n = (isinfo[S].bsize > 0) ? isinfo[S].bsize : ibsize), \ - (istat[_g] = _n = wfdb_fread(isbuf[_g], 1, _n, isf[S])), \ - (isbe[_g] = (isbp[_g] = isbuf[_g]) + _n),\ - *(isbp[_g]++))))) - -#define w8(V,S) (_g = osinfo[S].group, \ - (*(osbp[_g]++) = (char)(V), \ - (_l = ((osbp[_g] != osbe[_g]) ? 0 : \ - ((_n = (osinfo[S].bsize > 0) ? osinfo[S].bsize : obsize), \ - (wfdb_fwrite((osbp[_g] = osbuf[_g]), 1, _n, osf[S]))))))) +#define r8(G) ((G->bp < G->be) ? *(G->bp++) : \ + ((_n = (G->bsize > 0) ? G->bsize : ibsize), \ + (G->stat = _n = wfdb_fread(G->buf, 1, _n, G->fp)), \ + (G->be = (G->bp = G->buf) + _n),\ + *(G->bp++))) + +#define w8(V,G) (((*(G->bp++) = (char)V)), \ + (_l = (G->bp != G->be) ? 0 : \ + ((_n = (G->bsize > 0) ? G->bsize : obsize), \ + wfdb_fwrite((G->bp = G->buf), 1, _n, G->fp)))) /* If a short integer is not 16 bits, it may be necessary to redefine r16() and r61() in order to obtain proper sign extension. */ #ifndef BROKEN_CC -#define r16(S) (_l = r8(S), ((int)((short)((r8(S) << 8) | (_l & 0xff))))) -#define w16(V,S) (w8((V), (S)), w8(((V) >> 8), (S))) -#define r61(S) (_l = r8(S), ((int)((short)((r8(S) & 0xff) | (_l << 8))))) -#define w61(V,S) (w8(((V) >> 8), (S)), w8((V), (S))) +#define r16(G) (_l = r8(G), ((int)((short)((r8(G) << 8) | (_l & 0xff))))) +#define w16(V,G) (w8((V), (G)), w8(((V) >> 8), (G))) +#define r61(G) (_l = r8(G), ((int)((short)((r8(G) & 0xff) | (_l << 8))))) +#define w61(V,G) (w8(((V) >> 8), (G)), w8((V), (G))) #else -static int r16(s) -WFDB_Signal s; +static int r16(g) +struct igdata *g; { int l, h; - l = r8(s); - h = r8(s); + l = r8(g); + h = r8(g); return ((int)((short)((h << 8) | (l & 0xff)))); } -static void w16(v, s) +static void w16(v, g) WFDB_Sample v; -WFDB_Signal s; +struct ogdata *g; { - w8(v, s); - w8((v >> 8), s); + w8(v, g); + w8((v >> 8), g); } -static int r61(s) -WFDB_Signal s; +static int r61(g) +struct igdata *g; { int l, h; - h = r8(s); - l = r8(s); + h = r8(g); + l = r8(g); return ((int)((short)((h << 8) | (l & 0xff)))); } -static void w61(v, s) +static void w61(v, g) WFDB_Sample v; -WFDB_Signal s; +struct ogdata *g; { - w8((v >> 8), s); - w8(v, s); + w8((v >> 8), g); + w8(v, g); } #endif -#define r80(S) ((r8(S) & 0xff) - (1 << 7)) -#define w80(V, S) (w8(((V) & 0xff) + (1 << 7), S)) +#define r80(G) ((r8(G) & 0xff) - (1 << 7)) +#define w80(V, G) (w8(((V) & 0xff) + (1 << 7), G)) -#define r160(S) ((r16(S) & 0xffff) - (1 << 15)) -#define w160(V, S) (w16(((V) & 0xffff) + (1 << 15), S)) +#define r160(G) ((r16(G) & 0xffff) - (1 << 15)) +#define w160(V, G) (w16(((V) & 0xffff) + (1 << 15), G)) -static int r212(s) /* read and return the next sample from a format 212 */ -WFDB_Signal s; /* signal file (2 12-bit samples bit-packed in 3 bytes) */ +static int r212(g) /* read and return the next sample from a format 212 */ +struct igdata *g; /* signal file (2 12-bit samples bit-packed in 3 bytes) */ { - WFDB_Group g = isinfo[s].group; int v; - static int x[WFDB_MAXSIG]; /* Obtain the next 12-bit value right-justified in v. */ - switch (icount[g]++) { - case 0: v = x[g] = r16(s); break; + switch (g->count++) { + case 0: v = g->data = r16(g); break; case 1: - default: icount[g] = 0; - v = ((x[g] >> 4) & 0xf00) | (r8(s) & 0xff); break; + default: g->count = 0; + v = ((g->data >> 4) & 0xf00) | (r8(g) & 0xff); break; } /* Sign-extend from the twelfth bit. */ if (v & 0x800) v |= ~(0xfff); @@ -755,36 +1037,34 @@ return (v); } -static void w212(v, s) /* write the next sample to a format 212 signal file */ +static void w212(v, g) /* write the next sample to a format 212 signal file */ WFDB_Sample v; -WFDB_Signal s; +struct ogdata *g; { - WFDB_Group g = osinfo[s].group; - static int x[WFDB_MAXSIG]; - /* Samples are buffered here and written in pairs, as three bytes. */ - switch (ocount[g]++) { - case 0: x[g] = v & 0xfff; break; - case 1: ocount[g] = 0; - x[g] |= (v << 4) & 0xf000; w16(x[g], s); w8(v, s); + switch (g->count++) { + case 0: g->data = v & 0xfff; break; + case 1: g->count = 0; + g->data |= (v << 4) & 0xf000; + w16(g->data, g); + w8(v, g); break; } } -static int r310(s) /* read and return the next sample from a format 310 */ -WFDB_Signal s; /* signal file (3 10-bit samples bit-packed in 4 bytes) */ +static int r310(g) /* read and return the next sample from a format 310 */ +struct igdata *g; /* signal file (3 10-bit samples bit-packed in 4 bytes) */ { - WFDB_Group g = isinfo[s].group; int v; - static int x[WFDB_MAXSIG], y[WFDB_MAXSIG]; /* Obtain the next 10-bit value right-justified in v. */ - switch (icount[g]++) { - case 0: v = (x[g] = r16(s)) >> 1; break; - case 1: v = (y[g] = r16(s)) >> 1; break; + switch (g->count++) { + case 0: v = (g->data = r16(g)) >> 1; break; + case 1: v = (g->datb = r16(g)) >> 1; break; case 2: - default: icount[g] = 0; - v = ((x[g] & 0xf800) >> 11) | ((y[g] & 0xf800) >> 6); break; + default: g->count = 0; + v = ((g->data & 0xf800) >> 11) | ((g->datb & 0xf800) >> 6); + break; } /* Sign-extend from the tenth bit. */ if (v & 0x200) v |= ~(0x3ff); @@ -792,43 +1072,39 @@ return (v); } -static void w310(v, s) /* write the next sample to a format 310 signal file */ +static void w310(v, g) /* write the next sample to a format 310 signal file */ WFDB_Sample v; -WFDB_Signal s; +struct ogdata *g; { - WFDB_Group g = osinfo[s].group; - static int x[WFDB_MAXSIG], y[WFDB_MAXSIG]; - /* Samples are buffered here and written in groups of three, as two left-justified 15-bit words. */ - switch (ocount[g]++) { - case 0: x[g] = (v << 1) & 0x7fe; break; - case 1: y[g] = (v << 1) & 0x7fe; break; + switch (g->count++) { + case 0: g->data = (v << 1) & 0x7fe; break; + case 1: g->datb = (v << 1) & 0x7fe; break; case 2: - default: ocount[g] = 0; - x[g] |= (v << 11); w16(x[g], s); - y[g] |= ((v << 6) & ~0x7fe); w16(y[g], s); + default: g->count = 0; + g->data |= (v << 11); w16(g->data, g); + g->datb |= ((v << 6) & ~0x7fe); w16(g->datb, g); break; } } /* Note that formats 310 and 311 differ in the layout of the bit-packed data */ -static int r311(s) /* read and return the next sample from a format 311 */ -WFDB_Signal s; /* signal file (3 10-bit samples bit-packed in 4 bytes) */ +static int r311(g) /* read and return the next sample from a format 311 */ +struct igdata *g; /* signal file (3 10-bit samples bit-packed in 4 bytes) */ { - WFDB_Group g = isinfo[s].group; int v; - static int x[WFDB_MAXSIG], y[WFDB_MAXSIG]; /* Obtain the next 10-bit value right-justified in v. */ - switch (icount[g]++) { - case 0: v = (x[g] = r16(s)); break; - case 1: y[g] = r16(s); - v = ((x[g] & 0xfc00) >> 10) | ((y[g] & 0xf) << 6); break; + switch (g->count++) { + case 0: v = (g->data = r16(g)); break; + case 1: g->datb = r16(g); + v = ((g->data & 0xfc00) >> 10) | ((g->datb & 0xf) << 6); + break; case 2: - default: icount[g] = 0; - v = y[g] >> 4; break; + default: g->count = 0; + v = g->datb >> 4; break; } /* Sign-extend from the tenth bit. */ if (v & 0x200) v |= ~(0x3ff); @@ -836,22 +1112,19 @@ return (v); } -static void w311(v, s) /* write the next sample to a format 311 signal file */ +static void w311(v, g) /* write the next sample to a format 311 signal file */ WFDB_Sample v; -WFDB_Signal s; +struct ogdata *g; { - WFDB_Group g = osinfo[s].group; - static int x[WFDB_MAXSIG], y[WFDB_MAXSIG]; - /* Samples are buffered here and written in groups of three, bit-packed into the 30 low bits of a 32-bit word. */ - switch (ocount[g]++) { - case 0: x[g] = v & 0x3ff; break; - case 1: x[g] |= (v << 10); w16(x[g], s); - y[g] = (v >> 6) & 0xf; break; + switch (g->count++) { + case 0: g->data = v & 0x3ff; break; + case 1: g->data |= (v << 10); w16(g->data, g); + g->datb = (v >> 6) & 0xf; break; case 2: - default: ocount[g] = 0; - y[g] |= (v << 4); y[g] &= 0x3fff; w16(y[g], s); + default: g->count = 0; + g->datb |= (v << 4); g->datb &= 0x3fff; w16(g->datb, g); break; } } @@ -862,12 +1135,13 @@ { int i, trem = 0; long nb, tt; + struct igdata *ig; WFDB_Signal s; unsigned int b, d = 1, n, nn; - /* Find the first signal which belongs to group g. */ - for (s = 0; s < nisig && g != isinfo[s].group; s++) + /* Find the first signal that belongs to group g. */ + for (s = 0; s < nisig && g != isd[s]->info.group; s++) ; if (s == nisig) { wfdb_error("isgsettime: incorrect signal group number %d\n", g); @@ -892,7 +1166,7 @@ tseg++; if (segp != tseg) { segp = tseg; - if (isigopen(segp->recname, tsinfo, (int)nisig) != nisig) { + if (isigopen(segp->recname, NULL, (int)nisig) != nisig) { wfdb_error("isigsettime: can't open segment %s\n", segp->recname); return (-1); @@ -901,20 +1175,21 @@ t -= segp->samp0; } + ig = igd[g]; /* Determine the number of samples per frame for signals in the group. */ - for (n = nn = 0; s+n < nisig && isinfo[s+n].group == g; n++) - nn += isinfo[s+n].spf; + for (n = nn = 0; s+n < nisig && isd[s+n]->info.group == g; n++) + nn += isd[s+n]->info.spf; /* Determine the number of bytes per sample interval in the file. */ - switch (isinfo[s].fmt) { + switch (isd[s]->info.fmt) { case 0: if (t < nsamples) { if (s == 0) istime = (in_msrec) ? t + segp->samp0 : t; - isinfo[s].nsamp = nsamples - t; - return (istat[g] = 1); + isd[s]->info.nsamp = nsamples - t; + return (ig->stat = 1); } else { if (s == 0) istime = (in_msrec) ? msnsamples : nsamples; - isinfo[s].nsamp = 0L; + isd[s]->info.nsamp = 0L; return (-1); } case 8: @@ -925,7 +1200,7 @@ case 160: b = 2*nn; break; case 212: /* Reset the input counter. */ - icount[g] = 0; + ig->count = 0; /* If the desired sample does not lie on a byte boundary, seek to the previous sample and then read ahead. */ if ((nn & 1) && (t & 1)) { @@ -934,14 +1209,14 @@ if (i = isgsetframe(g, t - 1)) return (i); for (i = 0; i < nn; i++) - (void)r212(s); + (void)r212(ig); istime++; return (0); } b = 3*nn; d = 2; break; case 310: /* Reset the input counter. */ - icount[g] = 0; + ig->count = 0; /* If the desired sample does not lie on a byte boundary, seek to the closest previous sample that does, then read ahead. */ if ((nn % 3) && (trem = (t % 3))) { @@ -950,14 +1225,14 @@ if (i = isgsetframe(g, t - trem)) return (i); for (i = nn*trem; i > 0; i--) - (void)r310(s); + (void)r310(ig); istime += trem; return (0); } b = 4*nn; d = 3; break; case 311: /* Reset the input counter. */ - icount[g] = 0; + ig->count = 0; /* If the desired sample does not lie on a byte boundary, seek to the closest previous sample that does, then read ahead. */ if ((nn % 3) && (trem = (t % 3))) { @@ -966,7 +1241,7 @@ if (i = isgsetframe(g, t - trem)) return (i); for (i = nn*trem; i > 0; i--) - (void)r311(s); + (void)r311(ig); istime += trem; return (0); } @@ -975,14 +1250,14 @@ /* Seek to the beginning of the block which contains the desired sample. For normal files, use fseek() to do so. */ - if (iseek[g]) { + if (ig->seek) { tt = t*b; - nb = tt/d + istart[s]; - i = (isinfo[s].bsize == 0) ? ibsize : isinfo[s].bsize; + nb = tt/d + ig->start; + if ((i = ig->bsize) == 0) i = ibsize; /* Seek to a position such that the next block read will contain the desired sample. */ tt = nb/i; - if (wfdb_fseek(isf[s], tt*i, 0)) { + if (wfdb_fseek(ig->fp, tt*i, 0)) { wfdb_error("isigsettime: improper seek on signal group %d\n", g); return (-1); } @@ -992,23 +1267,25 @@ else { long t0, t1; - t0 = istime - (isbp[g] - isbuf[g])/b; /* earliest buffered sample */ - t1 = t0 + (isbe[g] - isbuf[g])/b; /* earliest unread sample */ + /* Get the time of the earliest buffered sample ... */ + t0 = istime - (ig->bp - ig->buf)/b; + /* ... and that of the earliest unread sample. */ + t1 = t0 + (ig->be - ig->buf)/b; /* There are three possibilities: either the desired sample has been read and has passed out of the buffer, requiring a rewind ... */ if (t < t0) { - if (wfdb_fseek(isf[s], 0L, 0)) { + if (wfdb_fseek(ig->fp, 0L, 0)) { wfdb_error("isigsettime: improper seek on signal group %d\n", g); return (-1); } tt = t*b; - nb = tt/d + istart[s]; + nb = tt/d + ig->start; } /* ... or it is in the buffer already ... */ else if (t < t1) { tt = (t - t0)*b; - isbp[g] = isbuf[g] + tt/d; + ig->bp = ig->buf + tt/d; return (0); } /* ... or it has not yet been read. */ @@ -1016,18 +1293,18 @@ tt = (t - t1) * b; nb = tt/d; } - while (nb > isinfo[s].bsize && !wfdb_feof(isf[s])) - nb -= wfdb_fread(isbuf[g], 1, isinfo[s].bsize, isf[s]); + while (nb > ig->bsize && !wfdb_feof(ig->fp)) + nb -= wfdb_fread(ig->buf, 1, ig->bsize, ig->fp); } /* Reset the block pointer to indicate nothing has been read in the current block. */ - isbp[g] = isbe[g]; - istat[g] = 1; - /* Read any bytes in the current block which precede the desired sample. */ - while (nb-- > 0 && istat[g] > 0) - i = r8(s); - if (istat[g] <= 0) return (-1); + ig->bp = ig->be; + ig->stat = 1; + /* Read any bytes in the current block that precede the desired sample. */ + while (nb-- > 0 && ig->stat > 0) + i = r8(ig); + if (ig->stat <= 0) return (-1); /* Reset the getvec sample-within-frame counter. */ gvc = ispfmax; @@ -1036,66 +1313,70 @@ testing (by setting the number of samples remaining to 0). */ if (s == 0) istime = in_msrec ? t + segp->samp0 : t; while (n-- != 0) - isinfo[s+n].nsamp = (WFDB_Time)0L; + isd[s+n]->info.nsamp = (WFDB_Time)0L; return (0); } static int getskewedframe(vector) WFDB_Sample *vector; { - int c, stat = (int)nisig; + int c, stat; + struct isdata *is; + struct igdata *ig; + WFDB_Group g; WFDB_Signal s; + if ((stat = (int)nisig) == 0) return (0); if (istime == 0L) { - /* Go through groups in reverse order since seeking on group 0 should - always be done last. */ - s = nisig-1; - do { - ivec[s] = isinfo[s].initval; - if ((s == 0 || isinfo[s].group != isinfo[s-1].group) && - istart[s] > 0L) - (void)isgsetframe(isinfo[s].group, 0L); - - } while (s-- != 0); + for (s = 0; s < nisig; s++) + isd[s]->samp = isd[s]->info.initval; + for (g = nigroups; g; ) { + /* Go through groups in reverse order since seeking on group 0 + should always be done last. */ + if (--g == 0 || igd[g]->start > 0L) + (void)isgsetframe(g, 0L); + } } for (s = 0; s < nisig; s++) { - for (c = 0; c < isinfo[s].spf; c++, vector++) { - switch (isinfo[s].fmt) { + is = isd[s]; + ig = igd[is->info.group]; + for (c = 0; c < is->info.spf; c++, vector++) { + switch (is->info.fmt) { case 0: /* null signal: return adczero */ - *vector = isinfo[s].adczero; - if (isinfo[s].nsamp == 0) istat[isinfo[s].group] = -1; + *vector = is->info.adczero; + if (is->info.nsamp == 0) ig->stat = -1; break; case 8: /* 8-bit first differences */ default: - *vector = ivec[s] += r8(s); break; + *vector = is->samp += r8(ig); break; case 16: /* 16-bit amplitudes */ - *vector = r16(s); break; + *vector = r16(ig); break; case 61: /* 16-bit amplitudes, bytes swapped */ - *vector = r61(s); break; + *vector = r61(ig); break; case 80: /* 8-bit offset binary amplitudes */ - *vector = r80(s); break; + *vector = r80(ig); break; case 160: /* 16-bit offset binary amplitudes */ - *vector = r160(s); break; + *vector = r160(ig); break; case 212: /* 2 12-bit amplitudes bit-packed in 3 bytes */ - *vector = r212(s); break; + *vector = r212(ig); break; case 310: /* 3 10-bit amplitudes bit-packed in 4 bytes */ - *vector = r310(s); break; + *vector = r310(ig); break; case 311: /* 3 10-bit amplitudes bit-packed in 4 bytes */ - *vector = r311(s); break; + *vector = r311(ig); break; } - if (istat[isinfo[s].group] <= 0) { + if (ig->stat <= 0) { /* End of file -- reset input counter. */ - icount[isinfo[s].group] = 0; - if (isinfo[s].nsamp > (WFDB_Time)0L) { + ig->count = 0; + if (is->info.nsamp > (WFDB_Time)0L) { wfdb_error("getvec: unexpected EOF in signal %d\n", s); stat = -3; } else if (in_msrec && segp < segend) { segp++; - if (isigopen(segp->recname, tsinfo, (int)nisig) < nisig) { + if (isigopen(segp->recname, NULL, (int)nisig) < nisig) { wfdb_error("getvec: error opening segment %s\n", - segp->recname); + segp->recname); stat = -3; } else { @@ -1105,7 +1386,7 @@ } else stat = -1; - if (isinfo[s].nsamp > (WFDB_Time)0L) { + if (is->info.nsamp > (WFDB_Time)0L) { wfdb_error("getvec: unexpected EOF in signal %d\n", s); stat = -3; } @@ -1113,10 +1394,11 @@ stat = -1; } else - isinfo[s].cksum -= *vector; + is->info.cksum -= *vector; } - if (--isinfo[s].nsamp == (WFDB_Time)0L && (isinfo[s].cksum & 0xffff) && - isinfo[s].fmt != 0) { + if (--is->info.nsamp == (WFDB_Time)0L && + (is->info.cksum & 0xffff) && + is->info.fmt != 0) { wfdb_error("getvec: checksum error in signal %d\n", s); stat = -4; } @@ -1131,12 +1413,12 @@ WFDB_Siginfo *siarray; int nsig; { - WFDB_FILE **ifp; - WFDB_Group g; - int navail; - WFDB_Siginfo *isi; + int navail, ngroups, nn; + struct hsdata *hs; + struct isdata *is; + struct igdata *ig; WFDB_Signal s, si, sj; - unsigned int buflen, ga; + WFDB_Group g; /* Close previously opened input signals unless otherwise requested. */ if (*record == '+') record++; @@ -1146,11 +1428,11 @@ if (!in_msrec) wfdb_setirec(record); /* Read the header and determine how many signals are available. */ - if ((navail = readheader(record, tsinfo)) <= 0) { + if ((navail = readheader(record)) <= 0) { if (navail == 0 && segments) { /* this is a multi-segment record */ in_msrec = 1; /* Open the first segment to get signal information. */ - if ((navail = readheader(segp->recname, tsinfo)) >= 0) { + if ((navail = readheader(segp->recname)) >= 0) { if (msbtime == 0L) msbtime = btime; if (msbdate == 0L) msbdate = bdate; } @@ -1167,84 +1449,88 @@ if (nsig <= 0) { nsig = -nsig; if (navail < nsig) nsig = navail; - for (s = 0; s < nsig; s++) - siarray[s] = tsinfo[s]; + if (siarray != NULL) + for (s = 0; s < nsig; s++) + siarray[s] = hsd[s]->info; + in_msrec = 0; /* necessary to avoid errors when reopening */ return (navail); } - /* Initialize local variables. */ - ifp = &isf[nisig]; - isi = &isinfo[nisig]; - if (ibsize <= 0) ibsize = BUFSIZ; - - /* Determine how many signals we should attempt to open. The caller's - upper limit on this number is nsig, the upper limit defined by the - header is navail, and the upper limit imposed by the WFDB library is - WFDB_MAXSIG-nisig (the number of empty slots in the input signal - arrays). */ + /* Determine how many new signals we should attempt to open. The caller's + upper limit on this number is nsig, and the upper limit defined by the + header is navail. */ if (nsig > navail) nsig = navail; - if (nsig > WFDB_MAXSIG - nisig) nsig = WFDB_MAXSIG - nisig; - /* Set the group number adjustment. This quantity is added to the group - numbers of signals which are opened below; it accounts for any input - signals which were left open from previous calls. */ - ga = nisig ? isinfo[nisig-1].group + 1 : 0; + /* Allocate input signals and signal group workspace. */ + nn = nisig + nsig; + if (allocisig(nn) != nn) + return (-1); /* failed, nisig is unchanged, allocisig emits error */ + else + nsig = nn; + nn = nigroups + hsd[nsig-1]->info.group + 1; + if (allocigroup(nn) != nn) + return (-1); /* failed, allocigroup emits error */ + else + ngroups = nn; + /* Set default buffer size (if not set already by setibsize). */ + if (ibsize <= 0) ibsize = BUFSIZ; + /* Open the signal files. One signal group is handled per iteration. In - this loop, si counts through the entries in tsinfo, and s counts the - entries added to the isinfo and isf (ifp) arrays. */ - for (si = s = 0; si < navail && s < nsig; ) { + this loop, si counts through the entries that have been read from hsd, + and s counts the entries that have been added to isd. */ + for (g = si = s = 0; si < navail && s < nsig; si = sj) { + hs = hsd[si]; + is = isd[nisig+s]; + ig = igd[nigroups+g]; + /* Find out how many signals are in this group. */ - for (sj = si+1; sj nsig-s) { - si = sj; - ga--; - continue; - } - /* Don't open a file for a null signal. */ - if (tsinfo[si].fmt == 0) - ifp[s] = NULL; - /* The file name '-' specifies the standard input. */ - else if (strcmp(tsinfo[si].fname, "-") == 0) { - ifp[s]->type = WFDB_LOCAL; - ifp[s]->fp = stdin; - } - /* Skip this group if the signal file can't be opened. */ - else if ((ifp[s]=wfdb_open(tsinfo[si].fname,(char *)NULL,WFDB_READ)) == - NULL){ - si = sj; - ga--; - continue; - } - g = tsinfo[si].group + ga; /* the next group number to be assigned */ - if (tsinfo[si].bsize > 0) buflen = tsinfo[si].bsize; - else if (tsinfo[si].bsize < 0) buflen = -tsinfo[si].bsize; - else buflen = ibsize; + for (sj = si + 1; sj < navail; sj++) + if (hsd[sj]->info.group != hs->info.group) break; + + /* Skip this group if there are too few slots in the caller's array. */ + if (sj - si > nsig - s) continue; + + /* Set the buffer size and the seek capability flag. */ + if (hs->info.bsize < 0) { + ig->bsize = hs->info.bsize = -hs->info.bsize; + ig->seek = 0; + } + else { + if ((ig->bsize = hs->info.bsize) == 0) ig->bsize = ibsize; + ig->seek = 1; + } + /* Skip this group if a buffer can't be allocated. */ - if ((isbuf[g] = (char *)malloc(buflen)) == NULL) { - si = sj; - ga--; - continue; - } - isbe[g] = isbp[g] = isbuf[g] + buflen; - istat[g] = 1; - if (tsinfo[si].bsize < 0) { - tsinfo[si].bsize = -tsinfo[si].bsize; - iseek[g] = 0; + if ((ig->buf = (char *)malloc(ig->bsize)) == NULL) continue; + + /* Check that the signal file is readable. */ + if (hs->info.fmt == 0) + ig->fp = NULL; /* Don't open a file for a null signal. */ + else { + ig->fp = wfdb_open(hs->info.fname, (char *)NULL, WFDB_READ); + /* Skip this group if the signal file can't be opened. */ + if (ig->fp == NULL) { + (void)free(ig->buf); + continue; + } } - else - iseek[g] = 1; - istart[s+nisig] = tstart[si]; - isi[s] = tsinfo[si++]; - isi[s++].group = g; - while (si < sj) { - ifp[s] = ifp[s-1]; - istart[s+nisig] = tstart[si]; - isi[s] = tsinfo[si++]; - isi[s++].group = g; + + /* All tests passed -- fill in remaining data for this group. */ + ig->be = ig->bp = ig->buf + ig->bsize; + ig->start = hs->start; + ig->stat = 1; + while (si < sj && s < nsig) { + if (copysi(&is->info, &hs->info) < 0) { + wfdb_error("isigopen: insufficient memory\n"); + return (-3); + } + is->info.group = g; + is->skew = hs->skew; + hs = hsd[++si]; + is = isd[nisig + ++s]; } + g++; } /* Produce a warning message if none of the requested signals could be @@ -1253,39 +1539,47 @@ wfdb_error("isigopen: none of the signals for record %s is readable\n", record); - /* Copy the WFDB_Siginfo structures to the caller's array. */ + /* Copy the WFDB_Siginfo structures to the caller's array. Use these + data to construct the initial sample vector, and to determine the + maximum number of samples per signal per frame and the maximum skew. */ for (si = 0; si < s; si++) { - siarray[si] = isi[si]; - if (ispfmax < isi[si].spf) ispfmax = isi[si].spf; - if (skewmax < iskew[si]) skewmax = iskew[si]; - ivec[si] = isi[si].initval; /* *** check this *** */ + is = isd[nisig + si]; + if (siarray != NULL && copysi(&siarray[si], &is->info) < 0) { + wfdb_error("isigopen: insufficient memory\n"); + return (-3); + } + is->samp = is->info.initval; + if (ispfmax < is->info.spf) ispfmax = is->info.spf; + if (skewmax < is->skew) skewmax = is->skew; } - /* Reset sfreq if appropriate. */ - setgvmode(gvmode); - - /* Initialize getvec's sample-within-frame counter. */ - gvc = ispfmax; - - /* Update the count of open input signals. */ - nisig += s; + setgvmode(gvmode); /* Reset sfreq if appropriate. */ + gvc = ispfmax; /* Initialize getvec's sample-within-frame counter. */ + nisig += s; /* Update the count of open input signals. */ + nigroups += g; /* Update the count of open input signal groups. */ /* Determine the total number of samples per frame. */ for (si = framelen = 0; si < nisig; si++) - framelen += isinfo[si].spf; + framelen += isd[si]->info.spf; + + /* Allocate workspace for getvec and isgsettime. */ + if ((tvector = calloc(sizeof(WFDB_Sample), framelen)) == NULL || + (uvector = calloc(sizeof(WFDB_Sample), framelen)) == NULL) { + wfdb_error("isigopen: can't allocate frame buffer\n"); + if (tvector) (void)free(tvector); + return (-3); + } /* If deskewing is required, allocate the deskewing buffer (unless this is - a multi-segment record and dsbuf has been allocated already); produce a - warning message if the buffer couldn't be allocated. In this case, the - signals can still be read, but won't be deskewed. */ + a multi-segment record and dsbuf has been allocated already). */ if (skewmax != 0 && (!in_msrec || dsbuf == NULL)) { dsbi = -1; /* mark buffer contents as invalid */ dsblen = framelen * (skewmax + 1); -#ifndef lint if (dsbuf) free(dsbuf); if ((dsbuf=(WFDB_Sample *)malloc(dsblen*sizeof(WFDB_Sample))) == NULL) wfdb_error("isigopen: can't allocate buffer for deskewing\n"); -#endif + /* If the buffer couldn't be allocated, the signals can still be read, + but won't be deskewed. */ } return (s); } @@ -1295,22 +1589,17 @@ WFDB_Siginfo *siarray; unsigned int nsig; { - WFDB_FILE **ofp; int n; - WFDB_Siginfo *osi; - WFDB_Signal s, si; + struct osdata *os, *op; + struct ogdata *og; + WFDB_Signal s; unsigned int buflen, ga; /* Close previously opened output signals unless otherwise requested. */ if (*record == '+') record++; else osigclose(); - /* Determine if nsig output signals can be opened. */ - if (nsig > WFDB_MAXSIG - nosig) { - wfdb_error("osigopen: attempt to open too many output signals\n"); - return (-3); - } - if ((n = readheader(record, tsinfo)) < 0) + if ((n = readheader(record)) < 0) return (n); if (n < nsig) { wfdb_error("osigopen: record %s has fewer signals than needed\n", @@ -1318,58 +1607,75 @@ return (-3); } + /* Allocate workspace for output signals. */ + if (allocosig(nosig + nsig) < 0) return (-3); + /* Allocate workspace for output signal groups. */ + if (allocogroup(nogroups + hsd[nsig-1]->info.group + 1) < 0) return (-3); + /* Initialize local variables. */ - ofp = &osf[nosig]; - osi = &osinfo[nosig]; if (obsize <= 0) obsize = BUFSIZ; /* Set the group number adjustment. This quantity is added to the group numbers of signals which are opened below; it accounts for any output signals which were left open from previous calls. */ - ga = nosig ? osinfo[nosig-1].group + 1 : 0; + ga = nogroups; /* Open the signal files. One signal is handled per iteration. */ - for (s = 0; s < nsig; s++) { - /* Check if this signal is in the same group as the previous one. */ - if (s != 0 && tsinfo[s].group == tsinfo[s-1].group) - ofp[s] = ofp[s-1]; - else if (tsinfo[s].fmt == 0) - ofp[s] = NULL; /* don't open a file for a null signal */ - /* The filename '-' specifies the standard output. */ - else if (strcmp(tsinfo[s].fname, "-") == 0) { - ofp[s]->type = WFDB_LOCAL; - ofp[s]->fp = stdout; - } - /* An error in opening an output file is fatal. */ - else if ((ofp[s]=wfdb_open(tsinfo[s].fname,(char *)NULL,WFDB_WRITE)) == - NULL){ - wfdb_error("osigopen: can't open %s\n", tsinfo[s].fname); + for (s = 0, os = osd[nosig]; s < nsig; s++, nosig++, siarray++) { + op = os; + os = osd[nosig]; + + /* Copy signal information from readheader's workspace. */ + if (copysi(&os->info, &hsd[s]->info) < 0 || + copysi(siarray, &hsd[s]->info) < 0) { + wfdb_error("osigopen: insufficient memory\n"); return (-3); } - osi[s] = tsinfo[s]; - buflen = (osi[s].bsize > 0) ? osi[s].bsize : obsize; - osi[s].group += ga; - /* An error allocating a buffer is fatal. */ - if ((s == 0 || osi[s].group != osi[s-1].group) && - (osbuf[osi[s].group] = (char *)malloc(buflen)) == NULL) { - wfdb_error("osigopen: can't allocate buffer for %s\n", - osi[s].fname); - return (-3); + if (os->info.spf < 1) os->info.spf = siarray->spf = 1; + os->info.cksum = siarray->cksum = 0; + os->info.nsamp = siarray->nsamp = (WFDB_Time)0L; + os->info.group += ga; siarray->group += ga; + + if (s == 0 || os->info.group != op->info.group) { + /* This is the first signal in a new group; allocate buffer. */ + size_t obuflen; + + og = ogd[os->info.group]; + og->bsize = os->info.bsize; + obuflen = og->bsize ? og->bsize : obsize; + if ((og->buf = (char *)malloc(obuflen)) == NULL) { + wfdb_error("osigopen: can't allocate buffer for %s\n", + os->info.fname); + return (-3); + } + og->bp = og->buf; + og->be = og->buf + obuflen; + if (os->info.fmt == 0) + og->fp = NULL; /* don't open a file for a null signal */ + /* An error in opening an output file is fatal. */ + else { + og->fp = wfdb_open(os->info.fname,(char *)NULL, WFDB_WRITE); + if (og->fp == NULL) { + wfdb_error("osigopen: can't open %s\n", os->info.fname); + free(og->buf); + og->buf = NULL; + osigclose(); + return (-3); + } + } + nogroups++; + } + else { + /* This signal belongs to the same group as the previous signal. */ + if (os->info.fmt != op->info.fmt || + os->info.bsize != op->info.bsize) { + wfdb_error( + "osigopen: error in specification of signal %d or %d\n", + s-1, s); + return (-2); + } } - osbp[osi[s].group] = osbuf[osi[s].group]; - osbe[osi[s].group] = osbuf[osi[s].group] + buflen; - } - - /* Copy the WFDB_Siginfo structures to the caller's array. */ - for (si = 0; si < s; si++) { - osi[si].cksum = 0; - osi[si].nsamp = (WFDB_Time)0L; - siarray[si] = osi[si]; } - - /* Update the count of open output signals. */ - nosig += s; - return (s); } @@ -1377,94 +1683,126 @@ WFDB_Siginfo *siarray; unsigned int nsig; { - unsigned int buflen; + struct osdata *os, *op; + struct ogdata *og; + int s; + WFDB_Siginfo *si; /* Close any open output signals. */ osigclose(); + /* Do nothing further if there are no signals to open. */ + if (siarray == NULL || nsig == 0) return (0); + if (obsize <= 0) obsize = BUFSIZ; + /* Prescan siarray to check the signal specifications and to determine + the number of signal groups. */ + for (s = 0, si = siarray; s < nsig; s++, si++) { + /* The combined lengths of the fname and desc strings should be 80 + characters or less, the bsize field must not be negative, the + format should be legal, group numbers should be the same if and + only if file names are the same, and group numbers should begin + at zero and increase in steps of 1. */ + if (strlen(si->fname) + strlen(si->desc) > 80 || + si->bsize < 0 || !isfmt(si->fmt)) { + wfdb_error("osigfopen: error in specification of signal %d\n", + s); + return (-2); + } + if (!((s == 0 && si->group == 0) || + (s && si->group == (si-1)->group && + strcmp(si->fname, (si-1)->fname) == 0) || + (s && si->group == (si-1)->group + 1 && + strcmp(si->fname, (si-1)->fname) != 0))) { + wfdb_error( + "osigfopen: incorrect file name or group for signal %d\n", + s); + return (-2); + } + } + + /* Allocate workspace for output signals. */ + if (allocosig(nsig) < 0) return (-3); + /* Allocate workspace for output signal groups. */ + if (allocogroup((si-1)->group + 1) < 0) return (-3); + /* Open the signal files. One signal is handled per iteration. */ - for ( ; nosig < nsig; nosig++) { + for (os = osd[0]; nosig < nsig; nosig++, siarray++) { + + op = os; + os = osd[nosig]; /* Check signal specifications. The combined lengths of the fname and desc strings should be 80 characters or less, the bsize field must not be negative, the format should be legal, group numbers should be the same if and only if file names are the same, and group numbers should begin at zero and increase in steps of 1. */ - if (strlen(siarray[nosig].fname) + strlen(siarray[nosig].desc) > 80 || - siarray[nosig].bsize < 0 || !isfmt(siarray[nosig].fmt)) { - wfdb_error("osigfopen: error in specification of signal %d\n",nosig); + if (strlen(siarray->fname) + strlen(siarray->desc) > 80 || + siarray->bsize < 0 || !isfmt(siarray->fmt)) { + wfdb_error("osigfopen: error in specification of signal %d\n", + nosig); return (-2); } - if (!((nosig == 0 && siarray[nosig].group == 0) || - (nosig && siarray[nosig].group == siarray[nosig-1].group && - strcmp(siarray[nosig].fname, siarray[nosig-1].fname) == 0) || - (nosig && siarray[nosig].group == siarray[nosig-1].group + 1 && - strcmp(siarray[nosig].fname, siarray[nosig-1].fname) != 0))) { + if (!((nosig == 0 && siarray->group == 0) || + (nosig && siarray->group == (siarray-1)->group && + strcmp(siarray->fname, (siarray-1)->fname) == 0) || + (nosig && siarray->group == (siarray-1)->group + 1 && + strcmp(siarray->fname, (siarray-1)->fname) != 0))) { wfdb_error( - "osigfopen: incorrect file name or group for signal %d\n", + "osigfopen: incorrect file name or group for signal %d\n", nosig); return (-2); } + + /* Copy signal information from the caller's array. */ + if (copysi(&os->info, siarray) < 0) { + wfdb_error("osigfopen: insufficient memory\n"); + return (-3); + } + if (os->info.spf < 1) os->info.spf = 1; + os->info.cksum = 0; + os->info.nsamp = (WFDB_Time)0L; + /* Check if this signal is in the same group as the previous one. */ - if (nosig && siarray[nosig].group == siarray[nosig-1].group) { - osf[nosig] = osf[nosig-1]; - if (siarray[nosig].fmt != siarray[nosig-1].fmt || - siarray[nosig].bsize != siarray[nosig-1].bsize) { + if (nosig == 0 || os->info.group != op->info.group) { + size_t obuflen; + + og = ogd[os->info.group]; + og->bsize = os->info.bsize; + obuflen = og->bsize ? og->bsize : obsize; + /* This is the first signal in a new group; allocate buffer. */ + if ((og->buf = (char *)malloc(obuflen)) == NULL) { + wfdb_error("osigfopen: can't allocate buffer for %s\n", + os->info.fname); + return (-3); + } + og->bp = og->buf; + og->be = og->buf + obuflen; + if (os->info.fmt == 0) + og->fp = NULL; /* don't open a file for a null signal */ + /* An error in opening an output file is fatal. */ + else { + og->fp = wfdb_open(os->info.fname,(char *)NULL, WFDB_WRITE); + if (og->fp == NULL) { + wfdb_error("osigfopen: can't open %s\n", os->info.fname); + free(og->buf); + og->buf = NULL; + osigclose(); + return (-3); + } + } + nogroups++; + } + else { + /* This signal belongs to the same group as the previous signal. */ + if (os->info.fmt != op->info.fmt || + os->info.bsize != op->info.bsize) { wfdb_error( "osigfopen: error in specification of signal %d or %d\n", nosig-1, nosig); return (-2); } } - else if (siarray[nosig].fmt == 0) - osf[nosig] = NULL; /* don't open a file for a null signal */ - /* The filename '-' specifies the standard output. */ - else if (strcmp(siarray[nosig].fname, "-") == 0) { - osf[nosig]->type = WFDB_LOCAL; - osf[nosig]->fp = stdout; - } - /* An error in opening an output file is fatal. */ - else if ((osf[nosig] = wfdb_open(siarray[nosig].fname, (char *)NULL, - WFDB_WRITE)) == NULL) { - wfdb_error("osigfopen: can't open %s\n", siarray[nosig].fname); - return (-3); - } - osinfo[nosig] = siarray[nosig]; - if (osinfo[nosig].spf < 1) osinfo[nosig].spf = 1; - osinfo[nosig].cksum = 0; - osinfo[nosig].nsamp = (WFDB_Time)0L; - buflen = (osinfo[nosig].bsize > 0) ? osinfo[nosig].bsize : obsize; - /* An error allocating a buffer is fatal. */ - if ((nosig == 0 || siarray[nosig].group != siarray[nosig-1].group) && - (osbuf[osinfo[nosig].group] = (char *)malloc(buflen)) == NULL || - (osinfo[nosig].fname = - (char *)malloc((unsigned)strlen(siarray[nosig].fname)+1))==NULL) { - wfdb_error("osigfopen: can't allocate buffer for %s\n", - osinfo[nosig].fname); - return (-3); - } - if (nosig != 0 && osinfo[nosig].group == osinfo[nosig-1].group) - osinfo[nosig].fname = osinfo[nosig-1].fname; - else - (void)strcpy(osinfo[nosig].fname, siarray[nosig].fname); - if ((osinfo[nosig].desc = - (char *)malloc((unsigned)strlen(siarray[nosig].desc)+1))==NULL) { - wfdb_error("osigfopen: insufficient memory\n"); - return (-3); - } - (void)strcpy(osinfo[nosig].desc, siarray[nosig].desc); - if (siarray[nosig].units) { - if ((osinfo[nosig].units = - (char *)malloc((unsigned)strlen(siarray[nosig].units)+1)) == - NULL) { - wfdb_error("osigfopen: insufficient memory\n"); - return (-3); - } - (void)strcpy(osinfo[nosig].units, siarray[nosig].units); - } - osbp[osinfo[nosig].group] = osbuf[osinfo[nosig].group]; - osbe[osinfo[nosig].group] = osbuf[osinfo[nosig].group] + buflen; } return (nosig); @@ -1502,7 +1840,6 @@ FINT getvec(vector) WFDB_Sample *vector; { - static WFDB_Sample tvector[WFDB_MAXSIG*WFDB_MAXSPF]; WFDB_Sample *tp; WFDB_Signal s; static int stat; @@ -1517,9 +1854,11 @@ stat = getframe(tvector); for (s = 0, tp = tvector; s < nisig; s++) { - for (c = v = 0; c < isinfo[s].spf; c++) + int sf = isd[s]->info.spf; + + for (c = v = 0; c < sf; c++) v += *tp++; - *vector++ = v/isinfo[s].spf; + *vector++ = v/sf; } } else { /* return ispfmax samples per frame, using @@ -1529,8 +1868,10 @@ gvc = 0; } for (s = 0, tp = tvector; s < nisig; s++) { - *vector++ = tp[(isinfo[s].spf*gvc)/ispfmax]; - tp += isinfo[s].spf; + int sf = isd[s]->info.spf; + + *vector++ = tp[(sf*gvc)/ispfmax]; + tp += sf; } gvc++; } @@ -1557,8 +1898,8 @@ } /* Assemble the deskewed frame from the data in dsbuf. */ for (j = s = 0; s < nisig; s++) { - if ((i = j + dsbi + iskew[s]*framelen) >= dsblen) i -= dsblen; - for (c = 0; c < isinfo[s].spf; c++) + if ((i = j + dsbi + isd[s]->skew*framelen) >= dsblen) i -= dsblen; + for (c = 0; c < isd[s]->info.spf; c++) vector[j++] = dsbuf[i++]; } } @@ -1572,44 +1913,50 @@ WFDB_Sample *vector; { int c, dif, stat = (int)nosig; + struct osdata *os; + struct ogdata *og; WFDB_Signal s; + WFDB_Group g; for (s = 0; s < nosig; s++) { - if (osinfo[s].nsamp++ == (WFDB_Time)0L) - osinfo[s].initval = ovec[s] = *vector; - for (c = 0; c < osinfo[s].spf; c++, vector++) { - switch (osinfo[s].fmt) { + os = osd[s]; + g = os->info.group; + og = ogd[os->info.group]; + if (os->info.nsamp++ == (WFDB_Time)0L) + os->info.initval = os->samp = *vector; + for (c = 0; c < os->info.spf; c++, vector++) { + switch (os->info.fmt) { case 0: /* null signal (do not write) */ - ovec[s] = *vector; break; + os->samp = *vector; break; case 8: /* 8-bit first differences */ default: /* Handle large slew rates sensibly. */ - if ((dif = *vector - ovec[s]) < -128) { dif = -128; stat = 0; } + if ((dif = *vector - os->samp) < -128) { dif = -128; stat=0; } else if (dif > 127) { dif = 127; stat = 0; } - ovec[s] += dif; - w8(dif, s); + os->samp += dif; + w8(dif, og); break; case 16: /* 16-bit amplitudes */ - w16(*vector, s); ovec[s] = *vector; break; + w16(*vector, og); os->samp = *vector; break; case 61: /* 16-bit amplitudes, bytes swapped */ - w61(*vector, s); ovec[s] = *vector; break; + w61(*vector, og); os->samp = *vector; break; case 80: /* 8-bit offset binary amplitudes */ - w80(*vector, s); ovec[s] = *vector; break; + w80(*vector, og); os->samp = *vector; break; case 160: /* 16-bit offset binary amplitudes */ - w160(*vector, s); ovec[s] = *vector; break; + w160(*vector, og); os->samp = *vector; break; case 212: /* 2 12-bit amplitudes bit-packed in 3 bytes */ - w212(*vector, s); ovec[s] = *vector; break; + w212(*vector, og); os->samp = *vector; break; case 310: /* 3 10-bit amplitudes bit-packed in 4 bytes */ - w310(*vector, s); ovec[s] = *vector; break; + w310(*vector, og); os->samp = *vector; break; case 311: /* 3 10-bit amplitudes bit-packed in 4 bytes */ - w311(*vector, s); ovec[s] = *vector; break; + w311(*vector, og); os->samp = *vector; break; } - if (wfdb_ferror(osf[s])) { + if (wfdb_ferror(og->fp)) { wfdb_error("putvec: write error in signal %d\n", s); stat = -1; } else - osinfo[s].cksum += ovec[s]; + os->info.cksum += os->samp; } } ostime++; @@ -1620,15 +1967,14 @@ WFDB_Time t; { WFDB_Group g; - int stat; + int stat = 0; WFDB_Signal s; /* Return immediately if no seek is needed. */ if (t == istime || nisig == 0) return (0); - for (g = s = stat = 0; s < nisig; s++) - if (isinfo[s].group != g && - (stat = isgsettime(g = isinfo[s].group, t)) < 0) break; + for (g = 1; g < nigroups; g++) + if ((stat = isgsettime(g, t)) < 0) break; /* Seek on signal group 0 last (since doing so updates istime and would confuse isgsettime if done first). */ if (stat == 0) stat = isgsettime(0, t); @@ -1654,9 +2000,7 @@ if ((stat = isgsetframe(g, t)) == 0 && g == 0) { while (trem-- > 0) { - int v[WFDB_MAXSIG*WFDB_MAXSPF]; - - if (getvec(v) < 0) { + if (getvec(uvector) < 0) { wfdb_error("isigsettime: improper seek on signal group %d\n", g); return (-1); @@ -1699,9 +2043,27 @@ FINT newheader(record) char *record; { + int stat; WFDB_Signal s; + WFDB_Siginfo *osi; - return (setheader(record, osinfo, nosig)); + if ((osi = malloc(nosig*sizeof(WFDB_Siginfo))) == NULL) { + wfdb_error("newheader: insufficient memory\n"); + return (-1); + } + for (s = 0; s < nosig; s++) + if (copysi(&osi[s], &osd[s]->info) < 0) { + wfdb_error("newheader: insufficient memory\n"); + return (-1); + } + stat = setheader(record, osi, nosig); + for (s = 0; s < nosig; s++) { + if (osi[s].fname) (void)free(osi[s].fname); + if (osi[s].desc) (void)free(osi[s].desc); + if (osi[s].units) (void)free(osi[s].units); + } + (void)free(osi); + return (stat); } FINT setheader(record, siarray, nsig) @@ -1747,10 +2109,11 @@ (void)wfdb_fprintf(oheader, "%s %d", siarray[s].fname, siarray[s].fmt); if (siarray[s].spf > 1) (void)wfdb_fprintf(oheader, "x%d", siarray[s].spf); - if (oskew[s]) - (void)wfdb_fprintf(oheader, ":%d", oskew[s]*siarray[s].spf); - if (ostart[s]) - (void)wfdb_fprintf(oheader, "+%ld", ostart[s]); + if (osd[s]->skew) + (void)wfdb_fprintf(oheader, ":%d", osd[s]->skew*siarray[s].spf); + if (ogd[osd[s]->info.group]->start) + (void)wfdb_fprintf(oheader, "+%ld", + ogd[osd[s]->info.group]->start); (void)wfdb_fprintf(oheader, " %g", siarray[s].gain); if (siarray[s].baseline != siarray[s].adczero) (void)wfdb_fprintf(oheader, "(%d)", siarray[s].baseline); @@ -1794,40 +2157,32 @@ return (-1); } -#ifndef lint if ((ns = (long *)malloc((unsigned)(sizeof(long)*nsegments))) == NULL) { wfdb_error("setmsheader: insufficient memory\n"); return (-2); } -#endif for (i = 0; i < nsegments; i++) { if (strlen(segment_name[i]) > WFDB_MAXRNL) { wfdb_error( "setmsheader: `%s' is too long for a segment name in record %s\n", segment_name[i], record); -#ifndef lint (void)free(ns); -#endif return (-2); } in_msrec = 1; - n = readheader(segment_name[i], tsinfo); + n = readheader(segment_name[i]); in_msrec = old_in_msrec; if (n < 0) { wfdb_error("setmsheader: can't read segment %s header\n", segment_name[i]); -#ifndef lint (void)free(ns); -#endif return (-3); } - if ((ns[i] = tsinfo[0].nsamp) <= 0L) { + if ((ns[i] = hsd[0]->info.nsamp) <= 0L) { wfdb_error("setmsheader: length of segment %s must be specified\n", segment_name[i]); -#ifndef lint (void)free(ns); -#endif return (-4); } if (i == 0) { @@ -1844,18 +2199,14 @@ wfdb_error( "setmsheader: incorrect number of signals in segment %s\n", segment_name[i]); -#ifndef lint (void)free(ns); -#endif return (-4); } if (msfreq != ffreq) { wfdb_error( "setmsheader: incorrect sampling frequency in segment %s\n", segment_name[i]); -#ifndef lint (void)free(ns); -#endif return (-4); } msnsamples += ns[i]; @@ -1863,12 +2214,10 @@ } /* Try to create the header file. */ - if ((oheader = wfdb_open("header", record, WFDB_WRITE)) == NULL) { + if ((oheader = wfdb_open("hea", record, WFDB_WRITE)) == NULL) { wfdb_error("setmsheader: can't create header file for record %s\n", record); -#ifndef lint (void)free(ns); -#endif return (-1); } @@ -1890,17 +2239,15 @@ for (i = 0; i < nsegments; i++) (void)wfdb_fprintf(oheader, "%s %ld\r\n", segment_name[i], ns[i]); -#ifndef lint (void)free(ns); -#endif return (0); } FINT wfdbgetskew(s) WFDB_Signal s; { - if (s < WFDB_MAXSIG) - return (iskew[s]); + if (s < nisig) + return (isd[s]->skew); else return (0); } @@ -1911,8 +2258,8 @@ WFDB_Signal s; int skew; { - if (s < WFDB_MAXSIG) - iskew[s] = skew; + if (s < nisig) + isd[s]->skew = skew; } /* Note: wfdbsetskew affects *only* the skew to be written by setheader. @@ -1922,15 +2269,15 @@ WFDB_Signal s; int skew; { - if (s < WFDB_MAXSIG) - oskew[s] = skew; + if (s < nosig) + osd[s]->skew = skew; } FLONGINT wfdbgetstart(s) WFDB_Signal s; { - if (s < WFDB_MAXSIG) - return (istart[s]); + if (s < nisig) + return (igd[isd[s]->info.group]->start); else return (0L); } @@ -1942,8 +2289,8 @@ WFDB_Signal s; long bytes; { - if (s < WFDB_MAXSIG) - ostart[s] = bytes; + if (s < nosig) + ogd[osd[s]->info.group]->start = bytes; } FSTRING getinfo(record) @@ -1952,18 +2299,18 @@ char *p; static char linebuf[256]; - if (record != NULL && readheader(record, tsinfo) < 0) { + if (record != NULL && readheader(record) < 0) { wfdb_error("getinfo: can't read record %s header\n", record); return (NULL); } - else if (record == NULL && iheader == NULL) { + else if (record == NULL && hheader == NULL) { wfdb_error("getinfo: caller did not specify record name\n"); return (NULL); } /* Find a line beginning with '#'. */ do { - if (wfdb_fgets(linebuf, 256, iheader) == NULL) + if (wfdb_fgets(linebuf, 256, hheader) == NULL) return (NULL); } while (linebuf[0] != '#'); @@ -1994,7 +2341,12 @@ if (record != NULL) { /* Save the current record name. */ wfdb_setirec(record); - if ((n = readheader(record, tsinfo)) < 0) + /* Don't require the sampling frequency of this record to match that + of the previously opened record, if any. (readheader will + complain if the previously defined sampling frequency was > 0.) */ + setsampfreq(0.); + /* readheader sets sfreq if successful. */ + if ((n = readheader(record)) < 0) /* error message will come from readheader */ return ((WFDB_Frequency)n); } @@ -2016,6 +2368,12 @@ static char date_string[12] = ""; static char time_string[30]; +#ifndef __STDC__ +#ifndef _WINDOWS +typedef long time_t; +#endif +#endif + FINT setbasetime(string) char *string; { @@ -2024,15 +2382,9 @@ if (string == NULL || *string == '\0') { #ifndef NOTIME struct tm *now; -#if defined(__STDC__) || defined(_WINDOWS) time_t t, time(); t = time((time_t *)NULL); /* get current time from system clock */ -#else - long t, time(); - - t = time((long *)NULL); -#endif now = localtime(&t); (void)sprintf(date_string, "%02d/%02d/%d", now->tm_mday, now->tm_mon+1, now->tm_year+1900); @@ -2240,7 +2592,7 @@ WFDB_Signal s; WFDB_Sample a; { - WFDB_Gain g = (s < nisig) ? isinfo[s].gain : WFDB_DEFGAIN; + WFDB_Gain g = (s < nisig) ? isd[s]->info.gain : WFDB_DEFGAIN; if (g == 0.) g = WFDB_DEFGAIN; return ((int)(a*1000./g + 0.5)); @@ -2250,7 +2602,7 @@ WFDB_Signal s; int v; { - WFDB_Gain g = (s < nisig) ? isinfo[s].gain : WFDB_DEFGAIN; + WFDB_Gain g = (s < nisig) ? isd[s]->info.gain : WFDB_DEFGAIN; if (g == 0.) g = WFDB_DEFGAIN; return ((int)(g*v*0.001 + 0.5)); @@ -2264,8 +2616,8 @@ WFDB_Gain g; if (s < nisig) { - b = isinfo[s].baseline; - g = isinfo[s].gain; + b = isd[s]->info.baseline; + g = isd[s]->info.gain; if (g == 0.) g = WFDB_DEFGAIN; } else { @@ -2283,8 +2635,8 @@ WFDB_Gain g; if (s < nisig) { - b = isinfo[s].baseline; - g = isinfo[s].gain; + b = isd[s]->info.baseline; + g = isd[s]->info.gain; if (g == 0.) g = WFDB_DEFGAIN; } else { @@ -2305,31 +2657,23 @@ pdays = (WFDB_Date)-1; segments = in_msrec = skewmax = 0; if (dsbuf) { -#ifndef lint (void)free(dsbuf); -#endif dsbuf = NULL; dsbi = -1; } if (segarray) { int i; -#ifndef lint (void)free(segarray); -#endif segarray = segp = segend = (struct segrec *)NULL; - for (i = 0; i < WFDB_MAXSIG; i++) { - if (isinfo[i].desc) { -#ifndef lint - (void)free(isinfo[i].desc); -#endif - isinfo[i].desc = NULL; - } - if (isinfo[i].units) { -#ifndef lint - (void)free(isinfo[i].units); -#endif - isinfo[i].units = NULL; + for (i = 0; i < maxisig; i++) { + if (isd[i]->info.desc) { + (void)free(isd[i]->info.desc); + isd[i]->info.desc = NULL; + } + if (isd[i]->info.units) { + (void)free(isd[i]->info.units); + isd[i]->info.units = NULL; } } } @@ -2337,15 +2681,15 @@ void wfdb_osflush() { - WFDB_Signal s; WFDB_Group g; + struct ogdata *og; - for (s = 0; s < nosig; s++) - if (s == 0 || (g = osinfo[s].group) != osinfo[s-1].group) { - if (osinfo[s].bsize == 0 && osbp[g] != osbuf[g]) { - (void)wfdb_fwrite(osbuf[g], 1, osbp[g] - osbuf[g], osf[s]); - osbp[g] = osbuf[g]; - } - (void)wfdb_fflush(osf[s]); + for (g = 0; g < nogroups; g++) { + og = ogd[g]; + if (og->bsize == 0 && og->bp != og->buf) { + (void)wfdb_fwrite(og->buf, 1, og->bp - og->buf, og->fp); + og->bp = og->buf; } + (void)wfdb_fflush(og->fp); + } } diff -Naur wfdb-10.1.6/lib/wfdb.h wfdb-10.2.0/lib/wfdb.h --- wfdb-10.1.6/lib/wfdb.h Wed Aug 1 10:28:34 2001 +++ wfdb-10.2.0/lib/wfdb.h Mon Oct 15 14:40:00 2001 @@ -1,5 +1,5 @@ /* file: wfdb.h G. Moody 13 June 1983 - Last revised: 28 February 2001 wfdblib 10.1.6 + Last revised: 14 August 2001 wfdblib 10.2.0 WFDB library type, constant, structure, and function interface definitions _______________________________________________________________________________ @@ -32,8 +32,8 @@ /* WFDB library version. */ #define WFDB_MAJOR 10 -#define WFDB_MINOR 1 -#define WFDB_RELEASE 6 +#define WFDB_MINOR 2 +#define WFDB_RELEASE 0 #define WFDB_NETFILES 1 /* if 1, library includes code for HTTP, FTP clients */ /* Determine what type of compiler is being used. */ @@ -78,7 +78,11 @@ typedef unsigned int WFDB_Signal; /* signal number */ typedef unsigned int WFDB_Annotator;/* annotator number */ -/* Array sizes */ +/* Array sizes + Many older applications use the values of WFDB_MAXANN, WFDB_MAXSIG, and + WFDB_MAXSPF to determine array sizes, but (since WFDB library version 10.2) + there are no longer any fixed limits imposed by the WFDB library. +*/ #define WFDB_MAXANN 2 /* maximum number of input or output annotators */ #define WFDB_MAXSIG 32 /* maximum number of input or output signals */ #define WFDB_MAXSPF 4 /* maximum number of samples per signal per frame */ @@ -267,7 +271,7 @@ extern FINT putinfo(char *info); extern FINT newheader(char *record); extern FINT setheader(char *record, WFDB_Siginfo *siarray, unsigned int nsig); -extern FINT setmsheader(char *record, char **seg_names, unsigned int nsegments); +extern FINT setmsheader(char *record, char **segnames, unsigned int nsegments); extern FINT wfdbgetskew(WFDB_Signal s); extern FVOID wfdbsetskew(WFDB_Signal s, int skew); extern FLONGINT wfdbgetstart(WFDB_Signal s); diff -Naur wfdb-10.1.6/lib/wfdbio.c wfdb-10.2.0/lib/wfdbio.c --- wfdb-10.1.6/lib/wfdbio.c Sat Jul 28 13:45:15 2001 +++ wfdb-10.2.0/lib/wfdbio.c Fri Sep 7 15:21:45 2001 @@ -1,5 +1,5 @@ /* file: wfdbio.c G. Moody 18 November 1988 - Last revised: 19 July 2001 wfdblib 10.1.6 + Last revised: 7 September 2001 wfdblib 10.2.0 Low-level I/O functions for the WFDB library _______________________________________________________________________________ @@ -1511,9 +1511,10 @@ #endif /* WFDB_NETFILES */ WFDB_FILE *wfdb_fopen(fname, mode) -const char *fname, *mode; +char *fname; +const char *mode; { - const char *p = fname; + char *p = fname; WFDB_FILE *wp = (WFDB_FILE *)malloc(sizeof(WFDB_FILE)); if (wp == NULL) { @@ -1534,6 +1535,29 @@ if (wp->fp = fopen(fname, mode)) { wp->type = WFDB_LOCAL; return (wp); + } + if (strcmp(mode, WB) == 0) { + int stat = 1; + + /* An attempt to create an output file failed. Check to see if all + of the directories in the path exist, create them if necessary + and possible, then try again. */ + for (p = fname; *p; p++) + if (*p == '/') { /* only Unix-style directory separators */ + *p = '\0'; + stat = mkdir(fname, 0755); + /* The '0755' means that (under Unix), the directory will + be world-readable, but writeable only by the owner. */ + *p = '/'; + } + /* At this point, we may have created one or more directories. + Only the last attempt to do so matters here: if and only if + it was successful (i.e., if stat is now 0), we should try again + to create the output file. */ + if (stat == 0 && (wp->fp = fopen(fname, mode))) { + wp->type = WFDB_LOCAL; + return (wp); + } } free(wp); return (NULL); diff -Naur wfdb-10.1.6/lib/wfdblib.h wfdb-10.2.0/lib/wfdblib.h --- wfdb-10.1.6/lib/wfdblib.h Tue May 23 01:19:44 2000 +++ wfdb-10.2.0/lib/wfdblib.h Fri Sep 7 15:20:27 2001 @@ -1,10 +1,10 @@ /* file: wfdblib.h G. Moody 13 April 1989 - Last revised: 23 May 2000 wfdblib 10.1.4 + Last revised: 7 September 2001 wfdblib 10.2.0 External definitions for WFDB library private functions _______________________________________________________________________________ wfdb: a library for reading and writing annotated waveforms (time series data) -Copyright (C) 2000 George B. Moody +Copyright (C) 2001 George B. Moody This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free @@ -297,7 +297,7 @@ extern int wfdb_parse_path(char *wfdb_path); extern void wfdb_addtopath(char *pathname); extern void wfdb_error(char *format_string, ...); -extern WFDB_FILE* wfdb_fopen(const char *fname, const char *mode); +extern WFDB_FILE* wfdb_fopen(char *fname, const char *mode); extern int wfdb_fprintf(WFDB_FILE *fp, const char *format, ...); extern void wfdb_setirec(char *record_name); diff -Naur wfdb-10.1.6/psd/Makefile wfdb-10.2.0/psd/Makefile --- wfdb-10.1.6/psd/Makefile Wed Aug 1 10:28:34 2001 +++ wfdb-10.2.0/psd/Makefile Mon Oct 15 14:40:00 2001 @@ -32,12 +32,12 @@ # directory). # _____________________________________________________________________________ # file: version.def G. Moody 24 May 2000 -# Last revised: 28 February 2001 +# Last revised: 14 August 2001 # Each release of the WFDB Software Package is identified by a three-part # version number, defined here: MAJOR = 10 -MINOR = 1 -RELEASE = 6 +MINOR = 2 +RELEASE = 0 VERSION = $(MAJOR).$(MINOR).$(RELEASE) # VDEFS is the set of C compiler options needed to set version number variables @@ -45,7 +45,7 @@ VDEFS = -DWFDB_MAJOR=$(MAJOR) -DWFDB_MINOR=$(MINOR) -DWFDB_RELEASE=$(RELEASE) # _____________________________________________________________________________ -PACKAGE=wfdb-10.1.6 +PACKAGE=wfdb-10.2.0 # file: linux.def G. Moody 31 May 2000 # Last revised: 5 June 2000 # 'make' definitions for compiling the WFDB Software Package under Linux diff -Naur wfdb-10.1.6/psd/Makefile-dos-gcc wfdb-10.2.0/psd/Makefile-dos-gcc --- wfdb-10.1.6/psd/Makefile-dos-gcc Wed May 24 22:35:27 2000 +++ wfdb-10.2.0/psd/Makefile-dos-gcc Wed Dec 31 19:00:00 1969 @@ -1,100 +0,0 @@ -# file: Makefile-dos-gcc G. Moody 24 April 1997 -# Last revised: 5 May 1999 -# -# ----------------------------------------------------------------------------- -# GCC-DOS `make' description file for PSD estimation programs -# Copyright (C) 1999 George B. Moody -# -# These programs are free software; you can redistribute them and/or modify -# them under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# These programs are distributed in the hope that they will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# these programs; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# You may contact the author by e-mail (george@mit.edu) or postal mail -# (MIT Room E25-505A, Cambridge, MA 02139 USA). For updates to this software, -# please visit PhysioNet (http://www.physionet.org/). -# _____________________________________________________________________________ -# -# This file is used with the UNIX `make' command to cross-compile MS-DOS -# binaries of the power spectral density (PSD) estimation applications that -# come with the WFDB Software Package. Before using it for the first time, -# check that the site-specific variables below are appropriate for your system. -# To build and install these applications and their man pages, just type `make -# -f Makefile-dos-gcc' (from within this directory). - -# Site-specific variables -# ----------------------- -# CCDIR is the directory containing the cross-compiler and the binary -# file utilities for MSDOS. -CCDIR = /usr/lib/gcc-lib/i386-go32-msdos/2.7.2 - -# CC is the name of the cross-compiler. -CC = $(CCDIR)/gcc - -# CCDEFS is the set of C compiler options needed to set preprocessor variables -# while compiling the DB Software Package. You should include definitions of -# the major, minor, and release numbers, and of MSDOS, as shown below. Other -# definitions are needed only for various versions of UNIX and should be -# omitted here. -CCDEFS = -DDB_MAJOR=$(MAJOR) -DDB_MINOR=$(MINOR) -DDB_RELEASE=$(RELEASE) -DMSDOS - -# CFLAGS is the list of C compiler options used when compiling programs in the -# `app', `convert', and `example' directories. Add the following options to -# CFLAGS as appropriate (separating them by spaces if you use more than one): -# -g to save symbols for debugging -# -O to use the optimizer -# -I$(INCDIR) needed if INCDIR is not in the normal search path for -# `#include' files; harmless otherwise -# -L$(LIBDIR) needed if LIBDIR is not in the normal library search path; -# harmless if LIBDIR is in the normal library search path -# As noted above, gcc-dos allows you to use both -g and -O if you wish. -CFLAGS = -O -I/usr/local/dos/include $(CCDEFS) -L/usr/local/dos/lib - -# BINDIR specifies the directory in which the applications will be installed; -# it should be a directory in the PATH of those who will use the applications. -# You will need to have write permission in BINDIR. Users of this software -# will need to have search (execute) permission in BINDIR. -BINDIR = /usr/local/dos/bin - -# STRIP is the command used to compact the compiled binaries by removing their -# symbol tables. The next line is commented out because $(CCDIR)/strip fails. -# STRIP = $(CCDIR)/strip -# To retain the symbol tables for debugging, comment out the previous line, and -# uncomment the next line. -STRIP = : - -# It should not be necessary to modify anything below this line. -# ----------------------------------------------------------------------------- - -# General rule for compiling C sources into executable files. -.SUFFIXES: .exe -.c.exe: - $(CC) $(CFLAGS) $< -o $@ -lm - -# Programs to be compiled. -XFILES = coherenc.exe fft.exe log10.exe lomb.exe memse.exe - -# `make' or `make install': build and install applications, clean up -install: all - cp $(XFILES) $(BINDIR) - $(MAKE) clean - -# `make all': build applications -all: $(XFILES) - $(STRIP) $(XFILES) - -coherenc.exe: coherence.c - $(CC) $(CFLAGS) $< -o $@ -lm - -# `make clean': remove intermediate and backup files. -clean: - rm -f *.o *~ $(XFILES) diff -Naur wfdb-10.1.6/wave/Makefile wfdb-10.2.0/wave/Makefile --- wfdb-10.1.6/wave/Makefile Wed Aug 1 10:28:34 2001 +++ wfdb-10.2.0/wave/Makefile Mon Oct 15 14:40:00 2001 @@ -45,12 +45,12 @@ # just type `make' (from within this directory). # _____________________________________________________________________________ # file: version.def G. Moody 24 May 2000 -# Last revised: 28 February 2001 +# Last revised: 14 August 2001 # Each release of the WFDB Software Package is identified by a three-part # version number, defined here: MAJOR = 10 -MINOR = 1 -RELEASE = 6 +MINOR = 2 +RELEASE = 0 VERSION = $(MAJOR).$(MINOR).$(RELEASE) # VDEFS is the set of C compiler options needed to set version number variables @@ -58,7 +58,7 @@ VDEFS = -DWFDB_MAJOR=$(MAJOR) -DWFDB_MINOR=$(MINOR) -DWFDB_RELEASE=$(RELEASE) # _____________________________________________________________________________ -PACKAGE=wfdb-10.1.6 +PACKAGE=wfdb-10.2.0 # file: linux.def G. Moody 31 May 2000 # Last revised: 5 June 2000 # 'make' definitions for compiling the WFDB Software Package under Linux @@ -172,12 +172,12 @@ lib-post-uninstall: echo "Nothing to be done for lib-post-uninstall" # _____________________________________________________________________________ -# file: Makefile.tpl G. Moody 31 May 2000 -# Last revised: 29 May 2001 +# file: Makefile.tpl G. Moody 31 May 2000 +# Last revised: 13 October 2001 # Change the settings below as appropriate for your setup. # WAVEVERSION is the WAVE version number. -WAVEVERSION = 6.4 +WAVEVERSION = 6.5 # Choose directories in which to install WAVE and its ancillary files by # editing the variables below. You will need write permission in all of them diff -Naur wfdb-10.1.6/wave/Makefile.tpl wfdb-10.2.0/wave/Makefile.tpl --- wfdb-10.1.6/wave/Makefile.tpl Tue May 29 16:27:26 2001 +++ wfdb-10.2.0/wave/Makefile.tpl Sat Oct 13 15:57:32 2001 @@ -1,9 +1,9 @@ -# file: Makefile.tpl G. Moody 31 May 2000 -# Last revised: 29 May 2001 +# file: Makefile.tpl G. Moody 31 May 2000 +# Last revised: 13 October 2001 # Change the settings below as appropriate for your setup. # WAVEVERSION is the WAVE version number. -WAVEVERSION = 6.4 +WAVEVERSION = 6.5 # Choose directories in which to install WAVE and its ancillary files by # editing the variables below. You will need write permission in all of them diff -Naur wfdb-10.1.6/wave/analyze.c wfdb-10.2.0/wave/analyze.c --- wfdb-10.1.6/wave/analyze.c Tue May 29 12:29:21 2001 +++ wfdb-10.2.0/wave/analyze.c Sun Oct 14 16:40:14 2001 @@ -1,5 +1,5 @@ /* file: analyze.c G. Moody 10 August 1990 - Last revised: 29 May 2001 + Last revised: 14 October 2001 Functions for the analysis panel of WAVE ------------------------------------------------------------------------------- @@ -340,6 +340,7 @@ PANEL_LABEL_STRING, "Signal list: ", XV_HELP_DATA, "wave:file.analyze.signal_list", PANEL_VALUE_DISPLAY_LENGTH, 15, + PANEL_VALUE_STORED_LENGTH, 1024, PANEL_NOTIFY_PROC, set_siglist, 0); reset_siglist(); @@ -548,22 +549,30 @@ void set_siglist_from_string(s) char *s; { - siglistlen = 0; - while (*s == ' ' || *s == '\t') - s++; - while (siglistlen < WFDB_MAXSIG && *s != '\0' && - sscanf(s, "%d", &siglist[siglistlen]) == 1) { - if (0 <= siglist[siglistlen] && siglist[siglistlen] < nsig) - siglistlen++; - while (*s != ' ' && *s != '\t') { - if (*s == '\0') { - reset_siglist(); - return; - } - else s++; - } - while (*s == ' ' || *s == '\t') - s++; + char *p; + + /* Count the number of signals named in the string (s). */ + for (p = s, siglistlen = 0; *p; ) { + while (*p && (*p == ' ' || *p == '\t')) + p++; + if (*p) siglistlen++; + while (*p && (*p != ' ' && *p != '\t')) + p++; + } + /* Allocate storage for siglist. */ + if (siglistlen > maxsiglistlen) { + siglist = realloc(siglist, siglistlen * sizeof(int)); + base = realloc(base, siglistlen * sizeof(int)); + level = realloc(level, siglistlen * sizeof(XSegment)); + maxsiglistlen = siglistlen; + } + /* Now store the signal numbers in siglist. */ + for (p = s, siglistlen = 0; *p && siglistlen < maxsiglistlen; ) { + while (*p && (*p == ' ' || *p == '\t')) + p++; + if (*p) siglist[siglistlen++] = atoi(p); + while (*p && (*p != ' ' && *p != '\t')) + p++; } reset_siglist(); } @@ -795,9 +804,15 @@ void reset_siglist() { if (analyze_popup_active >= 0) { - char *p, sigliststring[WFDB_MAXSIG*4], s[4]; + char *p; int i; + static char *sigliststring; + static int maxrssiglistlen; + if (siglistlen > maxrssiglistlen) { + sigliststring = realloc(sigliststring, 8 * siglistlen); + maxrssiglistlen = siglistlen; + } p = sigliststring; *p = '\0'; for (i = 0; i < siglistlen; i++) { @@ -824,10 +839,16 @@ void add_to_siglist(i) int i; { - if (siglistlen < WFDB_MAXSIG && 0 <= i && i < nsig) { - siglist[siglistlen++] = i; - reset_siglist(); + if (0 <= i && i < nsig) { + if (++siglistlen >= maxsiglistlen) { + siglist = realloc(siglist, siglistlen * sizeof(int)); + base = realloc(base, nsig * sizeof(int)); + level = realloc(level, nsig * sizeof(XSegment)); + maxsiglistlen = siglistlen; + } + siglist[siglistlen-1] = i; } + reset_siglist(); } void delete_from_siglist(i) @@ -875,8 +896,8 @@ p1 = p2 += 6; } else if (strncmp(p1, "ANNOTATOR", 9) == 0) { - if (annotator[0][0]) - ttysw_input(tty, annotator[0], strlen(annotator[0])); + if (annotator[0]) + ttysw_input(tty, annotator, strlen(annotator)); else ttysw_input(tty, "\"\"", 2); p1 = p2 += 9; @@ -1026,10 +1047,10 @@ do_command(mep->nme->command); } -static char *tempfilename; +static char fname[20]; /* This function gets called once per second while the timer is running. - Once the temporary file named by tempfilename contains readable data, it + Once the temporary file named by fname contains readable data, it waits one more second, turns off the timer, and then deletes the file. */ Notify_value check_if_done() @@ -1041,14 +1062,14 @@ if (file_ready) { notify_set_itimer_func(analyze_frame, NOTIFY_FUNC_NULL, ITIMER_REAL, NULL, NULL); - unlink(tempfilename); + unlink(fname); file_ready = 0; reinitialize(); set_start(start_item, (Event *)NULL); set_stop(end_item, (Event *)NULL); return (NOTIFY_DONE); } - if ((tfile = fopen(tempfilename, "r")) == NULL) + if ((tfile = fopen(fname, "r")) == NULL) return (NOTIFY_DONE); fclose(tfile); file_ready++; @@ -1057,13 +1078,13 @@ void reload() { - static char command[80], fname[20]; + static char command[80]; static struct itimerval timer; - char *mktemp(); if (fname[0] == '\0') { sprintf(fname, "/tmp/wave.XXXXXX"); - sprintf(command, "touch %s\n", tempfilename = mktemp(fname)); + mkstemp(fname); + sprintf(command, "touch %s\n", fname); } do_command(command); timer.it_value.tv_sec = timer.it_interval.tv_sec = 1; diff -Naur wfdb-10.1.6/wave/annot.c wfdb-10.2.0/wave/annot.c --- wfdb-10.1.6/wave/annot.c Sun Jan 30 04:13:20 2000 +++ wfdb-10.2.0/wave/annot.c Fri Oct 12 13:36:44 2001 @@ -1,10 +1,10 @@ /* file: annot.c G. Moody 1 May 1990 - Last revised: 7 September 1999 + Last revised: 12 October 2001 Annotation list handling and display functions for WAVE ------------------------------------------------------------------------------- WAVE: Waveform analyzer, viewer, and editor -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -118,9 +118,9 @@ } /* Check that the annotator name, if any, is legal. */ - if (nann > 0 && badname(af[0].name)) { + if (nann > 0 && badname(af.name)) { char ts[ANLMAX+3]; - int dummy = (int)sprintf(ts, "`%s'", af[0].name); + int dummy = (int)sprintf(ts, "`%s'", af.name); #ifdef NOTICE Xv_notice notice = xv_create((Frame)frame, NOTICE, @@ -138,8 +138,8 @@ #ifdef NOTICE xv_destroy_safe(notice); #endif - af[0].name = NULL; - annotator[0][0] = '\0'; + af.name = NULL; + annotator[0] = '\0'; set_annot_item(""); set_frame_title(); return (annotations = 0); @@ -152,7 +152,7 @@ tupdate = time((time_t *)NULL); /* Return 0 if no annotations are requested or available. */ - if (nann < 1 || annopen(record, af, nann) < 0) { + if (nann < 1 || annopen(record, &af, 1) < 0) { ap_start = annp = scope_annp = NULL; if (frame) xv_set(frame, FRAME_BUSY, FALSE, NULL); return (annotations = 0); @@ -901,9 +901,9 @@ /* If there was no annotator name specified, use the name by which this program was invoked for this purpose. */ - if (af[0].name == NULL) { - af[0].name = pname; - strcpy(annotator[0], pname); + if (af.name == NULL) { + af.name = pname; + strcpy(annotator, pname); set_annot_item(pname); } @@ -912,7 +912,7 @@ FILE *tfile; /* Generate a name for the updated annotation file. */ - sprintf(afname, "%s.%s", record, af[0].name); + sprintf(afname, "%s.%s", record, af.name); /* If the file already exists in the current directory, rename it. */ if (tfile = fopen(afname, "r")) { @@ -954,8 +954,8 @@ savebackup = 0; } - af[0].stat = (af[0].stat == WFDB_AHA_READ) ? WFDB_AHA_WRITE : WFDB_WRITE; - if (annopen(record, af, 1)) { + af.stat = (af.stat == WFDB_AHA_READ) ? WFDB_AHA_WRITE : WFDB_WRITE; + if (annopen(record, &af, 1)) { /* An error from annopen is most likely to result from not being able to create the output file. Warn the user and try again later. */ #ifdef NOTICE @@ -985,7 +985,7 @@ exit(1); } } - af[0].stat = (af[0].stat == WFDB_AHA_WRITE) ? WFDB_AHA_READ : WFDB_READ; + af.stat = (af.stat == WFDB_AHA_WRITE) ? WFDB_AHA_READ : WFDB_READ; a = ap_start; /* Write the annotation list to the output file. This might take a while @@ -1047,13 +1047,13 @@ ANLMAX for annotator name, 2 for " " or ") ", DSLMAX for description from log file, 1 for null */ - if (annotator[0][0]) { + if (annotator[0]) { if (changes) sprintf(frame_title, "WAVE %s Record %s(%s) ", WAVEVERSION, - record, annotator[0]); + record, annotator); else sprintf(frame_title, "WAVE %s Record %s %s ", WAVEVERSION, - record, annotator[0]); + record, annotator); } else sprintf(frame_title, "Record %s ", record); diff -Naur wfdb-10.1.6/wave/edit.c wfdb-10.2.0/wave/edit.c --- wfdb-10.1.6/wave/edit.c Wed May 30 11:49:45 2001 +++ wfdb-10.2.0/wave/edit.c Sun Oct 14 14:04:06 2001 @@ -1,5 +1,5 @@ -/* file: edit.c G. Moody 1 May 1990 - Last revised: 30 May 2001 +/* file: edit.c G. Moody 1 May 1990 + Last revised: 14 October 2001 Annotation-editing functions for WAVE ------------------------------------------------------------------------------- @@ -33,14 +33,11 @@ #include #include -WFDB_Sample vref[WFDB_MAXSIG]; WFDB_Time level_time; Frame level_frame; Panel level_panel; -Panel_item level_mode_item, level_time_item, level_name[WFDB_MAXSIG], - level_value[WFDB_MAXSIG], level_units[WFDB_MAXSIG]; -static char level_time_string[36], level_name_string[WFDB_MAXSIG][12], - level_value_string[WFDB_MAXSIG][12], level_units_string[WFDB_MAXSIG][12]; +Panel_item level_mode_item, level_time_item; +static char level_time_string[36]; int bar_on, bar_x, bar_y; int level_mode, level_popup_active = -1; @@ -75,7 +72,6 @@ int stat; { int i, invalid_data; - static WFDB_Sample v[WFDB_MAXSIG]; void create_level_popup(); switch (level_mode) { @@ -98,7 +94,7 @@ level_time - ref_mark_time); break; } - invalid_data = (isigsettime(level_time) < 0 || getvec(v) < 0); + invalid_data = (isigsettime(level_time) < 0 || getvec(level_v) < 0); for (i = 0; i < nsig; i++) { sprintf(level_name_string[i], "%8s: ", signame[i]); if (invalid_data) { @@ -108,22 +104,22 @@ else switch (level_mode) { default: case 0: /* physical units (absolute) */ - sprintf(level_value_string[i], "%8.3lf", aduphys(i, v[i])); + sprintf(level_value_string[i], "%8.3lf", aduphys(i, level_v[i])); sprintf(level_units_string[i], "%s%s", sigunits[i], calibrated[i] ? "" : " *"); break; case 1: /* physical units (relative) */ sprintf(level_value_string[i], "%8.3lf", - aduphys(i, v[i]) - aduphys(i, vref[i])); + aduphys(i, level_v[i]) - aduphys(i, vref[i])); sprintf(level_units_string[i], "%s%s", sigunits[i], calibrated[i] ? "" : " *"); break; case 2: /* raw units (absolute) */ - sprintf(level_value_string[i], "%6d", v[i]); + sprintf(level_value_string[i], "%6d", level_v[i]); sprintf(level_units_string[i], "adu"); break; case 3: /* raw units (relative) */ - sprintf(level_value_string[i], "%6d", v[i] - vref[i]); + sprintf(level_value_string[i], "%6d", level_v[i] - vref[i]); sprintf(level_units_string[i], "adu"); break; } @@ -190,7 +186,7 @@ PANEL_LABEL_BOLD, TRUE, XV_HELP_DATA, "wave:level.time", 0); - for (i = 0; i < nsig; i++) { + for (i = 0; i < nsig; i++) { level_name[i] = xv_create(level_panel, PANEL_MESSAGE, XV_X, xv_col(level_panel, 0), XV_Y, xv_row(level_panel, i+2), @@ -232,7 +228,7 @@ { int ya = y - mmy(8) - 1, yb = y + mmy(5) + 1; static int level_on; - static XSegment bar[2], level[WFDB_MAXSIG]; + static XSegment bar[2]; /* Erase any other bar and levels. */ if (bar_on) { diff -Naur wfdb-10.1.6/wave/faq.hlp wfdb-10.2.0/wave/faq.hlp --- wfdb-10.1.6/wave/faq.hlp Wed May 24 16:38:25 2000 +++ wfdb-10.2.0/wave/faq.hlp Fri Oct 12 13:23:02 2001 @@ -765,12 +765,6 @@ frames. If you have a block-interleaved file, therefore, you may be able to view it with WAVE via this expedient: - * First, check that the block size in samples is no greater than - WFDB_MAXSPF, a symbol defined in the WFDB library header file wfdb.h - (which you will probably find in /usr/include/wfdb). If necessary, - increase the value of WFDB_MAXSPF, recompile and reinstall the shared - WFDB library (libwfdb.so.*), and check to be sure that WAVE loads this - version of the WFDB library (use the command ldd `which wave`). * Write a header file describing the layout of the block-interleaved signal file (see header(5), in the WFDB Applications Guide, for details). The sampling frequency in the first line of the header should be given as the @@ -932,10 +926,8 @@ Can WAVE open more than 32 signals at once? ------------------------------------------- -Not without recompiling. The limit is WFDB_MAXSIG (defined as 32 in -); it is necessary to recompile WAVE itself, as well as the WFDB -library, in order to increase this limit. In a future version, the current -limit of 32 signals will be substantially increased or removed. +Yes. There is no fixed limit on the number of signals that current versions +of WAVE can open. Earlier versions were limited to 32 or fewer signals. Can WAVE open more than one annotation file at once? diff -Naur wfdb-10.1.6/wave/init.c wfdb-10.2.0/wave/init.c --- wfdb-10.1.6/wave/init.c Sat Jul 28 13:09:42 2001 +++ wfdb-10.2.0/wave/init.c Sun Oct 14 14:21:23 2001 @@ -1,5 +1,5 @@ /* file: init.c G. Moody 1 May 1990 - Last revised: 28 July 2001 + Last revised: 14 October 2001 Initialization functions for WAVE ------------------------------------------------------------------------------- @@ -30,7 +30,74 @@ #include "xvwave.h" #include -static struct WFDB_siginfo df[WFDB_MAXSIG]; +static WFDB_Siginfo *df; +static int maxnsig; + +void memerr() +{ +#ifdef NOTICE + Xv_notice notice = xv_create((Frame)frame, + NOTICE, XV_SHOW, TRUE, + NOTICE_MESSAGE_STRINGS, + "Insufficient memory", 0, + NOTICE_BUTTON_YES, "Continue", NULL); + xv_destroy_safe(notice); +#else + (void)notice_prompt((Frame)frame, (Event *)NULL, + NOTICE_MESSAGE_STRINGS, + "Insufficient memory", 0, + NOTICE_BUTTON_YES, "Continue", NULL); +#endif +} + +void alloc_sigdata(ns) +int ns; +{ + int i; + + if ((df = realloc(df, ns * sizeof(WFDB_Siginfo))) == NULL || + (signame = realloc(signame, ns * sizeof(char *))) == NULL || + (sigunits = realloc(sigunits, ns * sizeof(char *))) == NULL || + (calibrated = realloc(calibrated, ns * sizeof(char))) == NULL || + (scope_v = realloc(scope_v, ns * sizeof(WFDB_Sample))) == NULL || + (vref = realloc(vref, ns * sizeof(WFDB_Sample))) == NULL || + (level_v = realloc(level_v, ns * sizeof(WFDB_Sample))) == NULL || + (v = realloc(v, ns * sizeof(WFDB_Sample))) == NULL || + (v0 = realloc(v0, ns * sizeof(WFDB_Sample))) == NULL || + (vmax = realloc(vmax, ns * sizeof(WFDB_Sample))) == NULL || + (vmin = realloc(vmin, ns * sizeof(WFDB_Sample))) == NULL || + (level_name_string = + realloc(level_name_string, ns * sizeof(char **))) == NULL || + (level_value_string = + realloc(level_value_string, ns * sizeof(char **))) == NULL || + (level_units_string = + realloc(level_units_string, ns * sizeof(char **))) == NULL || + (vscale = realloc(vscale, ns * sizeof(double))) == NULL || + (dc_coupled = realloc(dc_coupled, ns * sizeof(int))) == NULL || + (sigbase = realloc(sigbase, ns * sizeof(int))) == NULL || + (blabel = realloc(blabel, ns * sizeof(char *))) == NULL || + (level_name = + realloc(level_name, ns * sizeof(Panel_item))) == NULL || + (level_value = + realloc(level_value, ns * sizeof(Panel_item))) == NULL || + (level_units = + realloc(level_units, ns * sizeof(Panel_item))) == NULL) { + memerr(); + } + for (i = maxnsig; i < ns; i++) { + signame[i] = sigunits[i] = blabel[i] = NULL; + level_name[i] = level_value[i] = level_units[i] = (Panel_item)NULL; + dc_coupled[i] = scope_v[i] = vref[i] = level_v[i] = v[i] = v0[i] = + vmax[i] = vmin[i] = 0; + vscale[i] = 1.0; + if ((level_name_string[i] = calloc(1, 12)) == NULL || + (level_value_string[i] = calloc(1, 12)) == NULL || + (level_units_string[i] = calloc(1, 12)) == NULL) { + memerr(); + } + } + maxnsig = ns; +} /* Open up a new ECG record. */ int record_init(s) @@ -61,8 +128,12 @@ /* Reset the frame title. */ set_frame_title(); + /* Open as many signals as possible. */ - nsig = isigopen(record, df, WFDB_MAXSIG); + nsig = isigopen(record, NULL, 0); + if (nsig > maxnsig) + alloc_sigdata(nsig); + nsig = isigopen(record, df, nsig); /* Get time resolution for annotations in sample intervals. Except in WFDB_HIGHRES mode (selected using the -H option), the resolution is 1 sample interval. In WFDB_HIGHRES mode, when editing a multi-frequency @@ -138,6 +209,12 @@ /* Initialize the signal list unless the new record name matches the old one. */ if (rebuild_list) { + if (nsig > maxsiglistlen) { + siglist = realloc(siglist, nsig * sizeof(int)); + base = realloc(base, nsig * sizeof(int)); + level = realloc(level, nsig * sizeof(XSegment)); + maxsiglistlen = nsig; + } for (i = 0; i < nsig; i++) siglist[i] = i; siglistlen = nsig; diff -Naur wfdb-10.1.6/wave/mainpan.c wfdb-10.2.0/wave/mainpan.c --- wfdb-10.1.6/wave/mainpan.c Sun Jan 30 04:13:21 2000 +++ wfdb-10.2.0/wave/mainpan.c Fri Oct 12 14:24:37 2001 @@ -1,10 +1,10 @@ /* file: mainpan.c G. Moody 30 April 1990 - Last revised: 4 May 1999 + Last revised: 12 October 2001 Functions for the main control panel of WAVE ------------------------------------------------------------------------------- WAVE: Waveform analyzer, viewer, and editor -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -34,6 +34,10 @@ #include #include +#ifdef NOMKSTEMP +#define mkstemp mktemp +#endif + Panel panel; /* main control panel (above ECG window) */ Panel load_panel; /* File menu load command window */ Panel print_setup_panel; /* File menu print setup window */ @@ -115,7 +119,7 @@ PANEL_LABEL_STRING, "Annotator: ", PANEL_VALUE_DISPLAY_LENGTH, 8, PANEL_NOTIFY_PROC, disp_proc, - PANEL_VALUE, annotator[0], + PANEL_VALUE, annotator, 0); xv_create(load_panel, PANEL_BUTTON, PANEL_LABEL_STRING, "Reload", @@ -295,13 +299,13 @@ 0); } -static char *filename, *title; +static char filename[20], *title; static void show_print() { char print_command[128]; - if (filename) { + if (*filename) { if (strncmp(filename, "/tmp/wave-s", 11) == 0) sprintf(print_command, "wfdbdesc $RECORD | %s\n", textprint); else if (strncmp(filename, "/tmp/wave-a", 11) == 0) @@ -407,17 +411,16 @@ &timer, NULL); } -static char command[80], fname[20]; -char *mktemp(); +static char command[80]; static void prop_signals() { - sprintf(fname, "/tmp/wave-s.XXXXXX"); + sprintf(filename, "/tmp/wave-s.XXXXXX"); /* The `echo' is to make sure that something gets written to the file, even if `wfdbdesc' doesn't work (so that check_file doesn't wait forever). */ - sprintf(command, "(wfdbdesc $RECORD; echo =====) >%s\n", - filename=mktemp(fname)); + mkstemp(filename); + sprintf(command, "(wfdbdesc $RECORD; echo =====) >%s\n", filename); do_command(command); title = "Signals"; wait_for_file(); @@ -426,12 +429,13 @@ static void prop_annotations() { post_changes(); - sprintf(fname, "/tmp/wave-a.XXXXXX"); + sprintf(filename, "/tmp/wave-a.XXXXXX"); + mkstemp(filename); sprintf(command, "(sumann -r $RECORD -a $ANNOTATOR; echo =====) >%s\n", - filename=mktemp(fname)); + filename); do_command(command); title = "Annotations"; - wait_for_file(fname); + wait_for_file(); } static void prop_wave() @@ -439,7 +443,6 @@ static char fname[40]; sprintf(fname, "%s/wave/wave.pro", helpdir); - filename = fname; title = "About WAVE"; show_file(); } @@ -700,17 +703,17 @@ } if (!record_init((char *)xv_get(record_item, PANEL_VALUE))) return; - annotator[0][0] = '\0'; /* force re-initialization of annotator if + annotator[0] = '\0'; /* force re-initialization of annotator if record was changed */ savebackup = 1; } /* If a new annotator has been selected, re-initialize. */ if (reload_annotations || - strncmp(annotator[0], (char *)xv_get(annot_item,PANEL_VALUE),ANLMAX)) { - strncpy(annotator[0], (char *)xv_get(annot_item, PANEL_VALUE), ANLMAX); - if (annotator[0][0]) { - af[0].name = annotator[0]; af[0].stat = WFDB_READ; + strncmp(annotator, (char *)xv_get(annot_item,PANEL_VALUE),ANLMAX)) { + strncpy(annotator, (char *)xv_get(annot_item, PANEL_VALUE), ANLMAX); + if (annotator[0]) { + af.name = annotator; af.stat = WFDB_READ; nann = 1; } else @@ -755,7 +758,7 @@ break; case ']': /* Find next occurrence of specified annotation. */ case '[': /* Find previous occurrence of specified annotation. */ - if (annotator[0][0]) { + if (annotator[0]) { char *fp = (char *)xv_get(find_item, PANEL_VALUE); static char auxstr[256]; int mask, noise_mask, target; diff -Naur wfdb-10.1.6/wave/scope.c wfdb-10.2.0/wave/scope.c --- wfdb-10.1.6/wave/scope.c Sun Jan 30 04:13:21 2000 +++ wfdb-10.2.0/wave/scope.c Sun Oct 14 14:35:35 2001 @@ -1,10 +1,10 @@ /* file: scope.c G. Moody 31 July 1991 - Last revised: 4 May 1999 + Last revised: 14 October 2001 Scope window functions for WAVE ------------------------------------------------------------------------------- WAVE: Waveform analyzer, viewer, and editor -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -480,7 +480,7 @@ static int show_this_frame() { static char plane = 3, first_frame = 1; - int i, i0, tt, tt0 = 0, v[WFDB_MAXSIG], v0; + int i, i0, tt, tt0 = 0, v0; long t; if (first_frame && use_overlays) { @@ -494,48 +494,44 @@ tt0 = (int)(-t); t = 0L; } - if (isigsettime(t) < 0 || getvec(v) < 0) return (0); + if (isigsettime(t) < 0 || getvec(scope_v) < 0) return (0); switch (map2(scope_annp->this.anntyp)) { case NORMAL: case LEARN: - v0 = v[signal_choice] * vscale[signal_choice] - v0n; + v0 = scope_v[signal_choice] * vscale[signal_choice] - v0n; break; case FUSION: - v0 = v[signal_choice] * vscale[signal_choice] - v0f; + v0 = scope_v[signal_choice] * vscale[signal_choice] - v0f; break; case PVC: - v0 = v[signal_choice] * vscale[signal_choice] - v0v; + v0 = scope_v[signal_choice] * vscale[signal_choice] - v0v; break; } if (tscale >= 1.0) { /* resolution limited by input data */ for (i = i0 = tt0; i < scope_width; i++) { - if (getvec(v) <= 0) break; - sbuf[i].y = v[signal_choice] * vscale[signal_choice] - v0; + if (getvec(scope_v) <= 0) break; + sbuf[i].y = scope_v[signal_choice] * vscale[signal_choice] - v0; } i--; } else { /* resolution limited by display */ int vmax, vmin, vv, x; - (void)getvec(v); - vmax = vmin = v[signal_choice]; + (void)getvec(scope_v); + vmax = vmin = scope_v[signal_choice]; i = i0 = tt0*tscale; if (i < scope_width) - sbuf[i].y = v[signal_choice] * vscale[signal_choice] - v0; - for (tt = tt0 + 1; i < scope_width && getvec(v) > 0; tt++) { + sbuf[i].y = scope_v[signal_choice] * vscale[signal_choice] - v0; + for (tt = tt0 + 1; i < scope_width && getvec(scope_v) > 0; tt++) { + if (scope_v[signal_choice] > vmax) vmax = scope_v[signal_choice]; + else if (scope_v[signal_choice] i) { i = x; - if (v[signal_choice] > vmax) vmax = v[signal_choice]; - else if (v[signal_choice] < vmin) vmin = v[signal_choice]; if (vmax - vv > vv - vmin) vv = vmin = vmax; else vv = vmax = vmin; sbuf[i].y = vv * vscale[signal_choice] - v0; - } - else { - if (v[signal_choice] > vmax) vmax = v[signal_choice]; - else if (v[signal_choice] < vmin) vmin = v[signal_choice]; } } } diff -Naur wfdb-10.1.6/wave/sig.c wfdb-10.2.0/wave/sig.c --- wfdb-10.1.6/wave/sig.c Tue Mar 14 11:24:06 2000 +++ wfdb-10.2.0/wave/sig.c Sat Oct 13 15:54:49 2001 @@ -1,10 +1,10 @@ /* file: sig.c G. Moody 27 April 1990 - Last revised: 14 March 2000 + Last revised: 13 October 2001 Signal display functions for WAVE ------------------------------------------------------------------------------- WAVE: Waveform analyzer, viewer, and editor -Copyright (C) 2000 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -199,12 +199,9 @@ static int max_nlists = MAX_DISPLAY_LISTS; struct display_list *lp = NULL, *lpl; - if (nsig > WFDB_MAXSIG) return (NULL); - - if (nlists < max_nlists) { - lp = (struct display_list *)calloc(1, sizeof(struct display_list)); - if (lp) nlists++; - } + if (nlists < max_nlists && + (lp = (struct display_list *)calloc(1, sizeof(struct display_list)))) + nlists++; if (lp == NULL) switch (nlists) { case 0: return (NULL); @@ -217,6 +214,15 @@ lpl->next = NULL; break; } + if (lp->nsig < nsig) { + lp->sb = realloc(lp->sb, nsig * sizeof(int)); + lp->vlist = realloc(lp->vlist, nsig * sizeof(XPoint *)); + for (i = lp->nsig; i < nsig; i++) { + lp->sb[i] = 0; + lp->vlist[i] = NULL; + } + lp->nsig = nsig; + } if (canvas_width > vlist_size) vlist_size = canvas_width; @@ -267,7 +273,6 @@ } } lp->next = first_list; - lp->nsig = nsig; lp->npoints = nsamp; lp->xmax = maxx; return (first_list = lp); @@ -283,7 +288,6 @@ long fdl_time; { int c, i, j, x, x0, y, ymax, ymin; - int v[WFDB_MAXSIG], v0[WFDB_MAXSIG], vmax[WFDB_MAXSIG], vmin[WFDB_MAXSIG]; struct display_list *lp; XPoint *tp; @@ -414,7 +418,7 @@ if (canvas_width > vlist_size) { for (lp = first_list; lp; lp = lp->next) { - for (i = 0; i < WFDB_MAXSIG && lp->vlist[i] != NULL; i++) { + for (i = 0; i < lp->nsig && lp->vlist[i] != NULL; i++) { free(lp->vlist[i]); lp->vlist[i] = NULL; } diff -Naur wfdb-10.1.6/wave/wave.c wfdb-10.2.0/wave/wave.c --- wfdb-10.1.6/wave/wave.c Tue May 29 16:25:43 2001 +++ wfdb-10.2.0/wave/wave.c Sun Oct 14 14:23:27 2001 @@ -1,5 +1,5 @@ /* file: wave.c G. Moody 27 April 1990 - Last revised: 29 May 2001 + Last revised: 14 October 2001 main() function for WAVE ------------------------------------------------------------------------------- @@ -27,8 +27,10 @@ */ #include "wave.h" -#include /* for strchr definition */ -#include /* for getpid definition */ +#include "xvwave.h" +#include /* for realloc declaration */ +#include /* for strchr declaration */ +#include /* for getpid declaration */ /* Spot help files for WAVE are located in HELPDIR/wave. Their names are of the form `HELPDIR/wave/*.info'. */ @@ -41,7 +43,7 @@ char *argv[]; { char *wfdbp, *hp, *p, *start_string = NULL, *tp, *getenv(); - int do_demo = 0, i, mode = 0; + int do_demo = 0, i, j, mode = 0; static char *helppath; static int wave_procno; void set_frame_footer(); @@ -135,7 +137,7 @@ pname); exit(1); } - strcpy(annotator[0], argv[i]); + strcpy(annotator, argv[i]); break; case 'd': /* display resolution */ if (strcmp(argv[i], "-dpi")) break; @@ -210,23 +212,33 @@ strcpy(record, argv[i]); break; case 's': /* signal list follows */ - while (++i < argc && *argv[i] != '-') { - int sig; - - sig = atoi(argv[i]); - if (0 <= sig && sig < WFDB_MAXSIG && - siglistlen < WFDB_MAXSIG){ - siglist[siglistlen] = sig; - siglistlen++; - } - } - --i; - if (siglistlen < 1) { + /* count the number of signals */ + for (j = 0; ++i < argc && *argv[i] != '-'; j++) + ; + if (j == 0) { (void)fprintf(stderr, "%s: one or more signal numbers must follow -s\n", pname); exit(1); } + /* allocate storage for the signal list */ + if (siglistlen + j > maxsiglistlen) { + if ((siglist = realloc(siglist, + (siglistlen+j) * sizeof(int))) == NULL || + (base = realloc(base, + (siglistlen+j) * sizeof(int))) == NULL || + (level = realloc(level, + (siglistlen+j) * sizeof(XSegment))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", + pname); + exit(2); + } + maxsiglistlen = siglistlen + j; + } + /* fill the signal list */ + for (i -= j; i < argc && *argv[i] != '-'; ) + siglist[siglistlen++] = atoi(argv[i++]); + i--; sig_mode = 1; /* display listed signals only (may be overridden using -VS 0) */ break; @@ -345,8 +357,8 @@ /* Open the selected record (and annotation file, if specified). */ if (record_init(record)) { - if (annotator[0][0]) { - af[0].name = annotator[0]; af[0].stat = WFDB_READ; + if (annotator[0]) { + af.name = annotator; af.stat = WFDB_READ; nann = 1; annot_init(); } diff -Naur wfdb-10.1.6/wave/wave.h wfdb-10.2.0/wave/wave.h --- wfdb-10.1.6/wave/wave.h Sat Jul 28 12:46:07 2001 +++ wfdb-10.2.0/wave/wave.h Sun Oct 14 14:34:14 2001 @@ -1,5 +1,5 @@ /* file: wave.h G. Moody 26 April 1990 - Last revised: 28 July 2001 + Last revised: 14 October 2001 Constants, macros, global variables, and function prototypes for WAVE ------------------------------------------------------------------------------- @@ -122,9 +122,30 @@ process in this group -- make a sync button on the main panel */ COMMON char record[RNLMAX+1]; /* record name */ -COMMON char *signame[WFDB_MAXSIG]; /* signal names */ -COMMON char *sigunits[WFDB_MAXSIG]; /* signal units */ -COMMON char calibrated[WFDB_MAXSIG]; /* 0: not calibrated, 1: calibrated */ +COMMON char **signame; /* signal names */ +COMMON char **sigunits; /* signal units */ +COMMON char *calibrated; /* 0: not calibrated, 1: calibrated */ +COMMON WFDB_Sample *scope_v; /* sample vector (see scope.c) */ + +COMMON WFDB_Sample *vref; /* see edit.c */ +COMMON WFDB_Sample *level_v; +COMMON char **level_name_string; +COMMON char **level_value_string; +COMMON char **level_units_string; + +COMMON WFDB_Sample *v; /* see sig.c */ +COMMON WFDB_Sample *v0; +COMMON WFDB_Sample *vmax; +COMMON WFDB_Sample *vmin; + +COMMON double *vscale; /* amplitude scales for each signal + (pixels/adu) */ +COMMON int *base; /* baseline ordinate for each signal */ +COMMON int *dc_coupled; /* if non-zero, signal is DC coupled + (i.e., has a defined baseline) */ +COMMON int *sigbase; /* baselines for DC-coupled signals */ +COMMON char **blabel; /* baseline label strings */ + COMMON char *cfname; /* calibration file name */ COMMON char *helpdir; /* name of directory containing on-line help files for WAVE */ @@ -132,9 +153,8 @@ COMMON char description[DSLMAX+1]; /* description from log file */ COMMON int nsig; /* number of signals */ COMMON int nann; /* number of annotators (0 or 1) */ -COMMON char annotator[WFDB_MAXANN][ANLMAX+1];/* annotator names */ -COMMON struct WFDB_anninfo af[WFDB_MAXANN]; /* see ; passed to - annopen */ +COMMON char annotator[ANLMAX+1]; /* annotator name */ +COMMON WFDB_Anninfo af; /* annotator info, passed to annopen */ COMMON int savebackup; /* if non-zero, the current annotation file should be backed up if any edits are made */ @@ -155,17 +175,10 @@ COMMON double freq; /* sampling frequency (Hz) */ COMMON int atimeres; /* annot time resolution in samples */ COMMON double tscale; /* time scale (pixels/samp interval) */ -COMMON double vscale[WFDB_MAXSIG]; /* amplitude scales for each signal - (pixels/adu) */ COMMON double mmpermv; /* amplitude scale for export */ COMMON double mmpersec; /* time scale for export */ -COMMON int base[WFDB_MAXSIG]; /* baseline ordinate for each signal */ COMMON int abase; /* baseline ordinate for annotation display */ -COMMON int dc_coupled[WFDB_MAXSIG]; /* if non-zero, signal is DC coupled - (i.e., has a defined baseline) */ -COMMON int sigbase[WFDB_MAXSIG]; /* baselines for DC-coupled signals */ -COMMON char *blabel[WFDB_MAXSIG]; /* baseline label strings */ COMMON int use_overlays; /* if non-zero, the grid, cursor, annotations, and signals can be erased independently */ @@ -213,9 +226,10 @@ COMMON int fine_grid_mode; /* as above, for use at other times */ COMMON int signal_choice; /* signal to be analyzed (from analyze panel) */ -COMMON int siglist[WFDB_MAXSIG]; /* signals to be analyzed (from analyze +COMMON int *siglist; /* signals to be analyzed (from analyze panel) */ COMMON int siglistlen; /* number of valid siglist entries */ +COMMON int maxsiglistlen; /* length of siglist array */ COMMON int freeze_siglist; /* 1: don't rebuild in record_init */ COMMON int scan_active; /* 1: scope display is running */ diff -Naur wfdb-10.1.6/wave/xvwave.c wfdb-10.2.0/wave/xvwave.c --- wfdb-10.1.6/wave/xvwave.c Sat Jul 28 13:17:46 2001 +++ wfdb-10.2.0/wave/xvwave.c Sun Oct 14 14:34:38 2001 @@ -1,5 +1,5 @@ -/* file: xvwave.c G. Moody 27 April 1990 - Last revised: 28 July 2001 +/* file: xvwave.c G. Moody 27 April 1990 + Last revised: 14 October 2001 XView support functions for WAVE ------------------------------------------------------------------------------- @@ -114,6 +114,8 @@ if (*record) { set_baselines(); dismiss_mode(); /* read and set user-selected scales, if any */ + alloc_sigdata(2); + vscale[0] = 0.; /* force clear_cache() -- see calibrate() */ calibrate(); } @@ -331,7 +333,7 @@ if (p > new_record) p--; *p = '\0'; } - if (*new_annotator && strcmp(annotator[0], new_annotator)) + if (*new_annotator && strcmp(annotator, new_annotator)) set_annot_item(new_annotator); if (*new_time) set_start_time(new_time); @@ -968,8 +970,11 @@ /* Signals are drawn using draw_sig, and erased using clear_sig. */ gcvalues.foreground = pixel_table[signal_color]; gcvalues.plane_mask = use_overlays ? gcvalues.foreground : ~0; + gcvalues.line_width = defaults_get_integer("wave.signalwindow.line_width", + "Wave.SignalWindow.Line_width", + 1); draw_sig = XCreateGC(display, xid, - GCBackground | GCFont| GCForeground | GCPlaneMask, + GCBackground | GCFont | GCForeground | GCPlaneMask | GCLineWidth, &gcvalues); if (use_overlays) { gcvalues.foreground = gcvalues.background; diff -Naur wfdb-10.1.6/wave/xvwave.h wfdb-10.2.0/wave/xvwave.h --- wfdb-10.1.6/wave/xvwave.h Sun Jan 30 04:13:23 2000 +++ wfdb-10.2.0/wave/xvwave.h Sat Oct 13 15:54:01 2001 @@ -1,10 +1,10 @@ /* file: xvwave.h G. Moody 27 April 1990 - Last revised: 29 April 1999 + Last revised: 13 October 2001 XView constants, macros, function prototypes, and global variables for WAVE ------------------------------------------------------------------------------- WAVE: Waveform analyzer, viewer, and editor -Copyright (C) 1999 George B. Moody +Copyright (C) 2001 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -116,10 +116,12 @@ int npoints; /* number of (input) points per signal */ int ndpts; /* number of (output) points per signal */ int xmax; /* largest x, expressed as window abscissa */ - int sb[WFDB_MAXSIG];/* signal baselines, expressed as window ordinates */ - XPoint *vlist[WFDB_MAXSIG]; /* vertex list pointers for each signal */ + int *sb; /* signal baselines, expressed as window ordinates */ + XPoint **vlist; /* vertex list pointers for each signal */ }; COMMON struct display_list *first_list; +COMMON Panel_item *level_name, *level_value, *level_units; /* see edit.c */ +COMMON XSegment *level; /* Function prototypes for ANSI C and C++ compilers. (Most of these are in wave.h; those below are only for functions that use X or XView objects diff -Naur wfdb-10.1.6/wave-doc/guide/wug.tex wfdb-10.2.0/wave-doc/guide/wug.tex --- wfdb-10.1.6/wave-doc/guide/wug.tex Mon Jun 19 15:04:54 2000 +++ wfdb-10.2.0/wave-doc/guide/wug.tex Fri Oct 12 13:24:58 2001 @@ -6062,15 +6062,6 @@ \begin{itemize} \item -First, check that the block size in samples is no greater than {\tt -WFDB\_MAXSPF}, a symbol defined in the WFDB library header file {\tt wfdb.h} -(which you will probably find in {\tt /usr/include/wfdb}). If -necessary, increase the value of {\tt WFDB\_MAXSPF}, recompile and -reinstall the shared WFDB library ({\tt libwfdb.so.*}), and check to be -sure that \WAVE{} loads this version of the WFDB library (use the -command {\tt ldd `which wave`}). - -\item Write a header file describing the layout of the block-interleaved signal file (see \htmladdnormallink{{\tt header(5)}}{../dbag/header-5.htm}, @@ -6286,11 +6277,8 @@ \subsection{Can \WAVE{} open more than 32 signals in a window at once?} -\index{WFDB\_MAXSIG@{\tt WFDB\_MAXSIG}} -Not without recompiling. The limit is {\tt WFDB\_MAXSIG} (defined as 32 in -{\tt }); it is necessary to recompile \WAVE{} itself, as well as -the WFDB library, in order to increase this limit. In a future version, -the current limit of 32 signals will be substantially increased or removed. +Yes. There is no fixed limit on the number of signals that current versions +of \WAVE{} can open. Earlier versions were limited to 32 or fewer signals. \subsection{Can \WAVE{} open more than one annotation file in a window at once?} diff -Naur wfdb-10.1.6/waverc/Makefile wfdb-10.2.0/waverc/Makefile --- wfdb-10.1.6/waverc/Makefile Wed Aug 1 10:28:34 2001 +++ wfdb-10.2.0/waverc/Makefile Mon Oct 15 14:40:00 2001 @@ -25,12 +25,12 @@ # please visit PhysioNet (http://www.physionet.org/). # _____________________________________________________________________________ # file: version.def G. Moody 24 May 2000 -# Last revised: 28 February 2001 +# Last revised: 14 August 2001 # Each release of the WFDB Software Package is identified by a three-part # version number, defined here: MAJOR = 10 -MINOR = 1 -RELEASE = 6 +MINOR = 2 +RELEASE = 0 VERSION = $(MAJOR).$(MINOR).$(RELEASE) # VDEFS is the set of C compiler options needed to set version number variables @@ -38,7 +38,7 @@ VDEFS = -DWFDB_MAJOR=$(MAJOR) -DWFDB_MINOR=$(MINOR) -DWFDB_RELEASE=$(RELEASE) # _____________________________________________________________________________ -PACKAGE=wfdb-10.1.6 +PACKAGE=wfdb-10.2.0 # file: linux.def G. Moody 31 May 2000 # Last revised: 5 June 2000 # 'make' definitions for compiling the WFDB Software Package under Linux diff -Naur wfdb-10.1.6/waverc/wave-remote.c wfdb-10.2.0/waverc/wave-remote.c --- wfdb-10.1.6/waverc/wave-remote.c Tue May 29 16:24:23 2001 +++ wfdb-10.2.0/waverc/wave-remote.c Sun Oct 14 20:49:01 2001 @@ -1,5 +1,5 @@ /* file: wave-remote.c G. Moody 10 October 1996 - Last revised: 29 May 2001 + Last revised: 14 October 2001 Remote control for WAVE ------------------------------------------------------------------------------- @@ -119,7 +119,7 @@ { char fname[30]; FILE *ofile; - int i, j = 0, pid, siglist[WFDB_MAXSIG]; + int i, j = 0, pid, *siglist; static char *ppid, *record, *annotator, *ptime; pname = argv[0]; @@ -157,13 +157,21 @@ } record = argv[i]; break; - case 's': /* signal numbers follow */ - if (++i >= argc) { - fprintf(stderr, "%s: -s must be followed by a signal number\n", - argv[0]); + case 's': /* signal numbers follow */ + /* count the number of output signals */ + for (j = 0; ++i < argc && argv[i][0] != '-'; j++) + ; + if (j == 0) { + fprintf(stderr, "%s: signal list must follow -s\n", argv[0]); exit(1); } - while (i < argc && j < WFDB_MAXSIG && argv[i][0] != '-') + /* allocate storage for the signal list */ + if ((siglist = (int *)malloc((j+1) * sizeof(int))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", argv[0]); + exit(2); + } + /* fill the signal list */ + for (i -= j, j = 0; i < argc && argv[i][0] != '-'; ) siglist[j++] = atoi(argv[i++]); i--; break; diff -Naur wfdb-10.1.6/waverc/wavescript.c wfdb-10.2.0/waverc/wavescript.c --- wfdb-10.1.6/waverc/wavescript.c Wed Aug 1 12:11:27 2001 +++ wfdb-10.2.0/waverc/wavescript.c Sun Oct 14 21:52:27 2001 @@ -1,5 +1,5 @@ /* file: wavescript.c G. Moody 10 October 1996 - Last revised: 1 August 2001 + Last revised: 14 October 2001 Remote control for WAVE via script ------------------------------------------------------------------------------- @@ -127,7 +127,6 @@ #ifndef BINDIR #define BINDIR /usr/bin #endif -#define MAXARGS (WFDB_MAXSIG+12) #define STRING(A) #A #define PATH(A,B) STRING(A) "/" #B @@ -135,9 +134,19 @@ char *record, *annotator, *ptime, **siglist, *path; { if (*record) { - static char *arg[MAXARGS+1]; - int nargs; + char **arg; + int i, nargs; + nargs = 4; + if (*annotator) nargs += 2; + if (*ptime) nargs += 2; + if (*path) nargs += 2; + if (*siglist) { + for (i = 0; siglist[i]; i++) + ; + nargs += i+1; + } + arg = (char **)malloc(nargs * sizeof(char *)); arg[0] = PATH(BINDIR, wave); arg[1] = "-r"; arg[2] = record; @@ -156,7 +165,7 @@ } if (*siglist) { arg[nargs++] = "-s"; - while (nargs < MAXARGS && *siglist) + while (*siglist) arg[nargs++] = *siglist++; } arg[nargs] = NULL; @@ -186,7 +195,7 @@ FILE *ofile = NULL, *script; int i = 0, pid; static char buf[80], record[80], annotator[80], ptime[80], path[80]; - static char *siglist[WFDB_MAXSIG], sigstrings[80]; + static char **siglist, sigstrings[80]; pname = argv[0]; environ = env; @@ -224,14 +233,28 @@ strcpy(sigstrings, q); /* copy the list of signal numbers */ sigstrings[strlen(sigstrings)-1] = ' '; /* append a space */ q = sigstrings; - while (*q && i < WFDB_MAXSIG) { /* split the list into tokens */ - siglist[i++] = q++; /* save pointer to current token */ - while (*q != ' ' && *q != '\t') /* find the end of the token */ - q++; - *q++ = '\0'; /* split the list at the end of the token */ - while (*q == ' ' || *q == '\t') + while (*q) { /* count the tokens in the list */ + while (*q && (*q == ' ' || *q == '\t')) q++; /* look for the next token, if any */ + if (*q) i++; /* count this token */ + while (*q && (*q != ' ' && *q != '\t')) + q++; /* find the end of the token */ } + siglist = (char **)malloc((i+1) * sizeof(char *)); + q = sigstrings; + i = 0; + while (*q) { /* split the list into tokens */ + while (*q && (*q == ' ' || *q == '\t')) + q++; /* look for the next token, if any */ + if (*q) siglist[i++] = q++; /* save pointer to current token */ + while (*q && (*q != ' ' && *q != '\t')) + q++; /* find the end of the token */ + *q++ = '\0'; /* split the list at the end of the token */ + } + siglist[i] = NULL; + break; + default: + break; } } fclose(script); @@ -292,7 +315,7 @@ if (*ptime) fprintf(ofile, "-f %s\n", ptime); if (siglist[0]) { fprintf(ofile, "-s %s", siglist[0]); - for (i = 1; i < WFDB_MAXSIG && siglist[i]; i++) + for (i = 1; siglist[i]; i++) fprintf(ofile, " %s", siglist[i]); fprintf(ofile, "\n"); }