source: trunk/python/asaplotbase.py@ 2030

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

New Development: No

JIRA Issue: Yes (CAS-2765/ASAP-230)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs: plot spectra, select a spectrum with left-mouse button, and drag on it

Put in Release Notes: No

Module(s): asapplotter, sdplot

Description:

Fixed a bug in asapplotter, i.e., spec value printing doesn't work once you changed the pages.


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