source: trunk/python/asapplotter.py @ 1824

Last change on this file since 1824 was 1824, checked in by Malte Marquarding, 14 years ago

Refactoring of init.py. Moved functionality into separate modules. Some minor fixes to make unit test work under 'standard asap'.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 52.5 KB
Line 
1from asap.parameters import rcParams
2from asap.selector import selector
3from asap.scantable import scantable
4from asap.logging import asaplog, print_log, print_log_dec
5import matplotlib.axes
6from matplotlib.font_manager import FontProperties
7from matplotlib.text import Text
8
9import re
10
11class asapplotter:
12    """
13    The ASAP plotter.
14    By default the plotter is set up to plot polarisations
15    'colour stacked' and scantables across panels.
16    Note:
17        Currenly it only plots 'spectra' not Tsys or
18        other variables.
19    """
20    def __init__(self, visible=None , **kwargs):
21        self._visible = rcParams['plotter.gui']
22        if visible is not None:
23            self._visible = visible
24        self._plotter = self._newplotter(**kwargs)
25        # additional tool bar
26        self._plotter.figmgr.casabar=self._newcasabar()
27
28        self._panelling = None
29        self._stacking = None
30        self.set_panelling()
31        self.set_stacking()
32        self._rows = None
33        self._cols = None
34        self._autoplot = False
35        self._minmaxx = None
36        self._minmaxy = None
37        self._datamask = None
38        self._data = None
39        self._lmap = None
40        self._title = None
41        self._ordinate = None
42        self._abcissa = None
43        self._abcunit = None
44        self._usermask = []
45        self._maskselection = None
46        self._selection = selector()
47        self._hist = rcParams['plotter.histogram']
48        self._fp = FontProperties()
49        self._panellayout = self.set_panellayout(refresh=False)
50
51    def _translate(self, instr):
52        keys = "s b i p t".split()
53        if isinstance(instr, str):
54            for key in keys:
55                if instr.lower().startswith(key):
56                    return key
57        return None
58
59    def _newplotter(self, **kwargs):
60        backend=matplotlib.get_backend()
61        if not self._visible:
62            from asap.asaplot import asaplot
63        elif backend == 'TkAgg':
64            from asap.asaplotgui import asaplotgui as asaplot
65        elif backend == 'Qt4Agg':
66            from asap.asaplotgui_qt4 import asaplotgui as asaplot
67        elif backend == 'GTkAgg':
68            from asap.asaplotgui_gtk import asaplotgui as asaplot
69        else:
70            from asap.asaplot import asaplot
71        return asaplot(**kwargs)
72
73    def _newcasabar(self):
74        backend=matplotlib.get_backend()
75        if self._visible and backend == "TkAgg":
76            from asap.casatoolbar import CustomToolbarTkAgg
77            return CustomToolbarTkAgg(self)
78        else: return None
79
80    @print_log_dec
81    def plot(self, scan=None):
82        """
83        Plot a scantable.
84        Parameters:
85            scan:   a scantable
86        Note:
87            If a scantable was specified in a previous call
88            to plot, no argument has to be given to 'replot'
89            NO checking is done that the abcissas of the scantable
90            are consistent e.g. all 'channel' or all 'velocity' etc.
91        """
92        if self._plotter.is_dead:
93            if hasattr(self._plotter.figmgr,'casabar'):
94                del self._plotter.figmgr.casabar
95            self._plotter = self._newplotter()
96            self._plotter.figmgr.casabar=self._newcasabar()
97        self._plotter.hold()
98        self._plotter.clear()
99        if not self._data and not scan:
100            msg = "Input is not a scantable"
101            if rcParams['verbose']:
102                #print msg
103                asaplog.push( msg )
104                print_log( 'ERROR' )
105                return
106            raise TypeError(msg)
107        if scan: self.set_data(scan,refresh=False)
108        self._plot(self._data)
109        if self._minmaxy is not None:
110            self._plotter.set_limits(ylim=self._minmaxy)
111        if self._plotter.figmgr.casabar: self._plotter.figmgr.casabar.enable_button()
112        self._plotter.release()
113        self._plotter.tidy()
114        self._plotter.show(hardrefresh=False)
115        print_log()
116        return
117
118    def gca(self):
119        return self._plotter.figure.gca()
120
121    def refresh(self):
122        """Do a soft refresh"""
123        self._plotter.figure.show()
124
125    def create_mask(self, nwin=1, panel=0, color=None):
126        """
127        Interactively define a mask.It retruns a mask that is equivalent to
128        the one created manually with scantable.create_mask.
129        Parameters:
130            nwin:       The number of mask windows to create interactively
131                        default is 1.
132            panel:      Which panel to use for mask selection. This is useful
133                        if different IFs are spread over panels (default 0)
134        """
135        if self._data is None:
136            return []
137        outmask = []
138        self._plotter.subplot(panel)
139        xmin, xmax = self._plotter.axes.get_xlim()
140        marg = 0.05*(xmax-xmin)
141        self._plotter.axes.set_xlim(xmin-marg, xmax+marg)
142        self.refresh()
143
144        def cleanup(lines=False, texts=False, refresh=False):
145            if lines:
146                del self._plotter.axes.lines[-1]
147            if texts:
148                del self._plotter.axes.texts[-1]
149            if refresh:
150                self.refresh()
151
152        for w in xrange(nwin):
153            wpos = []
154            self.text(0.05,1.0, "Add start boundary",
155                      coords="relative", fontsize=10)
156            point = self._plotter.get_point()
157            cleanup(texts=True)
158            if point is None:
159                continue
160            wpos.append(point[0])
161            self.axvline(wpos[0], color=color)
162            self.text(0.05,1.0, "Add end boundary", coords="relative", fontsize=10)
163            point = self._plotter.get_point()
164            cleanup(texts=True, lines=True)
165            if point is None:
166                self.refresh()
167                continue
168            wpos.append(point[0])
169            self.axvspan(wpos[0], wpos[1], alpha=0.1,
170                         edgecolor=color, facecolor=color)
171            ymin, ymax = self._plotter.axes.get_ylim()
172            outmask.append(wpos)
173
174        self._plotter.axes.set_xlim(xmin, xmax)
175        self.refresh()
176        if len(outmask) > 0:
177            return self._data.create_mask(*outmask)
178        return []
179
180    # forwards to matplotlib axes
181    def text(self, *args, **kwargs):
182        if kwargs.has_key("interactive"):
183            if kwargs.pop("interactive"):
184                pos = self._plotter.get_point()
185                args = tuple(pos)+args
186        self._axes_callback("text", *args, **kwargs)
187
188    text.__doc__ = matplotlib.axes.Axes.text.__doc__
189
190    def arrow(self, *args, **kwargs):
191        if kwargs.has_key("interactive"):
192            if kwargs.pop("interactive"):
193                pos = self._plotter.get_region()
194                dpos = (pos[0][0], pos[0][1],
195                        pos[1][0]-pos[0][0],
196                        pos[1][1] - pos[0][1])
197                args = dpos + args
198        self._axes_callback("arrow", *args, **kwargs)
199
200    arrow.__doc__ = matplotlib.axes.Axes.arrow.__doc__
201
202    def annotate(self, text, xy=None, xytext=None, **kwargs):
203        if kwargs.has_key("interactive"):
204            if kwargs.pop("interactive"):
205                xy = self._plotter.get_point()
206                xytext = self._plotter.get_point()
207        if not kwargs.has_key("arrowprops"):
208            kwargs["arrowprops"] = dict(arrowstyle="->")
209        self._axes_callback("annotate", text, xy, xytext, **kwargs)
210
211    annotate.__doc__ = matplotlib.axes.Axes.annotate.__doc__
212
213    def axvline(self, *args, **kwargs):
214        if kwargs.has_key("interactive"):
215            if kwargs.pop("interactive"):
216                pos = self._plotter.get_point()
217                args = (pos[0],)+args
218        self._axes_callback("axvline", *args, **kwargs)
219
220    axvline.__doc__ = matplotlib.axes.Axes.axvline.__doc__
221
222    def axhline(self, *args, **kwargs):
223        if kwargs.has_key("interactive"):
224            if kwargs.pop("interactive"):
225                pos = self._plotter.get_point()
226                args = (pos[1],)+args
227        self._axes_callback("axhline", *args, **kwargs)
228
229    axhline.__doc__ = matplotlib.axes.Axes.axhline.__doc__
230
231    def axvspan(self, *args, **kwargs):
232        if kwargs.has_key("interactive"):
233            if kwargs.pop("interactive"):
234                pos = self._plotter.get_region()
235                dpos = (pos[0][0], pos[1][0])
236                args = dpos + args
237        self._axes_callback("axvspan", *args, **kwargs)
238        # hack to preventy mpl from redrawing the patch
239        # it seem to convert the patch into lines on every draw.
240        # This doesn't happen in a test script???
241        #del self._plotter.axes.patches[-1]
242
243    axvspan.__doc__ = matplotlib.axes.Axes.axvspan.__doc__
244
245    def axhspan(self, *args, **kwargs):
246        if kwargs.has_key("interactive"):
247            if kwargs.pop("interactive"):
248                pos = self._plotter.get_region()
249                dpos = (pos[0][1], pos[1][1])
250                args = dpos + args
251        self._axes_callback("axhspan", *args, **kwargs)
252        # hack to preventy mpl from redrawing the patch
253        # it seem to convert the patch into lines on every draw.
254        # This doesn't happen in a test script???
255        #del self._plotter.axes.patches[-1]
256
257    axhspan.__doc__ = matplotlib.axes.Axes.axhspan.__doc__
258
259    def _axes_callback(self, axesfunc, *args, **kwargs):
260        panel = 0
261        if kwargs.has_key("panel"):
262            panel = kwargs.pop("panel")
263        coords = None
264        if kwargs.has_key("coords"):
265            coords = kwargs.pop("coords")
266            if coords.lower() == 'world':
267                kwargs["transform"] = self._plotter.axes.transData
268            elif coords.lower() == 'relative':
269                kwargs["transform"] = self._plotter.axes.transAxes
270        self._plotter.subplot(panel)
271        self._plotter.axes.set_autoscale_on(False)
272        getattr(self._plotter.axes, axesfunc)(*args, **kwargs)
273        self._plotter.show(False)
274        self._plotter.axes.set_autoscale_on(True)
275    # end matplotlib.axes fowarding functions
276
277    def set_data(self, scan, refresh=True):
278        """
279        Set a scantable to plot.
280        Parameters:
281            scan:      a scantable
282            refresh:   True (default) or False. If True, the plot is
283                       replotted based on the new parameter setting(s).
284                       Otherwise,the parameter(s) are set without replotting.
285        Note:
286           The user specified masks and data selections will be reset
287           if a new scantable is set. This method should be called before
288           setting data selections (set_selection) and/or masks (set_mask).
289        """
290        from asap import scantable
291        if isinstance(scan, scantable):
292            if self._data is not None:
293                if scan != self._data:
294                    self._data = scan
295                    # reset
296                    self._reset()
297                    msg = "A new scantable is set to the plotter. The masks and data selections are reset."
298                    asaplog.push( msg )
299                    print_log( 'INFO' )
300            else:
301                self._data = scan
302                self._reset()
303        else:
304            msg = "Input is not a scantable"
305            if rcParams['verbose']:
306                #print msg
307                asaplog.push( msg )
308                print_log( 'ERROR' )
309                return
310            raise TypeError(msg)
311
312        # ranges become invalid when unit changes
313        if self._abcunit and self._abcunit != self._data.get_unit():
314            self._minmaxx = None
315            self._minmaxy = None
316            self._abcunit = self._data.get_unit()
317            self._datamask = None
318        if refresh: self.plot()
319
320
321    def set_mode(self, stacking=None, panelling=None, refresh=True):
322        """
323        Set the plots look and feel, i.e. what you want to see on the plot.
324        Parameters:
325            stacking:     tell the plotter which variable to plot
326                          as line colour overlays (default 'pol')
327            panelling:    tell the plotter which variable to plot
328                          across multiple panels (default 'scan'
329            refresh:      True (default) or False. If True, the plot is
330                          replotted based on the new parameter setting(s).
331                          Otherwise,the parameter(s) are set without replotting.
332        Note:
333            Valid modes are:
334                 'beam' 'Beam' 'b':     Beams
335                 'if' 'IF' 'i':         IFs
336                 'pol' 'Pol' 'p':       Polarisations
337                 'scan' 'Scan' 's':     Scans
338                 'time' 'Time' 't':     Times
339        """
340        msg = "Invalid mode"
341        if not self.set_panelling(panelling) or \
342               not self.set_stacking(stacking):
343            if rcParams['verbose']:
344                #print msg
345                asaplog.push( msg )
346                print_log( 'ERROR' )
347                return
348            else:
349                raise TypeError(msg)
350        if refresh and self._data: self.plot(self._data)
351        return
352
353    def set_panelling(self, what=None):
354        mode = what
355        if mode is None:
356             mode = rcParams['plotter.panelling']
357        md = self._translate(mode)
358        if md:
359            self._panelling = md
360            self._title = None
361            return True
362        return False
363
364    def set_layout(self,rows=None,cols=None,refresh=True):
365        """
366        Set the multi-panel layout, i.e. how many rows and columns plots
367        are visible.
368        Parameters:
369             rows:   The number of rows of plots
370             cols:   The number of columns of plots
371             refresh:  True (default) or False. If True, the plot is
372                       replotted based on the new parameter setting(s).
373                       Otherwise,the parameter(s) are set without replotting.
374        Note:
375             If no argument is given, the potter reverts to its auto-plot
376             behaviour.
377        """
378        self._rows = rows
379        self._cols = cols
380        if refresh and self._data: self.plot(self._data)
381        return
382
383    def set_stacking(self, what=None):
384        mode = what
385        if mode is None:
386             mode = rcParams['plotter.stacking']
387        md = self._translate(mode)
388        if md:
389            self._stacking = md
390            self._lmap = None
391            return True
392        return False
393
394    def set_range(self,xstart=None,xend=None,ystart=None,yend=None,refresh=True):
395        """
396        Set the range of interest on the abcissa of the plot
397        Parameters:
398            [x,y]start,[x,y]end:  The start and end points of the 'zoom' window
399            refresh:  True (default) or False. If True, the plot is
400                      replotted based on the new parameter setting(s).
401                      Otherwise,the parameter(s) are set without replotting.
402        Note:
403            These become non-sensical when the unit changes.
404            use plotter.set_range() without parameters to reset
405
406        """
407        if xstart is None and xend is None:
408            self._minmaxx = None
409        else:
410            self._minmaxx = [xstart,xend]
411        if ystart is None and yend is None:
412            self._minmaxy = None
413        else:
414            self._minmaxy = [ystart,yend]
415        if refresh and self._data: self.plot(self._data)
416        return
417
418    def set_legend(self, mp=None, fontsize = None, mode = 0, refresh=True):
419        """
420        Specify a mapping for the legend instead of using the default
421        indices:
422        Parameters:
423            mp:        a list of 'strings'. This should have the same length
424                       as the number of elements on the legend and then maps
425                       to the indeces in order. It is possible to uses latex
426                       math expression. These have to be enclosed in r'',
427                       e.g. r'$x^{2}$'
428            fontsize:  The font size of the label (default None)
429            mode:      where to display the legend
430                       Any other value for loc else disables the legend:
431                        0: auto
432                        1: upper right
433                        2: upper left
434                        3: lower left
435                        4: lower right
436                        5: right
437                        6: center left
438                        7: center right
439                        8: lower center
440                        9: upper center
441                        10: center
442            refresh:    True (default) or False. If True, the plot is
443                        replotted based on the new parameter setting(s).
444                        Otherwise,the parameter(s) are set without replotting.
445
446        Example:
447             If the data has two IFs/rest frequencies with index 0 and 1
448             for CO and SiO:
449             plotter.set_stacking('i')
450             plotter.set_legend(['CO','SiO'])
451             plotter.plot()
452             plotter.set_legend([r'$^{12}CO$', r'SiO'])
453        """
454        self._lmap = mp
455        self._plotter.legend(mode)
456        if isinstance(fontsize, int):
457            from matplotlib import rc as rcp
458            rcp('legend', fontsize=fontsize)
459        if refresh and self._data: self.plot(self._data)
460        return
461
462    def set_title(self, title=None, fontsize=None, refresh=True):
463        """
464        Set the title of the plot. If multiple panels are plotted,
465        multiple titles have to be specified.
466        Parameters:
467            refresh:    True (default) or False. If True, the plot is
468                        replotted based on the new parameter setting(s).
469                        Otherwise,the parameter(s) are set without replotting.
470        Example:
471             # two panels are visible on the plotter
472             plotter.set_title(["First Panel","Second Panel"])
473        """
474        self._title = title
475        if isinstance(fontsize, int):
476            from matplotlib import rc as rcp
477            rcp('axes', titlesize=fontsize)
478        if refresh and self._data: self.plot(self._data)
479        return
480
481    def set_ordinate(self, ordinate=None, fontsize=None, refresh=True):
482        """
483        Set the y-axis label of the plot. If multiple panels are plotted,
484        multiple labels have to be specified.
485        Parameters:
486            ordinate:    a list of ordinate labels. None (default) let
487                         data determine the labels
488            refresh:     True (default) or False. If True, the plot is
489                         replotted based on the new parameter setting(s).
490                         Otherwise,the parameter(s) are set without replotting.
491        Example:
492             # two panels are visible on the plotter
493             plotter.set_ordinate(["First Y-Axis","Second Y-Axis"])
494        """
495        self._ordinate = ordinate
496        if isinstance(fontsize, int):
497            from matplotlib import rc as rcp
498            rcp('axes', labelsize=fontsize)
499            rcp('ytick', labelsize=fontsize)
500        if refresh and self._data: self.plot(self._data)
501        return
502
503    def set_abcissa(self, abcissa=None, fontsize=None, refresh=True):
504        """
505        Set the x-axis label of the plot. If multiple panels are plotted,
506        multiple labels have to be specified.
507        Parameters:
508            abcissa:     a list of abcissa labels. None (default) let
509                         data determine the labels
510            refresh:     True (default) or False. If True, the plot is
511                         replotted based on the new parameter setting(s).
512                         Otherwise,the parameter(s) are set without replotting.
513        Example:
514             # two panels are visible on the plotter
515             plotter.set_ordinate(["First X-Axis","Second X-Axis"])
516        """
517        self._abcissa = abcissa
518        if isinstance(fontsize, int):
519            from matplotlib import rc as rcp
520            rcp('axes', labelsize=fontsize)
521            rcp('xtick', labelsize=fontsize)
522        if refresh and self._data: self.plot(self._data)
523        return
524
525    def set_colors(self, colmap, refresh=True):
526        """
527        Set the colours to be used. The plotter will cycle through
528        these colours when lines are overlaid (stacking mode).
529        Parameters:
530            colmap:     a list of colour names
531            refresh:    True (default) or False. If True, the plot is
532                        replotted based on the new parameter setting(s).
533                        Otherwise,the parameter(s) are set without replotting.
534        Example:
535             plotter.set_colors("red green blue")
536             # If for example four lines are overlaid e.g I Q U V
537             # 'I' will be 'red', 'Q' will be 'green', U will be 'blue'
538             # and 'V' will be 'red' again.
539        """
540        if isinstance(colmap,str):
541            colmap = colmap.split()
542        self._plotter.palette(0, colormap=colmap)
543        if refresh and self._data: self.plot(self._data)
544
545    # alias for english speakers
546    set_colours = set_colors
547
548    def set_histogram(self, hist=True, linewidth=None, refresh=True):
549        """
550        Enable/Disable histogram-like plotting.
551        Parameters:
552            hist:        True (default) or False. The fisrt default
553                         is taken from the .asaprc setting
554                         plotter.histogram
555            refresh:     True (default) or False. If True, the plot is
556                         replotted based on the new parameter setting(s).
557                         Otherwise,the parameter(s) are set without replotting.
558        """
559        self._hist = hist
560        if isinstance(linewidth, float) or isinstance(linewidth, int):
561            from matplotlib import rc as rcp
562            rcp('lines', linewidth=linewidth)
563        if refresh and self._data: self.plot(self._data)
564
565    def set_linestyles(self, linestyles=None, linewidth=None, refresh=True):
566        """
567        Set the linestyles to be used. The plotter will cycle through
568        these linestyles when lines are overlaid (stacking mode) AND
569        only one color has been set.
570        Parameters:
571             linestyles:     a list of linestyles to use.
572                             'line', 'dashed', 'dotted', 'dashdot',
573                             'dashdotdot' and 'dashdashdot' are
574                             possible
575            refresh:         True (default) or False. If True, the plot is
576                             replotted based on the new parameter setting(s).
577                             Otherwise,the parameter(s) are set without replotting.
578        Example:
579             plotter.set_colors("black")
580             plotter.set_linestyles("line dashed dotted dashdot")
581             # If for example four lines are overlaid e.g I Q U V
582             # 'I' will be 'solid', 'Q' will be 'dashed',
583             # U will be 'dotted' and 'V' will be 'dashdot'.
584        """
585        if isinstance(linestyles,str):
586            linestyles = linestyles.split()
587        self._plotter.palette(color=0,linestyle=0,linestyles=linestyles)
588        if isinstance(linewidth, float) or isinstance(linewidth, int):
589            from matplotlib import rc as rcp
590            rcp('lines', linewidth=linewidth)
591        if refresh and self._data: self.plot(self._data)
592
593    def set_font(self, refresh=True,**kwargs):
594        """
595        Set font properties.
596        Parameters:
597            family:    one of 'sans-serif', 'serif', 'cursive', 'fantasy', 'monospace'
598            style:     one of 'normal' (or 'roman'), 'italic'  or 'oblique'
599            weight:    one of 'normal or 'bold'
600            size:      the 'general' font size, individual elements can be adjusted
601                       seperately
602            refresh:   True (default) or False. If True, the plot is
603                       replotted based on the new parameter setting(s).
604                       Otherwise,the parameter(s) are set without replotting.
605        """
606        from matplotlib import rc as rcp
607        fdict = {}
608        for k,v in kwargs.iteritems():
609            if v:
610                fdict[k] = v
611        self._fp = FontProperties(**fdict)
612        if refresh and self._data: self.plot(self._data)
613
614    def set_panellayout(self,layout=[],refresh=True):
615        """
616        Set the layout of subplots.
617        Parameters:
618            layout:   a list of subplots layout in figure coordinate (0-1),
619                      i.e., fraction of the figure width or height.
620                      The order of elements should be:
621                      [left, bottom, right, top, horizontal space btw panels,
622                      vertical space btw panels].
623            refresh:  True (default) or False. If True, the plot is
624                      replotted based on the new parameter setting(s).
625                      Otherwise,the parameter(s) are set without replotting.
626        Note
627        * When layout is not specified, the values are reset to the defaults
628          of matplotlib.
629        * If any element is set to be None, the current value is adopted.
630        """
631        if layout == []: self._panellayout=self._reset_panellayout()
632        else:
633            self._panellayout=[None]*6
634            self._panellayout[0:len(layout)]=layout
635        #print "panel layout set to ",self._panellayout
636        if refresh and self._data: self.plot(self._data)
637
638    def _reset_panellayout(self):
639        ks=map(lambda x: 'figure.subplot.'+x,
640               ['left','bottom','right','top','hspace','wspace'])
641        return map(matplotlib.rcParams.get,ks)
642
643    def plot_lines(self, linecat=None, doppler=0.0, deltachan=10, rotate=90.0,
644                   location=None):
645        """
646        Plot a line catalog.
647        Parameters:
648            linecat:      the linecatalog to plot
649            doppler:      the velocity shift to apply to the frequencies
650            deltachan:    the number of channels to include each side of the
651                          line to determine a local maximum/minimum
652            rotate:       the rotation (in degrees) )for the text label (default 90.0)
653            location:     the location of the line annotation from the 'top',
654                          'bottom' or alternate (None - the default)
655        Notes:
656        If the spectrum is flagged no line will be drawn in that location.
657        """
658        if not self._data:
659            raise RuntimeError("No scantable has been plotted yet.")
660        from asap._asap import linecatalog
661        if not isinstance(linecat, linecatalog):
662            raise ValueError("'linecat' isn't of type linecatalog.")
663        if not self._data.get_unit().endswith("Hz"):
664            raise RuntimeError("Can only overlay linecatalogs when data is in frequency.")
665        from numpy import ma
666        for j in range(len(self._plotter.subplots)):
667            self._plotter.subplot(j)
668            lims = self._plotter.axes.get_xlim()
669            for row in range(linecat.nrow()):
670                # get_frequency returns MHz
671                base = { "GHz": 1000.0, "MHz": 1.0, "Hz": 1.0e-6 }
672                restf = linecat.get_frequency(row)/base[self._data.get_unit()]
673                c = 299792.458
674                freq = restf*(1.0-doppler/c)
675                if lims[0] < freq < lims[1]:
676                    if location is None:
677                        loc = 'bottom'
678                        if row%2: loc='top'
679                    else: loc = location
680                    maxys = []
681                    for line in self._plotter.axes.lines:
682                        v = line._x
683                        asc = v[0] < v[-1]
684
685                        idx = None
686                        if not asc:
687                            if v[len(v)-1] <= freq <= v[0]:
688                                i = len(v)-1
689                                while i>=0 and v[i] < freq:
690                                    idx = i
691                                    i-=1
692                        else:
693                           if v[0] <= freq <= v[len(v)-1]:
694                                i = 0
695                                while  i<len(v) and v[i] < freq:
696                                    idx = i
697                                    i+=1
698                        if idx is not None:
699                            lower = idx - deltachan
700                            upper = idx + deltachan
701                            if lower < 0: lower = 0
702                            if upper > len(v): upper = len(v)
703                            s = slice(lower, upper)
704                            y = line._y[s]
705                            maxy = ma.maximum(y)
706                            if isinstance( maxy, float):
707                                maxys.append(maxy)
708                    if len(maxys):
709                        peak = max(maxys)
710                        if peak > self._plotter.axes.get_ylim()[1]:
711                            loc = 'bottom'
712                    else:
713                        continue
714                    self._plotter.vline_with_label(freq, peak,
715                                                   linecat.get_name(row),
716                                                   location=loc, rotate=rotate)
717        self._plotter.show(hardrefresh=False)
718
719
720    def save(self, filename=None, orientation=None, dpi=None):
721        """
722        Save the plot to a file. The know formats are 'png', 'ps', 'eps'.
723        Parameters:
724             filename:    The name of the output file. This is optional
725                          and autodetects the image format from the file
726                          suffix. If non filename is specified a file
727                          called 'yyyymmdd_hhmmss.png' is created in the
728                          current directory.
729             orientation: optional parameter for postscript only (not eps).
730                          'landscape', 'portrait' or None (default) are valid.
731                          If None is choosen for 'ps' output, the plot is
732                          automatically oriented to fill the page.
733             dpi:         The dpi of the output non-ps plot
734        """
735        self._plotter.save(filename,orientation,dpi)
736        return
737
738
739    def set_mask(self, mask=None, selection=None, refresh=True):
740        """
741        Set a plotting mask for a specific polarization.
742        This is useful for masking out "noise" Pangle outside a source.
743        Parameters:
744             mask:           a mask from scantable.create_mask
745             selection:      the spectra to apply the mask to.
746             refresh:        True (default) or False. If True, the plot is
747                             replotted based on the new parameter setting(s).
748                             Otherwise,the parameter(s) are set without replotting.
749        Example:
750             select = selector()
751             select.setpolstrings("Pangle")
752             plotter.set_mask(mymask, select)
753        """
754        if not self._data:
755            msg = "Can only set mask after a first call to plot()"
756            if rcParams['verbose']:
757                #print msg
758                asaplog.push( msg )
759                print_log( 'ERROR' )
760                return
761            else:
762                raise RuntimeError(msg)
763        if len(mask):
764            if isinstance(mask, list) or isinstance(mask, tuple):
765                self._usermask = array(mask)
766            else:
767                self._usermask = mask
768        if mask is None and selection is None:
769            self._usermask = []
770            self._maskselection = None
771        if isinstance(selection, selector):
772            self._maskselection = {'b': selection.get_beams(),
773                                   's': selection.get_scans(),
774                                   'i': selection.get_ifs(),
775                                   'p': selection.get_pols(),
776                                   't': [] }
777        else:
778            self._maskselection = None
779        if refresh: self.plot(self._data)
780
781    def _slice_indeces(self, data):
782        mn = self._minmaxx[0]
783        mx = self._minmaxx[1]
784        asc = data[0] < data[-1]
785        start=0
786        end = len(data)-1
787        inc = 1
788        if not asc:
789            start = len(data)-1
790            end = 0
791            inc = -1
792        # find min index
793        #while start > 0 and data[start] < mn:
794        #    start+= inc
795        minind=start
796        for ind in xrange(start,end+inc,inc):
797            if data[ind] > mn: break
798            minind=ind
799        # find max index
800        #while end > 0 and data[end] > mx:
801        #    end-=inc
802        #if end > 0: end +=1
803        maxind=end
804        for ind in xrange(end,start-inc,-inc):
805            if data[ind] < mx: break
806            maxind=ind
807        start=minind
808        end=maxind
809        if start > end:
810            return end,start+1
811        elif start < end:
812            return start,end+1
813        else:
814            return start,end
815
816    def _reset(self):
817        self._usermask = []
818        self._usermaskspectra = None
819        self.set_selection(None, False)
820
821    def _plot(self, scan):
822        savesel = scan.get_selection()
823        sel = savesel +  self._selection
824        d0 = {'s': 'SCANNO', 'b': 'BEAMNO', 'i':'IFNO',
825              'p': 'POLNO', 'c': 'CYCLENO', 't' : 'TIME' }
826        order = [d0[self._panelling],d0[self._stacking]]
827        sel.set_order(order)
828        scan.set_selection(sel)
829        d = {'b': scan.getbeam, 's': scan.getscan,
830             'i': scan.getif, 'p': scan.getpol, 't': scan._gettime }
831
832        polmodes = dict(zip(self._selection.get_pols(),
833                            self._selection.get_poltypes()))
834        # this returns either a tuple of numbers or a length  (ncycles)
835        # convert this into lengths
836        n0,nstack0 = self._get_selected_n(scan)
837        if isinstance(n0, int): n = n0
838        else: n = len(n0)
839        if isinstance(nstack0, int): nstack = nstack0
840        else: nstack = len(nstack0)
841        maxpanel, maxstack = 16,16
842        if n > maxpanel or nstack > maxstack:
843            maxn = 0
844            if nstack > maxstack: maxn = maxstack
845            if n > maxpanel: maxn = maxpanel
846            msg ="Scan to be plotted contains more than %d selections.\n" \
847                  "Selecting first %d selections..." % (maxn, maxn)
848            asaplog.push(msg)
849            print_log('WARN')
850            n = min(n,maxpanel)
851            nstack = min(nstack,maxstack)
852        if n > 1:
853            ganged = rcParams['plotter.ganged']
854            if self._panelling == 'i':
855                ganged = False
856            if self._rows and self._cols:
857                n = min(n,self._rows*self._cols)
858                self._plotter.set_panels(rows=self._rows,cols=self._cols,
859#                                         nplots=n,ganged=ganged)
860                                         nplots=n,layout=self._panellayout,ganged=ganged)
861            else:
862#                self._plotter.set_panels(rows=n,cols=0,nplots=n,ganged=ganged)
863                self._plotter.set_panels(rows=n,cols=0,nplots=n,layout=self._panellayout,ganged=ganged)
864        else:
865#            self._plotter.set_panels()
866            self._plotter.set_panels(layout=self._panellayout)
867        r=0
868        nr = scan.nrow()
869        a0,b0 = -1,-1
870        allxlim = []
871        allylim = []
872        newpanel=True
873        panelcount,stackcount = 0,0
874        while r < nr:
875            a = d[self._panelling](r)
876            b = d[self._stacking](r)
877            if a > a0 and panelcount < n:
878                if n > 1:
879                    self._plotter.subplot(panelcount)
880                self._plotter.palette(0)
881                #title
882                xlab = self._abcissa and self._abcissa[panelcount] \
883                       or scan._getabcissalabel()
884                ylab = self._ordinate and self._ordinate[panelcount] \
885                       or scan._get_ordinate_label()
886                self._plotter.set_axes('xlabel', xlab)
887                self._plotter.set_axes('ylabel', ylab)
888                lbl = self._get_label(scan, r, self._panelling, self._title)
889                if isinstance(lbl, list) or isinstance(lbl, tuple):
890                    if 0 <= panelcount < len(lbl):
891                        lbl = lbl[panelcount]
892                    else:
893                        # get default label
894                        lbl = self._get_label(scan, r, self._panelling, None)
895                self._plotter.set_axes('title',lbl)
896                newpanel = True
897                stackcount =0
898                panelcount += 1
899            if (b > b0 or newpanel) and stackcount < nstack:
900                y = []
901                if len(polmodes):
902                    y = scan._getspectrum(r, polmodes[scan.getpol(r)])
903                else:
904                    y = scan._getspectrum(r)
905                m = scan._getmask(r)
906                from numpy import logical_not, logical_and
907                if self._maskselection and len(self._usermask) == len(m):
908                    if d[self._stacking](r) in self._maskselection[self._stacking]:
909                        m = logical_and(m, self._usermask)
910                x = scan._getabcissa(r)
911                from numpy import ma, array
912                y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
913                if self._minmaxx is not None:
914                    s,e = self._slice_indeces(x)
915                    x = x[s:e]
916                    y = y[s:e]
917                if len(x) > 1024 and rcParams['plotter.decimate']:
918                    fac = len(x)/1024
919                    x = x[::fac]
920                    y = y[::fac]
921                llbl = self._get_label(scan, r, self._stacking, self._lmap)
922                if isinstance(llbl, list) or isinstance(llbl, tuple):
923                    if 0 <= stackcount < len(llbl):
924                        # use user label
925                        llbl = llbl[stackcount]
926                    else:
927                        # get default label
928                        llbl = self._get_label(scan, r, self._stacking, None)
929                self._plotter.set_line(label=llbl)
930                plotit = self._plotter.plot
931                if self._hist: plotit = self._plotter.hist
932                if len(x) > 0:
933                    plotit(x,y)
934                    xlim= self._minmaxx or [min(x),max(x)]
935                    allxlim += xlim
936                    ylim= self._minmaxy or [ma.minimum(y),ma.maximum(y)]
937                    allylim += ylim
938                else:
939                    xlim = self._minmaxx or []
940                    allxlim += xlim
941                    ylim= self._minmaxy or []
942                    allylim += ylim
943                stackcount += 1
944                # last in colour stack -> autoscale x
945                if stackcount == nstack and len(allxlim) > 0:
946                    allxlim.sort()
947                    self._plotter.subplots[panelcount-1]['axes'].set_xlim([allxlim[0],allxlim[-1]])
948                    # clear
949                    allxlim =[]
950
951            newpanel = False
952            a0=a
953            b0=b
954            # ignore following rows
955            if (panelcount == n) and (stackcount == nstack):
956                # last panel -> autoscale y if ganged
957                if rcParams['plotter.ganged'] and len(allylim) > 0:
958                    allylim.sort()
959                    self._plotter.set_limits(ylim=[allylim[0],allylim[-1]])
960                break
961            r+=1 # next row
962        #reset the selector to the scantable's original
963        scan.set_selection(savesel)
964
965        #temporary switch-off for older matplotlib
966        #if self._fp is not None:
967        if self._fp is not None and getattr(self._plotter.figure,'findobj',False):
968            for o in self._plotter.figure.findobj(Text):
969                o.set_fontproperties(self._fp)
970
971    def set_selection(self, selection=None, refresh=True, **kw):
972        """
973        Parameters:
974            selection:  a selector object (default unset the selection)
975            refresh:    True (default) or False. If True, the plot is
976                        replotted based on the new parameter setting(s).
977                        Otherwise,the parameter(s) are set without replotting.
978        """
979        if selection is None:
980            # reset
981            if len(kw) == 0:
982                self._selection = selector()
983            else:
984                # try keywords
985                for k in kw:
986                    if k not in selector.fields:
987                        raise KeyError("Invalid selection key '%s', valid keys are %s" % (k, selector.fields))
988                self._selection = selector(**kw)
989        elif isinstance(selection, selector):
990            self._selection = selection
991        else:
992            raise TypeError("'selection' is not of type selector")
993
994        d0 = {'s': 'SCANNO', 'b': 'BEAMNO', 'i':'IFNO',
995              'p': 'POLNO', 'c': 'CYCLENO', 't' : 'TIME' }
996        order = [d0[self._panelling],d0[self._stacking]]
997        self._selection.set_order(order)
998        if refresh and self._data: self.plot(self._data)
999
1000    def _get_selected_n(self, scan):
1001        d1 = {'b': scan.getbeamnos, 's': scan.getscannos,
1002             'i': scan.getifnos, 'p': scan.getpolnos, 't': scan.ncycle }
1003        d2 = { 'b': self._selection.get_beams(),
1004               's': self._selection.get_scans(),
1005               'i': self._selection.get_ifs(),
1006               'p': self._selection.get_pols(),
1007               't': self._selection.get_cycles() }
1008        n =  d2[self._panelling] or d1[self._panelling]()
1009        nstack = d2[self._stacking] or d1[self._stacking]()
1010        return n,nstack
1011
1012    def _get_label(self, scan, row, mode, userlabel=None):
1013        if isinstance(userlabel, list) and len(userlabel) == 0:
1014            userlabel = " "
1015        pms = dict(zip(self._selection.get_pols(),self._selection.get_poltypes()))
1016        if len(pms):
1017            poleval = scan._getpollabel(scan.getpol(row),pms[scan.getpol(row)])
1018        else:
1019            poleval = scan._getpollabel(scan.getpol(row),scan.poltype())
1020        d = {'b': "Beam "+str(scan.getbeam(row)),
1021             #'s': scan._getsourcename(row),
1022             's': "Scan "+str(scan.getscan(row))+\
1023                  " ("+str(scan._getsourcename(row))+")",
1024             'i': "IF"+str(scan.getif(row)),
1025             'p': poleval,
1026             't': str(scan.get_time(row)) }
1027        return userlabel or d[mode]
1028
1029    def plotazel(self, scan=None, outfile=None):
1030    #def plotazel(self):
1031        """
1032        plot azimuth and elevation versus time of a scantable
1033        """
1034        from matplotlib import pylab as PL
1035        from matplotlib.dates import DateFormatter, timezone
1036        from matplotlib.dates import HourLocator, MinuteLocator,SecondLocator, DayLocator
1037        from matplotlib.ticker import MultipleLocator
1038        from numpy import array, pi
1039        self._data = scan
1040        self._outfile = outfile
1041        dates = self._data.get_time(asdatetime=True)
1042        t = PL.date2num(dates)
1043        tz = timezone('UTC')
1044        PL.cla()
1045        PL.ioff()
1046        PL.clf()
1047        # Adjust subplot layouts
1048        if len(self._panellayout) !=6: self.set_panellayout(refresh=False)
1049        lef, bot, rig, top, wsp, hsp = self._panellayout
1050        PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
1051                                 wspace=wsp,hspace=hsp)
1052
1053        tdel = max(t) - min(t)
1054        ax = PL.subplot(2,1,1)
1055        el = array(self._data.get_elevation())*180./pi
1056        PL.ylabel('El [deg.]')
1057        dstr = dates[0].strftime('%Y/%m/%d')
1058        if tdel > 1.0:
1059            dstr2 = dates[len(dates)-1].strftime('%Y/%m/%d')
1060            dstr = dstr + " - " + dstr2
1061            majloc = DayLocator()
1062            minloc = HourLocator(range(0,23,12))
1063            timefmt = DateFormatter("%b%d")
1064        elif tdel > 24./60.:
1065            timefmt = DateFormatter('%H:%M')
1066            majloc = HourLocator()
1067            minloc = MinuteLocator(30)
1068        else:
1069            timefmt = DateFormatter('%H:%M')
1070            majloc = MinuteLocator(interval=5)
1071            minloc = SecondLocator(30)
1072
1073        PL.title(dstr)
1074        if tdel == 0.0:
1075            th = (t - PL.floor(t))*24.0
1076            PL.plot(th,el,'o',markersize=2, markerfacecolor='b', markeredgecolor='b')
1077        else:
1078            PL.plot_date(t,el,'o', markersize=2, markerfacecolor='b', markeredgecolor='b',tz=tz)
1079            #ax.grid(True)
1080            ax.xaxis.set_major_formatter(timefmt)
1081            ax.xaxis.set_major_locator(majloc)
1082            ax.xaxis.set_minor_locator(minloc)
1083        ax.yaxis.grid(True)
1084        yloc = MultipleLocator(30)
1085        ax.set_ylim(0,90)
1086        ax.yaxis.set_major_locator(yloc)
1087        if tdel > 1.0:
1088            labels = ax.get_xticklabels()
1089        #    PL.setp(labels, fontsize=10, rotation=45)
1090            PL.setp(labels, fontsize=10)
1091
1092        # Az plot
1093        az = array(self._data.get_azimuth())*180./pi
1094        if min(az) < 0:
1095            for irow in range(len(az)):
1096                if az[irow] < 0: az[irow] += 360.0
1097
1098        ax2 = PL.subplot(2,1,2)
1099        #PL.xlabel('Time (UT [hour])')
1100        PL.ylabel('Az [deg.]')
1101        if tdel == 0.0:
1102            PL.plot(th,az,'o',markersize=2, markeredgecolor='b',markerfacecolor='b')
1103        else:
1104            PL.plot_date(t,az,'o', markersize=2,markeredgecolor='b',markerfacecolor='b',tz=tz)
1105            ax2.xaxis.set_major_formatter(timefmt)
1106            ax2.xaxis.set_major_locator(majloc)
1107            ax2.xaxis.set_minor_locator(minloc)
1108        #ax2.grid(True)
1109        ax2.set_ylim(0,360)
1110        ax2.yaxis.grid(True)
1111        #hfmt = DateFormatter('%H')
1112        #hloc = HourLocator()
1113        yloc = MultipleLocator(60)
1114        ax2.yaxis.set_major_locator(yloc)
1115        if tdel > 1.0:
1116            labels = ax2.get_xticklabels()
1117            PL.setp(labels, fontsize=10)
1118            PL.xlabel('Time (UT [day])')
1119        else:
1120            PL.xlabel('Time (UT [hour])')
1121
1122        PL.ion()
1123        PL.draw()
1124        if (self._outfile is not None):
1125           PL.savefig(self._outfile)
1126
1127    def plotpointing(self, scan=None, outfile=None):
1128    #def plotpointing(self):
1129        """
1130        plot telescope pointings
1131        """
1132        from matplotlib import pylab as PL
1133        from numpy import array, pi
1134        self._data = scan
1135        self._outfile = outfile
1136        dir = array(self._data.get_directionval()).transpose()
1137        ra = dir[0]*180./pi
1138        dec = dir[1]*180./pi
1139        PL.cla()
1140        #PL.ioff()
1141        PL.clf()
1142        # Adjust subplot layouts
1143        if len(self._panellayout) !=6: self.set_panellayout(refresh=False)
1144        lef, bot, rig, top, wsp, hsp = self._panellayout
1145        PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
1146                                 wspace=wsp,hspace=hsp)
1147        ax = PL.gca()
1148        #ax = PL.axes([0.1,0.1,0.8,0.8])
1149        #ax = PL.axes([0.1,0.1,0.8,0.8])
1150        ax.set_aspect('equal')
1151        PL.plot(ra, dec, 'b,')
1152        PL.xlabel('RA [deg.]')
1153        PL.ylabel('Declination [deg.]')
1154        PL.title('Telescope pointings')
1155        [xmin,xmax,ymin,ymax] = PL.axis()
1156        PL.axis([xmax,xmin,ymin,ymax])
1157        #PL.ion()
1158        PL.draw()
1159        if (self._outfile is not None):
1160           PL.savefig(self._outfile)
1161
1162    # plot total power data
1163    # plotting in time is not yet implemented..
1164    def plottp(self, scan=None, outfile=None):
1165        if self._plotter.is_dead:
1166            if hasattr(self._plotter.figmgr,'casabar'):
1167                del self._plotter.figmgr.casabar
1168            self._plotter = self._newplotter()
1169            self._plotter.figmgr.casabar=self._newcasabar()
1170        self._plotter.hold()
1171        self._plotter.clear()
1172        from asap import scantable
1173        if not self._data and not scan:
1174            msg = "Input is not a scantable"
1175            if rcParams['verbose']:
1176                #print msg
1177                asaplog.push( msg )
1178                print_log( 'ERROR' )
1179                return
1180            raise TypeError(msg)
1181        if isinstance(scan, scantable):
1182            if self._data is not None:
1183                if scan != self._data:
1184                    self._data = scan
1185                    # reset
1186                    self._reset()
1187            else:
1188                self._data = scan
1189                self._reset()
1190        # ranges become invalid when abcissa changes?
1191        #if self._abcunit and self._abcunit != self._data.get_unit():
1192        #    self._minmaxx = None
1193        #    self._minmaxy = None
1194        #    self._abcunit = self._data.get_unit()
1195        #    self._datamask = None
1196
1197        # Adjust subplot layouts
1198        if len(self._panellayout) !=6: self.set_panellayout(refresh=False)
1199        lef, bot, rig, top, wsp, hsp = self._panellayout
1200        self._plotter.figure.subplots_adjust(
1201            left=lef,bottom=bot,right=rig,top=top,wspace=wsp,hspace=hsp)
1202        if self._plotter.figmgr.casabar: self._plotter.figmgr.casabar.disable_button()
1203        self._plottp(self._data)
1204        if self._minmaxy is not None:
1205            self._plotter.set_limits(ylim=self._minmaxy)
1206        self._plotter.release()
1207        self._plotter.tidy()
1208        self._plotter.show(hardrefresh=False)
1209        print_log()
1210        return
1211
1212    def _plottp(self,scan):
1213        """
1214        private method for plotting total power data
1215        """
1216        from numpy import ma, array, arange, logical_not
1217        r=0
1218        nr = scan.nrow()
1219        a0,b0 = -1,-1
1220        allxlim = []
1221        allylim = []
1222        y=[]
1223        self._plotter.set_panels()
1224        self._plotter.palette(0)
1225        #title
1226        #xlab = self._abcissa and self._abcissa[panelcount] \
1227        #       or scan._getabcissalabel()
1228        #ylab = self._ordinate and self._ordinate[panelcount] \
1229        #       or scan._get_ordinate_label()
1230        xlab = self._abcissa or 'row number' #or Time
1231        ylab = self._ordinate or scan._get_ordinate_label()
1232        self._plotter.set_axes('xlabel',xlab)
1233        self._plotter.set_axes('ylabel',ylab)
1234        lbl = self._get_label(scan, r, 's', self._title)
1235        if isinstance(lbl, list) or isinstance(lbl, tuple):
1236        #    if 0 <= panelcount < len(lbl):
1237        #        lbl = lbl[panelcount]
1238        #    else:
1239                # get default label
1240             lbl = self._get_label(scan, r, self._panelling, None)
1241        self._plotter.set_axes('title',lbl)
1242        y=array(scan._get_column(scan._getspectrum,-1))
1243        m = array(scan._get_column(scan._getmask,-1))
1244        y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
1245        x = arange(len(y))
1246        # try to handle spectral data somewhat...
1247        l,m = y.shape
1248        if m > 1:
1249            y=y.mean(axis=1)
1250        plotit = self._plotter.plot
1251        llbl = self._get_label(scan, r, self._stacking, None)
1252        self._plotter.set_line(label=llbl)
1253        if len(x) > 0:
1254            plotit(x,y)
1255
1256
1257    # forwards to matplotlib.Figure.text
1258    def figtext(self, *args, **kwargs):
1259        """
1260        Add text to figure at location x,y (relative 0-1 coords).
1261        This method forwards *args and **kwargs to a Matplotlib method,
1262        matplotlib.Figure.text.
1263        See the method help for detailed information.
1264        """
1265        self._plotter.text(*args, **kwargs)
1266    # end matplotlib.Figure.text forwarding function
1267
1268
1269    # printing header information
1270    def print_header(self, plot=True, fontsize=9, logger=False, selstr='', extrastr=''):
1271        """
1272        print data (scantable) header on the plot and/or logger.
1273        Parameters:
1274            plot:      whether or not print header info on the plot.
1275            fontsize:  header font size (valid only plot=True)
1276            autoscale: whether or not autoscale the plot (valid only plot=True)
1277            logger:    whether or not print header info on the logger.
1278            selstr:    additional selection string (not verified)
1279            extrastr:  additional string to print (not verified)
1280        """
1281        if not plot and not logger: return
1282        if not self._data: raise RuntimeError("No scantable has been set yet.")
1283        # Now header will be printed on plot and/or logger.
1284        # Get header information and format it.
1285        ssum=self._data.__str__()
1286        # Print Observation header to the upper-left corner of plot
1287        if plot:
1288            headstr=[ssum[ssum.find('Observer:'):ssum.find('Flux Unit:')]]
1289            headstr.append(ssum[ssum.find('Beams:'):ssum.find('Observer:')]
1290                         +ssum[ssum.find('Rest Freqs:'):ssum.find('Abcissa:')])
1291            if extrastr != '': headstr[0]=extrastr+'\n'+headstr[0]
1292            #headstr[1]='Data File:     '+(filestr or 'unknown')+'\n'+headstr[1]
1293            ssel='***Selections***\n'+(selstr+self._data.get_selection().__str__() or 'none')
1294            headstr.append(ssel)
1295            nstcol=len(headstr)
1296
1297            self._plotter.hold()
1298            for i in range(nstcol):
1299                self._plotter.figure.text(0.03+float(i)/nstcol,0.98,
1300                             headstr[i],
1301                             horizontalalignment='left',
1302                             verticalalignment='top',
1303                             fontsize=fontsize)
1304            import time
1305            self._plotter.figure.text(0.99,0.0,
1306                            time.strftime("%a %d %b %Y  %H:%M:%S %Z"),
1307                            horizontalalignment='right',
1308                            verticalalignment='bottom',fontsize=8)
1309            self._plotter.release()
1310            del headstr, ssel
1311        if logger:
1312            asaplog.push("----------------\n  Plot Summary\n----------------")
1313            asaplog.push(extrastr)
1314            asaplog.push(ssum[ssum.find('Beams:'):])
1315            print_log()
1316        del ssum
Note: See TracBrowser for help on using the repository browser.