source: trunk/python/asapplotter.py @ 2147

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

New Development: No

JIRA Issue: No (a minor imporvement)

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed: added a method asapplotter.casabar_exist()

Test Programs:

Put in Release Notes: No

Module(s): asapplotter, sdplot

Description:

added a method asapplotter.casabar_exist() which tells whether or not casa toolbar exists.


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