source: trunk/python/asapplotter.py@ 531

Last change on this file since 531 was 525, checked in by mar637, 20 years ago

added handling of stokes!!!

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.5 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]
33 self._panels = 's'
[226]34 self._stacking = rcParams['plotter.stacking']
[377]35 self._rows = None
36 self._cols = None
[203]37 self._autoplot = False
[525]38 self._minmaxx = None
39 self._minmaxy = None
[203]40 self._data = None
41 self._lmap = []
[226]42 self._title = None
[257]43 self._ordinate = None
44 self._abcissa = None
[525]45 self._cursor = {'t':None, 'b':None,
46 'i':None, 'p':None
47 }
[203]48
49 def _translate(self, name):
50 for d in self._dicts:
51 if d.has_key(name):
52 return d[name]
53 return None
54
[525]55 def plot(self, *args):
[203]56 """
57 Plot a (list of) scantables.
58 Parameters:
59 one or more comma separated scantables
60 Note:
61 If a (list) of scantables was specified in a previous call
62 to plot, no argument has to be given to 'replot'
[525]63 NO checking is done that the abcissas of the scantables
[203]64 are consistent e.g. all 'channel' or all 'velocity' etc.
65 """
66 if self._plotter.is_dead:
67 self._plotter = ASAPlot()
68 self._plotter.clear()
69 self._plotter.hold()
70 if len(args) > 0:
[525]71 if self._data is not None:
72 if list(args) != self._data:
73 self._data = list(args)
74 # reset cursor
75 self.set_cursor()
76 else:
77 self._data = list(args)
78 self.set_cursor()
[203]79 if self._panels == 't':
[525]80 if self._data[0].nrow() > 49:
81 print "Scan to be plotted contains more than 25 rows.\n \
82 Can't plot that many panels..."
[203]83 return
84 self._plot_time(self._data[0], self._stacking)
85 elif self._panels == 's':
86 self._plot_scans(self._data, self._stacking)
87 else:
88 self._plot_other(self._data, self._stacking)
[525]89 if self._minmaxx is not None or self._minmaxy is not None:
90 self._plotter.set_limits(xlim=self._minmaxx,ylim=self._minmaxy)
[203]91 self._plotter.release()
92 return
93
94 def _plot_time(self, scan, colmode):
95 if colmode == 't':
96 return
[525]97 n = len(self._cursor["t"])
[203]98 cdict = {'b':'scan.setbeam(j)',
99 'i':'scan.setif(j)',
100 'p':'scan.setpol(j)'}
[525]101 cdict2 = {'b':'self._cursor["b"]',
102 'i':'self._cursor["i"]',
103 'p':'self._cursor["p"]'}
104 ncol = 1
[203]105 if self._stacking is not None:
106 ncol = eval(self._cdict.get(colmode))
107 self._plotter.set_panels()
108 if n > 1:
[377]109 if self._rows and self._cols:
110 n = min(n,self._rows*self._cols)
111 self._plotter.set_panels(rows=self._rows,cols=self._cols,
112 nplots=n)
113 else:
[485]114 self._plotter.set_panels(rows=n,cols=0,nplots=n)
[525]115 rows = self._cursor["t"]
116 self._plotter.palette(1)
117 for rowsel in rows:
118 i = self._cursor["t"].index(rowsel)
[203]119 if n > 1:
[377]120 self._plotter.palette(1)
[203]121 self._plotter.subplot(i)
[525]122 colvals = eval(cdict2.get(colmode))
123 for j in colvals:
124 polmode = "raw"
125 jj = colvals.index(j)
126 savej = j
127 for k in cdict.keys():
128 sel = eval(cdict2.get(k))
129 j = sel[0]
130 if k == "p":
131 which = self._cursor["p"].index(j)
132 polmode = self._polmode[which]
133 j = which
134 eval(cdict.get(k))
135 j = savej
136 if colmode == "p":
137 polmode = self._polmode[self._cursor["p"].index(j)]
138 j = jj
[203]139 eval(cdict.get(colmode))
140 x = None
141 y = None
142 m = None
[226]143 if not self._title:
[525]144 tlab = scan._getsourcename(rowsel)
[226]145 else:
146 if len(self._title) == n:
[525]147 tlab = self._title[rowsel]
[226]148 else:
[525]149 tlab = scan._getsourcename(rowsel)
150 x,xlab = scan.get_abcissa(rowsel)
[257]151 if self._abcissa: xlab = self._abcissa
[525]152 y = None
153 if polmode == "stokes":
154 y = scan._getstokesspectrum(rowsel)
155 elif polmode == "stokes2":
156 y = scan._getstokesspectrum(rowsel,True)
157 else:
158 y = scan._getspectrum(rowsel)
[257]159 if self._ordinate:
160 ylab = self._ordinate
161 else:
162 ylab = 'Flux ('+scan.get_fluxunit()+')'
[525]163 m = scan._getmask(rowsel)
[226]164 if self._lmap and len(self._lmap) > 0:
[525]165 llab = self._lmap[jj]
[203]166 else:
[525]167 if colmode == 'p':
168 if polmode == "stokes":
169 llab = scan._getpolarizationlabel(0,1,0)
170 elif polmode == "stokes2":
171 llab = scan._getpolarizationlabel(0,1,1)
172 else:
173 llab = scan._getpolarizationlabel(1,0,0)
174 else:
175 llab = self._ldict.get(colmode)+' '+str(j)
[203]176 self._plotter.set_line(label=llab)
177 self._plotter.plot(x,y,m)
178 xlim=[min(x),max(x)]
179 self._plotter.axes.set_xlim(xlim)
180 self._plotter.set_axes('xlabel',xlab)
181 self._plotter.set_axes('ylabel',ylab)
182 self._plotter.set_axes('title',tlab)
183 return
184
[525]185 def _plot_scans(self, scans, colmode):
186 print "Can only plot one row per scan."
[203]187 if colmode == 's':
188 return
189 cdict = {'b':'scan.setbeam(j)',
190 'i':'scan.setif(j)',
191 'p':'scan.setpol(j)'}
[525]192 cdict2 = {'b':'self._cursor["b"]',
193 'i':'self._cursor["i"]',
194 'p':'self._cursor["p"]'}
195
[203]196 n = len(scans)
[525]197 ncol = 1
[203]198 if self._stacking is not None:
199 scan = scans[0]
200 ncol = eval(self._cdict.get(colmode))
201 self._plotter.set_panels()
202 if n > 1:
[377]203 if self._rows and self._cols:
204 n = min(n,self._rows*self._cols)
205 self._plotter.set_panels(rows=self._rows,cols=self._cols,
206 nplots=n)
207 else:
[485]208 self._plotter.set_panels(rows=n,cols=0,nplots=n)
[525]209 self._plotter.palette(1)
[203]210 for scan in scans:
211 if n > 1:
[525]212 self._plotter.subplot(scans.index(scan))
[485]213 self._plotter.palette(1)
[525]214 colvals = eval(cdict2.get(colmode))
215 rowsel = self._cursor["t"][0]
216 for j in colvals:
217 polmode = "raw"
218 jj = colvals.index(j)
219 savej = j
220 for k in cdict.keys():
221 sel = eval(cdict2.get(k))
222 j = sel[0]
223 eval(cdict.get(k))
224 if k == "p":
225 which = self._cursor["p"].index(j)
226 polmode = self._polmode[which]
227 j = which
228 j = savej
229 if colmode == "p":
230 polmode = self._polmode[self._cursor["p"].index(j)]
231 j = jj
[203]232 eval(cdict.get(colmode))
233 x = None
234 y = None
235 m = None
[226]236 tlab = self._title
237 if not self._title:
[525]238 tlab = scan._getsourcename(rowsel)
239 x,xlab = scan.get_abcissa(rowsel)
[257]240 if self._abcissa: xlab = self._abcissa
[525]241 if polmode == "stokes":
242 y = scan._getstokesspectrum(rowsel)
243 elif polmode == "stokes2":
244 y = scan._getstokesspectrum(rowsel,True)
245 else:
246 y = scan._getspectrum(rowsel)
[257]247 if self._ordinate:
248 ylab = self._ordinate
249 else:
250 ylab = 'Flux ('+scan.get_fluxunit()+')'
[525]251 m = scan._getmask(rowsel)
[257]252 if self._lmap and len(self._lmap) > 0:
[525]253 llab = self._lmap[jj]
[203]254 else:
[525]255 if colmode == 'p':
256 if polmode == "stokes":
257 llab = scan._getpolarizationlabel(0,1,0)
258 elif polmode == "stokes2":
259 llab = scan._getpolarizationlabel(0,1,1)
260 else:
261 llab = scan._getpolarizationlabel(1,0,0)
262 else:
263 llab = self._ldict.get(colmode)+' '+str(j)
[203]264 self._plotter.set_line(label=llab)
265 self._plotter.plot(x,y,m)
266 xlim=[min(x),max(x)]
267 self._plotter.axes.set_xlim(xlim)
268
269 self._plotter.set_axes('xlabel',xlab)
270 self._plotter.set_axes('ylabel',ylab)
271 self._plotter.set_axes('title',tlab)
272 return
273
274 def _plot_other(self,scans,colmode):
275 if colmode == self._panels:
276 return
[525]277 cdict = {'b':'scan.setbeam(i)',
278 'i':'scan.setif(i)',
279 'p':'scan.setpol(i)'}
280 cdict2 = {'b':'self._cursor["b"]',
281 'i':'self._cursor["i"]',
282 'p':'self._cursor["p"]',
283 's': 'scans',
284 't': 'self._cursor["t"]'}
[203]285 scan = scans[0]
286 n = eval(self._cdict.get(self._panels))
[525]287 ncol=1
[203]288 if self._stacking is not None:
289 ncol = eval(self._cdict.get(colmode))
290 self._plotter.set_panels()
291 if n > 1:
[377]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:
[485]297 self._plotter.set_panels(rows=n,cols=0,nplots=n)
[525]298 self._plotter.palette(1)
299 panels = self._cursor[self._panels]
300 for i in panels:
301 polmode = "raw"
302 ii = self._cursor[self._panels].index(i)
[203]303 if n>1:
[525]304 self._plotter.subplot(ii)
305 if self._panels == "p":
306 polmode = self._polmode[ii]
307 eval(cdict.get(self._panels))
308 else:
309 eval(cdict.get(self._panels))
310 colvals = eval(cdict2.get(colmode))
311 for j in colvals:
312 rowsel = self._cursor["t"][0]
313 jj = colvals.index(j)
314 savei = i
315 for k in cdict.keys():
316 if k != self._panels:
317 sel = eval(cdict2.get(k))
318 i = sel[0]
319 if k == "p":
320 which = self._cursor["p"].index(j)
321 polmode = self._polmode[which]
322 i = which
323 eval(cdict.get(k))
324 i = savei
[203]325 if colmode == 's':
[525]326 scan = j
[203]327 elif colmode == 't':
[525]328 rowsel = j
[203]329 else:
[525]330 savei = i
331 if colmode == 'p':
332 polmode = self._polmode[self._cursor["p"].index(j)]
333 i = j
[203]334 eval(cdict.get(colmode))
[525]335 i = savei
[203]336 x = None
337 y = None
338 m = None
[525]339 x,xlab = scan.get_abcissa(rowsel)
[257]340 if self._abcissa: xlab = self._abcissa
[525]341 if polmode == "stokes":
342 y = scan._getstokesspectrum(rowsel)
343 elif polmode == "stokes2":
344 y = scan._getstokesspectrum(rowsel,True)
345 else:
346 y = scan._getspectrum(rowsel)
347
[257]348 if self._ordinate:
349 ylab = self._ordinate
350 else:
351 ylab = 'Flux ('+scan.get_fluxunit()+')'
[525]352 m = scan._getmask(rowsel)
[203]353 if colmode == 's' or colmode == 't':
[525]354 if self._title and len(self._title) > 0:
355 tlab = self._title[ii]
356 else:
[226]357 tlab = self._ldict.get(self._panels)+' '+str(i)
[525]358 llab = scan._getsourcename(rowsel)
[203]359 else:
[226]360 if self._title and len(self._title) > 0:
[525]361 tlab = self._title[ii]
[226]362 else:
[257]363 tlab = self._ldict.get(self._panels)+' '+str(i)
[226]364 if self._lmap and len(self._lmap) > 0:
[525]365 llab = self._lmap[jj]
[203]366 else:
[525]367 if colmode == 'p':
368 if polmode == "stokes":
369 llab = scan._getpolarizationlabel(0,1,0)
370 elif polmode == "stokes2":
371 llab = scan._getpolarizationlabel(0,1,1)
372 else:
373 llab = scan._getpolarizationlabel(1,0,0)
374 else:
375 llab = self._ldict.get(colmode)+' '+str(j)
376 if self._panels == 'p':
377 if polmode == "stokes":
378 tlab = scan._getpolarizationlabel(0,1,0)
379 elif polmode == "stokes2":
380 tlab = scan._getpolarizationlabel(0,1,1)
381 else:
382 tlab = scan._getpolarizationlabel(1,0,0)
[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 """
411 if not self.set_panels(panelling):
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
[377]420 def set_panels(self, what=None):
[226]421 if not what:
422 what = rcParams['plotter.panelling']
[203]423 md = self._translate(what)
424 if md:
[226]425 self._panels = md
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):
447 if not what:
448 what = rcParams['plotter.stacking']
[203]449 md = self._translate(what)
450 if md:
451 self._stacking = md
[226]452 self._lmap = None
[203]453 return True
454 return False
455
[525]456 def set_range(self,xstart=None,xend=None,ystart=None,yend=None):
[203]457 """
458 Set the range of interest on the abcissa of the plot
459 Parameters:
[525]460 [x,y]start,[x,y]end: The start and end points of the 'zoom' window
[203]461 Note:
462 These become non-sensical when the unit changes.
463 use plotter.set_range() without parameters to reset
464
465 """
[525]466 if xstart is None and xend is None:
467 self._minmaxx = None
[226]468 if self._data: self.plot()
[525]469 return
470 if ystart is None and yend is None:
471 self._minmaxy = None
[226]472 if self._data: self.plot()
[525]473 return
474 self._minmaxx = [xstart,xend]
475 self._minmaxy = [ystart,yend]
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
527 def set_cursor(self, row=None,beam=None,IF=None,pol=None):
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)"]
542 Circular polarisation are not handled yet.
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:
562 if 0 > 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 0 > 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 0 > 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,"RL":2,"LR":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("cricular")
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
626 if self._data: self.plot()
627
628
[203]629if __name__ == '__main__':
630 plotter = asapplotter()
Note: See TracBrowser for help on using the repository browser.