source: trunk/python/asapplotter.py @ 525

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

added handling of stokes!!!

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.5 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._panels = 's'
34        self._stacking = rcParams['plotter.stacking']
35        self._rows = None
36        self._cols = None
37        self._autoplot = False
38        self._minmaxx = None
39        self._minmaxy = None
40        self._data = None
41        self._lmap = []
42        self._title = None
43        self._ordinate = None
44        self._abcissa = None
45        self._cursor = {'t':None, 'b':None,
46                        'i':None, 'p':None
47                        }
48
49    def _translate(self, name):
50        for d in self._dicts:
51            if d.has_key(name):
52                return d[name]
53        return None
54       
55    def plot(self, *args):
56        """
57        Plot a (list of) scantables.
58        Parameters:
59            one or more comma separated scantables
60        Note:
61            If a (list) of scantables was specified in a previous call
62            to plot, no argument has to be given to 'replot'
63            NO checking is done that the abcissas of the scantables
64            are consistent e.g. all 'channel' or all 'velocity' etc.
65        """
66        if self._plotter.is_dead:
67            self._plotter = ASAPlot()
68        self._plotter.clear()
69        self._plotter.hold()
70        if len(args) > 0:
71            if self._data is not None:               
72                if list(args) != self._data:
73                    self._data = list(args)
74                    # reset cursor
75                    self.set_cursor()
76            else:
77                self._data = list(args)
78                self.set_cursor()
79        if self._panels == 't':
80            if self._data[0].nrow() > 49:
81                print "Scan to be plotted contains more than 25 rows.\n \
82                Can't plot that many panels..."
83                return
84            self._plot_time(self._data[0], self._stacking)
85        elif self._panels == 's':
86            self._plot_scans(self._data, self._stacking)
87        else:
88            self._plot_other(self._data, self._stacking)
89        if self._minmaxx is not None or self._minmaxy is not None:
90            self._plotter.set_limits(xlim=self._minmaxx,ylim=self._minmaxy)
91        self._plotter.release()
92        return
93
94    def _plot_time(self, scan, colmode):
95        if colmode == 't':
96            return
97        n = len(self._cursor["t"])
98        cdict = {'b':'scan.setbeam(j)',
99                 'i':'scan.setif(j)',
100                 'p':'scan.setpol(j)'}
101        cdict2 = {'b':'self._cursor["b"]',
102                  'i':'self._cursor["i"]',
103                  'p':'self._cursor["p"]'}
104        ncol = 1
105        if self._stacking is not None:
106            ncol = eval(self._cdict.get(colmode))
107        self._plotter.set_panels()
108        if n > 1:
109            if self._rows and self._cols:
110                n = min(n,self._rows*self._cols)
111                self._plotter.set_panels(rows=self._rows,cols=self._cols,
112                                         nplots=n)
113            else:
114                self._plotter.set_panels(rows=n,cols=0,nplots=n)
115        rows = self._cursor["t"]
116        self._plotter.palette(1)
117        for rowsel in rows:
118            i = self._cursor["t"].index(rowsel)
119            if n > 1:
120                self._plotter.palette(1)
121                self._plotter.subplot(i)
122            colvals = eval(cdict2.get(colmode))
123            for j in colvals:
124                polmode = "raw"
125                jj = colvals.index(j)
126                savej = j
127                for k in cdict.keys():
128                    sel = eval(cdict2.get(k))                   
129                    j = sel[0]
130                    if k == "p":
131                        which = self._cursor["p"].index(j)
132                        polmode = self._polmode[which]
133                        j = which
134                    eval(cdict.get(k))
135                j = savej
136                if colmode == "p":
137                    polmode = self._polmode[self._cursor["p"].index(j)]
138                    j = jj
139                eval(cdict.get(colmode))
140                x = None
141                y = None
142                m = None
143                if not self._title:
144                    tlab = scan._getsourcename(rowsel)                   
145                else:
146                    if len(self._title) == n:
147                        tlab = self._title[rowsel]
148                    else:
149                        tlab = scan._getsourcename(rowsel)
150                x,xlab = scan.get_abcissa(rowsel)
151                if self._abcissa: xlab = self._abcissa
152                y = None
153                if polmode == "stokes":
154                    y = scan._getstokesspectrum(rowsel)
155                elif polmode == "stokes2":
156                    y = scan._getstokesspectrum(rowsel,True)
157                else:
158                    y = scan._getspectrum(rowsel)
159                if self._ordinate:
160                    ylab = self._ordinate
161                else:
162                    ylab = 'Flux ('+scan.get_fluxunit()+')'
163                m = scan._getmask(rowsel)
164                if self._lmap and len(self._lmap) > 0:
165                    llab = self._lmap[jj]
166                else:
167                    if colmode == 'p':
168                        if polmode == "stokes":
169                            llab = scan._getpolarizationlabel(0,1,0)
170                        elif polmode == "stokes2":
171                            llab = scan._getpolarizationlabel(0,1,1)
172                        else:
173                            llab = scan._getpolarizationlabel(1,0,0)
174                    else:                   
175                        llab = self._ldict.get(colmode)+' '+str(j)
176                self._plotter.set_line(label=llab)
177                self._plotter.plot(x,y,m)
178                xlim=[min(x),max(x)]
179                self._plotter.axes.set_xlim(xlim)
180            self._plotter.set_axes('xlabel',xlab)
181            self._plotter.set_axes('ylabel',ylab)
182            self._plotter.set_axes('title',tlab)           
183        return
184
185    def _plot_scans(self, scans, colmode):
186        print "Can only plot one row per scan."
187        if colmode == 's':
188            return
189        cdict = {'b':'scan.setbeam(j)',
190                 'i':'scan.setif(j)',
191                 'p':'scan.setpol(j)'}
192        cdict2 = {'b':'self._cursor["b"]',
193                  'i':'self._cursor["i"]',
194                  'p':'self._cursor["p"]'}
195       
196        n = len(scans)
197        ncol = 1
198        if self._stacking is not None:
199            scan = scans[0]
200            ncol = eval(self._cdict.get(colmode))
201        self._plotter.set_panels()
202        if n > 1:
203            if self._rows and self._cols:
204                n = min(n,self._rows*self._cols)
205                self._plotter.set_panels(rows=self._rows,cols=self._cols,
206                                         nplots=n)
207            else:
208                self._plotter.set_panels(rows=n,cols=0,nplots=n)
209        self._plotter.palette(1)
210        for scan in scans:
211            if n > 1:
212                self._plotter.subplot(scans.index(scan))
213                self._plotter.palette(1)
214            colvals = eval(cdict2.get(colmode))
215            rowsel = self._cursor["t"][0]
216            for j in colvals:
217                polmode = "raw"
218                jj = colvals.index(j)
219                savej = j
220                for k in cdict.keys():
221                    sel = eval(cdict2.get(k))                   
222                    j = sel[0]
223                    eval(cdict.get(k))
224                    if k == "p":
225                        which = self._cursor["p"].index(j)
226                        polmode = self._polmode[which]
227                        j = which
228                j = savej
229                if colmode == "p":
230                    polmode = self._polmode[self._cursor["p"].index(j)]
231                    j = jj
232                eval(cdict.get(colmode))
233                x = None
234                y = None
235                m = None
236                tlab = self._title
237                if not self._title:
238                    tlab = scan._getsourcename(rowsel)
239                x,xlab = scan.get_abcissa(rowsel)
240                if self._abcissa: xlab = self._abcissa
241                if polmode == "stokes":
242                    y = scan._getstokesspectrum(rowsel)
243                elif polmode == "stokes2":
244                    y = scan._getstokesspectrum(rowsel,True)
245                else:
246                    y = scan._getspectrum(rowsel)
247                if self._ordinate:
248                    ylab = self._ordinate
249                else:
250                    ylab = 'Flux ('+scan.get_fluxunit()+')'
251                m = scan._getmask(rowsel)
252                if self._lmap and len(self._lmap) > 0:
253                    llab = self._lmap[jj]
254                else:
255                    if colmode == 'p':
256                        if polmode == "stokes":
257                            llab = scan._getpolarizationlabel(0,1,0)
258                        elif polmode == "stokes2":
259                            llab = scan._getpolarizationlabel(0,1,1)
260                        else:
261                            llab = scan._getpolarizationlabel(1,0,0)
262                    else:
263                        llab = self._ldict.get(colmode)+' '+str(j)
264                self._plotter.set_line(label=llab)
265                self._plotter.plot(x,y,m)
266                xlim=[min(x),max(x)]
267                self._plotter.axes.set_xlim(xlim)
268
269            self._plotter.set_axes('xlabel',xlab)
270            self._plotter.set_axes('ylabel',ylab)
271            self._plotter.set_axes('title',tlab)
272        return
273   
274    def _plot_other(self,scans,colmode):
275        if colmode == self._panels:
276            return
277        cdict = {'b':'scan.setbeam(i)',
278                 'i':'scan.setif(i)',
279                 'p':'scan.setpol(i)'}
280        cdict2 = {'b':'self._cursor["b"]',
281                  'i':'self._cursor["i"]',
282                  'p':'self._cursor["p"]',
283                  's': 'scans',
284                  't': 'self._cursor["t"]'}
285        scan = scans[0]
286        n = eval(self._cdict.get(self._panels))
287        ncol=1
288        if self._stacking is not None:           
289            ncol = eval(self._cdict.get(colmode))
290        self._plotter.set_panels()
291        if n > 1:
292            if self._rows and self._cols:
293                n = min(n,self._rows*self._cols)
294                self._plotter.set_panels(rows=self._rows,cols=self._cols,
295                                         nplots=n)
296            else:
297                self._plotter.set_panels(rows=n,cols=0,nplots=n)
298        self._plotter.palette(1)
299        panels = self._cursor[self._panels]       
300        for i in panels:
301            polmode = "raw"
302            ii = self._cursor[self._panels].index(i)
303            if n>1:
304                self._plotter.subplot(ii)
305            if self._panels == "p":
306                polmode = self._polmode[ii]
307                eval(cdict.get(self._panels))
308            else:
309                eval(cdict.get(self._panels))
310            colvals = eval(cdict2.get(colmode))
311            for j in colvals:
312                rowsel = self._cursor["t"][0]
313                jj = colvals.index(j)
314                savei = i
315                for k in cdict.keys():
316                    if k != self._panels:
317                        sel = eval(cdict2.get(k))
318                        i = sel[0]
319                        if k == "p":
320                            which = self._cursor["p"].index(j)
321                            polmode = self._polmode[which]
322                            i = which                       
323                        eval(cdict.get(k))
324                i = savei
325                if colmode == 's':
326                    scan = j
327                elif colmode == 't':
328                    rowsel = j                   
329                else:
330                    savei = i
331                    if colmode == 'p':
332                        polmode = self._polmode[self._cursor["p"].index(j)]
333                    i = j
334                    eval(cdict.get(colmode))
335                    i = savei
336                x = None
337                y = None
338                m = None
339                x,xlab = scan.get_abcissa(rowsel)
340                if self._abcissa: xlab = self._abcissa
341                if polmode == "stokes":
342                    y = scan._getstokesspectrum(rowsel)
343                elif polmode == "stokes2":
344                    y = scan._getstokesspectrum(rowsel,True)
345                else:
346                    y = scan._getspectrum(rowsel)
347
348                if self._ordinate:
349                    ylab = self._ordinate
350                else:
351                    ylab = 'Flux ('+scan.get_fluxunit()+')'
352                m = scan._getmask(rowsel)
353                if colmode == 's' or colmode == 't':
354                    if self._title and len(self._title) > 0:
355                        tlab = self._title[ii]
356                    else:                       
357                        tlab = self._ldict.get(self._panels)+' '+str(i)
358                    llab = scan._getsourcename(rowsel)
359                else:
360                    if self._title and len(self._title) > 0:
361                        tlab = self._title[ii]
362                    else:
363                        tlab = self._ldict.get(self._panels)+' '+str(i)
364                    if self._lmap and len(self._lmap) > 0:
365                        llab = self._lmap[jj]
366                    else:
367                        if colmode == 'p':
368                            if polmode == "stokes":
369                                llab = scan._getpolarizationlabel(0,1,0)
370                            elif polmode == "stokes2":
371                                llab = scan._getpolarizationlabel(0,1,1)
372                            else:
373                                llab = scan._getpolarizationlabel(1,0,0)
374                        else:
375                            llab = self._ldict.get(colmode)+' '+str(j)
376                if self._panels == 'p':
377                    if polmode == "stokes":
378                        tlab = scan._getpolarizationlabel(0,1,0)
379                    elif polmode == "stokes2":
380                        tlab = scan._getpolarizationlabel(0,1,1)
381                    else:
382                        tlab = scan._getpolarizationlabel(1,0,0)
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_panels(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_panels(self, what=None):
421        if not what:
422             what = rcParams['plotter.panelling']
423        md = self._translate(what)
424        if md:
425            self._panels = md
426            self._title = None
427            return True
428        return False
429
430    def set_layout(self,rows=None,cols=None):
431        """
432        Set the multi-panel layout, i.e. how many rows and columns plots
433        are visible.
434        Parameters:
435             rows:   The number of rows of plots
436             cols:   The number of columns of plots
437        Note:
438             If no argument is given, the potter reverts to its auto-plot
439             behaviour.
440        """
441        self._rows = rows
442        self._cols = cols
443        if self._data: self.plot()
444        return
445
446    def set_stacking(self, what=None): 
447        if not what:
448             what = rcParams['plotter.stacking']       
449        md = self._translate(what)
450        if md:
451            self._stacking = md
452            self._lmap = None
453            return True
454        return False
455
456    def set_range(self,xstart=None,xend=None,ystart=None,yend=None):
457        """
458        Set the range of interest on the abcissa of the plot
459        Parameters:
460            [x,y]start,[x,y]end:  The start and end points of the 'zoom' window
461        Note:
462            These become non-sensical when the unit changes.
463            use plotter.set_range() without parameters to reset
464
465        """
466        if xstart is None and xend is None:
467            self._minmaxx = None
468            if self._data: self.plot()
469            return
470        if ystart is None and yend is None:
471            self._minmaxy = None
472            if self._data: self.plot()
473            return
474        self._minmaxx = [xstart,xend]
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):
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)"]
542                    Circular polarisation are not handled yet.
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 0 > 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 0 > 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 0 > 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,"RL":2,"LR":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("cricular")
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: self.plot()
627
628           
629if __name__ == '__main__':
630    plotter = asapplotter()
Note: See TracBrowser for help on using the repository browser.