source: trunk/python/asapplotter.py @ 702

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

merges from Release-2-fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.0 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(0)
124        for rowsel in rows:
125            i = self._cursor["t"].index(rowsel)
126            if n > 1:
127                self._plotter.palette(0)
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        for scan in scans:
215            self._plotter.palette(0)
216            if n > 1:
217                self._plotter.subplot(scans.index(scan))
218            colvals = eval(cdict2.get(colmode))
219            rowsel = self._cursor["t"][0]
220            for j in colvals:
221                polmode = "raw"
222                jj = colvals.index(j)
223                savej = j
224                for k in cdict.keys():
225                    sel = eval(cdict2.get(k))                   
226                    j = sel[0]
227                    eval(cdict.get(k))
228                    if k == "p":
229                        which = self._cursor["p"].index(j)
230                        polmode = self._polmode[which]
231                        j = which
232                j = savej
233                if colmode == "p":
234                    polmode = self._polmode[self._cursor["p"].index(j)]
235                    j = jj
236                eval(cdict.get(colmode))
237                x = None
238                y = None
239                m = None
240                tlab = self._title
241                if not self._title:
242                    tlab = scan._getsourcename(rowsel)
243                x,xlab = scan.get_abcissa(rowsel)
244                if self._abcissa: xlab = self._abcissa
245                if polmode == "stokes":
246                    y = scan._getstokesspectrum(rowsel)
247                elif polmode == "stokes2":
248                    y = scan._getstokesspectrum(rowsel,True)
249                elif polmode == "circular":
250                    y = scan._stokestopolspectrum(rowsel,False,-1)
251                else:
252                    y = scan._getspectrum(rowsel)
253                if self._ordinate:
254                    ylab = self._ordinate
255                else:
256                    ylab = scan._get_ordinate_label()
257                m = scan._getmask(rowsel)
258                if self._lmap and len(self._lmap) > 0:
259                    llab = self._lmap[jj]
260                else:
261                    if colmode == 'p':
262                        llab = self._get_pollabel(scan, polmode)
263                    else:
264                        llab = self._ldict.get(colmode)+' '+str(j)
265                self._plotter.set_line(label=llab)
266                self._plotter.plot(x,y,m)
267                xlim=[min(x),max(x)]
268                self._plotter.axes.set_xlim(xlim)
269
270            self._plotter.set_axes('xlabel',xlab)
271            self._plotter.set_axes('ylabel',ylab)
272            self._plotter.set_axes('title',tlab)
273        return
274   
275    def _plot_other(self,scans,colmode):
276        if colmode == self._panelling:
277            return
278        cdict = {'b':'scan.setbeam(i)',
279                 'i':'scan.setif(i)',
280                 'p':'scan.setpol(i)'}
281        cdict2 = {'b':'self._cursor["b"]',
282                  'i':'self._cursor["i"]',
283                  'p':'self._cursor["p"]',
284                  's': 'scans',
285                  't': 'self._cursor["t"]'}
286        scan = scans[0]
287        n = eval(self._cdict.get(self._panelling))
288        ncol=1
289        if self._stacking is not None:           
290            ncol = eval(self._cdict.get(colmode))
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        else:
299            self._plotter.set_panels()           
300        panels = self._cursor[self._panelling]       
301        for i in panels:
302            self._plotter.palette(0)
303            polmode = "raw"
304            ii = self._cursor[self._panelling].index(i)
305            if n>1:
306                self._plotter.subplot(ii)
307            if self._panelling == "p":
308                polmode = self._polmode[ii]
309                eval(cdict.get(self._panelling))
310            else:
311                eval(cdict.get(self._panelling))
312            colvals = eval(cdict2.get(colmode))
313            for j in colvals:
314                rowsel = self._cursor["t"][0]
315                jj = colvals.index(j)
316                savei = i
317                for k in cdict.keys():
318                    if k != self._panelling:
319                        sel = eval(cdict2.get(k))
320                        i = sel[0]
321                        if k == "p":
322                            which = self._cursor["p"].index(i)
323                            polmode = self._polmode[which]
324                            i = which                       
325                        eval(cdict.get(k))
326                i = savei
327                if colmode == 's':
328                    scan = j
329                elif colmode == 't':
330                    rowsel = j                   
331                else:
332                    savei = i
333                    if colmode == 'p':
334                        polmode = self._polmode[self._cursor["p"].index(j)]
335                    i = j
336                    eval(cdict.get(colmode))
337                    i = savei
338                x = None
339                y = None
340                m = None
341                x,xlab = scan.get_abcissa(rowsel)
342                if self._abcissa: xlab = self._abcissa
343                if polmode == "stokes":
344                    y = scan._getstokesspectrum(rowsel)
345                elif polmode == "stokes2":
346                    y = scan._getstokesspectrum(rowsel,True)
347                elif polmode == "circular":
348                    y = scan._stokestopolspectrum(rowsel,False,-1)
349                else:
350                    y = scan._getspectrum(rowsel)
351
352                if self._ordinate:
353                    ylab = self._ordinate
354                else:
355                    ylab = scan._get_ordinate_label()
356                m = scan._getmask(rowsel)
357                if colmode == 's' or colmode == 't':
358                    if self._title and len(self._title) > 0:
359                        tlab = self._title[ii]
360                    else:                       
361                        tlab = self._ldict.get(self._panelling)+' '+str(i)
362                    if self._lmap and len(self._lmap) > 0:
363                        llab = self._lmap[jj]
364                    else:
365                        llab = scan._getsourcename(rowsel)
366                else:
367                    if self._title and len(self._title) > 0:
368                        tlab = self._title[ii]
369                    else:
370                        if self._panelling == 'p':
371                            tlab = self._get_pollabel(scan, polmode)
372                        else:
373                            tlab = self._ldict.get(self._panelling)+' '+str(i)
374                    if self._lmap and len(self._lmap) > 0:
375                        llab = self._lmap[jj]
376                    else:
377                        if colmode == 'p':
378                            llab = self._get_pollabel(scan, polmode)
379                        else:
380                            llab = self._ldict.get(colmode)+' '+str(j)
381                self._plotter.set_line(label=llab)
382                self._plotter.plot(x,y,m)
383                xlim=[min(x),max(x)]
384                self._plotter.axes.set_xlim(xlim)
385
386            self._plotter.set_axes('xlabel',xlab)
387            self._plotter.set_axes('ylabel',ylab)
388            self._plotter.set_axes('title',tlab)
389       
390        return
391
392
393    def set_mode(self, stacking=None, panelling=None):
394        """
395        Set the plots look and feel, i.e. what you want to see on the plot.
396        Parameters:
397            stacking:     tell the plotter which variable to plot
398                          as line colour overlays (default 'pol')
399            panelling:    tell the plotter which variable to plot
400                          across multiple panels (default 'scan'
401        Note:
402            Valid modes are:
403                 'beam' 'Beam' 'b':     Beams
404                 'if' 'IF' 'i':         IFs
405                 'pol' 'Pol' 'p':       Polarisations
406                 'scan' 'Scan' 's':     Scans
407                 'time' 'Time' 't':     Times
408        """
409        if not self.set_panelling(panelling):
410            print "Invalid mode"
411            return
412        if not self.set_stacking(stacking):
413            print "Invalid mode"
414            return
415        if self._data: self.plot()
416        return
417
418    def set_panelling(self, what=None):
419        mode = what
420        if mode is None:
421             mode = rcParams['plotter.panelling']
422        md = self._translate(mode)
423        if md:
424            self._panelling = md
425            self._title = None
426            return True
427        return False
428
429    def set_layout(self,rows=None,cols=None):
430        """
431        Set the multi-panel layout, i.e. how many rows and columns plots
432        are visible.
433        Parameters:
434             rows:   The number of rows of plots
435             cols:   The number of columns of plots
436        Note:
437             If no argument is given, the potter reverts to its auto-plot
438             behaviour.
439        """
440        self._rows = rows
441        self._cols = cols
442        if self._data: self.plot()
443        return
444
445    def set_stacking(self, what=None): 
446        mode = what
447        if mode is None:           
448             mode = rcParams['plotter.stacking']       
449        md = self._translate(mode)
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        else:
469            self._minmaxx = [xstart,xend]
470        if ystart is None and yend is None:
471            self._minmaxy = None
472        else:
473            self._minmaxy = [ystart,yend]           
474        if self._data: self.plot()
475        return
476   
477    def set_legend(self, mp=None):
478        """
479        Specify a mapping for the legend instead of using the default
480        indices:
481        Parameters:
482             mp:    a list of 'strings'. This should have the same length
483                    as the number of elements on the legend and then maps
484                    to the indeces in order
485
486        Example:
487             If the data has two IFs/rest frequencies with index 0 and 1
488             for CO and SiO:
489             plotter.set_stacking('i')
490             plotter.set_legend_map(['CO','SiO'])
491             plotter.plot()
492        """
493        self._lmap = mp
494        if self._data: self.plot()
495        return
496
497    def set_title(self, title=None):
498        self._title = title
499        if self._data: self.plot()
500        return
501
502    def set_ordinate(self, ordinate=None):
503        self._ordinate = ordinate
504        if self._data: self.plot()
505        return
506
507    def set_abcissa(self, abcissa=None):
508        self._abcissa = abcissa
509        if self._data: self.plot()
510        return
511
512    def save(self, filename=None, orientation='landscape'):
513        """
514        Save the plot to a file. The know formats are 'png', 'ps', 'eps'.
515        Parameters:
516             filename:    The name of the output file. This is optional
517                          and autodetects the image format from the file
518                          suffix. If non filename is specified a file
519                          called 'yyyymmdd_hhmmss.png' is created in the
520                          current directory.
521             orientation: optional parameter for postscript. 'landscape'
522                          (default) and 'portrait' are valid.
523        """
524        self._plotter.save(filename,orientation)
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                        print "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.