Package Biskit :: Module plotUtils
[hide private]
[frames] | no frames]

Source Code for Module Biskit.plotUtils

  1  ## 
  2  ## Biskit, a toolkit for the manipulation of macromolecular structures 
  3  ## Copyright (C) 2004-2005 Raik Gruenberg & Johan Leckner 
  4  ## 
  5  ## This program is free software; you can redistribute it and/or 
  6  ## modify it under the terms of the GNU General Public License as 
  7  ## published by the Free Software Foundation; either version 2 of the 
  8  ## License, or any later version. 
  9  ## 
 10  ## This program is distributed in the hope that it will be useful, 
 11  ## but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 13  ## General Public License for more details. 
 14  ## 
 15  ## You find a copy of the GNU General Public License in the file 
 16  ## license.txt along with this program; if not, write to the Free 
 17  ## Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 18  ## 
 19  ## 
 20  ## last $Author: graik $ 
 21  ## last $Date: 2006/11/12 21:59:44 $ 
 22  ## $Revision: 2.6 $ 
 23  """ 
 24  bar-plotting for Biggles 
 25  """ 
 26   
 27  try: 
 28      import biggles as B 
 29  except: 
 30      B = 0 
 31   
 32   
 33  ############################## 
 34  ## low-level tools 
 35   
 36   
37 -def multibar_curve( values, x0=None, xwidth=0.25, xsep=0.15 ):
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
88 -def boxed_diagonal( x0, y0, x1, y1, vy ):
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 ## line completely within rectangle 114 xa = x0 115 ya = vy 116 xb = x1 117 yb = vy + dx 118 119 ## cut off low end 120 if vy < y0: 121 xa = x0 + (y0-vy) 122 ya = y0 ## mhm, doesn't work as it is supposed to 123 124 ## cut of high end 125 if vy > y1 - dx: 126 xb = x0 + dy - vy 127 yb = y1 128 129 return xa,ya, xb,yb
130 131 132 ########################## 133 ## Fill patterns 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 = [] ## will hold result 241 242 vy = y0 - (x1 - x0) - sep ## virtual y coordinate 243 244 ## shift mirrored lines horizontally to get better criss-cross effect 245 if invert: vy = vy - sep/2 246 247 while vy < (y1 - y0): 248 249 ## lower diagonal 250 xa,ya, xb,yb = boxed_diagonal( x0,y0, x1,y1, vy ) 251 252 ## upper diagonal 253 if vy + size < y1 - y0: 254 xc,yc, xd,yd = boxed_diagonal( x0,y0, x1,y1, vy+size ) 255 else: ## never start outside box 256 xc, yc = xa, y1-y0 257 xd, yd = xb, y1-y0 258 259 ## mirror line 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
273 -def diagonal_line_fill( x0, y0, x1, y1, sep=0.2, size=0.05, invert=0, **kw ):
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 = [] ## will hold result 299 300 vy = y0 - (x1 - x0) - sep ## virtual y coordinate 301 302 kw[ 'width' ] = kw.get('width',None) or size 303 304 ## shift mirrored lines horizontally to get better criss-cross effect 305 if invert: vy = vy - sep/2 306 307 while vy <= (y1 - y0): 308 309 ## lower diagonal 310 xa,ya, xb,yb = boxed_diagonal( x0,y0, x1,y1, vy ) 311 312 ## mirror line 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
322 -def solid_fill( x0, y0, x1, y1, **kw ):
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 ## Bar-plotting 347 348
349 -def box_curve( x0, y0, x1, y1, **kw ):
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
371 -def box_fill( x0, y0, x1, y1, **kw ):
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
393 -def add_box( p, x0, y0, x1, y1, fillfunc=solid_fill, **kw ):
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 ## extract attributes starting with 'l' 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 ## draw filling 484 if fillfunc is not None: 485 fill_bars( p, values,x0=x0, xwidth=xwidth, xoffset=xoffset, 486 fillfunc=fillfunc, **kw) 487 488 ## extract attributes starting with 'l' 489 attr = {} 490 for k,v in kw.items(): 491 if k[0] == 'l': 492 attr[ k[1:] ] = v 493 494 ## draw bar outline 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 ## other stuff 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 ## TESTING 541 ############# 542
543 -class Test:
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 ## ## example of how to write an eps plot to disc 573 ## p.write_eps(T.absfile('~/test.eps'), width='10cm', height='8.7cm') 574 575 p.show() 576 577 if local: 578 globals().update( locals() ) 579 580 return 1
581 582
583 - def expected_result( self ):
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