double sampleRate = 0.0 ; double Vthresh = 0.0 ; double Tthresh = 0.0 ; double Vmin = 0.0 ; double Tmin = 0.0 ; /* file: analyze.c This file is a template for a challenge entry. Replace the contents of initialize(), analyze(), and finalize() with your own code. You may define other functions in this file if necessary; do not redefine main(), label(), open_files(), or close_input(). Before submitting your entry, don't forget to fill in your name, organization, and email address below! Author(s) : P. Langley, E. Bowers, N Brown, J Wilde, M Drinnan, A Murray Organization : Medical Physics Dept. Freeman Hospital, Newcaslte upon Tyne, UK email address : philip.langley@ncl.ac.uk */ /* Comment out any of these that the algorithm will not need. */ #if !defined(NOWFDB) // #define USE_DAT /* open the .dat (digitized ECG) file */ // #define USE_ANN /* open the .atr and .16a annotation files */ #endif #define USE_STF /* open the .stf (ST level function) file */ //#define USE_KLT /* open the .klt (QRS, ST principal components) file */ /* The variables defined here are initialized by the main program after initialize() is invoked, but before analyze() is called. Do not change their values! */ #if defined(USE_DAT) || defined(USE_ANN) #include int nsig; /* number of input signals (2 or 3) */ /* To read a sample at time t from signal s, use code such as v = sample(s, t); where s is the signal number (0, 1, or 2) t is elapsed time from the first sample (at t=0) in sample intervals (1 sample interval = 4 milliseconds) v is the unscaled digitizer output (-2048 to +2047); -2048 corresponds to -10.24 millivolts, and +2047 corresponds to +10.23 millivolts To read annotations, declare a WFDB_Annotation object: WFDB_Annotation a; Use getann(0, &a); to read the next annotation from the .atr file, or getann(1, &a); to read the next annotation from the .16a file. The contents of the annotation can then be read from 'a': a.time is the elapsed time of the annotation in sample intervals a.anntyp is a code indicating the annotation type; use #include to obtain symbolic definitions of the various annotation codes a.aux is a string describing the event at a.time; the first byte indicates the length of the remainder of the string in bytes (1 to 254) 'a' contains other attributes that are not significant in these files. For additional information, see the WFDB Programmer's Guide at http://www.physionet.org/physiotools/wpg/ */ #endif #if defined(USE_STF) #define cMaxST 100000 /* was 50000 */ FILE *stffile; /* may be used to read the contents of the .stf file */ double ST[ cMaxST ][ 10 ] ; int STSize = 0 ; #endif #if defined(USE_KLT) FILE *kltfile; /* may be used to read the contents of the .klt file */ #endif /* label() is defined in stclass.c -- use it to record your classifications */ void label(int event_id, char event_label); int first_call = 0; void initialize(void) /* called once, before input files are opened */ { first_call = 1; } void setup(void) /* called once by analyze, before beginning the analysis */ { char Line[ 1000 ] ; int Fields ; int Offset ; int ChanNo ; double a, b, c, d, e, f, g, h, i, j ; sampleRate = 250 ; STSize = 0 ; while( 1 ) { if( fgets( Line, sizeof( Line ) - 1, stffile ) == NULL ) break ; Fields = sscanf( Line, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", &a, &b, &c, &d, &e, &f, &g, &h, &i, &j ) ; if( Fields >= 4 ) { ST[ STSize ][ 0 ] = a ; ST[ STSize ][ 1 ] = b ; ST[ STSize ][ 2 ] = c ; ST[ STSize ][ 3 ] = d ; } if( Fields >= 7 ) { ST[ STSize ][ 4 ] = e ; ST[ STSize ][ 5 ] = f ; ST[ STSize ][ 6 ] = g ; } if( Fields >= 10 ) { ST[ STSize ][ 7 ] = h ; ST[ STSize ][ 8 ] = i ; ST[ STSize ][ 9 ] = j ; } STSize ++ ; } // convert to microV // convert time axis from samples to s for( Offset = 0 ; Offset < STSize ; Offset ++ ) { ST[ Offset ][ 0 ] /= sampleRate ; for( ChanNo = 1 ; ChanNo < 10 ; ChanNo ++ ) ST[ Offset ][ ChanNo ] *= 5.0 ; } Vthresh = 50; Tthresh = 40; Vmin = 100; Tmin = 30; } void analyze(int event_id, long event_time, int event_sig) { /* called once per event, in event_id order */ int channelNum ; int indEventT ; int Index ; int sample ; int count ; int eventEnd ; int ind50[ cMaxST ] ; int ind50Size ; int ind100[ cMaxST ] ; int ind100Size ; char verdict ; if (first_call) { setup(); first_call = 0; } channelNum = 3*event_sig+3; for( indEventT = 0 ; indEventT < STSize ; indEventT ++ ) if( ST[ indEventT ][ 0 ] >= event_time ) break ; // is deltaST greater than Vthres microV? if ( fabs( ST[ indEventT ][ channelNum ] ) < Vthresh ) { verdict = 'N' ; } else // find where deltaST drops below Vthres microV { ind50Size = 0 ; for( Index = indEventT ; Index < STSize ; Index ++ ) if( fabs(ST[ Index ][ channelNum ]) < Vthresh ) ind50[ ind50Size ++ ] = Index ; if( ind50Size == 0 ) // if it doesn't set ind50 to last sample { ind50[ 0 ] = STSize - 1 ; ind50Size = 1 ; eventEnd = ind50[ 0 ] ; } else // find where deltaST drops below Vthres microV for Tthres s or more { int count = 0 ; for( sample = 0 ; sample < ind50Size - 1 ; sample ++ ) { if( ( ind50[ sample + 1 ] - ind50[ sample ] ) == 1 ) { count ++ ; // count = count+1; // count in 2 s intervals if( count == Tthresh / 2 ) { eventEnd = ind50[ sample - 14 ] ; break; } } else count = 0 ; } } // does deltaST go above Vmin microV in this interval? ind100Size = 0 ; for( Index = indEventT ; Index < eventEnd ; Index ++ ) if( fabs(ST[ Index ][ channelNum ]) >= Vmin ) ind100[ ind100Size ++ ] = Index ; if( ind100Size == 0 ) { verdict = 'N' ; } else // does deltaST stay at greater than Vmin microV for Tmin s? // assume it doesn't to start with { verdict = 'N' ; count = 0; for ( sample = 1 ; sample < ind100Size - 1 ; sample ++ ) { if (( ind100[ sample+1 ] - ind100[ sample ] ) == 1 ) { count ++ ; // count in 2 s intervals if (count == (Tmin/2)) { verdict = 'I' ; break ; } // can't say if N or I if end of data is reached if (( ind100[sample+1 ] + indEventT ) == STSize ) { verdict = '?' ; fprintf(stderr, "? ...\n"); } } else count = 0; } } } label( event_id, verdict ) ; fprintf(stderr, "Event ID: %d Time: %ld Signal: %d Verdict: %c\n", event_id, event_time, event_sig, verdict); } void finalize(void) /* called once, after input files are closed, but before the .epo file has been written */ { fprintf(stderr, "done!\n"); }