diff -Naur --exclude Makefile --exclude info wfdb-10.4.14/app/Makefile.tpl wfdb-10.4.15/app/Makefile.tpl --- wfdb-10.4.14/app/Makefile.tpl 2009-02-18 18:25:48.000000000 -0500 +++ wfdb-10.4.15/app/Makefile.tpl 2009-02-26 22:39:22.000000000 -0500 @@ -1,5 +1,5 @@ # file: Makefile.tpl G. Moody 23 May 2000 -# Last revised: 18 February 2009 +# Last revised: 26 February 2009 # This section of the Makefile should not need to be changed. CFILES = ann2rr.c bxb.c calsig.c ecgeval.c epicmp.c fir.c ihr.c mfilt.c \ @@ -13,7 +13,7 @@ rdsamp rr2ann rxr sampfreq sigamp sigavg signame signum \ skewedit snip sortann sqrs sqrs125 sumann sumstats tach \ time2sec wabp wfdbcat wfdbcollate wfdbdesc \ - wfdbwhich wqrs wrann wrsamp xform + wfdbtime wfdbwhich wqrs wrann wrsamp xform SCRIPTS = cshsetwfdb setwfdb PSFILES = pschart.pro psfd.pro 12lead.pro MFILES = Makefile diff -Naur --exclude Makefile --exclude info wfdb-10.4.14/checkpkg/expected/lcheck.log-NETFILES wfdb-10.4.15/checkpkg/expected/lcheck.log-NETFILES --- wfdb-10.4.14/checkpkg/expected/lcheck.log-NETFILES 2008-01-04 11:30:38.000000000 -0500 +++ wfdb-10.4.15/checkpkg/expected/lcheck.log-NETFILES 2009-02-24 16:35:07.000000000 -0500 @@ -36,16 +36,16 @@ [OK]: datstr returned ' 31/12/1999' [OK]: iannsettime skipping forward to 0:05 [OK]: getann read: {Y 0 0 0} at 0:05.025 (1809) -[OK]: getann read: {A 0 0 0} at 0:05.677 (2044) +[OK]: getann read: {A 0 0 0} at 0:05.678 (2044) [OK]: getann read: {Y 0 0 0} at 0:06.672 (2402) -[OK]: getann read: {Y 0 0 0} at 0:07.516 (2706) -[OK]: getann read: {Y 0 0 0} at 0:08.327 (2998) +[OK]: getann read: {Y 0 0 0} at 0:07.517 (2706) +[OK]: getann read: {Y 0 0 0} at 0:08.328 (2998) [OK]: iannsettime skipping backward to 0:00 [OK]: 75 annotations read, 75 written [OK]: isigopen(100s, 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.003) getframe returned { 995, 1011} +[OK]: (at 0:00.006) getframe returned { 995, 1011} [OK]: (at 0:00.008) getframe returned { 995, 1011} [OK]: (at 0:00.011) getframe returned { 995, 1011} [OK]: aduphys returned -0.12 @@ -57,15 +57,15 @@ [OK]: timstr returned ' 0:20' [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.003) getvec returned { 942, 945} [-0.410, -0.395] +[OK]: (at 0:20.006) 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.003) getframe returned { 942, 945} +[OK]: (at 0:20.006) 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 @@ -94,16 +94,16 @@ [OK]: datstr returned ' 31/12/1999' [OK]: iannsettime skipping forward to 0:05 [OK]: getann read: {Y 0 0 0} at 0:05.025 (1809) -[OK]: getann read: {A 0 0 0} at 0:05.677 (2044) +[OK]: getann read: {A 0 0 0} at 0:05.678 (2044) [OK]: getann read: {Y 0 0 0} at 0:06.672 (2402) -[OK]: getann read: {Y 0 0 0} at 0:07.516 (2706) -[OK]: getann read: {Y 0 0 0} at 0:08.327 (2998) +[OK]: getann read: {Y 0 0 0} at 0:07.517 (2706) +[OK]: getann read: {Y 0 0 0} at 0:08.328 (2998) [OK]: iannsettime skipping backward to 0:00 [OK]: 75 annotations read, 75 written [OK]: isigopen(udb/100s, 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.003) getframe returned { 995, 1011} +[OK]: (at 0:00.006) getframe returned { 995, 1011} [OK]: (at 0:00.008) getframe returned { 995, 1011} [OK]: (at 0:00.011) getframe returned { 995, 1011} [OK]: aduphys returned -0.12 @@ -115,15 +115,15 @@ [OK]: timstr returned ' 0:20' [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.003) getvec returned { 942, 945} [-0.410, -0.395] +[OK]: (at 0:20.006) 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.003) getframe returned { 942, 945} +[OK]: (at 0:20.006) 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 diff -Naur --exclude Makefile --exclude info wfdb-10.4.14/checkpkg/expected/lcheck.log-no-NETFILES wfdb-10.4.15/checkpkg/expected/lcheck.log-no-NETFILES --- wfdb-10.4.14/checkpkg/expected/lcheck.log-no-NETFILES 2008-01-04 11:30:40.000000000 -0500 +++ wfdb-10.4.15/checkpkg/expected/lcheck.log-no-NETFILES 2009-02-24 16:38:54.000000000 -0500 @@ -36,16 +36,16 @@ [OK]: datstr returned ' 31/12/1999' [OK]: iannsettime skipping forward to 0:05 [OK]: getann read: {Y 0 0 0} at 0:05.025 (1809) -[OK]: getann read: {A 0 0 0} at 0:05.677 (2044) +[OK]: getann read: {A 0 0 0} at 0:05.678 (2044) [OK]: getann read: {Y 0 0 0} at 0:06.672 (2402) -[OK]: getann read: {Y 0 0 0} at 0:07.516 (2706) -[OK]: getann read: {Y 0 0 0} at 0:08.327 (2998) +[OK]: getann read: {Y 0 0 0} at 0:07.517 (2706) +[OK]: getann read: {Y 0 0 0} at 0:08.328 (2998) [OK]: iannsettime skipping backward to 0:00 [OK]: 75 annotations read, 75 written [OK]: isigopen(100s, 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.003) getframe returned { 995, 1011} +[OK]: (at 0:00.006) getframe returned { 995, 1011} [OK]: (at 0:00.008) getframe returned { 995, 1011} [OK]: (at 0:00.011) getframe returned { 995, 1011} [OK]: aduphys returned -0.12 @@ -57,15 +57,15 @@ [OK]: timstr returned ' 0:20' [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.003) getvec returned { 942, 945} [-0.410, -0.395] +[OK]: (at 0:20.006) 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.003) getframe returned { 942, 945} +[OK]: (at 0:20.006) 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 diff -Naur --exclude Makefile --exclude info wfdb-10.4.14/checkpkg/expected/rdann.out wfdb-10.4.15/checkpkg/expected/rdann.out --- wfdb-10.4.14/checkpkg/expected/rdann.out 2001-09-10 00:07:51.000000000 -0400 +++ wfdb-10.4.15/checkpkg/expected/rdann.out 2009-02-24 16:23:22.000000000 -0500 @@ -1,36 +1,36 @@ 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:00.214 77 N 0 0 0 + 0:01.028 370 N 0 0 0 + 0:01.839 662 N 0 0 0 + 0:02.628 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:05.678 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:07.517 2706 N 0 0 0 + 0:08.328 2998 N 0 0 0 + 0:09.117 3282 N 0 0 0 + 0:09.889 3560 N 0 0 0 + 0:10.728 3862 N 0 0 0 0:11.583 4170 N 0 0 0 - 0:12.405 4466 N 0 0 0 + 0:12.406 4466 N 0 0 0 0:13.233 4764 N 0 0 0 - 0:14.055 5060 N 0 0 0 + 0:14.056 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:16.439 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:18.131 6527 N 0 0 0 + 0:18.953 6823 N 0 0 0 + 0:19.739 7106 N 0 0 0 + 0:20.531 7391 N 0 0 0 + 0:21.306 7670 N 0 0 0 + 0:22.092 7953 N 0 0 0 + 0:22.903 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:25.392 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 @@ -38,38 +38,38 @@ 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:31.889 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:33.517 12066 N 0 0 0 + 0:34.306 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:39.253 14131 N 0 0 0 + 0:40.064 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:42.528 15310 N 0 0 0 + 0:43.353 15607 N 0 0 0 + 0:44.164 15899 N 0 0 0 + 0:44.953 16183 N 0 0 0 0:45.733 16464 N 0 0 0 - 0:46.541 16755 N 0 0 0 + 0:46.542 16755 N 0 0 0 0:47.383 17058 N 0 0 0 - 0:48.216 17358 N 0 0 0 + 0:48.217 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:49.853 17947 N 0 0 0 + 0:50.631 18227 N 0 0 0 + 0:51.428 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:53.856 19388 N 0 0 0 + 0:54.703 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:57.881 20837 N 0 0 0 0:58.697 21131 N 0 0 0 0:59.508 21423 N 0 0 0 diff -Naur --exclude Makefile --exclude info wfdb-10.4.14/convert/Makefile.tpl wfdb-10.4.15/convert/Makefile.tpl --- wfdb-10.4.14/convert/Makefile.tpl 2008-07-23 16:15:07.000000000 -0400 +++ wfdb-10.4.15/convert/Makefile.tpl 2009-02-26 18:06:18.000000000 -0500 @@ -3,9 +3,9 @@ # This section of the Makefile should not need to be changed. CFILES = a2m.c ad2m.c ahaecg2mit.c m2a.c md2a.c readid.c makeid.c edf2mit.c \ - mit2edf.c rdedfann.c wav2mit.c mit2wav.c revise.c + mit2edf.c rdedfann.c wav2mit.c mit2wav.c wfdb2mat.c revise.c XFILES = a2m ad2m ahaecg2mit m2a md2a readid makeid edf2mit mit2edf rdedfann \ - wav2mit mit2wav revise + wav2mit mit2wav wfdb2mat revise SCRIPTS = ahaconvert MFILES = Makefile diff -Naur --exclude Makefile --exclude info wfdb-10.4.14/convert/wfdb2mat.c wfdb-10.4.15/convert/wfdb2mat.c --- wfdb-10.4.14/convert/wfdb2mat.c 1969-12-31 19:00:00.000000000 -0500 +++ wfdb-10.4.15/convert/wfdb2mat.c 2009-02-26 18:27:21.000000000 -0500 @@ -0,0 +1,349 @@ +/* file: wfdb2mat.c G. Moody 26 February 2009 + +------------------------------------------------------------------------------- +wfdb2mat: Convert (all or part of) a WFDB signal file to Matlab .mat format +Copyright (C) 2009 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/). +_______________________________________________________________________________ + +This program converts the signals of any PhysioBank record (or one in any +compatible format) into a .mat file that can be read directly using any version +of Matlab, and a short text file containing information about the signals +(names, gains, baselines, units, sampling frequency, and start time/date if +known). If the input record name is REC, the output files are RECm.mat and +RECm.hea. The output files can also be read by any WFDB application as record +RECm. + +This program does not convert annotation files; for that task, 'rdann' is +recommended. + +The output .mat file contains a single matrix named 'val' containing raw +(unshifted, unscaled) samples from the selected record. Using various options, +you can select any time interval within a record, or any subset of the signals, +which can be rearranged as desired within the rows of the matrix. Since .mat +files are written in column-major order (i.e., all of column n precedes all of +column n+1), each vector of samples is written as a column rather than as a +row, so that the column number in the .mat file equals the sample number in the +input record. If this seems odd, transpose your matrix after reading it! + +This program writes version 4 MAT-file format output files, as documented in +http://www.mathworks.com/access/helpdesk/help/pdf_doc/matlab/matfile_format.pdf +The samples are written as 16-bit signed integers in little-endian format +(type=30 below), or as 8-bit unsigned integers (type=50) for records that +contain only 8-bit unsigned samples. + +Although version 5 and newer versions of Matlab normally use a different (less +compact and more complex) format, they can read these files without difficulty. +The advantage of version 4 MAT-file format, apart from compactness and +portability, is that files in these formats are still WFDB-compatible, given +the .hea file constructed by this program. + +Example: + +To convert record mitdb/200, use this command: + wfdb2mat -r mitdb/200 + +This works even if the input files have not been downloaded; in this case, +wfdb2mat reads them directly from the PhysioNet server. + +The output files are mitdb/200m.mat and mitdb/200m.hea. Note that if a +subdirectory named 'mitdb' did not exist already, it would be created by +wfdb2mat. + +*/ + +#include +#include + +char *pname; + +main(argc, argv) +int argc; +char *argv[]; +{ + char *matname, *orec, *p, *record = NULL, *search = NULL, *prog_name(); + static int prolog[6]; /* assumes sizeof(int) == 4; if not true, fix! */ + int highres = 0, i, isiglist, nisig, nosig = 0, pflag = 0, s, *sig = NULL, + type = 50, vflag = 0; + WFDB_Frequency freq; + WFDB_Sample *vi, *vo; + WFDB_Siginfo *si, *so; + WFDB_Time from = 0L, maxl = 0L, t, to = 0L; + void help(); + + pname = prog_name(argv[0]); + for (i = 1 ; i < argc; i++) { + if (*argv[i] == '-') switch (*(argv[i]+1)) { + case 'f': /* starting time */ + if (++i >= argc) { + (void)fprintf(stderr, "%s: time must follow -f\n", pname); + exit(1); + } + from = i; + break; + case 'h': /* help requested */ + help(); + exit(0); + break; + case 'H': /* select high-resolution mode */ + highres = 1; + break; + case 'l': /* maximum length of output follows */ + if (++i >= argc) { + (void)fprintf(stderr, "%s: max output length must follow -l\n", + pname); + exit(1); + } + maxl = i; + break; + case 'r': /* record name */ + if (++i >= argc) { + (void)fprintf(stderr, "%s: record name must follow -r\n", + pname); + exit(1); + } + record = argv[i]; + break; + case 's': /* signal list follows */ + isiglist = i+1; /* index of first argument containing a signal # */ + while (i+1 < argc && *argv[i+1] != '-') { + i++; + nosig++; /* number of elements in signal list */ + } + if (nosig == 0) { + (void)fprintf(stderr, "%s: signal list must follow -s\n", + pname); + exit(1); + } + break; + case 'S': /* search for valid sample of specified signal */ + if (++i >= argc) { + (void)fprintf(stderr, + "%s: signal name or number must follow -S\n", + pname); + exit(1); + } + search = argv[i]; + break; + + case 't': /* end time */ + if (++i >= argc) { + (void)fprintf(stderr, "%s: time must follow -t\n",pname); + exit(1); + } + to = i; + break; + default: + (void)fprintf(stderr, "%s: unrecognized option %s\n", pname, + argv[i]); + exit(1); + } + else { + (void)fprintf(stderr, "%s: unrecognized argument %s\n", pname, + argv[i]); + exit(1); + } + } + if (record == NULL) { + help(); + exit(1); + } + if ((nisig = isigopen(record, NULL, 0)) <= 0) exit(2); + if ((vi = malloc(nisig * sizeof(WFDB_Sample))) == NULL || + (si = malloc(nisig * sizeof(WFDB_Siginfo))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + if ((nisig = isigopen(record, si, nisig)) <= 0) + exit(2); + for (i = 0; i < nisig; i++) + if (si[i].gain == 0.0) si[i].gain = WFDB_DEFGAIN; + if (highres) + setgvmode(WFDB_HIGHRES); + freq = sampfreq(NULL); + if (from > 0L && (from = strtim(argv[from])) < 0L) + from = -from; + if (isigsettime(from) < 0) + exit(2); + if (to > 0L && (to = strtim(argv[to])) < 0L) + to = -to; + + if (nosig) { /* convert samples only from specified signals */ + if ((sig = (int *)malloc((unsigned)nosig*sizeof(int))) == NULL || + (vo = malloc(nosig * sizeof(WFDB_Sample))) == NULL || + (so = malloc((unsigned)nosig * sizeof(WFDB_Siginfo))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + for (i = 0; i < nosig; i++) { + if ((s = findsig(argv[isiglist+i])) < 0) { + (void)fprintf(stderr, "%s: can't read signal '%s'\n", pname, + argv[isiglist+i]); + exit(2); + } + sig[i] = s; + } + } + else { /* convert samples from all signals */ + nosig = nisig; + if ((sig = (int *)malloc((unsigned)nosig*sizeof(int))) == NULL || + (so = malloc((unsigned)nosig * sizeof(WFDB_Siginfo))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + for (i = 0; i < nosig; i++) + sig[i] = i; + } + + /* Reset 'from' if a search was requested. */ + if (search && + ((s = findsig(search)) < 0 || (from = tnextvec(s, from)) < 0)) { + (void)fprintf(stderr, "%s: can't read signal '%s'\n", pname, search); + exit(2); + } + + /* Reset 'to' if a duration limit was specified. */ + if (maxl > 0L && (maxl = strtim(argv[maxl])) < 0L) + maxl = -maxl; + if (maxl && (to == 0L || to > from + maxl)) + to = from + maxl; + + t = strtim("e"); /* the end of the record */ + if (to == 0L || to > t) + to = t; + + /* Quit if there will be no output. */ + if (to <= from) { + wfdbquit(); + fprintf(stderr, "%s: no output\n", pname); + fprintf(stderr, " Use the -f and -t options to specify time limits\n" + "(or type '%s -h' for help)\n", pname); + exit(1); + } + + /* Generate the names for the output .mat file, and the output record. */ + if ((matname = (char *)malloc(strlen(record)+5)) == NULL || + (orec = (char *)malloc(strlen(record)+1)) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + sprintf(orec, "%sm", record); + sprintf(matname, "%s.mat", orec); + + /* Determine if we can write 8-bit unsigned samples, or if 16 bits are + needed per sample. */ + for (i = 0; i < nosig; i++) + if (si[sig[i]].fmt != 80) { type = 30; break; } + for (i = 0; i < nosig; i++) { + so[i] = si[sig[i]]; + so[i].fname = matname; + so[i].fmt = (type == 30) ? 16 : 80; + } + + /* Create an empty .mat file. */ + if (osigfopen(so, nosig) != nosig) { + wfdbquit(); /* failed to open output, quit */ + exit(1); + } + + /* Fill in the .mat file's prolog and write it. */ + prolog[0] = type; /* format */ + prolog[1] = nosig; /* number of rows */ + prolog[2] = to - from; /* number of columns */ + prolog[3] = 0; /* matrix is real */ + prolog[4] = 4; /* strlen("val") + 1 */ + prolog[5] = ((int)'v') | ((int)'a' << 8) | ((int)'l' << 16); /* "val" */ + wfdbputprolog((char *)prolog, sizeof(prolog), 0); + + /* Copy the selected data into the .mat file. */ + for (t = from; from < to && getvec(vi) >= 0; t++) { + for (i = 0; i < nosig; i++) + vo[i] = vi[sig[i]]; + if (putvec(vo) != nosig) + break; + } + + /* Create the new header file. */ + newheader(orec); + if (p = malloc(strlen(record)+40)) { + sprintf(p, "created using wfdb2mat from record %s", record); + putinfo(p); + free(p); + } + + /* Summarize the contents of the .mat file. */ + printf("Generated %s, containing matrix 'val'\n", matname); + printf(" with %d rows and %d columns\n", nosig, to-from); + printf("Duration: %s\n", timstr(to-from)); + printf("Sampling frequency: %g columns/second\n", sampfreq(NULL)); + printf("Row\tSignal\tGain\tBase\tUnits\n"); + for (i = 0; i < nosig; i++) + printf("%d\t%s\t%g\t%d\t%s\n", i+1, so[i].desc, so[i].gain, + so[i].baseline, so[i].units); + printf("\nTo convert from raw units to the physical units shown\n" + "above, subtract 'base' and divide by 'gain'.\n"); + + wfdbquit(); + + exit(0); /*NOTREACHED*/ +} + +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 -r RECORD [OPTIONS ...]\n", + "where RECORD is the name of the input record, and OPTIONS may include:", + " -f TIME begin at specified time", + " -h print this usage summary", + " -H read multifrequency signals in high resolution mode", + " -l INTERVAL truncate output after the specified time interval (hh:mm:ss)", + " -s SIGNAL [SIGNAL ...] convert only the specified signal(s)", + " -S SIGNAL search for a valid sample of the specified SIGNAL at or after", + " the time specified with -f, and begin converting then", + " -t TIME stop at specified time", +"Outputs are written to the current directory as RECORD.mat and RECORDm.hea.", +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]); +} diff -Naur --exclude Makefile --exclude info wfdb-10.4.14/doc/wag-src/wfdb2mat.1 wfdb-10.4.15/doc/wag-src/wfdb2mat.1 --- wfdb-10.4.14/doc/wag-src/wfdb2mat.1 1969-12-31 19:00:00.000000000 -0500 +++ wfdb-10.4.15/doc/wag-src/wfdb2mat.1 2009-02-26 22:17:43.000000000 -0500 @@ -0,0 +1,104 @@ +.TH WFDB2MAT 1 "26 February 2009" "WFDB 10.4.15" "WFDB Applications Guide" +.SH NAME +wfdb2mat \- convert WFDB-compatible signal file to Matlab .mat file +.SH SYNOPSIS +\fBwfdb2mat -i\fR \fIrecord\fR [ \fIoptions\fR ... ] +.SH DESCRIPTION +.PP +This program converts the signals of any PhysioBank record (or one in +any compatible format) into a \fIrecord\fB.mat\fR file that can be +read directly using any version of Matlab, and a short +\fIrecord\fB.hea\fR text file containing information about the signals +(names, gains, baselines, units, sampling frequency, and start +time/date if known). In addition, \fBwfdb2mat\fR writes a brief +summary of this information to the standard output. +.PP +The \fB.mat\fR and \fB.hea\fR output files can also be read by +any WFDB application as record \fIRECm\fR. +.PP +This program does not convert annotation files; for that task, +\fBrdann\fR(1) is recommended. +.PP +The output \fB.mat\fR file contains a single matrix named \fBval\fR, +containing raw (unshifted, unscaled) samples from the selected \fIrecord\fR. +Using various options (below), one can select any time interval within a +record, or any subset of the signals, which can be rearranged as +desired within the rows of the matrix. Since \fB.mat\fR files are written +in column-major order (i.e., all of column \fIn\fR precedes all of column +\fIn+1\fR), each vector of samples is written as a column rather than as a +row, so that the column number in the \fB.mat\fR file equals the sample +number in the input record. If this seems odd, transpose your matrix +after reading it! +.PP +This program writes version 4 MAT-file format output files, as documented in +http://www.mathworks.com/access/helpdesk/help/pdf_doc/matlab/matfile_format.pdf. +The samples are written as 16-bit signed integers in little-endian format, or +as 8-bit unsigned integers for records that contain only 8-bit unsigned samples. +Although version 5 and newer versions of Matlab normally use a different (less +compact and more complex) format, they can read these files without difficulty. +The advantage of version 4 MAT-file format, apart from compactness and +portability, is that files in these formats are still WFDB-compatible, given +the \fB.hea\fR file constructed by this program. +.PP +Options for \fBwfdb2mat\fR include: +.TP +\fB-f\fR \fItime\fR +Begin at the specified \fItime\fR. By default, \fBwfdb2mat\fR starts at the +beginning of the record. +.TP +\fB-h\fR +Print a brief usage summary. +.TP +\fB-H\fR +Read the signal files in high-resolution mode (default: standard mode). +These modes are identical for ordinary records. For multifrequency records, +the standard decimation of oversampled signals to the frame rate is suppressed +in high-resolution mode (rather, all other signals are resampled at the highest +sampling frequency). +.TP +\fB-l\fR \fIinterval\fR +Limit the amount of output to the specified time \fIinterval\fR (in standard +time format; default: no limit). If both \fB-l\fR and \fB-t\fR are used, +\fBwfdb2mat\fR stops at the earlier of the two limits. +.TP +\fB-s\fR \fIsignal-list\fR +Convert only the signals named in the \fIsignal-list\fR (one or more +input signal numbers or names, separated by spaces; default: print all +signals). This option may be used to re-order or duplicate signals. +.TP +\fB-S\fR \fIsignal\fR +Search for the first valid sample of the specified \fIsignal\fR (a signal name +or number) at or following the time specified with \fB-f\fR (or the beginning of +the record if the \fB-f\fR option is not present), and begin converting at that +time. +.TP +\fB-t\fR \fItime\fR +Stop at the specified \fItime\fR. By default, \fBwfdb2mat\fR stops at the end +of the record. +.SS Example +.PP +To convert record \fBmitdb/200\fR, use this command: +.br + \fBwfdb2mat -r mitdb/200\fR +.PP +This works even if the input files have not been downloaded; in this case, +\fBwfdb2mat\fR reads them directly from the PhysioNet server. +.PP +The output files are \fBmitdb/200m.mat\fR and \fBmitdb/200m.hea\fR. Note that +if a subdirectory of the current directory named \fBmitdb\fR did not exist +already, it would be created by \fBwfdb2mat\fR. +.SH ENVIRONMENT +.PP +It may be necessary to set and export the shell variable \fBWFDB\fR (see +\fBsetwfdb\fR(1)). +.SH AVAILABILITY +This program is provided in the \fIconvert\fR directory of the WFDB Software +Package. Run \fBmake\fR in that directory to compile and install it if it +have not been installed already. +.SH SEE ALSO +\fBa2m\fR(1), \fBedf2mit\fR, \fBsnip\fR(1), \fBwav2mit\fR(1), \fBxform\fR(1), +\fBwfdb\fR(3), \fBheader\fR(5) +.SH AUTHOR +George B. Moody (george@mit.edu) +.SH SOURCES +http://www.physionet.org/physiotools/wfdb/convert/wfdb2mat.c diff -Naur --exclude Makefile --exclude info wfdb-10.4.14/doc/wpg-src/wpg0.tex wfdb-10.4.15/doc/wpg-src/wpg0.tex --- wfdb-10.4.14/doc/wpg-src/wpg0.tex 2009-02-18 13:04:40.000000000 -0500 +++ wfdb-10.4.15/doc/wpg-src/wpg0.tex 2009-02-26 19:59:46.000000000 -0500 @@ -510,6 +510,15 @@ WFDB Software Package distribution, for information on any more recent changes that may not be described here. +@unnumberedsubsec Changes in version 10.4.15 + +WFDB library function @code{mstimstr} now outputs time to the nearest +millisecond, rather than truncating its calculation to the next lowest number +of milliseconds. + +A new WFDB library function, @code{wfdbputprolog}, can write a prolog at the +beginning of a signal file. WFDB applications ignore embedded prologs. + @unnumberedsubsec Changes in version 10.4.14 WFDB library function @code{setwfdb()} now exports the WFDB library @@ -3987,6 +3996,7 @@ * wfdbsetskew:: Recording intersignal skew. * wfdbgetstart:: Reading the prolog size in a signal file. * wfdbsetstart:: Recording the prolog size in a signal file. +* wfdbputprolog:: Writing a prolog to a signal file. @end menu @@ -5046,7 +5056,7 @@ version 9.4.) @c @group -@node wfdbsetstart, , wfdbgetstart, miscellaneous functions +@node wfdbsetstart, wfdbputprolog, wfdbgetstart, miscellaneous functions @unnumberedsubsec wfdbsetstart @findex wfdbsetstart (9.4) @cindex byte offset @@ -5069,6 +5079,26 @@ the signals were opened. (This function was first introduced in WFDB library version 9.4.) +@c @group +@node wfdbputprolog, , wfdbgetstart, miscellaneous functions +@unnumberedsubsec wfdbputprolog +@findex wfdbputprolog (10.4.15) +@cindex byte offset +@cindex cruft (in signal files) +@cindex prolog (in signal files) +@cindex start of sample data + +@example +void wfdbputprolog(char *@var{prolog}, long @var{bytes}, WFDB_Signal @var{s}) +@end example +@c @end group + +@noindent +This function writes the specified @var{prolog} of length @var{bytes} to the +signal file for the specified output signal @var{s}, and invokes +@code{wfdbsetstart(}@var{s, bytes}@code{)}. (This function was first +introduced in WFDB library version 10.4.15.) + @node Data Types, Annotation Codes, Functions, Top @chapter Data Types diff -Naur --exclude Makefile --exclude info wfdb-10.4.14/lib/signal.c wfdb-10.4.15/lib/signal.c --- wfdb-10.4.14/lib/signal.c 2009-02-15 12:31:51.000000000 -0500 +++ wfdb-10.4.15/lib/signal.c 2009-02-26 18:09:34.000000000 -0500 @@ -1,5 +1,5 @@ /* file: signal.c G. Moody 13 April 1989 - Last revised: 14 February 2009 wfdblib 10.4.13 + Last revised: 26 February 2009 wfdblib 10.4.15 WFDB library functions for signals _______________________________________________________________________________ @@ -76,6 +76,7 @@ wfdbsetskew [9.4](sets skew to be written by setheader) wfdbgetstart [9.4](returns byte offset of sample 0 within signal file) wfdbsetstart [9.4](sets byte offset to be written by setheader) + wfdbputprolog [10.4.15](writes a prolog to a signal file) getinfo [4.0] (reads a line of info for a record) putinfo [4.0] (writes a line of info for a record) sampfreq (returns the sampling frequency of the specified record) @@ -2846,6 +2847,18 @@ prolog_bytes = bytes; } +FINT wfdbputprolog(char *buf, long int size, WFDB_Signal s) +{ + long int n; + WFDB_Group g = osd[s]->info.group; + + n = wfdb_fwrite(buf, 1, size, ogd[g]->fp); + wfdbsetstart(s, n); + if (n != size) + wfdb_error("wfdbputprolog: only %ld of %ld bytes written\n", n, size); + return (n == size ? 0 : -1); +} + FSTRING getinfo(char *record) { char *p; @@ -2994,7 +3007,8 @@ if (t < 0L) t = -t; /* Convert from sample intervals to seconds. */ s = (long)(t / f); - msec = (int)((t - s*f)*1000/f); + msec = (int)((t - s*f)*1000/f + 0.5); + if (msec == 1000) { msec = 0; s++; } t = s; seconds = t % 60; t /= 60; @@ -3012,7 +3026,8 @@ t = (WFDB_Time)(btime*sfreq/1000.0 + 0.5) - t; /* Convert from sample intervals to seconds. */ s = (long)(t / f); - msec = (int)((t - s*f)*1000/f); + msec = (int)((t - s*f)*1000/f + 0.5); + if (msec == 1000) { msec = 0; s++; } t = s; seconds = t % 60; t /= 60; diff -Naur --exclude Makefile --exclude info wfdb-10.4.14/lib/wfdb.h wfdb-10.4.15/lib/wfdb.h --- wfdb-10.4.14/lib/wfdb.h 2009-02-18 22:47:37.000000000 -0500 +++ wfdb-10.4.15/lib/wfdb.h 2009-02-26 22:52:13.000000000 -0500 @@ -1,5 +1,5 @@ /* file: wfdb.h G. Moody 13 June 1983 - Last revised: 13 February 2009 wfdblib 10.4.13 + Last revised: 13 February 2009 wfdblib 10.4.15 WFDB library type, constant, structure, and function interface definitions _______________________________________________________________________________ @@ -33,7 +33,7 @@ /* WFDB library version. */ #define WFDB_MAJOR 10 #define WFDB_MINOR 4 -#define WFDB_RELEASE 14 +#define WFDB_RELEASE 15 #define WFDB_NETFILES 1 /* if 1, library includes code for HTTP, FTP clients */ #define WFDB_NETFILES_LIBCURL 1 @@ -305,6 +305,7 @@ extern FVOID wfdbsetskew(WFDB_Signal s, int skew); extern FLONGINT wfdbgetstart(WFDB_Signal s); extern FVOID wfdbsetstart(WFDB_Signal s, long bytes); +extern FINT wfdbputprolog(char *prolog, long bytes, WFDB_Signal s); extern FVOID wfdbquit(void); extern FFREQUENCY sampfreq(char *record); extern FINT setsampfreq(WFDB_Frequency sampling_frequency); @@ -336,10 +337,9 @@ strann(), setannstr(), setanndesc(), wfdb_isann(), wfdb_isqrs(), wfdb_setisqrs(), wfdb_map1(), wfdb_setmap1(), wfdb_map2(), wfdb_setmap2(), wfdb_ammap(), wfdb_mamap(), wfdb_annpos(), wfdb_setannpos(), - adumuv(), newheader(), setheader(), - setmsheader(), setsampfreq(), setbasetime(), putinfo(), setibsize(), - setobsize(), calopen(), getcal(), putcal(), newcal(), wfdbgetskew(), - sample_valid(); + adumuv(), newheader(), setheader(), setmsheader(), wfdbputprolog(), + setsampfreq(), setbasetime(), putinfo(), setibsize(), setobsize(), + calopen(), getcal(), putcal(), newcal(), wfdbgetskew(), sample_valid(); extern FLONGINT wfdbgetstart(); extern FSAMPLE muvadu(), physadu(), sample(); extern FSTRING ecgstr(), annstr(), anndesc(), timstr(), mstimstr(), diff -Naur --exclude Makefile --exclude info wfdb-10.4.14/lib/wfdb.h0 wfdb-10.4.15/lib/wfdb.h0 --- wfdb-10.4.14/lib/wfdb.h0 2009-02-13 17:08:29.000000000 -0500 +++ wfdb-10.4.15/lib/wfdb.h0 2009-02-26 18:05:24.000000000 -0500 @@ -1,5 +1,5 @@ /* file: wfdb.h G. Moody 13 June 1983 - Last revised: 13 February 2009 wfdblib 10.4.13 + Last revised: 13 February 2009 wfdblib 10.4.15 WFDB library type, constant, structure, and function interface definitions _______________________________________________________________________________ @@ -305,6 +305,7 @@ extern FVOID wfdbsetskew(WFDB_Signal s, int skew); extern FLONGINT wfdbgetstart(WFDB_Signal s); extern FVOID wfdbsetstart(WFDB_Signal s, long bytes); +extern FINT wfdbputprolog(char *prolog, long bytes, WFDB_Signal s); extern FVOID wfdbquit(void); extern FFREQUENCY sampfreq(char *record); extern FINT setsampfreq(WFDB_Frequency sampling_frequency); @@ -336,10 +337,9 @@ strann(), setannstr(), setanndesc(), wfdb_isann(), wfdb_isqrs(), wfdb_setisqrs(), wfdb_map1(), wfdb_setmap1(), wfdb_map2(), wfdb_setmap2(), wfdb_ammap(), wfdb_mamap(), wfdb_annpos(), wfdb_setannpos(), - adumuv(), newheader(), setheader(), - setmsheader(), setsampfreq(), setbasetime(), putinfo(), setibsize(), - setobsize(), calopen(), getcal(), putcal(), newcal(), wfdbgetskew(), - sample_valid(); + adumuv(), newheader(), setheader(), setmsheader(), wfdbputprolog(), + setsampfreq(), setbasetime(), putinfo(), setibsize(), setobsize(), + calopen(), getcal(), putcal(), newcal(), wfdbgetskew(), sample_valid(); extern FLONGINT wfdbgetstart(); extern FSAMPLE muvadu(), physadu(), sample(); extern FSTRING ecgstr(), annstr(), anndesc(), timstr(), mstimstr(), diff -Naur --exclude Makefile --exclude info wfdb-10.4.14/MANIFEST wfdb-10.4.15/MANIFEST --- wfdb-10.4.14/MANIFEST 2009-02-18 18:35:00.000000000 -0500 +++ wfdb-10.4.15/MANIFEST 2009-02-26 22:18:59.000000000 -0500 @@ -168,6 +168,7 @@ convert/README convert/revise.c convert/wav2mit.c +convert/wfdb2mat.c COPYING data/ data/100a.atr @@ -336,6 +337,7 @@ doc/wag-src/wag.tex doc/wag-src/wav2mit.1 doc/wag-src/wave.1 +doc/wag-src/wfdb2mat.1 doc/wag-src/wfdb.3 doc/wag-src/wfdbcal.5 doc/wag-src/wfdbcat.1 diff -Naur --exclude Makefile --exclude info wfdb-10.4.14/NEWS wfdb-10.4.15/NEWS --- wfdb-10.4.14/NEWS 2009-02-23 10:06:21.000000000 -0500 +++ wfdb-10.4.15/NEWS 2009-02-26 23:06:17.000000000 -0500 @@ -1,14 +1,26 @@ +10.4.15: + WFDB library function mstimstr() now outputs time to the nearest + millisecond, rather than truncating its calculation to the next + lowest number of milliseconds. + + A new WFDB library function, wfdbputprolog(), can write a prolog at the + beginning of a signal file. WFDB applications ignore embedded prologs. + + A new WFDB application, convert/wfdb2mat, can convert all or part of + a WFDB-compatible signal file into a Matlab-compatible .mat file that + remains readable by WFDB applications. + 10.4.14: - WFDB library function setwfdb() now exports the WFDB library environment - variables (WFDB, WFDBCAL, WFDBANNSORT, and WFDBGVMODE) on all modern - platforms, so that a process started by a WFDB application inherits the - WFDB environment of its parent. (This is not possible on platforms - that do not provide a working putenv() function, such as MacOS 9 and - earlier, and 16-bit versions of MS-Windows.) Some previous versions - also included this capability, but the older implementation caused a - memory leak, and it was disabled in version 10.4.6. Thanks to Omar - Abdala and Dan Scott for reporting the problem and help in identifying - its cause. + WFDB library function setwfdb() now exports the WFDB library + environment variables (WFDB, WFDBCAL, WFDBANNSORT, and WFDBGVMODE) on + all modern platforms, so that a process started by a WFDB application + inherits the WFDB environment of its parent. (This is not possible on + platforms that do not provide a working putenv() function, such as + MacOS 9 and earlier, and 16-bit versions of MS-Windows.) Some previous + versions also included this capability, but the older implementation + caused a memory leak, and it was disabled in version 10.4.6. Thanks to + Omar Abdala and Dan Scott for reporting the problem and help in + identifying its cause. A new WFDB application, wfdbtime, is convenient for use in scripts to convert among absolute and elapsed times and times in sample intervals. @@ -17,7 +29,8 @@ A new WFDB library function, tnextvec(), finds the next valid sample from a chosen signal, occurring at or after a specified time. This function is particularly useful when reading variable-layout - multi-segment records that may have lengthy gaps in signals of interest. + multi-segment records that may have lengthy gaps in signals of + interest. For portability, the WFDB library has always stored parameters such as sampling frequency and gain as strings rather than as floating-point @@ -25,13 +38,13 @@ always negligible, it has been observable in the specific case of converting very large time intervals from sample intervals to seconds, when the sampling frequency in Hz cannot be represented exactly in - binary (e.g., if the sampling frequency is once per minute, or 1/60 Hz). - This situation cannot be wholly avoided, but it can be minimized. + binary (e.g., if the sampling frequency is once per minute, or 1/60 + Hz). This situation cannot be wholly avoided, but it can be minimized. Changes in this release, in setheader() and in functions that record time units in annotation files, increase the precision with which - non-integer parameters are recorded, so that loss of precision as - a result of converting them to and from strings should almost never - be observable. + non-integer parameters are recorded, so that loss of precision as a + result of converting them to and from strings should almost never be + observable. Several options have been added to rdsamp, which can now print the time of each sample in a variey of formats, and can use the new diff -Naur --exclude Makefile --exclude info wfdb-10.4.14/wfdb.spec wfdb-10.4.15/wfdb.spec --- wfdb-10.4.14/wfdb.spec 2009-02-18 18:34:05.000000000 -0500 +++ wfdb-10.4.15/wfdb.spec 2009-02-26 22:21:14.000000000 -0500 @@ -15,6 +15,9 @@ BuildRoot: /var/tmp/%{name}-root %changelog +* Thu Feb 29 2009 George B Moody +- added wfdb2mat + * Wed Feb 18 2009 George B Moody - added wfdbtime @@ -192,6 +195,7 @@ %{_bindir}/url_view %{_bindir}/wabp %{_bindir}/wav2mit +%{_bindir}/wfdb2mat %{_bindir}/wfdbcat %{_bindir}/wfdbcollate %{_bindir}/wfdbdesc