diff -Naur --exclude Makefile --exclude info wfdb-10.4.21/app/pschart.c wfdb-10.4.22/app/pschart.c --- wfdb-10.4.21/app/pschart.c 2009-04-09 22:12:33.000000000 -0400 +++ wfdb-10.4.22/app/pschart.c 2009-05-27 15:47:06.000000000 -0400 @@ -1,5 +1,5 @@ /* file: pschart.c G. Moody 15 March 1988 - Last revised: 9 April 2009 + Last revised: 27 May 2009 ------------------------------------------------------------------------------- pschart: Produce annotated `chart recordings' on a PostScript device @@ -446,7 +446,7 @@ /* count the number of output signals (arguments not beginning with a hyphen, and not including the last argument, which must be the name of the script) */ - for (j = i+1; j < argc-2 && *argv[j] != '-'; j++) + for (j = i+1; j < argc-1 && *argv[j] != '-'; j++) ; if (j == i+1) { (void)fprintf(stderr, "%s: signal list must follow -s\n", diff -Naur --exclude Makefile --exclude info wfdb-10.4.21/app/psfd.c wfdb-10.4.22/app/psfd.c --- wfdb-10.4.21/app/psfd.c 2009-03-18 12:23:12.000000000 -0400 +++ wfdb-10.4.22/app/psfd.c 2009-05-27 15:47:52.000000000 -0400 @@ -1,5 +1,5 @@ /* file: psfd.c G. Moody 9 August 1988 - Last revised: 18 March 2009 + Last revised: 27 May 2009 ------------------------------------------------------------------------------- psfd: Produces annotated full-disclosure ECG plots on a PostScript device @@ -417,7 +417,7 @@ /* count the number of output signals (arguments not beginning with a hyphen, and not including the last argument, which must be the name of the script) */ - for (j = i+1; j < argc-2 && *argv[j] != '-'; j++) + for (j = i+1; j < argc-1 && *argv[j] != '-'; j++) ; if (j == i+1) { (void)fprintf(stderr, "%s: signal list must follow -s\n", diff -Naur --exclude Makefile --exclude info wfdb-10.4.21/app/wabp.c wfdb-10.4.22/app/wabp.c --- wfdb-10.4.21/app/wabp.c 2009-01-07 14:30:35.000000000 -0500 +++ wfdb-10.4.22/app/wabp.c 2009-06-12 16:38:01.000000000 -0400 @@ -1,5 +1,5 @@ /* file wabp.c Wei Zong 23 October 1998 - Last revised: 7 January 2009 (by G. Moody) + Last revised: 12 June 2009 (by O. Abdala) ----------------------------------------------------------------------------- wabp: beat detector for arterial blood presure (ABP) signal Copyright (C) 1998-2009 Wei Zong @@ -73,6 +73,29 @@ int Tm = TmDEF; /* minimum threshold value */ WFDB_Sample *lbuf = NULL; +char *trim_whitespace(char *str) +{ + size_t len = 0; + char *frontp = str - 1; + char *endp = NULL; + + if (str == NULL) return NULL; + if (str[0] == '\0') return str; + len = strlen(str); + endp = str + len; + while (isspace(*(++frontp))); + while (isspace(*(--endp)) && endp != frontp); + if (str + len - 1 != endp) + *(endp + 1) = '\0'; + else if (frontp != str && endp == frontp) + *str = '\0'; + endp = str; + if (frontp != str) { + while (*frontp) *endp++ = *frontp++; + *endp = '\0'; + } + return str; +} WFDB_Sample slpsamp(WFDB_Time t) { @@ -99,7 +122,17 @@ } while (t > tt) { static int aet = 0, et; - dy = sample(sig, tt) - sample(sig, tt-1); + int prevVal = 0; + int val1; + int val2; + val2 = sample(sig, tt - 1); + if (sample_valid() != 1) + val2 = prevVal; + val1 = sample(sig, tt); + if (sample_valid() != 1) + val1 = val2; + prevVal = val2; + dy = val1 - val2; if (dy < 0) dy = 0; et = ebuf[(++tt)&(BUFLN-1)] = dy; lbuf[(tt)&(BUFLN-1)] = aet += et - ebuf[(tt-SLPwindow)&(BUFLN-1)]; @@ -218,7 +251,7 @@ if (sig < 0 || sig >= nsig) { /* Identify the lowest-numbered ABP, ART, or BP signal */ for (i = 0; i < nsig; i++) - if (strcmp(s[i].desc, "ABP") == 0 || + if (strcmp(trim_whitespace(s[i].desc), "ABP") == 0 || strcmp(s[i].desc, "ART") == 0 || strcmp(s[i].desc, "BP") == 0) break; @@ -256,8 +289,7 @@ ExpectPeriod = sps * NDP; /* maximum expected RR interval */ SLPwindow = sps * SLPW; /* slope window size */ - if (vflag) - { + if (vflag) { printf("\n------------------------------------------------------\n"); printf("Record Name: %s\n", record); printf("Total Signals: %d (", nsig); diff -Naur --exclude Makefile --exclude info wfdb-10.4.21/app/wrann.c wfdb-10.4.22/app/wrann.c --- wfdb-10.4.21/app/wrann.c 2009-04-09 21:26:24.000000000 -0400 +++ wfdb-10.4.22/app/wrann.c 2009-07-15 12:08:07.000000000 -0400 @@ -1,5 +1,5 @@ /* file wrann.c G. Moody 6 July 1983 - Last revised: 9 April 2009 + Last revised: 15 July 2009 ------------------------------------------------------------------------------- wrann: Translate an ASCII file in 'rdann' output format to an annotation file @@ -94,7 +94,7 @@ if (annopen(record, &ai, 1) < 0) /* open annotation file */ exit(2); while (fgets(line, sizeof(line), stdin) != NULL) { - static char a[256]; + static char a[256], *ap; p = line+9; if (line[0] == '[') while (*p != ']') @@ -102,7 +102,7 @@ while (*p != ' ') p++; *(a+1) = '\0'; - (void)sscanf(p+1, "%ld%s%d%d%d\t%s", &tm, annstr, &sub, &ch, &nm, a+1); + (void)sscanf(p+1, "%ld%s%d%d%d", &tm, annstr, &sub, &ch, &nm); annot.anntyp = strann(annstr); if (line[0] == '[') { annot.time = -strtim(line); @@ -111,8 +111,10 @@ else annot.time = tm; annot.subtyp = sub; annot.chan = ch; annot.num = nm; - if (*(a+1)) { - *a = strlen(a+1); + if (ap = strchr(p+1, '\t')) { /* look for aux string after tab */ + strncpy(a+1, ap+1, sizeof(a)-2); /* leave room for count and null */ + *a = strlen(a+1) - 1; /* set byte count (excluding newline) */ + a[*a+1] = '\0'; /* replace trailing newline with null */ annot.aux = a; } else diff -Naur --exclude Makefile --exclude info wfdb-10.4.21/convert/mit2wav.c wfdb-10.4.22/convert/mit2wav.c --- wfdb-10.4.21/convert/mit2wav.c 2003-02-12 13:21:05.000000000 -0500 +++ wfdb-10.4.22/convert/mit2wav.c 2009-06-10 12:21:03.000000000 -0400 @@ -135,7 +135,8 @@ char buf[80], *nrec = NULL, *ofname, *record = NULL, tfname[10]; double sps; FILE *sfile; - int bitspersample, bytespersecond, framelen, i, mag, nsig, *offset, *shift; + int bitspersample = 0, bytespersecond, framelen, i, mag, nsig, *offset, + *shift; long nsamp; static WFDB_Sample *x, *y; static WFDB_Siginfo *s; diff -Naur --exclude Makefile --exclude info wfdb-10.4.21/doc/wpg-src/wpg0.tex wfdb-10.4.22/doc/wpg-src/wpg0.tex --- wfdb-10.4.21/doc/wpg-src/wpg0.tex 2009-03-15 08:43:18.000000000 -0400 +++ wfdb-10.4.22/doc/wpg-src/wpg0.tex 2009-07-28 19:25:09.000000000 -0400 @@ -510,6 +510,33 @@ WFDB Software Package distribution, for information on any more recent changes that may not be described here. +@unnumberedsubsec Changes in version 10.4.22 + +When reading multifrequency records in WFDB_LOWRES mode, invalid +sample values occurring in signals that need to be decimated were not +always handled properly in WFDB library function getvec(), resulting +in spurious artifacts during intervals that contained a mixture of +valid and invalid samples. This bug has been corrected; thanks to +Omar Abdala for a report that brought this problem to light. + +A declaration for WFDB library function findsig has been added to wfdb.h. +Thanks to Thomas Heldt for reporting a warning that resulted from its +omission in previous versions. + +@unnumberedsubsec Changes in version 10.4.21 + +Changes in lib/Makefile.tpl were needed in order to pass configuration +constants to the functions added to wfdbio.c in 10.4.20, but were +omitted from that release; they have been included in this version. + +@unnumberedsubsec Changes in version 10.4.20 + +Several new functions have been added to lib/wfdbio.c, to make +configuration constants accessible at run time; these are needed by +the WFDB Toolkit for Matlab. + +(WFDB library version 10.4.19 was identical to version 10.4.18.) + @unnumberedsubsec Changes in version 10.4.18 The WFDB library no longer reports spurious checksum errors when reading @@ -3168,10 +3195,10 @@ @noindent This function resets the input signal file pointers so that the next -samples read by @code{getvec} from each input annotation file will -include the next valid sample of the specified signal @var{s} -occurring at or after @var{t}. Use @code{tnextvec} to skip lengthy -gaps in a signal of interest efficiently. +samples read by @code{getvec} will include the next valid sample of +the specified signal @var{s} occurring at or after @var{t}. Use +@code{tnextvec} to skip lengthy gaps in a signal of interest +efficiently. @c @group @node iannsettime, sample, tnextvec, non-sequential diff -Naur --exclude Makefile --exclude info wfdb-10.4.21/lib/signal.c wfdb-10.4.22/lib/signal.c --- wfdb-10.4.21/lib/signal.c 2009-03-14 23:54:09.000000000 -0400 +++ wfdb-10.4.22/lib/signal.c 2009-06-12 16:18:02.000000000 -0400 @@ -1,10 +1,10 @@ /* file: signal.c G. Moody 13 April 1989 - Last revised: 14 March 2009 wfdblib 10.4.18 + Last revised: 12 June 2009 wfdblib 10.4.22 WFDB library functions for signals _______________________________________________________________________________ wfdb: a library for reading and writing annotated waveforms (time series data) -Copyright (C) 1989-2008 George B. Moody +Copyright (C) 1989-2009 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 @@ -288,8 +288,7 @@ dsbuf does not contain valid data) */ static unsigned dsblen; /* capacity of dsbuf, in samples */ static unsigned framelen; /* total number of samples per frame */ -static int gvmode = -1; /* getvec mode (WFDB_HIGHRES or WFDB_LOWRES - once initialized) */ +static int gvmode = DEFWFDBGVMODE; /* getvec mode */ static int gvpad; /* getvec padding (if non-zero, replace invalid samples with previous valid samples) */ static int gvc; /* getvec sample-within-frame counter */ @@ -1770,8 +1769,8 @@ if (ispfmax < 2) /* all signals at the same frequency */ return (getframe(vector)); - if (gvmode != WFDB_HIGHRES) {/* return one sample per frame, decimating - (by averaging) if necessary */ + if ((gvmode & WFDB_HIGHRES) != WFDB_HIGHRES) { + /* return one sample per frame, decimating by averaging if necessary */ unsigned c; long v; @@ -1779,9 +1778,14 @@ for (s = 0, tp = tvector; s < nvsig; s++) { int sf = vsd[s]->info.spf; - for (c = v = 0; c < sf; c++) + for (c = v = 0; c < sf && *tp != WFDB_INVALID_SAMPLE; c++) v += *tp++; - *vector++ = v/sf; + if (c == sf) + *vector++ = v/sf; + else { + *vector++ = WFDB_INVALID_SAMPLE; + tp += sf - c; + } } } else { /* return ispfmax samples per frame, using @@ -2039,10 +2043,18 @@ SALLOC(og->buf, 1, obuflen); og->bp = og->buf; og->be = og->buf + obuflen; - if (os->info.fmt == 0) - og->fp = NULL; /* don't open a file for a null signal */ - /* An error in opening an output file is fatal. */ - else { + if (os->info.fmt == 0) { + /* If the signal file name was NULL or "~", don't create a + signal file. */ + if (os->info.fname == NULL || strcmp("~", os->info.fname) == 0) + og->fp = NULL; + /* Otherwise, assume that the user wants to write a signal + file in the default format (16). */ + else + os->info.fmt = 16; + } + if (os->info.fmt != 0) { + /* An error in opening an output file is fatal. */ og->fp = wfdb_open(os->info.fname,(char *)NULL, WFDB_WRITE); if (og->fp == NULL) { wfdb_error("osigopen: can't open %s\n", os->info.fname); @@ -2157,10 +2169,18 @@ SALLOC(og->buf, 1,obuflen); og->bp = og->buf; og->be = og->buf + obuflen; - if (os->info.fmt == 0) - og->fp = NULL; /* don't open a file for a null signal */ - /* An error in opening an output file is fatal. */ - else { + if (os->info.fmt == 0) { + /* If the signal file name was NULL or "~", don't create a + signal file. */ + if (os->info.fname == NULL || strcmp("~", os->info.fname) == 0) + og->fp = NULL; + /* Otherwise, assume that the user wants to write a signal + file in the default format (16). */ + else + os->info.fmt = 16; + } + if (os->info.fmt != 0) { + /* An error in opening an output file is fatal. */ og->fp = wfdb_open(os->info.fname,(char *)NULL, WFDB_WRITE); if (og->fp == NULL) { wfdb_error("osigfopen: can't open %s\n", os->info.fname); @@ -2256,6 +2276,7 @@ if ((mode & WFDB_HIGHRES) == WFDB_HIGHRES) { gvmode = WFDB_HIGHRES; + if (ispfmax == 0) ispfmax = 1; sfreq = ffreq * ispfmax; } else { @@ -2930,7 +2951,7 @@ { if (freq >= 0.) { sfreq = ffreq = freq; - if (gvmode == WFDB_HIGHRES) sfreq *= ispfmax; + if ((gvmode & WFDB_HIGHRES) == WFDB_HIGHRES) sfreq *= ispfmax; return (0); } wfdb_error("setsampfreq: sampling frequency must not be negative\n"); @@ -3088,11 +3109,11 @@ (WFDB_Time)((atof(string+1)-bcount)*f/cfreq) : (WFDB_Time)atol(string+1)); case 'e': return ((in_msrec ? msnsamples : nsamples) * - ((gvmode == WFDB_HIGHRES) ? ispfmax : 1)); + (((gvmode&WFDB_HIGHRES) == WFDB_HIGHRES) ? ispfmax: 1)); case 'f': return (WFDB_Time)(atol(string+1)*f/ffreq); case 'i': return (WFDB_Time)(istime * (ifreq > 0.0 ? (ifreq/sfreq) : 1.0) * - ((gvmode == WFDB_HIGHRES) ? ispfmax : 1)); + (((gvmode&WFDB_HIGHRES) == WFDB_HIGHRES) ? ispfmax: 1)); case 'o': return (ostime); case 's': return ((WFDB_Time)atol(string+1)); case '[': /* time of day, possibly with date or days since start */ diff -Naur --exclude Makefile --exclude info wfdb-10.4.21/lib/wfdb.h wfdb-10.4.22/lib/wfdb.h --- wfdb-10.4.21/lib/wfdb.h 2009-05-14 11:06:33.000000000 -0400 +++ wfdb-10.4.22/lib/wfdb.h 2009-07-28 19:33:34.000000000 -0400 @@ -1,5 +1,5 @@ /* file: wfdb.h G. Moody 13 June 1983 - Last revised: 13 February 2009 wfdblib 10.4.15 + Last revised: 28 July 2009 wfdblib 10.4.22 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 21 +#define WFDB_RELEASE 22 #define WFDB_NETFILES 1 /* if 1, library includes code for HTTP, FTP clients */ #define WFDB_NETFILES_LIBCURL 1 @@ -242,6 +242,7 @@ extern FINT wfdbinit(char *record, WFDB_Anninfo *aiarray, unsigned int nann, WFDB_Siginfo *siarray, unsigned int nsig); +extern FINT findsig(char *signame); extern FINT getspf(void); extern FVOID setgvmode(int mode); extern FINT setifreq(WFDB_Frequency freq); @@ -336,7 +337,7 @@ #endif #ifdef wfdb_KRC /* declare only function return types for K&R C compilers */ -extern FINT annopen(), isigopen(), osigopen(), wfdbinit(), getspf(), +extern FINT annopen(), isigopen(), osigopen(), wfdbinit(), findsig(), getspf(), setifreq(), getvec(), getframe(), putvec(), getann(), ungetann(), putann(), isigsettime(), isgsettime(), iannsettime(), strecg(), setecgstr(), strann(), setannstr(), setanndesc(), wfdb_isann(), wfdb_isqrs(), diff -Naur --exclude Makefile --exclude info wfdb-10.4.21/lib/wfdb.h0 wfdb-10.4.22/lib/wfdb.h0 --- wfdb-10.4.21/lib/wfdb.h0 2009-04-16 14:57:58.000000000 -0400 +++ wfdb-10.4.22/lib/wfdb.h0 2009-07-28 08:25:49.000000000 -0400 @@ -1,5 +1,5 @@ /* file: wfdb.h G. Moody 13 June 1983 - Last revised: 13 February 2009 wfdblib 10.4.15 + Last revised: 28 July 2009 wfdblib 10.4.22 WFDB library type, constant, structure, and function interface definitions _______________________________________________________________________________ @@ -242,6 +242,7 @@ extern FINT wfdbinit(char *record, WFDB_Anninfo *aiarray, unsigned int nann, WFDB_Siginfo *siarray, unsigned int nsig); +extern FINT findsig(char *signame); extern FINT getspf(void); extern FVOID setgvmode(int mode); extern FINT setifreq(WFDB_Frequency freq); @@ -336,7 +337,7 @@ #endif #ifdef wfdb_KRC /* declare only function return types for K&R C compilers */ -extern FINT annopen(), isigopen(), osigopen(), wfdbinit(), getspf(), +extern FINT annopen(), isigopen(), osigopen(), wfdbinit(), findsig(), getspf(), setifreq(), getvec(), getframe(), putvec(), getann(), ungetann(), putann(), isigsettime(), isgsettime(), iannsettime(), strecg(), setecgstr(), strann(), setannstr(), setanndesc(), wfdb_isann(), wfdb_isqrs(), diff -Naur --exclude Makefile --exclude info wfdb-10.4.21/NEWS wfdb-10.4.22/NEWS --- wfdb-10.4.21/NEWS 2009-05-14 11:34:46.000000000 -0400 +++ wfdb-10.4.22/NEWS 2009-07-28 20:20:03.000000000 -0400 @@ -1,3 +1,26 @@ +10.4.22: + When reading multifrequency records in WFDB_LOWRES mode, invalid + sample values occurring in signals that need to be decimated were + not always handled properly in WFDB library function getvec(), + resulting in spurious artifacts during intervals that contained a + mixture of valid and invalid samples. This bug has been corrected; + thanks to Omar Abdala for a report that brought this problem to light. + + A declaration for WFDB library function findsig() has been added + to wfdb.h. Thanks to Thomas Heldt for reporting a warning + that resulted from its omission in previous versions. + + Omar also found and corrected a bug in app/wabp.c that resulted in + premature termination of processing some variable-layout multisegment + records, and improved the autoselection of a default ABP signal. + + An uninitialized variable in convert/mit2wav.c caused problems in + previous versions; thanks to Greg Downs for the bug report and fix. + + WFDB application 'wrann' from the previous two versions truncated + 'aux' strings containing embedded whitespace; this has been corrected. + Thanks to Mauro Villarroel for the bug report. + 10.4.21: Changes in lib/Makefile.tpl were needed in order to pass configuration constants to the functions added to wfdbio.c in 10.4.20, but were diff -Naur --exclude Makefile --exclude info wfdb-10.4.21/wave/sig.c wfdb-10.4.22/wave/sig.c --- wfdb-10.4.21/wave/sig.c 2009-05-13 13:21:45.000000000 -0400 +++ wfdb-10.4.22/wave/sig.c 2009-06-12 15:02:13.000000000 -0400 @@ -1,5 +1,5 @@ /* file: sig.c G. Moody 27 April 1990 - Last revised: 13 May 2009 + Last revised: 12 June 2009 Signal display functions for WAVE ------------------------------------------------------------------------------- @@ -345,7 +345,7 @@ data. */ if (nsamp > canvas_width) { for (i = 1, x0 = 0; i < nsamp && getvec(v) > 0; i++) { - for (c = 0; c < nsig; c++) { + for (c = 0, vvalid[c] = 0; c < nsig; c++) { if (v[c] != WFDB_INVALID_SAMPLE) { if (v[c] > vmax[c]) vmax[c] = v[c]; if (v[c] < vmin[c]) vmin[c] = v[c]; @@ -364,7 +364,6 @@ } else lp->vlist[c][x0].y = WFDB_INVALID_SAMPLE; - // vvalid[c] = 0; } } }