source: trunk/python/asapplotter.py @ 2693

Last change on this file since 2693 was 2693, checked in by Kana Sugimoto, 11 years ago

New Development: Yes

JIRA Issue: Yes (Trac-287)

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed: a new method, asapplotter.plotpointings2

Test Programs:

Put in Release Notes: No

Module(s): asapplotter, sdplot

Description:

a new method, asapplotter.plotpointings2, is created.
This method will be supposed to replace asapplotter.plotpointing
in near future if there's no issue found.
plotpointings2 plots pointing directions of a scantable.
It is possible to plot pointings of different source type, scanno,
ifno, polno, or beamno in different colors by setting the 'colorby'
paramter. When showline=True, the scan pattern is plotted in dotted
line.
This function alway plots pointings on ASAP plotter and works properly
with custom toolbar.


  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 78.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
8from matplotlib import _pylab_helpers
9
10import re
11
12def new_asaplot(visible=None,**kwargs):
13    """
14    Returns a new asaplot instance based on the backend settings.
15    """
16    if visible == None:
17        visible = rcParams['plotter.gui']
18
19    backend=matplotlib.get_backend()
20    if not visible:
21        from asap.asaplot import asaplot
22    elif backend == 'TkAgg':
23        from asap.asaplotgui import asaplotgui as asaplot
24    elif backend == 'Qt4Agg':
25        from asap.asaplotgui_qt4 import asaplotgui as asaplot
26    elif backend == 'GTkAgg':
27        from asap.asaplotgui_gtk import asaplotgui as asaplot
28    else:
29        from asap.asaplot import asaplot
30    return asaplot(**kwargs)
31
32class asapplotter:
33    """
34    The ASAP plotter.
35    By default the plotter is set up to plot polarisations
36    'colour stacked' and scantables across panels.
37
38    .. note::
39
40        Currenly it only plots 'spectra' not Tsys or
41        other variables.
42
43    """
44    def __init__(self, visible=None , **kwargs):
45        self._visible = rcParams['plotter.gui']
46        if visible is not None:
47            self._visible = visible
48        self._plotter = None
49        self._inikwg = kwargs
50
51        self._panelling = None
52        self._stacking = None
53        self.set_panelling()
54        self.set_stacking()
55        self._rows = None
56        self._cols = None
57        self._minmaxx = None
58        self._minmaxy = None
59        self._datamask = None
60        self._data = None
61        self._lmap = None
62        self._title = None
63        self._ordinate = None
64        self._abcissa = None
65        self._abcunit = None
66        self._usermask = []
67        self._maskselection = None
68        self._selection = selector()
69        self._hist = rcParams['plotter.histogram']
70        self._fp = FontProperties()
71        self._margins = self.set_margin(refresh=False)
72        self._offset = None
73        self._startrow = 0
74        self._ipanel = -1
75        self._panelrows = []
76        self._headtext={'string': None, 'textobj': None}
77        self._colormap = None
78        self._linestyles = None
79        self._legendloc = None
80
81    def _translate(self, instr):
82        keys = "s b i p t r".split()
83        if isinstance(instr, str):
84            for key in keys:
85                if instr.lower().startswith(key):
86                    return key
87        return None
88
89    @asaplog_post_dec
90    def _reload_plotter(self):
91        if self._plotter is not None:
92            #if not self._plotter.is_dead:
93            #    # clear lines and axes
94            #    try:
95            #        self._plotter.clear()
96            #    except: # Can't remove when already killed.
97            #        pass
98            if self.casabar_exists():
99                del self._plotter.figmgr.casabar
100            self._plotter.quit()
101            del self._plotter
102        asaplog.push('Loading new plotter')
103        self._plotter = new_asaplot(self._visible,**self._inikwg)
104        self._plotter.figmgr.casabar=self._new_custombar()
105        # just to make sure they're set
106        self._plotter.palette(color=0,colormap=self._colormap,
107                              linestyle=0,linestyles=self._linestyles)
108        self._plotter.legend(self._legendloc)
109
110    def _new_custombar(self):
111        backend=matplotlib.get_backend()
112        if not self._visible:
113            return None
114        elif backend == "TkAgg":
115            from asap.customgui_tkagg import CustomToolbarTkAgg
116            return CustomToolbarTkAgg(self)
117        elif backend == "Qt4Agg":
118            from asap.customgui_qt4agg import CustomToolbarQT4Agg
119            return CustomToolbarQT4Agg(self)
120        return None
121
122    def casabar_exists(self):
123        if not hasattr(self._plotter.figmgr,'casabar'):
124            return False
125        elif self._plotter.figmgr.casabar:
126            return True
127        return False
128
129    def _assert_plotter(self,action="status",errmsg=None):
130        """
131        Check plot window status. Returns True if plot window is alive.
132        Parameters
133            action:    An action to take if the plotter window is not alive.
134                       ['status'|'reload'|'halt']
135                       The action 'status' simply returns False if asaplot
136                       is not alive. When action='reload', plot window is
137                       reloaded and the method returns True. Finally, an
138                       error is raised when action='halt'.
139            errmsg:    An error (warning) message to send to the logger,
140                       when plot window is not alive.
141        """
142        isAlive = (self._plotter is not None) and self._plotter._alive()
143        # More tests
144        #if isAlive:
145        #    if self._plotter.figmgr:
146        #        figmgr = self._plotter.figmgr
147        #        figid = figmgr.num
148        #        # Make sure figid=0 is what asapplotter expects.
149        #        # It might be already destroied/overridden by matplotlib
150        #        # commands or other plotting methods using asaplot.
151        #        isAlive = _pylab_helpers.Gcf.has_fignum(figid) and \
152        #                  (figmgr == \
153        #                   _pylab_helpers.Gcf.get_fig_manager(figid))
154        #    else:
155        #        isAlive = False
156           
157        if isAlive:
158            return True
159        # Plotter is not alive.
160        haltmsg = "Plotter window has not yet been loaded or is closed."
161        if type(errmsg)==str and len(errmsg) > 0:
162            haltmsg = errmsg
163       
164        if action.upper().startswith("R"):
165            # reload plotter
166            self._reload_plotter()
167            return True
168        elif action.upper().startswith("H"):
169            # halt
170            asaplog.push(haltmsg)
171            asaplog.post("ERROR")
172            raise RuntimeError(haltmsg)
173        else:
174            if errmsg:
175                asaplog.push(errmsg)
176                asaplog.post("WARN")
177            return False
178
179
180    @asaplog_post_dec
181    def plot(self, scan=None):
182        """
183        Plot a scantable.
184        Parameters:
185            scan:   a scantable
186        Note:
187            If a scantable was specified in a previous call
188            to plot, no argument has to be given to 'replot'
189            NO checking is done that the abcissas of the scantable
190            are consistent e.g. all 'channel' or all 'velocity' etc.
191        """
192        if not self._data and not scan:
193            msg = "Input is not a scantable"
194            raise TypeError(msg)
195        self._startrow = 0
196        self._ipanel = -1
197        self._reset_header()
198        self._panelrows = []
199
200        self._assert_plotter(action="reload")
201        if self.casabar_exists():
202            self._plotter.figmgr.casabar.set_pagecounter(1)
203
204        self._plotter.hold()
205        #self._plotter.clear()
206        if scan:
207            self.set_data(scan, refresh=False)
208        self._plotter.palette(color=0,colormap=self._colormap,
209                              linestyle=0,linestyles=self._linestyles)
210        self._plotter.legend(self._legendloc)
211        self._plot(self._data)
212        if self._minmaxy is not None:
213            self._plotter.set_limits(ylim=self._minmaxy)
214        if self.casabar_exists(): self._plotter.figmgr.casabar.enable_button()
215        self._plotter.release()
216        self._plotter.tidy()
217        self._plotter.show(hardrefresh=False)
218        return
219
220    def gca(self):
221        errmsg = "No axis to retun. Need to plot first."
222        if not self._assert_plotter(action="status",errmsg=errmsg):
223            return None
224        return self._plotter.figure.gca()
225
226    def refresh(self):
227        """Do a soft refresh"""
228        errmsg = "No figure to re-plot. Need to plot first."
229        self._assert_plotter(action="halt",errmsg=errmsg)
230
231        self._plotter.figure.show()
232
233    def create_mask(self, nwin=1, panel=0, color=None):
234        """
235        Interactively define a mask. It retruns a mask that is equivalent to
236        the one created manually with scantable.create_mask.
237        Parameters:
238            nwin:       The number of mask windows to create interactively
239                        default is 1.
240            panel:      Which panel to use for mask selection. This is useful
241                        if different IFs are spread over panels (default 0)
242        """
243        ## this method relies on already plotted figure
244        if not self._assert_plotter(action="status") or (self._data is None):
245            msg = "Cannot create mask interactively on plot. Can only create mask after plotting."
246            asaplog.push( msg )
247            asaplog.post( "ERROR" )
248            return []
249        outmask = []
250        self._plotter.subplot(panel)
251        xmin, xmax = self._plotter.axes.get_xlim()
252        marg = 0.05*(xmax-xmin)
253        self._plotter.axes.set_xlim(xmin-marg, xmax+marg)
254        self.refresh()
255
256        def cleanup(lines=False, texts=False, refresh=False):
257            if lines:
258                del self._plotter.axes.lines[-1]
259            if texts:
260                del self._plotter.axes.texts[-1]
261            if refresh:
262                self.refresh()
263
264        for w in xrange(nwin):
265            wpos = []
266            self.text(0.05,1.0, "Add start boundary",
267                      coords="relative", fontsize=10)
268            point = self._plotter.get_point()
269            cleanup(texts=True)
270            if point is None:
271                continue
272            wpos.append(point[0])
273            self.axvline(wpos[0], color=color)
274            self.text(0.05,1.0, "Add end boundary", coords="relative", fontsize=10)
275            point = self._plotter.get_point()
276            cleanup(texts=True, lines=True)
277            if point is None:
278                self.refresh()
279                continue
280            wpos.append(point[0])
281            self.axvspan(wpos[0], wpos[1], alpha=0.1,
282                         edgecolor=color, facecolor=color)
283            ymin, ymax = self._plotter.axes.get_ylim()
284            outmask.append(wpos)
285
286        self._plotter.axes.set_xlim(xmin, xmax)
287        self.refresh()
288        if len(outmask) > 0:
289            return self._data.create_mask(*outmask)
290        return []
291
292    # forwards to matplotlib axes
293    def text(self, *args, **kwargs):
294        self._assert_plotter(action="reload")
295        if kwargs.has_key("interactive"):
296            if kwargs.pop("interactive"):
297                pos = self._plotter.get_point()
298                args = tuple(pos)+args
299        self._axes_callback("text", *args, **kwargs)
300
301    text.__doc__ = matplotlib.axes.Axes.text.__doc__
302
303    def arrow(self, *args, **kwargs):
304        self._assert_plotter(action="reload")
305        if kwargs.has_key("interactive"):
306            if kwargs.pop("interactive"):
307                pos = self._plotter.get_region()
308                dpos = (pos[0][0], pos[0][1],
309                        pos[1][0]-pos[0][0],
310                        pos[1][1] - pos[0][1])
311                args = dpos + args
312        self._axes_callback("arrow", *args, **kwargs)
313
314    arrow.__doc__ = matplotlib.axes.Axes.arrow.__doc__
315
316    def annotate(self, text, xy=None, xytext=None, **kwargs):
317        self._assert_plotter(action="reload")
318        if kwargs.has_key("interactive"):
319            if kwargs.pop("interactive"):
320                xy = self._plotter.get_point()
321                xytext = self._plotter.get_point()
322        if not kwargs.has_key("arrowprops"):
323            kwargs["arrowprops"] = dict(arrowstyle="->")
324        self._axes_callback("annotate", text, xy, xytext, **kwargs)
325
326    annotate.__doc__ = matplotlib.axes.Axes.annotate.__doc__
327
328    def axvline(self, *args, **kwargs):
329        self._assert_plotter(action="reload")
330        if kwargs.has_key("interactive"):
331            if kwargs.pop("interactive"):
332                pos = self._plotter.get_point()
333                args = (pos[0],)+args
334        self._axes_callback("axvline", *args, **kwargs)
335
336    axvline.__doc__ = matplotlib.axes.Axes.axvline.__doc__
337
338    def axhline(self, *args, **kwargs):
339        self._assert_plotter(action="reload")
340        if kwargs.has_key("interactive"):
341            if kwargs.pop("interactive"):
342                pos = self._plotter.get_point()
343                args = (pos[1],)+args
344        self._axes_callback("axhline", *args, **kwargs)
345
346    axhline.__doc__ = matplotlib.axes.Axes.axhline.__doc__
347
348    def axvspan(self, *args, **kwargs):
349        self._assert_plotter(action="reload")
350        if kwargs.has_key("interactive"):
351            if kwargs.pop("interactive"):
352                pos = self._plotter.get_region()
353                dpos = (pos[0][0], pos[1][0])
354                args = dpos + args
355        self._axes_callback("axvspan", *args, **kwargs)
356        # hack to preventy mpl from redrawing the patch
357        # it seem to convert the patch into lines on every draw.
358        # This doesn't happen in a test script???
359        #del self._plotter.axes.patches[-1]
360
361    axvspan.__doc__ = matplotlib.axes.Axes.axvspan.__doc__
362
363    def axhspan(self, *args, **kwargs):
364        self._assert_plotter(action="reload")
365        if kwargs.has_key("interactive"):
366            if kwargs.pop("interactive"):
367                pos = self._plotter.get_region()
368                dpos = (pos[0][1], pos[1][1])
369                args = dpos + args
370        self._axes_callback("axhspan", *args, **kwargs)
371        # hack to preventy mpl from redrawing the patch
372        # it seem to convert the patch into lines on every draw.
373        # This doesn't happen in a test script???
374        #del self._plotter.axes.patches[-1]
375
376    axhspan.__doc__ = matplotlib.axes.Axes.axhspan.__doc__
377
378    def _axes_callback(self, axesfunc, *args, **kwargs):
379        self._assert_plotter(action="reload")
380        panel = 0
381        if kwargs.has_key("panel"):
382            panel = kwargs.pop("panel")
383        coords = None
384        if kwargs.has_key("coords"):
385            coords = kwargs.pop("coords")
386            if coords.lower() == 'world':
387                kwargs["transform"] = self._plotter.axes.transData
388            elif coords.lower() == 'relative':
389                kwargs["transform"] = self._plotter.axes.transAxes
390        self._plotter.subplot(panel)
391        self._plotter.axes.set_autoscale_on(False)
392        getattr(self._plotter.axes, axesfunc)(*args, **kwargs)
393        self._plotter.show(False)
394        self._plotter.axes.set_autoscale_on(True)
395    # end matplotlib.axes fowarding functions
396
397    @asaplog_post_dec
398    def set_data(self, scan, refresh=True):
399        """
400        Set a scantable to plot.
401        Parameters:
402            scan:      a scantable
403            refresh:   True (default) or False. If True, the plot is
404                       replotted based on the new parameter setting(s).
405                       Otherwise,the parameter(s) are set without replotting.
406        Note:
407           The user specified masks and data selections will be reset
408           if a new scantable is set. This method should be called before
409           setting data selections (set_selection) and/or masks (set_mask).
410        """
411        from asap import scantable
412        if isinstance(scan, scantable):
413            if (self._data is not None) and (scan != self._data):
414                del self._data
415                msg = "A new scantable is set to the plotter. "\
416                      "The masks and data selections are reset."
417                asaplog.push( msg )
418            self._data = scan
419            # reset
420            self._reset()
421        else:
422            msg = "Input is not a scantable"
423            raise TypeError(msg)
424
425        # ranges become invalid when unit changes
426        if self._abcunit and self._abcunit != self._data.get_unit():
427            self._minmaxx = None
428            self._minmaxy = None
429            self._abcunit = self._data.get_unit()
430            self._datamask = None
431        if refresh: self.plot()
432
433    @asaplog_post_dec
434    def set_mode(self, stacking=None, panelling=None, refresh=True):
435        """
436        Set the plots look and feel, i.e. what you want to see on the plot.
437        Parameters:
438            stacking:     tell the plotter which variable to plot
439                          as line colour overlays (default 'pol')
440            panelling:    tell the plotter which variable to plot
441                          across multiple panels (default 'scan'
442            refresh:      True (default) or False. If True, the plot is
443                          replotted based on the new parameter setting(s).
444                          Otherwise,the parameter(s) are set without replotting.
445        Note:
446            Valid modes are:
447                 'beam' 'Beam' 'b':     Beams
448                 'if' 'IF' 'i':         IFs
449                 'pol' 'Pol' 'p':       Polarisations
450                 'scan' 'Scan' 's':     Scans
451                 'time' 'Time' 't':     Times
452                 'row' 'Row' 'r':       Rows
453            When either 'stacking' or 'panelling' is set to 'row',
454            the other parameter setting is ignored.
455        """
456        msg = "Invalid mode"
457        if not self.set_panelling(panelling) or \
458               not self.set_stacking(stacking):
459            raise TypeError(msg)
460        #if self._panelling == 'r':
461        #    self._stacking = '_r'
462        #if self._stacking == 'r':
463        #    self._panelling = '_r'
464        if refresh and self._data: self.plot(self._data)
465        return
466
467    def set_panelling(self, what=None):
468        """Set the 'panelling' mode i.e. which type of spectra should be
469        spread across different panels.
470        """
471
472        mode = what
473        if mode is None:
474             mode = rcParams['plotter.panelling']
475        md = self._translate(mode)
476        if md:
477            self._panelling = md
478            self._title = None
479            #if md == 'r':
480            #    self._stacking = '_r'
481            # you need to reset counters for multi page plotting
482            self._reset_counters()
483            return True
484        return False
485
486    def set_layout(self,rows=None,cols=None,refresh=True):
487        """
488        Set the multi-panel layout, i.e. how many rows and columns plots
489        are visible.
490        Parameters:
491             rows:   The number of rows of plots
492             cols:   The number of columns of plots
493             refresh:  True (default) or False. If True, the plot is
494                       replotted based on the new parameter setting(s).
495                       Otherwise,the parameter(s) are set without replotting.
496        Note:
497             If no argument is given, the potter reverts to its auto-plot
498             behaviour.
499        """
500        self._rows = rows
501        self._cols = cols
502        if refresh and self._data: self.plot(self._data)
503        return
504
505    def set_stacking(self, what=None):
506        """Set the 'stacking' mode i.e. which type of spectra should be
507        overlayed.
508        """
509        mode = what
510        if mode is None:
511             mode = rcParams['plotter.stacking']
512        md = self._translate(mode)
513        if md:
514            self._stacking = md
515            self._lmap = None
516            #if md == 'r':
517            #    self._panelling = '_r'
518            # you need to reset counters for multi page plotting
519            self._reset_counters()
520            return True
521        return False
522
523    def _reset_counters(self):
524        self._startrow = 0
525        self._ipanel = -1
526        self._panelrows = []
527
528    def set_range(self,xstart=None,xend=None,ystart=None,yend=None,refresh=True, offset=None):
529        """
530        Set the range of interest on the abcissa of the plot
531        Parameters:
532            [x,y]start,[x,y]end:  The start and end points of the 'zoom' window
533            refresh:  True (default) or False. If True, the plot is
534                      replotted based on the new parameter setting(s).
535                      Otherwise,the parameter(s) are set without replotting.
536            offset:   shift the abcissa by the given amount. The abcissa label will
537                      have '(relative)' appended to it.
538        Note:
539            These become non-sensical when the unit changes.
540            use plotter.set_range() without parameters to reset
541
542        """
543        self._offset = offset
544        if xstart is None and xend is None:
545            self._minmaxx = None
546        else:
547            self._minmaxx = [xstart,xend]
548        if ystart is None and yend is None:
549            self._minmaxy = None
550        else:
551            self._minmaxy = [ystart,yend]
552        if refresh and self._data: self.plot(self._data)
553        return
554
555    def set_legend(self, mp=None, fontsize = None, mode = 0, refresh=True):
556        """
557        Specify a mapping for the legend instead of using the default
558        indices:
559        Parameters:
560            mp:        a list of 'strings'. This should have the same length
561                       as the number of elements on the legend and then maps
562                       to the indeces in order. It is possible to uses latex
563                       math expression. These have to be enclosed in r'',
564                       e.g. r'$x^{2}$'
565            fontsize:  The font size of the label (default None)
566            mode:      where to display the legend
567                       Any other value for loc else disables the legend:
568                        0: auto
569                        1: upper right
570                        2: upper left
571                        3: lower left
572                        4: lower right
573                        5: right
574                        6: center left
575                        7: center right
576                        8: lower center
577                        9: upper center
578                        10: center
579            refresh:    True (default) or False. If True, the plot is
580                        replotted based on the new parameter setting(s).
581                        Otherwise,the parameter(s) are set without replotting.
582
583        Example:
584             If the data has two IFs/rest frequencies with index 0 and 1
585             for CO and SiO:
586             plotter.set_stacking('i')
587             plotter.set_legend(['CO','SiO'])
588             plotter.plot()
589             plotter.set_legend([r'$^{12}CO$', r'SiO'])
590        """
591        self._lmap = mp
592        #self._plotter.legend(mode)
593        self._legendloc = mode
594        if isinstance(fontsize, int):
595            from matplotlib import rc as rcp
596            rcp('legend', fontsize=fontsize)
597        if refresh and self._data: self.plot(self._data)
598        return
599
600    def set_title(self, title=None, fontsize=None, refresh=True):
601        """
602        Set the title of sub-plots. If multiple sub-plots are plotted,
603        multiple titles have to be specified.
604        Parameters:
605            title:      a list of titles of sub-plots.
606            fontsize:   a font size of titles (integer)
607            refresh:    True (default) or False. If True, the plot is
608                        replotted based on the new parameter setting(s).
609                        Otherwise,the parameter(s) are set without replotting.
610        Example:
611             # two panels are visible on the plotter
612             plotter.set_title(['First Panel','Second Panel'])
613        """
614        self._title = title
615        if isinstance(fontsize, int):
616            from matplotlib import rc as rcp
617            rcp('axes', titlesize=fontsize)
618        if refresh and self._data: self.plot(self._data)
619        return
620
621    def set_ordinate(self, ordinate=None, fontsize=None, refresh=True):
622        """
623        Set the y-axis label of the plot. If multiple panels are plotted,
624        multiple labels have to be specified.
625        Parameters:
626            ordinate:    a list of ordinate labels. None (default) let
627                         data determine the labels
628            fontsize:    a font size of vertical axis labels (integer)
629            refresh:     True (default) or False. If True, the plot is
630                         replotted based on the new parameter setting(s).
631                         Otherwise,the parameter(s) are set without replotting.
632        Example:
633             # two panels are visible on the plotter
634             plotter.set_ordinate(['First Y-Axis','Second Y-Axis'])
635        """
636        self._ordinate = ordinate
637        if isinstance(fontsize, int):
638            from matplotlib import rc as rcp
639            rcp('axes', labelsize=fontsize)
640            rcp('ytick', labelsize=fontsize)
641        if refresh and self._data: self.plot(self._data)
642        return
643
644    def set_abcissa(self, abcissa=None, fontsize=None, refresh=True):
645        """
646        Set the x-axis label of the plot. If multiple panels are plotted,
647        multiple labels have to be specified.
648        Parameters:
649            abcissa:     a list of abcissa labels. None (default) let
650                         data determine the labels
651            fontsize:    a font size of horizontal axis labels (integer)
652            refresh:     True (default) or False. If True, the plot is
653                         replotted based on the new parameter setting(s).
654                         Otherwise,the parameter(s) are set without replotting.
655        Example:
656             # two panels are visible on the plotter
657             plotter.set_ordinate(['First X-Axis','Second X-Axis'])
658        """
659        self._abcissa = abcissa
660        if isinstance(fontsize, int):
661            from matplotlib import rc as rcp
662            rcp('axes', labelsize=fontsize)
663            rcp('xtick', labelsize=fontsize)
664        if refresh and self._data: self.plot(self._data)
665        return
666
667    def set_colors(self, colmap, refresh=True):
668        """
669        Set the colours to be used. The plotter will cycle through
670        these colours when lines are overlaid (stacking mode).
671        Parameters:
672            colmap:     a list of colour names
673            refresh:    True (default) or False. If True, the plot is
674                        replotted based on the new parameter setting(s).
675                        Otherwise,the parameter(s) are set without replotting.
676        Example:
677             plotter.set_colors('red green blue')
678             # If for example four lines are overlaid e.g I Q U V
679             # 'I' will be 'red', 'Q' will be 'green', U will be 'blue'
680             # and 'V' will be 'red' again.
681        """
682        #if isinstance(colmap,str):
683        #    colmap = colmap.split()
684        #self._plotter.palette(0, colormap=colmap)
685        self._colormap = colmap
686        if refresh and self._data: self.plot(self._data)
687
688    # alias for english speakers
689    set_colours = set_colors
690
691    def set_histogram(self, hist=True, linewidth=None, refresh=True):
692        """
693        Enable/Disable histogram-like plotting.
694        Parameters:
695            hist:        True (default) or False. The fisrt default
696                         is taken from the .asaprc setting
697                         plotter.histogram
698            linewidth:   a line width
699            refresh:     True (default) or False. If True, the plot is
700                         replotted based on the new parameter setting(s).
701                         Otherwise,the parameter(s) are set without replotting.
702        """
703        self._hist = hist
704        if isinstance(linewidth, float) or isinstance(linewidth, int):
705            from matplotlib import rc as rcp
706            rcp('lines', linewidth=linewidth)
707        if refresh and self._data: self.plot(self._data)
708
709    def set_linestyles(self, linestyles=None, linewidth=None, refresh=True):
710        """
711        Set the linestyles to be used. The plotter will cycle through
712        these linestyles when lines are overlaid (stacking mode) AND
713        only one color has been set.
714        Parameters:
715            linestyles:      a list of linestyles to use.
716                             'line', 'dashed', 'dotted', 'dashdot',
717                             'dashdotdot' and 'dashdashdot' are
718                             possible
719            linewidth:       a line width
720            refresh:         True (default) or False. If True, the plot is
721                             replotted based on the new parameter setting(s).
722                             Otherwise,the parameter(s) are set without replotting.
723        Example:
724             plotter.set_colors('black')
725             plotter.set_linestyles('line dashed dotted dashdot')
726             # If for example four lines are overlaid e.g I Q U V
727             # 'I' will be 'solid', 'Q' will be 'dashed',
728             # U will be 'dotted' and 'V' will be 'dashdot'.
729        """
730        #if isinstance(linestyles,str):
731        #    linestyles = linestyles.split()
732        #self._plotter.palette(color=0,linestyle=0,linestyles=linestyles)
733        self._linestyles = linestyles
734        if isinstance(linewidth, float) or isinstance(linewidth, int):
735            from matplotlib import rc as rcp
736            rcp('lines', linewidth=linewidth)
737        if refresh and self._data: self.plot(self._data)
738
739    def set_font(self, refresh=True,**kwargs):
740        """
741        Set font properties.
742        Parameters:
743            family:    one of 'sans-serif', 'serif', 'cursive', 'fantasy', 'monospace'
744            style:     one of 'normal' (or 'roman'), 'italic'  or 'oblique'
745            weight:    one of 'normal or 'bold'
746            size:      the 'general' font size, individual elements can be adjusted
747                       seperately
748            refresh:   True (default) or False. If True, the plot is
749                       replotted based on the new parameter setting(s).
750                       Otherwise,the parameter(s) are set without replotting.
751        """
752        from matplotlib import rc as rcp
753        fdict = {}
754        for k,v in kwargs.iteritems():
755            if v:
756                fdict[k] = v
757        self._fp = FontProperties(**fdict)
758        if refresh and self._data: self.plot(self._data)
759
760    def set_margin(self,margin=[],refresh=True):
761        """
762        Set margins between subplots and plot edges.
763        Parameters:
764            margin:   a list of margins in figure coordinate (0-1),
765                      i.e., fraction of the figure width or height.
766                      The order of elements should be:
767                      [left, bottom, right, top, horizontal space btw panels,
768                      vertical space btw panels].
769            refresh:  True (default) or False. If True, the plot is
770                      replotted based on the new parameter setting(s).
771                      Otherwise,the parameter(s) are set without replotting.
772        Note
773        * When margin is not specified, the values are reset to the defaults
774          of matplotlib.
775        * If any element is set to be None, the current value is adopted.
776        """
777        if margin == []: self._margins=self._reset_margin()
778        else:
779            self._margins=[None]*6
780            self._margins[0:len(margin)]=margin
781        #print "panel margin set to ",self._margins
782        if refresh and self._data: self.plot(self._data)
783
784    def _reset_margin(self):
785        ks=map(lambda x: 'figure.subplot.'+x,
786               ['left','bottom','right','top','hspace','wspace'])
787        return map(matplotlib.rcParams.get,ks)
788
789    def plot_lines(self, linecat=None, doppler=0.0, deltachan=10, rotate=90.0,
790                   location=None):
791        """
792        Plot a line catalog.
793        Parameters:
794            linecat:      the linecatalog to plot
795            doppler:      the velocity shift to apply to the frequencies
796            deltachan:    the number of channels to include each side of the
797                          line to determine a local maximum/minimum
798            rotate:       the rotation (in degrees) for the text label (default 90.0)
799            location:     the location of the line annotation from the 'top',
800                          'bottom' or alternate (None - the default)
801        Notes:
802        If the spectrum is flagged no line will be drawn in that location.
803        """
804        errmsg = "Cannot plot spectral lines. Need to plot scantable first."
805        self._assert_plotter(action="halt",errmsg=errmsg)
806        if not self._data:
807            raise RuntimeError("No scantable has been plotted yet.")
808        from asap._asap import linecatalog
809        if not isinstance(linecat, linecatalog):
810            raise ValueError("'linecat' isn't of type linecatalog.")
811        if not self._data.get_unit().endswith("Hz"):
812            raise RuntimeError("Can only overlay linecatalogs when data is in frequency.")
813        from numpy import ma
814        for j in range(len(self._plotter.subplots)):
815            self._plotter.subplot(j)
816            lims = self._plotter.axes.get_xlim()
817            for row in range(linecat.nrow()):
818                # get_frequency returns MHz
819                base = { "GHz": 1000.0, "MHz": 1.0, "Hz": 1.0e-6 }
820                restf = linecat.get_frequency(row)/base[self._data.get_unit()]
821                c = 299792.458
822                freq = restf*(1.0-doppler/c)
823                if lims[0] < freq < lims[1]:
824                    if location is None:
825                        loc = 'bottom'
826                        if row%2: loc='top'
827                    else: loc = location
828                    maxys = []
829                    for line in self._plotter.axes.lines:
830                        v = line._x
831                        asc = v[0] < v[-1]
832
833                        idx = None
834                        if not asc:
835                            if v[len(v)-1] <= freq <= v[0]:
836                                i = len(v)-1
837                                while i>=0 and v[i] < freq:
838                                    idx = i
839                                    i-=1
840                        else:
841                           if v[0] <= freq <= v[len(v)-1]:
842                                i = 0
843                                while  i<len(v) and v[i] < freq:
844                                    idx = i
845                                    i+=1
846                        if idx is not None:
847                            lower = idx - deltachan
848                            upper = idx + deltachan
849                            if lower < 0: lower = 0
850                            if upper > len(v): upper = len(v)
851                            s = slice(lower, upper)
852                            y = line._y[s]
853                            maxy = ma.maximum(y)
854                            if isinstance( maxy, float):
855                                maxys.append(maxy)
856                    if len(maxys):
857                        peak = max(maxys)
858                        if peak > self._plotter.axes.get_ylim()[1]:
859                            loc = 'bottom'
860                    else:
861                        continue
862                    self._plotter.vline_with_label(freq, peak,
863                                                   linecat.get_name(row),
864                                                   location=loc, rotate=rotate)
865        self._plotter.show(hardrefresh=False)
866
867
868    def save(self, filename=None, orientation=None, dpi=None):
869        """
870        Save the plot to a file. The known formats are 'png', 'ps', 'eps'.
871        Parameters:
872             filename:    The name of the output file. This is optional
873                          and autodetects the image format from the file
874                          suffix. If non filename is specified a file
875                          called 'yyyymmdd_hhmmss.png' is created in the
876                          current directory.
877             orientation: optional parameter for postscript only (not eps).
878                          'landscape', 'portrait' or None (default) are valid.
879                          If None is choosen for 'ps' output, the plot is
880                          automatically oriented to fill the page.
881             dpi:         The dpi of the output non-ps plot
882        """
883        errmsg = "Cannot save figure. Need to plot first."
884        self._assert_plotter(action="halt",errmsg=errmsg)
885       
886        self._plotter.save(filename,orientation,dpi)
887        return
888
889    @asaplog_post_dec
890    def set_mask(self, mask=None, selection=None, refresh=True):
891        """
892        Set a plotting mask for a specific polarization.
893        This is useful for masking out 'noise' Pangle outside a source.
894        Parameters:
895             mask:           a mask from scantable.create_mask
896             selection:      the spectra to apply the mask to.
897             refresh:        True (default) or False. If True, the plot is
898                             replotted based on the new parameter setting(s).
899                             Otherwise,the parameter(s) are set without replotting.
900        Example:
901             select = selector()
902             select.setpolstrings('Pangle')
903             plotter.set_mask(mymask, select)
904        """
905        if not self._data:
906            msg = "Can only set mask after a first call to plot()"
907            raise RuntimeError(msg)
908        if len(mask):
909            if isinstance(mask, list) or isinstance(mask, tuple):
910                self._usermask = array(mask)
911            else:
912                self._usermask = mask
913        if mask is None and selection is None:
914            self._usermask = []
915            self._maskselection = None
916        if isinstance(selection, selector):
917            self._maskselection = {'b': selection.get_beams(),
918                                   's': selection.get_scans(),
919                                   'i': selection.get_ifs(),
920                                   'p': selection.get_pols(),
921                                   't': [] }
922        else:
923            self._maskselection = None
924        if refresh: self.plot(self._data)
925
926    def _slice_indeces(self, data):
927        mn = self._minmaxx[0]
928        mx = self._minmaxx[1]
929        asc = data[0] < data[-1]
930        start=0
931        end = len(data)-1
932        inc = 1
933        if not asc:
934            start = len(data)-1
935            end = 0
936            inc = -1
937        # find min index
938        #while start > 0 and data[start] < mn:
939        #    start+= inc
940        minind=start
941        for ind in xrange(start,end+inc,inc):
942            if data[ind] > mn: break
943            minind=ind
944        # find max index
945        #while end > 0 and data[end] > mx:
946        #    end-=inc
947        #if end > 0: end +=1
948        maxind=end
949        for ind in xrange(end,start-inc,-inc):
950            if data[ind] < mx: break
951            maxind=ind
952        start=minind
953        end=maxind
954        if start > end:
955            return end,start+1
956        elif start < end:
957            return start,end+1
958        else:
959            return start,end
960
961    def _reset(self):
962        self._usermask = []
963        self._usermaskspectra = None
964        self._offset = None
965        self.set_selection(None, False)
966        self._reset_header()
967
968    def _reset_header(self):
969        self._headtext={'string': None, 'textobj': None}
970
971    def _plot(self, scan):
972        savesel = scan.get_selection()
973        sel = savesel +  self._selection
974        order = self._get_sortstring([self._panelling,self._stacking])
975        if order:
976            sel.set_order(order)
977        scan.set_selection(sel)
978        d = {'b': scan.getbeam, 's': scan.getscan,
979             'i': scan.getif, 'p': scan.getpol, 't': scan.get_time,
980             'r': int}#, '_r': int}
981
982        polmodes = dict(zip(sel.get_pols(), sel.get_poltypes()))
983        # this returns either a tuple of numbers or a length  (ncycles)
984        # convert this into lengths
985        n0,nstack0 = self._get_selected_n(scan)
986        if isinstance(n0, int): n = n0
987        else: n = len(n0)
988        if isinstance(nstack0, int): nstack = nstack0
989        else: nstack = len(nstack0)
990        # In case of row stacking
991        rowstack = False
992        titlemode = self._panelling
993        if self._stacking == "r" and self._panelling != "r":
994            rowstack = True
995            titlemode = '_r'
996        nptot = n
997        maxpanel, maxstack = 16,16
998        if nstack > maxstack:
999            msg ="Scan to be overlayed contains more than %d selections.\n" \
1000                  "Selecting first %d selections..." % (maxstack, maxstack)
1001            asaplog.push(msg)
1002            asaplog.post('WARN')
1003            nstack = min(nstack,maxstack)
1004        #n = min(n-self._ipanel-1,maxpanel)
1005        n = n-self._ipanel-1
1006
1007        ganged = False
1008        if n > 1:
1009            ganged = rcParams['plotter.ganged']
1010            if self._panelling == 'i':
1011                ganged = False
1012            if self._rows and self._cols:
1013                n = min(n,self._rows*self._cols)
1014                self._plotter.set_panels(rows=self._rows,cols=self._cols,
1015                                         nplots=n,margin=self._margins,
1016                                         ganged=ganged)
1017            else:
1018                n = min(n,maxpanel)
1019                self._plotter.set_panels(rows=n,cols=0,nplots=n,
1020                                         margin=self._margins,ganged=ganged)
1021        else:
1022            self._plotter.set_panels(margin=self._margins)
1023        #r = 0
1024        r = self._startrow
1025        nr = scan.nrow()
1026        a0,b0 = -1,-1
1027        allxlim = []
1028        allylim = []
1029        #newpanel=True
1030        newpanel=False
1031        panelcount,stackcount = 0,0
1032        # If this is not the first page
1033        if r > 0:
1034            # panelling value of the prev page
1035            a0 = d[self._panelling](r-1)
1036            # set the initial stackcount large not to plot
1037            # the start row automatically
1038            stackcount = nstack
1039
1040        while r < nr:
1041            a = d[self._panelling](r)
1042            b = d[self._stacking](r)
1043            if a > a0 and panelcount < n:
1044                if n > 1:
1045                    self._plotter.subplot(panelcount)
1046                self._plotter.palette(0)
1047                #title
1048                xlab = self._abcissa and self._abcissa[panelcount] \
1049                       or scan._getabcissalabel()
1050                if self._offset and not self._abcissa:
1051                    xlab += " (relative)"
1052                ylab = self._ordinate and self._ordinate[panelcount] \
1053                       or scan._get_ordinate_label()
1054                self._plotter.set_axes('xlabel', xlab)
1055                self._plotter.set_axes('ylabel', ylab)
1056                #lbl = self._get_label(scan, r, self._panelling, self._title)
1057                lbl = self._get_label(scan, r, titlemode, self._title)
1058                if isinstance(lbl, list) or isinstance(lbl, tuple):
1059                    if 0 <= panelcount < len(lbl):
1060                        lbl = lbl[panelcount]
1061                    else:
1062                        # get default label
1063                        #lbl = self._get_label(scan, r, self._panelling, None)
1064                        lbl = self._get_label(scan, r, titlemode, None)
1065                self._plotter.set_axes('title',lbl)
1066                newpanel = True
1067                stackcount = 0
1068                panelcount += 1
1069                # save the start row to plot this panel for future revisit.
1070                if self._panelling != 'r' and \
1071                       len(self._panelrows) < self._ipanel+1+panelcount:
1072                    self._panelrows += [r]
1073                   
1074            #if (b > b0 or newpanel) and stackcount < nstack:
1075            if stackcount < nstack and (newpanel or \
1076                                            rowstack or (a == a0 and b > b0)):
1077                y = []
1078                if len(polmodes):
1079                    y = scan._getspectrum(r, polmodes[scan.getpol(r)])
1080                else:
1081                    y = scan._getspectrum(r)
1082                # flag application
1083                mr = scan._getflagrow(r)
1084                from numpy import ma, array
1085                if mr:
1086                    y = ma.masked_array(y,mask=mr)
1087                else:
1088                    m = scan._getmask(r)
1089                    from numpy import logical_not, logical_and
1090                    if self._maskselection and len(self._usermask) == len(m):
1091                        if d[self._stacking](r) in self._maskselection[self._stacking]:
1092                            m = logical_and(m, self._usermask)
1093                    y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
1094
1095                x = array(scan._getabcissa(r))
1096                if self._offset:
1097                    x += self._offset
1098                if self._minmaxx is not None:
1099                    s,e = self._slice_indeces(x)
1100                    x = x[s:e]
1101                    y = y[s:e]
1102                if len(x) > 1024 and rcParams['plotter.decimate']:
1103                    fac = len(x)/1024
1104                    x = x[::fac]
1105                    y = y[::fac]
1106                llbl = self._get_label(scan, r, self._stacking, self._lmap)
1107                if isinstance(llbl, list) or isinstance(llbl, tuple):
1108                    if 0 <= stackcount < len(llbl):
1109                        # use user label
1110                        llbl = llbl[stackcount]
1111                    else:
1112                        # get default label
1113                        llbl = self._get_label(scan, r, self._stacking, None)
1114                self._plotter.set_line(label=llbl)
1115                plotit = self._plotter.plot
1116                if self._hist: plotit = self._plotter.hist
1117                if len(x) > 0 and not mr:
1118                    plotit(x,y)
1119                    xlim= self._minmaxx or [min(x),max(x)]
1120                    allxlim += xlim
1121                    ylim= self._minmaxy or [ma.minimum(y),ma.maximum(y)]
1122                    allylim += ylim
1123                else:
1124                    xlim = self._minmaxx or []
1125                    allxlim += xlim
1126                    ylim= self._minmaxy or []
1127                    allylim += ylim
1128                stackcount += 1
1129                a0=a
1130                b0=b
1131                # last in colour stack -> autoscale x
1132                if stackcount == nstack and len(allxlim) > 0:
1133                    allxlim.sort()
1134                    self._plotter.subplots[panelcount-1]['axes'].set_xlim([allxlim[0],allxlim[-1]])
1135                    if ganged:
1136                        allxlim = [allxlim[0],allxlim[-1]]
1137                    else:
1138                        # clear
1139                        allxlim =[]
1140
1141            newpanel = False
1142            #a0=a
1143            #b0=b
1144            # ignore following rows
1145            if (panelcount == n and stackcount == nstack) or (r == nr-1):
1146                # last panel -> autoscale y if ganged
1147                #if rcParams['plotter.ganged'] and len(allylim) > 0:
1148                if ganged and len(allylim) > 0:
1149                    allylim.sort()
1150                    self._plotter.set_limits(ylim=[allylim[0],allylim[-1]])
1151                break
1152            r+=1 # next row
1153
1154        # save the current counter for multi-page plotting
1155        self._startrow = r+1
1156        self._ipanel += panelcount
1157        if self.casabar_exists():
1158            if self._ipanel >= nptot-1:
1159                self._plotter.figmgr.casabar.disable_next()
1160            else:
1161                self._plotter.figmgr.casabar.enable_next()
1162            if self._ipanel + 1 - panelcount > 0:
1163                self._plotter.figmgr.casabar.enable_prev()
1164            else:
1165                self._plotter.figmgr.casabar.disable_prev()
1166
1167        #reset the selector to the scantable's original
1168        scan.set_selection(savesel)
1169
1170        #temporary switch-off for older matplotlib
1171        #if self._fp is not None:
1172        if self._fp is not None and getattr(self._plotter.figure,'findobj',False):
1173            for o in self._plotter.figure.findobj(Text):
1174                o.set_fontproperties(self._fp)
1175
1176    def _get_sortstring(self, lorders):
1177        d0 = {'s': 'SCANNO', 'b': 'BEAMNO', 'i':'IFNO',
1178              'p': 'POLNO', 'c': 'CYCLENO', 't' : 'TIME', 'r':None, '_r':None }
1179        if not (type(lorders) == list) and not (type(lorders) == tuple):
1180            return None
1181        if len(lorders) > 0:
1182            lsorts = []
1183            for order in lorders:
1184                if order == "r":
1185                    # don't sort if row panelling/stacking
1186                    return None
1187                ssort = d0[order]
1188                if ssort:
1189                    lsorts.append(ssort)
1190            return lsorts
1191        return None
1192
1193    def set_selection(self, selection=None, refresh=True, **kw):
1194        """
1195        Parameters:
1196            selection:  a selector object (default unset the selection)
1197            refresh:    True (default) or False. If True, the plot is
1198                        replotted based on the new parameter setting(s).
1199                        Otherwise,the parameter(s) are set without replotting.
1200        """
1201        if selection is None:
1202            # reset
1203            if len(kw) == 0:
1204                self._selection = selector()
1205            else:
1206                # try keywords
1207                for k in kw:
1208                    if k not in selector.fields:
1209                        raise KeyError("Invalid selection key '%s', valid keys are %s" % (k, selector.fields))
1210                self._selection = selector(**kw)
1211        elif isinstance(selection, selector):
1212            self._selection = selection
1213        else:
1214            raise TypeError("'selection' is not of type selector")
1215
1216        order = self._get_sortstring([self._panelling,self._stacking])
1217        if order:
1218            self._selection.set_order(order)
1219        if refresh and self._data:
1220            self.plot()
1221
1222    def _get_selected_n(self, scan):
1223        d1 = {'b': scan.getbeamnos, 's': scan.getscannos,
1224             'i': scan.getifnos, 'p': scan.getpolnos, 't': scan.ncycle,
1225             'r': scan.nrow}#, '_r': False}
1226        d2 = { 'b': self._selection.get_beams(),
1227               's': self._selection.get_scans(),
1228               'i': self._selection.get_ifs(),
1229               'p': self._selection.get_pols(),
1230               't': self._selection.get_cycles(),
1231               'r': False}#, '_r': 1}
1232        n =  d2[self._panelling] or d1[self._panelling]()
1233        nstack = d2[self._stacking] or d1[self._stacking]()
1234        # handle row panelling/stacking
1235        if self._panelling == 'r':
1236            nstack = 1
1237        elif self._stacking == 'r':
1238            n = 1
1239        return n,nstack
1240
1241    def _get_label(self, scan, row, mode, userlabel=None):
1242        if isinstance(userlabel, list) and len(userlabel) == 0:
1243            userlabel = " "
1244        pms = dict(zip(self._selection.get_pols(),self._selection.get_poltypes()))
1245        if len(pms):
1246            poleval = scan._getpollabel(scan.getpol(row),pms[scan.getpol(row)])
1247        else:
1248            poleval = scan._getpollabel(scan.getpol(row),scan.poltype())
1249        d = {'b': "Beam "+str(scan.getbeam(row)),
1250             #'s': scan._getsourcename(row),
1251             's': "Scan "+str(scan.getscan(row))+\
1252                  " ("+str(scan._getsourcename(row))+")",
1253             'i': "IF"+str(scan.getif(row)),
1254             'p': poleval,
1255             't': str(scan.get_time(row)),
1256             'r': "row "+str(row),
1257             #'_r': str(scan.get_time(row))+",\nIF"+str(scan.getif(row))+", "+poleval+", Beam"+str(scan.getbeam(row)) }
1258             '_r': "" }
1259        return userlabel or d[mode]
1260
1261    def plotazel(self, scan=None, outfile=None):
1262        """
1263        plot azimuth and elevation versus time of a scantable
1264        """
1265        visible = rcParams['plotter.gui']
1266        from matplotlib import pylab as PL
1267        from matplotlib.dates import DateFormatter
1268        from pytz import timezone
1269        from matplotlib.dates import HourLocator, MinuteLocator,SecondLocator, DayLocator
1270        from matplotlib.ticker import MultipleLocator
1271        from numpy import array, pi
1272        if not visible or not self._visible:
1273            PL.ioff()
1274            from matplotlib.backends.backend_agg import FigureCanvasAgg
1275            PL.gcf().canvas.switch_backends(FigureCanvasAgg)
1276        self._data = scan
1277        dates = self._data.get_time(asdatetime=True)
1278        t = PL.date2num(dates)
1279        tz = timezone('UTC')
1280        PL.cla()
1281        PL.ioff()
1282        PL.clf()
1283        # Adjust subplot margins
1284        if not self._margins or len(self._margins) != 6:
1285            self.set_margin(refresh=False)
1286        lef, bot, rig, top, wsp, hsp = self._margins
1287        PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
1288                                 wspace=wsp,hspace=hsp)
1289
1290        tdel = max(t) - min(t)
1291        ax = PL.subplot(2,1,1)
1292        el = array(self._data.get_elevation())*180./pi
1293        PL.ylabel('El [deg.]')
1294        dstr = dates[0].strftime('%Y/%m/%d')
1295        if tdel > 1.0:
1296            dstr2 = dates[len(dates)-1].strftime('%Y/%m/%d')
1297            dstr = dstr + " - " + dstr2
1298            majloc = DayLocator()
1299            minloc = HourLocator(range(0,23,12))
1300            timefmt = DateFormatter("%b%d")
1301        elif tdel > 24./60.:
1302            timefmt = DateFormatter('%H:%M')
1303            majloc = HourLocator()
1304            minloc = MinuteLocator(30)
1305        else:
1306            timefmt = DateFormatter('%H:%M')
1307            majloc = MinuteLocator(interval=5)
1308            minloc = SecondLocator(30)
1309
1310        PL.title(dstr)
1311        if tdel == 0.0:
1312            th = (t - PL.floor(t))*24.0
1313            PL.plot(th,el,'o',markersize=2, markerfacecolor='b', markeredgecolor='b')
1314        else:
1315            PL.plot_date(t,el,'o', markersize=2, markerfacecolor='b', markeredgecolor='b',tz=tz)
1316            #ax.grid(True)
1317            ax.xaxis.set_major_formatter(timefmt)
1318            ax.xaxis.set_major_locator(majloc)
1319            ax.xaxis.set_minor_locator(minloc)
1320        ax.yaxis.grid(True)
1321        yloc = MultipleLocator(30)
1322        ax.set_ylim(0,90)
1323        ax.yaxis.set_major_locator(yloc)
1324        if tdel > 1.0:
1325            labels = ax.get_xticklabels()
1326        #    PL.setp(labels, fontsize=10, rotation=45)
1327            PL.setp(labels, fontsize=10)
1328
1329        # Az plot
1330        az = array(self._data.get_azimuth())*180./pi
1331        if min(az) < 0:
1332            for irow in range(len(az)):
1333                if az[irow] < 0: az[irow] += 360.0
1334
1335        ax2 = PL.subplot(2,1,2)
1336        #PL.xlabel('Time (UT [hour])')
1337        PL.ylabel('Az [deg.]')
1338        if tdel == 0.0:
1339            PL.plot(th,az,'o',markersize=2, markeredgecolor='b',markerfacecolor='b')
1340        else:
1341            PL.plot_date(t,az,'o', markersize=2,markeredgecolor='b',markerfacecolor='b',tz=tz)
1342            ax2.xaxis.set_major_formatter(timefmt)
1343            ax2.xaxis.set_major_locator(majloc)
1344            ax2.xaxis.set_minor_locator(minloc)
1345        #ax2.grid(True)
1346        ax2.set_ylim(0,360)
1347        ax2.yaxis.grid(True)
1348        #hfmt = DateFormatter('%H')
1349        #hloc = HourLocator()
1350        yloc = MultipleLocator(60)
1351        ax2.yaxis.set_major_locator(yloc)
1352        if tdel > 1.0:
1353            labels = ax2.get_xticklabels()
1354            PL.setp(labels, fontsize=10)
1355            PL.xlabel('Time (UT [day])')
1356        else:
1357            PL.xlabel('Time (UT [hour])')
1358
1359        PL.ion()
1360        PL.draw()
1361        if matplotlib.get_backend() == 'Qt4Agg': PL.gcf().show()
1362        if (outfile is not None):
1363           PL.savefig(outfile)
1364
1365
1366    def plotpointing2(self, scan=None, colorby='', showline=False, projection=''):
1367        """
1368        plot telescope pointings
1369        Parameters:
1370            infile  : input filename or scantable instance
1371            colorby : change color by either
1372                      'type'(source type)|'scan'|'if'|'pol'|'beam'
1373            showline : show dotted line
1374            projection : projection type either
1375                         ''(no projection [deg])|'coord'(not implemented)
1376        """
1377        from numpy import array, pi
1378        from asap import scantable
1379        # check for scantable
1380        if isinstance(scan, scantable):
1381            if self._data is not None:
1382                if scan != self._data:
1383                    self._data = scan
1384                    # reset
1385                    self._reset()
1386            else:
1387                self._data = scan
1388                self._reset()
1389        if not self._data:
1390            msg = "Input is not a scantable"
1391            raise TypeError(msg)
1392        # check for color mode
1393        validtypes=['type','scan','if','pol', 'beam']
1394        stype = None
1395        if (colorby in validtypes):
1396            stype = colorby[0]
1397        elif len(colorby) > 0:
1398            msg = "Invalid choice of 'colorby' (choices: %s)" % str(validtypes)
1399            raise ValueError(msg)
1400        self._assert_plotter(action="reload")
1401        self._plotter.hold()
1402        if self.casabar_exists(): self._plotter.figmgr.casabar.disable_button()
1403        # for now, only one plot
1404        self._plotter.set_panels(rows=1,cols=1)
1405        # first panel
1406        self._plotter.subplot(0)
1407        # first color and linestyles
1408        self._plotter.palette(0)
1409        self.gca().set_aspect('equal')
1410        basesel = scan.get_selection()
1411        marker = "+"
1412        if showline:
1413            basesel.set_order(["TIME"])
1414            scan.set_selection(basesel)
1415            if not (stype in ["t", "s"]):
1416                marker = "+:"
1417        if not stype:
1418            selIds = [""] # cheating
1419            sellab = "all points"
1420        elif stype == 't':
1421            selIds = range(15)
1422            sellab = "src type "
1423        else:
1424            selIds = getattr(self._data,'get'+colorby+'nos')()
1425            sellab = colorby.upper()
1426        selFunc = "set_"+colorby+"s"
1427        for idx in selIds:
1428            sel = selector() + basesel
1429            if stype:
1430                bid = getattr(basesel,'get_'+colorby+"s")()
1431                if (len(bid) > 0) and (not idx in bid):
1432                    # base selection doesn't contain idx
1433                    # Note summation of selector is logical sum if
1434                    continue
1435                getattr(sel, selFunc)([idx])
1436            if not sel.is_empty():
1437                try:
1438                    self._data.set_selection(sel)
1439                except RuntimeError, instance:
1440                    if stype == 't' and str(instance).startswith("Selection contains no data."):
1441                        continue
1442                    else:
1443                        self._data.set_selection(basesel)
1444                        raise RuntimeError, instance
1445            if self._data.nrow() == 0:
1446                self._data.set_selection(basesel)
1447                continue
1448            print "Plotting direction of %s = %s" % (colorby, str(idx))
1449            dir = array(self._data.get_directionval()).transpose()
1450            ra = dir[0]*180./pi
1451            dec = dir[1]*180./pi
1452            self._plotter.set_line(label=(sellab+str(idx)))
1453            self._plotter.plot(ra,dec,marker)
1454
1455        # restore original selection
1456        self._data.set_selection(basesel)
1457        # need to plot scan pattern explicitly
1458        if showline and (stype in ["t", "s"]):
1459            dir = array(self._data.get_directionval()).transpose()
1460            ra = dir[0]*180./pi
1461            dec = dir[1]*180./pi
1462            self._plotter.set_line(label="scan pattern")
1463            self._plotter.plot(ra,dec,":")
1464           
1465        xlab = 'RA [deg.]'
1466        ylab = 'Declination [deg.]'
1467        self._plotter.set_axes('xlabel', xlab)
1468        self._plotter.set_axes('ylabel', ylab)
1469        self._plotter.set_axes('title', 'Telescope pointings')
1470        if stype: self._plotter.legend(self._legendloc)
1471        else: self._plotter.legend(None)
1472        # reverse x-axis
1473        xmin, xmax = self.gca().get_xlim()
1474        self._plotter.set_limits(xlim=[xmax,xmin])
1475
1476        self._plotter.release()
1477        self._plotter.show(hardrefresh=False)
1478        return
1479
1480    def plotpointing(self, scan=None, outfile=None):
1481        """
1482        plot telescope pointings
1483        """
1484        visible = rcParams['plotter.gui']
1485        from matplotlib import pylab as PL
1486        from numpy import array, pi
1487        if not visible or not self._visible:
1488            PL.ioff()
1489            from matplotlib.backends.backend_agg import FigureCanvasAgg
1490            PL.gcf().canvas.switch_backends(FigureCanvasAgg)
1491        self._data = scan
1492        dir = array(self._data.get_directionval()).transpose()
1493        ra = dir[0]*180./pi
1494        dec = dir[1]*180./pi
1495        PL.cla()
1496        #PL.ioff()
1497        PL.clf()
1498        # Adjust subplot margins
1499        if not self._margins or len(self._margins) != 6:
1500            self.set_margin(refresh=False)
1501        lef, bot, rig, top, wsp, hsp = self._margins
1502        PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
1503                                 wspace=wsp,hspace=hsp)
1504        ax = PL.gca()
1505        #ax = PL.axes([0.1,0.1,0.8,0.8])
1506        #ax = PL.axes([0.1,0.1,0.8,0.8])
1507        ax.set_aspect('equal')
1508        PL.plot(ra, dec, 'b,')
1509        PL.xlabel('RA [deg.]')
1510        PL.ylabel('Declination [deg.]')
1511        PL.title('Telescope pointings')
1512        [xmin,xmax,ymin,ymax] = PL.axis()
1513        PL.axis([xmax,xmin,ymin,ymax])
1514        PL.ion()
1515        PL.draw()
1516        if matplotlib.get_backend() == 'Qt4Agg': PL.gcf().show()
1517        if (outfile is not None):
1518           PL.savefig(outfile)
1519
1520    # plot total power data
1521    # plotting in time is not yet implemented..
1522    @asaplog_post_dec
1523    def plottp(self, scan=None):
1524        from asap import scantable
1525        if not self._data and not scan:
1526            msg = "Input is not a scantable"
1527            raise TypeError(msg)
1528        if isinstance(scan, scantable):
1529            if self._data is not None:
1530                if scan != self._data:
1531                    self._data = scan
1532                    # reset
1533                    self._reset()
1534            else:
1535                self._data = scan
1536                self._reset()
1537        # ranges become invalid when abcissa changes?
1538        #if self._abcunit and self._abcunit != self._data.get_unit():
1539        #    self._minmaxx = None
1540        #    self._minmaxy = None
1541        #    self._abcunit = self._data.get_unit()
1542        #    self._datamask = None
1543
1544        self._assert_plotter(action="reload")
1545        self._plotter.hold()
1546        self._plotter.clear()
1547        # Adjust subplot margins
1548        if not self._margins or len(self._margins) !=6:
1549            self.set_margin(refresh=False)
1550        lef, bot, rig, top, wsp, hsp = self._margins
1551        self._plotter.figure.subplots_adjust(
1552            left=lef,bottom=bot,right=rig,top=top,wspace=wsp,hspace=hsp)
1553        if self.casabar_exists(): self._plotter.figmgr.casabar.disable_button()
1554        self._plottp(self._data)
1555        if self._minmaxy is not None:
1556            self._plotter.set_limits(ylim=self._minmaxy)
1557        self._plotter.release()
1558        self._plotter.tidy()
1559        self._plotter.show(hardrefresh=False)
1560        return
1561
1562    def _plottp(self,scan):
1563        """
1564        private method for plotting total power data
1565        """
1566        from numpy import ma, array, arange, logical_not
1567        r=0
1568        nr = scan.nrow()
1569        a0,b0 = -1,-1
1570        allxlim = []
1571        allylim = []
1572        y=[]
1573        self._plotter.set_panels()
1574        self._plotter.palette(0)
1575        #title
1576        #xlab = self._abcissa and self._abcissa[panelcount] \
1577        #       or scan._getabcissalabel()
1578        #ylab = self._ordinate and self._ordinate[panelcount] \
1579        #       or scan._get_ordinate_label()
1580        xlab = self._abcissa or 'row number' #or Time
1581        ylab = self._ordinate or scan._get_ordinate_label()
1582        self._plotter.set_axes('xlabel',xlab)
1583        self._plotter.set_axes('ylabel',ylab)
1584        lbl = self._get_label(scan, r, 's', self._title)
1585        if isinstance(lbl, list) or isinstance(lbl, tuple):
1586        #    if 0 <= panelcount < len(lbl):
1587        #        lbl = lbl[panelcount]
1588        #    else:
1589                # get default label
1590             lbl = self._get_label(scan, r, self._panelling, None)
1591        self._plotter.set_axes('title',lbl)
1592        y=array(scan._get_column(scan._getspectrum,-1))
1593        m = array(scan._get_column(scan._getmask,-1))
1594        y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
1595        x = arange(len(y))
1596        # try to handle spectral data somewhat...
1597        l,m = y.shape
1598        if m > 1:
1599            y=y.mean(axis=1)
1600        plotit = self._plotter.plot
1601        llbl = self._get_label(scan, r, self._stacking, None)
1602        self._plotter.set_line(label=llbl)
1603        if len(x) > 0:
1604            plotit(x,y)
1605
1606
1607    # forwards to matplotlib.Figure.text
1608    def figtext(self, *args, **kwargs):
1609        """
1610        Add text to figure at location x,y (relative 0-1 coords).
1611        This method forwards *args and **kwargs to a Matplotlib method,
1612        matplotlib.Figure.text.
1613        See the method help for detailed information.
1614        """
1615        self._assert_plotter(action="reload")
1616        self._plotter.text(*args, **kwargs)
1617    # end matplotlib.Figure.text forwarding function
1618
1619
1620    # printing header information
1621    @asaplog_post_dec
1622    def print_header(self, plot=True, fontsize=9, logger=False, selstr='', extrastr=''):
1623        """
1624        print data (scantable) header on the plot and/or logger.
1625        To plot the header on the plot, this method should be called after
1626        plotting spectra by the method, asapplotter.plot.
1627        Parameters:
1628            plot:      whether or not print header info on the plot.
1629            fontsize:  header font size (valid only plot=True)
1630            logger:    whether or not print header info on the logger.
1631            selstr:    additional selection string (not verified)
1632            extrastr:  additional string to print at the beginning (not verified)
1633        """
1634        if not plot and not logger:
1635            return
1636        if not self._data:
1637            raise RuntimeError("No scantable has been set yet.")
1638        # Now header will be printed on plot and/or logger.
1639        # Get header information and format it.
1640        ssum=self._data._list_header()
1641        # Print Observation header to the upper-left corner of plot
1642        headstr=[ssum[0:ssum.find('Obs. Type:')]]
1643        headstr.append(ssum[ssum.find('Obs. Type:'):ssum.find('Flux Unit:')])
1644        if extrastr != '':
1645            headstr[0]=extrastr+'\n'+headstr[0]
1646            self._headtext['extrastr'] = extrastr
1647        if selstr != '':
1648            selstr += '\n'
1649            self._headtext['selstr'] = selstr
1650        ssel=(selstr+self._data.get_selection().__str__()+self._selection.__str__() or 'none')
1651        headstr.append('***Selections***\n'+ssel)
1652
1653        if plot:
1654            errmsg = "Can plot header only after the first call to plot()."
1655            self._assert_plotter(action="halt",errmsg=errmsg)
1656            self._plotter.hold()
1657            self._header_plot(headstr,fontsize=fontsize)
1658            import time
1659            self._plotter.figure.text(0.99,0.01,
1660                            time.strftime("%a %d %b %Y  %H:%M:%S %Z"),
1661                            horizontalalignment='right',
1662                            verticalalignment='bottom',fontsize=8)
1663            self._plotter.release()
1664        if logger:
1665            selstr = "Selections:    "+ssel
1666            asaplog.push("----------------\n  Plot Summary\n----------------")
1667            asaplog.push(extrastr)
1668            asaplog.push(ssum[0:ssum.find('Selection:')]\
1669                         + selstr)
1670        self._headtext['string'] = headstr
1671        del ssel, ssum, headstr
1672
1673    def _header_plot(self, texts, fontsize=9):
1674        self._headtext['textobj']=[]
1675        nstcol=len(texts)
1676        for i in range(nstcol):
1677            self._headtext['textobj'].append(
1678                self._plotter.figure.text(0.03+float(i)/nstcol,0.98,
1679                                          texts[i],
1680                                          horizontalalignment='left',
1681                                          verticalalignment='top',
1682                                          fontsize=fontsize))
1683
1684    def clear_header(self):
1685        if not self._headtext['textobj']:
1686            asaplog.push("No header has been plotted. Exit without any operation")
1687            asaplog.post("WARN")
1688        elif self._assert_plotter(action="status"):
1689            self._plotter.hold()
1690            for textobj in self._headtext['textobj']:
1691                #if textobj.get_text() in self._headstring:
1692                try:
1693                    textobj.remove()
1694                except NotImplementedError:
1695                    self._plotter.figure.texts.pop(self._plotter.figure.texts.index(textobj))
1696            self._plotter.release()
1697        self._reset_header()
1698
1699    # plot spectra by pointing
1700    @asaplog_post_dec
1701    def plotgrid(self, scan=None,center=None,spacing=None,rows=None,cols=None):
1702        """
1703        Plot spectra based on direction.
1704       
1705        Parameters:
1706            scan:      a scantable to plot
1707            center:    the grid center direction (a list) of plots in the
1708                       unit of DIRECTION column.
1709                       (default) the center of map region
1710            spacing:   a list of horizontal (R.A.) and vertical (Dec.)
1711                       spacing in the unit of DIRECTION column.
1712                       (default) Calculated by the extent of map region and
1713                       the number of rows and cols to cover
1714            rows:      number of panels (grid points) in horizontal direction
1715            cols:      number of panels (grid points) in vertical direction
1716
1717        Note:
1718        - Only the first IFNO, POLNO, and BEAM in the scantable will be
1719        plotted.
1720        - This method doesn't re-grid and average spectra in scantable. Use
1721        asapgrid module to re-grid spectra before plotting with this method.
1722        Only the first spectrum is plotted in case there are multiple
1723        spectra which belong to a grid.
1724        """
1725        from asap import scantable
1726        from numpy import array, ma, cos
1727        if not self._data and not scan:
1728            msg = "No scantable is specified to plot"
1729            raise TypeError(msg)
1730        if scan:
1731            self.set_data(scan, refresh=False)
1732            del scan
1733
1734        # Rows and cols
1735        if rows:
1736            self._rows = int(rows)
1737        else:
1738            msg = "Number of rows to plot are not specified. "
1739            if self._rows:
1740                msg += "Using previous value = %d" % (self._rows)
1741                asaplog.push(msg)
1742            else:
1743                self._rows = 1
1744                msg += "Setting rows = %d" % (self._rows)
1745                asaplog.post()
1746                asaplog.push(msg)
1747                asaplog.post("WARN")
1748        if cols:
1749            self._cols = int(cols)
1750        else:
1751            msg = "Number of cols to plot are not specified. "
1752            if self._cols:
1753                msg += "Using previous value = %d" % (self._cols)
1754                asaplog.push(msg)
1755            else:
1756                self._cols = 1
1757                msg += "Setting cols = %d" % (self._cols)
1758                asaplog.post()
1759                asaplog.push(msg)
1760                asaplog.post("WARN")
1761
1762        # Center and spacing
1763        dirarr = array(self._data.get_directionval()).transpose()
1764        print "Pointing range: (x, y) = (%f - %f, %f - %f)" %\
1765              (dirarr[0].min(),dirarr[0].max(),dirarr[1].min(),dirarr[1].max())
1766        dircent = [0.5*(dirarr[0].max() + dirarr[0].min()),
1767                   0.5*(dirarr[1].max() + dirarr[1].min())]
1768        del dirarr
1769        if center is None:
1770            #asaplog.post()
1771            asaplog.push("Grid center is not specified. Automatically calculated from pointing center.")
1772            #asaplog.post("WARN")
1773            #center = [dirarr[0].mean(), dirarr[1].mean()]
1774            center = dircent
1775        elif (type(center) in (list, tuple)) and len(center) > 1:
1776            from numpy import pi
1777            # make sure center_x is in +-pi of pointing center
1778            # (assumes dirs are in rad)
1779            rotnum = round(abs(center[0] - dircent[0])/(2*pi))
1780            if center[0] < dircent[0]: rotnum *= -1
1781            cenx = center[0] - rotnum*2*pi
1782            center = [cenx, center[1]]
1783        else:
1784            msg = "Direction of grid center should be a list of float (R.A., Dec.)"
1785            raise ValueError, msg
1786        asaplog.push("Grid center: (%f, %f) " % (center[0],center[1]))
1787
1788        if spacing is None:
1789            #asaplog.post()
1790            asaplog.push("Grid spacing not specified. Automatically calculated from map coverage")
1791            #asaplog.post("WARN")
1792            # automatically get spacing
1793            dirarr = array(self._data.get_directionval()).transpose()
1794            wx = 2. * max(abs(dirarr[0].max()-center[0]),
1795                          abs(dirarr[0].min()-center[0]))
1796            wy = 2. * max(abs(dirarr[1].max()-center[1]),
1797                          abs(dirarr[1].min()-center[1]))
1798            ## slightly expand area to plot the edges
1799            #wx *= 1.1
1800            #wy *= 1.1
1801            xgrid = wx/max(self._cols-1.,1.)
1802            #xgrid = wx/float(max(self._cols,1.))
1803            xgrid *= cos(center[1])
1804            ygrid = wy/max(self._rows-1.,1.)
1805            #ygrid = wy/float(max(self._rows,1.))
1806            # single pointing (identical R.A. and/or Dec. for all spectra.)
1807            if xgrid == 0:
1808                xgrid = 1.
1809            if ygrid == 0:
1810                ygrid = 1.
1811            # spacing should be negative to transpose plot
1812            spacing = [- xgrid, - ygrid]
1813            del dirarr, xgrid, ygrid
1814        #elif isinstance(spacing, str):
1815        #    # spacing is a quantity
1816        elif (type(spacing) in (list, tuple)) and len(spacing) > 1:
1817            for i in xrange(2):
1818                val = spacing[i]
1819                if not isinstance(val, float):
1820                    raise TypeError("spacing should be a list of float")
1821                if val > 0.:
1822                    spacing[i] = -val
1823            spacing = spacing[0:2]
1824        else:
1825            msg = "Invalid spacing."
1826            raise TypeError(msg)
1827        asaplog.push("Spacing: (%f, %f) (projected)" % (spacing[0],spacing[1]))
1828
1829        ntotpl = self._rows * self._cols
1830        ifs = self._data.getifnos()
1831        if len(ifs) > 1:
1832            msg = "Found multiple IFs in scantable. Only the first IF (IFNO=%d) will be plotted." % ifs[0]
1833            asaplog.post()
1834            asaplog.push(msg)
1835            asaplog.post("WARN")
1836        pols = self._data.getpolnos()
1837        if len(pols) > 1:
1838            msg = "Found multiple POLs in scantable. Only the first POL (POLNO=%d) will be plotted." % pols[0]
1839            asaplog.post()
1840            asaplog.push(msg)
1841            asaplog.post("WARN")
1842        beams = self._data.getbeamnos()
1843        if len(beams) > 1:
1844            msg = "Found multiple BEAMs in scantable. Only the first BEAM (BEAMNO=%d) will be plotted." % beams[0]
1845            asaplog.post()
1846            asaplog.push(msg)
1847            asaplog.post("WARN")
1848        self._data.set_selection(ifs=[ifs[0]],pols=[pols[0]],beams=[beams[0]])
1849        if self._data.nrow() > ntotpl:
1850            msg = "Scantable is finely sampled than plotting grids. "\
1851                  + "Only the first spectrum is plotted in each grid."
1852            asaplog.post()
1853            asaplog.push(msg)
1854            asaplog.post("WARN")
1855       
1856        self._assert_plotter(action="reload")
1857        self._plotter.hold()
1858        #self._plotter.clear() #all artists are cleared at set_panels
1859        self._plotter.legend()
1860
1861        # Adjust subplot margins
1862        if not self._margins or len(self._margins) !=6:
1863            self.set_margin(refresh=False)
1864        self._plotter.set_panels(rows=self._rows,cols=self._cols,
1865                                 nplots=ntotpl,margin=self._margins,ganged=True)       
1866        if self.casabar_exists():
1867            self._plotter.figmgr.casabar.set_pagecounter(1)
1868            self._plotter.figmgr.casabar.enable_button()
1869        # Plot helper
1870        from asap._asap import plothelper as plhelper
1871        ph = plhelper(self._data)
1872        ph.set_gridval(self._cols, self._rows, spacing[0], spacing[1],
1873                          center[0], center[1], epoch="J2000", projname="SIN")
1874        # Actual plot
1875        npl = 0
1876        for irow in range(self._data.nrow()):
1877            (ix, iy) = ph.get_gpos(irow)
1878            #print("asapplotter.plotgrid: (ix, iy) = (%f, %f)" % (ix, iy))
1879            if ix < 0 or ix >= self._cols:
1880                #print "Row %d : Out of X-range (x = %f) ... skipped" % (irow, pos[0])
1881                continue
1882            ix = int(ix)
1883            if iy < 0 or iy >= self._rows:
1884                #print "Row %d : Out of Y-range (y = %f) ... skipped" % (irow,pos[1])
1885                continue
1886            iy = int(iy)
1887            ipanel = ix + iy*self._rows
1888            #print("Resolved panel Id (%d, %d): %d" % (ix, iy, ipanel))
1889            if len(self._plotter.subplots[ipanel]['lines']) > 0:
1890                #print "Row %d : panel %d lready plotted ... skipped" % (irow,ipanel)
1891                # a spectrum already plotted in the panel
1892                continue
1893            # Plotting this row
1894            #print "PLOTTING row %d (panel=%d)" % (irow, ipanel)
1895            npl += 1
1896            self._plotter.subplot(ipanel)
1897            self._plotter.palette(0,colormap=self._colormap, \
1898                                  linestyle=0,linestyles=self._linestyles)
1899            xlab = self._abcissa and self._abcissa[ipanel] \
1900                   or self._data._getabcissalabel(irow)
1901            if self._offset and not self._abcissa:
1902                xlab += " (relative)"
1903            ylab = self._ordinate and self._ordinate[ipanel] \
1904                   or self._data._get_ordinate_label()
1905            self._plotter.set_axes('xlabel', xlab)
1906            self._plotter.set_axes('ylabel', ylab)
1907            lbl = self._data.get_direction(irow)
1908            self._plotter.set_axes('title',lbl)
1909
1910            y = self._data._getspectrum(irow)
1911            # flag application
1912            mr = self._data._getflagrow(irow)
1913            if mr:  # FLAGROW=True
1914                y = ma.masked_array(y,mask=mr)
1915            else:
1916                m = self._data._getmask(irow)
1917                from numpy import logical_not, logical_and
1918                ### user mask is not available so far
1919                #if self._maskselection and len(self._usermask) == len(m):
1920                #    if d[self._stacking](irow) in self._maskselection[self._stacking]:
1921                #            m = logical_and(m, self._usermask)
1922                y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
1923
1924            x = array(self._data._getabcissa(irow))
1925            if self._offset:
1926                x += self._offset
1927            if self._minmaxx is not None:
1928                s,e = self._slice_indeces(x)
1929                x = x[s:e]
1930                y = y[s:e]
1931            if len(x) > 1024 and rcParams['plotter.decimate']:
1932                fac = len(x)/1024
1933                x = x[::fac]
1934                y = y[::fac]
1935            self._plotter.set_line(label=lbl)
1936            plotit = self._plotter.plot
1937            if self._hist: plotit = self._plotter.hist
1938            if len(x) > 0 and not mr:
1939                plotit(x,y)
1940#                 xlim= self._minmaxx or [min(x),max(x)]
1941#                 allxlim += xlim
1942#                 ylim= self._minmaxy or [ma.minimum(y),ma.maximum(y)]
1943#                 allylim += ylim
1944#             else:
1945#                 xlim = self._minmaxx or []
1946#                 allxlim += xlim
1947#                 ylim= self._minmaxy or []
1948#                 allylim += ylim
1949           
1950            if npl >= ntotpl:
1951                break
1952           
1953        if self._minmaxy is not None:
1954            self._plotter.set_limits(ylim=self._minmaxy)
1955        self._plotter.release()
1956        self._plotter.tidy()
1957        self._plotter.show(hardrefresh=False)
1958        return
Note: See TracBrowser for help on using the repository browser.