int main(int argc, char **argv)
{
    int c;
    int inflag = 0;
    int dbg = 0;
    int sr_ds = 200;
    char * rec_name = "vfdb/427";
    char * db_path = "/opt/physiobank/database";
    size_t win_sec = 8;
    /* r stands for record with folder
     * p for path
     * i for information of record
     * s downsample sr
     * w window length default:8
     * d debug
     */
    while ((c = getopt(argc, argv, "idr:p:s:w:")) != -1)
        switch (c){
            case 'i':
                inflag = 1; 
                break;
            case 'r':
                rec_name = optarg;
                break;
            case 'p':
                db_path = optarg;
                break;
            case 's':
                sr_ds= atoi(optarg);
                break;
            case'w':
                win_sec = atoi(optarg);
                break;
            case'd':
                dbg = 1;
                break;
            default:
                abort();
        }            
    int i, j, nsig;
    WFDB_Sample *v;
    WFDB_Siginfo *s;
    WFDB_Anninfo a;
    setwfdb(db_path);
    
    nsig = isigopen(rec_name, NULL, 0);
    if (nsig < 1){
        printf("nsig:%d\n",nsig);
        exit(1);
    }
    s = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo));
    if (isigopen(rec_name, s, nsig) != nsig)
        exit(1);
    v = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample));

    int orig_sr = sampfreq(rec_name);
    a.name = "atr"; a.stat = WFDB_READ;
    if (wfdbinit(rec_name, &a, 1, s, nsig) != nsig) exit(3);
    if(1 == inflag ){
        printf("sr:%d\n",orig_sr);
        printf("%d signals\n", nsig);
        for (i = 0; i < nsig; i++) {
            printf("Group %d, Signal %d:\n", s[i].group, i); 
            printf("File: %s\n", s[i].fname);
            printf("Description: %s\n", s[i].desc);
            printf("Gain: ");
            if (s[i].gain == 0.) 
                printf("uncalibrated; assume %g", WFDB_DEFGAIN);
            else printf("%g", s[i].gain);
            printf(" adu/%s\n", s[i].units ? s[i].units : "mV");
            printf(" Initial value: %d\n", s[i].initval);
            printf(" Storage format: %d\n", s[i].fmt);
            printf(" I/O: ");
            if (s[i].bsize == 0) printf("can be unbuffered\n");
            else printf("%d-byte blocks\n", s[i].bsize);
            printf(" ADC resolution: %d bits\n", s[i].adcres);
            printf(" ADC zero: %d\n", s[i].adczero);
            if (s[i].nsamp > 0L) {
                printf(" Length: %s (%ld sample intervals)\n",
                       timstr(s[i].nsamp), s[i].nsamp);
                printf(" Checksum: %d\n", s[i].cksum);
            }
            else printf(" Length undefined\n");
        }
    }

    fifo_t fifo_ecg;
    int fifo_ecg_buf[FIFO_SIZE];
    fifo_init(&fifo_ecg, fifo_ecg_buf, FIFO_SIZE);

    fifo_t fifo_bt;
    int fifo_bt_buf[FIFO_SIZE];
    fifo_init(&fifo_bt, fifo_bt_buf, FIFO_SIZE);

    int tmp = 0;
    int sr = 200;
    WFDB_Time begin_samp = 0;
    WFDB_Time end_samp = orig_sr*win_sec;
    WFDB_Annotation begin_ann;
    WFDB_Annotation end_ann;
    getann(0, &begin_ann);
    while(0 == getann(0, &end_ann))
         if ((end_ann.aux != NULL && *end_ann.aux > 0)
                    ||0 == strcmp(annstr(end_ann.anntyp), "[")
                    ||0 == strcmp(annstr(end_ann.anntyp), "]")
                    ||0 == strcmp(annstr(end_ann.anntyp), "~")
                ){
            break;
        }
    
    int * pBt_len = (int*)calloc(win_sec,sizeof(int));
    ResetBDAC();
    for (; ;) {
        if (getvec(v) < 0)
            break;
//        for (j = 0; j < nsig; j++){
//        }
        tmp = v[nsig-1];
        tmp = v[0];
        int vout1 = 0;
        static int bt_i = 0;
        static unsigned int samplecnt = 0;
        int idx = 0;
        if(down_sample(tmp, &vout1, orig_sr, sr)) {
                samplecnt ++;
                fifo_write(&fifo_ecg, &vout1, 1*sizeof(int));
                int beatType, beatMatch;
                long ltmp = vout1-s[0].adczero;
                ltmp *= 200; ltmp /= s[0].gain;
                int bdac_dly = BeatDetectAndClassify(ltmp, &beatType, &beatMatch);
                idx = bt_i/sr;
                if (0 != bdac_dly ) {
                    pBt_len[idx]++;
                    fifo_write(&fifo_bt, &beatType, sizeof(int));
                }
                bt_i = ++bt_i%(win_sec*sr);
        }

        double cm = 0.0;

        int size = win_sec*sr;
        if(fifo_len(&fifo_ecg)/sizeof(int) >= sr*win_sec){
            int * win_data = (int*)malloc(win_sec*sr*sizeof(int));
            int * ds_data = (int*)malloc(win_sec*sr_ds*sizeof(int));
            
            int len = fifo_len(&fifo_bt)/sizeof(int);
            int * p = (int*)calloc(len, sizeof(int));
           
            if (0 != len){
               //printf("bt_i:%d\n", bt_i);
                fifo_read_steps(&fifo_bt, p, len*sizeof(int), pBt_len[bt_i/sr]*sizeof(int));
                //for (i = 0;i< len;i++) printf("%d ", p[i]);
                //printf("\n");

            }
            pBt_len[bt_i/sr] = 0;
            
            fifo_read_steps(&fifo_ecg, win_data, size*sizeof(int), sr*sizeof(int));
            filtering(win_data, size, sr);
            int i = 0;
            int ds_size = 0;
            int vout;
            for(i = 0;i < size;i++){
               // if(down_sample(win_data[i], &vout, sr, sr_ds)) ds_data[ds_size++] = vout;
            }
            double dven = 0.0;

            if (0 != len){
                int tmp_cnt = 0;
                for(i = 0; i < len ; i++){
                    if(5 == p[i]) dven ++;
                }
                //printf("div:%d %d\n", tmp_cnt, len);
                dven /= len; 
            }
                         
            //cm = ecg_complexity_measure(win_data, size);
            //cm = ecg_complexity_measure(ds_data, ds_size);
            //cm = cpsd(ds_data, ds_size, 0.5*sr_ds);
            //cm = calc_grid(ds_data, ds_size, 0.5*sr_ds);
            cm = calc_grid(win_data, size, 0.5*sr);


        
            if (-1 == cm ) continue;
            //VT print 1;
            //VF print 2;
            
            int hr =  (int)((double)(len*60)/win_sec+0.5);
            int ret = check_ann(begin_samp, end_samp, &begin_ann, &end_ann, "(VT");
            if (1 == ret){
                printf("%d %lf %lf %d\n", 1, cm, dven, hr);
            } else if (0 == ret) {
                ret = check_ann(begin_samp, end_samp, &begin_ann, &end_ann, "(VFL");
                int ret2 = check_ann(begin_samp, end_samp, &begin_ann, &end_ann, "[");
                if (1 == ret || 1 == ret2){
                    printf("%d %lf %lf %d\n", 2, cm, dven, hr);
                } else if (0 == ret){
//                    ret = check_ann(begin_samp, end_samp, &begin_ann, &end_ann, "(N");
//                    int ret3 = check_ann(begin_samp, end_samp, &begin_ann, &end_ann, "N");
//                    if ((1 == ret  || 1 == ret3) && -1 != begin_ann.subtyp) printf ("%d %lf %lf %d\n", 0, cm, dven, hr); 

                    if (1 == check_ann(begin_samp, end_samp, &begin_ann, &end_ann, "(AFIB") 
                        || 1 == check_ann(begin_samp, end_samp, &begin_ann, &end_ann, "(AFL")
                        || 1 == check_ann(begin_samp, end_samp, &begin_ann, &end_ann, "(IVR")
                        || 1 == check_ann(begin_samp, end_samp, &begin_ann, &end_ann, "(SVTA")
                        || 1 == check_ann(begin_samp, end_samp, &begin_ann, &end_ann, "(SBR")
                        || 1 == check_ann(begin_samp, end_samp, &begin_ann, &end_ann, "(BII")
                       ) printf ("%d %lf %lf %d\n", 0, cm, dven, hr); 
                    
                   // int ret = check_ann(begin_samp, end_samp, &begin_ann, &end_ann, "(SVTA");
                   // if (1 == ret)  printf ("%d %lf\n", 0, cm); 
                }
            }
            //iannsettime(begin_samp);
            begin_samp += orig_sr;
            end_samp += orig_sr;
            if(end_ann.time < begin_samp){
                begin_ann = end_ann;
                
                while(1)
                    if (0 != getann(0, &end_ann)){
                        end_ann = begin_ann;
                        /*the last sample of the signal*/
                        end_ann.time = s[nsig-1].nsamp;
                        break;
                    }else if ((end_ann.aux != NULL && *end_ann.aux > 0)
                                ||0 == strcmp(annstr(end_ann.anntyp), "[")
                                ||0 == strcmp(annstr(end_ann.anntyp), "]")
                                ||0 == strcmp(annstr(end_ann.anntyp), "~")
                            ){
                        break;
                    }
                if(dbg){
                    printf("begin tm:%s type:%s ", mstimstr(begin_ann.time), annstr(begin_ann.anntyp));
                    if(begin_ann.aux != NULL)
                        printf("begin aux:%s", begin_ann.aux+1);
                    printf("\n");
                    printf("end tm:%s type:%s ", mstimstr(end_ann.time), annstr(end_ann.anntyp));
                    if (end_ann.aux != NULL)
                        printf("end aux:%s", end_ann.aux+1);
                    printf("\n");

                    printf("begin sample:%s\n", mstimstr(begin_samp));
                    printf("ann diff:%s\n", mstimstr(end_ann.time-begin_ann.time));
                }
            }
            free(p);
            free(ds_data);
            free(win_data);
        }

    }
    free(pBt_len);
    wfdbquit();
    return 0;
}
Beispiel #2
0
void gettest()	/* get next test annotation */
{
    static long tt;	/* time of previous test beat annotation */
	 static struct WFDB_ann annot;

    tt = t;
    t = tprime;
    a = aprime;

    /* See comments on the similar code in getref(), above. */
    if (tt == 0L || t == huge_time ||
	(tt <= vfontest && vfontest < t) ||
	(tt <= sdontest && sdontest < t) ||
	(tt <= pvfontest && pvfontest < t) ||
	(tt <= psdontest && psdontest < t))
	rr = 0L;
    else
	rr = t - tt;

    if (oflag) test_annot = annot;

    while (getann(1, &annot) == 0) {
	if (isqrs(annot.anntyp) || Oflag) {
	    tprime = annot.time;
		 aprime = amap(annot.anntyp);
	    return;
	}
	if (annot.anntyp == NOISE) {
	    if ((annot.subtyp & 0x30) == 0x30) {
		psdontest = sdontest;
		psdofftest = sdofftest;
		sdontest = annot.time;
		if (getann(1, &annot) < 0) {
		    tprime = huge_time;
		    aprime = '*';
		    if (end_time > 0L)
			shut_down += end_time - sdontest;
		    else {
			(void)fprintf(stderr,
      "%s: unterminated shutdown starting at %s in record %s, annotator %s\n",
			      pname, timstr(sdontest), record, an[1].name);
			(void)fprintf(stderr,
			 " (not included in shutdown duration measurement)\n");
		    }
		    return;
		}
		if (annot.anntyp == NOISE &&
		    (annot.subtyp & 0x30) != 0x30)
		    sdofftest = annot.time;
		else {
		    if (vfofftest > t) sdontest = vfofftest + match_dt;
		    else sdontest = t + match_dt;
		    sdofftest = annot.time - match_dt;
		    if (sdontest > sdofftest) sdontest = sdofftest;
		    (void)ungetann(0, &annot);
		}
		/* update shutdown duration tally */
		shut_down += sdofftest - sdontest;
	    }
	}
	else if (annot.anntyp == VFON) {
	    pvfontest = vfontest;
	    pvfofftest = vfofftest;
	    vfontest = annot.time;
	    do {
		if (getann(1, &annot) < 0) {
		    tprime = huge_time;
		    aprime = '*';
		    return;
		}
	    } while (annot.anntyp != VFOFF);
	    vfofftest = annot.time;
	}
    }
    tprime = huge_time;
    aprime = '*';
}
Beispiel #3
0
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;
	    }
	}
    }
}
Beispiel #4
0
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);
}
Beispiel #5
0
INTEGER timstr_(INTEGER *time, char *string)
{
    strcpy(string, timstr((WFDB_Time)(*time)));
    cfstring(string);
    return (0L);
}
Beispiel #6
0
void info(void)
{
    char *info, *p;
    int i;
    WFDB_Time t;

    prep_signals();
    if (nsig < 0) {
	lwfail("The '.hea' file could not be read");
	return;
    }
    printf("{ \"info\":\n");
    printf("  { \"db\": %s,\n", p = strjson(db)); SFREE(p);
    printf("    \"record\": %s,\n", p = strjson(record)); SFREE(p);
    printf("    \"tfreq\": %g,\n", tfreq);
    p = timstr(0);
    if (*p == '[') {
        printf("    \"start\": \"%s\",\n", mstimstr(0L));
	printf("    \"end\": \"%s\",\n", mstimstr(-strtim("e")));
    }
    else {
        printf("    \"start\": null,\n");
	printf("    \"end\": null,\n");
    }
    t = strtim("e");
    if (t > (WFDB_Time)0) {
	p = mstimstr(t);
	while (*p == ' ') p++;
	printf("    \"duration\": \"%s\",\n", p);
    }
    else
	printf("    \"duration\": null,\n");

    if (nsig > 0) {
	printf("    \"signal\": [\n");
	for (i = 0; i < nsig; i++) {
	    printf("      { \"name\": %s,\n", p = strjson(sname[i])); SFREE(p);
	    printf("        \"tps\": %g,\n", tfreq/(ffreq*s[i].spf));
	    if (s[i].units) {
		printf("        \"units\": %s,\n", p = strjson(s[i].units));
		SFREE(p);
	    }
	    else
		printf("        \"units\": null,\n");
	    printf("        \"gain\": %g,\n",
		   s[i].gain ? s[i].gain : WFDB_DEFGAIN);
	    printf("        \"adcres\": %d,\n", s[i].adcres);
	    printf("        \"adczero\": %d,\n", s[i].adczero);
	    printf("        \"baseline\": %d\n", s[i].baseline);
	    printf("      }%s", i < nsig-1 ? ",\n" : "\n    ],\n");
	}
    }
    else
	printf("    \"signal\": null,\n");

    if (info = getinfo(recpath)) {
	printf("    \"note\": [\n      %s", p = strjson(info));
	while (info = getinfo((char *)NULL)) {
	    printf(",\n      %s", p = strjson(info));
	    SFREE(p);
	}
	printf("\n    ]\n");
    }
    else
	printf("    \"note\": null\n");

    printf("  },\n");
    lwpass();
}