Predicting Acute Hypotensive Episodes: The PhysioNet/Computing in Cardiology Challenge 2009 1.0.0

File: <base>/ahe-detect-1.0/ahelabel.c (2,826 bytes)
#include <stdio.h>
#include <wfdb/wfdb.h>
#include <wfdb/ecgcodes.h>

main(int argc, char **argv)
{
    static char *record, *p;
    static double map[30], m, msum;
    static int i, j, h, mapsig, minutes, n, nsig, seconds, spm, state, v;
    static WFDB_Anninfo ai;
    static WFDB_Annotation annot;
    static WFDB_Sample *x;
    static WFDB_Siginfo *si;
    static WFDB_Time t, tt;

    if (argc < 2) {
	fprintf(stderr, "usage: %s RECORD\n", argv[0]);
	exit(1);
    }

    record = argv[1];
    if ((nsig = isigopen(record, NULL, 0)) < 1) exit(1);
    si = (WFDB_Siginfo *)malloc(nsig * sizeof(WFDB_Siginfo));
    nsig = isigopen(record, si, nsig);
    x = (WFDB_Sample *)malloc(nsig * sizeof(WFDB_Sample));
    if ((mapsig = findsig("ABP Mean")) < 0) {
	fprintf(stderr, "%s: no ABP Mean signal for record %s\n",
		argv[0], argv[1]);
	exit(1);
    }
    ai.name = "ahe";
    ai.stat = WFDB_WRITE;
    if (annopen(record, &ai, 1) < 0) exit(1);
    spm = strtim("1:0");  /* samples per minute */

    for (p = timstr(0L); *p != ':'; p++)
	;
    minutes = atoi(p+1);
    if (spm == 60) {
	for (seconds = atoi(p+4); seconds < 60; seconds++, t++)
	    getvec(x);
    }
	
    while (1) {	/* process 1 minute of MAP per iteration, until end of data */
	annot.anntyp = NOTQRS;
	if (++minutes % 60 == 59) annot.anntyp = ARFCT;
	if (++i >= 30) i = 0;
	if (map[i] > 60.0) n--;		/* oldest MAP is normal */
	else if (map[i] > 10.0) h--;	/* oldest MAP is low */
	else if (t > 30*spm) n--;	/* assume invalid sample is normal */
	for (j = v = 0, msum = 0; j < spm; j++, t++) {
	    if (getvec(x) < 0) break;
	    m = aduphys(mapsig, x[mapsig]);
	    if (m > 0.0) { msum += m; v++; }
	}
	if (t < 0) t = -t;	/* absolute times returned as < 0 */
	if (j < spm) break; /* stop at end of data, discard remaining <60 sec */
	if (v > 0) map[i] = msum/v;
	else map[i] = 0;
	//	printf("%6ld %g\n", t, map[i]);
 	if (map[i] > 60.0) n++;		/* newest MAP is normal */
	else if (map[i] > 10.0) {
	    h++;	/* newest MAP is low */
	    annot.anntyp = SVPB;
	}
	else n++;			/* assume invalid sample is normal */
	switch (state) {
	case 0:		/* indeterminate state */
	    if (h >= 27) { /* hypotensive for >= 90% of last 30 minutes */
		annot.anntyp = PVC;
		for (tt = t - 30*spm; tt < t; tt += spm) {
		    annot.time = tt;
		    putann(0, &annot);
		}
		state = 1;
	    }
	    else if (n == 30) { /* normotensive for 100% of last 30 minutes */
		state = 2;
	    }
	    break;
	case 1:		/* hypotensive episode in progress */
	    if (h < 27) /* episode has ended */
		state = 0;
	    else
		annot.anntyp = PVC;
	    break;
	case 2:		/* normotensive episode in progress */
	    if (n < 30) /* episode has ended */
		state = 0;
	    break;
	}	    
	if (annot.anntyp) {
	    annot.time = t;
	    putann(0, &annot);
	}
    }
    wfdbquiet();
    wfdbquit();
}