source: trunk/python/asaplotbase.py@ 1177

Last change on this file since 1177 was 1153, checked in by mar637, 18 years ago

lots of changes to support soft refresh, for things like text overlays, linecatlogs etc. reworked plot_lines to to auto-peak detection. added forwarding functions to matplotlib.axes. drawing functions

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.4 KB
RevLine 
[705]1"""
2ASAP plotting class based on matplotlib.
3"""
4
5import sys
6from re import match
7
8import matplotlib
9
10from matplotlib.figure import Figure, Text
[1147]11from matplotlib.font_manager import FontProperties as FP
[705]12from matplotlib.numerix import sqrt
13from matplotlib import rc, rcParams
[710]14from asap import rcParams as asaprcParams
[1019]15from matplotlib.ticker import ScalarFormatter
16from matplotlib.ticker import NullLocator
[1147]17from matplotlib.transforms import blend_xy_sep_transform
18
[1095]19if int(matplotlib.__version__.split(".")[1]) < 87:
20 print "Warning: matplotlib version < 0.87. This might cause errors. Please upgrade."
[1019]21
22class MyFormatter(ScalarFormatter):
23 def __call__(self, x, pos=None):
[1025]24 #last = len(self.locs)-2
25 if pos==0:
26 return ''
[1019]27 else: return ScalarFormatter.__call__(self, x, pos)
28
[705]29class asaplotbase:
30 """
31 ASAP plotting base class based on matplotlib.
32 """
33
34 def __init__(self, rows=1, cols=0, title='', size=(8,6), buffering=False):
[1019]35 """
36 Create a new instance of the ASAPlot plotting class.
[705]37
[1019]38 If rows < 1 then a separate call to set_panels() is required to define
39 the panel layout; refer to the doctext for set_panels().
40 """
[705]41 self.is_dead = False
[1019]42 self.figure = Figure(figsize=size, facecolor='#ddddee')
[705]43 self.canvas = None
44
[1019]45 self.set_title(title)
46 self.subplots = []
47 if rows > 0:
48 self.set_panels(rows, cols)
[705]49
[710]50 # Set matplotlib default colour sequence.
51 self.colormap = "green red black cyan magenta orange blue purple yellow pink".split()
[1019]52
[710]53 c = asaprcParams['plotter.colours']
54 if isinstance(c,str) and len(c) > 0:
55 self.colormap = c.split()
56
57 self.lsalias = {"line": [1,0],
58 "dashdot": [4,2,1,2],
59 "dashed" : [4,2,4,2],
60 "dotted" : [1,2],
61 "dashdotdot": [4,2,1,2,1,2],
62 "dashdashdot": [4,2,4,2,1,2]
63 }
64
65 styles = "line dashed dotted dashdot".split()
66 c = asaprcParams['plotter.linestyles']
67 if isinstance(c,str) and len(c) > 0:
68 styles = c.split()
69 s = []
70 for ls in styles:
71 if self.lsalias.has_key(ls):
72 s.append(self.lsalias.get(ls))
73 else:
74 s.append('-')
75 self.linestyles = s
76
[705]77 self.color = 0;
[710]78 self.linestyle = 0;
[1019]79 self.attributes = {}
80 self.loc = 0
[705]81
[1019]82 self.buffering = buffering
[705]83
84 def clear(self):
[1019]85 """
[1147]86 Delete all lines from the plot. Line numbering will restart from 0.
[1019]87 """
[705]88
[1019]89 for i in range(len(self.lines)):
90 self.delete(i)
91 self.axes.clear()
92 self.color = 0
93 self.lines = []
[705]94
[710]95 def palette(self, color, colormap=None, linestyle=0, linestyles=None):
[705]96 if colormap:
[710]97 if isinstance(colormap,list):
98 self.colormap = colormap
99 elif isinstance(colormap,str):
100 self.colormap = colormap.split()
[705]101 if 0 <= color < len(self.colormap):
102 self.color = color
[710]103 if linestyles:
104 self.linestyles = []
105 if isinstance(linestyles,list):
106 styles = linestyles
107 elif isinstance(linestyles,str):
108 styles = linestyles.split()
109 for ls in styles:
110 if self.lsalias.has_key(ls):
111 self.linestyles.append(self.lsalias.get(ls))
112 else:
113 self.linestyles.append(self.lsalias.get('line'))
114 if 0 <= linestyle < len(self.linestyles):
115 self.linestyle = linestyle
[705]116
117 def delete(self, numbers=None):
[1019]118 """
119 Delete the 0-relative line number, default is to delete the last.
120 The remaining lines are NOT renumbered.
121 """
[705]122
[1019]123 if numbers is None: numbers = [len(self.lines)-1]
[705]124
[1019]125 if not hasattr(numbers, '__iter__'):
126 numbers = [numbers]
[705]127
[1019]128 for number in numbers:
129 if 0 <= number < len(self.lines):
130 if self.lines[number] is not None:
131 for line in self.lines[number]:
132 line.set_linestyle('None')
133 self.lines[number] = None
134 self.show()
[705]135
136 def get_line(self):
[1019]137 """
138 Get the current default line attributes.
139 """
140 return self.attributes
[705]141
142
[1086]143 def hist(self, x=None, y=None, fmt=None, add=None):
[1019]144 """
145 Plot a histogram. N.B. the x values refer to the start of the
146 histogram bin.
[705]147
[1019]148 fmt is the line style as in plot().
149 """
[1086]150 from matplotlib.numerix import array
151 from matplotlib.numerix.ma import MaskedArray
[1019]152 if x is None:
153 if y is None: return
[1023]154 x = range(len(y))
[705]155
[1019]156 if len(x) != len(y):
157 return
158 l2 = 2*len(x)
[1023]159 x2 = range(l2)
[1086]160 y2 = range(12)
[1023]161 y2 = range(l2)
162 m2 = range(l2)
[1086]163 ymsk = y.raw_mask()
164 ydat = y.raw_data()
[1023]165 for i in range(l2):
[1019]166 x2[i] = x[i/2]
[1086]167 m2[i] = ymsk[i/2]
[705]168
[1023]169 y2[0] = 0.0
[1019]170 for i in range(1,l2):
[1086]171 y2[i] = ydat[(i-1)/2]
[705]172
[1086]173 self.plot(x2, MaskedArray(y2,mask=m2,copy=0), fmt, add)
[705]174
175
176 def hold(self, hold=True):
[1019]177 """
178 Buffer graphics until subsequently released.
179 """
180 self.buffering = hold
[705]181
182
183 def legend(self, loc=None):
[1019]184 """
185 Add a legend to the plot.
[705]186
[1019]187 Any other value for loc else disables the legend:
188 1: upper right
189 2: upper left
190 3: lower left
191 4: lower right
192 5: right
193 6: center left
194 7: center right
195 8: lower center
196 9: upper center
197 10: center
[705]198
[1019]199 """
[1095]200 if isinstance(loc, int):
[1098]201 self.loc = None
202 if 0 <= loc <= 10: self.loc = loc
[1095]203 else:
204 self.loc = None
205 #self.show()
[705]206
207
[1086]208 def plot(self, x=None, y=None, fmt=None, add=None):
[1019]209 """
210 Plot the next line in the current frame using the current line
211 attributes. The ASAPlot graphics window will be mapped and raised.
[705]212
[1019]213 The argument list works a bit like the matlab plot() function.
214 """
215 if x is None:
216 if y is None: return
217 x = range(len(y))
[705]218
[1019]219 elif y is None:
220 y = x
221 x = range(len(y))
[1086]222 if fmt is None:
223 line = self.axes.plot(x, y)
[1019]224 else:
[1086]225 line = self.axes.plot(x, y, fmt)
[705]226
[1019]227 # Add to an existing line?
[1086]228 i = None
[1019]229 if add is None or len(self.lines) < add < 0:
230 # Don't add.
231 self.lines.append(line)
232 i = len(self.lines) - 1
233 else:
234 if add == 0: add = len(self.lines)
235 i = add - 1
236 self.lines[i].extend(line)
[705]237
[1019]238 # Set/reset attributes for the line.
239 gotcolour = False
240 for k, v in self.attributes.iteritems():
241 if k == 'color': gotcolour = True
242 for segment in self.lines[i]:
243 getattr(segment, "set_%s"%k)(v)
[705]244
[1019]245 if not gotcolour and len(self.colormap):
246 for segment in self.lines[i]:
247 getattr(segment, "set_color")(self.colormap[self.color])
[710]248 if len(self.colormap) == 1:
249 getattr(segment, "set_dashes")(self.linestyles[self.linestyle])
[1086]250
[1019]251 self.color += 1
252 if self.color >= len(self.colormap):
253 self.color = 0
[705]254
[710]255 if len(self.colormap) == 1:
256 self.linestyle += 1
[1019]257 if self.linestyle >= len(self.linestyles):
258 self.linestyle = 0
[710]259
[1019]260 self.show()
[705]261
262
263 def position(self):
[1019]264 """
265 Use the mouse to get a position from a graph.
266 """
[705]267
[1019]268 def position_disable(event):
269 self.register('button_press', None)
270 print '%.4f, %.4f' % (event.xdata, event.ydata)
[705]271
[1019]272 print 'Press any mouse button...'
273 self.register('button_press', position_disable)
[705]274
275
276 def region(self):
[1019]277 """
278 Use the mouse to get a rectangular region from a plot.
[705]279
[1019]280 The return value is [x0, y0, x1, y1] in world coordinates.
281 """
[705]282
[1019]283 def region_start(event):
284 height = self.canvas.figure.bbox.height()
285 self.rect = {'fig': None, 'height': height,
286 'x': event.x, 'y': height - event.y,
287 'world': [event.xdata, event.ydata,
288 event.xdata, event.ydata]}
289 self.register('button_press', None)
290 self.register('motion_notify', region_draw)
291 self.register('button_release', region_disable)
[705]292
[1019]293 def region_draw(event):
294 self.canvas._tkcanvas.delete(self.rect['fig'])
295 self.rect['fig'] = self.canvas._tkcanvas.create_rectangle(
296 self.rect['x'], self.rect['y'],
297 event.x, self.rect['height'] - event.y)
[705]298
[1019]299 def region_disable(event):
300 self.register('motion_notify', None)
301 self.register('button_release', None)
[705]302
[1019]303 self.canvas._tkcanvas.delete(self.rect['fig'])
[705]304
[1019]305 self.rect['world'][2:4] = [event.xdata, event.ydata]
306 print '(%.2f, %.2f) (%.2f, %.2f)' % (self.rect['world'][0],
307 self.rect['world'][1], self.rect['world'][2],
308 self.rect['world'][3])
[705]309
[1019]310 self.register('button_press', region_start)
[705]311
[1019]312 # This has to be modified to block and return the result (currently
313 # printed by region_disable) when that becomes possible in matplotlib.
[705]314
[1019]315 return [0.0, 0.0, 0.0, 0.0]
[705]316
317
318 def register(self, type=None, func=None):
[1019]319 """
320 Register, reregister, or deregister events of type 'button_press',
321 'button_release', or 'motion_notify'.
[705]322
[1019]323 The specified callback function should have the following signature:
[705]324
[1019]325 def func(event)
[705]326
[1019]327 where event is an MplEvent instance containing the following data:
[705]328
[1019]329 name # Event name.
330 canvas # FigureCanvas instance generating the event.
331 x = None # x position - pixels from left of canvas.
332 y = None # y position - pixels from bottom of canvas.
333 button = None # Button pressed: None, 1, 2, 3.
334 key = None # Key pressed: None, chr(range(255)), shift,
335 win, or control
336 inaxes = None # Axes instance if cursor within axes.
337 xdata = None # x world coordinate.
338 ydata = None # y world coordinate.
[705]339
[1019]340 For example:
[705]341
[1019]342 def mouse_move(event):
343 print event.xdata, event.ydata
[705]344
[1019]345 a = asaplot()
346 a.register('motion_notify', mouse_move)
[705]347
[1019]348 If func is None, the event is deregistered.
[705]349
[1019]350 Note that in TkAgg keyboard button presses don't generate an event.
351 """
[705]352
[1019]353 if not self.events.has_key(type): return
[705]354
[1019]355 if func is None:
356 if self.events[type] is not None:
357 # It's not clear that this does anything.
358 self.canvas.mpl_disconnect(self.events[type])
359 self.events[type] = None
[705]360
[1019]361 # It seems to be necessary to return events to the toolbar.
362 if type == 'motion_notify':
363 self.canvas.mpl_connect(type + '_event',
364 self.figmgr.toolbar.mouse_move)
365 elif type == 'button_press':
366 self.canvas.mpl_connect(type + '_event',
367 self.figmgr.toolbar.press)
368 elif type == 'button_release':
369 self.canvas.mpl_connect(type + '_event',
370 self.figmgr.toolbar.release)
[705]371
[1019]372 else:
373 self.events[type] = self.canvas.mpl_connect(type + '_event', func)
[705]374
375
376 def release(self):
[1019]377 """
378 Release buffered graphics.
379 """
380 self.buffering = False
381 self.show()
[705]382
383
[1095]384 def save(self, fname=None, orientation=None, dpi=None, papertype=None):
[1019]385 """
386 Save the plot to a file.
[705]387
[1019]388 fname is the name of the output file. The image format is determined
389 from the file suffix; 'png', 'ps', and 'eps' are recognized. If no
390 file name is specified 'yyyymmdd_hhmmss.png' is created in the current
391 directory.
392 """
[1095]393 from asap import rcParams
394 if papertype is None:
395 papertype = rcParams['plotter.papertype']
[1019]396 if fname is None:
397 from datetime import datetime
398 dstr = datetime.now().strftime('%Y%m%d_%H%M%S')
399 fname = 'asap'+dstr+'.png'
[705]400
[1019]401 d = ['png','.ps','eps']
[705]402
[1019]403 from os.path import expandvars
404 fname = expandvars(fname)
[705]405
[1019]406 if fname[-3:].lower() in d:
407 try:
[705]408 if fname[-3:].lower() == ".ps":
[1020]409 from matplotlib import __version__ as mv
[705]410 w = self.figure.figwidth.get()
[1019]411 h = self.figure.figheight.get()
412
[705]413 if orientation is None:
[1147]414 # oriented
[705]415 if w > h:
416 orientation = 'landscape'
417 else:
418 orientation = 'portrait'
[1095]419 from matplotlib.backends.backend_ps import papersize
420 pw,ph = papersize[papertype.lower()]
[1025]421 ds = None
422 if orientation == 'landscape':
[1095]423 ds = min(ph/w, pw/h)
[1025]424 else:
[1095]425 ds = min(pw/w, ph/h)
[1025]426 ow = ds * w
427 oh = ds * h
[1095]428 self.figure.set_figsize_inches((ow, oh))
429 self.figure.savefig(fname, orientation=orientation,
430 papertype=papertype.lower())
431 self.figure.set_figsize_inches((w, h))
[705]432 print 'Written file %s' % (fname)
[1019]433 else:
[705]434 if dpi is None:
435 dpi =150
[1025]436 self.figure.savefig(fname,dpi=dpi)
[705]437 print 'Written file %s' % (fname)
[1019]438 except IOError, msg:
439 print 'Failed to save %s: Error msg was\n\n%s' % (fname, err)
440 return
441 else:
442 print "Invalid image type. Valid types are:"
443 print "'ps', 'eps', 'png'"
[705]444
445
446 def set_axes(self, what=None, *args, **kwargs):
[1019]447 """
448 Set attributes for the axes by calling the relevant Axes.set_*()
449 method. Colour translation is done as described in the doctext
450 for palette().
451 """
[705]452
[1019]453 if what is None: return
454 if what[-6:] == 'colour': what = what[:-6] + 'color'
[705]455
[1153]456 key = "colour"
457 if kwargs.has_key(key):
458 val = kwargs.pop(key)
459 kwargs["color"] = val
[705]460
[1153]461 getattr(self.axes, "set_%s"%what)(*args, **kwargs)
[705]462
[1153]463 self.show(hardrefresh=False)
[705]464
[1019]465
[705]466 def set_figure(self, what=None, *args, **kwargs):
[1019]467 """
468 Set attributes for the figure by calling the relevant Figure.set_*()
469 method. Colour translation is done as described in the doctext
470 for palette().
471 """
[705]472
[1019]473 if what is None: return
474 if what[-6:] == 'colour': what = what[:-6] + 'color'
475 #if what[-5:] == 'color' and len(args):
476 # args = (get_colour(args[0]),)
[705]477
[1019]478 newargs = {}
479 for k, v in kwargs.iteritems():
480 k = k.lower()
481 if k == 'colour': k = 'color'
482 newargs[k] = v
[705]483
[1019]484 getattr(self.figure, "set_%s"%what)(*args, **newargs)
[1153]485 self.show(hardrefresh=False)
[705]486
487
488 def set_limits(self, xlim=None, ylim=None):
[1019]489 """
490 Set x-, and y-limits for each subplot.
[705]491
[1019]492 xlim = [xmin, xmax] as in axes.set_xlim().
493 ylim = [ymin, ymax] as in axes.set_ylim().
494 """
495 for s in self.subplots:
496 self.axes = s['axes']
497 self.lines = s['lines']
[705]498 oldxlim = list(self.axes.get_xlim())
499 oldylim = list(self.axes.get_ylim())
500 if xlim is not None:
501 for i in range(len(xlim)):
502 if xlim[i] is not None:
503 oldxlim[i] = xlim[i]
[1019]504 if ylim is not None:
[705]505 for i in range(len(ylim)):
506 if ylim[i] is not None:
507 oldylim[i] = ylim[i]
508 self.axes.set_xlim(oldxlim)
509 self.axes.set_ylim(oldylim)
510 return
511
512
513 def set_line(self, number=None, **kwargs):
[1019]514 """
515 Set attributes for the specified line, or else the next line(s)
516 to be plotted.
[705]517
[1019]518 number is the 0-relative number of a line that has already been
519 plotted. If no such line exists, attributes are recorded and used
520 for the next line(s) to be plotted.
[705]521
[1019]522 Keyword arguments specify Line2D attributes, e.g. color='r'. Do
[705]523
[1019]524 import matplotlib
525 help(matplotlib.lines)
[705]526
[1019]527 The set_* methods of class Line2D define the attribute names and
528 values. For non-US usage, "colour" is recognized as synonymous with
529 "color".
[705]530
[1019]531 Set the value to None to delete an attribute.
[705]532
[1019]533 Colour translation is done as described in the doctext for palette().
534 """
[705]535
[1019]536 redraw = False
537 for k, v in kwargs.iteritems():
538 k = k.lower()
539 if k == 'colour': k = 'color'
[705]540
[1019]541 if 0 <= number < len(self.lines):
542 if self.lines[number] is not None:
543 for line in self.lines[number]:
544 getattr(line, "set_%s"%k)(v)
545 redraw = True
546 else:
547 if v is None:
548 del self.attributes[k]
549 else:
550 self.attributes[k] = v
[705]551
[1153]552 if redraw: self.show(hardrefresh=False)
[705]553
554
555 def set_panels(self, rows=1, cols=0, n=-1, nplots=-1, ganged=True):
[1019]556 """
557 Set the panel layout.
[705]558
[1019]559 rows and cols, if cols != 0, specify the number of rows and columns in
560 a regular layout. (Indexing of these panels in matplotlib is row-
561 major, i.e. column varies fastest.)
[705]562
[1019]563 cols == 0 is interpreted as a retangular layout that accomodates
564 'rows' panels, e.g. rows == 6, cols == 0 is equivalent to
565 rows == 2, cols == 3.
[705]566
[1019]567 0 <= n < rows*cols is interpreted as the 0-relative panel number in
568 the configuration specified by rows and cols to be added to the
569 current figure as its next 0-relative panel number (i). This allows
570 non-regular panel layouts to be constructed via multiple calls. Any
571 other value of n clears the plot and produces a rectangular array of
572 empty panels. The number of these may be limited by nplots.
573 """
574 if n < 0 and len(self.subplots):
575 self.figure.clear()
576 self.set_title()
[705]577
[1019]578 if rows < 1: rows = 1
[705]579
[1019]580 if cols <= 0:
581 i = int(sqrt(rows))
582 if i*i < rows: i += 1
583 cols = i
[705]584
[1019]585 if i*(i-1) >= rows: i -= 1
586 rows = i
[705]587
[1019]588 if 0 <= n < rows*cols:
589 i = len(self.subplots)
590 self.subplots.append({})
[705]591
[1019]592 self.subplots[i]['axes'] = self.figure.add_subplot(rows,
593 cols, n+1)
594 self.subplots[i]['lines'] = []
[705]595
[1019]596 if i == 0: self.subplot(0)
[705]597
[1019]598 self.rows = 0
599 self.cols = 0
[705]600
[1019]601 else:
602 self.subplots = []
[705]603
[1019]604 if nplots < 1 or rows*cols < nplots:
605 nplots = rows*cols
[1025]606 if ganged:
607 hsp,wsp = None,None
608 if rows > 1: hsp = 0.0001
609 if cols > 1: wsp = 0.0001
610 self.figure.subplots_adjust(wspace=wsp,hspace=hsp)
[1019]611 for i in range(nplots):
612 self.subplots.append({})
[1153]613 self.subplots[i]['lines'] = []
614 if not ganged:
615 self.subplots[i]['axes'] = self.figure.add_subplot(rows,
[1019]616 cols, i+1)
[1153]617 else:
618 if i == 0:
619 self.subplots[i]['axes'] = self.figure.add_subplot(rows,
620 cols, i+1)
621 else:
622 self.subplots[i]['axes'] = self.figure.add_subplot(rows,
623 cols, i+1,
624 sharex=self.subplots[0]['axes'],
625 sharey=self.subplots[0]['axes'])
[705]626 # Suppress tick labelling for interior subplots.
627 if i <= (rows-1)*cols - 1:
628 if i+cols < nplots:
629 # Suppress x-labels for frames width
630 # adjacent frames
[1153]631 for tick in self.subplots[i]['axes'].xaxis.majorTicks:
632 tick.label1On = False
[1019]633 self.subplots[i]['axes'].xaxis.label.set_visible(False)
[705]634 if i%cols:
635 # Suppress y-labels for frames not in the left column.
636 for tick in self.subplots[i]['axes'].yaxis.majorTicks:
637 tick.label1On = False
638 self.subplots[i]['axes'].yaxis.label.set_visible(False)
[1025]639 # disable the first tick of [1:ncol-1] of the last row
[1153]640 #if i+1 < nplots:
641 # self.subplots[i]['axes'].xaxis.majorTicks[0].label1On = False
[1019]642 self.rows = rows
643 self.cols = cols
644 self.subplot(0)
[705]645
[1153]646 def tidy(self):
647 # this needs to be exceuted after the first "refresh"
648 nplots = len(self.subplots)
649 if nplots == 1: return
650 for i in xrange(nplots):
651 ax = self.subplots[i]['axes']
652 if i%self.cols:
653 ax.xaxis.majorTicks[0].label1On = False
654 else:
655 if i != 0:
656 ax.yaxis.majorTicks[-1].label1On = False
657
658
[705]659 def set_title(self, title=None):
[1019]660 """
661 Set the title of the plot window. Use the previous title if title is
662 omitted.
663 """
664 if title is not None:
665 self.title = title
[705]666
[1019]667 self.figure.text(0.5, 0.95, self.title, horizontalalignment='center')
[705]668
669
[1153]670 def show(self, hardrefresh=True):
[1019]671 """
672 Show graphics dependent on the current buffering state.
673 """
[1153]674 if not hardrefresh: return
[1019]675 if not self.buffering:
676 if self.loc is not None:
[1086]677 for sp in self.subplots:
[1019]678 lines = []
679 labels = []
680 i = 0
[1086]681 for line in sp['lines']:
[1019]682 i += 1
683 if line is not None:
684 lines.append(line[0])
685 lbl = line[0].get_label()
686 if lbl == '':
687 lbl = str(i)
688 labels.append(lbl)
[705]689
[1019]690 if len(lines):
[1147]691 fp = FP(size=rcParams['legend.fontsize'])
692 fsz = fp.get_size_in_points() - len(lines)
693 fp.set_size(max(fsz,6))
[1086]694 sp['axes'].legend(tuple(lines), tuple(labels),
[1147]695 self.loc, prop=fp)
[1019]696 else:
[1086]697 sp['axes'].legend((' '))
[705]698
[1086]699 from matplotlib.artist import setp
[1147]700 fp = FP(size=rcParams['xtick.labelsize'])
701 xts = fp.get_size_in_points()- (self.cols)/2
702 fp = FP(size=rcParams['ytick.labelsize'])
703 yts = fp.get_size_in_points() - (self.rows)/2
[1086]704 for sp in self.subplots:
705 ax = sp['axes']
706 s = ax.title.get_size()
707 tsize = s-(self.cols+self.rows)
708 ax.title.set_size(tsize)
[1147]709 fp = FP(size=rcParams['axes.labelsize'])
[1086]710 setp(ax.get_xticklabels(), fontsize=xts)
711 setp(ax.get_yticklabels(), fontsize=yts)
[1147]712 origx = fp.get_size_in_points()
713 origy = origx
[1086]714 off = 0
715 if self.cols > 1: off = self.cols
716 xfsize = origx-off
717 ax.xaxis.label.set_size(xfsize)
718 off = 0
719 if self.rows > 1: off = self.rows
720 yfsize = origy-off
721 ax.yaxis.label.set_size(yfsize)
[705]722
723 def subplot(self, i=None, inc=None):
[1019]724 """
725 Set the subplot to the 0-relative panel number as defined by one or
726 more invokations of set_panels().
727 """
728 l = len(self.subplots)
729 if l:
730 if i is not None:
731 self.i = i
[705]732
[1019]733 if inc is not None:
734 self.i += inc
[705]735
[1019]736 self.i %= l
737 self.axes = self.subplots[self.i]['axes']
738 self.lines = self.subplots[self.i]['lines']
[705]739
740 def text(self, *args, **kwargs):
[1019]741 """
742 Add text to the figure.
743 """
744 self.figure.text(*args, **kwargs)
745 self.show()
[1147]746
747 def vline_with_label(self, x, y, label,
748 location='bottom', rotate=0.0, **kwargs):
749 """
750 Plot a vertical line with label.
751 It takes "world" values fo x and y.
752 """
753 ax = self.axes
754 # need this to suppress autoscaling during this function
755 self.axes.set_autoscale_on(False)
756 ymin = 0.0
757 ymax = 1.0
758 valign = 'center'
759 if location.lower() == 'top':
760 y = max(0.0, y)
761 elif location.lower() == 'bottom':
762 y = min(0.0, y)
763 lbloffset = 0.06
764 # a rough estimate for the bb of the text
765 if rotate > 0.0: lbloffset = 0.03*len(label)
766 peakoffset = 0.01
767 xy0 = ax.transData.xy_tup((x,y))
768 # get relative coords
769 xy = ax.transAxes.inverse_xy_tup(xy0)
770 if location.lower() == 'top':
771 ymax = 1.0-lbloffset
772 ymin = xy[1]+peakoffset
773 valign = 'bottom'
774 ylbl = ymax+0.01
775 elif location.lower() == 'bottom':
776 ymin = lbloffset
777 ymax = xy[1]-peakoffset
778 valign = 'top'
779 ylbl = ymin-0.01
780 trans = blend_xy_sep_transform(ax.transData, ax.transAxes)
781 l = ax.axvline(x, ymin, ymax, color='black', **kwargs)
782 t = ax.text(x, ylbl ,label, verticalalignment=valign,
783 horizontalalignment='center',
784 rotation=rotate,transform = trans)
785 self.axes.set_autoscale_on(True)
Note: See TracBrowser for help on using the repository browser.