source: trunk/python/asapplotter.py @ 626

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

fix for asap0019 from Release-1

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.8 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 = None
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 = 25
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 self._title is None:
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 = scan._get_ordinate_label()
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_panels(rows=self._rows,cols=self._cols,
209                                         nplots=n)
210            else:
211                self._plotter.set_panels(rows=n,cols=0,nplots=n)
212        else:
213            self._plotter.set_panels()
214
215        for scan in scans:
216            self._plotter.palette(1)
217            if n > 1:
218                self._plotter.subplot(scans.index(scan))
219                self._plotter.palette(1)
220            colvals = eval(cdict2.get(colmode))
221            rowsel = self._cursor["t"][0]
222            for j in colvals:
223                polmode = "raw"
224                jj = colvals.index(j)
225                savej = j
226                for k in cdict.keys():
227                    sel = eval(cdict2.get(k))                   
228                    j = sel[0]
229                    eval(cdict.get(k))
230                    if k == "p":
231                        which = self._cursor["p"].index(j)
232                        polmode = self._polmode[which]
233                        j = which
234                j = savej
235                if colmode == "p":
236                    polmode = self._polmode[self._cursor["p"].index(j)]
237                    j = jj
238                eval(cdict.get(colmode))
239                x = None
240                y = None
241                m = None
242                tlab = self._title
243                if not self._title:
244                    tlab = scan._getsourcename(rowsel)
245                x,xlab = scan.get_abcissa(rowsel)
246                if self._abcissa: xlab = self._abcissa
247                if polmode == "stokes":
248                    y = scan._getstokesspectrum(rowsel)
249                elif polmode == "stokes2":
250                    y = scan._getstokesspectrum(rowsel,True)
251                elif polmode == "circular":
252                    y = scan._stokestopolspectrum(rowsel,False,-1)
253                else:
254                    y = scan._getspectrum(rowsel)
255                if self._ordinate:
256                    ylab = self._ordinate
257                else:
258                    ylab = scan._get_ordinate_label()
259                m = scan._getmask(rowsel)
260                if self._lmap and len(self._lmap) > 0:
261                    llab = self._lmap[jj]
262                else:
263                    if colmode == 'p':
264                        llab = self._get_pollabel(scan, polmode)
265                    else:
266                        llab = self._ldict.get(colmode)+' '+str(j)
267                self._plotter.set_line(label=llab)
268                self._plotter.plot(x,y,m)
269                xlim=[min(x),max(x)]
270                self._plotter.axes.set_xlim(xlim)
271
272            self._plotter.set_axes('xlabel',xlab)
273            self._plotter.set_axes('ylabel',ylab)
274            self._plotter.set_axes('title',tlab)
275        return
276   
277    def _plot_other(self,scans,colmode):
278        if colmode == self._panelling:
279            return
280        cdict = {'b':'scan.setbeam(i)',
281                 'i':'scan.setif(i)',
282                 'p':'scan.setpol(i)'}
283        cdict2 = {'b':'self._cursor["b"]',
284                  'i':'self._cursor["i"]',
285                  'p':'self._cursor["p"]',
286                  's': 'scans',
287                  't': 'self._cursor["t"]'}
288        scan = scans[0]
289        n = eval(self._cdict.get(self._panelling))
290        ncol=1
291        if self._stacking is not None:           
292            ncol = eval(self._cdict.get(colmode))
293        if n > 1:
294            if self._rows and self._cols:
295                n = min(n,self._rows*self._cols)
296                self._plotter.set_panels(rows=self._rows,cols=self._cols,
297                                         nplots=n)
298            else:
299                self._plotter.set_panels(rows=n,cols=0,nplots=n)
300        else:
301            self._plotter.set_panels()           
302        panels = self._cursor[self._panelling]       
303        for i in panels:
304            self._plotter.palette(1)
305            polmode = "raw"
306            ii = self._cursor[self._panelling].index(i)
307            if n>1:
308                self._plotter.subplot(ii)
309            if self._panelling == "p":
310                polmode = self._polmode[ii]
311                eval(cdict.get(self._panelling))
312            else:
313                eval(cdict.get(self._panelling))
314            colvals = eval(cdict2.get(colmode))
315            for j in colvals:
316                rowsel = self._cursor["t"][0]
317                jj = colvals.index(j)
318                savei = i
319                for k in cdict.keys():
320                    if k != self._panelling:
321                        sel = eval(cdict2.get(k))
322                        i = sel[0]
323                        if k == "p":
324                            which = self._cursor["p"].index(i)
325                            polmode = self._polmode[which]
326                            i = which                       
327                        eval(cdict.get(k))
328                i = savei
329                if colmode == 's':
330                    scan = j
331                elif colmode == 't':
332                    rowsel = j                   
333                else:
334                    savei = i
335                    if colmode == 'p':
336                        polmode = self._polmode[self._cursor["p"].index(j)]
337                    i = j
338                    eval(cdict.get(colmode))
339                    i = savei
340                x = None
341                y = None
342                m = None
343                x,xlab = scan.get_abcissa(rowsel)
344                if self._abcissa: xlab = self._abcissa
345                if polmode == "stokes":
346                    y = scan._getstokesspectrum(rowsel)
347                elif polmode == "stokes2":
348                    y = scan._getstokesspectrum(rowsel,True)
349                elif polmode == "circular":
350                    y = scan._stokestopolspectrum(rowsel,False,-1)
351                else:
352                    y = scan._getspectrum(rowsel)
353
354                if self._ordinate:
355                    ylab = self._ordinate
356                else:
357                    ylab = scan._get_ordinate_label()
358                m = scan._getmask(rowsel)
359                if colmode == 's' or colmode == 't':
360                    if self._title and len(self._title) > 0:
361                        tlab = self._title[ii]
362                    else:                       
363                        tlab = self._ldict.get(self._panelling)+' '+str(i)
364                    if self._lmap and len(self._lmap) > 0:
365                        llab = self._lmap[jj]
366                    else:
367                        llab = scan._getsourcename(rowsel)
368                else:
369                    if self._title and len(self._title) > 0:
370                        tlab = self._title[ii]
371                    else:
372                        if self._panelling == 'p':
373                            tlab = self._get_pollabel(scan, polmode)
374                        else:
375                            tlab = self._ldict.get(self._panelling)+' '+str(i)
376                    if self._lmap and len(self._lmap) > 0:
377                        llab = self._lmap[jj]
378                    else:
379                        if colmode == 'p':
380                            llab = self._get_pollabel(scan, polmode)
381                        else:
382                            llab = self._ldict.get(colmode)+' '+str(j)
383                self._plotter.set_line(label=llab)
384                self._plotter.plot(x,y,m)
385                xlim=[min(x),max(x)]
386                self._plotter.axes.set_xlim(xlim)
387
388            self._plotter.set_axes('xlabel',xlab)
389            self._plotter.set_axes('ylabel',ylab)
390            self._plotter.set_axes('title',tlab)
391       
392        return
393
394
395    def set_mode(self, stacking=None, panelling=None):
396        """
397        Set the plots look and feel, i.e. what you want to see on the plot.
398        Parameters:
399            stacking:     tell the plotter which variable to plot
400                          as line colour overlays (default 'pol')
401            panelling:    tell the plotter which variable to plot
402                          across multiple panels (default 'scan'
403        Note:
404            Valid modes are:
405                 'beam' 'Beam' 'b':     Beams
406                 'if' 'IF' 'i':         IFs
407                 'pol' 'Pol' 'p':       Polarisations
408                 'scan' 'Scan' 's':     Scans
409                 'time' 'Time' 't':     Times
410        """
411        if not self.set_panelling(panelling):
412            print "Invalid mode"
413            return
414        if not self.set_stacking(stacking):
415            print "Invalid mode"
416            return
417        if self._data: self.plot()
418        return
419
420    def set_panelling(self, what=None):
421        mode = what
422        if mode is None:
423             mode = rcParams['plotter.panelling']
424        md = self._translate(mode)
425        if md:
426            self._panelling = md
427            self._title = None
428            return True
429        return False
430
431    def set_layout(self,rows=None,cols=None):
432        """
433        Set the multi-panel layout, i.e. how many rows and columns plots
434        are visible.
435        Parameters:
436             rows:   The number of rows of plots
437             cols:   The number of columns of plots
438        Note:
439             If no argument is given, the potter reverts to its auto-plot
440             behaviour.
441        """
442        self._rows = rows
443        self._cols = cols
444        if self._data: self.plot()
445        return
446
447    def set_stacking(self, what=None): 
448        mode = what
449        if mode is None:           
450             mode = rcParams['plotter.stacking']       
451        md = self._translate(mode)
452        if md:
453            self._stacking = md
454            self._lmap = None
455            return True
456        return False
457
458    def set_range(self,xstart=None,xend=None,ystart=None,yend=None):
459        """
460        Set the range of interest on the abcissa of the plot
461        Parameters:
462            [x,y]start,[x,y]end:  The start and end points of the 'zoom' window
463        Note:
464            These become non-sensical when the unit changes.
465            use plotter.set_range() without parameters to reset
466
467        """
468        if xstart is None and xend is None:
469            self._minmaxx = None
470        else:
471            self._minmaxx = [xstart,xend]
472        if ystart is None and yend is None:
473            self._minmaxy = None
474        else:
475            self._minmaxy = [ystart,yend]           
476        if self._data: self.plot()
477        return
478   
479    def set_legend(self, mp=None):
480        """
481        Specify a mapping for the legend instead of using the default
482        indices:
483        Parameters:
484             mp:    a list of 'strings'. This should have the same length
485                    as the number of elements on the legend and then maps
486                    to the indeces in order
487
488        Example:
489             If the data has two IFs/rest frequencies with index 0 and 1
490             for CO and SiO:
491             plotter.set_stacking('i')
492             plotter.set_legend_map(['CO','SiO'])
493             plotter.plot()
494        """
495        self._lmap = mp
496        if self._data: self.plot()
497        return
498
499    def set_title(self, title=None):
500        self._title = title
501        if self._data: self.plot()
502        return
503
504    def set_ordinate(self, ordinate=None):
505        self._ordinate = ordinate
506        if self._data: self.plot()
507        return
508
509    def set_abcissa(self, abcissa=None):
510        self._abcissa = abcissa
511        if self._data: self.plot()
512        return
513
514    def save(self, filename=None):
515        """
516        Save the plot to a file. The know formats are 'png', 'ps', 'eps'.
517        Parameters:
518             filename:    The name of the output file. This is optional
519                          and autodetects the image format from the file
520                          suffix. If non filename is specified a file
521                          called 'yyyymmdd_hhmmss.png' is created in the
522                          current directory.
523        """
524        self._plotter.save(filename)
525        return
526   
527    def set_cursor(self, row=None,beam=None,IF=None,pol=None, refresh=True):
528        """
529        Specify a 'cursor' for plotting selected spectra. Time (rows),
530        Beam, IF, Polarisation ranges can be specified.
531        Parameters:
532            Default for all paramaters is to select all available
533            row:    selects the rows (time stamps) to be plotted, this has
534                    to be a vector of row indices, e.g. row=[0,2,5] or row=[2]
535            beam:   select a range of beams
536            IF:     select a range of IFs
537            pol:    select Polarisations for plotting these can be by index
538                    (raw polarisations (default)) or by names any of:
539                    ["I", "Q", "U", "V"] or
540                    ["I", "Plinear", "Pangle", "V"] or
541                    ["XX", "YY", "Real(XY)", "Imag(XY)"] or
542                    ["RR", "LL"]
543        Example:
544            plotter.set_mode('pol','time')
545            plotter.plot(myscan) # plots all raw polarisations colour stacked
546            plotter.set_cursor(pol=["I"]) # plot "I" only for all rows
547            # plot "I" only for two time stamps row=0 and row=2
548            plotter.set_cursor(row=[0,2],pol=["I"])
549
550        Note:
551            Be careful to select only exisiting polarisations.           
552        """
553        if not self._data:
554            print "Can only set cursor after a first call to plot()"
555            return
556       
557        n = self._data[0].nrow()
558        if row is None:
559            self._cursor["t"] = range(n)
560        else:
561            for i in row:
562                if i < 0 or i >= n:
563                    print "Row index '%d' out of range" % i
564                    return
565            self._cursor["t"] = row
566
567        n = self._data[0].nbeam()
568        if beam is None:
569            self._cursor["b"] = range(n)
570        else:
571            for i in beam:
572                if i < 0 or  i >= n:
573                    print "Beam index '%d' out of range" % i
574                    return           
575            self._cursor["b"] = beam
576
577        n = self._data[0].nif()
578        if IF is None:
579            self._cursor["i"] = range(n)
580        else:
581            for i in IF:
582                if i < 0 or i >= n:
583                    print "IF index '%d' out of range" %i
584                    return           
585            self._cursor["i"] = IF           
586
587        n = self._data[0].npol()
588        dstokes = {"I":0,"Q":1,"U":2,"V":3}
589        dstokes2 = {"I":0,"Plinear":1,"Pangle":2,"V":3}
590        draw = {"XX":0, "YY":1,"Real(XY)":2, "Imag(XY)":3}
591        dcirc = { "RR":0,"LL":1}#,"Real(RL)":2,"Image(RL)":3}
592       
593        if pol is None:
594            self._cursor["p"] = range(n)
595            self._polmode = ["raw" for i in range(n)]
596        else:
597            if isinstance(pol,str):
598                pol = pol.split()
599            polmode = []
600            pols = []
601            for i in pol:
602                if isinstance(i,str):
603                    if draw.has_key(i):
604                        pols.append(draw.get(i))
605                        polmode.append("raw")
606                    elif dstokes.has_key(i):
607                        pols.append(dstokes.get(i))
608                        polmode.append("stokes")
609                    elif dstokes2.has_key(i):
610                        pols.append(dstokes2.get(i))
611                        polmode.append("stokes2")
612                    elif dcirc.has_key(i):
613                        pols.append(dcirc.get(i))
614                        polmode.append("circular")
615                    else:
616                        "Pol type '%s' not valid" %i
617                        return
618                elif 0 > i >= n:
619                    print "Pol index '%d' out of range" %i
620                    return
621                else:
622                    pols.append(i)
623                    polmode.append("raw")
624            self._cursor["p"] = pols
625            self._polmode = polmode
626        if self._data and refresh: self.plot()
627
628    def _get_pollabel(self, scan, polmode):
629        tlab = ""
630        if polmode == "stokes":
631            tlab = scan._getpolarizationlabel(0,1,0)
632        elif polmode == "stokes2":
633            tlab = scan._getpolarizationlabel(0,1,1)
634        elif polmode == "circular":
635            tlab = scan._getpolarizationlabel(0,0,0)
636        else:
637            tlab = scan._getpolarizationlabel(1,0,0)
638        return tlab
639           
640if __name__ == '__main__':
641    plotter = asapplotter()
Note: See TracBrowser for help on using the repository browser.