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

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

New Development: No

JIRA Issue: No (bug fixes)

Ready for Test: Yes

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: Quit plotter with buttons and replot

Put in Release Notes: No

Module(s): sdplot

Description: fixed bugs for the plotter to work fine for replotting once after quitted


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