Mercurial > hg > aim92
diff 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 diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/x11play.c Fri May 20 15:19:45 2011 +0100 @@ -0,0 +1,475 @@ +/**************************************************************************** +* +* 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); +} + +