Mercurial > hg > aim92
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 |