source: trunk/python/asapplotter.py@ 627

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

fix for asap0019 from Release-1

  • 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
[607]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()
[600]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':
[626]82 maxrows = 25
[541]83 if self._data[0].nrow() > maxrows:
[603]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)
[600]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
[626]150 if self._title is None:
[525]151 tlab = scan._getsourcename(rowsel)
[226]152 else:
[626]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:
[626]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':
[603]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)
[626]208 self._plotter.set_panels(rows=self._rows,cols=self._cols,
[377]209 nplots=n)
210 else:
[626]211 self._plotter.set_panels(rows=n,cols=0,nplots=n)
[600]212 else:
213 self._plotter.set_panels()
[626]214
[203]215 for scan in scans:
[541]216 self._plotter.palette(1)
[203]217 if n > 1:
[525]218 self._plotter.subplot(scans.index(scan))
[485]219 self._plotter.palette(1)
[525]220 colvals = eval(cdict2.get(colmode))
221 rowsel = self._cursor["t"][0]
222 for j in colvals:
223 polmode = "raw"
224 jj = colvals.index(j)
225 savej = j
226 for k in cdict.keys():
227 sel = eval(cdict2.get(k))
228 j = sel[0]
229 eval(cdict.get(k))
230 if k == "p":
231 which = self._cursor["p"].index(j)
232 polmode = self._polmode[which]
233 j = which
234 j = savej
235 if colmode == "p":
236 polmode = self._polmode[self._cursor["p"].index(j)]
237 j = jj
[203]238 eval(cdict.get(colmode))
239 x = None
240 y = None
241 m = None
[226]242 tlab = self._title
243 if not self._title:
[525]244 tlab = scan._getsourcename(rowsel)
245 x,xlab = scan.get_abcissa(rowsel)
[257]246 if self._abcissa: xlab = self._abcissa
[525]247 if polmode == "stokes":
248 y = scan._getstokesspectrum(rowsel)
249 elif polmode == "stokes2":
250 y = scan._getstokesspectrum(rowsel,True)
[541]251 elif polmode == "circular":
252 y = scan._stokestopolspectrum(rowsel,False,-1)
[525]253 else:
254 y = scan._getspectrum(rowsel)
[257]255 if self._ordinate:
256 ylab = self._ordinate
257 else:
[626]258 ylab = scan._get_ordinate_label()
[525]259 m = scan._getmask(rowsel)
[257]260 if self._lmap and len(self._lmap) > 0:
[525]261 llab = self._lmap[jj]
[203]262 else:
[525]263 if colmode == 'p':
[603]264 llab = self._get_pollabel(scan, polmode)
[525]265 else:
266 llab = self._ldict.get(colmode)+' '+str(j)
[203]267 self._plotter.set_line(label=llab)
268 self._plotter.plot(x,y,m)
269 xlim=[min(x),max(x)]
270 self._plotter.axes.set_xlim(xlim)
271
272 self._plotter.set_axes('xlabel',xlab)
273 self._plotter.set_axes('ylabel',ylab)
274 self._plotter.set_axes('title',tlab)
275 return
276
277 def _plot_other(self,scans,colmode):
[554]278 if colmode == self._panelling:
[203]279 return
[525]280 cdict = {'b':'scan.setbeam(i)',
281 'i':'scan.setif(i)',
282 'p':'scan.setpol(i)'}
283 cdict2 = {'b':'self._cursor["b"]',
284 'i':'self._cursor["i"]',
285 'p':'self._cursor["p"]',
286 's': 'scans',
287 't': 'self._cursor["t"]'}
[203]288 scan = scans[0]
[554]289 n = eval(self._cdict.get(self._panelling))
[525]290 ncol=1
[203]291 if self._stacking is not None:
292 ncol = eval(self._cdict.get(colmode))
293 if n > 1:
[377]294 if self._rows and self._cols:
295 n = min(n,self._rows*self._cols)
296 self._plotter.set_panels(rows=self._rows,cols=self._cols,
297 nplots=n)
298 else:
[485]299 self._plotter.set_panels(rows=n,cols=0,nplots=n)
[600]300 else:
301 self._plotter.set_panels()
[554]302 panels = self._cursor[self._panelling]
[525]303 for i in panels:
[541]304 self._plotter.palette(1)
[525]305 polmode = "raw"
[554]306 ii = self._cursor[self._panelling].index(i)
[203]307 if n>1:
[525]308 self._plotter.subplot(ii)
[554]309 if self._panelling == "p":
[525]310 polmode = self._polmode[ii]
[554]311 eval(cdict.get(self._panelling))
[525]312 else:
[554]313 eval(cdict.get(self._panelling))
[525]314 colvals = eval(cdict2.get(colmode))
315 for j in colvals:
316 rowsel = self._cursor["t"][0]
317 jj = colvals.index(j)
318 savei = i
319 for k in cdict.keys():
[554]320 if k != self._panelling:
[525]321 sel = eval(cdict2.get(k))
322 i = sel[0]
323 if k == "p":
[557]324 which = self._cursor["p"].index(i)
[525]325 polmode = self._polmode[which]
326 i = which
327 eval(cdict.get(k))
328 i = savei
[203]329 if colmode == 's':
[525]330 scan = j
[203]331 elif colmode == 't':
[525]332 rowsel = j
[203]333 else:
[525]334 savei = i
335 if colmode == 'p':
336 polmode = self._polmode[self._cursor["p"].index(j)]
337 i = j
[203]338 eval(cdict.get(colmode))
[525]339 i = savei
[203]340 x = None
341 y = None
342 m = None
[525]343 x,xlab = scan.get_abcissa(rowsel)
[257]344 if self._abcissa: xlab = self._abcissa
[525]345 if polmode == "stokes":
346 y = scan._getstokesspectrum(rowsel)
347 elif polmode == "stokes2":
348 y = scan._getstokesspectrum(rowsel,True)
[541]349 elif polmode == "circular":
350 y = scan._stokestopolspectrum(rowsel,False,-1)
[525]351 else:
352 y = scan._getspectrum(rowsel)
353
[257]354 if self._ordinate:
355 ylab = self._ordinate
356 else:
[626]357 ylab = scan._get_ordinate_label()
[525]358 m = scan._getmask(rowsel)
[203]359 if colmode == 's' or colmode == 't':
[525]360 if self._title and len(self._title) > 0:
361 tlab = self._title[ii]
362 else:
[554]363 tlab = self._ldict.get(self._panelling)+' '+str(i)
[607]364 if self._lmap and len(self._lmap) > 0:
365 llab = self._lmap[jj]
366 else:
367 llab = scan._getsourcename(rowsel)
[203]368 else:
[226]369 if self._title and len(self._title) > 0:
[525]370 tlab = self._title[ii]
[226]371 else:
[603]372 if self._panelling == 'p':
373 tlab = self._get_pollabel(scan, polmode)
374 else:
375 tlab = self._ldict.get(self._panelling)+' '+str(i)
[226]376 if self._lmap and len(self._lmap) > 0:
[525]377 llab = self._lmap[jj]
[203]378 else:
[525]379 if colmode == 'p':
[603]380 llab = self._get_pollabel(scan, polmode)
[525]381 else:
382 llab = self._ldict.get(colmode)+' '+str(j)
[203]383 self._plotter.set_line(label=llab)
384 self._plotter.plot(x,y,m)
385 xlim=[min(x),max(x)]
386 self._plotter.axes.set_xlim(xlim)
387
388 self._plotter.set_axes('xlabel',xlab)
389 self._plotter.set_axes('ylabel',ylab)
390 self._plotter.set_axes('title',tlab)
391
392 return
393
394
[226]395 def set_mode(self, stacking=None, panelling=None):
[203]396 """
[377]397 Set the plots look and feel, i.e. what you want to see on the plot.
[203]398 Parameters:
399 stacking: tell the plotter which variable to plot
400 as line colour overlays (default 'pol')
401 panelling: tell the plotter which variable to plot
402 across multiple panels (default 'scan'
403 Note:
404 Valid modes are:
405 'beam' 'Beam' 'b': Beams
406 'if' 'IF' 'i': IFs
407 'pol' 'Pol' 'p': Polarisations
408 'scan' 'Scan' 's': Scans
409 'time' 'Time' 't': Times
410 """
[554]411 if not self.set_panelling(panelling):
[203]412 print "Invalid mode"
[226]413 return
[203]414 if not self.set_stacking(stacking):
415 print "Invalid mode"
[226]416 return
417 if self._data: self.plot()
[203]418 return
419
[554]420 def set_panelling(self, what=None):
421 mode = what
422 if mode is None:
423 mode = rcParams['plotter.panelling']
424 md = self._translate(mode)
[203]425 if md:
[554]426 self._panelling = md
[226]427 self._title = None
[203]428 return True
429 return False
430
[377]431 def set_layout(self,rows=None,cols=None):
432 """
433 Set the multi-panel layout, i.e. how many rows and columns plots
434 are visible.
435 Parameters:
436 rows: The number of rows of plots
437 cols: The number of columns of plots
438 Note:
439 If no argument is given, the potter reverts to its auto-plot
440 behaviour.
441 """
442 self._rows = rows
443 self._cols = cols
444 if self._data: self.plot()
445 return
446
[226]447 def set_stacking(self, what=None):
[554]448 mode = what
449 if mode is None:
450 mode = rcParams['plotter.stacking']
451 md = self._translate(mode)
[203]452 if md:
453 self._stacking = md
[226]454 self._lmap = None
[203]455 return True
456 return False
457
[525]458 def set_range(self,xstart=None,xend=None,ystart=None,yend=None):
[203]459 """
460 Set the range of interest on the abcissa of the plot
461 Parameters:
[525]462 [x,y]start,[x,y]end: The start and end points of the 'zoom' window
[203]463 Note:
464 These become non-sensical when the unit changes.
465 use plotter.set_range() without parameters to reset
466
467 """
[525]468 if xstart is None and xend is None:
469 self._minmaxx = None
[600]470 else:
471 self._minmaxx = [xstart,xend]
[525]472 if ystart is None and yend is None:
473 self._minmaxy = None
[600]474 else:
475 self._minmaxy = [ystart,yend]
[525]476 if self._data: self.plot()
[203]477 return
478
[257]479 def set_legend(self, mp=None):
[203]480 """
481 Specify a mapping for the legend instead of using the default
482 indices:
483 Parameters:
484 mp: a list of 'strings'. This should have the same length
485 as the number of elements on the legend and then maps
486 to the indeces in order
487
488 Example:
[485]489 If the data has two IFs/rest frequencies with index 0 and 1
[203]490 for CO and SiO:
491 plotter.set_stacking('i')
492 plotter.set_legend_map(['CO','SiO'])
493 plotter.plot()
494 """
495 self._lmap = mp
[226]496 if self._data: self.plot()
497 return
498
499 def set_title(self, title=None):
500 self._title = title
501 if self._data: self.plot()
502 return
503
[257]504 def set_ordinate(self, ordinate=None):
505 self._ordinate = ordinate
506 if self._data: self.plot()
507 return
508
509 def set_abcissa(self, abcissa=None):
510 self._abcissa = abcissa
511 if self._data: self.plot()
512 return
513
[377]514 def save(self, filename=None):
515 """
516 Save the plot to a file. The know formats are 'png', 'ps', 'eps'.
517 Parameters:
518 filename: The name of the output file. This is optional
519 and autodetects the image format from the file
520 suffix. If non filename is specified a file
521 called 'yyyymmdd_hhmmss.png' is created in the
522 current directory.
523 """
524 self._plotter.save(filename)
525 return
[525]526
[541]527 def set_cursor(self, row=None,beam=None,IF=None,pol=None, refresh=True):
[525]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]541 ["XX", "YY", "Real(XY)", "Imag(XY)"] or
542 ["RR", "LL"]
[525]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"])
[257]549
[525]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:
[554]562 if i < 0 or i >= n:
[525]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:
[554]572 if i < 0 or i >= n:
[525]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:
[554]582 if i < 0 or i >= n:
[525]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}
[541]591 dcirc = { "RR":0,"LL":1}#,"Real(RL)":2,"Image(RL)":3}
[525]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))
[541]614 polmode.append("circular")
[525]615 else:
616 "Pol type '%s' not valid" %i
617 return
618 elif 0 > i >= n:
619 print "Pol index '%d' out of range" %i
620 return
621 else:
622 pols.append(i)
623 polmode.append("raw")
624 self._cursor["p"] = pols
625 self._polmode = polmode
[541]626 if self._data and refresh: self.plot()
[525]627
[603]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
[525]639
[203]640if __name__ == '__main__':
641 plotter = asapplotter()
Note: See TracBrowser for help on using the repository browser.