source: trunk/python/asaplotbase.py @ 2699

Last change on this file since 2699 was 2699, checked in by Kana Sugimoto, 11 years ago

New Development: No

JIRA Issue: No (bug fixes)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs: unit tests of sdplot

Put in Release Notes: No

Module(s): asapplotter and sdplot

Description:

Fixed a bug which caused failure of plots by user defined linestyles.
Made sure data is plotted on mpl plotter (not on ASAP plotter) by
plotpointing and plotazel.


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