source: trunk/python/asaplotbase.py@ 2699

Last change on this file since 2699 was 2699, checked in by Kana Sugimoto, 12 years ago

New Development: No

JIRA Issue: No (bug fixes)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs: unit tests of sdplot

Put in Release Notes: No

Module(s): asapplotter and sdplot

Description:

Fixed a bug which caused failure of plots by user defined linestyles.
Made sure data is plotted on mpl plotter (not on ASAP plotter) by
plotpointing and plotazel.


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