source: trunk/python/asaplotbase.py @ 2037

Last change on this file since 2037 was 2037, checked in by Kana Sugimoto, 13 years ago

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed:

  • Renamed a method asapplotter.set_panellayout to asapplotter.set_margin.
  • Renamed a parameter layout to margin in asapplotter.set_margin and

asaplotbase.set_panels.

Test Programs: call asapplotter.set_margin(margin=[0.1,0.1])

Put in Release Notes: Yes

Module(s): asapplotter, asaplotbase, and sdplot

Description:

  • Renamed a method asapplotter.set_panellayout to asapplotter.set_margin.
  • Renamed a parameter layout to margin in asapplotter.set_margin and

asaplotbase.set_panels.

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