source: trunk/python/asaplotbase.py @ 2538

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

New Development: No

JIRA Issue: Yes (related to CAS-3749)

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed: added a new method, _alive(), in asaplotbase class

Test Programs: Interactive tests

Put in Release Notes: No

Module(s):

Description:

Added a new method, _alive(), in asaplotbase class. The method return True
if asaplot instance is alive. More complete check compared to 'is_dead' parameter.
asapplotter._assert_plotter method is simplified by calling this function.

Fixed misc bugs found in interactive tests.

  1. set back linewidth = 1 in plots invoked by modules, interactivemask, asapmath, and asapfitter.
  2. interactivemask module: plotter in properly quited at the end.
  3. interactivemask module: avoid error when user close interacive plot window before calling the finalization method, finish_selection().
  4. added definition of a dummy function, quit(), in asaplot class.


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