source: trunk/python/asapplotter.py @ 554

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

Fixed asaprc set_mode issues.
Fixed set_cursor range detection

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