source: trunk/python/asapplotter.py @ 1989

Last change on this file since 1989 was 1989, checked in by Kana Sugimoto, 13 years ago

New Development: Yes

JIRA Issue: Yes (CAS-1306 and ASAP-205)

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed: enabled stack='r' and panel='r' in sdplot as well as

stacking='r' and panelling='r' in asapplotter.set_mode.

Test Programs: run sdplot with either stack='r' or panel='r'.

Or, asapplotter.set_mode with either stacking='r' or panelling='r',
and then asapplotter.plot

Put in Release Notes: Yes

Module(s): sdplot and asapplotter

Description: enabled row based stacking and panelling in sdplot and asapplotter.


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