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