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

Last change on this file since 1612 was 1612, 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: Yes

Module(s): Module Names change impacts.

Description: Describe your changes here...

I have changed that almost all log messages are output to casapy.log,
not to the terminal window. After this change, asap becomes to depend on casapy
and is not running in standalone, because asap have to import taskinit module
to access casalogger.


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