Mercurial > hg > aim92
diff tools/x11plot.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/x11plot.c Fri May 20 15:19:45 2011 +0100 @@ -0,0 +1,392 @@ +/**************************************************************************** +* +* x11plot - a no-scale plot for X11 windows. Mike Allerhand, March 1989. +* Also for overplotting multiple files. +* +* usage: x11plot [options] filename1 [filename2 ...] +* where filename is a stream of binary shorts. +* Alternatively, input can be piped, as in: +* cat filename | x11plot [options] +* +* mouse: +* left button = print pointer coordinates. +* centre button = re-draw plot (but not any printed coordinates). +* right button = exit program (destroy windows). +* +****************************************************************************/ +#include <stdio.h> +#include <math.h> +#include "x11coord.h" + + +/**************************************************************************** +* Defaults +****************************************************************************/ +#define UNSET (-9999) + +#define DEFAMPL 1000 +#define DEFSCALE 256 +#define DEFSAMPLERATE 20000 + +char DEFUNITS[] = "p" ; + + +#define SAMPLES 0 +#define SECONDS 1 +#define MILLISECONDS 2 + +int xscale_units ; +char *unitstr = DEFUNITS ; + + +float argXd0=UNSET, argYd0=UNSET; +float argXd1=UNSET, argYd1=UNSET; + +int Yincr=0; /* Increment y-origin for successive files */ + +int plotxorg = PLOTXORG ; +int plotyorg = PLOTYORG ; +int plotheight = PLOTHEIGHT ; +int plotwidth = PLOTWIDTH ; + + +/**************************************************************************** +* Input-file arguments +****************************************************************************/ +int m; /* num files to read */ +int n; /* length read from file */ +int s; /* start position in file */ +short z = 1; /* Flag for drawing zero line */ +short v = 1; /* Flag for calibrating box */ + +int samplerate = DEFSAMPLERATE ; + +short **data ; /* data values for each file */ +XPoint **point ; /* XPoints (pixel coords) for each file */ +int *npoints ; /* number of points actually read in from each file */ + +/**************************************************************************** +* 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[] ; +{ + FILE *fp, *fopen(); + Window w ; + float n0=DEFSCALE, s0=0 ; + int i ; + + while (--argc > 0 && **++argv == '-') + switch (*++*argv) { + case 'n': n0 = atof(++*argv); break; + case 's': s0 = atof(++*argv); break; + case 'y': argYd0 = atof(++*argv); break; + case 'a': argYd1 = atof(++*argv); break; + case 'z': z = 0; break; + case 'v': v = 0; break; + case 'Y': Yincr = atoi(++*argv); break; + case 'S': samplerate = atoi(++*argv); break; + case 'u': unitstr = ++*argv ; break; + case 'F': theFontString = ++*argv ; break; + case 'H': + default: help(); + } + + if (argc==0) m=1; /* 1 file from stdin. */ + else m=argc; /* m files given as args. */ + + if ( strcmp( unitstr, "p" ) == 0 ) xscale_units = SAMPLES ; + else if ( strcmp( unitstr, "s" ) == 0 ) xscale_units = SECONDS ; + else if ( strcmp( unitstr, "ms" ) == 0 ) xscale_units = MILLISECONDS ; + else { + fprintf( stderr, "x11plot: unknown x-axis units\n" ); + exit( 1 ); + } + + n = to_samples( n0 ) ; + s = to_samples( s0 ) ; + + + /* Allocate a data and an XPoint matrix for m files, each of n points */ + if ( (data = (short **) malloc(m * sizeof(short *)) ) == NULL || + (point = (XPoint **) malloc(m * sizeof(XPoint *)) ) == NULL || + (npoints = (int *) malloc(m * sizeof( int )) ) == NULL ) { + fprintf( stderr, "x11plot: malloc out of space\n"); + exit( 1 ) ; + } + + /* For each of m files ... */ + for ( i=0 ; i<m ; i++, argv++ ) { + + /* Allocate space for data and XPoints */ + if ( (data[i] = (short *) malloc(n * sizeof(short )) ) == NULL || + (point[i] = (XPoint *) malloc(n * sizeof(XPoint)) ) == NULL ) { + fprintf( stderr,"x11plot: malloc out of space\n"); + exit( 1 ) ; + } + + /* Open file, seek start of data in file and read data in*/ + if (argc==0) fp=stdin; + else if ((fp = fopen(*argv, "r")) == NULL) { + fprintf(stderr,"can't open %s\n", *argv); + exit(1); + } + if (s > 0) seekstart(s,fp); + + if ( ( npoints[i] = fread( data[i], sizeof(short), n, fp ) ) < n ) { + if (argc==0) + fprintf(stderr,"Warning: %d points read from stdin.\n", npoints[i]); + else + fprintf(stderr,"Warning: %d points read from input stream %s.\n", npoints[i], *argv); + } + + fclose(fp); + } + + /* Set argument defaults etc. */ + + if (argXd0==UNSET) argXd0 = 0 ; + if (argXd1==UNSET) argXd1 = (float) n ; + + 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); + + mapwaves() ; + xopen(); + xgc( 1, theFontString ) ; + w = xcreate("x11plot", ButtonPressMask | ExposureMask | StructureNotifyMask ) ; + + xevent_monitor(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) { + fprintf(stderr,"seek overshot end-of-file\n"); + exit( 1 ) ; + } +} + + +/**************************************************************************** +* X11 Event Monitor. +* The window is plotted when an expose event is (automatically) generated. +* The plotting routines are called from within the event monitor. +****************************************************************************/ +xevent_monitor(w) +Window w; +{ + XEvent event; + XWindowAttributes attribs ; + + for ( ; ; ) { + XNextEvent(theDisplay,&event); + switch (event.type) { + case ButtonPress: + switch(event.xbutton.button) { + case Button1 : /* Left */ + report(w, event); + break; + case Button2 : /* Centre */ + clearplot( w, plotwidth, plotheight ) ; + drawwaves( w ) ; + break; + case Button3 : /* Right */ + XDestroyWindow(theDisplay,w); + return; + default: + fprintf(stderr,"button %d not used\n", event.xbutton.button); + } + break; + case ConfigureNotify : + plotwidth = event.xconfigure.width ; + plotheight = event.xconfigure.height ; + mapwaves() ; + clearplot( w, plotwidth, plotheight ) ; +/* drawwaves( w ) ; */ + break; + case Expose: + if (event.xexpose.count == 0) { + drawwaves( w ) ; + } + break; + } + } +} + + + +/**************************************************************************** +* Set the parameters for mapping data coords onto pixel coords. +* For each data file, map the data onto pixel coords in the corresponding +* XPoints array. +****************************************************************************/ +mapwaves() +{ + int i, j, n ; + short *dat ; + XPoint *pix ; + + set_window_parameters( plotxorg, plotyorg, plotwidth, plotheight ); + set_bordered_box(10); + set_data_parameters(0,0, argXd0,argYd0, argXd1,argYd1); + + for ( i = 0 ; i < m ; i++ ) { + dat = data[i] ; + pix = point[i] ; + n = npoints[i] ; + for ( j = 0 ; j < n ; j++ ) { + pix[j].x = px(j) ; + if ( ( pix[j].y = py(dat[j]) ) > pbottom() ) pix[j].y = pbottom(); + else if ( pix[j].y < ptop() ) pix[j].y = ptop(); + } + if ( Yincr > 0 ) /* Increment Y-origin for successive files (Y decreases upwards) */ + set_data_parameters(0,0, argXd0,argYd0-((i+1)*Yincr), argXd1,argYd1); + } + + if ( Yincr > 0 ) /* Reset original values so that "report" works for first file */ + set_data_parameters(0,0, argXd0,argYd0, argXd1,argYd1); +} + + + +clearplot( w, width, height ) /* clear the plot window */ +Window w; +int width, height ; +{ + XClearArea( theDisplay, w, 0, 0, width, height, 0 ) ; +} + +drawwaves( w ) /* draw the mapped data for all files */ +Window w; +{ + int i ; + + draw_box(w); + if (v) draw_calibration( w ); + if (z) draw_Xaxis(w,0); /* Draw zero line */ + + for ( i = 0 ; i < m ; i++ ) + XDrawLines(theDisplay, w, theGC, point[i], npoints[i], CoordModeOrigin ) ; + + XFlush(theDisplay); +} + + +draw_calibration( w ) +Window w ; +{ + float d0, d1 ; + + switch ( xscale_units ) { + case SAMPLES : d0 = (float) s ; + d1 = d0 + (float) n ; + break ; + case SECONDS : d0 = (float) s / samplerate ; + d1 = d0 + (float) n / samplerate ; + break ; + case MILLISECONDS : d0 = (float) s * 1000. / samplerate ; + d1 = d0 + (float) n * 1000. / samplerate ; + break ; + } + + calibrate_Axis( w, pleft(),pright(), d0,d1, pbottom(), 'x' ) ; + calibrate_Axis( w, pbottom(),ptop(), _Yd0,_Yd1, pleft(), 'y' ) ; +} + + + +/**************************************************************************** +* Report position of cursor on screen. +****************************************************************************/ +report(w, event) +Window w; +XEvent event; +{ + char str[32]; + int x, y; /* pixel coords of cursor, wrt window origin */ + int X, Y; /* data system coords */ + float xscale; + int XCALIBSPACE = 100; /* Space for calib value labels for X axis (ie in Y direction) */ + int YCALIBSPACE = 190; /* Space for calib value labels for Y axis (ie in X direction) */ + + x = event.xbutton.x; + y = event.xbutton.y; + xscale = (float)pwidth()/n; +/* X = s + (x-Xp0)/xscale; */ /* addition of s offset assumes time scale only */ + X = xp(x); + Y = yp(y); + sprintf(str,"(%d,%d)", X, Y); + XDrawLine(theDisplay, w, theGC, x-10, y, x+10, y); + XDrawLine(theDisplay, w, theGC, x, y-10, x, y+10); + XDrawString(theDisplay, w, theGC, x+5, y-5, str, strlen(str)); +} + + +/**************************************************************************** +* Convert length to samples according to given xscale_units. +****************************************************************************/ + +to_samples( x ) +float x ; +{ + int samples ; + + switch ( xscale_units ) { + case SAMPLES : samples = x ; + break ; + case SECONDS : samples = x * samplerate ; + break ; + case MILLISECONDS : samples = x * samplerate * 0.001 ; + break ; + } + return samples ; +} + + +help () +{ + printf ("\nx11plot: plot n points, read as binary shorts.\n"); + printf ("Usage: a) x11plot [options] filename1 [filename2 ... ]\n"); + printf (" b) cat filename | x11plot [options]\n"); + printf (" where filename is an input stream of 16-bit binary numbers (shorts)\n"); + printf ("Options:\n"); + printf ("-S [int] = Samplerate in Hz (default 20000).\n"); + printf ("-u [string] = Units (s, ms, or default p (samples)).\n"); + printf ("\n"); + printf ("-n [int] = Length plotted (default=%d samples).\n", DEFSCALE); + printf ("-s [int] = Offset from start of file (default=0 samples).\n"); + printf ("\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 ("-Y [int] = Increment Y-origin for successive files (default=0).\n"); + printf ("\n"); + printf ("-v = Suppress calibration.\n"); + printf ("-z = Suppress zero-line.\n"); + printf ("-F [font] = Font name (default=%s)\n", theFontString); + exit (0); +} +