Mercurial > hg > aim92
view 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 |
line wrap: on
line source
/**************************************************************************** * * x11play -Animate successive plots of n points. The points are read as binary shorts. * Like x11plot, but plots successive blocks of n points * on top of each other, rubbing out the previous plot, so * as to form an "animated" sequence of plots. * * -Help: x11play -H * -Usage, EG: * fft -n128 -o120 file | x11play -n64 -y0 -c5000 * Quit program with left mouse button. * -Step-mode * With a -S flag, single-step through frames using * the mouse as follows: * * left - quit * centre - freeze animation (successive centre * buttons give single successive frames). * right - continue animation * * Note: animation is slower in step-mode because * XSynchronise has to be on. ****************************************************************************/ #include <stdio.h> #include <math.h> #include "x11coord.h" /**************************************************************************** * Defaults ****************************************************************************/ #define UNSET (-9999) #define DEFAMPL 1000 #define DEFSCALE 256 float argXd0=UNSET, argYd0=UNSET; float argXd1=UNSET, argYd1=UNSET; /**************************************************************************** * Input-file arguments ****************************************************************************/ int n = DEFSCALE; /* num points to read from file */ int s = 0; /* start position in file */ short summary= 0; /* Flag for method of block summary in downsample */ short z = 1; /* Flag for drawing zero line */ short stepmode=0; /* Flag for single-step mode */ short overplot=0; /* Flag for overplot mode */ short stepcount=0; char DEFNAME[]="stdin"; char *name=DEFNAME; short *data; XPoint *points; FILE *fp, *fopen(); /**************************************************************************** * main * The window is plotted when an expose event is (automatically) generated. * The plotting routines are called from within the event monitor. ****************************************************************************/ main(argc, argv) int argc ; char *argv[] ; { Window w; int npoints; while (--argc > 0 && **++argv == '-') switch (*++*argv) { case 'n': n = atoi(++*argv); break; case 's': s = atoi(++*argv); break; case 'x': argXd0 = atof(++*argv); break; case 'y': argYd0 = atof(++*argv); break; case 'c': argXd1 = atof(++*argv); break; case 'a': argYd1 = atof(++*argv); break; case 'b': summary = atoi(++*argv); break; case 'z': z = 0; break; case 'S': stepmode++; break; case 'O': overplot++; break; case 'F': theFontString = ++*argv; break; case 'H': default: help(); } if (argXd0==UNSET) argXd0 = s; if (argXd1==UNSET) argXd1 = n; else argXd1 = argXd1-argXd0; /* ie, a range */ if (argYd0==UNSET) { if (argYd1==UNSET) argYd1 = 2*DEFAMPL; else argYd1 = 2*argYd1; argYd0 = argYd1/2; } else { if (argYd1==UNSET) argYd1 = DEFAMPL+argYd0; else argYd1 = argYd1+argYd0; } argYd0 = (-argYd0); if ((data = (short*) malloc(n * sizeof(short))) == NULL) error("malloc out of space\n"); if ((points = (XPoint*)malloc(n * sizeof(XPoint))) == NULL) error("malloc out of space\n"); if (argc) { /* Open data file */ name = *argv; if ((fp = fopen(name, "r")) == NULL) { fprintf(stderr,"can't open %s\n", *argv); exit(1); } } else fp = stdin; /* Seek start of data in file */ if (s > 0) seekstart(s,fp); set_window_parameters(PLOTXORG,PLOTYORG, PLOTWIDTH,PLOTHEIGHT); set_bordered_box(10); set_data_parameters(0,0, argXd0,argYd0, argXd1,argYd1); xopen(); xgc( 1, theFontString ) ; w = xcreate(name, ButtonPressMask | ExposureMask); init_xevent(w); } /**************************************************************************** * Seek s points from current position in stream. * This general seek works even when fp is stdin, unlike fseek. ****************************************************************************/ seekstart(s,fp) int s; FILE *fp; { int i; short p; for (i=0 ; i<s && fread(&p, sizeof(short), 1, fp) ; i++) ; if (i<s) error("seek overshot end-of-file\n"); } /**************************************************************************** * X11 Event Monitor. * The window is plotted when an expose event is (automatically) generated. * This routine catches the initial expose event to first draw the window. * After this, the xevent_monitor is called from upsample, which is called * from draw_plot. ****************************************************************************/ init_xevent(w) /* to catch initial expose event and draw first plot */ Window w; { XEvent event; for ( ; ; ) { XNextEvent(theDisplay,&event); switch (event.type) { case ButtonPress: switch(event.xbutton.button) { case Button1: /* Left */ XDestroyWindow(theDisplay,w); exit(0); case Button2: /* Middle */ case Button3: break; /* Right */ default: fprintf(stderr,"button %d not used\n", event.xbutton.button); } break; case Expose: if (event.xexpose.count == 0) { draw_calibrated_box(w); draw_plot(w); } break; default: fprintf(stderr,"event type %d not found\n", event.type); } } } xevent_monitor(w) Window w; { XEvent event; static short wait=1; if (!stepmode) wait=0; do { /* get next event provided one is on queue; don't wait otherwise */ if (wait || XEventsQueued(theDisplay,QueuedAlready) > 0) { XNextEvent(theDisplay,&event); switch (event.type) { case ButtonPress: switch(event.xbutton.button) { case Button1: /* Left */ XDestroyWindow(theDisplay,w); exit(0); case Button2: /* Middle */ if (stepmode) { if (wait) single_shot(w,fp); else wait=1; } break; case Button3: if (stepmode) wait=0; break;/* Right */ default: fprintf(stderr,"button %d not used\n", event.xbutton.button); } break; default: fprintf(stderr,"event type %d not found\n", event.type); } } } while (wait); } /**************************************************************************** * Draw a calibrated box in a window and plot data inside it. ****************************************************************************/ draw_plot(w) Window w; { int i, npoints; if (z) draw_Xaxis(w,0); /* Draw zero line */ if (!overplot) XSetFunction(theDisplay,theGC,GXinvert); if (stepmode) XSynchronize(theDisplay,True); if (n <= pwidth()) npoints = upsample(w,fp); else fprintf(stderr,"successive downsampling not implemented yet!\n"); /* npoints = downsample(w,fp); */ } /**************************************************************************** * Up and Down sampling. ****************************************************************************/ char stepcountstr[128]; upsample (w,fp) Window w; FILE *fp; { int i, x, j=0; int lastx,lasty, X,Y; short y, notfirst=0; float res, incr, carry; res = (float)pwidth()/(n-1); /* resolution of plot */ incr = res; /* x-value increment */ x = 0; /* initial x-value */ while (fread(&y, sizeof(short), 1, fp)) { if (stepmode) { if (stepcount > 0) supertopline(w,stepcountstr); sprintf(stepcountstr,"%d", ++stepcount); supertopline(w,stepcountstr); } lastx=pleft(); lasty=py(y); carry = res - (int)res; incr = res + carry; x = (int)incr; for (i=1 ; i<n && fread(&y, sizeof(short), 1, fp) ; i++) { X = x+pleft(); Y = py(y); /* Plot only inside y-limits of box */ if (Y > pbottom()) Y = pbottom(); if (Y < ptop()) Y = ptop(); /* rub-out a segment of last plot */ if (notfirst) XDrawLine(theDisplay, w, theGC, points[i-1].x, points[i-1].y, points[i].x, points[i].y); else notfirst=1; /* draw a new segment for current plot */ XDrawLine(theDisplay, w, theGC, lastx, lasty, X, Y); points[i-1].x = lastx; points[i-1].y = lasty; lastx = X; lasty = Y; carry = incr - (int)incr; incr = res + carry; x += (int)incr; } points[i-1].x = lastx; points[i-1].y = lasty; /* if (XEventsQueued(theDisplay,QueuedAlready) > 0) */ xevent_monitor(w); } } single_shot (w,fp) Window w; FILE *fp; { int i, x, j=0; int lastx,lasty, X,Y; short y, notfirst=0; float res, incr, carry; res = (float)pwidth()/(n-1); /* resolution of plot */ incr = res; /* x-value increment */ x = 0; /* initial x-value */ if (fread(&y, sizeof(short), 1, fp)) { if (stepmode) { if (stepcount > 0) supertopline(w,stepcountstr); sprintf(stepcountstr,"%d", ++stepcount); supertopline(w,stepcountstr); } lastx=pleft(); lasty=py(y); carry = res - (int)res; incr = res + carry; x = (int)incr; for (i=1 ; i<n && fread(&y, sizeof(short), 1, fp) ; i++) { X = x+pleft(); Y = py(y); /* Plot only inside y-limits of box */ if (Y > pbottom()) Y = pbottom(); if (Y < ptop()) Y = ptop(); /* rub-out a segment of last plot */ if (notfirst) XDrawLine(theDisplay, w, theGC, points[i-1].x, points[i-1].y, points[i].x, points[i].y); else notfirst=1; /* draw a new segment for current plot */ XDrawLine(theDisplay, w, theGC, lastx, lasty, X, Y); points[i-1].x = lastx; points[i-1].y = lasty; lastx = X; lasty = Y; carry = incr - (int)incr; incr = res + carry; x += (int)incr; } points[i-1].x = lastx; points[i-1].y = lasty; } } #define BLOCK 256 float block; /* for averaging in downsample */ downsample (w,fp) Window w; FILE *fp; { int i, x, j = 0; short y; float rate; float res; float incr; float carry; rate = (float)n/pwidth(); if ((block = rate) >= BLOCK) error ("excessive downsampling; re-define BLOCK\n"); res = (float)pwidth()/(n-1); /* resolution of plot */ incr = res; /* x-value increment */ x = 0; /* initial x-value */ for (i=0 ; i<n ; i++) { if (incr >= 1.0) { if (sample(&y, i, rate)) { points[j].x = x+pleft(); points[j].y = py(y); /* Plot only inside y-limits of box */ if (points[j].y > pbottom()) points[j].y = pbottom(); if (points[j].y < ptop()) points[j].y = ptop(); j++; } } carry = incr - (int)incr; incr = res + carry; x += (int)incr; } return j; } sample (y, i, rate) short *y; int i; float rate; { short average(); float carry; if (block <= n-i) { *y = average ((int)block, &data[i]); carry = block - (int)block; block = rate + carry; return 1; } else return 0; } /* short average (block, p) int block; short p[]; { int i; float sum = 0; for (i = 0 ; i < block ; i++) sum += p[i]; return (short)(sum / block); } */ short average (block, p) int block; short p[]; { int i; float sum = 0; short MIN = 32000, MAX = 0; for (i = 0 ; i < block ; i++) { sum += p[i]; if (p[i] < MIN) MIN = p[i]; if (p[i] > MAX) MAX = p[i]; } if (summary==0) { /* summary of block is largest extremal value */ if (MAX >= (-MIN)) return MAX; /* summary of block is MAX value */ else return MIN; /* summary of block is MIN value */ } if (summary == 1) return (p[0]); /* summary of block is sample value */ return (short)(sum / block); /* summary of block is mean value */ } /**************************************************************************** * Miscellaneous ****************************************************************************/ error(s) { fprintf(stderr,"%s",s); exit(1); } help () { printf ("\nx11play: animated plot of sets of n points, read as binary shorts.\n"); printf ("Usage: a) x11play [options] filename\n"); printf (" b) cat filename | x11play [options]\n"); printf (" where filename is an input stream of 16-bit binary numbers (shorts)\n"); printf ("Options:\n"); printf ("-n [int] = Number of points plotted (default=%d).\n", DEFSCALE); printf ("-s [int] = Offset points from start of file (default=0).\n"); printf ("-a [float] = Amplitude between zero-line and top of box (default=%d).\n", DEFAMPL); printf ("-y [int] = Amplitude between zero-line and bottom of box (default=a).\n"); printf ("-c [float] = Calibration at right end of x-axis (default=n+s).\n"); printf ("-x [int] = Calibration at left end of x-axis (default=s).\n"); printf ("-z = Suppress zero-line.\n"); printf ("-b [0,1,2] = Method of block summary for down-sampling.\n"); printf (" 0=MAX, 1=SAMPLE, 2=MEAN, (default=MAX).\n"); printf ("-S = Step-mode, (centre-button=single-step, right-button=play).\n"); printf ("-O = Over-plot successive plots of n points.\n"); printf ("-F [font] = Font name (default=%s)\n", theFontString); exit (0); }