source: branches/alma/python/asaplotbase.py@ 1619

Last change on this file since 1619 was 1614, checked in by Takeshi Nakazato, 16 years ago

New Development: No

JIRA Issue: Yes CAS-729, CAS-1147

Ready to Release: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: No

Module(s): Module Names change impacts.

Description: Describe your changes here...

  1. Added level parameter to print_log()
  2. Replaced casalog.post() to asaplog.push() + print_log().


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