source: trunk/python/asaplotbase.py @ 2451

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

New Development: No

JIRA Issue: Yes (CAS-3749)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs: unit tests of sdplot

Put in Release Notes: No

Module(s): sdplot, sdfit, sdstat, sdflag, sdcal, sdreduce

Description:

Made asapplotter not to generate plotter window at start-up, but the window is
only generated at the first invokation of plotting operation.


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