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 /*---------------------------------------------------------------------------*/