Mercurial > hg > aim92
comparison saitools/saigraph.c @ 0:5242703e91d3 tip
Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author | tomwalters |
---|---|
date | Fri, 20 May 2011 15:19:45 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:5242703e91d3 |
---|---|
1 /* | |
2 Copyright (c) Applied Psychology Unit, Medical Research Council. 1993 | |
3 =========================================================================== | |
4 | |
5 Permission to use, copy, modify, and distribute this software without fee | |
6 is hereby granted for research purposes, provided that this copyright | |
7 notice appears in all copies and in all supporting documentation, and that | |
8 the software is not redistributed for any fee (except for a nominal | |
9 shipping charge). Anyone wanting to incorporate all or part of this | |
10 software in a commercial product must obtain a license from the Medical | |
11 Research Council. | |
12 | |
13 The MRC makes no representations about the suitability of this | |
14 software for any purpose. It is provided "as is" without express or | |
15 implied warranty. | |
16 | |
17 THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | |
18 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | |
19 THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES | |
20 OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
21 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |
22 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | |
23 SOFTWARE. | |
24 */ | |
25 | |
26 /*------------------------------------------------------------------------*/ | |
27 | |
28 /* saigraph.c | |
29 * -------------- | |
30 * | |
31 * Works out the (first-order) temporal intervals between peaks in a .sai file, | |
32 * and saves them in a SINGLE-FRAME .sai | |
33 * In essence, a histogram. | |
34 * | |
35 * Uses ALL peaks: if you just want the locallly maxima peaks, then use | |
36 * trbigpeak first. | |
37 * | |
38 * Output is another .sai file: but only a single frame. The header is | |
39 * modified accordingly. | |
40 * | |
41 * | |
42 * | |
43 * M. Akeroyd. May 1993. Version 2.0 | |
44 * | |
45 * Autumn 1993: added grayscaleflag | |
46 * Winter 1994: allowed weighting, and other general revisions. | |
47 */ | |
48 | |
49 | |
50 | |
51 #include <stdio.h> | |
52 #include <string.h> | |
53 #include <stdlib.h> | |
54 | |
55 #include "tip.h" | |
56 | |
57 | |
58 /* Function declarations */ | |
59 /*------------------------------------------------------------*/ | |
60 | |
61 void parsecommandline (int argc, char *argv[], char inputfn[], char outputfn[]); | |
62 | |
63 int readheader(FILE *inputfp); | |
64 void checkheader(); | |
65 void writeheader(FILE *outputfp); | |
66 | |
67 void changeheader(int no_frames, int new_pwidth, int new_nwidth, int framewidth_samples_output); | |
68 | |
69 int findpeaksreverse (); | |
70 void find_intervals(int total_peaks, int channel, int max_interval); | |
71 | |
72 void writedata_output (FILE *outputfp, int samples_to_write); | |
73 void writedata_output_fg (FILE *figurefp, FILE *groundfp, int samples_to_write); | |
74 FILE *open_file (char filefn[], FILE *dir_default, int streamtype); | |
75 | |
76 void copytooutput_fg_single (int total_peaks, int frame, int channel, int trigger_peak); | |
77 | |
78 void write_matrix_hori_time(int framewidth, FILE *outputfigurefp); | |
79 void write_matrix_hori_freq(int framewidth, FILE *outputfigurefp); | |
80 | |
81 | |
82 | |
83 | |
84 /* Data arrays: global */ | |
85 /*-----------------------------------------------------------------*/ | |
86 | |
87 | |
88 short inputdata[MAX_DATA]; /* input .sai: a single channel of a frame */ | |
89 short outputdata[MAX_DATA]; /* output .sai: a single channel */ | |
90 short outputfiguredata[MAX_DATA]; /* output figure.sai: a single channel */ | |
91 short outputgrounddata[MAX_DATA]; /* output ground.sai: a single channel */ | |
92 short clip[MAX_CHANNELS]; | |
93 | |
94 short interval[MAX_CHANNELS][MAX_DATA]; /* histogram */ | |
95 short summation[MAX_CHANNELS]; | |
96 | |
97 | |
98 | |
99 /* other variables */ | |
100 /*----------------------------------------------------------------*/ | |
101 | |
102 struct Peak peak[MAX_PEAKS]; /* used in findpeaksreverse(): | |
103 * single channel */ | |
104 struct NextEvent nextevent[MAX_NEXTEVENTS]; /* used in findpeaksreverse(): | |
105 * single channel */ | |
106 | |
107 | |
108 | |
109 /* variables read from header */ | |
110 /*---------------------------------------------------------------*/ | |
111 | |
112 char header[MAX_LINES_HEADER][MAX_LINE_LENGTH]; | |
113 int header_lines; | |
114 | |
115 int no_frames; | |
116 int frameheight; /* number of channels */ | |
117 int framewidth_samples; /* pwidth + nwidth * samplerate */ | |
118 int frameshift_samples; /* frstep_aid * samplerate */ | |
119 int pwidth; /* in msecs */ | |
120 int nwidth; /* in msecs: NEGATIVE */ | |
121 int width_win; /* pixels */ | |
122 int height_win; /* pixels */ | |
123 long samplerate; /* samples per sec */ | |
124 int mincf; /* Hz */ | |
125 int maxcf; /* Hz */ | |
126 | |
127 | |
128 | |
129 | |
130 /* misc */ | |
131 /*-----------------------------------------------------------*/ | |
132 | |
133 char progname[MAX_STRING_LENGTH]; | |
134 char outputfigurefn[MAX_STRING_LENGTH]; | |
135 | |
136 | |
137 int verboseflag = OFF; /* -v */ | |
138 int removeflag = OFF; /* -r */ | |
139 double removevalue = 0.1; | |
140 int widthflag = OFF; /* -width : if OFF, copy pwdith/nwidth | |
141 * off Input .sai */ | |
142 int total_width; /* -width : total width of new .sai */ | |
143 int asciiflag = OFF; /* -a */ | |
144 int asciireverseflag = OFF; /* -ar */ | |
145 int summationflag = OFF; /* -s */ | |
146 int greyscaleflag = OFF; /* -g */ | |
147 int weightflag = OFF; /* -weight */ | |
148 int oppositearchflag = OFF; /* -oparch: if ON, then the header-reading | |
149 * code will load one (1) extra byte. This | |
150 * is so that Sun .sai/.nap can be read | |
151 * on a DEC, and equally the reverse. | |
152 * It is NOT required if reading Sun on | |
153 * Sun, or DEC on DEC. */ | |
154 | |
155 | |
156 | |
157 /*............... Main ................................*/ | |
158 /*.........................................................................*/ | |
159 /*.........................................................................*/ | |
160 | |
161 | |
162 | |
163 void main (int argc, char *argv[]) | |
164 { | |
165 int sample; | |
166 int n; | |
167 | |
168 int frame, channel; | |
169 int trigger_peak = 0; | |
170 int no_peak = 0, total_peaks =0, total_peaks_2; | |
171 int framewidth_samples_input, | |
172 framewidth_samples_output; | |
173 int new_pwidth, | |
174 new_nwidth; | |
175 int header_bytes = 0; | |
176 | |
177 char inputfn[MAX_STRING_LENGTH], | |
178 outputbasefn[MAX_STRING_LENGTH]; | |
179 | |
180 FILE *inputfp, *outputfigurefp; | |
181 | |
182 int clipflag = OFF; | |
183 | |
184 /*-----------------------------------------*/ | |
185 | |
186 strcpy(progname, argv[0]); | |
187 strcpy(inputfn, ""); | |
188 strcpy(outputbasefn, ""); | |
189 strcpy(outputfigurefn, ""); | |
190 | |
191 /* parse command line */ | |
192 parsecommandline(argc, argv, inputfn, outputbasefn); | |
193 | |
194 if (strcmp(outputbasefn, "") == 0) | |
195 strcpy(outputfigurefn, ""); | |
196 else | |
197 strcpy(outputfigurefn, outputbasefn); | |
198 | |
199 | |
200 /* open files */ | |
201 /* default directions are: | |
202 * input = stdin | |
203 * figure = stdout | |
204 */ | |
205 | |
206 inputfp = open_file(inputfn, stdin, READ); | |
207 outputfigurefp = open_file(outputfigurefn, stdout, WRITE); | |
208 | |
209 /* read Header */ | |
210 header_bytes = readheader(inputfp); | |
211 checkheader(); | |
212 | |
213 | |
214 /* reset the variables */ | |
215 framewidth_samples_input = framewidth_samples; | |
216 if (widthflag == OFF) { | |
217 new_pwidth = + pwidth; | |
218 new_nwidth = -nwidth; | |
219 framewidth_samples_output = framewidth_samples_input;} | |
220 else { | |
221 new_pwidth = + NEW_PWIDTH; | |
222 new_nwidth = (new_pwidth + total_width); | |
223 framewidth_samples_output = (int) ((int) (abs(new_pwidth) + abs (new_nwidth)) * samplerate ) / 1000;} | |
224 | |
225 if (framewidth_samples_output >= MAX_DATA) { | |
226 fprintf(stderr, "%s: new frame is too wide at %i: only allowed %i samples\n", progname, framewidth_samples_output, MAX_DATA); | |
227 exit(-1); } | |
228 | |
229 | |
230 /* change header */ | |
231 changeheader(1, new_pwidth, new_nwidth, framewidth_samples_output); | |
232 | |
233 /* write header */ | |
234 if (asciiflag == OFF) | |
235 writeheader(outputfigurefp); | |
236 else { | |
237 /* begining of ascii header. The rest depends on the matrix format ... */ | |
238 fprintf(outputfigurefp, "# saigraph output. %s\n", inputfn); | |
239 fprintf(outputfigurefp, "# \n"); | |
240 fprintf(outputfigurefp, "# samplerate=%i pwidth=%d nwidth=%d frames=%i ", samplerate, pwidth, nwidth, no_frames); | |
241 fprintf(outputfigurefp, " mincf=%i maxcf=%i channels=%i \n", mincf, maxcf, frameheight); | |
242 fprintf(outputfigurefp, "# \n"); | |
243 } | |
244 | |
245 /*------------------------------------------*/ | |
246 | |
247 /* Main loop */ | |
248 | |
249 if (verboseflag == ON) { | |
250 fprintf(stderr, " frames "); | |
251 fflush(stderr);} | |
252 | |
253 | |
254 /* clear arrays */ | |
255 | |
256 for (channel=0; channel<MAX_CHANNELS; channel++) { | |
257 for(sample=0; sample<MAX_DATA; sample++) | |
258 interval[channel][sample] = 0; | |
259 clip[channel]=OFF; | |
260 } | |
261 | |
262 | |
263 /* reset this, so everything still works */ | |
264 framewidth_samples = framewidth_samples_input; | |
265 | |
266 | |
267 for (frame=1; frame<=no_frames; frame++) { | |
268 | |
269 if (verboseflag == ON) { | |
270 fprintf(stderr, " %i ", frame); | |
271 fflush(stderr);} | |
272 | |
273 /*--------------------------------------------*/ | |
274 | |
275 /* load the whole frame's worth of data first */ | |
276 | |
277 for (channel=1; channel <=frameheight; channel ++) { | |
278 | |
279 /* clear arrays */ | |
280 for(sample=0; sample<framewidth_samples; sample++) | |
281 inputdata[sample] = outputdata[sample] = 0; | |
282 for(n=0; n < MAX_PEAKS; n++){ | |
283 peak[n].tent = UNSET; | |
284 peak[n].sample=0;} | |
285 | |
286 /* Nextevents are unnecessary */ | |
287 | |
288 /* load a single channel's worth of data */ | |
289 fread (inputdata, 2, (size_t) framewidth_samples, inputfp); | |
290 | |
291 /* This next is a simple input check: if any numbers < 0, then say so */ | |
292 for(sample=0; sample<framewidth_samples; sample++) | |
293 if (inputdata[sample] < 0 ) { | |
294 fprintf(stderr, "%s: something's gone wrong: the data is negative.\n", progname); | |
295 exit(-1); } | |
296 | |
297 /* find peaks. WARNING: in reverse */ | |
298 total_peaks = findpeaksreverse(); | |
299 | |
300 /* bin any small peaks ... */ | |
301 if ((removeflag == ON) && (total_peaks !=0 ) ) { | |
302 total_peaks_2 = removepeaks(total_peaks); | |
303 for(n=0; n < MAX_PEAKS; n++) { | |
304 peak[n].tent = UNSET; | |
305 peak[n].sample = 0;} | |
306 total_peaks = findpeaksreverse();} | |
307 | |
308 /* get intervals */ | |
309 find_intervals(total_peaks, channel, framewidth_samples_output); | |
310 | |
311 } /* channel */ | |
312 | |
313 } /* frame */ | |
314 | |
315 | |
316 /*------------------------------------------*/ | |
317 /*------------------------------------------*/ | |
318 | |
319 | |
320 fflush(stdout); | |
321 | |
322 | |
323 /* If required, sum the values */ | |
324 if (summationflag==ON) { | |
325 | |
326 for (channel = 1; channel <= frameheight; channel ++) | |
327 summation[channel] = 0; | |
328 | |
329 for (channel = 1; channel <= frameheight; channel ++) { | |
330 clipflag = OFF; | |
331 for (sample = 0; sample < framewidth_samples_output; sample++) | |
332 summation[channel] += interval[channel][sample]; | |
333 | |
334 /* clip check */ | |
335 if ((summation[channel] > 32765) || | |
336 (summation[channel] < 0)){ | |
337 if (clipflag == OFF) { | |
338 fprintf(stderr, " \nclipping: channel %i, summations.\n ", channel); | |
339 clipflag = ON;} | |
340 summation[channel] = 32765; | |
341 } | |
342 } | |
343 } | |
344 | |
345 /*-------------------------------------------*/ | |
346 | |
347 /* write output */ | |
348 | |
349 if (asciiflag == OFF) { | |
350 for (channel = 1; channel <= frameheight; channel ++){ | |
351 for (sample = 0; sample < framewidth_samples_output; sample++) | |
352 outputfiguredata[sample] = interval[channel][sample]; | |
353 writedata_output(outputfigurefp, framewidth_samples_output); | |
354 } | |
355 } | |
356 else { | |
357 if (asciireverseflag == OFF) | |
358 write_matrix_hori_freq(framewidth_samples_output, outputfigurefp); | |
359 else | |
360 write_matrix_hori_time(framewidth_samples_output, outputfigurefp); | |
361 } | |
362 | |
363 /*-------------------------------------------*/ | |
364 | |
365 /* Tidy up and exit */ | |
366 | |
367 if (verboseflag == ON) | |
368 fprintf(stderr, "\n"); | |
369 fclose(inputfp); | |
370 fclose(outputfigurefp); | |
371 | |
372 if ( ferror(inputfp) != 0) { | |
373 fprintf(stderr, " %s : error closing input file.\n", progname); | |
374 exit(-1);} | |
375 | |
376 if ( ferror(outputfigurefp) != 0) { | |
377 fprintf(stderr, " %s : error closing figure file.\n", progname); | |
378 exit(-1);} | |
379 | |
380 exit(0); | |
381 | |
382 } /* Main */ | |
383 | |
384 | |
385 | |
386 | |
387 | |
388 | |
389 /*---------------------------------------------------------------------------*/ | |
390 /*---------------------------------------------------------------------------*/ | |
391 | |
392 | |
393 | |
394 | |
395 | |
396 void parsecommandline(int argc, char *argv[], char inputfn[], char outputbasefn[]) | |
397 { | |
398 int x=1, helpflag = OFF; | |
399 | |
400 while (x < argc){ | |
401 if (!strcmp(argv[x], "-o")) {strcpy(outputbasefn, argv[x+1]); x+=2;} | |
402 else if (!strcmp(argv[x], "-output")) {strcpy(outputbasefn, argv[x+1]); x+=2;} | |
403 else if (!strcmp(argv[x], "-i")) {strcpy(inputfn, argv[x+1]); x+=2;} | |
404 else if (!strcmp(argv[x], "-input")) {strcpy(inputfn, argv[x+1]); x+=2;} | |
405 else if (!strcmp(argv[x], "-help")) {helpflag = ON; x+=1;} | |
406 else if (!strcmp(argv[x], "-h")) {helpflag = ON; x+=1;} | |
407 else if (!strcmp(argv[x], "-verbose")) {verboseflag = ON; x+=1;} | |
408 else if (!strcmp(argv[x], "-v")) {verboseflag = ON; x+=1;} | |
409 else if (!strcmp(argv[x], "-weight")) {weightflag = NORMAL_WEIGHTING; x+=1;} | |
410 else if (!strcmp(argv[x], "-weightlog")) {weightflag = LOG_WEIGHTING; x+=1;} | |
411 else if (!strcmp(argv[x], "-width")) {widthflag = ON; total_width=atoi(argv[x+1]); x+=2;} | |
412 else if (!strcmp(argv[x], "-r")) { removeflag = ON; removevalue = atof(argv[x+1]); x+=2;} | |
413 else if (!strcmp(argv[x], "-a")) { asciiflag = ON;x+=1;} | |
414 else if (!strcmp(argv[x], "-ar")) { asciiflag = ON; asciireverseflag=ON; x+=1;} | |
415 else if (!strcmp(argv[x], "-s")) { summationflag=ON; x+=1;} | |
416 else if (!strcmp(argv[x], "-g")) { greyscaleflag=ON; x+=1;} | |
417 else if (!strcmp(argv[x], "-grey")) { greyscaleflag=ON; x+=1;} | |
418 else if (!strcmp(argv[x], "-gray")) { greyscaleflag=ON; x+=1;} | |
419 else if (!strcmp(argv[x], "-oparch")) { oppositearchflag=ON; x+=1;} | |
420 else {fprintf(stderr, "%s: unknown option %s\n", progname, argv[x]); | |
421 exit(-1);} | |
422 } | |
423 | |
424 if (helpflag == ON) | |
425 { | |
426 fprintf(stderr, "\n"); | |
427 fprintf(stderr, " %s\n", progname); | |
428 fprintf(stderr, " -----------------------------------------------------------------------------\n"); | |
429 fprintf(stderr, " Works out a histogram of peak intervals, from a .sai\n"); | |
430 fprintf(stderr, " Default output is a .sai file: if -a or -ar specified,\n"); | |
431 | |
432 fprintf(stderr, " then output is a ASCII matrix.\n"); | |
433 fprintf(stderr, "\n"); | |
434 fprintf(stderr, " The -oparch option is REQUIRED if reading a Sun .sai files \n"); | |
435 fprintf(stderr, " on a DEC cpu or vice-versa.\n"); | |
436 fprintf(stderr, " Add .sai to both input and output filenames.\n"); | |
437 | |
438 fprintf(stderr, " -----------------------------------------------------------------------------\n"); | |
439 fprintf(stderr, "\n"); | |
440 fprintf(stderr, " -i <.sai file> input file default = stdin\n"); | |
441 fprintf(stderr, " -o <.sai file> output file default = stdout\n"); | |
442 fprintf(stderr, " -oparch assume input was generated on an opposing architecture\n"); | |
443 fprintf(stderr, "\n"); | |
444 fprintf(stderr, " -a ASCII output: rows = channels\n"); | |
445 fprintf(stderr, " -ar ASCII output: rows = time intervals\n"); | |
446 fprintf(stderr, " -s include summations over time intervals (ASCII options only)\n"); | |
447 fprintf(stderr, "\n"); | |
448 fprintf(stderr, " -width <int> width of graph.sai (msecs).\n"); | |
449 fprintf(stderr, " -r <fraction> remove any peaks F(n) < F(n+1) & F(n-1) * fract \n"); | |
450 fprintf(stderr, " default = %.3f\n", removevalue); | |
451 fprintf(stderr, " -weight weight histogram entries by mean height of peaks\n"); | |
452 fprintf(stderr, " -weightlog as per -weight, but use 10log(mean height)\n"); | |
453 fprintf(stderr, "\n"); | |
454 fprintf(stderr, " -v verbose output (to stderr)\n"); | |
455 fprintf(stderr, " -g change .sai 'view' format to 'grayscale'.\n"); | |
456 fprintf(stderr, "\n\n"); | |
457 exit(-1);} | |
458 | |
459 } | |
460 | |
461 | |
462 | |
463 | |
464 /* The End */ | |
465 /*---------------------------------------------------------------------------*/ |