INTEGER physadu_(INTEGER *signal, DOUBLE_PRECISION *v) { return (physadu((WFDB_Signal)(*signal), *v)); }
int main(int argc, char **argv) { char *record = NULL; /* input record name */ float sps; /* sampling frequency, in Hz (SR) */ float samplingInterval; /* sampling interval, in milliseconds */ int i, max, min, minutes = 0, onset, timer, vflag = 0; int dflag = 0; /* if non-zero, dump raw and filtered samples only; do not run detector */ int Rflag = 0; /* if non-zero, resample at 125 Hz */ int EyeClosing; /* eye-closing period, related to SR */ int ExpectPeriod; /* if no ABP pulse is detected over this period, the threshold is automatically reduced to a minimum value; the threshold is restored upon a detection */ int Ta, T0; /* high and low detection thresholds */ WFDB_Anninfo a; WFDB_Annotation annot; WFDB_Siginfo *s; WFDB_Time from = 0L, next_minute, spm, t, tpq, to = 0L, tt, t1; char *p, *prog_name(); static int gvmode = 0; void help(); pname = prog_name(argv[0]); for (i = 1; i < argc; i++) { if (*argv[i] == '-') switch (*(argv[i]+1)) { case 'd': /* dump filter data */ dflag = 1; break; 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': /* operate in WFDB_HIGHRES mode */ gvmode = WFDB_HIGHRES; break; case 'm': /* threshold */ if (++i >= argc || (Tm = atoi(argv[i])) <= 0) { (void)fprintf(stderr, "%s: threshold ( > 0) must follow -m\n", pname); exit(1); } break; case 'r': /* record name */ if (++i >= argc) { (void)fprintf(stderr, "%s: input record name must follow -r\n", pname); exit(1); } record = argv[i]; break; case 'R': /* resample */ Rflag = 1; break; case 's': /* signal */ if (++i >= argc) { (void)fprintf(stderr, "%s: signal number or name must follow -s\n", pname); exit(1); } sig = i; /* remember argument until record is open */ break; case 't': /* end time */ if (++i >= argc) { (void)fprintf(stderr, "%s: time must follow -t\n", pname); exit(1); } to = i; break; case 'v': /* verbose mode */ vflag = 1; 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 (gvmode == 0 && (p = getenv("WFDBGVMODE"))) gvmode = atoi(p); setgvmode(gvmode|WFDB_GVPAD); if ((nsig = isigopen(record, NULL, 0)) < 1) exit(2); if ((s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo))) == NULL) { (void)fprintf(stderr, "%s: insufficient memory\n", pname); exit(2); } a.name = "wabp"; a.stat = WFDB_WRITE; if ((nsig = wfdbinit(record, &a, 1, s, nsig)) < 1) exit(2); if (sig >= 0) sig = findsig(argv[sig]); if (sig < 0 || sig >= nsig) { /* Identify the lowest-numbered ABP, ART, or BP signal */ for (i = 0; i < nsig; i++) if (strcmp(trim_whitespace(s[i].desc), "ABP") == 0 || strcmp(s[i].desc, "ART") == 0 || strcmp(s[i].desc, "BP") == 0) break; if (i == nsig) { fprintf(stderr, "%s: no ABP signal specified; use -s option\n\n", pname); help(); exit(3); } sig = i; } if (vflag) fprintf(stderr, "%s: analyzing signal %d (%s)\n", pname, sig, s[sig].desc); sps = sampfreq((char *)NULL); if (Rflag) setifreq(sps = 125.); if (from > 0L) { if ((from = strtim(argv[from])) < 0L) from = -from; } if (to > 0L) { if ((to = strtim(argv[to])) < 0L) to = -to; } annot.subtyp = annot.num = 0; annot.chan = sig; annot.aux = NULL; Tm = physadu((unsigned)sig, Tm); samplingInterval = 1000.0/sps; spm = 60 * sps; next_minute = from + spm; EyeClosing = sps * EYE_CLS; /* set eye-closing period */ ExpectPeriod = sps * NDP; /* maximum expected RR interval */ SLPwindow = sps * SLPW; /* slope window size */ if (vflag) { printf("\n------------------------------------------------------\n"); printf("Record Name: %s\n", record); printf("Total Signals: %d (", nsig); for (i = 0; i < nsig - 1; i++) printf("%d, ", i); printf("%d)\n", nsig - 1); printf("Sampling Frequency: %.1f Hz\n", sps); printf("Sampling Interval: %.3f ms\n", samplingInterval); printf("Signal channel used for detection: %d\n", sig); printf("Eye-closing period: %d samples (%.0f ms)\n", EyeClosing, EyeClosing*samplingInterval); printf("Minimum threshold: %d\n", Tm); printf("\n------------------------------------------------------\n\n"); printf("Processing:\n"); } (void)sample(sig, 0L); if (dflag) { for (t = from; (to == 0L || t < to) && sample_valid(); t++) printf("%6d\t%6d\n", sample(sig, t), slpsamp(t)); exit(0); } /* Average the first 8 seconds of the slope samples to determine the initial thresholds Ta and T0 */ t1 = from + strtim("8"); for (T0 = 0, t = from; t < t1 && sample_valid(); t++) T0 += slpsamp(t); T0 /= t1 - from; Ta = 3 * T0; /* Main loop */ for (t = from; (to == 0L || t < to) && sample_valid(); t++) { static int learning = 1, T1; if (learning) { if (t > from + LPERIOD) { learning = 0; T1 = T0; t = from; /* start over */ } else T1 = 2*T0; } if (slpsamp(t) > T1) { /* found a possible ABP pulse near t */ timer = 0; /* used for counting the time after previous ABP pulse */ max = min = slpsamp(t); for (tt = t+1; tt < t + EyeClosing/2; tt++) if (slpsamp(tt) > max) max = slpsamp(tt); for (tt = t-1; tt > t - EyeClosing/2; tt--) if (slpsamp(tt) < min) min = slpsamp(tt); if (max > min+10) { onset = max/100 + 2; tpq = t - 5; for (tt = t; tt > t - EyeClosing/2; tt--) { if (slpsamp(tt) - slpsamp(tt-1) < onset) { tpq = tt; break; } } if (!learning) { /* Check that we haven't reached the end of the record. */ (void)sample(sig, tpq); if (sample_valid() == 0) break; /* Record an annotation at the ABP pulse onset */ annot.time = tpq; annot.anntyp = NORMAL; if (putann(0, &annot) < 0) { /* write the annotation */ wfdbquit(); /* close files if an error occurred */ exit(1); } } /* Adjust thresholds */ Ta += (max - Ta)/10; T1 = Ta / 3; /* Lock out further detections during the eye-closing period */ t += EyeClosing; } } else if (!learning) { /* Once past the learning period, decrease threshold if no pulse was detected recently. */ if (++timer > ExpectPeriod && Ta > Tm) { Ta--; T1 = Ta / 3; } } /* Keep track of progress by printing a dot for each minute analyzed */ if (t >= next_minute) { next_minute += spm; (void)fprintf(stderr, "."); (void)fflush(stderr); if (++minutes >= 60) { (void)fprintf(stderr, "\n"); minutes = 0; } } } (void)free(lbuf); (void)free(ebuf); wfdbquit(); /* close WFDB files */ fprintf(stderr, "\n"); if (vflag) { printf("\n\nDone! \n\nResulting annotation file: %s.wabp\n\n\n", record); } exit(0); }