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

Last change on this file since 1336 was 622, checked in by mar637, 20 years ago

fixed a typo introduced in last revision.
fixed asap0019

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