source: branches/alma/python/asaplotbase.py@ 1749

Last change on this file since 1749 was 1723, checked in by Kana Sugimoto, 14 years ago

New Development: No

JIRA Issue: Yes (CAS-1801, CAS-2064)

Ready to Release: Yes

Interface Changes: Yes

What Interface Changed:
Three methods, print_headder(), set_panellayout() and _reset_panellayout()
are added to the class asapplotter.
A parameter layout (list) is added to set_layout() in asaplotbase class.

Test Programs: run sdplot with header & plotstyle=True + layout parameter set.

Put in Release Notes: Yes

Module(s): sdplot() task.

Description:

  1. asapplotter.print_header(plot=True, fontsize=9, logger=False, selstr=, extrastr=): prints scantable header on the plot and/or logger (see help doc for parameter details). Note that the header information will not overlayed to the plot by plotazel() and plotpointing().
  2. set_panellayout(layout=[],refresh=True): sets the layout of subplots. layout is a list of subplots layout in figure coordinate (0-1) in order of [left, bottom, right, top, horizontal space btw panels, vertical space btw panels]
  3. _reset_panellayout(): resets the layout of subplots to matplotlib rc value.
  4. a member variable 'asapplotter._panellayout' (list) is specified to store layout values.


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