source: branches/Release-1-fixes/python/asapplotter.py @ 601

Last change on this file since 601 was 601, checked in by mar637, 19 years ago

Fixed asap00015, extracted pol_lablelling into separate function

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.7 KB
Line 
1from asap.asaplot import ASAPlot
2from asap import rcParams
3
4class asapplotter:
5    """
6    The ASAP plotter.
7    By default the plotter is set up to plot polarisations
8    'colour stacked' and scantables across panels.
9    Note:
10        Currenly it only plots 'spectra' not Tsys or
11        other variables.
12    """
13    def __init__(self):
14        self._plotter = ASAPlot()
15
16        self._tdict = {'Time':'t','time':'t','t':'t','T':'t'}
17        self._bdict = {'Beam':'b','beam':'b','b':'b','B':'b'}
18        self._idict = {'IF':'i','if':'i','i':'i','I':'i'}
19        self._pdict = {'Pol':'p','pol':'p','p':'p'}
20        self._sdict = {'scan':'s','Scan':'s','s':'s','S':'s'}
21        self._cdict = {'t':'len(self._cursor["t"])',
22                       'b':'len(self._cursor["b"])',
23                       'i':'len(self._cursor["i"])',
24                       'p':'len(self._cursor["p"])',
25                       's':'len(scans)'}
26        self._ldict = {'b':'Beam',
27                       'i':'IF',
28                       'p':'Pol',
29                       's':'Scan'}
30        self._dicts = [self._tdict,self._bdict,
31                       self._idict,self._pdict,
32                       self._sdict]
33        self._panelling = None
34        self._stacking = None
35        self.set_panelling()
36        self.set_stacking()
37        self._rows = None
38        self._cols = None
39        self._autoplot = False
40        self._minmaxx = None
41        self._minmaxy = None
42        self._data = None
43        self._lmap = []
44        self._title = None
45        self._ordinate = None
46        self._abcissa = None
47        self._cursor = {'t':None, 'b':None,
48                        'i':None, 'p':None
49                        }
50
51    def _translate(self, name):
52        for d in self._dicts:
53            if d.has_key(name):
54                return d[name]
55        return None
56       
57    def plot(self, *args):
58        """
59        Plot a (list of) scantables.
60        Parameters:
61            one or more comma separated scantables
62        Note:
63            If a (list) of scantables 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 scantables
66            are consistent e.g. all 'channel' or all 'velocity' etc.
67        """
68        if self._plotter.is_dead:
69            self._plotter = ASAPlot()
70        self._plotter.hold()
71        self._plotter.clear()
72        if len(args) > 0:
73            if self._data is not None:               
74                if list(args) != self._data:
75                    self._data = list(args)
76                    # reset cursor
77                    self.set_cursor(refresh=False)
78            else:
79                self._data = list(args)
80                self.set_cursor(refresh=False)
81        if self._panelling == 't':
82            maxrows = 9
83            if self._data[0].nrow() > maxrows:
84                if self._cursor["t"] is None or \
85                       (isinstance(self._cursor["t"],list) and \
86                        len(self._cursor["t"]) > maxrows ):
87                    print "Scan to be plotted contains more than %d rows.\n" \
88                          "Selecting first %d rows..." % (maxrows,maxrows)
89                    self._cursor["t"] = range(maxrows)
90            self._plot_time(self._data[0], self._stacking)
91        elif self._panelling == 's':
92            self._plot_scans(self._data, self._stacking)
93        else:
94            self._plot_other(self._data, self._stacking)
95        if self._minmaxx is not None or self._minmaxy is not None:
96            self._plotter.set_limits(xlim=self._minmaxx,ylim=self._minmaxy)
97        self._plotter.release()
98        return
99
100    def _plot_time(self, scan, colmode):
101        if colmode == 't':
102            return
103        n = len(self._cursor["t"])
104        cdict = {'b':'scan.setbeam(j)',
105                 'i':'scan.setif(j)',
106                 'p':'scan.setpol(j)'}
107        cdict2 = {'b':'self._cursor["b"]',
108                  'i':'self._cursor["i"]',
109                  'p':'self._cursor["p"]'}
110        ncol = 1
111        if self._stacking is not None:
112            ncol = eval(self._cdict.get(colmode))
113        if n > 1:
114            if self._rows and self._cols:
115                n = min(n,self._rows*self._cols)
116                self._plotter.set_panels(rows=self._rows,cols=self._cols,
117                                         nplots=n)
118            else:
119                self._plotter.set_panels(rows=n,cols=0,nplots=n)
120        else:
121            self._plotter.set_panels()
122        rows = self._cursor["t"]
123        self._plotter.palette(1)
124        for rowsel in rows:
125            i = self._cursor["t"].index(rowsel)
126            if n > 1:
127                self._plotter.palette(1)
128                self._plotter.subplot(i)
129            colvals = eval(cdict2.get(colmode))
130            for j in colvals:
131                polmode = "raw"
132                jj = colvals.index(j)
133                savej = j
134                for k in cdict.keys():
135                    sel = eval(cdict2.get(k))                   
136                    j = sel[0]
137                    if k == "p":
138                        which = self._cursor["p"].index(j)
139                        polmode = self._polmode[which]
140                        j = which
141                    eval(cdict.get(k))
142                j = savej
143                if colmode == "p":
144                    polmode = self._polmode[self._cursor["p"].index(j)]
145                    j = jj
146                eval(cdict.get(colmode))
147                x = None
148                y = None
149                m = None
150                if not self._title:
151                    tlab = scan._getsourcename(rowsel)                   
152                else:
153                    if len(self._title) == n:
154                        tlab = self._title[rowsel]
155                    else:
156                        tlab = scan._getsourcename(rowsel)
157                x,xlab = scan.get_abcissa(rowsel)
158                if self._abcissa: xlab = self._abcissa
159                y = None
160                if polmode == "stokes":
161                    y = scan._getstokesspectrum(rowsel)
162                elif polmode == "stokes2":
163                    y = scan._getstokesspectrum(rowsel,True)
164                elif polmode == "circular":
165                    y = scan._stokestopolspectrum(rowsel,False,-1)
166                else:
167                    y = scan._getspectrum(rowsel)
168                if self._ordinate:
169                    ylab = self._ordinate
170                else:
171                    ylab = 'Flux ('+scan.get_fluxunit()+')'
172                m = scan._getmask(rowsel)
173                if self._lmap and len(self._lmap) > 0:
174                    llab = self._lmap[jj]
175                else:
176                    if colmode == 'p':
177                        llab = self._get_pollabel(scan, polmode)
178                    else:                   
179                        llab = self._ldict.get(colmode)+' '+str(j)
180                self._plotter.set_line(label=llab)
181                self._plotter.plot(x,y,m)
182                xlim=[min(x),max(x)]
183                self._plotter.axes.set_xlim(xlim)
184            self._plotter.set_axes('xlabel',xlab)
185            self._plotter.set_axes('ylabel',ylab)
186            self._plotter.set_axes('title',tlab)           
187        return
188
189    def _plot_scans(self, scans, colmode):
190        print "Can only plot one row per scan."
191        if colmode == 's':
192            return
193        cdict = {'b':'scan.setbeam(j)',
194                 'i':'scan.setif(j)',
195                 'p':'scan.setpol(j)'}
196        cdict2 = {'b':'self._cursor["b"]',
197                  'i':'self._cursor["i"]',
198                  'p':'self._cursor["p"]'}
199       
200        n = len(scans)
201        ncol = 1
202        if self._stacking is not None:
203            scan = scans[0]
204            ncol = eval(self._cdict.get(colmode))
205        if n > 1:
206            if self._rows and self._cols:
207                n = min(n,self._rows*self._cols)
208                self._plotter.set_panel(rows=self._rows,cols=self._cols,
209                                         nplots=n)
210            else:
211                self._plotter.set_panel(rows=n,cols=0,nplots=n)
212        else:
213            self._plotter.set_panels()
214        for scan in scans:
215            self._plotter.palette(1)
216            if n > 1:
217                self._plotter.subplot(scans.index(scan))
218                self._plotter.palette(1)
219            colvals = eval(cdict2.get(colmode))
220            rowsel = self._cursor["t"][0]
221            for j in colvals:
222                polmode = "raw"
223                jj = colvals.index(j)
224                savej = j
225                for k in cdict.keys():
226                    sel = eval(cdict2.get(k))                   
227                    j = sel[0]
228                    eval(cdict.get(k))
229                    if k == "p":
230                        which = self._cursor["p"].index(j)
231                        polmode = self._polmode[which]
232                        j = which
233                j = savej
234                if colmode == "p":
235                    polmode = self._polmode[self._cursor["p"].index(j)]
236                    j = jj
237                eval(cdict.get(colmode))
238                x = None
239                y = None
240                m = None
241                tlab = self._title
242                if not self._title:
243                    tlab = scan._getsourcename(rowsel)
244                x,xlab = scan.get_abcissa(rowsel)
245                if self._abcissa: xlab = self._abcissa
246                if polmode == "stokes":
247                    y = scan._getstokesspectrum(rowsel)
248                elif polmode == "stokes2":
249                    y = scan._getstokesspectrum(rowsel,True)
250                elif polmode == "circular":
251                    y = scan._stokestopolspectrum(rowsel,False,-1)
252                else:
253                    y = scan._getspectrum(rowsel)
254                if self._ordinate:
255                    ylab = self._ordinate
256                else:
257                    ylab = 'Flux ('+scan.get_fluxunit()+')'
258                m = scan._getmask(rowsel)
259                if self._lmap and len(self._lmap) > 0:
260                    llab = self._lmap[jj]
261                else:
262                    if colmode == 'p':
263                        llab = self._get_pollabel(scan, polmode)
264                    else:
265                        llab = self._ldict.get(colmode)+' '+str(j)
266                self._plotter.set_line(label=llab)
267                self._plotter.plot(x,y,m)
268                xlim=[min(x),max(x)]
269                self._plotter.axes.set_xlim(xlim)
270
271            self._plotter.set_axes('xlabel',xlab)
272            self._plotter.set_axes('ylabel',ylab)
273            self._plotter.set_axes('title',tlab)
274        return
275   
276    def _plot_other(self,scans,colmode):
277        if colmode == self._panelling:
278            return
279        cdict = {'b':'scan.setbeam(i)',
280                 'i':'scan.setif(i)',
281                 'p':'scan.setpol(i)'}
282        cdict2 = {'b':'self._cursor["b"]',
283                  'i':'self._cursor["i"]',
284                  'p':'self._cursor["p"]',
285                  's': 'scans',
286                  't': 'self._cursor["t"]'}
287        scan = scans[0]
288        n = eval(self._cdict.get(self._panelling))
289        ncol=1
290        if self._stacking is not None:           
291            ncol = eval(self._cdict.get(colmode))
292        if n > 1:
293            if self._rows and self._cols:
294                n = min(n,self._rows*self._cols)
295                self._plotter.set_panels(rows=self._rows,cols=self._cols,
296                                         nplots=n)
297            else:
298                self._plotter.set_panels(rows=n,cols=0,nplots=n)
299        else:
300            self._plotter.set_panels()           
301        panels = self._cursor[self._panelling]       
302        for i in panels:
303            self._plotter.palette(1)
304            polmode = "raw"
305            ii = self._cursor[self._panelling].index(i)
306            if n>1:
307                self._plotter.subplot(ii)
308            if self._panelling == "p":
309                polmode = self._polmode[ii]
310                eval(cdict.get(self._panelling))
311            else:
312                eval(cdict.get(self._panelling))
313            colvals = eval(cdict2.get(colmode))
314            for j in colvals:
315                rowsel = self._cursor["t"][0]
316                jj = colvals.index(j)
317                savei = i
318                for k in cdict.keys():
319                    if k != self._panelling:
320                        sel = eval(cdict2.get(k))
321                        i = sel[0]
322                        if k == "p":
323                            which = self._cursor["p"].index(i)
324                            polmode = self._polmode[which]
325                            i = which                       
326                        eval(cdict.get(k))
327                i = savei
328                if colmode == 's':
329                    scan = j
330                elif colmode == 't':
331                    rowsel = j                   
332                else:
333                    savei = i
334                    if colmode == 'p':
335                        polmode = self._polmode[self._cursor["p"].index(j)]
336                    i = j
337                    eval(cdict.get(colmode))
338                    i = savei
339                x = None
340                y = None
341                m = None
342                x,xlab = scan.get_abcissa(rowsel)
343                if self._abcissa: xlab = self._abcissa
344                if polmode == "stokes":
345                    y = scan._getstokesspectrum(rowsel)
346                elif polmode == "stokes2":
347                    y = scan._getstokesspectrum(rowsel,True)
348                elif polmode == "circular":
349                    y = scan._stokestopolspectrum(rowsel,False,-1)
350                else:
351                    y = scan._getspectrum(rowsel)
352
353                if self._ordinate:
354                    ylab = self._ordinate
355                else:
356                    ylab = 'Flux ('+scan.get_fluxunit()+')'
357                m = scan._getmask(rowsel)
358                if colmode == 's' or colmode == 't':
359                    if self._title and len(self._title) > 0:
360                        tlab = self._title[ii]
361                    else:                       
362                        tlab = self._ldict.get(self._panelling)+' '+str(i)
363                    llab = scan._getsourcename(rowsel)
364                else:
365                    if self._title and len(self._title) > 0:
366                        tlab = self._title[ii]
367                    else:
368                        if self._panelling == 'p':
369                            tlab = self._get_pollabel(scan, polmode)
370                        else:
371                            tlab = self._ldict.get(self._panelling)+' '+str(i)
372                    if self._lmap and len(self._lmap) > 0:
373                        llab = self._lmap[jj]
374                    else:
375                        if colmode == 'p':
376                            llab = self._get_pollabel(scan, polmode)
377                        else:
378                            llab = self._ldict.get(colmode)+' '+str(j)
379                self._plotter.set_line(label=llab)
380                self._plotter.plot(x,y,m)
381                xlim=[min(x),max(x)]
382                self._plotter.axes.set_xlim(xlim)
383
384            self._plotter.set_axes('xlabel',xlab)
385            self._plotter.set_axes('ylabel',ylab)
386            self._plotter.set_axes('title',tlab)
387       
388        return
389
390
391    def set_mode(self, stacking=None, panelling=None):
392        """
393        Set the plots look and feel, i.e. what you want to see on the plot.
394        Parameters:
395            stacking:     tell the plotter which variable to plot
396                          as line colour overlays (default 'pol')
397            panelling:    tell the plotter which variable to plot
398                          across multiple panels (default 'scan'
399        Note:
400            Valid modes are:
401                 'beam' 'Beam' 'b':     Beams
402                 'if' 'IF' 'i':         IFs
403                 'pol' 'Pol' 'p':       Polarisations
404                 'scan' 'Scan' 's':     Scans
405                 'time' 'Time' 't':     Times
406        """
407        if not self.set_panelling(panelling):
408            print "Invalid mode"
409            return
410        if not self.set_stacking(stacking):
411            print "Invalid mode"
412            return
413        if self._data: self.plot()
414        return
415
416    def set_panelling(self, what=None):
417        mode = what
418        if mode is None:
419             mode = rcParams['plotter.panelling']
420        md = self._translate(mode)
421        if md:
422            self._panelling = md
423            self._title = None
424            return True
425        return False
426
427    def set_layout(self,rows=None,cols=None):
428        """
429        Set the multi-panel layout, i.e. how many rows and columns plots
430        are visible.
431        Parameters:
432             rows:   The number of rows of plots
433             cols:   The number of columns of plots
434        Note:
435             If no argument is given, the potter reverts to its auto-plot
436             behaviour.
437        """
438        self._rows = rows
439        self._cols = cols
440        if self._data: self.plot()
441        return
442
443    def set_stacking(self, what=None): 
444        mode = what
445        if mode is None:           
446             mode = rcParams['plotter.stacking']       
447        md = self._translate(mode)
448        if md:
449            self._stacking = md
450            self._lmap = None
451            return True
452        return False
453
454    def set_range(self,xstart=None,xend=None,ystart=None,yend=None):
455        """
456        Set the range of interest on the abcissa of the plot
457        Parameters:
458            [x,y]start,[x,y]end:  The start and end points of the 'zoom' window
459        Note:
460            These become non-sensical when the unit changes.
461            use plotter.set_range() without parameters to reset
462
463        """
464        if xstart is None and xend is None:
465            self._minmaxx = None
466        else:
467            self._minmaxx = [xstart,xend]
468        if ystart is None and yend is None:
469            self._minmaxy = None
470        else:
471            self._minmaxy = [ystart,yend]           
472        if self._data: self.plot()
473        return
474   
475    def set_legend(self, mp=None):
476        """
477        Specify a mapping for the legend instead of using the default
478        indices:
479        Parameters:
480             mp:    a list of 'strings'. This should have the same length
481                    as the number of elements on the legend and then maps
482                    to the indeces in order
483
484        Example:
485             If the data has two IFs/rest frequencies with index 0 and 1
486             for CO and SiO:
487             plotter.set_stacking('i')
488             plotter.set_legend_map(['CO','SiO'])
489             plotter.plot()
490        """
491        self._lmap = mp
492        if self._data: self.plot()
493        return
494
495    def set_title(self, title=None):
496        self._title = title
497        if self._data: self.plot()
498        return
499
500    def set_ordinate(self, ordinate=None):
501        self._ordinate = ordinate
502        if self._data: self.plot()
503        return
504
505    def set_abcissa(self, abcissa=None):
506        self._abcissa = abcissa
507        if self._data: self.plot()
508        return
509
510    def save(self, filename=None):
511        """
512        Save the plot to a file. The know formats are 'png', 'ps', 'eps'.
513        Parameters:
514             filename:    The name of the output file. This is optional
515                          and autodetects the image format from the file
516                          suffix. If non filename is specified a file
517                          called 'yyyymmdd_hhmmss.png' is created in the
518                          current directory.
519        """
520        self._plotter.save(filename)
521        return
522   
523    def set_cursor(self, row=None,beam=None,IF=None,pol=None, refresh=True):
524        """
525        Specify a 'cursor' for plotting selected spectra. Time (rows),
526        Beam, IF, Polarisation ranges can be specified.
527        Parameters:
528            Default for all paramaters is to select all available
529            row:    selects the rows (time stamps) to be plotted, this has
530                    to be a vector of row indices, e.g. row=[0,2,5] or row=[2]
531            beam:   select a range of beams
532            IF:     select a range of IFs
533            pol:    select Polarisations for plotting these can be by index
534                    (raw polarisations (default)) or by names any of:
535                    ["I", "Q", "U", "V"] or
536                    ["I", "Plinear", "Pangle", "V"] or
537                    ["XX", "YY", "Real(XY)", "Imag(XY)"] or
538                    ["RR", "LL"]
539        Example:
540            plotter.set_mode('pol','time')
541            plotter.plot(myscan) # plots all raw polarisations colour stacked
542            plotter.set_cursor(pol=["I"]) # plot "I" only for all rows
543            # plot "I" only for two time stamps row=0 and row=2
544            plotter.set_cursor(row=[0,2],pol=["I"])
545
546        Note:
547            Be careful to select only exisiting polarisations.           
548        """
549        if not self._data:
550            print "Can only set cursor after a first call to plot()"
551            return
552       
553        n = self._data[0].nrow()
554        if row is None:
555            self._cursor["t"] = range(n)
556        else:
557            for i in row:
558                if i < 0 or i >= n:
559                    print "Row index '%d' out of range" % i
560                    return
561            self._cursor["t"] = row
562
563        n = self._data[0].nbeam()
564        if beam is None:
565            self._cursor["b"] = range(n)
566        else:
567            for i in beam:
568                if i < 0 or  i >= n:
569                    print "Beam index '%d' out of range" % i
570                    return           
571            self._cursor["b"] = beam
572
573        n = self._data[0].nif()
574        if IF is None:
575            self._cursor["i"] = range(n)
576        else:
577            for i in IF:
578                if i < 0 or i >= n:
579                    print "IF index '%d' out of range" %i
580                    return           
581            self._cursor["i"] = IF           
582
583        n = self._data[0].npol()
584        dstokes = {"I":0,"Q":1,"U":2,"V":3}
585        dstokes2 = {"I":0,"Plinear":1,"Pangle":2,"V":3}
586        draw = {"XX":0, "YY":1,"Real(XY)":2, "Imag(XY)":3}
587        dcirc = { "RR":0,"LL":1}#,"Real(RL)":2,"Image(RL)":3}
588       
589        if pol is None:
590            self._cursor["p"] = range(n)
591            self._polmode = ["raw" for i in range(n)]
592        else:
593            if isinstance(pol,str):
594                pol = pol.split()
595            polmode = []
596            pols = []
597            for i in pol:
598                if isinstance(i,str):
599                    if draw.has_key(i):
600                        pols.append(draw.get(i))
601                        polmode.append("raw")
602                    elif dstokes.has_key(i):
603                        pols.append(dstokes.get(i))
604                        polmode.append("stokes")
605                    elif dstokes2.has_key(i):
606                        pols.append(dstokes2.get(i))
607                        polmode.append("stokes2")
608                    elif dcirc.has_key(i):
609                        pols.append(dcirc.get(i))
610                        polmode.append("circular")
611                    else:
612                        "Pol type '%s' not valid" %i
613                        return
614                elif 0 > i >= n:
615                    print "Pol index '%d' out of range" %i
616                    return
617                else:
618                    pols.append(i)
619                    polmode.append("raw")
620            self._cursor["p"] = pols
621            self._polmode = polmode
622        if self._data and refresh: self.plot()
623
624    def _get_pollabel(self, scan, polmode):
625        tlab = ""
626        if polmode == "stokes":
627            tlab = scan._getpolarizationlabel(0,1,0)
628        elif polmode == "stokes2":
629            tlab = scan._getpolarizationlabel(0,1,1)
630        elif polmode == "circular":
631            tlab = scan._getpolarizationlabel(0,0,0)
632        else:
633            tlab = scan._getpolarizationlabel(1,0,0)
634        return tlab
635           
636if __name__ == '__main__':
637    plotter = asapplotter()
Note: See TracBrowser for help on using the repository browser.