source: trunk/python/asapplotter.py @ 1910

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

New Development: Yes/No?

JIRA Issue: Yes (CAS-1822)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs:

Put in Release Notes: No

Module(s): ASAP plotter and sdplot

Description: enabled row panelling


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