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