示例#1
0
void process(char *record, FILE *ifile)
{
    char ofname[10], data[5];
    WFDB_Time t = -1;
    static WFDB_Siginfo si[2];
    static WFDB_Anninfo ai;
    static WFDB_Sample v[2];
    static WFDB_Annotation a;

    setsampfreq(250.0);	/* AHA DB is sampled at 250 Hz for each signal */
    sprintf(ofname, "%s.dat", record);
    si[0].fname = ofname;
    si[0].desc = "ECG0";
    si[0].units = "mV";
    si[0].gain = 400;
    si[0].fmt = 212;
    si[0].adcres = 12;
    si[1] = si[0];
    si[1].desc = "ECG1";
    ai.name = "atr";
    ai.stat = WFDB_WRITE;
    if (osigfopen(si, 2) != 2 || annopen(record, &ai, 1) < 0) {
	wfdbquit();
	return;
    }
    while (fread(data, 1, 5, ifile) == 5) {
	v[0] = (data[0] & 0xff) | ((data[1] << 8) & 0xff00);
	v[1] = (data[2] & 0xff) | ((data[3] << 8) & 0xff00);
	(void)putvec(v);
	if (data[4] != '.') {
	    a.anntyp = ammap(data[4]);
	    a.subtyp = (data[4] == 'U' ? -1 : 0);
	    a.time = t;
	    (void)putann(0, &a);
	}
	t++;
    }
    (void)newheader(record);
    wfdbquit();
    fprintf(stderr, "wrote %s.atr, $s.dat, and %s.hea\n", record,record,record);
    return;
}
示例#2
0
main()
{
    WFDB_Anninfo an[2];
    char record[8], iann[10], oann[10];
    WFDB_Annotation annot;

    printf("Type record name: ");
    fgets(record, 8, stdin); record[strlen(record)-1] = '\0';
    printf("Type input annotator name: ");
    fgets(iann, 10, stdin); iann[strlen(iann)-1] = '\0';
    printf("Type output annotator name: ");
    fgets(oann, 10, stdin); oann[strlen(oann)-1] = '\0';
    an[0].name = iann; an[0].stat = WFDB_READ;
    an[1].name = oann; an[1].stat = WFDB_WRITE;
    if (annopen(record, an, 2) < 0) exit(1);
    while (getann(0, &annot) == 0)
        if (isqrs(annot.anntyp)) {
            annot.anntyp = NORMAL;
            if (putann(0, &annot) < 0) break;
        }
    wfdbquit();
}
示例#3
0
文件: wfdbf.c 项目: cardionetics/wfdb
INTEGER putann_(INTEGER *annotator, INTEGER *time, INTEGER *anntyp, INTEGER *subtyp, INTEGER *chan, INTEGER *num, char *aux)
{
    static WFDB_Annotation oann;
    int i, j;
    char *p, *q = NULL;

    oann.time = *time;
    oann.anntyp = *anntyp;
    oann.subtyp = *subtyp;
    oann.chan = *chan;
    oann.num = *num;
    if (aux) {
	p = fcstring(aux);
	q = calloc(strlen(p)+2, 1);
	*q = strlen(p);
	strcpy(q+1, p);
    }
    oann.aux = q;
    i = putann((WFDB_Annotator)(*annotator), &oann);
    if (q) free(q);
    return (i);
}
示例#4
0
main(int argc, char **argv)
{
    char *oaname = "gqf";
    double HR;
    FILE *config = NULL;
    int a0 = 0, a1 = 0, **count, dn, i, ibest, ichosen = 0, j, *mbuf,
	n, niann = 0, nseg, tdn;
    WFDB_Anninfo *a;
    WFDB_Annotation annot;
    WFDB_Frequency spm;
    WFDB_Time t0, tf;

    pname = prog_name(argv[0]);

    for (i = 1; i < argc; i++) {
	if (*argv[i] == '-') switch (*(argv[i]+1)) {
	  case 'a':	/* input annotator names */
	      for (a0 = a1 = ++i; a1 < argc && *argv[a1] != '-'; a1++, i++)
		;
	    if ((niann = a1 - a0) < 2) {
		(void)fprintf(stderr,
			      "%s: input annotator names must follow -a\n",
			      pname);
		cleanup(1);
	    }
	    break;
	  case 'c':	/* configuration file */
	    if (++i >= argc) {
		(void)fprintf(stderr,
		     "%s: name of configuration file must follow -c\n", pname);
		cleanup(1);
	    }
	    if ((config = fopen(argv[i], "rt")) == NULL) {
		(void)fprintf(stderr,
		     "%s: can't read configuration file %s\n", pname, argv[i]);
		cleanup(1);
	    }
	    break;
	  case 'h':	/* help requested */
	    help();
	    cleanup(0);
	    break;
	  case 'o':	/* output annotator name */
	    if (++i >= argc) {
		(void)fprintf(stderr,
			      "%s: output annotator name must follow -o\n",
			      pname);
		cleanup(1);
	    }
	    oaname = argv[i];
	    break;
	  case 'r':	/* record name */
	    if (++i >= argc) {
		(void)fprintf(stderr, "%s: input record name must follow -r\n",
			      pname);
		cleanup(1);
	    }
	    record = argv[i];
	    break;
	  default:
	    (void)fprintf(stderr, "%s: unrecognized option %s\n", pname,
			  argv[i]);
	    cleanup(1);
	}
	else {
	    (void)fprintf(stderr, "%s: unrecognized argument %s\n", pname,
			  argv[i]);
	    cleanup(1);
	}
    }

    /* Quit unless record name and at least two annotator names specified. */
    if (record == NULL || niann < 2) {
	help();
	cleanup(1);
    }

    /* Set up annotator info. */
    a = gcalloc(sizeof(WFDB_Anninfo), niann+1);
    for (i = a0, j = 0; i < a1; i++, j++) {
	a[j].name = argv[i]; a[j].stat = WFDB_READ;
    }
    a[j].name = oaname; a[j].stat = WFDB_WRITE;

    /* Read a priori physiologic parameters from the configuration file if
       available. They can be adjusted in the configuration file for pediatric,
       fetal, or animal ECGs. */
    if (config) {
	char buf[256], *p;

	/* Read the configuration file a line at a time. */
	while (fgets(buf, sizeof(buf), config)) {
	    /* Skip comments (empty lines and lines beginning with `#'). */
	    if (buf[0] == '#' || buf[0] == '\n') continue;
	    /* Set parameters.  Each `getconf' below is executed once for
	       each non-comment line in the configuration file. */
	    getconf(HR, "%lf");
	}
	fclose(config);
    }

    /* If any a priori parameters were not specified in the configuration file,
       initialize them here (using values chosen for adult human ECGs). */
    if (HR == 0.0) HR = 75;

    spm = 60.0 * sampfreq(record);  /* sample intervals per minute */
    nseg = strtim("e")/spm;	    /* number of complete 1-minute intervals */

    /* Set up buffer for median calculation. */
    mbuf = gcalloc(sizeof(int), niann + 1);
    mbuf[niann] = HR;	/* initial median is HR */

    /* Set up arrays for HR minute-by-minute time series. */
    count = gcalloc(sizeof(int *), niann + 1);
    for (i = 0; i < niann; i++)
	count[i] = gcalloc(sizeof(int), nseg+1);

    /* Pass 1: Load the HR arrays. */
    if (annopen(record, a, niann) < 0) cleanup(2);
    for (i = 0; i < niann; i++) {
	for (tf = spm, j = 0; j < nseg+1; tf += spm, j++) {
	    n = 0;
	    while (getann(i, &annot) == 0 && annot.time < tf)
		if (isqrs(annot.anntyp)) n++;
	    count[i][j] = n;
	}
    }
    wfdbquit();

    /* Pass 2: Select the input annotations to be copied, and copy them. */
    if (annopen(record, a, niann+1) < 0) cleanup(2);
    for (j = 0, t0 = 0, tf = spm; j < nseg+1; j++, t0 = tf, tf += spm) {
	for (i = 0; i < niann; i++)
	    mbuf[i] = count[i][j];
	/* Note that the last element, mbuf[niann], is the previous median. */
	qsort(mbuf, niann+1, sizeof(int), icomp);
	/* If mbuf has an even number of members, the median is the mean of
	   the two central values. */
	if (niann & 1) mbuf[niann] = (mbuf[(niann-1)/2] + mbuf[(niann+1)/2])/2;
	/* Otherwise it's the single central value. */
	else mbuf[niann] = mbuf[niann/2];
	/* Find the input that best matches the prediction (the median). */
	for (i = 0, dn = 9999; i < niann; i++) {
	    tdn = mbuf[niann] - count[i][j];
	    if (tdn < 0) tdn = -tdn;
	    if (tdn < dn) { dn = tdn; ibest = i; }
	}
	/* If the best match is not the previously chosen input, avoid switching
	   the input unless it's more than 2 beats further from the median. */
	if (ibest != ichosen) {
	    tdn = mbuf[niann] - count[ichosen][j];
	    if (tdn < 0) tdn = -tdn;
	    if (tdn < dn + 3) ibest = ichosen;
	}
	ichosen = ibest;
	/* Copy the chosen annotations for this one-minute segment. */
	n = 0;
	while (getann(ichosen, &annot) == 0 && n <= count[ichosen][j]) {
	    if (annot.time >= t0 && isqrs(annot.anntyp)) {
		putann(0, &annot);
		n++;
	    }
	}
	ungetann(ichosen, &annot);
    }
    cleanup(0);
}
示例#5
0
文件: bxbep.c 项目: TheChetan/ECGCS
void pair(int ref, int test)	/* count a beat label pair */
{
    switch (ref) {
	case 'N': switch (test) {
		case 'N': Nn++; break;
		case 'S': Ns++; break;
		case 'V': Nv++; break;
		case 'F': Nf++; break;
		case 'Q': Nq++; break;
		case 'O': No++; break;
		case 'X': Nx++; break;
	    } break;
	case 'S': switch (test) {
		case 'N': Sn++; break;
		case 'S': Ss++; break;
		case 'V': Sv++; break;
		case 'F': Sf++; break;
		case 'Q': Sq++; break;
		case 'O': So++; break;
		case 'X': Sx++; break;
	    } break;
	case 'V': switch (test) {
		case 'N': Vn++; break;
		case 'S': Vs++; break;
		case 'V': Vv++; break;
		case 'F': Vf++; break;
		case 'Q': Vq++; break;
		case 'O': Vo++; break;
		case 'X': Vx++; break;
	    } break;
	case 'F': switch (test) {
		case 'N': Fn++; break;
		case 'S': Fs++; break;
		case 'V': Fv++; break;
		case 'F': Ff++; break;
		case 'Q': Fq++; break;
		case 'O': Fo++; break;
		case 'X': Fx++; break;
	    } break;
	case 'Q': switch (test) {
		case 'N': Qn++; break;
		case 'S': Qs++; break;
		case 'V': Qv++; break;
		case 'F': Qf++; break;
		case 'Q': Qq++; break;
		case 'O': Qo++; break;
		case 'X': Qx++; break;
	    } break;
	case 'O': switch (test) {
		case 'N': On++; break;
		case 'S': Os++; break;
		case 'V': Ov++; break;
		case 'F': Of++; break;
		case 'Q': Oq++; break;
	    } break;
	case 'X': switch (test) {
		case 'N': Xn++; break;
		case 'S': Xs++; break;
		case 'V': Xv++; break;
		case 'F': Xf++; break;
		case 'Q': Xq++; break;
	    } break;
    }

    /* Compute the RR interval error and update the sum of squared errors. */
    if (RR > 0L && rr > 0L) {
	double rre = RR - rr;

	ssrre += rre*rre;
	nrre++;
    }

    if (oflag) {
	if (ref == test) (void)putann(0, &test_annot);
	else {
		 struct WFDB_ann out_annot;
	    char auxp[3];

	    auxp[0] = 2; auxp[1] = ref; auxp[2] = test - 'A' + 'a';
	    if (test == 'O' || test == 'X')
		out_annot.time = T;
	    else
		out_annot.time = t;
	    out_annot.anntyp = NOTE;
	    out_annot.subtyp = out_annot.chan = out_annot.num = 0;
	    out_annot.aux = auxp;
	    (void)putann(0, &out_annot);
	}
    }
    if (verbose && ref != test) {
	if (ref == 'O' || ref == 'X')
	    (void)fprintf(stderr, "%c(%ld)/%c(%ld)\n", ref, t, test, t);
	else if (test == 'O' || test == 'X')
	    (void)fprintf(stderr, "%c(%ld)/%c(%ld)\n", ref, T, test, T);
	else
	    (void)fprintf(stderr, "%c(%ld)/%c(%ld)\n", ref, T, test, t);
    }
}
示例#6
0
文件: bxbep.c 项目: TheChetan/ECGCS
void genxcmp()
{
    int alen;
    static char mstring[550], *p, nullaux[1];

    if (ref_annot.anntyp == 0) getref();
    if (test_annot.anntyp == 0) gettest();
    if (!ref_annot.aux) ref_annot.aux = nullaux;
    if (!test_annot.aux) test_annot.aux = nullaux;
    while ((end_time > 0L && (T <= end_time || t <= end_time)) ||
	   (end_time == -1L && T != huge_time) ||
	   (end_time == 0L && T != huge_time && t != huge_time)) {
	for (p = mstring+1; p < mstring + *mstring; p++)
	    *p = '\0';
	if (t < T) {
	    /* Test annotation precedes reference annotation. */
	    if (T-t <= match_dt &&
		     (T-t < abs(T-tprime) || aprime == 'O')) {
		/* Annotation times match within the window. */
		if (test_annot.anntyp != ref_annot.anntyp ||
		    test_annot.subtyp != ref_annot.subtyp ||
		    test_annot.chan   != ref_annot.chan   ||
		    test_annot.num    != ref_annot.num    ||
		    strcmp(test_annot.aux, ref_annot.aux)) {
		    /* Annotation types, subtypes, ..., don't match. */
		    p = mstring+1;
		    (void)strcat(p, annstr(ref_annot.anntyp));
		    p += strlen(p);
		    if (test_annot.subtyp != ref_annot.subtyp ||
			test_annot.chan   != ref_annot.chan   ||
			test_annot.num    != ref_annot.num) {
			(void)sprintf(p, "[%d,%d,%d]", ref_annot.subtyp,
				ref_annot.chan, ref_annot.num);
			p += strlen(p);
		    }
		    if (*ref_annot.aux) {
			(void)sprintf(p, " (%s)", ref_annot.aux+1);
			p += strlen(p);
		    }
		    (void)sprintf(p, "/%s", annstr(test_annot.anntyp));
		    p += strlen(p);
		    if (*test_annot.aux)
			(void)sprintf(p, " (%s)", test_annot.aux+1);
		    alen = strlen(mstring+1);
		    if (alen > 254) {
			(void)fprintf(stderr,
				      "aux string truncated at %s (%ld)\n",
				timstr(test_annot.time), test_annot.time);
			alen = 254;
			mstring[alen+1] = '\0';
		    }
		    mstring[0] = alen;
		    test_annot.aux = mstring;
		    test_annot.anntyp = NOTE;
		}
		(void)putann(0, &test_annot);
		getref();
		gettest();
		if (!ref_annot.aux) ref_annot.aux = nullaux;
		if (!test_annot.aux) test_annot.aux = nullaux;
	    }
	    else {
		/* No matching reference annotation. */
		p = mstring+1;
		(void)sprintf(p, "%c/%s",
			   rpann(test_annot.time), annstr(test_annot.anntyp));
		p += strlen(p);
		if (*test_annot.aux)
		    (void)sprintf(p, " (%s)", test_annot.aux+1);
		alen = strlen(mstring+1);
		if (alen > 254) {
		    (void)fprintf(stderr, "aux string truncated at %s (%ld)\n",
			    timstr(test_annot.time), test_annot.time);
		    alen = 254;
		    mstring[alen+1] = '\0';
		}
		mstring[0] = alen;
		test_annot.aux = mstring;
		test_annot.anntyp = NOTE;
		(void)putann(0, &test_annot);
		gettest();
		if (!test_annot.aux) test_annot.aux = nullaux;
	    }
	}
	else {
	    /* Reference annotation precedes test annotation. */
	    if (t-T <= match_dt &&
		     (t-T < abs(t-Tprime) || Aprime == 'O')) {
		/* Annotation times match within the window. */
		if (test_annot.anntyp != ref_annot.anntyp ||
		    test_annot.subtyp != ref_annot.subtyp ||
		    test_annot.chan   != ref_annot.chan   ||
		    test_annot.num    != ref_annot.num    ||
		    strcmp(test_annot.aux, ref_annot.aux)) {
		    /* Annotation types, subtypes, ..., don't match. */
		    p = mstring+1;
		    (void)strcat(p, annstr(ref_annot.anntyp));
		    p += strlen(p);
		    if (test_annot.subtyp != ref_annot.subtyp ||
			test_annot.chan   != ref_annot.chan   ||
			test_annot.num    != ref_annot.num) {
			(void)sprintf(p, "[%d,%d,%d]", ref_annot.subtyp,
				ref_annot.chan, ref_annot.num);
			p += strlen(p);
		    }
		    if (*ref_annot.aux) {
			(void)sprintf(p, " (%s)", ref_annot.aux+1);
			p += strlen(p);
		    }
		    (void)sprintf(p, "/%s", annstr(test_annot.anntyp));
		    p += strlen(p);
		    if (*test_annot.aux)
			(void)sprintf(p, " (%s)", test_annot.aux+1);
		    alen = strlen(mstring+1);
		    if (alen > 254) {
			(void)fprintf(stderr,
				      "aux string truncated at %s (%ld)\n",
				timstr(test_annot.time), test_annot.time);
			alen = 254;
			mstring[alen+1] = '\0';
		    }
		    mstring[0] = alen;
		    test_annot.aux = mstring;
		    test_annot.anntyp = NOTE;
		}
		(void)putann(0, &test_annot);
		getref();
		gettest();
		if (!ref_annot.aux) ref_annot.aux = nullaux;
		if (!test_annot.aux) test_annot.aux = nullaux;
	    }
	    else {
		/* No matching test annotation. */
		p = mstring+1;
		(void)sprintf(p, "%s", annstr(ref_annot.anntyp));
		p += strlen(p);
		if (*ref_annot.aux) {
		    (void)sprintf(p, " (%s)", ref_annot.aux+1);
		    p += strlen(p);
		}
		(void)sprintf(p, "/%c", tpann(ref_annot.time));
		alen = strlen(mstring+1);
		if (alen > 254) {
		    (void)fprintf(stderr, "aux string truncated at %s (%ld)\n",
			    timstr(ref_annot.time), ref_annot.time);
		    alen = 254;
		    mstring[alen+1] = '\0';
		}
		mstring[0] = alen;
		ref_annot.aux = mstring;
		ref_annot.anntyp = NOTE;
		(void)putann(0, &ref_annot);
		getref();
		if (!ref_annot.aux) ref_annot.aux = nullaux;
	    }
	}
    }
}
示例#7
0
文件: wqrs.c 项目: bemoody/wfdb
main(int argc, char **argv)
{ 
    char *p;
    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 jflag = 0;		     /* if non-zero, annotate J-points */
    int Rflag = 0;		     /* if non-zero, resample at 120 or 150 Hz
				      */
    int EyeClosing;                  /* eye-closing period, related to SR */
    int ExpectPeriod;                /* if no QRS is detected over this period,
					the threshold is automatically reduced
					to a minimum value;  the threshold is
					restored upon a detection */
    double Ta, T0;		     /* high and low detection thresholds */
    WFDB_Anninfo a;
    WFDB_Annotation annot;
    WFDB_Gain gain;
    WFDB_Siginfo *s;
    WFDB_Time from = 0L, next_minute, spm, t, tj, tpq, to = 0L, tt, t1;
    static int gvmode = WFDB_GVPAD | WFDB_LOWRES;
    char *prog_name();
    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_GVPAD | WFDB_HIGHRES;
	    break;
	  case 'j':	/* annotate J-points (ends of QRS complexes) */
	    jflag = 1;
	    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 'p':	/* specify power line (mains) frequency */
	    if (++i >= argc || (PWFreq = atoi(argv[i])) <= 0) {
		(void)fprintf(stderr,
			    "%s: power line frequency ( > 0) must follow -p\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 the argument until the 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);
    }
    if ((nsig = isigopen(record, s, nsig)) < 1) exit(2);
    sps = sampfreq((char *)NULL);
    if (sps < PWFreq) {
	(void)fprintf(stderr, "%s: sampling frequency (%g Hz) is too low%s",
		      pname, sps,
		      (gvmode & WFDB_HIGHRES) ? "\n" : ", try -H option\n");
	exit(3);
    }
    if (gvmode & WFDB_HIGHRES)
	setafreq(sampfreq((char *)NULL));
    a.name = "wqrs"; a.stat = WFDB_WRITE;
    if (annopen(record, &a, 1) < 0) exit(2);
    if (sig >= 0) sig = findsig(argv[sig]);
    if (sig < 0 || sig >= nsig) sig = 0;
    if ((gain = s[sig].gain) == 0.0) gain = WFDB_DEFGAIN;
    if (Rflag) {
    	if (PWFreq == 60.0) setifreq(sps = 120.);
    	else setifreq(sps = 150.);
    }
    if (from > 0L) {
	if ((from = strtim(argv[from])) < 0L)
	from = -from;
    }
    if (to > 0L) {
	if ((to = strtim(argv[to])) < 0L)
	    to = -to;
    }
    else
	to = strtim("e");

    annot.subtyp = annot.num = 0;
    annot.chan = sig;
    annot.aux = NULL;
    Tm = muvadu((unsigned)sig, Tm);
    samplingInterval = 1000.0/sps;
    lfsc = 1.25*gain*gain/sps;	/* length function scale constant */
    spm = 60 * sps;
    next_minute = from + spm;
    LPn = sps/PWFreq; 		/* The LP filter will have a notch at the
				    power line (mains) frequency */
    if (LPn > 8)  LPn = 8;	/* avoid filtering too agressively */
    LP2n = 2 * LPn;
    EyeClosing = sps * EYE_CLS; /* set eye-closing period */
    ExpectPeriod = sps * NDP;	/* maximum expected RR interval */
    LTwindow = sps * MaxQRSw;   /* length transform window size */

    (void)sample(sig, 0L);
    if (dflag) {
	for (t = from; t < to || (to == 0L && sample_valid()); t++)
	    printf("%6d\t%6d\n", sample(sig, t), ltsamp(t));
	exit(0);
    }

    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 A/D units (%d microvolts)\n",
	       Tm, adumuv(sig, Tm));
	printf("Power line frequency:    %d Hz\n", PWFreq);
	printf("\n------------------------------------------------------\n\n");
	printf("Processing:\n");
    }

    /* Average the first 8 seconds of the length-transformed samples
       to determine the initial thresholds Ta and T0. The number of samples
       in the average is limited to half of the ltsamp buffer if the sampling
       frequency exceeds about 2 KHz. */
    if ((t1 = strtim("8")) > BUFLN*0.9)
	t1 = BUFLN/2;
    t1 += from;
    for (T0 = 0, t = from; t < t1 && sample_valid(); t++)
	T0 += ltsamp(t);
    T0 /= t1 - from;
    Ta = 3 * T0;

    /* Main loop */
    for (t = from; t < to || (to == 0L && sample_valid()); t++) {
	static int learning = 1, T1;
	
	if (learning) {
	    if (t > t1) {
		learning = 0;
		T1 = T0;
		t = from;	/* start over */
	    }
	    else
		T1 = 2*T0;
	}
	
	/* Compare a length-transformed sample against T1. */
	if (ltsamp(t) > T1) {	/* found a possible QRS near t */
	    timer = 0; /* used for counting the time after previous QRS */
	    max = min = ltsamp(t);
	    for (tt = t+1; tt < t + EyeClosing/2; tt++)
		if (ltsamp(tt) > max) max = ltsamp(tt);
	    for (tt = t-1; tt > t - EyeClosing/2; tt--)
		if (ltsamp(tt) < min) min = ltsamp(tt);
	    if (max > min+10) { /* There is a QRS near tt */
		/* Find the QRS onset (PQ junction) */
		onset = max/100 + 2;
		tpq = t - 5;
		for (tt = t; tt > t - EyeClosing/2; tt--) {
		    if (ltsamp(tt)   - ltsamp(tt-1) < onset &&
			ltsamp(tt-1) - ltsamp(tt-2) < onset &&
			ltsamp(tt-2) - ltsamp(tt-3) < onset &&
			ltsamp(tt-3) - ltsamp(tt-4) < onset) {
			tpq = tt - LP2n;	/* account for phase shift */
			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 QRS onset */
		    annot.time = tpq;
		    annot.anntyp = NORMAL;
		    if (putann(0, &annot) < 0) { /* write the annotation */
			wfdbquit();	/* close files if an error occurred */
			exit(1);
		    }
		    if (jflag) {
			/* Find the end of the QRS */
			for (tt = t, tj = t + 5; tt < t + EyeClosing/2; tt++) {
			    if (ltsamp(tt) > max - (max/10)) {
				tj = tt;
				break;
			    }
			}
			(void)sample(sig, tj);
			if (sample_valid() == 0) break;
			/* Record an annotation at the J-point */
			annot.time = tj;
			annot.anntyp = JPT;
			if (putann(0, &annot) < 0) {
			    wfdbquit();
			    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 QRS
	       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, " %s\n", timstr(t));
		minutes = 0;
	    }
	}
    }
    if (minutes) (void)fprintf(stderr, " %s\n", timstr(t));

    (void)free(lbuf);
    (void)free(ebuf);
    wfdbquit();		        /* close WFDB files */
    fprintf(stderr, "\n");
    if (vflag) {
	printf("\n\nDone! \n\nResulting annotation file:  %s.wqrs\n\n\n",
	       record);
    }
    exit(0);
}
示例#8
0
MAINTYPE main()
	{
	char record[10], fname[20] ;
	int i, ecg[2], delay, recNum ;
	WFDB_Siginfo s[2] ;
	WFDB_Anninfo a[2] ;
	WFDB_Annotation annot ;

	unsigned char byte ;
	FILE *newAnn0, *newAnn1 ;
	long SampleCount = 0, lTemp, DetectionTime ;
	int beatType, beatMatch ;

	// Set up path to database directory

	setwfdb(ECG_DB_PATH) ;

	// Analyze all 48 MIT/BIH Records.

	for(recNum = 0; recNum < REC_COUNT; ++recNum)
		{
		sprintf(record,"%d",Records[recNum]) ;
		printf("Record %d\n",Records[recNum]) ;

		// Open a 2 channel record

		if(isigopen(record,s,2) < 1)
			{
			printf("Couldn't open %s\n",record) ;
			return ;
			}

		ADCZero = s[0].adczero ;
		ADCUnit = s[0].gain ;
		InputFileSampleFrequency = sampfreq(record) ;

		// Setup for output annotations

		a[0].name = "atest"; a[0].stat = WFDB_WRITE ;

		if(annopen(record, a, 1) < 0)
			return ;

		// Initialize sampling frequency adjustment.

		NextSample(ecg,2,InputFileSampleFrequency,SAMPLE_RATE,1) ;

		// Initialize beat detection and classification.

		ResetBDAC() ;
		SampleCount = 0 ;

		// Read data from MIT/BIH file until there is none left.

		while(NextSample(ecg,2,InputFileSampleFrequency,SAMPLE_RATE,0) >= 0)
			{
			++SampleCount ;

			// Set baseline to 0 and resolution to 5 mV/lsb (200 units/mV)

			lTemp = ecg[0]-ADCZero ;
			lTemp *= 200 ;			lTemp /= ADCUnit ;			ecg[0] = lTemp ;

			// Pass sample to beat detection and classification.

			delay = BeatDetectAndClassify(ecg[0], &beatType, &beatMatch) ;

			// If a beat was detected, annotate the beat location
			// and type.

			if(delay != 0)
				{
				DetectionTime = SampleCount - delay ;

				// Convert sample count to input file sample
				// rate.

				DetectionTime *= InputFileSampleFrequency ;
				DetectionTime /= SAMPLE_RATE ;
				annot.time = DetectionTime ;
				annot.anntyp = beatType ;
				annot.aux = NULL ;
				putann(0,&annot) ;
				}
			}

		// Reset database after record is done.

		wfdbquit() ;

#if 0
		/* This code is obsolete.  The annotation files are always
		   written into "<record>.ate" in the current directory.
                   They do not need to be copied in order to be read by bxbep,
		   if the WFDB path includes both the current current directory
		   and the one containing the .atr reference annotation files.
                 */

		// Copy "atest.<record>" to "<record>.ate" for future ascess.
		// (This is necessary for PC files)

		sprintf(fname,"%s.ate",record) ;
		newAnn0 = fopen(fname,"rb") ;
		sprintf(fname,"%s%s.ate",ECG_DB_PATH,record) ;
		newAnn1 = fopen(fname,"wb") ;

		// Copy byte image of annotation file in this
		// directory to a correctly named file in the
		// database directory.

		while(fread(&byte,sizeof(char),1,newAnn0) == 1)
			fwrite(&byte,sizeof(char),1,newAnn1) ;

		fclose(newAnn0) ;
		fclose(newAnn1) ;
#endif
		}
	}
示例#9
0
文件: wabp.c 项目: DanielEColi/wfdb
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);
}