annotate 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
rev   line source
tomwalters@0 1 /****************************************************************************
tomwalters@0 2 *
tomwalters@0 3 * x11plot - a no-scale plot for X11 windows. Mike Allerhand, March 1989.
tomwalters@0 4 * Also for overplotting multiple files.
tomwalters@0 5 *
tomwalters@0 6 * usage: x11plot [options] filename1 [filename2 ...]
tomwalters@0 7 * where filename is a stream of binary shorts.
tomwalters@0 8 * Alternatively, input can be piped, as in:
tomwalters@0 9 * cat filename | x11plot [options]
tomwalters@0 10 *
tomwalters@0 11 * mouse:
tomwalters@0 12 * left button = print pointer coordinates.
tomwalters@0 13 * centre button = re-draw plot (but not any printed coordinates).
tomwalters@0 14 * right button = exit program (destroy windows).
tomwalters@0 15 *
tomwalters@0 16 ****************************************************************************/
tomwalters@0 17 #include <stdio.h>
tomwalters@0 18 #include <math.h>
tomwalters@0 19 #include "x11coord.h"
tomwalters@0 20
tomwalters@0 21
tomwalters@0 22 /****************************************************************************
tomwalters@0 23 * Defaults
tomwalters@0 24 ****************************************************************************/
tomwalters@0 25 #define UNSET (-9999)
tomwalters@0 26
tomwalters@0 27 #define DEFAMPL 1000
tomwalters@0 28 #define DEFSCALE 256
tomwalters@0 29 #define DEFSAMPLERATE 20000
tomwalters@0 30
tomwalters@0 31 char DEFUNITS[] = "p" ;
tomwalters@0 32
tomwalters@0 33
tomwalters@0 34 #define SAMPLES 0
tomwalters@0 35 #define SECONDS 1
tomwalters@0 36 #define MILLISECONDS 2
tomwalters@0 37
tomwalters@0 38 int xscale_units ;
tomwalters@0 39 char *unitstr = DEFUNITS ;
tomwalters@0 40
tomwalters@0 41
tomwalters@0 42 float argXd0=UNSET, argYd0=UNSET;
tomwalters@0 43 float argXd1=UNSET, argYd1=UNSET;
tomwalters@0 44
tomwalters@0 45 int Yincr=0; /* Increment y-origin for successive files */
tomwalters@0 46
tomwalters@0 47 int plotxorg = PLOTXORG ;
tomwalters@0 48 int plotyorg = PLOTYORG ;
tomwalters@0 49 int plotheight = PLOTHEIGHT ;
tomwalters@0 50 int plotwidth = PLOTWIDTH ;
tomwalters@0 51
tomwalters@0 52
tomwalters@0 53 /****************************************************************************
tomwalters@0 54 * Input-file arguments
tomwalters@0 55 ****************************************************************************/
tomwalters@0 56 int m; /* num files to read */
tomwalters@0 57 int n; /* length read from file */
tomwalters@0 58 int s; /* start position in file */
tomwalters@0 59 short z = 1; /* Flag for drawing zero line */
tomwalters@0 60 short v = 1; /* Flag for calibrating box */
tomwalters@0 61
tomwalters@0 62 int samplerate = DEFSAMPLERATE ;
tomwalters@0 63
tomwalters@0 64 short **data ; /* data values for each file */
tomwalters@0 65 XPoint **point ; /* XPoints (pixel coords) for each file */
tomwalters@0 66 int *npoints ; /* number of points actually read in from each file */
tomwalters@0 67
tomwalters@0 68 /****************************************************************************
tomwalters@0 69 * main
tomwalters@0 70 * The window is plotted when an expose event is (automatically) generated.
tomwalters@0 71 * The plotting routines are called from within the event monitor.
tomwalters@0 72 ****************************************************************************/
tomwalters@0 73 main(argc, argv)
tomwalters@0 74 int argc ;
tomwalters@0 75 char *argv[] ;
tomwalters@0 76 {
tomwalters@0 77 FILE *fp, *fopen();
tomwalters@0 78 Window w ;
tomwalters@0 79 float n0=DEFSCALE, s0=0 ;
tomwalters@0 80 int i ;
tomwalters@0 81
tomwalters@0 82 while (--argc > 0 && **++argv == '-')
tomwalters@0 83 switch (*++*argv) {
tomwalters@0 84 case 'n': n0 = atof(++*argv); break;
tomwalters@0 85 case 's': s0 = atof(++*argv); break;
tomwalters@0 86 case 'y': argYd0 = atof(++*argv); break;
tomwalters@0 87 case 'a': argYd1 = atof(++*argv); break;
tomwalters@0 88 case 'z': z = 0; break;
tomwalters@0 89 case 'v': v = 0; break;
tomwalters@0 90 case 'Y': Yincr = atoi(++*argv); break;
tomwalters@0 91 case 'S': samplerate = atoi(++*argv); break;
tomwalters@0 92 case 'u': unitstr = ++*argv ; break;
tomwalters@0 93 case 'F': theFontString = ++*argv ; break;
tomwalters@0 94 case 'H':
tomwalters@0 95 default: help();
tomwalters@0 96 }
tomwalters@0 97
tomwalters@0 98 if (argc==0) m=1; /* 1 file from stdin. */
tomwalters@0 99 else m=argc; /* m files given as args. */
tomwalters@0 100
tomwalters@0 101 if ( strcmp( unitstr, "p" ) == 0 ) xscale_units = SAMPLES ;
tomwalters@0 102 else if ( strcmp( unitstr, "s" ) == 0 ) xscale_units = SECONDS ;
tomwalters@0 103 else if ( strcmp( unitstr, "ms" ) == 0 ) xscale_units = MILLISECONDS ;
tomwalters@0 104 else {
tomwalters@0 105 fprintf( stderr, "x11plot: unknown x-axis units\n" );
tomwalters@0 106 exit( 1 );
tomwalters@0 107 }
tomwalters@0 108
tomwalters@0 109 n = to_samples( n0 ) ;
tomwalters@0 110 s = to_samples( s0 ) ;
tomwalters@0 111
tomwalters@0 112
tomwalters@0 113 /* Allocate a data and an XPoint matrix for m files, each of n points */
tomwalters@0 114 if ( (data = (short **) malloc(m * sizeof(short *)) ) == NULL ||
tomwalters@0 115 (point = (XPoint **) malloc(m * sizeof(XPoint *)) ) == NULL ||
tomwalters@0 116 (npoints = (int *) malloc(m * sizeof( int )) ) == NULL ) {
tomwalters@0 117 fprintf( stderr, "x11plot: malloc out of space\n");
tomwalters@0 118 exit( 1 ) ;
tomwalters@0 119 }
tomwalters@0 120
tomwalters@0 121 /* For each of m files ... */
tomwalters@0 122 for ( i=0 ; i<m ; i++, argv++ ) {
tomwalters@0 123
tomwalters@0 124 /* Allocate space for data and XPoints */
tomwalters@0 125 if ( (data[i] = (short *) malloc(n * sizeof(short )) ) == NULL ||
tomwalters@0 126 (point[i] = (XPoint *) malloc(n * sizeof(XPoint)) ) == NULL ) {
tomwalters@0 127 fprintf( stderr,"x11plot: malloc out of space\n");
tomwalters@0 128 exit( 1 ) ;
tomwalters@0 129 }
tomwalters@0 130
tomwalters@0 131 /* Open file, seek start of data in file and read data in*/
tomwalters@0 132 if (argc==0) fp=stdin;
tomwalters@0 133 else if ((fp = fopen(*argv, "r")) == NULL) {
tomwalters@0 134 fprintf(stderr,"can't open %s\n", *argv);
tomwalters@0 135 exit(1);
tomwalters@0 136 }
tomwalters@0 137 if (s > 0) seekstart(s,fp);
tomwalters@0 138
tomwalters@0 139 if ( ( npoints[i] = fread( data[i], sizeof(short), n, fp ) ) < n ) {
tomwalters@0 140 if (argc==0)
tomwalters@0 141 fprintf(stderr,"Warning: %d points read from stdin.\n", npoints[i]);
tomwalters@0 142 else
tomwalters@0 143 fprintf(stderr,"Warning: %d points read from input stream %s.\n", npoints[i], *argv);
tomwalters@0 144 }
tomwalters@0 145
tomwalters@0 146 fclose(fp);
tomwalters@0 147 }
tomwalters@0 148
tomwalters@0 149 /* Set argument defaults etc. */
tomwalters@0 150
tomwalters@0 151 if (argXd0==UNSET) argXd0 = 0 ;
tomwalters@0 152 if (argXd1==UNSET) argXd1 = (float) n ;
tomwalters@0 153
tomwalters@0 154 if (argYd0==UNSET) {
tomwalters@0 155 if (argYd1==UNSET) argYd1 = 2*DEFAMPL;
tomwalters@0 156 else argYd1 = 2*argYd1;
tomwalters@0 157 argYd0 = argYd1/2;
tomwalters@0 158 }
tomwalters@0 159 else {
tomwalters@0 160 if (argYd1==UNSET) argYd1 = DEFAMPL+argYd0;
tomwalters@0 161 else argYd1 = argYd1+argYd0;
tomwalters@0 162 }
tomwalters@0 163 argYd0 = (-argYd0);
tomwalters@0 164
tomwalters@0 165 mapwaves() ;
tomwalters@0 166 xopen();
tomwalters@0 167 xgc( 1, theFontString ) ;
tomwalters@0 168 w = xcreate("x11plot", ButtonPressMask | ExposureMask | StructureNotifyMask ) ;
tomwalters@0 169
tomwalters@0 170 xevent_monitor(w);
tomwalters@0 171 }
tomwalters@0 172
tomwalters@0 173
tomwalters@0 174 /****************************************************************************
tomwalters@0 175 * Seek s points from current position in stream.
tomwalters@0 176 * This general seek works even when fp is stdin, unlike fseek.
tomwalters@0 177 ****************************************************************************/
tomwalters@0 178 seekstart(s,fp)
tomwalters@0 179 int s;
tomwalters@0 180 FILE *fp;
tomwalters@0 181 {
tomwalters@0 182 int i;
tomwalters@0 183 short p;
tomwalters@0 184
tomwalters@0 185 for (i=0 ; i<s && fread(&p, sizeof(short), 1, fp) ; i++)
tomwalters@0 186 ;
tomwalters@0 187 if (i<s) {
tomwalters@0 188 fprintf(stderr,"seek overshot end-of-file\n");
tomwalters@0 189 exit( 1 ) ;
tomwalters@0 190 }
tomwalters@0 191 }
tomwalters@0 192
tomwalters@0 193
tomwalters@0 194 /****************************************************************************
tomwalters@0 195 * X11 Event Monitor.
tomwalters@0 196 * The window is plotted when an expose event is (automatically) generated.
tomwalters@0 197 * The plotting routines are called from within the event monitor.
tomwalters@0 198 ****************************************************************************/
tomwalters@0 199 xevent_monitor(w)
tomwalters@0 200 Window w;
tomwalters@0 201 {
tomwalters@0 202 XEvent event;
tomwalters@0 203 XWindowAttributes attribs ;
tomwalters@0 204
tomwalters@0 205 for ( ; ; ) {
tomwalters@0 206 XNextEvent(theDisplay,&event);
tomwalters@0 207 switch (event.type) {
tomwalters@0 208 case ButtonPress:
tomwalters@0 209 switch(event.xbutton.button) {
tomwalters@0 210 case Button1 : /* Left */
tomwalters@0 211 report(w, event);
tomwalters@0 212 break;
tomwalters@0 213 case Button2 : /* Centre */
tomwalters@0 214 clearplot( w, plotwidth, plotheight ) ;
tomwalters@0 215 drawwaves( w ) ;
tomwalters@0 216 break;
tomwalters@0 217 case Button3 : /* Right */
tomwalters@0 218 XDestroyWindow(theDisplay,w);
tomwalters@0 219 return;
tomwalters@0 220 default:
tomwalters@0 221 fprintf(stderr,"button %d not used\n", event.xbutton.button);
tomwalters@0 222 }
tomwalters@0 223 break;
tomwalters@0 224 case ConfigureNotify :
tomwalters@0 225 plotwidth = event.xconfigure.width ;
tomwalters@0 226 plotheight = event.xconfigure.height ;
tomwalters@0 227 mapwaves() ;
tomwalters@0 228 clearplot( w, plotwidth, plotheight ) ;
tomwalters@0 229 /* drawwaves( w ) ; */
tomwalters@0 230 break;
tomwalters@0 231 case Expose:
tomwalters@0 232 if (event.xexpose.count == 0) {
tomwalters@0 233 drawwaves( w ) ;
tomwalters@0 234 }
tomwalters@0 235 break;
tomwalters@0 236 }
tomwalters@0 237 }
tomwalters@0 238 }
tomwalters@0 239
tomwalters@0 240
tomwalters@0 241
tomwalters@0 242 /****************************************************************************
tomwalters@0 243 * Set the parameters for mapping data coords onto pixel coords.
tomwalters@0 244 * For each data file, map the data onto pixel coords in the corresponding
tomwalters@0 245 * XPoints array.
tomwalters@0 246 ****************************************************************************/
tomwalters@0 247 mapwaves()
tomwalters@0 248 {
tomwalters@0 249 int i, j, n ;
tomwalters@0 250 short *dat ;
tomwalters@0 251 XPoint *pix ;
tomwalters@0 252
tomwalters@0 253 set_window_parameters( plotxorg, plotyorg, plotwidth, plotheight );
tomwalters@0 254 set_bordered_box(10);
tomwalters@0 255 set_data_parameters(0,0, argXd0,argYd0, argXd1,argYd1);
tomwalters@0 256
tomwalters@0 257 for ( i = 0 ; i < m ; i++ ) {
tomwalters@0 258 dat = data[i] ;
tomwalters@0 259 pix = point[i] ;
tomwalters@0 260 n = npoints[i] ;
tomwalters@0 261 for ( j = 0 ; j < n ; j++ ) {
tomwalters@0 262 pix[j].x = px(j) ;
tomwalters@0 263 if ( ( pix[j].y = py(dat[j]) ) > pbottom() ) pix[j].y = pbottom();
tomwalters@0 264 else if ( pix[j].y < ptop() ) pix[j].y = ptop();
tomwalters@0 265 }
tomwalters@0 266 if ( Yincr > 0 ) /* Increment Y-origin for successive files (Y decreases upwards) */
tomwalters@0 267 set_data_parameters(0,0, argXd0,argYd0-((i+1)*Yincr), argXd1,argYd1);
tomwalters@0 268 }
tomwalters@0 269
tomwalters@0 270 if ( Yincr > 0 ) /* Reset original values so that "report" works for first file */
tomwalters@0 271 set_data_parameters(0,0, argXd0,argYd0, argXd1,argYd1);
tomwalters@0 272 }
tomwalters@0 273
tomwalters@0 274
tomwalters@0 275
tomwalters@0 276 clearplot( w, width, height ) /* clear the plot window */
tomwalters@0 277 Window w;
tomwalters@0 278 int width, height ;
tomwalters@0 279 {
tomwalters@0 280 XClearArea( theDisplay, w, 0, 0, width, height, 0 ) ;
tomwalters@0 281 }
tomwalters@0 282
tomwalters@0 283 drawwaves( w ) /* draw the mapped data for all files */
tomwalters@0 284 Window w;
tomwalters@0 285 {
tomwalters@0 286 int i ;
tomwalters@0 287
tomwalters@0 288 draw_box(w);
tomwalters@0 289 if (v) draw_calibration( w );
tomwalters@0 290 if (z) draw_Xaxis(w,0); /* Draw zero line */
tomwalters@0 291
tomwalters@0 292 for ( i = 0 ; i < m ; i++ )
tomwalters@0 293 XDrawLines(theDisplay, w, theGC, point[i], npoints[i], CoordModeOrigin ) ;
tomwalters@0 294
tomwalters@0 295 XFlush(theDisplay);
tomwalters@0 296 }
tomwalters@0 297
tomwalters@0 298
tomwalters@0 299 draw_calibration( w )
tomwalters@0 300 Window w ;
tomwalters@0 301 {
tomwalters@0 302 float d0, d1 ;
tomwalters@0 303
tomwalters@0 304 switch ( xscale_units ) {
tomwalters@0 305 case SAMPLES : d0 = (float) s ;
tomwalters@0 306 d1 = d0 + (float) n ;
tomwalters@0 307 break ;
tomwalters@0 308 case SECONDS : d0 = (float) s / samplerate ;
tomwalters@0 309 d1 = d0 + (float) n / samplerate ;
tomwalters@0 310 break ;
tomwalters@0 311 case MILLISECONDS : d0 = (float) s * 1000. / samplerate ;
tomwalters@0 312 d1 = d0 + (float) n * 1000. / samplerate ;
tomwalters@0 313 break ;
tomwalters@0 314 }
tomwalters@0 315
tomwalters@0 316 calibrate_Axis( w, pleft(),pright(), d0,d1, pbottom(), 'x' ) ;
tomwalters@0 317 calibrate_Axis( w, pbottom(),ptop(), _Yd0,_Yd1, pleft(), 'y' ) ;
tomwalters@0 318 }
tomwalters@0 319
tomwalters@0 320
tomwalters@0 321
tomwalters@0 322 /****************************************************************************
tomwalters@0 323 * Report position of cursor on screen.
tomwalters@0 324 ****************************************************************************/
tomwalters@0 325 report(w, event)
tomwalters@0 326 Window w;
tomwalters@0 327 XEvent event;
tomwalters@0 328 {
tomwalters@0 329 char str[32];
tomwalters@0 330 int x, y; /* pixel coords of cursor, wrt window origin */
tomwalters@0 331 int X, Y; /* data system coords */
tomwalters@0 332 float xscale;
tomwalters@0 333 int XCALIBSPACE = 100; /* Space for calib value labels for X axis (ie in Y direction) */
tomwalters@0 334 int YCALIBSPACE = 190; /* Space for calib value labels for Y axis (ie in X direction) */
tomwalters@0 335
tomwalters@0 336 x = event.xbutton.x;
tomwalters@0 337 y = event.xbutton.y;
tomwalters@0 338 xscale = (float)pwidth()/n;
tomwalters@0 339 /* X = s + (x-Xp0)/xscale; */ /* addition of s offset assumes time scale only */
tomwalters@0 340 X = xp(x);
tomwalters@0 341 Y = yp(y);
tomwalters@0 342 sprintf(str,"(%d,%d)", X, Y);
tomwalters@0 343 XDrawLine(theDisplay, w, theGC, x-10, y, x+10, y);
tomwalters@0 344 XDrawLine(theDisplay, w, theGC, x, y-10, x, y+10);
tomwalters@0 345 XDrawString(theDisplay, w, theGC, x+5, y-5, str, strlen(str));
tomwalters@0 346 }
tomwalters@0 347
tomwalters@0 348
tomwalters@0 349 /****************************************************************************
tomwalters@0 350 * Convert length to samples according to given xscale_units.
tomwalters@0 351 ****************************************************************************/
tomwalters@0 352
tomwalters@0 353 to_samples( x )
tomwalters@0 354 float x ;
tomwalters@0 355 {
tomwalters@0 356 int samples ;
tomwalters@0 357
tomwalters@0 358 switch ( xscale_units ) {
tomwalters@0 359 case SAMPLES : samples = x ;
tomwalters@0 360 break ;
tomwalters@0 361 case SECONDS : samples = x * samplerate ;
tomwalters@0 362 break ;
tomwalters@0 363 case MILLISECONDS : samples = x * samplerate * 0.001 ;
tomwalters@0 364 break ;
tomwalters@0 365 }
tomwalters@0 366 return samples ;
tomwalters@0 367 }
tomwalters@0 368
tomwalters@0 369
tomwalters@0 370 help ()
tomwalters@0 371 {
tomwalters@0 372 printf ("\nx11plot: plot n points, read as binary shorts.\n");
tomwalters@0 373 printf ("Usage: a) x11plot [options] filename1 [filename2 ... ]\n");
tomwalters@0 374 printf (" b) cat filename | x11plot [options]\n");
tomwalters@0 375 printf (" where filename is an input stream of 16-bit binary numbers (shorts)\n");
tomwalters@0 376 printf ("Options:\n");
tomwalters@0 377 printf ("-S [int] = Samplerate in Hz (default 20000).\n");
tomwalters@0 378 printf ("-u [string] = Units (s, ms, or default p (samples)).\n");
tomwalters@0 379 printf ("\n");
tomwalters@0 380 printf ("-n [int] = Length plotted (default=%d samples).\n", DEFSCALE);
tomwalters@0 381 printf ("-s [int] = Offset from start of file (default=0 samples).\n");
tomwalters@0 382 printf ("\n");
tomwalters@0 383 printf ("-a [float] = Amplitude between zero-line and top of box (default=%d).\n", DEFAMPL);
tomwalters@0 384 printf ("-y [int] = Amplitude between zero-line and bottom of box (default=a).\n");
tomwalters@0 385 printf ("-Y [int] = Increment Y-origin for successive files (default=0).\n");
tomwalters@0 386 printf ("\n");
tomwalters@0 387 printf ("-v = Suppress calibration.\n");
tomwalters@0 388 printf ("-z = Suppress zero-line.\n");
tomwalters@0 389 printf ("-F [font] = Font name (default=%s)\n", theFontString);
tomwalters@0 390 exit (0);
tomwalters@0 391 }
tomwalters@0 392