source: trunk/python/asaplotbase.py@ 2683

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

New Development: No

JIRA Issue: Yes (related to CAS-3749)

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed: added a new method, _alive(), in asaplotbase class

Test Programs: Interactive tests

Put in Release Notes: No

Module(s):

Description:

Added a new method, _alive(), in asaplotbase class. The method return True
if asaplot instance is alive. More complete check compared to 'is_dead' parameter.
asapplotter._assert_plotter method is simplified by calling this function.

Fixed misc bugs found in interactive tests.

  1. set back linewidth = 1 in plots invoked by modules, interactivemask, asapmath, and asapfitter.
  2. interactivemask module: plotter in properly quited at the end.
  3. interactivemask module: avoid error when user close interacive plot window before calling the finalization method, finish_selection().
  4. added definition of a dummy function, quit(), in asaplot class.


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