diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/app/hrstats.c wfdb-10.5.11/app/hrstats.c --- wfdb-10.5.10/app/hrstats.c 1969-12-31 19:00:00.000000000 -0500 +++ wfdb-10.5.11/app/hrstats.c 2012-04-06 15:15:35.000000000 -0400 @@ -0,0 +1,309 @@ +/* file: hrstats.c G. Moody 18 March 2012 + Last revised: 6 April 2012 +------------------------------------------------------------------------------- +hrstats: Collect and summarize heart rate statistics +Copyright (C) 1985-2012 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 reads an annotation file and produces a uniformly sampled and +smoothed instantaneous heart rate signal, using the IPFM model as originally +implemented in tach.c. In this context, heart rate (HR) is defined as ten +times the number of beat-to-beat (RR) intervals (and fractional intervals) +within a 6-second HR measurement window, including intervals beginning and/or +ending with ectopic beats, and RR intervals are defined by the locations of +consecutive beat annotations in the annotation file. + +The first HR window starts at the beginning of the first RR interval in the +record and ends 6 seconds later. Subsequent HR windows begin at 1-second +intervals following the first, i.e, they overlap by 5/6 (83.33%). HR windows +that contain part or all of a very long (>3 sec) or very short (<0.2 sec) +interval are discarded. All others are used to generate HR measurements that +are accumulated in a histogram with 1 bpm bins. + +When all intervals have been processed, summary statistics calculated from the +histogram are written to the standard output and to a WFDB '.info' file, +in this format: + +
: 71|73/75/81|86 +-1.8 bpm [atr] + +This example is the output of 'hrstats -r mitdb/100 -a atr'. From left to +right, it shows: + the characteristic that is summarized [HR] + extreme low value [in the example, 71] + 5th percentile [73] + mean (trimmed, excluding outliers below 5th or above 95th percentiles) [75] + 95th percentile [81] + extreme high value [86] + sample deviation (of values included in the trimmed mean) [1.8] + units of all statistics [bpm] + source of data [atr annotations] + +Optionally, the HR histogram can also be written to a file containing two +columns separated by a tab. The second column contains the number of +measurements of heart rate falling within 0.5 bpm of the heart rate in the +first column. The histogram includes only heart rates between the extreme +low and extreme high heart rates inclusive. +*/ + +#include +#include +#include +#include + +#define HRMAX 500 /* maximum heart rate (bpm) */ +#define TBMAX 128 /* length of ix[] and tb[] (must be a power of 2) */ + +/* Note that iexcl() and tbeat() must be usable as lvalues! */ +#define iexcl(A) (ix[(A)&(TBMAX-1)]) /* exclude interval A if non-zero */ +#define tbeat(A) (tb[(A)&(TBMAX-1)]) /* time of beat following interval A */ + +char *irec, *aname, *ofname, *pname, *prog_name(); +int hrhist[HRMAX+1], ix[TBMAX], tot, wexcl; +void cleanup(), help(); +WFDB_Anninfo ai; +WFDB_Time tb[TBMAX], getbeat(); + +main(int argc, char **argv) +{ + double dt, left, right, rr, rrcnt, rrmin, rrmax, sps, t; + int i, hr; + long max = 0, min = 0, n; + WFDB_Time tmaxb, tminb; + + pname = prog_name(argv[0]); + + /* Interpret command-line options. */ + for (i = 1; i < argc; i++) { + if (*argv[i] == '-') switch (*(argv[i]+1)) { + case 'a': /* annotator follows */ + if (++i >= argc) { + (void)fprintf(stderr, "%s: annotator must follow -a\n", + pname); + exit(1); + } + ai.name = aname = argv[i]; + break; + case 'h': /* print usage summary and quit */ + help(); + exit(0); + break; + case 'o': /* histogram output file name follows */ + if (++i >= argc) { + (void)fprintf(stderr, + "%s: histogram output file name must follow -o\n", + pname); + exit(1); + } + ofname = argv[i]; + break; + case 'r': /* input record name follows */ + if (++i >= argc) { + (void)fprintf(stderr, "%s: input record name must follow -r\n", + pname); + exit(1); + } + irec = argv[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 (irec == NULL || ai.name == NULL) { + help(); + exit(1); + } + + if ((sps = sampfreq(irec)) <= 0.) { + (void)setsampfreq(sps = WFDB_DEFFREQ); + fprintf(stderr, + "%s (warning): sampling frequency unspecified for record %s," + "(assuming %g Hz)\n", + pname, irec, sps); + } + dt = 3 * sps; /* window half-width */ + rrmax = 3 * sps; /* maximum valid RR interval */ + rrmin = 0.2 * sps; /* minimum valid RR interval */ + tbeat(-1) = -1; /* avoid division by zero if tbeat(0) is 0 */ + + ai.stat = WFDB_READ; + if (annopen(irec, &ai, 1) < 0) /* open annotation file */ + exit(2); + + /* Start with the left edge of the window at the time of the first beat, + then read and process the remainder of the annotations. */ + for (tbeat(min) = getbeat(), t = tbeat(min)+dt; max-min < TBMAX; t += sps) { + /* Reset the window limits. */ + left = t - dt; right = t + dt; + + /* read additional beats as needed to fill the window */ + while ((tmaxb = tbeat(max)) <= right) { + tbeat(++max) = getbeat(); + rr = tbeat(max) - tbeat(max-1); + /* interval is invalid if not in bounds */ + iexcl(max) = !(rrmin < rr && rr < rrmax); + /* window is invalid if it includes any invalid intervals */ + wexcl += iexcl(max); + } + + /* advance min as needed until tbeat(min) is in the window */ + while ((tminb = tbeat(min)) <= left) + wexcl -= iexcl(min++); + if (wexcl == 0) { /* all intervals in the window are valid */ + /* get the whole and fractional number of intervals in the window */ + rrcnt = max - min + (tminb - left) / (tminb - tbeat(min-1)) + - (tmaxb - right) / (tmaxb - tbeat(max-1)); + hr = (int)(10 * rrcnt + 0.5); /* multiply beats in 6 seconds by + 10 to get beats per minute */ + if (hr > HRMAX) hr = HRMAX; + hrhist[hr]++; + tot++; + } + } + if (max >= min + TBMAX) { + fprintf(stderr, "%s: annotation buffer overflow\n", pname); + cleanup(); + } +} + +WFDB_Time getbeat() +{ + int stat; + WFDB_Annotation annot; + + while ((stat = getann(0, &annot)) >= 0 && !isqrs(annot.anntyp)) + ; + if (stat < 0) + cleanup(); + return (annot.time); +} + +void cleanup() +{ + char hrbuf[80]; + double mean, sampdev, ssum, sum, target; + int extreme_high, extreme_low, i, imean, max95, min5, n, outliers; + + wfdbquit(); + + /* derive statistics from histograms */ + for (i = 0; i <= HRMAX; i++) + if (hrhist[i]) break; + if (i > HRMAX) { + fprintf(stderr, "%s: no HR data for record %s, annotator %s\n", + pname, irec, aname); + exit(1); + } + extreme_low = i; + + for (i = HRMAX; i >= extreme_low; i--) + if (hrhist[i]) break; + extreme_high = i; + + /* if requested, write histogram to specified file */ + if (ofname) { + FILE *ofile; + + if ((ofile = fopen(ofname, "wt")) == NULL) { + fprintf(stderr, "%s: can't write %s\n", pname, ofname); + } + else { + for (i = extreme_low; i <= extreme_high; i++) + fprintf(ofile, "%d\t%d\n", i, hrhist[i]); + fclose(ofile); + } + } + + for (i = extreme_low, n = 0, target = 0.05 * tot; n <= target; i++) + n += hrhist[i]; + /* Adjust the count in the 5th percentile bin so that exactly 5% of + the lowest values are excluded from the mean. */ + hrhist[--i] = n - target; + min5 = i; /* 5th percentile */ + + for (i = extreme_high, n = 0; n <= target; i--) + n += hrhist[i]; + /* Adjust the count in the 95th percentile bin so that exactly 5% of + the highest values are excluded from the mean. */ + hrhist[++i] = n - target; + max95 = i; /* 95th percentile */ + + for (i = min5, n = sum = 0; i <= max95; i++) { + n += hrhist[i]; + sum += hrhist[i]*i; + } + mean = sum / n; + imean = (int)(mean + 0.5); + + for (i = min5, ssum = 0; i <= max95; i++) + ssum += hrhist[i] * (i - mean) * (i - mean); + sampdev = sqrt(ssum / n); + + /* write statistics to standard output */ + sprintf(hrbuf, "
: %d|%d/%d/%d|%d +-%.2g bpm [%s]", + extreme_low, min5, imean, max95, extreme_high, sampdev, aname); + printf("%s\n", hrbuf); + setinfo(irec); + putinfo(hrbuf); + exit(0); +} + +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 -a ANNOTATOR [OPTIONS ...]\n", + "where RECORD and ANNOTATOR specify the input; OPTIONS may include any of:", +" -h print this usage summary", +" -o HISTFILE save histogram in HISTFILE", +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.5.10/app/Makefile.tpl wfdb-10.5.11/app/Makefile.tpl --- wfdb-10.5.10/app/Makefile.tpl 2011-11-16 14:47:07.000000000 -0500 +++ wfdb-10.5.11/app/Makefile.tpl 2012-04-06 15:04:13.000000000 -0400 @@ -1,19 +1,19 @@ # file: Makefile.tpl G. Moody 23 May 2000 -# Last revised: 16 November 2011 +# Last revised: 6 April 2012 # 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 \ - mrgann.c mxm.c nguess.c nst.c plotstm.c pscgen.c pschart.c psfd.c rdann.c \ - rdsamp.c rr2ann.c rxr.c sampfreq.c sigamp.c sigavg.c signame.c signum.c \ - skewedit.c snip.c sortann.c sqrs.c sqrs125.c sumann.c sumstats.c tach.c \ - time2sec.c wabp.c wfdb-config.c wfdbcat.c wfdbcollate.c wfdbdesc.c \ +CFILES = ann2rr.c bxb.c calsig.c ecgeval.c epicmp.c fir.c hrstats.c ihr.c \ + mfilt.c mrgann.c mxm.c nguess.c nst.c plotstm.c pscgen.c pschart.c psfd.c \ + rdann.c rdsamp.c rr2ann.c rxr.c sampfreq.c sigamp.c sigavg.c signame.c \ + signum.c skewedit.c snip.c sortann.c sqrs.c sqrs125.c sumann.c sumstats.c \ + tach.c time2sec.c wabp.c wfdb-config.c wfdbcat.c wfdbcollate.c wfdbdesc.c \ wfdbmap.c wfdbsignals.c wfdbtime.c wfdbwhich.c wqrs.c wrann.c wrsamp.c xform.c HFILES = signal-colors.h -XFILES = ann2rr bxb calsig ecgeval epicmp fir ihr mfilt \ - mrgann mxm nguess nst plotstm pscgen pschart psfd rdann \ - rdsamp rr2ann rxr sampfreq sigamp sigavg signame signum \ - skewedit snip sortann sqrs sqrs125 sumann sumstats tach \ - time2sec wabp wfdb-config wfdbcat wfdbcollate wfdbdesc \ +XFILES = ann2rr bxb calsig ecgeval epicmp fir hrstats ihr \ + mfilt mrgann mxm nguess nst plotstm pscgen pschart psfd \ + rdann rdsamp rr2ann rxr sampfreq sigamp sigavg signame \ + signum skewedit snip sortann sqrs sqrs125 sumann sumstats \ + tach time2sec wabp wfdb-config wfdbcat wfdbcollate wfdbdesc \ wfdbmap wfdbsignals wfdbtime wfdbwhich wqrs wrann wrsamp xform SCRIPTS = cshsetwfdb setwfdb PSFILES = pschart.pro psfd.pro 12lead.pro @@ -73,6 +73,8 @@ bxb: bxb.c $(CC) $(CFLAGS) bxb.c -o $@ $(LDFLAGS) -lm +hrstats: hrstats.c + $(CC) $(CFLAGS) hrstats.c -o $@ $(LDFLAGS) -lm mxm: mxm.c $(CC) $(CFLAGS) mxm.c -o $@ $(LDFLAGS) -lm nguess: nguess.c diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/app/snip.c wfdb-10.5.11/app/snip.c --- wfdb-10.5.10/app/snip.c 2011-08-05 16:53:30.000000000 -0400 +++ wfdb-10.5.11/app/snip.c 2012-03-21 00:49:45.000000000 -0400 @@ -1,8 +1,8 @@ /* file: snip.c G. Moody 30 July 1989 - Last revised: 27 July 2010 + Last revised: 20 March 2012 ------------------------------------------------------------------------------- snip: Copy an excerpt of a database record -Copyright (C) 1989-2010 George B. Moody +Copyright (C) 1989-2012 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 @@ -225,7 +225,7 @@ void copy_sig(char *nrec, char *irec, WFDB_Time from, WFDB_Time to, int recurse) { char *ofname, *p, tstring[24]; - int i, j, nsig, maxseg; + int i, j, nsig, maxseg, maxres, fmt; long nsamp; WFDB_Sample *v; WFDB_Siginfo *si; @@ -292,7 +292,11 @@ si[i].cksum = 0; } - if (tstring[0]) setbasetime(tstring); + if (tstring[0]) { + static char tstring_copy[24]; + strcpy(tstring_copy, tstring); + setbasetime(tstring_copy); + } if (0 > setheader(olrecname, si, nsig)) { fprintf(stderr, "%s: can't create layout header\n", pname); @@ -363,12 +367,37 @@ return; } + /* Choose an output format */ + maxres = si[0].adcres; + fmt = si[0].fmt; + for (i = 1; i < nsig; i++) { + if (si[i].adcres > maxres) + maxres = si[i].adcres; + if (si[i].fmt != fmt) + fmt = 0; + } + + if (fmt == 0) { + if (maxres > 24) + fmt = 32; + else if (maxres > 16) + fmt = 24; + else if (maxres > 12) + fmt = 16; + else if (maxres > 10) + fmt = 212; + else if (maxres > 8) + fmt = 310; + else + fmt = 80; + } + /* 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; + si[i].fmt = fmt; } if (osigfopen(si, (unsigned)nsig) != nsig) exit(2); diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/app/wfdbdesc.c wfdb-10.5.11/app/wfdbdesc.c --- wfdb-10.5.10/app/wfdbdesc.c 2009-03-14 16:35:40.000000000 -0400 +++ wfdb-10.5.11/app/wfdbdesc.c 2012-04-06 13:33:11.000000000 -0400 @@ -1,9 +1,9 @@ /* file: wfdbdesc.c G. Moody June 1989 - Last revised: 14 March 2009 + Last revised: 6 April 2012 ------------------------------------------------------------------------------- wfdbdesc: Describe signal specifications -Copyright (C) 1989-2009 George B. Moody +Copyright (C) 1989-2012 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 @@ -76,7 +76,7 @@ (void)printf("----------------------------------------------"); } } - if (info = getinfo((char *)NULL)) { + if (info = getinfo(argv[1])) { (void)printf("\nNotes\n=====\n"); do { puts(info); diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/checkpkg/expected/lcheck_cal wfdb-10.5.11/checkpkg/expected/lcheck_cal --- wfdb-10.5.10/checkpkg/expected/lcheck_cal 2010-11-22 09:11:53.000000000 -0500 +++ wfdb-10.5.11/checkpkg/expected/lcheck_cal 2012-04-06 13:13:06.000000000 -0400 @@ -24,11 +24,13 @@ HR 0 100 square 100 bpm PULSE 0 - undefined 100 bpm PR 0 - undefined 100 BPM +Pulse 0 - undefined 100 1/min RESP 0 - undefined 50 bpm SpO2 0 - undefined 10 % Tblood 0 - undefined 1 degC Temp 0 - undefined 1 degC -C.O. 0 - undefined 1 lpm +C.O. 0 - undefined 5 lpm +CO 0 - undefined 5 Lpm PAWP 0 - undefined 10 mmHg MCL - 2 square 1 mV aV - 2 square 1 mV @@ -42,6 +44,7 @@ CS - - undefined 1 mV Thorax - - undefined 2 mV Abdomen - - undefined 200 uV +AV - 1 square 1 mV F - - undefined 100 uV C - - undefined 100 uV A - - undefined 100 uV diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/data/wfdbcal wfdb-10.5.11/data/wfdbcal --- wfdb-10.5.10/data/wfdbcal 2010-10-25 11:05:23.000000000 -0400 +++ wfdb-10.5.11/data/wfdbcal 2012-03-21 09:51:31.000000000 -0400 @@ -1,5 +1,5 @@ # file: wfdbcal G. Moody June 1991 -# Last revised: 14 March 2008 +# Last revised: 21 March 2012 # Default calibration database for WFDB library # # Format: @@ -41,11 +41,13 @@ HR 0 100 square 100 bpm PULSE 0 - undefined 100 bpm PR 0 - undefined 100 BPM +Pulse 0 - undefined 100 1/min RESP 0 - undefined 50 bpm SpO2 0 - undefined 10 % Tblood 0 - undefined 1 degC Temp 0 - undefined 1 degC -C.O. 0 - undefined 1 lpm +C.O. 0 - undefined 5 lpm +CO 0 - undefined 5 Lpm PAWP 0 - undefined 10 mmHg # Special definitions for MIMIC Database ECG signals with 2 mV peak-to-peak @@ -73,6 +75,9 @@ Thorax - - undefined 2 mV Abdomen - - undefined 200 uV +# ECG from INCART database +AV - 1 square 1 mV + # EEG F - - undefined 100 uV C - - undefined 100 uV diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/doc/wag-src/hrstats.1 wfdb-10.5.11/doc/wag-src/hrstats.1 --- wfdb-10.5.10/doc/wag-src/hrstats.1 1969-12-31 19:00:00.000000000 -0500 +++ wfdb-10.5.11/doc/wag-src/hrstats.1 2012-04-06 15:15:28.000000000 -0400 @@ -0,0 +1,72 @@ +.TH HRSTATS 1 "6 April 2012" "WFDB 10.5.11" "WFDB Applications Guide" +.SH NAME +hrstats \- collect and summarize heart rate statistics from an annotation file +.SH SYNOPSIS +\fBhrstats -r\fR \fIrecord\fR \fB-a\fR \fIannotator\fR [ \fIoptions\fR ... ] +.SH DESCRIPTION +\fBhrstats\fR reads the annotation file specified by \fIrecord\fR and +\fIannotator\fR and produces a uniformly sampled and +smoothed instantaneous heart rate signal, using the IPFM model as originally +implemented in tach.c. In this context, heart rate (HR) is defined as ten +times the number of beat-to-beat (RR) intervals (and fractional intervals) +within a 6-second HR measurement window, including intervals beginning and/or +ending with ectopic beats, and RR intervals are defined by the locations of +consecutive beat annotations in the annotation file. +.PP +The first HR window starts at the beginning of the first RR interval in the +record and ends 6 seconds later. Subsequent HR windows begin at 1-second +intervals following the first, i.e, they overlap by 5/6 (83.33%). HR windows +that contain part or all of a very long (>3 sec) or very short (<0.2 sec) +interval are discarded. All others are used to generate HR measurements that +are accumulated in a histogram with 1 bpm bins. +.PP +When all intervals have been processed, summary statistics calculated from the +histogram are written to the standard output and to a WFDB '.info' file, +in this format: +.IP +
: 71|73/75/81|86 +-1.8 bpm [atr] +.PP +This example is the output of 'hrstats -r mitdb/100 -a atr'. From left to +right, it shows: +.IP + the characteristic that is summarized [HR] +.br + extreme low value [in the example, 71] +.br + 5th percentile [73] +.br + mean (trimmed, excluding outliers below 5th or above 95th percentiles) [75] +.br + 95th percentile [81] +.br + extreme high value [86] +.br + sample deviation (of values included in the trimmed mean) [1.8] +.br + units of all statistics [bpm] +.br + source of data [atr annotations] +.PP +Optionally, the HR histogram can also be written to a file containing two +columns separated by a tab. The second column contains the number of +measurements of heart rate falling within 0.5 bpm of the heart rate in the +first column. The histogram includes only heart rates between the extreme +low and extreme high heart rates inclusive. +.PP +\fIOptions\fR include: +.TP +\fB-h\fR +Print a usage summary. +.TP +\fB-o\fR \fIfile\fR +Write the HR histogram to the specified \fIfile\fR. +.SH ENVIRONMENT +.PP +It may be necessary to set and export the shell variable \fBWFDB\fR (see +\fBsetwfdb\fR(1)). +.SH SEE ALSO +\fBihr\fR(1), \fBtach\fR(1) +.SH AUTHOR +George B. Moody (george@mit.edu) +.SH SOURCE +http://www.physionet.org/physiotools/wfdb/app/hrstats.c diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/doc/wag-src/wag.ht0 wfdb-10.5.11/doc/wag-src/wag.ht0 --- wfdb-10.5.10/doc/wag-src/wag.ht0 2010-03-17 14:15:15.000000000 -0400 +++ wfdb-10.5.11/doc/wag-src/wag.ht0 2012-04-09 12:01:02.000000000 -0400 @@ -20,7 +20,7 @@ George B. Moody
Harvard-MIT Division of Health Sciences and Technology

-Copyright ©1980-2010 George B. Moody +Copyright ©1980-2012 George B. Moody

The most recent versions of the programs described in this guide may be freely downloaded from PhysioNet. For diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/doc/wag-src/wag.tex wfdb-10.5.11/doc/wag-src/wag.tex --- wfdb-10.5.10/doc/wag-src/wag.tex 2010-03-17 14:14:43.000000000 -0400 +++ wfdb-10.5.11/doc/wag-src/wag.tex 2012-04-09 12:01:07.000000000 -0400 @@ -36,7 +36,7 @@ \pagestyle{empty} \vspace*{\fill} \noindent -Copyright \copyright 1980 -- 2010 George B. Moody +Copyright \copyright 1980 -- 2012 George B. Moody \vspace{1 in} \noindent diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/doc/wpg-src/wpg0.tex wfdb-10.5.11/doc/wpg-src/wpg0.tex --- wfdb-10.5.10/doc/wpg-src/wpg0.tex 2011-11-15 15:49:06.000000000 -0500 +++ wfdb-10.5.11/doc/wpg-src/wpg0.tex 2012-04-09 13:07:46.000000000 -0400 @@ -21,7 +21,7 @@ @center Harvard-MIT Division of Health Sciences and Technology @page @vskip 0pt plus 1filll -Copyright @copyright{} 1980 -- 2011 George B. Moody +Copyright @copyright{} 1980 -- 2012 George B. Moody @sp 2 The most recent versions of the software described in this guide may be downloaded from @uref{http://physionet.org/}. @@ -3338,6 +3338,8 @@ samples. * getinfo:: Reading info strings from a @file{hea} file. * putinfo:: Writing info strings into a @file{hea} file. +* setinfo:: Opening an info file for output. +* wfdb_freeinfo:: Freeing memory allocated for info strings. * setibsize:: Setting the default input buffer size. * setobsize:: Setting the default output buffer size. * wfdbgetskew:: Reading intersignal skew. @@ -4184,14 +4186,17 @@ @c @end group @noindent -This function reads an ``info'' string from the @file{hea} file for -the specified @var{record}. If @var{record} is @code{NULL}, then -@code{getinfo} reads the next available info string for the currently -open record. Info strings are null-terminated and do not -contain newline characters. The @file{hea} files of some records may -contain no info strings; others may contain more than one info string. -For example, the following code fragment may be used to read and print -all of the info for record @file{100s}: +If @var{record} is not @code{NULL}, @code{getinfo} reads the first ``info'' +string for @var{record}. If @var{record} is @code{NULL}, then @code{getinfo} +reads the next available info string for the currently open record. Info +strings are null-terminated and do not contain newline characters. Some +records may contain no info strings; others may contain more than one info +string. They may be stored within @file{hea} or @file{info} files; if any are +contained in a record's @file{hea} file, they are returned first. + +@noindent +For example, the following code fragment may be used to read and print all of +the info for record @file{100s}: @example @dots{} @@ -4224,7 +4229,7 @@ (This function was first introduced in WFDB library version 4.0.) @c @group -@node putinfo, setibsize, getinfo, miscellaneous functions +@node putinfo, setinfo, getinfo, miscellaneous functions @unnumberedsubsec putinfo @findex putinfo (4.0) @cindex header info (writing) @@ -4244,18 +4249,71 @@ @c @end group @noindent -This function writes @var{s} as an ``info'' string into the -@file{hea} file that was created by the most recent invocation of -@code{newheader}. The string argument, @var{s}, must be null-terminated -and should not contain newline characters. No more than 254 characters -may be written in a single invocation of @code{putinfo}. Two or more -info strings may be written to the same header by successive -invocations of @code{putinfo}. Note that @code{newheader} or -@code{setheader} must be used before @code{putinfo}. (This function was -first introduced in WFDB library version 4.0.) +This function writes @var{s} as an ``info'' string associated with the current +output record. If @code{setinfo} has been called more recently than +@code{newheader} or @code{setheader}, the info string is written to the +@file{info} file; otherwise, it is written to the @file{hea} file, unless none +of these three functions has been called (which results in an error). The +string argument, @var{s}, must be null-terminated and should not contain +newline characters. No more than 254 characters may be written in a single +invocation of @code{putinfo}. Two or more info strings may be written to the +same header or info file by successive invocations of @code{putinfo}. +(This function was first introduced in WFDB library version 4.0.) + +@c @group +@node setinfo, wfdb_freeinfo, putinfo, miscellaneous functions +@unnumberedsubsec setinfo +@findex setinfo (10.5.11) +@cindex info file (creating) + +@example +int setinfo(int @var{record}) +@end example +@noindent +@strong{Return:} +@table @asis +@item @t{0} +Success +@item @t{-1} +Failure: illegal record name, or info file could not be opened +@end table +@c @end group + +@noindent +This function opens the @file{info} file for the specified @var{record} for +writing using @code{putinfo}. If @var{record}.@code{info} does not exist in +the current directory, it is created; otherwise, it is opened for appending +(i.e., so that anything @code{putinfo} writes is added at the end of the +file rather than overwriting any existing contents). + +@noindent +The file opened by @code{setinfo} can be used to store arbitrary information +associated with @var{record}, without altering @var{record}'s header file. +(@code{setinfo} was first introduced in WFDB library version 10.5.11.) + +@c @group +@node wfdb_freeinfo, setibsize, setinfo, miscellaneous functions +@unnumberedsubsec wfdb_freeinfo +@findex wfdb_freeinfo (10.5.11) +@cindex info (memory deallocation) +@cindex memory deallocation +@cindex freeing memory + +@example +void wfdb_freeinfo() +@end example +@c @end group + +@noindent +This function releases memory allocated by @code{getinfo}, and closes +the file opened by @code{setinfo}, if any. After calling it, @code{getinfo} +behaves as it does on its initial call, (re)reading the info for the specified +record (or the currently open record, if no record is specified). +@code{wfdb_freeinfo} is invoked by @code{wfdbquit}. +(This function was first introduced in WFDB library version 10.5.11.) @c @group -@node setibsize, setobsize, putinfo, miscellaneous functions +@node setibsize, setobsize, wfdb_freeinfo, miscellaneous functions @unnumberedsubsec setibsize @findex setibsize (5.0) @cindex buffer size (setting) @@ -8990,6 +9048,43 @@ @unnumberedsec WFDB 10.5 +@unnumberedsubsec Changes in version 10.5.11 (6 April 2012) + +This release of the WFDB library introduces support for @file{.info} files. +These are files containing 'info' strings in the same format as those that can +be stored in @file{.hea} files. The @file{.info} file for a record named +@file{record} is named @file{record.info}, and it may be located anywhere in +the WFDB path. Function @code{getinfo()}, as in previous releases, returns +the first info string belonging to the record named as its argument, or the +next info string belonging to the previously specified record if its argument +is NULL. Beginning with this release, successive calls to @code{getinfo()} +return the next info string contained in the record's @file{.info} file if it +exists, and if there are no more in the record's @file{.hea} file. Function +@code{putinfo()} writes an info string to the currently open output @file{.hea} +file, unless function @code{setinfo()} (new in this release) has been invoked, +in which case the info string is appended to the record's @file{.info} file +in the current directory. @code{getinfo()} reads all of the record's info +strings the first time it is invoked, returning them one at a time; +@code{wfdb_freeinfo()} frees the memory allocated for @code{getinfo()}'s info +strings and closes the @file{.info} file opened by @file{putinfo()}, if any. +After invoking @code{wfdb_freeinfo()}, a subsequent call to @code{getinfo()} +reads the info strings again (or those of a different record, if a new record +has been opened). + +Virginia Faro-Maza identified and corrected a bug in WFDB library function +@code{iannsettime()}, in file{lib/annot.c}, that caused some annotations to be +missed when two or more annotation files are open simultaneously. + +WFDB library function @code{isigopen()}, in @file{lib/signal.c}, was reverted +to that of version 10.5.9. + +Benjamin Moody contributed patches for @file{app/snip.c} to ensure that the +output will be written using a format that can accommodate the sample +range. + +The signal calibration file, @file{data/wfdbcal}, has been updated with +new definitions. + @unnumberedsubsec Changes in version 10.5.10 (15 November 2011) The WFDB library function @code{isigopen()}, in @file{lib/signal.c}, searches diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/doc/wpg-src/wpg.ht0 wfdb-10.5.11/doc/wpg-src/wpg.ht0 --- wfdb-10.5.10/doc/wpg-src/wpg.ht0 2010-03-17 14:14:08.000000000 -0400 +++ wfdb-10.5.11/doc/wpg-src/wpg.ht0 2012-04-09 12:01:45.000000000 -0400 @@ -19,7 +19,7 @@ George B. Moody
Harvard-MIT Division of Health Sciences and Technology

-Copyright ©1980-2010 George B. Moody. +Copyright ©1980-2012 George B. Moody.

The most recent versions of the software described in this guide are freely downloadable from PhysioNet. For diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/doc/wug-src/wug0.tex wfdb-10.5.11/doc/wug-src/wug0.tex --- wfdb-10.5.10/doc/wug-src/wug0.tex 2010-07-14 01:28:13.000000000 -0400 +++ wfdb-10.5.11/doc/wug-src/wug0.tex 2012-04-09 12:02:15.000000000 -0400 @@ -57,7 +57,7 @@ \pagestyle{empty} \vspace*{\fill} \noindent -Copyright \copyright 1992 -- 2010 George B. Moody +Copyright \copyright 1992 -- 2012 George B. Moody \vspace{1 in} \noindent diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/lib/annot.c wfdb-10.5.11/lib/annot.c --- wfdb-10.5.10/lib/annot.c 2010-06-22 12:05:04.000000000 -0400 +++ wfdb-10.5.11/lib/annot.c 2012-04-06 15:33:44.000000000 -0400 @@ -1,10 +1,10 @@ /* file: annot.c G. Moody 13 April 1989 - Last revised: 18 April 2010 wfdblib 10.5.2 + Last revised: 6 April 2012 wfdblib 10.5.11 WFDB library functions for annotations _______________________________________________________________________________ wfdb: a library for reading and writing annotated waveforms (time series data) -Copyright (C) 1989-2010 George B. Moody +Copyright (C) 1989-2012 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 @@ -642,14 +642,15 @@ annotator, anntime >= t */ FINT iannsettime(WFDB_Time t) { - int stat = 0; + int stat = 0, niavalid = niaf; WFDB_Annotation tempann; WFDB_Annotator i; /* Handle negative arguments as equivalent positive arguments. */ if (t < 0L) t = -t; - for (i = 0; i < niaf && stat == 0; i++) { + /* Loop over all annotators. */ + for (i = 0; i < niaf; i++) { struct iadata *ia; ia = iad[i]; @@ -671,8 +672,10 @@ } while (ia->ann.time < t && (stat = getann(i, &tempann)) == 0) ; + if (stat < 0) niavalid--; } - return (stat); + stat = (niavalid > 0) ? 0 : -1; + return (stat); /* -1 if all inputs are invalid, 0 otherwise */ } /* Functions for converting between anntyp values (annotation codes defined in diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/lib/signal.c wfdb-10.5.11/lib/signal.c --- wfdb-10.5.10/lib/signal.c 2011-11-07 10:09:56.000000000 -0500 +++ wfdb-10.5.11/lib/signal.c 2012-04-06 14:49:14.000000000 -0400 @@ -1,10 +1,10 @@ /* file: signal.c G. Moody 13 April 1989 - Last revised: 7 November 2011 wfdblib 10.5.10 + Last revised: 6 April 2012 wfdblib 10.5.11 WFDB library functions for signals _______________________________________________________________________________ wfdb: a library for reading and writing annotated waveforms (time series data) -Copyright (C) 1989-2011 George B. Moody +Copyright (C) 1989-2012 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 @@ -78,8 +78,9 @@ 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) + setinfo [10.5.11] (creates a .info file for a record) putinfo [4.0] (writes a line of info for a record) + getinfo [4.0] (reads a line of info for a record) sampfreq (returns the sampling frequency of the specified record) setsampfreq (sets the putvec sampling frequency) setbasetime (sets the base time and date) @@ -108,6 +109,7 @@ wfdb_sampquit (frees memory allocated by sample() and sigmap_init()) wfdb_sigclose (closes signals and resets variables) wfdb_osflush (flushes output signals) + wfdb_freeinfo [10.5.11] (releases resources allocated for info string handling) Two versions of r16(), r24(), r32(), w16(), w24(), and w32() are provided here. The default versions are implemented as macros for efficiency. At least one @@ -299,6 +301,7 @@ 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 WFDB_FILE *outinfo; /* file pointer for output info file */ static struct osdata { /* unique for each output signal */ WFDB_Siginfo info; /* output signal information */ WFDB_Sample samp; /* most recent sample written */ @@ -319,6 +322,11 @@ static WFDB_Time ostime; /* time of next output sample */ static int obsize; /* default output buffer size */ +/* These variables relate to info strings. */ +static char **pinfo; /* array of info string pointers */ +static int nimax; /* number of info string pointers allocated */ +static int ninfo; /* number of info strings read */ + /* Local functions (not accessible outside this file). */ static char *ftimstr(WFDB_Time t, WFDB_Frequency f); @@ -1006,9 +1014,9 @@ 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); + wfdb_error("warning (init): in record %s, " + "stated record length (%ld)\n", record, msnsamples); + wfdb_error(" does not match sum of segment lengths (%ld)\n", ns); } return (0); } @@ -1286,6 +1294,7 @@ ostime = 0L; if (oheader) { (void)wfdb_fclose(oheader); + if (outinfo == oheader) outinfo = NULL; oheader = NULL; } if (nisig == 0 && maxhsig != 0) @@ -1890,7 +1899,6 @@ FINT isigopen(char *record, WFDB_Siginfo *siarray, int nsig) { - char *filename, *fullname, *p; int navail, ngroups, nn; struct hsdata *hs; struct isdata *is; @@ -1937,17 +1945,6 @@ return (navail); } - /* Save any directory prefix in record name and use this when looking for - signal files. */ - fullname = calloc(strlen(record)+strlen(getwfdb()+2), sizeof(char)); - strcpy(fullname, record); - filename = p = fullname; - while (*p) { - while (*p && *p != '/') ++p; - if (*p) filename = ++p; - } - *filename = '\0' ; - /* 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. */ @@ -1998,8 +1995,7 @@ if (hs->info.fmt == 0) ig->fp = NULL; /* Don't open a file for a null signal. */ else { - strcpy(filename, hs->info.fname); - ig->fp = wfdb_open(fullname, (char *)NULL, WFDB_READ); + 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) { SFREE(ig->buf); @@ -2023,7 +2019,6 @@ } g++; } - free(fullname); /* Produce a warning message if none of the requested signals could be opened. */ @@ -2746,6 +2741,7 @@ /* If another output header file was opened, close it. */ if (oheader) { (void)wfdb_fclose(oheader); + if (outinfo == oheader) outinfo = NULL; oheader = NULL; } @@ -2832,6 +2828,7 @@ /* If another output header file was opened, close it. */ if (oheader) { (void)wfdb_fclose(oheader); + if (outinfo == oheader) outinfo = NULL; oheader = NULL; } @@ -2992,49 +2989,123 @@ return (n == size ? 0 : -1); } -FSTRING getinfo(char *record) +/* Create a .info file (or open it for appending) */ +FINT setinfo(char *record) { - char *p; - static char linebuf[256]; + /* Close any previously opened output info file. */ + if (outinfo && outinfo != oheader) + wfdb_fclose(outinfo); + outinfo = NULL; + + /* Quit unless a record name has been specified. */ + if (record == NULL) return (0); /* Remove trailing .hea, if any, from record name. */ wfdb_striphea(record); - if (record != NULL && readheader(record) < 0) { - wfdb_error("getinfo: can't read record %s header\n", record); - return (NULL); - } - else if (record == NULL && hheader == NULL) { - if (isedf == 0) - wfdb_error("getinfo: caller did not specify record name\n"); - return (NULL); - } + /* Quit (with message from wfdb_checkname) if name is illegal. */ + if (wfdb_checkname(record, "record")) + return (-1); - /* Find a line beginning with '#'. */ - do { - if (hheader == NULL || wfdb_fgets(linebuf, 256, hheader) == NULL) - return (NULL); - } while (linebuf[0] != '#'); + /* Try to create the .info file. */ + if ((outinfo = wfdb_open("info", record, WFDB_APPEND)) == NULL) { + wfdb_error("setinfo: can't create info file for record %s\n", record); + return (-1); + } - /* Strip off trailing newline (and '\r' if present). */ - p = linebuf + strlen(linebuf) - 1; - if (*p == '\n') *p-- = '\0'; - if (*p == '\r') *p = '\0'; - return (linebuf+1); + /* Success! */ + return (0); } +/* Write an info string to the open output .hea or .info file */ FINT putinfo(char *s) { - if (oheader == NULL) { - wfdb_error( - "putinfo: header not initialized (call `newheader' first)\n"); - return (-1); + if (outinfo == NULL) { + if (oheader) outinfo = oheader; + else { + wfdb_error("putinfo: caller has not specified a record name\n"); + return (-1); + } } - (void)wfdb_fprintf(oheader, "#%s\r\n", s); - (void)wfdb_fflush(oheader); + (void)wfdb_fprintf(outinfo, "#%s\r\n", s); + (void)wfdb_fflush(outinfo); return (0); } +/* getinfo: On the first call, read all info strings from the .hea file and (if +available) the .info file for the specified record, and return a pointer to the +first one. On subsequent calls, return a pointer to the next info string. +Return NULL if there are no more info strings. */ + +FSTRING getinfo(char *record) +{ + static char buf[256], *p; + static int i; + WFDB_FILE *ifile; + + if (pinfo == NULL) { /* info for record has not yet been read */ + if (record == NULL) { + wfdb_error("getinfo: caller did not specify record name\n"); + return (NULL); + } + + if (ninfo) { + wfdb_freeinfo(); /* free memory allocated previously to info */ + ninfo = 0; + } + + i = 0; + nimax = 16; /* initial allotment of info string pointers */ + SALLOC(pinfo, nimax, sizeof(char *)); + + /* Read info from the .hea file, if available (skip for EDF files) */ + if (!isedf) { + /* Remove trailing .hea, if any, from record name. */ + wfdb_striphea(record); + if ((ifile = wfdb_open("hea", record, WFDB_READ))) { + while (wfdb_fgets(buf, 256, ifile)) + if (*buf != '#') break; /* skip initial comments, if any */ + while (wfdb_fgets(buf, 256, ifile)) + if (*buf == '#') break; /* skip header content */ + while (*buf == '#') { /* read and save info */ + p = buf + strlen(buf) - 1; + if (*p == '\n') *p-- = '\0'; + if (*p == '\r') *p = '\0'; + if (ninfo >= nimax) { + nimax += 16; + SREALLOC(pinfo, nimax, sizeof(char *)); + } + SSTRCPY(pinfo[ninfo], buf+1); + ninfo++; + if (wfdb_fgets(buf, 256, ifile) == NULL) break; + } + wfdb_fclose(ifile); + } + } + /* Read more info from the .info file, if available */ + if ((ifile = wfdb_open("info", record, WFDB_READ))) { + while (wfdb_fgets(buf, 256, ifile)) { + if (*buf == '#') { + p = buf + strlen(buf) - 1; + if (*p == '\n') *p-- = '\0'; + if (*p == '\r') *p = '\0'; + if (ninfo >= nimax) { + nimax += 16; + SREALLOC(pinfo, nimax, sizeof(char *)); + } + SSTRCPY(pinfo[ninfo], buf+1); + ninfo++; + } + } + wfdb_fclose(ifile); + } + } + if (i < ninfo) + return pinfo[i++]; + else + return (NULL); +} + FFREQUENCY sampfreq(char *record) { int n; @@ -3517,3 +3588,18 @@ (void)wfdb_fflush(og->fp); } } + +/* Release resources allocated for info string handling */ +void wfdb_freeinfo(void) +{ + int i; + + for (i = 0; i < nimax; i++) + SFREE(pinfo[i]); + SFREE(pinfo); + nimax = ninfo = 0; + if (outinfo) { + wfdb_fclose(outinfo); + outinfo = NULL; + } +} diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/lib/wfdb.h wfdb-10.5.11/lib/wfdb.h --- wfdb-10.5.10/lib/wfdb.h 2011-11-16 14:51:34.000000000 -0500 +++ wfdb-10.5.11/lib/wfdb.h 2012-04-09 13:08:35.000000000 -0400 @@ -1,9 +1,9 @@ /* file: wfdb.h G. Moody 13 June 1983 - Last revised: 16 December 2010 wfdblib 10.5.7 + Last revised: 4 April 2012 wfdblib 10.5.11 WFDB library type, constant, structure, and function interface definitions _______________________________________________________________________________ wfdb: a library for reading and writing annotated waveforms (time series data) -Copyright (C) 1983-2010 George B. Moody +Copyright (C) 1983-2012 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 @@ -32,7 +32,7 @@ /* WFDB library version. */ #define WFDB_MAJOR 10 #define WFDB_MINOR 5 -#define WFDB_RELEASE 10 +#define WFDB_RELEASE 11 #define WFDB_NETFILES 1 /* if 1, library includes code for HTTP, FTP clients */ #define WFDB_NETFILES_LIBCURL 1 @@ -99,11 +99,12 @@ #define WFDB_MAXUSL 50 /* maximum length of WFDB_siginfo `.units' string */ #define WFDB_MAXDSL 100 /* maximum length of WFDB_siginfo `.desc' string */ -/* WFDB_anninfo '.stat' values */ +/* wfdb_fopen mode values (WFDB_anninfo '.stat' values) */ #define WFDB_READ 0 /* standard input annotation file */ #define WFDB_WRITE 1 /* standard output annotation file */ #define WFDB_AHA_READ 2 /* AHA-format input annotation file */ #define WFDB_AHA_WRITE 3 /* AHA-format output annotation file */ +#define WFDB_APPEND 4 /* for output info files */ /* WFDB_siginfo '.fmt' values FMT_LIST is suitable as an initializer for a static array; it lists all of @@ -325,6 +326,8 @@ extern FVOID flushcal(void); extern FSTRING getinfo(char *record); extern FINT putinfo(char *info); +extern FINT setinfo(char *record); +extern FVOID wfdb_freeinfo(void); extern FINT newheader(char *record); extern FINT setheader(char *record, WFDB_Siginfo *siarray, unsigned int nsig); extern FINT setmsheader(char *record, char **segnames, unsigned int nsegments); @@ -373,17 +376,17 @@ wfdb_isqrs(), wfdb_setisqrs(), wfdb_map1(), wfdb_setmap1(), wfdb_map2(), wfdb_setmap2(), wfdb_ammap(), wfdb_mamap(), wfdb_annpos(), wfdb_setannpos(), adumuv(), newheader(), setheader(), setmsheader(), getseginfo(), - wfdbputprolog(), setsampfreq(), setbasetime(), putinfo(), setibsize(), - setobsize(), calopen(), getcal(), putcal(), newcal(), wfdbgetskew(), - sample_valid(); + wfdbputprolog(), setsampfreq(), setbasetime(), putinfo(), setinfo(), + setibsize(), setobsize(), calopen(), getcal(), putcal(), newcal(), + wfdbgetskew(), sample_valid(); extern FLONGINT wfdbgetstart(); extern FSAMPLE muvadu(), physadu(), sample(); extern FSTRING ecgstr(), annstr(), anndesc(), timstr(), mstimstr(), datstr(), getwfdb(), getinfo(), wfdberror(), wfdbfile(); extern FSITIME strtim(), tnextvec(); extern FDATE strdat(); -extern FVOID setafreq(), setgvmode(), wfdbquit(), wfdbquiet(), dbverbose(), - setdb(), wfdbflush(), setcfreq(), setbasecount(), flushcal(), +extern FVOID setafreq(), setgvmode(), wfdb_freeinfo(), wfdbquit(), wfdbquiet(), + wfdbverbose(), setdb(), wfdbflush(), setcfreq(), setbasecount(), flushcal(), wfdbsetiskew(), wfdbsetskew(), wfdbsetstart(), wfdbmemerr(); extern FFREQUENCY getafreq(), getifreq(), sampfreq(), getcfreq(); extern FDOUBLE aduphys(), getbasecount(); diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/lib/wfdb.h0 wfdb-10.5.11/lib/wfdb.h0 --- wfdb-10.5.10/lib/wfdb.h0 2010-12-16 18:55:23.000000000 -0500 +++ wfdb-10.5.11/lib/wfdb.h0 2012-04-04 16:10:54.000000000 -0400 @@ -1,9 +1,9 @@ /* file: wfdb.h G. Moody 13 June 1983 - Last revised: 16 December 2010 wfdblib 10.5.7 + Last revised: 4 April 2012 wfdblib 10.5.11 WFDB library type, constant, structure, and function interface definitions _______________________________________________________________________________ wfdb: a library for reading and writing annotated waveforms (time series data) -Copyright (C) 1983-2010 George B. Moody +Copyright (C) 1983-2012 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 @@ -99,11 +99,12 @@ #define WFDB_MAXUSL 50 /* maximum length of WFDB_siginfo `.units' string */ #define WFDB_MAXDSL 100 /* maximum length of WFDB_siginfo `.desc' string */ -/* WFDB_anninfo '.stat' values */ +/* wfdb_fopen mode values (WFDB_anninfo '.stat' values) */ #define WFDB_READ 0 /* standard input annotation file */ #define WFDB_WRITE 1 /* standard output annotation file */ #define WFDB_AHA_READ 2 /* AHA-format input annotation file */ #define WFDB_AHA_WRITE 3 /* AHA-format output annotation file */ +#define WFDB_APPEND 4 /* for output info files */ /* WFDB_siginfo '.fmt' values FMT_LIST is suitable as an initializer for a static array; it lists all of @@ -325,6 +326,8 @@ extern FVOID flushcal(void); extern FSTRING getinfo(char *record); extern FINT putinfo(char *info); +extern FINT setinfo(char *record); +extern FVOID wfdb_freeinfo(void); extern FINT newheader(char *record); extern FINT setheader(char *record, WFDB_Siginfo *siarray, unsigned int nsig); extern FINT setmsheader(char *record, char **segnames, unsigned int nsegments); @@ -373,17 +376,17 @@ wfdb_isqrs(), wfdb_setisqrs(), wfdb_map1(), wfdb_setmap1(), wfdb_map2(), wfdb_setmap2(), wfdb_ammap(), wfdb_mamap(), wfdb_annpos(), wfdb_setannpos(), adumuv(), newheader(), setheader(), setmsheader(), getseginfo(), - wfdbputprolog(), setsampfreq(), setbasetime(), putinfo(), setibsize(), - setobsize(), calopen(), getcal(), putcal(), newcal(), wfdbgetskew(), - sample_valid(); + wfdbputprolog(), setsampfreq(), setbasetime(), putinfo(), setinfo(), + setibsize(), setobsize(), calopen(), getcal(), putcal(), newcal(), + wfdbgetskew(), sample_valid(); extern FLONGINT wfdbgetstart(); extern FSAMPLE muvadu(), physadu(), sample(); extern FSTRING ecgstr(), annstr(), anndesc(), timstr(), mstimstr(), datstr(), getwfdb(), getinfo(), wfdberror(), wfdbfile(); extern FSITIME strtim(), tnextvec(); extern FDATE strdat(); -extern FVOID setafreq(), setgvmode(), wfdbquit(), wfdbquiet(), dbverbose(), - setdb(), wfdbflush(), setcfreq(), setbasecount(), flushcal(), +extern FVOID setafreq(), setgvmode(), wfdb_freeinfo(), wfdbquit(), wfdbquiet(), + wfdbverbose(), setdb(), wfdbflush(), setcfreq(), setbasecount(), flushcal(), wfdbsetiskew(), wfdbsetskew(), wfdbsetstart(), wfdbmemerr(); extern FFREQUENCY getafreq(), getifreq(), sampfreq(), getcfreq(); extern FDOUBLE aduphys(), getbasecount(); diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/lib/wfdbinit.c wfdb-10.5.11/lib/wfdbinit.c --- wfdb-10.5.10/lib/wfdbinit.c 2010-12-16 18:37:29.000000000 -0500 +++ wfdb-10.5.11/lib/wfdbinit.c 2012-04-06 14:17:31.000000000 -0400 @@ -1,9 +1,9 @@ /* file: wfdbinit.c G. Moody 23 May 1983 - Last revised: 16 December 2010 wfdblib 10.5.7 + Last revised: 6 April 2012 wfdblib 10.5.11 WFDB library functions wfdbinit, wfdbquit, and wfdbflush _______________________________________________________________________________ wfdb: a library for reading and writing annotated waveforms (time series data) -Copyright (C) 1983-2008 George B. Moody +Copyright (C) 1983-2012 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 @@ -48,6 +48,7 @@ wfdb_sigclose(); /* close signals, reset variables */ resetwfdb(); /* restore the WFDB path */ wfdb_sampquit(); /* release sample data buffer */ + wfdb_freeinfo(); /* release info strings */ #if WFDB_NETFILES wfdb_wwwquit(); /* release resources allocated by libcurl or libwww */ #endif diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/lib/wfdbio.c wfdb-10.5.11/lib/wfdbio.c --- wfdb-10.5.10/lib/wfdbio.c 2011-11-07 10:09:32.000000000 -0500 +++ wfdb-10.5.11/lib/wfdbio.c 2012-04-06 12:29:39.000000000 -0400 @@ -1,10 +1,10 @@ /* file: wfdbio.c G. Moody 18 November 1988 - Last revised: 7 November 2011 wfdblib 10.5.10 + Last revised: 6 April 2012 wfdblib 10.5.11 Low-level I/O functions for the WFDB library _______________________________________________________________________________ wfdb: a library for reading and writing annotated waveforms (time series data) -Copyright (C) 1988-2011 George B. Moody +Copyright (C) 1988-2012 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 @@ -427,6 +427,7 @@ #ifdef MSDOS #define DSEP '\\' #define PSEP ';' +#define AB "ab" #define RB "rb" #define WB "wb" #else @@ -441,6 +442,7 @@ #define DSEP '/' #define PSEP ':' #endif +#define AB "ab" #define RB "rb" #define WB "wb" @@ -448,6 +450,7 @@ # else #define DSEP '/' #define PSEP ':' +#define AB "a" #define RB "r" #define WB "w" #endif @@ -948,6 +951,11 @@ SFREE(r); return (wfdb_fopen(wfdb_filename, WB)); } + else if (mode == WFDB_APPEND) { + spr1(wfdb_filename, r, s); + SFREE(r); + return (wfdb_fopen(wfdb_filename, AB)); + } /* If the file is to be opened for input, prepare to search the database directories. */ @@ -1722,7 +1730,7 @@ if (!www_done_init) www_init(); - if (*mode == 'w') + if (*mode == 'w' || *mode == 'a') errno = EROFS; /* no support for output */ else if (*mode != 'r') errno = EINVAL; /* invalid mode string */ @@ -1967,7 +1975,7 @@ wp->type = WFDB_LOCAL; return (wp); } - if (strcmp(mode, WB) == 0) { + if (strcmp(mode, WB) == 0 || strcmp(mode, AB) == 0) { int stat = 1; /* An attempt to create an output file failed. Check to see if all diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/lib/wfdblib.h wfdb-10.5.11/lib/wfdblib.h --- wfdb-10.5.10/lib/wfdblib.h 2011-11-16 14:51:34.000000000 -0500 +++ wfdb-10.5.11/lib/wfdblib.h 2012-04-06 15:43:23.000000000 -0400 @@ -1,10 +1,10 @@ /* file: wfdblib.h G. Moody 13 April 1989 - Last revised: 1 March 2010 wfdblib 10.5.0 + Last revised: 6 April 2012 wfdblib 10.5.11 External definitions for WFDB library private functions _______________________________________________________________________________ wfdb: a library for reading and writing annotated waveforms (time series data) -Copyright (C) 1989-2010 George B. Moody +Copyright (C) 1989-2012 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 @@ -96,9 +96,9 @@ variable is not set. This value is edited by the configuration script (../configure), which also edits this block of comments to match. - If WFDB_NETFILES support is disabled, the string ". /usr/database" is + If WFDB_NETFILES support is disabled, the string ". /home/george/Desktop/wfdb-10.5.11/build/database" is usually sufficient for a default WFDB path, thus restricting the search for - WFDB files to the current directory ("."), followed by /usr/database). + WFDB files to the current directory ("."), followed by /home/george/Desktop/wfdb-10.5.11/build/database). If WFDB_NETFILES support is enabled, the first setting below adds the web-accessible PhysioBank databases to the default path; you may wish to @@ -107,9 +107,9 @@ */ #ifndef WFDB_NETFILES -# define DEFWFDB ". /usr/database" +# define DEFWFDB ". /home/george/Desktop/wfdb-10.5.11/build/database" #else -# define DEFWFDB ". /usr/database http://physionet.org/physiobank/database" +# define DEFWFDB ". /home/george/Desktop/wfdb-10.5.11/build/database http://physionet.org/physiobank/database" #endif /* Mac OS 9 and earlier, only: The value of DEFWFDB given below specifies @@ -343,6 +343,7 @@ extern void wfdb_sampquit(void); extern void wfdb_sigclose(void); extern void wfdb_osflush(void); +extern void wfdb_freeinfo(void); /* These functions are defined in annot.c */ extern void wfdb_anclose(void); diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/lib/wfdblib.h0 wfdb-10.5.11/lib/wfdblib.h0 --- wfdb-10.5.10/lib/wfdblib.h0 2010-03-01 14:28:03.000000000 -0500 +++ wfdb-10.5.11/lib/wfdblib.h0 2012-04-06 14:22:38.000000000 -0400 @@ -1,10 +1,10 @@ /* file: wfdblib.h G. Moody 13 April 1989 - Last revised: 1 March 2010 wfdblib 10.5.0 + Last revised: 6 April 2012 wfdblib 10.5.11 External definitions for WFDB library private functions _______________________________________________________________________________ wfdb: a library for reading and writing annotated waveforms (time series data) -Copyright (C) 1989-2010 George B. Moody +Copyright (C) 1989-2012 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 @@ -343,6 +343,7 @@ extern void wfdb_sampquit(void); extern void wfdb_sigclose(void); extern void wfdb_osflush(void); +extern void wfdb_freeinfo(void); /* These functions are defined in annot.c */ extern void wfdb_anclose(void); diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/MANIFEST wfdb-10.5.11/MANIFEST --- wfdb-10.5.10/MANIFEST 2011-11-15 15:53:08.000000000 -0500 +++ wfdb-10.5.11/MANIFEST 2012-04-06 15:44:35.000000000 -0400 @@ -7,6 +7,7 @@ app/ecgeval.c app/epicmp.c app/fir.c +app/hrstats.c app/ihr.c app/Makefile app/Makefile.top @@ -284,6 +285,7 @@ doc/wag-src/getpagenos.c doc/wag-src/header.5 doc/wag-src/hrfft.1 +doc/wag-src/hrstats.1 doc/wag-src/ihr.1 doc/wag-src/imageplt.1 doc/wag-src/install0.tex diff -Naur --exclude Makefile --exclude info wfdb-10.5.10/NEWS wfdb-10.5.11/NEWS --- wfdb-10.5.10/NEWS 2011-11-16 14:55:48.573806584 -0500 +++ wfdb-10.5.11/NEWS 2012-04-09 13:32:01.760522095 -0400 @@ -1,3 +1,42 @@ +10.5.11 (6 April 2012): + This release of the WFDB library introduces support for '.info' files. + These are files containing 'info' strings in the same format as those + that can be stored in '.hea' files. The '.info' file for a record + named 'record' is named 'record.info', and it may be located anywhere + in the WFDB path. Function getinfo(), as in previous releases, returns + the first info string belonging to the record named as its argument, or + the next info string belonging to the previously specified record if + its argument is NULL. Beginning with this release, successive calls to + getinfo() return the next info string contained in the record's '.info' + file if it exists, and if there are no more in the record's '.hea' + file. Function putinfo() writes an info string to the currently open + output '.hea' file, unless function setinfo() (new in this release) has + been invoked, in which case the info string is appended to the record's + '.info' file in the current directory. getinfo() reads all of the + record's info strings the first time it is invoked, returning them one + at a time; wfdb_freeinfo() frees the memory allocated for getinfo()'s + info strings and closes the '.info' file opened by putinfo(), if any. + After invoking wfdb_freeinfo(), a subsequent call to getinfo() reads + the info strings again (or those of a different record, if a new record + has been opened). + + A new application, app/hrstats.c, collects and summarizes heart rate + statistics based on the contents of an annotation file. + + Virginia Faro-Maza identified and corrected a bug in WFDB library + function iannsettime() (in lib/annot.c) that caused some annotations + to be missed when two or more annotation files are open simultaneously. + + WFDB library function isigopen(), in lib/signal.c, was reverted to that + of version 10.5.9. + + Benjamin Moody contributed patches for app/snip.c to ensure that the + output will be written using a format that can accommodate the sample + range. + + The signal calibration file, data/wfdbcal, has been updated with + new definitions. + 10.5.10 (15 November 2011): The WFDB library function isigopen(), in lib/signal.c, searches each component of the WFDB path for the signal file(s) named in the