source: branches/alma/python/asapplotter.py @ 1757

Last change on this file since 1757 was 1757, checked in by Kana Sugimoto, 14 years ago

New Development: Yes

JIRA Issue: Yes (CAS-2211)

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed: ASAP 3.0.0 interface changes

Test Programs:

Put in Release Notes: Yes

Module(s): all the CASA sd tools and tasks are affected.

Description: Merged ATNF-ASAP 3.0.0 developments to CASA (alma) branch.

Note you also need to update casa/code/atnf.


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