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