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

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

Fixed asap0008 and asap0014

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