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