comparison tools/x11play.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 *
3 * x11play -Animate successive plots of n points.
4 The points are read as binary shorts.
5 * Like x11plot, but plots successive blocks of n points
6 * on top of each other, rubbing out the previous plot, so
7 * as to form an "animated" sequence of plots.
8 *
9 * -Help: x11play -H
10 * -Usage, EG:
11 * fft -n128 -o120 file | x11play -n64 -y0 -c5000
12 * Quit program with left mouse button.
13 * -Step-mode
14 * With a -S flag, single-step through frames using
15 * the mouse as follows:
16 *
17 * left - quit
18 * centre - freeze animation (successive centre
19 * buttons give single successive frames).
20 * right - continue animation
21 *
22 * Note: animation is slower in step-mode because
23 * XSynchronise has to be on.
24 ****************************************************************************/
25 #include <stdio.h>
26 #include <math.h>
27 #include "x11coord.h"
28
29 /****************************************************************************
30 * Defaults
31 ****************************************************************************/
32 #define UNSET (-9999)
33
34 #define DEFAMPL 1000
35 #define DEFSCALE 256
36
37 float argXd0=UNSET, argYd0=UNSET;
38 float argXd1=UNSET, argYd1=UNSET;
39
40 /****************************************************************************
41 * Input-file arguments
42 ****************************************************************************/
43 int n = DEFSCALE; /* num points to read from file */
44 int s = 0; /* start position in file */
45 short summary= 0; /* Flag for method of block summary in downsample */
46 short z = 1; /* Flag for drawing zero line */
47 short stepmode=0; /* Flag for single-step mode */
48 short overplot=0; /* Flag for overplot mode */
49 short stepcount=0;
50 char DEFNAME[]="stdin";
51 char *name=DEFNAME;
52 short *data;
53 XPoint *points;
54
55 FILE *fp, *fopen();
56
57 /****************************************************************************
58 * main
59 * The window is plotted when an expose event is (automatically) generated.
60 * The plotting routines are called from within the event monitor.
61 ****************************************************************************/
62 main(argc, argv)
63 int argc ;
64 char *argv[] ;
65 {
66 Window w;
67 int npoints;
68
69 while (--argc > 0 && **++argv == '-')
70 switch (*++*argv) {
71 case 'n': n = atoi(++*argv); break;
72 case 's': s = atoi(++*argv); break;
73 case 'x': argXd0 = atof(++*argv); break;
74 case 'y': argYd0 = atof(++*argv); break;
75 case 'c': argXd1 = atof(++*argv); break;
76 case 'a': argYd1 = atof(++*argv); break;
77 case 'b': summary = atoi(++*argv); break;
78 case 'z': z = 0; break;
79 case 'S': stepmode++; break;
80 case 'O': overplot++; break;
81 case 'F': theFontString = ++*argv; break;
82 case 'H':
83 default: help();
84 }
85
86 if (argXd0==UNSET) argXd0 = s;
87 if (argXd1==UNSET) argXd1 = n;
88 else argXd1 = argXd1-argXd0; /* ie, a range */
89 if (argYd0==UNSET) {
90 if (argYd1==UNSET) argYd1 = 2*DEFAMPL;
91 else argYd1 = 2*argYd1;
92 argYd0 = argYd1/2;
93 }
94 else {
95 if (argYd1==UNSET) argYd1 = DEFAMPL+argYd0;
96 else argYd1 = argYd1+argYd0;
97 }
98 argYd0 = (-argYd0);
99
100 if ((data = (short*) malloc(n * sizeof(short))) == NULL)
101 error("malloc out of space\n");
102 if ((points = (XPoint*)malloc(n * sizeof(XPoint))) == NULL)
103 error("malloc out of space\n");
104
105 if (argc) {
106 /* Open data file */
107 name = *argv;
108 if ((fp = fopen(name, "r")) == NULL) {
109 fprintf(stderr,"can't open %s\n", *argv);
110 exit(1);
111 }
112 }
113 else fp = stdin;
114
115 /* Seek start of data in file */
116 if (s > 0) seekstart(s,fp);
117
118 set_window_parameters(PLOTXORG,PLOTYORG, PLOTWIDTH,PLOTHEIGHT);
119 set_bordered_box(10);
120 set_data_parameters(0,0, argXd0,argYd0, argXd1,argYd1);
121 xopen();
122 xgc( 1, theFontString ) ;
123 w = xcreate(name, ButtonPressMask | ExposureMask);
124 init_xevent(w);
125 }
126
127
128 /****************************************************************************
129 * Seek s points from current position in stream.
130 * This general seek works even when fp is stdin, unlike fseek.
131 ****************************************************************************/
132 seekstart(s,fp)
133 int s;
134 FILE *fp;
135 {
136 int i;
137 short p;
138
139 for (i=0 ; i<s && fread(&p, sizeof(short), 1, fp) ; i++)
140 ;
141 if (i<s) error("seek overshot end-of-file\n");
142 }
143
144
145 /****************************************************************************
146 * X11 Event Monitor.
147 * The window is plotted when an expose event is (automatically) generated.
148 * This routine catches the initial expose event to first draw the window.
149 * After this, the xevent_monitor is called from upsample, which is called
150 * from draw_plot.
151 ****************************************************************************/
152 init_xevent(w) /* to catch initial expose event and draw first plot */
153 Window w;
154 {
155 XEvent event;
156
157 for ( ; ; ) {
158 XNextEvent(theDisplay,&event);
159 switch (event.type) {
160 case ButtonPress:
161 switch(event.xbutton.button) {
162 case Button1: /* Left */
163 XDestroyWindow(theDisplay,w);
164 exit(0);
165 case Button2: /* Middle */
166 case Button3: break; /* Right */
167 default:
168 fprintf(stderr,"button %d not used\n", event.xbutton.button);
169 }
170 break;
171 case Expose:
172 if (event.xexpose.count == 0) {
173 draw_calibrated_box(w);
174 draw_plot(w);
175 }
176 break;
177 default:
178 fprintf(stderr,"event type %d not found\n", event.type);
179 }
180 }
181 }
182
183
184 xevent_monitor(w)
185 Window w;
186 {
187 XEvent event;
188 static short wait=1;
189
190 if (!stepmode) wait=0;
191 do {
192 /* get next event provided one is on queue; don't wait otherwise */
193 if (wait || XEventsQueued(theDisplay,QueuedAlready) > 0) {
194 XNextEvent(theDisplay,&event);
195 switch (event.type) {
196 case ButtonPress:
197 switch(event.xbutton.button) {
198 case Button1: /* Left */
199 XDestroyWindow(theDisplay,w);
200 exit(0);
201 case Button2: /* Middle */
202 if (stepmode) {
203 if (wait) single_shot(w,fp);
204 else wait=1;
205 }
206 break;
207 case Button3: if (stepmode) wait=0; break;/* Right */
208 default:
209 fprintf(stderr,"button %d not used\n", event.xbutton.button);
210 }
211 break;
212 default:
213 fprintf(stderr,"event type %d not found\n", event.type);
214 }
215 }
216 } while (wait);
217 }
218
219
220 /****************************************************************************
221 * Draw a calibrated box in a window and plot data inside it.
222 ****************************************************************************/
223 draw_plot(w)
224 Window w;
225 {
226 int i, npoints;
227
228 if (z) draw_Xaxis(w,0); /* Draw zero line */
229 if (!overplot) XSetFunction(theDisplay,theGC,GXinvert);
230 if (stepmode) XSynchronize(theDisplay,True);
231 if (n <= pwidth()) npoints = upsample(w,fp);
232 else fprintf(stderr,"successive downsampling not implemented yet!\n");
233 /* npoints = downsample(w,fp); */
234 }
235
236
237 /****************************************************************************
238 * Up and Down sampling.
239 ****************************************************************************/
240 char stepcountstr[128];
241
242 upsample (w,fp)
243 Window w;
244 FILE *fp;
245 {
246 int i, x, j=0;
247 int lastx,lasty, X,Y;
248 short y, notfirst=0;
249 float res, incr, carry;
250
251 res = (float)pwidth()/(n-1); /* resolution of plot */
252 incr = res; /* x-value increment */
253 x = 0; /* initial x-value */
254 while (fread(&y, sizeof(short), 1, fp)) {
255 if (stepmode) {
256 if (stepcount > 0) supertopline(w,stepcountstr);
257 sprintf(stepcountstr,"%d", ++stepcount);
258 supertopline(w,stepcountstr);
259 }
260 lastx=pleft(); lasty=py(y);
261 carry = res - (int)res;
262 incr = res + carry;
263 x = (int)incr;
264 for (i=1 ; i<n && fread(&y, sizeof(short), 1, fp) ; i++) {
265 X = x+pleft();
266 Y = py(y);
267 /* Plot only inside y-limits of box */
268 if (Y > pbottom()) Y = pbottom();
269 if (Y < ptop()) Y = ptop();
270
271 /* rub-out a segment of last plot */
272 if (notfirst)
273 XDrawLine(theDisplay, w, theGC, points[i-1].x, points[i-1].y, points[i].x, points[i].y);
274 else notfirst=1;
275 /* draw a new segment for current plot */
276 XDrawLine(theDisplay, w, theGC, lastx, lasty, X, Y);
277
278 points[i-1].x = lastx;
279 points[i-1].y = lasty;
280 lastx = X;
281 lasty = Y;
282
283 carry = incr - (int)incr;
284 incr = res + carry;
285 x += (int)incr;
286 }
287 points[i-1].x = lastx;
288 points[i-1].y = lasty;
289 /* if (XEventsQueued(theDisplay,QueuedAlready) > 0) */
290 xevent_monitor(w);
291 }
292 }
293
294
295 single_shot (w,fp)
296 Window w;
297 FILE *fp;
298 {
299 int i, x, j=0;
300 int lastx,lasty, X,Y;
301 short y, notfirst=0;
302 float res, incr, carry;
303
304 res = (float)pwidth()/(n-1); /* resolution of plot */
305 incr = res; /* x-value increment */
306 x = 0; /* initial x-value */
307 if (fread(&y, sizeof(short), 1, fp)) {
308 if (stepmode) {
309 if (stepcount > 0) supertopline(w,stepcountstr);
310 sprintf(stepcountstr,"%d", ++stepcount);
311 supertopline(w,stepcountstr);
312 }
313 lastx=pleft(); lasty=py(y);
314 carry = res - (int)res;
315 incr = res + carry;
316 x = (int)incr;
317 for (i=1 ; i<n && fread(&y, sizeof(short), 1, fp) ; i++) {
318 X = x+pleft();
319 Y = py(y);
320 /* Plot only inside y-limits of box */
321 if (Y > pbottom()) Y = pbottom();
322 if (Y < ptop()) Y = ptop();
323
324 /* rub-out a segment of last plot */
325 if (notfirst)
326 XDrawLine(theDisplay, w, theGC, points[i-1].x, points[i-1].y, points[i].x, points[i].y);
327 else notfirst=1;
328 /* draw a new segment for current plot */
329 XDrawLine(theDisplay, w, theGC, lastx, lasty, X, Y);
330
331 points[i-1].x = lastx;
332 points[i-1].y = lasty;
333 lastx = X;
334 lasty = Y;
335
336 carry = incr - (int)incr;
337 incr = res + carry;
338 x += (int)incr;
339 }
340 points[i-1].x = lastx;
341 points[i-1].y = lasty;
342 }
343 }
344
345
346 #define BLOCK 256
347 float block; /* for averaging in downsample */
348
349
350 downsample (w,fp)
351 Window w;
352 FILE *fp;
353 {
354 int i, x, j = 0;
355 short y;
356 float rate;
357 float res;
358 float incr;
359 float carry;
360
361 rate = (float)n/pwidth();
362 if ((block = rate) >= BLOCK)
363 error ("excessive downsampling; re-define BLOCK\n");
364
365 res = (float)pwidth()/(n-1); /* resolution of plot */
366 incr = res; /* x-value increment */
367 x = 0; /* initial x-value */
368 for (i=0 ; i<n ; i++) {
369 if (incr >= 1.0) {
370 if (sample(&y, i, rate)) {
371 points[j].x = x+pleft();
372 points[j].y = py(y);
373
374 /* Plot only inside y-limits of box */
375 if (points[j].y > pbottom()) points[j].y = pbottom();
376 if (points[j].y < ptop()) points[j].y = ptop();
377 j++;
378 }
379 }
380 carry = incr - (int)incr;
381 incr = res + carry;
382 x += (int)incr;
383 }
384 return j;
385 }
386
387 sample (y, i, rate)
388 short *y;
389 int i;
390 float rate;
391 {
392 short average();
393 float carry;
394
395 if (block <= n-i) {
396 *y = average ((int)block, &data[i]);
397 carry = block - (int)block;
398 block = rate + carry;
399 return 1;
400 }
401 else
402 return 0;
403 }
404
405 /*
406 short
407 average (block, p)
408 int block;
409 short p[];
410 {
411 int i;
412 float sum = 0;
413
414 for (i = 0 ; i < block ; i++)
415 sum += p[i];
416 return (short)(sum / block);
417 }
418 */
419
420 short
421 average (block, p)
422 int block;
423 short p[];
424 {
425 int i;
426 float sum = 0;
427 short MIN = 32000, MAX = 0;
428
429 for (i = 0 ; i < block ; i++) {
430 sum += p[i];
431 if (p[i] < MIN) MIN = p[i];
432 if (p[i] > MAX) MAX = p[i];
433 }
434 if (summary==0) { /* summary of block is largest extremal value */
435 if (MAX >= (-MIN)) return MAX; /* summary of block is MAX value */
436 else return MIN; /* summary of block is MIN value */
437 }
438 if (summary == 1) return (p[0]); /* summary of block is sample value */
439 return (short)(sum / block); /* summary of block is mean value */
440 }
441
442
443 /****************************************************************************
444 * Miscellaneous
445 ****************************************************************************/
446 error(s)
447 {
448 fprintf(stderr,"%s",s);
449 exit(1);
450 }
451
452
453 help ()
454 {
455 printf ("\nx11play: animated plot of sets of n points, read as binary shorts.\n");
456 printf ("Usage: a) x11play [options] filename\n");
457 printf (" b) cat filename | x11play [options]\n");
458 printf (" where filename is an input stream of 16-bit binary numbers (shorts)\n");
459 printf ("Options:\n");
460 printf ("-n [int] = Number of points plotted (default=%d).\n", DEFSCALE);
461 printf ("-s [int] = Offset points from start of file (default=0).\n");
462 printf ("-a [float] = Amplitude between zero-line and top of box (default=%d).\n", DEFAMPL);
463 printf ("-y [int] = Amplitude between zero-line and bottom of box (default=a).\n");
464 printf ("-c [float] = Calibration at right end of x-axis (default=n+s).\n");
465 printf ("-x [int] = Calibration at left end of x-axis (default=s).\n");
466 printf ("-z = Suppress zero-line.\n");
467 printf ("-b [0,1,2] = Method of block summary for down-sampling.\n");
468 printf (" 0=MAX, 1=SAMPLE, 2=MEAN, (default=MAX).\n");
469 printf ("-S = Step-mode, (centre-button=single-step, right-button=play).\n");
470 printf ("-O = Over-plot successive plots of n points.\n");
471 printf ("-F [font] = Font name (default=%s)\n", theFontString);
472 exit (0);
473 }
474
475