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);
+}
+
+