00001 """
00002 ASAP plotting class based on matplotlib.
00003 """
00004
00005 import sys
00006 from re import match
00007 import matplotlib
00008
00009 from matplotlib.figure import Figure, Text
00010 from matplotlib.font_manager import FontProperties as FP
00011 from numpy import sqrt
00012 from matplotlib import rc, rcParams
00013 from matplotlib.ticker import OldScalarFormatter
00014 from matplotlib import _pylab_helpers
00015
00016 from asap.parameters import rcParams as asaprcParams
00017 from asap.logging import asaplog
00018
00019
00020 try:
00021 from matplotlib.transforms import blended_transform_factory
00022 except ImportError:
00023 from matplotlib.transforms import blend_xy_sep_transform as blended_transform_factory
00024
00025 mvers = matplotlib.__version__.split(".")
00026 if int(mvers[0]) == 0 and int(mvers[1]) < 99:
00027
00028 asaplog.push( "matplotlib version < 0.99. This might cause errors. Please upgrade." )
00029 asaplog.post( 'WARN' )
00030
00031 class asaplotbase:
00032 """
00033 ASAP plotting base class based on matplotlib.
00034 """
00035
00036 def __init__(self, rows=1, cols=0, title='', size=None, buffering=False):
00037 """
00038 Create a new instance of the ASAPlot plotting class.
00039
00040 If rows < 1 then a separate call to set_panels() is required to define
00041 the panel layout; refer to the doctext for set_panels().
00042 """
00043 self.is_dead = False
00044 self.figure = Figure(figsize=size, facecolor='#ddddee')
00045 self.canvas = None
00046
00047 self.set_title(title)
00048 self.subplots = []
00049 if rows > 0:
00050 self.set_panels(rows, cols)
00051
00052
00053 self.colormap = "green red black cyan magenta orange blue purple yellow pink".split()
00054
00055 c = asaprcParams['plotter.colours']
00056 if isinstance(c,str) and len(c) > 0:
00057 self.colormap = c.split()
00058
00059 self.lsalias = {"line": [1,0],
00060 "dashdot": [4,2,1,2],
00061 "dashed" : [4,2,4,2],
00062 "dotted" : [1,2],
00063 "dashdotdot": [4,2,1,2,1,2],
00064 "dashdashdot": [4,2,4,2,1,2]
00065 }
00066
00067 styles = "line dashed dotted dashdot".split()
00068 c = asaprcParams['plotter.linestyles']
00069 if isinstance(c,str) and len(c) > 0:
00070 styles = c.split()
00071 s = []
00072 for ls in styles:
00073 if self.lsalias.has_key(ls):
00074 s.append(self.lsalias.get(ls))
00075 else:
00076 s.append('-')
00077 self.linestyles = s
00078
00079 self.color = 0;
00080 self.linestyle = 0;
00081 self.attributes = {}
00082 self.loc = 0
00083
00084 self.buffering = buffering
00085
00086 self.events = {'button_press':None,
00087 'button_release':None,
00088 'motion_notify':None}
00089
00090 def clear(self):
00091 """
00092 Delete all lines from the plot. Line numbering will restart from 0.
00093 """
00094
00095 for i in range(len(self.lines)):
00096 self.delete(i)
00097 self.axes.clear()
00098 self.color = 0
00099 self.lines = []
00100
00101 def palette(self, color, colormap=None, linestyle=0, linestyles=None):
00102 if colormap:
00103 if isinstance(colormap,list):
00104 self.colormap = colormap
00105 elif isinstance(colormap,str):
00106 self.colormap = colormap.split()
00107 if 0 <= color < len(self.colormap):
00108 self.color = color
00109 if linestyles:
00110 self.linestyles = []
00111 if isinstance(linestyles,list):
00112 styles = linestyles
00113 elif isinstance(linestyles,str):
00114 styles = linestyles.split()
00115 for ls in styles:
00116 if self.lsalias.has_key(ls):
00117 self.linestyles.append(self.lsalias.get(ls))
00118 else:
00119 self.linestyles.append(self.lsalias.get('line'))
00120 if 0 <= linestyle < len(self.linestyles):
00121 self.linestyle = linestyle
00122
00123 def delete(self, numbers=None):
00124 """
00125 Delete the 0-relative line number, default is to delete the last.
00126 The remaining lines are NOT renumbered.
00127 """
00128
00129 if numbers is None: numbers = [len(self.lines)-1]
00130
00131 if not hasattr(numbers, '__iter__'):
00132 numbers = [numbers]
00133
00134 for number in numbers:
00135 if 0 <= number < len(self.lines):
00136 if self.lines[number] is not None:
00137 for line in self.lines[number]:
00138 line.set_linestyle('None')
00139 self.lines[number] = None
00140 self.show()
00141
00142 def get_line(self):
00143 """
00144 Get the current default line attributes.
00145 """
00146 return self.attributes
00147
00148
00149 def hist(self, x=None, y=None, fmt=None, add=None):
00150 """
00151 Plot a histogram. N.B. the x values refer to the start of the
00152 histogram bin.
00153
00154 fmt is the line style as in plot().
00155 """
00156 from numpy import array
00157 from numpy.ma import MaskedArray
00158 if x is None:
00159 if y is None: return
00160 x = range(len(y))
00161
00162 if len(x) != len(y):
00163 return
00164 l2 = 2*len(x)
00165 x2 = range(l2)
00166 y2 = range(12)
00167 y2 = range(l2)
00168 m2 = range(l2)
00169 ymsk = None
00170 ydat = None
00171 if hasattr(y, "raw_mask"):
00172
00173 ymsk = y.raw_mask()
00174 ydat = y.raw_data()
00175 else:
00176 ymsk = y.mask
00177 ydat = y.data
00178 for i in range(l2):
00179 x2[i] = x[i/2]
00180 m2[i] = ymsk[i/2]
00181
00182 y2[0] = 0.0
00183 for i in range(1,l2):
00184 y2[i] = ydat[(i-1)/2]
00185
00186 self.plot(x2, MaskedArray(y2,mask=m2,copy=0), fmt, add)
00187
00188
00189 def hold(self, hold=True):
00190 """
00191 Buffer graphics until subsequently released.
00192 """
00193 self.buffering = hold
00194
00195
00196 def legend(self, loc=None):
00197 """
00198 Add a legend to the plot.
00199
00200 Any other value for loc else disables the legend:
00201 1: upper right
00202 2: upper left
00203 3: lower left
00204 4: lower right
00205 5: right
00206 6: center left
00207 7: center right
00208 8: lower center
00209 9: upper center
00210 10: center
00211
00212 """
00213 if isinstance(loc, int):
00214 self.loc = None
00215 if 0 <= loc <= 10: self.loc = loc
00216 else:
00217 self.loc = None
00218
00219
00220
00221 def plot(self, x=None, y=None, fmt=None, add=None):
00222 """
00223 Plot the next line in the current frame using the current line
00224 attributes. The ASAPlot graphics window will be mapped and raised.
00225
00226 The argument list works a bit like the matlab plot() function.
00227 """
00228 if x is None:
00229 if y is None: return
00230 x = range(len(y))
00231
00232 elif y is None:
00233 y = x
00234 x = range(len(y))
00235 if fmt is None:
00236 line = self.axes.plot(x, y)
00237 else:
00238 line = self.axes.plot(x, y, fmt)
00239
00240
00241 line[0].set_picker(5.0)
00242
00243
00244 i = None
00245 if add is None or len(self.lines) < add < 0:
00246
00247 self.lines.append(line)
00248 i = len(self.lines) - 1
00249 else:
00250 if add == 0: add = len(self.lines)
00251 i = add - 1
00252 self.lines[i].extend(line)
00253
00254
00255 gotcolour = False
00256 for k, v in self.attributes.iteritems():
00257 if k == 'color': gotcolour = True
00258 for segment in self.lines[i]:
00259 getattr(segment, "set_%s"%k)(v)
00260
00261 if not gotcolour and len(self.colormap):
00262 for segment in self.lines[i]:
00263 getattr(segment, "set_color")(self.colormap[self.color])
00264 if len(self.colormap) == 1:
00265 getattr(segment, "set_dashes")(self.linestyles[self.linestyle])
00266
00267 self.color += 1
00268 if self.color >= len(self.colormap):
00269 self.color = 0
00270
00271 if len(self.colormap) == 1:
00272 self.linestyle += 1
00273 if self.linestyle >= len(self.linestyles):
00274 self.linestyle = 0
00275
00276 self.show()
00277
00278
00279 def position(self):
00280 """
00281 Use the mouse to get a position from a graph.
00282 """
00283
00284 def position_disable(event):
00285 self.register('button_press', None)
00286 print '%.4f, %.4f' % (event.xdata, event.ydata)
00287
00288 print 'Press any mouse button...'
00289 self.register('button_press', position_disable)
00290
00291
00292 def get_region(self):
00293 pos = []
00294 print "Please select the bottom/left point"
00295 pos.append(self.figure.ginput(n=1, show_clicks=False)[0])
00296 print "Please select the top/right point"
00297 pos.append(self.figure.ginput(n=1, show_clicks=False)[0])
00298 return pos
00299
00300 def get_point(self):
00301 print "Please select the point"
00302 pt = self.figure.ginput(n=1, show_clicks=False)
00303 if pt:
00304 return pt[0]
00305 else:
00306 return None
00307
00308 def region(self):
00309 """
00310 Use the mouse to get a rectangular region from a plot.
00311
00312 The return value is [x0, y0, x1, y1] in world coordinates.
00313 """
00314
00315 def region_start(event):
00316 self.rect = {'x': event.x, 'y': event.y,
00317 'world': [event.xdata, event.ydata,
00318 event.xdata, event.ydata]}
00319 self.register('button_press', None)
00320 self.register('motion_notify', region_draw)
00321 self.register('button_release', region_disable)
00322
00323 def region_draw(event):
00324 self.figmgr.toolbar.draw_rubberband(event, event.x, event.y,
00325 self.rect['x'], self.rect['y'])
00326
00327 def region_disable(event):
00328 self.register('motion_notify', None)
00329 self.register('button_release', None)
00330
00331 self.rect['world'][2:4] = [event.xdata, event.ydata]
00332 print '(%.2f, %.2f) (%.2f, %.2f)' % (self.rect['world'][0],
00333 self.rect['world'][1], self.rect['world'][2],
00334 self.rect['world'][3])
00335 self.figmgr.toolbar.release(event)
00336
00337 self.register('button_press', region_start)
00338
00339
00340
00341
00342 return [0.0, 0.0, 0.0, 0.0]
00343
00344
00345 def register(self, type=None, func=None):
00346 """
00347 Register, reregister, or deregister events of type 'button_press',
00348 'button_release', or 'motion_notify'.
00349
00350 The specified callback function should have the following signature:
00351
00352 def func(event)
00353
00354 where event is an MplEvent instance containing the following data:
00355
00356 name # Event name.
00357 canvas # FigureCanvas instance generating the event.
00358 x = None # x position - pixels from left of canvas.
00359 y = None # y position - pixels from bottom of canvas.
00360 button = None # Button pressed: None, 1, 2, 3.
00361 key = None # Key pressed: None, chr(range(255)), shift,
00362 win, or control
00363 inaxes = None # Axes instance if cursor within axes.
00364 xdata = None # x world coordinate.
00365 ydata = None # y world coordinate.
00366
00367 For example:
00368
00369 def mouse_move(event):
00370 print event.xdata, event.ydata
00371
00372 a = asaplot()
00373 a.register('motion_notify', mouse_move)
00374
00375 If func is None, the event is deregistered.
00376
00377 Note that in TkAgg keyboard button presses don't generate an event.
00378 """
00379
00380 if not self.events.has_key(type): return
00381
00382 if func is None:
00383 if self.events[type] is not None:
00384
00385 self.canvas.mpl_disconnect(self.events[type])
00386 self.events[type] = None
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 else:
00400 self.events[type] = self.canvas.mpl_connect(type + '_event', func)
00401
00402
00403 def release(self):
00404 """
00405 Release buffered graphics.
00406 """
00407 self.buffering = False
00408 self.show()
00409
00410
00411 def save(self, fname=None, orientation=None, dpi=None, papertype=None):
00412 """
00413 Save the plot to a file.
00414
00415 fname is the name of the output file. The image format is determined
00416 from the file suffix; 'png', 'ps', and 'eps' are recognized. If no
00417 file name is specified 'yyyymmdd_hhmmss.png' is created in the current
00418 directory.
00419 """
00420 from asap import rcParams
00421 if papertype is None:
00422 papertype = rcParams['plotter.papertype']
00423 if fname is None:
00424 from datetime import datetime
00425 dstr = datetime.now().strftime('%Y%m%d_%H%M%S')
00426 fname = 'asap'+dstr+'.png'
00427
00428 d = ['png','.ps','eps', 'svg']
00429
00430 from os.path import expandvars
00431 fname = expandvars(fname)
00432
00433 if fname[-3:].lower() in d:
00434 try:
00435 if fname[-3:].lower() == ".ps":
00436 from matplotlib import __version__ as mv
00437 w = self.figure.get_figwidth()
00438 h = self.figure.get_figheight()
00439
00440 if orientation is None:
00441
00442 if w > h:
00443 orientation = 'landscape'
00444 else:
00445 orientation = 'portrait'
00446 from matplotlib.backends.backend_ps import papersize
00447 pw,ph = papersize[papertype.lower()]
00448 ds = None
00449 if orientation == 'landscape':
00450 ds = min(ph/w, pw/h)
00451 else:
00452 ds = min(pw/w, ph/h)
00453 ow = ds * w
00454 oh = ds * h
00455 self.figure.set_size_inches((ow, oh))
00456 self.figure.savefig(fname, orientation=orientation,
00457 papertype=papertype.lower())
00458 self.figure.set_size_inches((w, h))
00459 print 'Written file %s' % (fname)
00460 else:
00461 if dpi is None:
00462 dpi =150
00463 self.figure.savefig(fname,dpi=dpi)
00464 print 'Written file %s' % (fname)
00465 except IOError, msg:
00466
00467 asaplog.post()
00468 asaplog.push('Failed to save %s: Error msg was\n\n%s' % (fname, str(msg)))
00469 asaplog.post( 'ERROR' )
00470 return
00471 else:
00472
00473
00474 asaplog.push( "Invalid image type. Valid types are:" )
00475 asaplog.push( "'ps', 'eps', 'png', 'svg'" )
00476 asaplog.post('WARN')
00477
00478
00479 def set_axes(self, what=None, *args, **kwargs):
00480 """
00481 Set attributes for the axes by calling the relevant Axes.set_*()
00482 method. Colour translation is done as described in the doctext
00483 for palette().
00484 """
00485
00486 if what is None: return
00487 if what[-6:] == 'colour': what = what[:-6] + 'color'
00488
00489 key = "colour"
00490 if kwargs.has_key(key):
00491 val = kwargs.pop(key)
00492 kwargs["color"] = val
00493
00494 getattr(self.axes, "set_%s"%what)(*args, **kwargs)
00495
00496 self.show(hardrefresh=False)
00497
00498
00499 def set_figure(self, what=None, *args, **kwargs):
00500 """
00501 Set attributes for the figure by calling the relevant Figure.set_*()
00502 method. Colour translation is done as described in the doctext
00503 for palette().
00504 """
00505
00506 if what is None: return
00507 if what[-6:] == 'colour': what = what[:-6] + 'color'
00508
00509
00510
00511 newargs = {}
00512 for k, v in kwargs.iteritems():
00513 k = k.lower()
00514 if k == 'colour': k = 'color'
00515 newargs[k] = v
00516
00517 getattr(self.figure, "set_%s"%what)(*args, **newargs)
00518 self.show(hardrefresh=False)
00519
00520
00521 def set_limits(self, xlim=None, ylim=None):
00522 """
00523 Set x-, and y-limits for each subplot.
00524
00525 xlim = [xmin, xmax] as in axes.set_xlim().
00526 ylim = [ymin, ymax] as in axes.set_ylim().
00527 """
00528 for s in self.subplots:
00529 self.axes = s['axes']
00530 self.lines = s['lines']
00531 oldxlim = list(self.axes.get_xlim())
00532 oldylim = list(self.axes.get_ylim())
00533 if xlim is not None:
00534 for i in range(len(xlim)):
00535 if xlim[i] is not None:
00536 oldxlim[i] = xlim[i]
00537 if ylim is not None:
00538 for i in range(len(ylim)):
00539 if ylim[i] is not None:
00540 oldylim[i] = ylim[i]
00541 self.axes.set_xlim(oldxlim)
00542 self.axes.set_ylim(oldylim)
00543 return
00544
00545
00546 def set_line(self, number=None, **kwargs):
00547 """
00548 Set attributes for the specified line, or else the next line(s)
00549 to be plotted.
00550
00551 number is the 0-relative number of a line that has already been
00552 plotted. If no such line exists, attributes are recorded and used
00553 for the next line(s) to be plotted.
00554
00555 Keyword arguments specify Line2D attributes, e.g. color='r'. Do
00556
00557 import matplotlib
00558 help(matplotlib.lines)
00559
00560 The set_* methods of class Line2D define the attribute names and
00561 values. For non-US usage, 'colour' is recognized as synonymous with
00562 'color'.
00563
00564 Set the value to None to delete an attribute.
00565
00566 Colour translation is done as described in the doctext for palette().
00567 """
00568
00569 redraw = False
00570 for k, v in kwargs.iteritems():
00571 k = k.lower()
00572 if k == 'colour': k = 'color'
00573
00574 if 0 <= number < len(self.lines):
00575 if self.lines[number] is not None:
00576 for line in self.lines[number]:
00577 getattr(line, "set_%s"%k)(v)
00578 redraw = True
00579 else:
00580 if v is None:
00581 del self.attributes[k]
00582 else:
00583 self.attributes[k] = v
00584
00585 if redraw: self.show(hardrefresh=False)
00586
00587
00588 #def set_panels(self, rows=1, cols=0, n=-1, nplots=-1, ganged=True):
00589 def set_panels(self, rows=1, cols=0, n=-1, nplots=-1, margin=None,ganged=True):
00590 """
00591 Set the panel layout.
00592
00593 rows and cols, if cols != 0, specify the number of rows and columns in
00594 a regular layout. (Indexing of these panels in matplotlib is row-
00595 major, i.e. column varies fastest.)
00596
00597 cols == 0 is interpreted as a retangular layout that accomodates
00598 'rows' panels, e.g. rows == 6, cols == 0 is equivalent to
00599 rows == 2, cols == 3.
00600
00601 0 <= n < rows*cols is interpreted as the 0-relative panel number in
00602 the configuration specified by rows and cols to be added to the
00603 current figure as its next 0-relative panel number (i). This allows
00604 non-regular panel layouts to be constructed via multiple calls. Any
00605 other value of n clears the plot and produces a rectangular array of
00606 empty panels. The number of these may be limited by nplots.
00607 """
00608 if n < 0 and len(self.subplots):
00609 self.figure.clear()
00610 self.set_title()
00611
00612 if margin:
00613 lef, bot, rig, top, wsp, hsp = margin
00614 self.figure.subplots_adjust(
00615 left=lef,bottom=bot,right=rig,top=top,wspace=wsp,hspace=hsp)
00616 del lef,bot,rig,top,wsp,hsp
00617
00618 if rows < 1: rows = 1
00619
00620 if cols <= 0:
00621 i = int(sqrt(rows))
00622 if i*i < rows: i += 1
00623 cols = i
00624
00625 if i*(i-1) >= rows: i -= 1
00626 rows = i
00627
00628 if 0 <= n < rows*cols:
00629 i = len(self.subplots)
00630
00631 self.subplots.append({})
00632
00633 self.subplots[i]['axes'] = self.figure.add_subplot(rows,
00634 cols, n+1)
00635 self.subplots[i]['lines'] = []
00636
00637 if i == 0: self.subplot(0)
00638
00639 self.rows = 0
00640 self.cols = 0
00641
00642 else:
00643 self.subplots = []
00644
00645 if nplots < 1 or rows*cols < nplots:
00646 nplots = rows*cols
00647 if ganged:
00648 hsp,wsp = None,None
00649 if rows > 1: hsp = 0.0001
00650 if cols > 1: wsp = 0.0001
00651 self.figure.subplots_adjust(wspace=wsp,hspace=hsp)
00652 for i in range(nplots):
00653 self.subplots.append({})
00654 self.subplots[i]['lines'] = []
00655 if not ganged:
00656 self.subplots[i]['axes'] = self.figure.add_subplot(rows,
00657 cols, i+1)
00658 if asaprcParams['plotter.axesformatting'] != 'mpl':
00659 self.subplots[i]['axes'].xaxis.set_major_formatter(OldScalarFormatter())
00660 else:
00661 if i == 0:
00662 self.subplots[i]['axes'] = self.figure.add_subplot(rows,
00663 cols, i+1)
00664 if asaprcParams['plotter.axesformatting'] != 'mpl':
00665
00666 self.subplots[i]['axes'].xaxis.set_major_formatter(OldScalarFormatter())
00667 else:
00668 self.subplots[i]['axes'] = self.figure.add_subplot(rows,
00669 cols, i+1,
00670 sharex=self.subplots[0]['axes'],
00671 sharey=self.subplots[0]['axes'])
00672
00673 # Suppress tick labelling for interior subplots.
00674 if i <= (rows-1)*cols - 1:
00675 if i+cols < nplots:
00676 # Suppress x-labels for frames width
00677 # adjacent frames
00678 for tick in self.subplots[i]['axes'].xaxis.majorTicks:
00679 tick.label1On = False
00680 #self.subplots[i]['axes'].xaxis.label.set_visible(False)
00681 if i%cols:
00682 # Suppress y-labels for frames not in the left column.
00683 for tick in self.subplots[i]['axes'].yaxis.majorTicks:
00684 tick.label1On = False
00685 #self.subplots[i]['axes'].yaxis.label.set_visible(False)
00686 # disable the first tick of [1:ncol-1] of the last row
00687 #if i+1 < nplots:
00688 # self.subplots[i]['axes'].xaxis.majorTicks[0].label1On = False
00689 # set axes label state for interior subplots.
00690 if i%cols:
00691 self.subplots[i]['axes'].yaxis.label.set_visible(False)
00692 if (i <= (rows-1)*cols - 1) and (i+cols < nplots):
00693 self.subplots[i]['axes'].xaxis.label.set_visible(False)
00694 self.rows = rows
00695 self.cols = cols
00696 self.subplot(0)
00697 del rows,cols,n,nplots,margin,ganged,i
00698
00699
00700 def tidy(self):
00701 # this needs to be exceuted after the first "refresh"
00702 nplots = len(self.subplots)
00703 if nplots == 1: return
00704 for i in xrange(nplots):
00705 ax = self.subplots[i]['axes']
00706 if i%self.cols:
00707 ax.xaxis.majorTicks[0].label1On = False
00708 else:
00709 if i != 0:
00710 ax.yaxis.majorTicks[-1].label1On = False
00711 ## set axes label state for interior subplots.
00712 #innerax=False
00713 #if i%self.cols:
00714 # ax.yaxis.label.set_visible(innerax)
00715 #if (i <= (self.rows-1)*self.cols - 1) and (i+self.cols < nplots):
00716 # ax.xaxis.label.set_visible(innerax)
00717
00718
00719 def set_title(self, title=None):
00720 """
00721 Set the title of the plot window. Use the previous title if title is
00722 omitted.
00723 """
00724 if title is not None:
00725 self.title = title
00726
00727 self.figure.text(0.5, 0.95, self.title, horizontalalignment='center')
00728
00729
00730 def show(self, hardrefresh=True):
00731 """
00732 Show graphics dependent on the current buffering state.
00733 """
00734 if not hardrefresh: return
00735 if not self.buffering:
00736 if self.loc is not None:
00737 for sp in self.subplots:
00738 lines = []
00739 labels = []
00740 i = 0
00741 for line in sp['lines']:
00742 i += 1
00743 if line is not None:
00744 lines.append(line[0])
00745 lbl = line[0].get_label()
00746 if lbl == '':
00747 lbl = str(i)
00748 labels.append(lbl)
00749
00750 if len(lines):
00751 fp = FP(size=rcParams['legend.fontsize'])
00752 #fsz = fp.get_size_in_points() - len(lines)
00753 fsz = fp.get_size_in_points() - max(len(lines),self.cols)
00754 #fp.set_size(max(fsz,6))
00755 fp.set_size(max(fsz,8))
00756 sp['axes'].legend(tuple(lines), tuple(labels),
00757 self.loc, prop=fp)
00758 #else:
00759 # sp['axes'].legend((' '))
00760
00761 from matplotlib.artist import setp
00762 fpx = FP(size=rcParams['xtick.labelsize'])
00763 xts = fpx.get_size_in_points()- (self.cols)/2
00764 fpy = FP(size=rcParams['ytick.labelsize'])
00765 yts = fpy.get_size_in_points() - (self.rows)/2
00766 fpa = FP(size=rcParams['axes.labelsize'])
00767 fpat = FP(size=rcParams['axes.titlesize'])
00768 axsize = fpa.get_size_in_points()
00769 tsize = fpat.get_size_in_points()-(self.cols)/2
00770 for sp in self.subplots:
00771 ax = sp['axes']
00772 ax.title.set_size(tsize)
00773 setp(ax.get_xticklabels(), fontsize=xts)
00774 setp(ax.get_yticklabels(), fontsize=yts)
00775 off = 0
00776 if self.cols > 1: off = self.cols
00777 ax.xaxis.label.set_size(axsize-off)
00778 off = 0
00779 if self.rows > 1: off = self.rows
00780 ax.yaxis.label.set_size(axsize-off)
00781
00782 def subplot(self, i=None, inc=None):
00783 """
00784 Set the subplot to the 0-relative panel number as defined by one or
00785 more invokations of set_panels().
00786 """
00787 l = len(self.subplots)
00788 if l:
00789 if i is not None:
00790 self.i = i
00791
00792 if inc is not None:
00793 self.i += inc
00794
00795 self.i %= l
00796 self.axes = self.subplots[self.i]['axes']
00797 self.lines = self.subplots[self.i]['lines']
00798
00799 def text(self, *args, **kwargs):
00800 """
00801 Add text to the figure.
00802 """
00803 self.figure.text(*args, **kwargs)
00804 self.show()
00805
00806 def vline_with_label(self, x, y, label,
00807 location='bottom', rotate=0.0, **kwargs):
00808 """
00809 Plot a vertical line with label.
00810 It takes "world" values fo x and y.
00811 """
00812 ax = self.axes
00813 # need this to suppress autoscaling during this function
00814 self.axes.set_autoscale_on(False)
00815 ymin = 0.0
00816 ymax = 1.0
00817 valign = 'center'
00818 if location.lower() == 'top':
00819 y = max(0.0, y)
00820 elif location.lower() == 'bottom':
00821 y = min(0.0, y)
00822 lbloffset = 0.06
00823 # a rough estimate for the bb of the text
00824 if rotate > 0.0: lbloffset = 0.03*len(label)
00825 peakoffset = 0.01
00826 xy = None
00827 xy0 = None
00828 # matplotlib api change 0.98 is using transform now
00829 if hasattr(ax.transData, "inverse_xy_tup"):
00830 # get relative coords
00831 xy0 = ax.transData.xy_tup((x,y))
00832 xy = ax.transAxes.inverse_xy_tup(xy0)
00833 else:
00834 xy0 = ax.transData.transform((x,y))
00835 # get relative coords
00836 xy = ax.transAxes.inverted().transform(xy0)
00837 if location.lower() == 'top':
00838 ymax = 1.0-lbloffset
00839 ymin = xy[1]+peakoffset
00840 valign = 'bottom'
00841 ylbl = ymax+0.01
00842 elif location.lower() == 'bottom':
00843 ymin = lbloffset
00844 ymax = xy[1]-peakoffset
00845 valign = 'top'
00846 ylbl = ymin-0.01
00847 trans = blended_transform_factory(ax.transData, ax.transAxes)
00848 l = ax.axvline(x, ymin, ymax, color='black', **kwargs)
00849 t = ax.text(x, ylbl ,label, verticalalignment=valign,
00850 horizontalalignment='center',
00851 rotation=rotate,transform = trans)
00852 self.axes.set_autoscale_on(True)
00853
00854 def _alive(self):
00855 # Return True if the GUI alives.
00856 if (not self.is_dead) and \
00857 self.figmgr and hasattr(self.figmgr, "num"):
00858 figid = self.figmgr.num
00859 # Make sure figid=0 is what asapplotter expects.
00860 # It might be already destroied/overridden by matplotlib
00861 # commands or other methods using asaplot.
00862 return _pylab_helpers.Gcf.has_fignum(figid) and \
00863 (self.figmgr == _pylab_helpers.Gcf.get_fig_manager(figid))
00864 return False