Diff of /HRV.src/statnn.c [000000] .. [1a3ddc]

Switch to unified view

a b/HRV.src/statnn.c
1
/* statnn.c     Joe Mietus      Oct 7 2008 */
2
3
/* 
4
statnn :
5
Usage: statnn [options]
6
Reads stdin: time(sec), interval(sec), annotation
7
and calculates nn interval stats
8
Outputs nn/rr, avnn, sdnn, sdann,
9
sdnnindx, rmssd and pnn on stderr
10
  options :
11
  [-l len] : window length (default 5:00)
12
  [-m] : RR intervals in msec
13
  [-p nndif ...] : nn diffenence for pnn
14
  [-s] : short term stats
15
         nn/rr, avnn, sdnn, rmssd and pnn on stderr
16
  [-L] : print ratio avnn sdnn sdann sdnnindx rmssd pnns on one line
17
*/
18
19
#include <stdio.h>
20
#include <stdlib.h>
21
#include <math.h>
22
23
#define MAXBUF 2400
24
#define MAXP 10
25
#define NNDIF 0.05
26
#define ABS(A) ((A) < 0 ? -(A) : (A))
27
#define ROFFERR 1e-10
28
29
main(argc, argv)
30
int argc;
31
char *argv[];
32
{
33
34
    char ann, lastann[2];
35
    int i, j, len, lflag, mflag, sflag;
36
    int n, nb, nrr, totrr, nnn, totnn, totnnn, np;
37
    static int nnx[MAXP];
38
    double t, lastt, rr, lastrr, start, end, sum, sum2;
39
    double ratio, avnn, sdnn, sdann, sdnnindx, rmssd, pnnx;
40
    static double ratbuf[MAXBUF], avbuf[MAXBUF], sdbuf[MAXBUF];
41
    static double nndif[MAXP];
42
43
    /* default 5:00 non-overlapping segments */
44
    len = 300;
45
46
    lflag = mflag = sflag = 0;
47
    np = 1;
48
    nndif[0] = NNDIF;
49
50
    for (i=0; ++i < argc && *argv[i] == '-'; ) {
51
        switch(argv[i][1]) {
52
        case 'l':  len = strtim(argv[++i]);
53
                   break;
54
        case 'm':  mflag = 1;
55
                   break;
56
        case 'p':  for (np=0; np<MAXP && i+1<argc && *argv[i+1]!='-'; np++)
57
                       nndif[np] = atof(argv[++i]);
58
                   if (np==MAXP)
59
               while (i+1<argc && *argv[i+1] != '-')
60
                   i++;
61
                   break;
62
            case 's':  sflag = 1;
63
                   break;
64
        case 'L':  lflag = 1;
65
                   break;
66
            default :  usage(argv[0]);
67
                       exit(1);
68
        }
69
    }
70
71
    if (len < 60) {
72
        fprintf(stderr, "%s : len must be 1:00 or greater\n", argv[0]);
73
        exit(1);
74
    }
75
76
    for (j=0; j<np; j++) {
77
        if (nndif[j] > 1)
78
        nndif[j] /= 1000;
79
    if (mflag)
80
        nndif[j] *= 1000;
81
    }
82
83
    if (scanf("%lf %lf %c", &t, &rr, &ann) != 3) {
84
        fprintf(stderr, "%s : improperly formatted data\n", argv[0]);
85
        exit(2);
86
    }
87
88
    i = 0;
89
    totrr = nrr = 1;
90
    totnnn = totnn = nnn = 0;
91
    rmssd = sum = sum2 = 0.0;
92
93
    lastt = t;
94
    lastrr = rr;
95
    lastann[0] = 'X';
96
    lastann[1] = ann;
97
    end = t + len;
98
99
    while (scanf("%lf %lf %c", &t, &rr, &ann) == 3) {
100
101
    while (t > end+len) {
102
        i++;
103
        end += len;
104
    }
105
106
    if (t >= end) {
107
        if (nnn > 1) {
108
        ratbuf[i] = (double)nnn/nrr;
109
            sdbuf[i] = sqrt((sdbuf[i] - avbuf[i]*avbuf[i]/nnn) / (nnn-1));
110
            avbuf[i] /= nnn;
111
        }
112
        i++;
113
        nnn = nrr = 0;
114
        end += len;
115
        }
116
117
        nrr++;
118
    totrr++;
119
120
        if (ann == 'N' && lastann[1] == 'N') {
121
            nnn++;
122
        totnn++;
123
        avbuf[i] += rr;
124
        sum += rr;
125
        sdbuf[i] += rr*rr;
126
        sum2 += rr*rr;
127
        if (lastann[0] == 'N') {
128
          totnnn++;
129
            rmssd += (rr-lastrr)*(rr-lastrr);
130
131
        /* modified 6-15-01 */
132
        /* equal may not be equal do to round of error !! */
133
            /* if (ABS(rr-lastrr) > nndif) { */
134
135
        for (j=0; j<np; j++) {
136
            if (ABS(rr-lastrr) - nndif[j] > ROFFERR) { 
137
                nnx[j]++;
138
                }
139
        }
140
        }
141
    }
142
143
    lastrr = rr;
144
    lastann[0] = lastann[1];
145
    lastann[1] = ann;
146
147
    }
148
149
    if (nnn > 1) {
150
    ratbuf[i] = (double)nnn/nrr;
151
        sdbuf[i] = sqrt((sdbuf[i] - avbuf[i]*avbuf[i]/nnn) / (nnn-1));
152
        avbuf[i] /= nnn;
153
    }
154
155
    nb = ++i;
156
157
    if (lflag) {
158
        /* print NN/RR AVNN SDNN SDANN SDNNIDX rMSSD pNNs on one line */
159
        printf("%g", (double)totnn/totrr);
160
        printf(" %g", sum/totnn);
161
        printf(" %g", sqrt((sum2 - sum*sum/totnn) / (totnn-1)));
162
    }
163
    else {
164
        printf("NN/RR = %g\n", (double)totnn/totrr);
165
        printf("AVNN = %g\n", sum/totnn);
166
        printf("SDNN = %g\n", sqrt((sum2 - sum*sum/totnn) / (totnn-1)));
167
    }
168
169
    if (!sflag) {
170
        sum = sum2 = 0;
171
        for (i=0, n=0; i<nb; i++) {
172
            if (ratbuf[i] != 0) {
173
                 n++;
174
         sum += avbuf[i];
175
             sum2 += avbuf[i]*avbuf[i];
176
        }
177
        }
178
        if (lflag) {
179
            if (n > 1)
180
                printf(" %g", sqrt((sum2 - sum*sum/n) / (n-1)));
181
            else
182
                printf(" -");
183
        }
184
        else {
185
            if (n > 1)
186
                printf("SDANN = %g\n", sqrt((sum2 - sum*sum/n) / (n-1)));
187
            else
188
                printf("SDANN = -\n");
189
        }
190
191
        sum = 0;
192
        for (i=0, n=0; i<nb; i++) {
193
            if (ratbuf[i] != 0) {
194
            n++;
195
            sum += sdbuf[i];
196
        }
197
        }
198
        if (lflag) {
199
            if (n > 0)
200
                printf(" %g", sum/n);
201
            else
202
                printf(" -");
203
        }
204
        else {
205
            if (n > 0)
206
                 printf("SDNNIDX = %g\n", sum/n);
207
            else
208
                printf("SDNNIDX = -\n");
209
        }
210
    }
211
212
    if (lflag) {
213
        printf(" %g", sqrt(rmssd/totnnn));
214
        for (j=0; j<np; j++)
215
            printf(" %g", mflag ? 100*(double)nnx[j]/totnnn
216
                                : (double)nnx[j]/totnnn);
217
        printf("\n");
218
    }
219
    else {
220
        printf("rMSSD = %g\n", sqrt(rmssd/totnnn));
221
        for (j=0; j<np; j++) {
222
            printf("pNN%g = ", mflag ? nndif[j] : nndif[j]*1000);
223
            printf("%g\n", mflag ? 100*(double)nnx[j]/totnnn
224
                         : (double)nnx[j]/totnnn);
225
        }
226
    }
227
}
228
229
230
/* convert string in [[HH:]MM:]SS format to seconds */
231
232
strtim(buf)
233
char *buf;
234
{
235
        int x, y, z;
236
237
        switch (sscanf(buf, "%d:%d:%d", &x, &y, &z)) {
238
                case 1: return (x);
239
                case 2: return (60*x + y);
240
                case 3: return (3600*x + 60*y + z);
241
                default: return (-1);
242
        }
243
}
244
245
246
usage(prog)
247
char *prog;
248
{
249
        fprintf(stderr, "Usage: %s [options]\n", prog);
250
        fprintf(stderr, "Reads stdin: time(sec), interval(sec), annotation\n");
251
        fprintf(stderr, "and calculates nn interval stats\n");
252
        fprintf(stderr, "Outputs nn/rr, avnn, sdnn, sdann,\n");
253
        fprintf(stderr, "sdnnindx, rmssd and pnn on stderr\n");
254
    fprintf(stderr, "  options :\n");
255
        fprintf(stderr, "  [-l len] : window length (default 5:00)\n");
256
        fprintf(stderr, "  [-m] : RR intervals in msec\n");
257
        fprintf(stderr, "  [-p nndif ...] : nn diffenence for pnn\n");
258
        fprintf(stderr, "  [-s] : short term stats\n");
259
        fprintf(stderr, "         nn/rr, avnn, sdnn, rmssd and pnn on stderr\n");
260
    fprintf(stderr, "  [-L] : print ratio avnn sdnn sdann sdnnindx");
261
    fprintf(stderr, " rmssd pnns on one line\n");
262
}