source: trunk/python/asaplotbase.py@ 1932

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

New Development: No

JIRA Issue: Yes (CAS-1808)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs: sdplot unit test

Put in Release Notes: No

Module(s): ASAP plotter and sdplot

Description:

Disabled axes labels of interior subplots.


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