source: branches/alma/python/asapplotter.py @ 1457

Last change on this file since 1457 was 1457, checked in by TakTsutsumi, 15 years ago

New Development: No

JIRA Issue: No

Ready to Release: Yes

Interface Changes: No

What Interface Changed:

Test Programs: sdplot(plottype='azel')

Put in Release Notes: No

Description: Fixed a bug in scantable.get_time().

Updated sd.plotter for azel plotting
with current get_time option.


  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 36.6 KB
Line 
1from asap import rcParams, print_log, selector
2import matplotlib.axes
3import re
4
5class asapplotter:
6    """
7    The ASAP plotter.
8    By default the plotter is set up to plot polarisations
9    'colour stacked' and scantables across panels.
10    Note:
11        Currenly it only plots 'spectra' not Tsys or
12        other variables.
13    """
14    def __init__(self, visible=None):
15        self._visible = rcParams['plotter.gui']
16        if visible is not None:
17            self._visible = visible
18        self._plotter = self._newplotter()
19
20        self._panelling = None
21        self._stacking = None
22        self.set_panelling()
23        self.set_stacking()
24        self._rows = None
25        self._cols = None
26        self._autoplot = False
27        self._minmaxx = None
28        self._minmaxy = None
29        self._datamask = None
30        self._data = None
31        self._lmap = None
32        self._title = None
33        self._ordinate = None
34        self._abcissa = None
35        self._abcunit = None
36        self._usermask = []
37        self._maskselection = None
38        self._selection = selector()
39        self._hist = rcParams['plotter.histogram']
40
41    def _translate(self, instr):
42        keys = "s b i p t".split()
43        if isinstance(instr, str):
44            for key in keys:
45                if instr.lower().startswith(key):
46                    return key
47        return None
48
49    def _newplotter(self):
50        if self._visible:
51            from asap.asaplotgui import asaplotgui as asaplot
52        else:
53            from asap.asaplot import asaplot
54        return asaplot()
55
56
57    def plot(self, scan=None):
58        """
59        Plot a scantable.
60        Parameters:
61            scan:   a scantable
62        Note:
63            If a scantable was specified in a previous call
64            to plot, no argument has to be given to 'replot'
65            NO checking is done that the abcissas of the scantable
66            are consistent e.g. all 'channel' or all 'velocity' etc.
67        """
68        if self._plotter.is_dead:
69            self._plotter = self._newplotter()
70        self._plotter.hold()
71        self._plotter.clear()
72        from asap import scantable
73        if not self._data and not scan:
74            msg = "Input is not a scantable"
75            if rcParams['verbose']:
76                print msg
77                return
78            raise TypeError(msg)
79        if isinstance(scan, scantable):
80            if self._data is not None:
81                if scan != self._data:
82                    self._data = scan
83                    # reset
84                    self._reset()
85            else:
86                self._data = scan
87                self._reset()
88        # ranges become invalid when unit changes
89        if self._abcunit and self._abcunit != self._data.get_unit():
90            self._minmaxx = None
91            self._minmaxy = None
92            self._abcunit = self._data.get_unit()
93            self._datamask = None
94        self._plot(self._data)
95        if self._minmaxy is not None:
96            self._plotter.set_limits(ylim=self._minmaxy)
97        self._plotter.release()
98        self._plotter.tidy()
99        self._plotter.show(hardrefresh=False)
100        print_log()
101        return
102
103
104    # forwards to matplotlib axes
105    def text(self, *args, **kwargs):
106        self._axes_callback("text", *args, **kwargs)
107    text.__doc__ = matplotlib.axes.Axes.text.__doc__
108    def arrow(self, *args, **kwargs):
109        self._axes_callback("arrow", *args, **kwargs)
110    arrow.__doc__ = matplotlib.axes.Axes.arrow.__doc__
111    def axvline(self, *args, **kwargs):
112        self._axes_callback("axvline", *args, **kwargs)
113    axvline.__doc__ = matplotlib.axes.Axes.axvline.__doc__
114    def axhline(self, *args, **kwargs):
115        self._axes_callback("axhline", *args, **kwargs)
116    axhline.__doc__ = matplotlib.axes.Axes.axhline.__doc__
117    def axvspan(self, *args, **kwargs):
118        self._axes_callback("axvspan", *args, **kwargs)
119        # hack to preventy mpl from redrawing the patch
120        # it seem to convert the patch into lines on every draw.
121        # This doesn't happen in a test script???
122        del self._plotter.axes.patches[-1]
123    axvspan.__doc__ = matplotlib.axes.Axes.axvspan.__doc__
124
125    def axhspan(self, *args, **kwargs):
126        self._axes_callback("axhspan", *args, **kwargs)
127        # hack to preventy mpl from redrawing the patch
128        # it seem to convert the patch into lines on every draw.
129        # This doesn't happen in a test script???
130        del self._plotter.axes.patches[-1]
131    axhspan.__doc__ = matplotlib.axes.Axes.axhspan.__doc__
132
133    def _axes_callback(self, axesfunc, *args, **kwargs):
134        panel = 0
135        if kwargs.has_key("panel"):
136            panel = kwargs.pop("panel")
137        coords = None
138        if kwargs.has_key("coords"):
139            coords = kwargs.pop("coords")
140            if coords.lower() == 'world':
141                kwargs["transform"] = self._plotter.axes.transData
142            elif coords.lower() == 'relative':
143                kwargs["transform"] = self._plotter.axes.transAxes
144        self._plotter.subplot(panel)
145        self._plotter.axes.set_autoscale_on(False)
146        getattr(self._plotter.axes, axesfunc)(*args, **kwargs)
147        self._plotter.show(False)
148        self._plotter.axes.set_autoscale_on(True)
149    # end matplotlib.axes fowarding functions
150
151    def set_mode(self, stacking=None, panelling=None):
152        """
153        Set the plots look and feel, i.e. what you want to see on the plot.
154        Parameters:
155            stacking:     tell the plotter which variable to plot
156                          as line colour overlays (default 'pol')
157            panelling:    tell the plotter which variable to plot
158                          across multiple panels (default 'scan'
159        Note:
160            Valid modes are:
161                 'beam' 'Beam' 'b':     Beams
162                 'if' 'IF' 'i':         IFs
163                 'pol' 'Pol' 'p':       Polarisations
164                 'scan' 'Scan' 's':     Scans
165                 'time' 'Time' 't':     Times
166        """
167        msg = "Invalid mode"
168        if not self.set_panelling(panelling) or \
169               not self.set_stacking(stacking):
170            if rcParams['verbose']:
171                print msg
172                return
173            else:
174                raise TypeError(msg)
175        if self._data: self.plot(self._data)
176        return
177
178    def set_panelling(self, what=None):
179        mode = what
180        if mode is None:
181             mode = rcParams['plotter.panelling']
182        md = self._translate(mode)
183        if md:
184            self._panelling = md
185            self._title = None
186            return True
187        return False
188
189    def set_layout(self,rows=None,cols=None):
190        """
191        Set the multi-panel layout, i.e. how many rows and columns plots
192        are visible.
193        Parameters:
194             rows:   The number of rows of plots
195             cols:   The number of columns of plots
196        Note:
197             If no argument is given, the potter reverts to its auto-plot
198             behaviour.
199        """
200        self._rows = rows
201        self._cols = cols
202        if self._data: self.plot(self._data)
203        return
204
205    def set_stacking(self, what=None):
206        mode = what
207        if mode is None:
208             mode = rcParams['plotter.stacking']
209        md = self._translate(mode)
210        if md:
211            self._stacking = md
212            self._lmap = None
213            return True
214        return False
215
216    def set_range(self,xstart=None,xend=None,ystart=None,yend=None):
217        """
218        Set the range of interest on the abcissa of the plot
219        Parameters:
220            [x,y]start,[x,y]end:  The start and end points of the 'zoom' window
221        Note:
222            These become non-sensical when the unit changes.
223            use plotter.set_range() without parameters to reset
224
225        """
226        if xstart is None and xend is None:
227            self._minmaxx = None
228        else:
229            self._minmaxx = [xstart,xend]
230        if ystart is None and yend is None:
231            self._minmaxy = None
232        else:
233            self._minmaxy = [ystart,yend]
234        if self._data: self.plot(self._data)
235        return
236
237    def set_legend(self, mp=None, fontsize = None, mode = 0):
238        """
239        Specify a mapping for the legend instead of using the default
240        indices:
241        Parameters:
242            mp:        a list of 'strings'. This should have the same length
243                       as the number of elements on the legend and then maps
244                       to the indeces in order. It is possible to uses latex
245                       math expression. These have to be enclosed in r'',
246                       e.g. r'$x^{2}$'
247            fontsize:  The font size of the label (default None)
248            mode:      where to display the legend
249                       Any other value for loc else disables the legend:
250                        0: auto
251                        1: upper right
252                        2: upper left
253                        3: lower left
254                        4: lower right
255                        5: right
256                        6: center left
257                        7: center right
258                        8: lower center
259                        9: upper center
260                        10: center
261
262        Example:
263             If the data has two IFs/rest frequencies with index 0 and 1
264             for CO and SiO:
265             plotter.set_stacking('i')
266             plotter.set_legend(['CO','SiO'])
267             plotter.plot()
268             plotter.set_legend([r'$^{12}CO$', r'SiO'])
269        """
270        self._lmap = mp
271        self._plotter.legend(mode)
272        if isinstance(fontsize, int):
273            from matplotlib import rc as rcp
274            rcp('legend', fontsize=fontsize)
275        if self._data:
276            self.plot(self._data)
277        return
278
279    def set_title(self, title=None, fontsize=None):
280        """
281        Set the title of the plot. If multiple panels are plotted,
282        multiple titles have to be specified.
283        Example:
284             # two panels are visible on the plotter
285             plotter.set_title(["First Panel","Second Panel"])
286        """
287        self._title = title
288        if isinstance(fontsize, int):
289            from matplotlib import rc as rcp
290            rcp('axes', titlesize=fontsize)
291        if self._data: self.plot(self._data)
292        return
293
294    def set_ordinate(self, ordinate=None, fontsize=None):
295        """
296        Set the y-axis label of the plot. If multiple panels are plotted,
297        multiple labels have to be specified.
298        Parameters:
299            ordinate:    a list of ordinate labels. None (default) let
300                         data determine the labels
301        Example:
302             # two panels are visible on the plotter
303             plotter.set_ordinate(["First Y-Axis","Second Y-Axis"])
304        """
305        self._ordinate = ordinate
306        if isinstance(fontsize, int):
307            from matplotlib import rc as rcp
308            rcp('axes', labelsize=fontsize)
309            rcp('ytick', labelsize=fontsize)
310        if self._data: self.plot(self._data)
311        return
312
313    def set_abcissa(self, abcissa=None, fontsize=None):
314        """
315        Set the x-axis label of the plot. If multiple panels are plotted,
316        multiple labels have to be specified.
317        Parameters:
318            abcissa:     a list of abcissa labels. None (default) let
319                         data determine the labels
320        Example:
321             # two panels are visible on the plotter
322             plotter.set_ordinate(["First X-Axis","Second X-Axis"])
323        """
324        self._abcissa = abcissa
325        if isinstance(fontsize, int):
326            from matplotlib import rc as rcp
327            rcp('axes', labelsize=fontsize)
328            rcp('xtick', labelsize=fontsize)
329        if self._data: self.plot(self._data)
330        return
331
332    def set_colors(self, colmap):
333        """
334        Set the colours to be used. The plotter will cycle through
335        these colours when lines are overlaid (stacking mode).
336        Parameters:
337            colmap:     a list of colour names
338        Example:
339             plotter.set_colors("red green blue")
340             # If for example four lines are overlaid e.g I Q U V
341             # 'I' will be 'red', 'Q' will be 'green', U will be 'blue'
342             # and 'V' will be 'red' again.
343        """
344        if isinstance(colmap,str):
345            colmap = colmap.split()
346        self._plotter.palette(0, colormap=colmap)
347        if self._data: self.plot(self._data)
348
349    # alias for english speakers
350    set_colours = set_colors
351
352    def set_histogram(self, hist=True, linewidth=None):
353        """
354        Enable/Disable histogram-like plotting.
355        Parameters:
356            hist:        True (default) or False. The fisrt default
357                         is taken from the .asaprc setting
358                         plotter.histogram
359        """
360        self._hist = hist
361        if isinstance(linewidth, float) or isinstance(linewidth, int):
362            from matplotlib import rc as rcp
363            rcp('lines', linewidth=linewidth)
364        if self._data: self.plot(self._data)
365
366    def set_linestyles(self, linestyles=None, linewidth=None):
367        """
368        Set the linestyles to be used. The plotter will cycle through
369        these linestyles when lines are overlaid (stacking mode) AND
370        only one color has been set.
371        Parameters:
372             linestyles:     a list of linestyles to use.
373                             'line', 'dashed', 'dotted', 'dashdot',
374                             'dashdotdot' and 'dashdashdot' are
375                             possible
376
377        Example:
378             plotter.set_colors("black")
379             plotter.set_linestyles("line dashed dotted dashdot")
380             # If for example four lines are overlaid e.g I Q U V
381             # 'I' will be 'solid', 'Q' will be 'dashed',
382             # U will be 'dotted' and 'V' will be 'dashdot'.
383        """
384        if isinstance(linestyles,str):
385            linestyles = linestyles.split()
386        self._plotter.palette(color=0,linestyle=0,linestyles=linestyles)
387        if isinstance(linewidth, float) or isinstance(linewidth, int):
388            from matplotlib import rc as rcp
389            rcp('lines', linewidth=linewidth)
390        if self._data: self.plot(self._data)
391
392    def set_font(self, family=None, style=None, weight=None, size=None):
393        """
394        Set font properties.
395        Parameters:
396            family:    one of 'sans-serif', 'serif', 'cursive', 'fantasy', 'monospace'
397            style:     one of 'normal' (or 'roman'), 'italic'  or 'oblique'
398            weight:    one of 'normal or 'bold'
399            size:      the 'general' font size, individual elements can be adjusted
400                       seperately
401        """
402        from matplotlib import rc as rcp
403        if isinstance(family, str):
404            rcp('font', family=family)
405        if isinstance(style, str):
406            rcp('font', style=style)
407        if isinstance(weight, str):
408            rcp('font', weight=weight)
409        if isinstance(size, float) or isinstance(size, int):
410            rcp('font', size=size)
411        if self._data: self.plot(self._data)
412
413    def plot_lines(self, linecat=None, doppler=0.0, deltachan=10, rotate=90.0,
414                   location=None):
415        """
416        Plot a line catalog.
417        Parameters:
418            linecat:      the linecatalog to plot
419            doppler:      the velocity shift to apply to the frequencies
420            deltachan:    the number of channels to include each side of the
421                          line to determine a local maximum/minimum
422            rotate:       the rotation (in degrees) )for the text label (default 90.0)
423            location:     the location of the line annotation from the 'top',
424                          'bottom' or alternate (None - the default)
425        Notes:
426        If the spectrum is flagged no line will be drawn in that location.
427        """
428        if not self._data:
429            raise RuntimeError("No scantable has been plotted yet.")
430        from asap._asap import linecatalog
431        if not isinstance(linecat, linecatalog):
432            raise ValueError("'linecat' isn't of type linecatalog.")
433        if not self._data.get_unit().endswith("Hz"):
434            raise RuntimeError("Can only overlay linecatalogs when data is in frequency.")
435        from matplotlib.numerix import ma
436        for j in range(len(self._plotter.subplots)):
437            self._plotter.subplot(j)
438            lims = self._plotter.axes.get_xlim()
439            for row in range(linecat.nrow()):
440                # get_frequency returns MHz
441                base = { "GHz": 1000.0, "MHz": 1.0, "Hz": 1.0e-6 }
442                restf = linecat.get_frequency(row)/base[self._data.get_unit()]
443                c = 299792.458
444                freq = restf*(1.0-doppler/c)
445                if lims[0] < freq < lims[1]:
446                    if location is None:
447                        loc = 'bottom'
448                        if row%2: loc='top'
449                    else: loc = location
450                    maxys = []
451                    for line in self._plotter.axes.lines:
452                        v = line._x
453                        asc = v[0] < v[-1]
454
455                        idx = None
456                        if not asc:
457                            if v[len(v)-1] <= freq <= v[0]:
458                                i = len(v)-1
459                                while i>=0 and v[i] < freq:
460                                    idx = i
461                                    i-=1
462                        else:
463                           if v[0] <= freq <= v[len(v)-1]:
464                                i = 0
465                                while  i<len(v) and v[i] < freq:
466                                    idx = i
467                                    i+=1
468                        if idx is not None:
469                            lower = idx - deltachan
470                            upper = idx + deltachan
471                            if lower < 0: lower = 0
472                            if upper > len(v): upper = len(v)
473                            s = slice(lower, upper)
474                            y = line._y[s]
475                            maxy = ma.maximum(y)
476                            if isinstance( maxy, float):
477                                maxys.append(maxy)
478                    if len(maxys):
479                        peak = max(maxys)
480                        if peak > self._plotter.axes.get_ylim()[1]:
481                            loc = 'bottom'
482                    else:
483                        continue
484                    self._plotter.vline_with_label(freq, peak,
485                                                   linecat.get_name(row),
486                                                   location=loc, rotate=rotate)
487        self._plotter.show(hardrefresh=False)
488
489
490    def save(self, filename=None, orientation=None, dpi=None):
491        """
492        Save the plot to a file. The know formats are 'png', 'ps', 'eps'.
493        Parameters:
494             filename:    The name of the output file. This is optional
495                          and autodetects the image format from the file
496                          suffix. If non filename is specified a file
497                          called 'yyyymmdd_hhmmss.png' is created in the
498                          current directory.
499             orientation: optional parameter for postscript only (not eps).
500                          'landscape', 'portrait' or None (default) are valid.
501                          If None is choosen for 'ps' output, the plot is
502                          automatically oriented to fill the page.
503             dpi:         The dpi of the output non-ps plot
504        """
505        self._plotter.save(filename,orientation,dpi)
506        return
507
508
509    def set_mask(self, mask=None, selection=None):
510        """
511        Set a plotting mask for a specific polarization.
512        This is useful for masking out "noise" Pangle outside a source.
513        Parameters:
514             mask:           a mask from scantable.create_mask
515             selection:      the spectra to apply the mask to.
516        Example:
517             select = selector()
518             select.setpolstrings("Pangle")
519             plotter.set_mask(mymask, select)
520        """
521        if not self._data:
522            msg = "Can only set mask after a first call to plot()"
523            if rcParams['verbose']:
524                print msg
525                return
526            else:
527                raise RuntimeError(msg)
528        if len(mask):
529            if isinstance(mask, list) or isinstance(mask, tuple):
530                self._usermask = array(mask)
531            else:
532                self._usermask = mask
533        if mask is None and selection is None:
534            self._usermask = []
535            self._maskselection = None
536        if isinstance(selection, selector):
537            self._maskselection = {'b': selection.get_beams(),
538                                   's': selection.get_scans(),
539                                   'i': selection.get_ifs(),
540                                   'p': selection.get_pols(),
541                                   't': [] }
542        else:
543            self._maskselection = None
544        self.plot(self._data)
545
546    def _slice_indeces(self, data):
547        mn = self._minmaxx[0]
548        mx = self._minmaxx[1]
549        asc = data[0] < data[-1]
550        start=0
551        end = len(data)-1
552        inc = 1
553        if not asc:
554            start = len(data)-1
555            end = 0
556            inc = -1
557        # find min index
558        while start > 0 and data[start] < mn:
559            start+= inc
560        # find max index
561        while end > 0 and data[end] > mx:
562            end-=inc
563        if end > 0: end +=1
564        if start > end:
565            return end,start
566        return start,end
567
568    def _reset(self):
569        self._usermask = []
570        self._usermaskspectra = None
571        self.set_selection(None, False)
572
573    def _plot(self, scan):
574        savesel = scan.get_selection()
575        sel = savesel +  self._selection
576        d0 = {'s': 'SCANNO', 'b': 'BEAMNO', 'i':'IFNO',
577              'p': 'POLNO', 'c': 'CYCLENO', 't' : 'TIME' }
578        order = [d0[self._panelling],d0[self._stacking]]
579        sel.set_order(order)
580        scan.set_selection(sel)
581        d = {'b': scan.getbeam, 's': scan.getscan,
582             'i': scan.getif, 'p': scan.getpol, 't': scan._gettime }
583
584        polmodes = dict(zip(self._selection.get_pols(),
585                            self._selection.get_poltypes()))
586        # this returns either a tuple of numbers or a length  (ncycles)
587        # convert this into lengths
588        n0,nstack0 = self._get_selected_n(scan)
589        if isinstance(n0, int): n = n0
590        else: n = len(n0)
591        if isinstance(nstack0, int): nstack = nstack0
592        else: nstack = len(nstack0)
593        maxpanel, maxstack = 16,8
594        if n > maxpanel or nstack > maxstack:
595            from asap import asaplog
596            maxn = 0
597            if nstack > maxstack: maxn = maxstack
598            if n > maxpanel: maxn = maxpanel
599            msg ="Scan to be plotted contains more than %d selections.\n" \
600                  "Selecting first %d selections..." % (maxn, maxn)
601            asaplog.push(msg)
602            print_log()
603            n = min(n,maxpanel)
604            nstack = min(nstack,maxstack)
605        if n > 1:
606            ganged = rcParams['plotter.ganged']
607            ###Start Mod: 2008.09.22 kana ###
608            if self._panelling == 'i':
609                ganged = False
610            ###End Mod#######################
611            if self._rows and self._cols:
612                n = min(n,self._rows*self._cols)
613                self._plotter.set_panels(rows=self._rows,cols=self._cols,
614                                         nplots=n,ganged=ganged)
615            else:
616                self._plotter.set_panels(rows=n,cols=0,nplots=n,ganged=ganged)
617        else:
618            self._plotter.set_panels()
619        r=0
620        nr = scan.nrow()
621        a0,b0 = -1,-1
622        allxlim = []
623        allylim = []
624        newpanel=True
625        panelcount,stackcount = 0,0
626        while r < nr:
627            a = d[self._panelling](r)
628            b = d[self._stacking](r)
629            if a > a0 and panelcount < n:
630                if n > 1:
631                    self._plotter.subplot(panelcount)
632                self._plotter.palette(0)
633                #title
634                xlab = self._abcissa and self._abcissa[panelcount] \
635                       or scan._getabcissalabel()
636                ylab = self._ordinate and self._ordinate[panelcount] \
637                       or scan._get_ordinate_label()
638                self._plotter.set_axes('xlabel',xlab)
639                self._plotter.set_axes('ylabel',ylab)
640                lbl = self._get_label(scan, r, self._panelling, self._title)
641                if isinstance(lbl, list) or isinstance(lbl, tuple):
642                    if 0 <= panelcount < len(lbl):
643                        lbl = lbl[panelcount]
644                    else:
645                        # get default label
646                        lbl = self._get_label(scan, r, self._panelling, None)
647                self._plotter.set_axes('title',lbl)
648                newpanel = True
649                stackcount =0
650                panelcount += 1
651            if (b > b0 or newpanel) and stackcount < nstack:
652                y = []
653                if len(polmodes):
654                    y = scan._getspectrum(r, polmodes[scan.getpol(r)])
655                else:
656                    y = scan._getspectrum(r)
657                m = scan._getmask(r)
658                from matplotlib.numerix import logical_not, logical_and
659                if self._maskselection and len(self._usermask) == len(m):
660                    if d[self._stacking](r) in self._maskselection[self._stacking]:
661                        m = logical_and(m, self._usermask)
662                x = scan._getabcissa(r)
663                from matplotlib.numerix import ma, array
664                y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
665                if self._minmaxx is not None:
666                    s,e = self._slice_indeces(x)
667                    x = x[s:e]
668                    y = y[s:e]
669                if len(x) > 1024 and rcParams['plotter.decimate']:
670                    fac = len(x)/1024
671                    x = x[::fac]
672                    y = y[::fac]
673                llbl = self._get_label(scan, r, self._stacking, self._lmap)
674                if isinstance(llbl, list) or isinstance(llbl, tuple):
675                    if 0 <= stackcount < len(llbl):
676                        # use user label
677                        llbl = llbl[stackcount]
678                    else:
679                        # get default label
680                        llbl = self._get_label(scan, r, self._stacking, None)
681                self._plotter.set_line(label=llbl)
682                plotit = self._plotter.plot
683                if self._hist: plotit = self._plotter.hist
684                if len(x) > 0:
685                    plotit(x,y)
686                    xlim= self._minmaxx or [min(x),max(x)]
687                    allxlim += xlim
688                    ylim= self._minmaxy or [ma.minimum(y),ma.maximum(y)]
689                    allylim += ylim
690                stackcount += 1
691                # last in colour stack -> autoscale x
692                if stackcount == nstack:
693                    allxlim.sort()
694                    ###Start Mod: 2008.09.22 kana ###
695                    #self._plotter.axes.set_xlim([allxlim[0],allxlim[-1]])
696                    self._plotter.subplots[panelcount-1]['axes'].set_xlim([allxlim[0],allxlim[-1]])
697                    ###End Mod#######################
698                    # clear
699                    allxlim =[]
700
701            newpanel = False
702            a0=a
703            b0=b
704            # ignore following rows
705            if (panelcount == n) and (stackcount == nstack):
706                # last panel -> autoscale y if ganged
707                if rcParams['plotter.ganged']:
708                    allylim.sort()
709                    self._plotter.set_limits(ylim=[allylim[0],allylim[-1]])
710                break
711            r+=1 # next row
712        #reset the selector to the scantable's original
713        scan.set_selection(savesel)
714
715    def set_selection(self, selection=None, refresh=True):
716        self._selection = isinstance(selection,selector) and selection or selector()
717        d0 = {'s': 'SCANNO', 'b': 'BEAMNO', 'i':'IFNO',
718              'p': 'POLNO', 'c': 'CYCLENO', 't' : 'TIME' }
719        order = [d0[self._panelling],d0[self._stacking]]
720        self._selection.set_order(order)
721        if self._data and refresh: self.plot(self._data)
722
723    def _get_selected_n(self, scan):
724        d1 = {'b': scan.getbeamnos, 's': scan.getscannos,
725             'i': scan.getifnos, 'p': scan.getpolnos, 't': scan.ncycle }
726        d2 = { 'b': self._selection.get_beams(),
727               's': self._selection.get_scans(),
728               'i': self._selection.get_ifs(),
729               'p': self._selection.get_pols(),
730               't': self._selection.get_cycles() }
731        n =  d2[self._panelling] or d1[self._panelling]()
732        nstack = d2[self._stacking] or d1[self._stacking]()
733        return n,nstack
734
735    def _get_label(self, scan, row, mode, userlabel=None):
736        if isinstance(userlabel, list) and len(userlabel) == 0:
737            userlabel = " "
738        pms = dict(zip(self._selection.get_pols(),self._selection.get_poltypes()))
739        if len(pms):
740            poleval = scan._getpollabel(scan.getpol(row),pms[scan.getpol(row)])
741        else:
742            poleval = scan._getpollabel(scan.getpol(row),scan.poltype())
743        d = {'b': "Beam "+str(scan.getbeam(row)),
744             's': scan._getsourcename(row),
745             'i': "IF"+str(scan.getif(row)),
746             'p': poleval,
747             't': str(scan.get_time(row)) }
748        return userlabel or d[mode]
749
750    def plotazel(self, scan=None, outfile=None):
751        """
752        plot azimuth and elevation  versus time of a scantable
753        """
754        import pylab as PL
755        from matplotlib.dates import DateFormatter, timezone, HourLocator, MinuteLocator, DayLocator
756        from matplotlib.ticker import MultipleLocator
757        from matplotlib.numerix import array, pi
758        self._data = scan
759        self._outfile = outfile
760        dates = self._data.get_time(asdatetime=True)
761        t = PL.date2num(dates)
762        tz = timezone('UTC')
763        PL.cla()
764        #PL.ioff()
765        PL.clf()
766        tdel = max(t) - min(t)
767        ax = PL.subplot(2,1,1)
768        el = array(self._data.get_elevation())*180./pi
769        PL.ylabel('El [deg.]')
770        dstr = dates[0].strftime('%Y/%m/%d')
771        if tdel > 1.0:
772            dstr2 = dates[len(dates)-1].strftime('%Y/%m/%d')
773            dstr = dstr + " - " + dstr2
774            majloc = DayLocator()
775            minloc = HourLocator(range(0,23,12))
776            timefmt = DateFormatter("%b%d")
777        else:
778            timefmt = DateFormatter('%H')
779            majloc = HourLocator()
780            minloc = MinuteLocator(20)
781        PL.title(dstr)
782
783        if tdel == 0.0:
784            th = (t - PL.floor(t))*24.0
785            PL.plot(th,el,'o',markersize=2, markerfacecolor='b', markeredgecolor='b')
786        else:
787            PL.plot_date(t,el,'o', markersize=2, markerfacecolor='b', markeredgecolor='b',tz=tz)
788            #ax.grid(True)
789            ax.xaxis.set_major_formatter(timefmt)
790            ax.xaxis.set_major_locator(majloc)
791            ax.xaxis.set_minor_locator(minloc)
792        ax.yaxis.grid(True)
793        yloc = MultipleLocator(30)
794        ax.set_ylim(0,90)
795        ax.yaxis.set_major_locator(yloc)
796        if tdel > 1.0:
797            labels = ax.get_xticklabels()
798        #    PL.setp(labels, fontsize=10, rotation=45)
799            PL.setp(labels, fontsize=10)
800
801        # Az plot
802        az = array(self._data.get_azimuth())*180./pi
803        if min(az) < 0:
804            for irow in range(len(az)):
805                if az[irow] < 0: az[irow] += 360.0
806
807        ax = PL.subplot(2,1,2)
808        #PL.xlabel('Time (UT [hour])')
809        PL.ylabel('Az [deg.]')
810        if tdel == 0.0:
811            PL.plot(th,az,'o',markersize=2, markeredgecolor='b',markerfacecolor='b')
812        else:
813            PL.plot_date(t,az,'o', markersize=2,markeredgecolor='b',markerfacecolor='b',tz=tz)
814            ax.xaxis.set_major_formatter(timefmt)
815            ax.xaxis.set_major_locator(majloc)
816            ax.xaxis.set_minor_locator(minloc)
817        #ax.grid(True)
818        ax.set_ylim(0,360)
819        ax.yaxis.grid(True)
820        #hfmt = DateFormatter('%H')
821        #hloc = HourLocator()
822        yloc = MultipleLocator(60)
823        ax.yaxis.set_major_locator(yloc)
824        if tdel > 1.0:
825            labels = ax.get_xticklabels()
826            PL.setp(labels, fontsize=10)
827            PL.xlabel('Time (UT [day])')
828        else:
829            PL.xlabel('Time (UT [hour])')
830
831        #PL.ion()
832        PL.draw()
833        if (self._outfile is not None):
834           PL.savefig(self._outfile)
835
836    def plotpointing(self, scan=None, outfile=None):
837        """
838        plot telescope pointings
839        """
840        import pylab as PL
841        from matplotlib.dates import DateFormatter, timezone
842        from matplotlib.ticker import MultipleLocator
843        from matplotlib.numerix import array, pi, zeros
844        self._data = scan
845        self._outfile = outfile
846        dir = array(self._data.get_directionval()).transpose()
847        ra = dir[0]*180./pi
848        dec = dir[1]*180./pi
849        PL.cla()
850        #PL.ioff()
851        PL.clf()
852        ax = PL.axes([0.1,0.1,0.8,0.8])
853        ax = PL.axes([0.1,0.1,0.8,0.8])
854        ax.set_aspect('equal')
855        PL.plot(ra,dec, 'b,')
856        PL.xlabel('RA [deg.]')
857        PL.ylabel('Declination [deg.]')
858        PL.title('Telescope pointings')
859        [xmin,xmax,ymin,ymax] = PL.axis()
860        PL.axis([xmax,xmin,ymin,ymax])
861        #PL.ion()
862        PL.draw()
863        if (self._outfile is not None):
864           PL.savefig(self._outfile)
865
866    # plot total power data
867    # plotting in time is not yet implemented..
868    def plottp(self, scan=None, outfile=None):
869        if self._plotter.is_dead:
870            self._plotter = self._newplotter()
871        self._plotter.hold()
872        self._plotter.clear()
873        from asap import scantable
874        if not self._data and not scan:
875            msg = "Input is not a scantable"
876            if rcParams['verbose']:
877                print msg
878                return
879            raise TypeError(msg)
880        if isinstance(scan, scantable):
881            if self._data is not None:
882                if scan != self._data:
883                    self._data = scan
884                    # reset
885                    self._reset()
886            else:
887                self._data = scan
888                self._reset()
889        # ranges become invalid when abcissa changes?
890        #if self._abcunit and self._abcunit != self._data.get_unit():
891        #    self._minmaxx = None
892        #    self._minmaxy = None
893        #    self._abcunit = self._data.get_unit()
894        #    self._datamask = None
895        self._plottp(self._data)
896        if self._minmaxy is not None:
897            self._plotter.set_limits(ylim=self._minmaxy)
898        self._plotter.release()
899        self._plotter.tidy()
900        self._plotter.show(hardrefresh=False)
901        print_log()
902        return
903
904    def _plottp(self,scan):
905        """
906        private method for plotting total power data
907        """
908        from matplotlib.numerix import ma, array, arange, logical_not
909        r=0
910        nr = scan.nrow()
911        a0,b0 = -1,-1
912        allxlim = []
913        allylim = []
914        y=[]
915        self._plotter.set_panels()
916        self._plotter.palette(0)
917        #title
918        #xlab = self._abcissa and self._abcissa[panelcount] \
919        #       or scan._getabcissalabel()
920        #ylab = self._ordinate and self._ordinate[panelcount] \
921        #       or scan._get_ordinate_label()
922        xlab = self._abcissa or 'row number' #or Time
923        ylab = self._ordinate or scan._get_ordinate_label()
924        self._plotter.set_axes('xlabel',xlab)
925        self._plotter.set_axes('ylabel',ylab)
926        lbl = self._get_label(scan, r, 's', self._title)
927        if isinstance(lbl, list) or isinstance(lbl, tuple):
928        #    if 0 <= panelcount < len(lbl):
929        #        lbl = lbl[panelcount]
930        #    else:
931                # get default label
932             lbl = self._get_label(scan, r, self._panelling, None)
933        self._plotter.set_axes('title',lbl)
934        y=array(scan._get_column(scan._getspectrum,-1))
935        m = array(scan._get_column(scan._getmask,-1))
936        y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
937        x = arange(len(y))
938        # try to handle spectral data somewhat...
939        l,m = y.shape
940        if m > 1:
941            y=y.mean(axis=1)
942        plotit = self._plotter.plot
943        llbl = self._get_label(scan, r, self._stacking, None)
944        self._plotter.set_line(label=llbl)
945        if len(x) > 0:
946            plotit(x,y)
947
948
949    # forwards to matplotlib.Figure.text
950    def figtext(self, *args, **kwargs):
951        """
952        Add text to figure at location x,y (relative 0-1 coords).
953        This method forwards *args and **kwargs to a Matplotlib method,
954        matplotlib.Figure.text.
955        See the method help for detailed information.
956        """
957        self._plotter.text(*args, **kwargs)
958    # end matplotlib.Figure.text forwarding function
959
Note: See TracBrowser for help on using the repository browser.