1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """
24 bar-plotting for Biggles
25 """
26
27 try:
28 import biggles as B
29 except:
30 B = 0
31
32
33
34
35
36
38 """
39 Get x,y values to draw many bars.
40
41 @param values: values to bar-plot
42 @type values: [float]
43 @param x0: start of first bar
44 @type x0: float
45 @param xwidth: width of bars (default: 0.25)
46 @type xwidth: float
47 @param xsep: space between bars (default: 0.15)
48 @type xsep: float
49
50 @return: x,y values that draw a bar for each y value
51 @rtype: [float],[float]
52
53 @note: not used at the moment because it draws connecting
54 line at the bottom
55 """
56 x = x0 or xsep
57 vy = []
58 vx = []
59
60 for y in values:
61 vy += [ 0, y,y, 0]
62 vx += [ x, x, x+xwidth, x+xwidth]
63 x += xwidth + xsep
64
65 return vx, vy
66
67
68 -def bar_curve( height, x0, xwidth=0.25, y0=0. ):
69 """
70 Get x,y values for a single bar.
71
72 @param height: height of bar
73 @type height: float
74 @param x0: start of first bar
75 @type x0: float
76 @param xwidth: width of bars (default: 0.25)
77 @type xwidth: float
78 @param y0: start of first bar
79 @type y0: float
80
81 @return: x,y values that draw a single bar.
82 @rtype: [ float ], [ float ]
83 """
84 y = height - y0
85 return [ x0, x0, x0+xwidth, x0+xwidth ], [y0,y,y,y0]
86
87
89 """
90 Get a diagonal connecting left (x0) to right (x1) edge but which is only
91 visible within a rectangular box.
92
93 @param x0: rectangular window of visibility
94 @type x0: float
95 @param y0: rectangular window of visibility
96 @type y0: float
97 @param x1: rectangular window of visibility
98 @type x1: float
99 @param y1: rectangular window of visibility
100 @type y1: float
101
102 @param vy: virtual starting point (y-coordinate, may be outside of the box)
103 @type vy: float
104
105 @return: xa, ya, xb, yb - start and end point of a diagonal
106 line originating at (x0, vy) but beeing only visible
107 within the rectangle (x0,y0,x1,y1)
108 @rtype: float, float, float, float
109 """
110 dx = x1 - x0
111 dy = y1 - y0
112
113
114 xa = x0
115 ya = vy
116 xb = x1
117 yb = vy + dx
118
119
120 if vy < y0:
121 xa = x0 + (y0-vy)
122 ya = y0
123
124
125 if vy > y1 - dx:
126 xb = x0 + dy - vy
127 yb = y1
128
129 return xa,ya, xb,yb
130
131
132
133
134
135
136 -def line_fill( x0, y0, x1, y1, sep=0.1, size=0.06, color='black', **kw ):
137 """
138 Fill the rectangle described by x0, y0, x1, y1 with horizontal lines.
139
140 @param x0: rectangular coorinates
141 @type x0: float
142 @param y0: rectangular coorinates
143 @type y0: float
144 @param x1: rectangular coorinates
145 @type x1: float
146 @param y1: rectangular coorinates
147 @type y1: float
148 @param sep: separation between lines (default: 0.1)
149 @type sep: float
150 @param size: line thickness (default: 0.06)
151 @type size: float
152 @param color: color name (default: black)
153 @type color: str
154 @param kw: additional key-value pairs
155 @type kw: key=value
156
157 @return: list of biggles plot objects
158 @rtype: [Biggles.Curve]
159 """
160 if not 'color' in kw:
161 kw['color'] = color
162 if not 'width' in kw:
163 kw['width'] = size
164
165 r = []
166 y = y1
167 while y >= y0:
168
169 r += [ B.Curve( [x0,x1], [y,y], **kw ) ]
170 y -= sep
171
172 return r
173
174
175 -def bar_fill( x0, y0, x1, y1, sep=0.1, size=0.06, color='grey', **kw ):
176 """
177 Fill the rectangle described by x0, y0, x1, y1 with horizontal bars.
178
179 @param x0: rectangular coorinates
180 @type x0: float
181 @param y0: rectangular coorinates
182 @type y0: float
183 @param x1: rectangular coorinates
184 @type x1: float
185 @param y1: rectangular coorinates
186 @type y1: float
187 @param sep: separation between lines (default: 0.1)
188 @type sep: float
189 @param size: line thickness (default: 0.06)
190 @type size: float
191 @param color: color name (default: grey)
192 @type color: str
193 @param kw: additional key-value pairs
194 @type kw: key=value
195
196 @return: list of biggles plot objects
197 @rtype: [Biggles.FillBetween]
198 """
199 kw.update( {'color':color} )
200 r = []
201 y = y1
202 while y >= y0:
203
204 y_low = y - size
205 if y_low < y0:
206 y_low = y0
207
208 r += [ B.FillBetween( [x0,x1], [y,y], [x0,x0,x1,x1], [y,y_low,y_low,y],
209 **kw ) ]
210 y -= sep
211
212 return r
213
214
215 -def diagonal_fill( x0, y0, x1, y1, sep=0.2, size=0.05, invert=0, **kw ):
216 """
217 Fill the rectangle described by x0,y0, x1,y1 (lower left and
218 upper right corner) with diagonal bars.
219
220 @param x0: rectangular coorinates
221 @type x0: float
222 @param y0: rectangular coorinates
223 @type y0: float
224 @param x1: rectangular coorinates
225 @type x1: float
226 @param y1: rectangular coorinates
227 @type y1: float
228 @param sep: offset between (low edges of) diagonal lines (default: 0.2)
229 @type sep: float
230 @param size: width of diagonal line (default: 0.05)
231 @type size: float
232 @param invert: mirror diagonals (default: 0)
233 @type invert: 1|0
234 @param kw: additional key-value pairs
235 @type kw: key=value
236
237 @return: list of biggles plot objects
238 @rtype: [Biggles.FillBetween]
239 """
240 r = []
241
242 vy = y0 - (x1 - x0) - sep
243
244
245 if invert: vy = vy - sep/2
246
247 while vy < (y1 - y0):
248
249
250 xa,ya, xb,yb = boxed_diagonal( x0,y0, x1,y1, vy )
251
252
253 if vy + size < y1 - y0:
254 xc,yc, xd,yd = boxed_diagonal( x0,y0, x1,y1, vy+size )
255 else:
256 xc, yc = xa, y1-y0
257 xd, yd = xb, y1-y0
258
259
260 if invert:
261 xa = x1 - (xa - x0)
262 xb = x0 - (xb - x1)
263 xc = x1 - (xc - x0)
264 xd = x0 - (xd - x1)
265
266 r += [ B.FillBetween( [xc,xa,xb,xd],[yc,ya,yb,yd], [xc,xd],[yc,yd],
267 **kw)]
268 vy += sep
269
270 return r
271
272
274 """
275 Fill the rectangle described by x0,y0, x1,y1 (lower left and
276 upper right corner) with diagonal lines.
277
278 @param x0: rectangular coorinates
279 @type x0: float
280 @param y0: rectangular coorinates
281 @type y0: float
282 @param x1: rectangular coorinates
283 @type x1: float
284 @param y1: rectangular coorinates
285 @type y1: float
286 @param sep: offset between (low edges of) diagonal lines (default: 0.2)
287 @type sep: float
288 @param size: width of diagonal line (default: 0.05)
289 @type size: float
290 @param invert: mirror diagonals (default: 0)
291 @type invert: 1|0
292 @param kw: additional key-value pairs
293 @type kw: key=value
294
295 @return: list of biggles plot objects
296 @rtype: [Biggles.Curve]
297 """
298 r = []
299
300 vy = y0 - (x1 - x0) - sep
301
302 kw[ 'width' ] = kw.get('width',None) or size
303
304
305 if invert: vy = vy - sep/2
306
307 while vy <= (y1 - y0):
308
309
310 xa,ya, xb,yb = boxed_diagonal( x0,y0, x1,y1, vy )
311
312
313 if invert:
314 xa = x1 - (xa - x0)
315 xb = x0 - (xb - x1)
316
317 r += [ B.Curve( [xa,xb],[ya,yb], **kw) ]
318 vy += sep
319
320 return r
321
323 """
324 Fill the rectangle described by x0,y0, x1,y1 (lower left and
325 upper right corner).
326
327 @param x0: rectangular coorinates
328 @type x0: float
329 @param y0: rectangular coorinates
330 @type y0: float
331 @param x1: rectangular coorinates
332 @type x1: float
333 @param y1: rectangular coorinates
334 @type y1: float
335 @param kw: additional key-value pairs
336 @type kw: key=value
337
338 @return: list of biggles plot objects
339 @rtype: [Biggles.FillBetween]
340 """
341 return [ B.FillBetween( [x0,x0,x1,x1], [y1,y0,y0,y1], [x0,x1], [y1,y1],
342 filltype=1, **kw) ]
343
344
345
346
347
348
350 """
351 A rectangle described by x0,y0, x1,y1 (lower left and
352 upper right corner).
353
354 @param x0: rectangular coorinates
355 @type x0: float
356 @param y0: rectangular coorinates
357 @type y0: float
358 @param x1: rectangular coorinates
359 @type x1: float
360 @param y1: rectangular coorinates
361 @type y1: float
362 @param kw: additional key-value pairs
363 @type kw: key=value
364
365 @return: biggles plot object
366 @rtype: biggles.Curv
367 """
368 return B.Curve( [x0,x1,x1,x0,x0],[y0,y0,y1,y1,y0], **kw )
369
370
372 """
373 Fill for a rectangle described by x0,y0, x1,y1 (lower left and
374 upper right corner).
375
376 @param x0: rectangular coorinates
377 @type x0: float
378 @param y0: rectangular coorinates
379 @type y0: float
380 @param x1: rectangular coorinates
381 @type x1: float
382 @param y1: rectangular coorinates
383 @type y1: float
384 @param kw: additional key-value pairs
385 @type kw: key=value
386
387 @return: biggles plot object
388 @rtype: biggles.FillBetween
389 """
390 return B.FillBetween( [x0,x1,x1],[y0,y0,y1],[x1,x0,x0],[y1,y1,y0], **kw)
391
392
394 """
395 Add single filled box to plot.
396
397 @param p: plot object which to add rectangle to
398 @type p: biggles.FramedPlot
399 @param x0: rectangular coorinates, lower left corner
400 @type x0: float
401 @param y0: rectangular coorinates, lower left corner
402 @type y0: float
403 @param x1: rectangular coorinates, upper right corner
404 @type x1: float
405 @param y1: rectangular coorinates, upper right corner
406 @type y1: float
407 @param fillfunc: function name (default: solid_fill)
408 @type fillfunc str
409 @param kw: arguments for fillfunc and (starting with 'l') for Curve
410 @type kw: key=value
411 """
412
413 for f in fillfunc( x0,y0, x1,y1, **kw ):
414 p.add( f )
415
416
417 attr = {}
418 for k,v in kw.items():
419 if k[0] == 'l':
420 attr[ k[1:] ] = v
421
422 p.add( box_curve( x0,y0, x1,y1, **attr ) )
423
424
425 -def fill_bars( p, values, x0=None, xwidth=0.25, xoffset=1, fillfunc=solid_fill,
426 margin=0.01, **kw ):
427 """
428 Add filling to bars described y values, left-most x, width and offset.
429
430 @param p: fill objects are added directly to the plot
431 @type p: Biggles.FramedPlot
432 @param values: bar heights
433 @type values: [float]
434 @param x0: left edge of first bar (default: None, xwidth)
435 @type x0: float
436 @param xwidth: width of each bar (default: 0.25)
437 @type xwidth: float
438 @param xoffset: distance between bars (measured between left edges)
439 (default: 1)
440 @type xoffset: float
441 @param fillfunc: function solid_fill | line_fill | diagonal_fill | bar_fill
442 @type fillfunc: str
443 @param kw: attributes for fill function, e.g. color, size, sep
444 @type kw: key=value
445 """
446 vx, vy = multibar_curve( values, x0=x0 or xwidth, xwidth=xwidth,
447 xsep=xoffset-xwidth )
448
449 for i in range( 0, len(vy), 4 ):
450
451 fill_objects = fillfunc( vx[i]+margin,vy[i]+margin,
452 vx[i+2]-margin,vy[i+2]-margin, **kw )
453
454 for l in fill_objects: p.add( l )
455
456
457 -def add_bars( p, values, x0=None, xwidth=0.25, xoffset=1, fillfunc=solid_fill,
458 **kw ):
459 """
460 Add bars to plot, described by y values, left-most x, width and offset.
461
462 @param p: fill objects are added directly to the plot
463 @type p: Biggles.FramedPlot
464 @param values: bar heights
465 @type values: [float]
466 @param x0: left edge of first bar (default: None, xwidth)
467 @type x0: float
468 @param xwidth: width of each bar (default 0.25)
469 @type xwidth: float
470 @param xoffset: distance between bars (measured between left edges)
471 (default 1)
472 @type xoffset: float
473 @param fillfunc: function solid_fill | line_fill | diagonal_fill
474 | bar_fill | None
475 @type fillfunc: str
476 @param kw: attributes for fill function (e.g. color, size, sep)
477 and Curve (the latter ones have to start with "l", e.g. lcolor)
478 @type kw: key=value
479 """
480 if x0 is None:
481 x0 = xwidth
482
483
484 if fillfunc is not None:
485 fill_bars( p, values,x0=x0, xwidth=xwidth, xoffset=xoffset,
486 fillfunc=fillfunc, **kw)
487
488
489 attr = {}
490 for k,v in kw.items():
491 if k[0] == 'l':
492 attr[ k[1:] ] = v
493
494
495 for i in range( len( values ) ):
496
497 x = x0 + i * xoffset
498 p.add( B.Curve( *bar_curve( values[i], x, xwidth=xwidth ), **attr) )
499
500
501
502
503
504 -def prepare_plot( xlabel='', ylabel='', yrange=None, xrange=None,
505 width=500, height=350 ):
506 """
507 Initiate a biggles.FramedPlot object.
508
509 @param xlabel: label for x-axis
510 @type xlabel: str
511 @param ylabel: label for y-axis
512 @type ylabel: str
513 @param yrange: range of y-axis
514 @type yrange: (float,float)
515 @param xrange: range of x-axis
516 @type xrange: (float,float)
517 @param width: hard plot width (in pixels or cm)
518 @type width: int
519 @param height: hard plot height
520 @type height: int
521
522 @return: biggles plot object
523 @rtype: biggles.FillBetween
524 """
525 B.configure( 'screen', 'height', height )
526 B.configure( 'screen', 'width', width )
527
528 p = B.FramedPlot()
529
530 p.xlabel = xlabel
531 p.ylabel = ylabel
532 if yrange: p.yrange = yrange
533 if xrange: p.xrange = xrange
534
535 return p
536
537
538
539
540
541
542
544 """
545 Test class
546 """
547
548 - def run( self, local=0 ):
549 """
550 run function test
551
552 @param local: transfer local variables to global and perform
553 other tasks only when run locally
554 @type local: 1|0
555
556 @return: 1
557 @rtype: int
558 """
559 p = prepare_plot(xlabel='', ylabel='flex $\langle{x}\rangle$',
560 xrange=(0,5), yrange=(0,4) )
561
562 add_bars( p, [ 1, 2.5, 1.25, 0.3 ], fillfunc=diagonal_fill,
563 color='grey', size=0.1, invert=1,
564 lcolor='black', lwidth=1 )
565
566 add_bars( p, [0.4, 1.5, 2., 0.6], x0=0.5,
567 fillfunc=solid_fill, lcolor='blue', lwidth=2 )
568
569 add_box( p, 3.5, 3, 4, 3.5, fillfunc=line_fill,
570 color='grey', size=5 )
571
572
573
574
575 p.show()
576
577 if local:
578 globals().update( locals() )
579
580 return 1
581
582
584 """
585 Precalculated result to check for consistent performance.
586
587 @return: 1
588 @rtype: int
589 """
590 return 1
591
592
593 if __name__ == '__main__':
594
595 test = Test()
596
597 assert test.run( local=1 ) == test.expected_result()
598