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

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

New Development: No

JIRA Issue: Yes (CAS2065)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs: run sdplot and make sure the additional tool bar appears and works.

Put in Release Notes: No

Module(s): sdplot and ASAP plotter running on TkAgg?

Description: A bit of refactoring (created a new method _newcasabar to load the additional tool bar)


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