source: trunk/python/asapplotter.py @ 1904

Last change on this file since 1904 was 1897, checked in by Malte Marquarding, 14 years ago

Ticket #202: add offset keyword to asapplotter.set_range

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