source: branches/casa-prerelease/pre-asap/python/asaplotbase.py @ 2329

Last change on this file since 2329 was 2169, checked in by Malte Marquarding, 13 years ago

Fix version check fro matplotlib >=1

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