source: trunk/python/asaplotbase.py@ 2534

Last change on this file since 2534 was 2451, checked in by Kana Sugimoto, 13 years ago

New Development: No

JIRA Issue: Yes (CAS-3749)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs: unit tests of sdplot

Put in Release Notes: No

Module(s): sdplot, sdfit, sdstat, sdflag, sdcal, sdreduce

Description:

Made asapplotter not to generate plotter window at start-up, but the window is
only generated at the first invokation of plotting operation.


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