Mercurial > hg > aim92
view 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 source
/**************************************************************************** * * 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); }