source: trunk/python/asapplotter.py@ 530

Last change on this file since 530 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
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._panels = 's'
34 self._stacking = rcParams['plotter.stacking']
35 self._rows = None
36 self._cols = None
37 self._autoplot = False
38 self._minmaxx = None
39 self._minmaxy = None
40 self._data = None
41 self._lmap = []
42 self._title = None
43 self._ordinate = None
44 self._abcissa = None
45 self._cursor = {'t':None, 'b':None,
46 'i':None, 'p':None
47 }
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
55 def plot(self, *args):
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'
63 NO checking is done that the abcissas of the scantables
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:
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()
79 if self._panels == 't':
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..."
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)
89 if self._minmaxx is not None or self._minmaxy is not None:
90 self._plotter.set_limits(xlim=self._minmaxx,ylim=self._minmaxy)
91 self._plotter.release()
92 return
93
94 def _plot_time(self, scan, colmode):
95 if colmode == 't':
96 return
97 n = len(self._cursor["t"])
98 cdict = {'b':'scan.setbeam(j)',
99 'i':'scan.setif(j)',
100 'p':'scan.setpol(j)'}
101 cdict2 = {'b':'self._cursor["b"]',
102 'i':'self._cursor["i"]',
103 'p':'self._cursor["p"]'}
104 ncol = 1
105 if self._stacking is not None:
106 ncol = eval(self._cdict.get(colmode))
107 self._plotter.set_panels()
108 if n > 1:
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:
114 self._plotter.set_panels(rows=n,cols=0,nplots=n)
115 rows = self._cursor["t"]
116 self._plotter.palette(1)
117 for rowsel in rows:
118 i = self._cursor["t"].index(rowsel)
119 if n > 1:
120 self._plotter.palette(1)
121 self._plotter.subplot(i)
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
139 eval(cdict.get(colmode))
140 x = None
141 y = None
142 m = None
143 if not self._title:
144 tlab = scan._getsourcename(rowsel)
145 else:
146 if len(self._title) == n:
147 tlab = self._title[rowsel]
148 else:
149 tlab = scan._getsourcename(rowsel)
150 x,xlab = scan.get_abcissa(rowsel)
151 if self._abcissa: xlab = self._abcissa
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)
159 if self._ordinate:
160 ylab = self._ordinate
161 else:
162 ylab = 'Flux ('+scan.get_fluxunit()+')'
163 m = scan._getmask(rowsel)
164 if self._lmap and len(self._lmap) > 0:
165 llab = self._lmap[jj]
166 else:
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)
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
185 def _plot_scans(self, scans, colmode):
186 print "Can only plot one row per scan."
187 if colmode == 's':
188 return
189 cdict = {'b':'scan.setbeam(j)',
190 'i':'scan.setif(j)',
191 'p':'scan.setpol(j)'}
192 cdict2 = {'b':'self._cursor["b"]',
193 'i':'self._cursor["i"]',
194 'p':'self._cursor["p"]'}
195
196 n = len(scans)
197 ncol = 1
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:
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:
208 self._plotter.set_panels(rows=n,cols=0,nplots=n)
209 self._plotter.palette(1)
210 for scan in scans:
211 if n > 1:
212 self._plotter.subplot(scans.index(scan))
213 self._plotter.palette(1)
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
232 eval(cdict.get(colmode))
233 x = None
234 y = None
235 m = None
236 tlab = self._title
237 if not self._title:
238 tlab = scan._getsourcename(rowsel)
239 x,xlab = scan.get_abcissa(rowsel)
240 if self._abcissa: xlab = self._abcissa
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)
247 if self._ordinate:
248 ylab = self._ordinate
249 else:
250 ylab = 'Flux ('+scan.get_fluxunit()+')'
251 m = scan._getmask(rowsel)
252 if self._lmap and len(self._lmap) > 0:
253 llab = self._lmap[jj]
254 else:
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)
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
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"]'}
285 scan = scans[0]
286 n = eval(self._cdict.get(self._panels))
287 ncol=1
288 if self._stacking is not None:
289 ncol = eval(self._cdict.get(colmode))
290 self._plotter.set_panels()
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 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)
303 if n>1:
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
325 if colmode == 's':
326 scan = j
327 elif colmode == 't':
328 rowsel = j
329 else:
330 savei = i
331 if colmode == 'p':
332 polmode = self._polmode[self._cursor["p"].index(j)]
333 i = j
334 eval(cdict.get(colmode))
335 i = savei
336 x = None
337 y = None
338 m = None
339 x,xlab = scan.get_abcissa(rowsel)
340 if self._abcissa: xlab = self._abcissa
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
348 if self._ordinate:
349 ylab = self._ordinate
350 else:
351 ylab = 'Flux ('+scan.get_fluxunit()+')'
352 m = scan._getmask(rowsel)
353 if colmode == 's' or colmode == 't':
354 if self._title and len(self._title) > 0:
355 tlab = self._title[ii]
356 else:
357 tlab = self._ldict.get(self._panels)+' '+str(i)
358 llab = scan._getsourcename(rowsel)
359 else:
360 if self._title and len(self._title) > 0:
361 tlab = self._title[ii]
362 else:
363 tlab = self._ldict.get(self._panels)+' '+str(i)
364 if self._lmap and len(self._lmap) > 0:
365 llab = self._lmap[jj]
366 else:
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)
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
395 def set_mode(self, stacking=None, panelling=None):
396 """
397 Set the plots look and feel, i.e. what you want to see on the plot.
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"
413 return
414 if not self.set_stacking(stacking):
415 print "Invalid mode"
416 return
417 if self._data: self.plot()
418 return
419
420 def set_panels(self, what=None):
421 if not what:
422 what = rcParams['plotter.panelling']
423 md = self._translate(what)
424 if md:
425 self._panels = md
426 self._title = None
427 return True
428 return False
429
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
446 def set_stacking(self, what=None):
447 if not what:
448 what = rcParams['plotter.stacking']
449 md = self._translate(what)
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 if self._data: self.plot()
469 return
470 if ystart is None and yend is None:
471 self._minmaxy = None
472 if self._data: self.plot()
473 return
474 self._minmaxx = [xstart,xend]
475 self._minmaxy = [ystart,yend]
476 if self._data: self.plot()
477 return
478
479 def set_legend(self, mp=None):
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:
489 If the data has two IFs/rest frequencies with index 0 and 1
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
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
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
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
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"])
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 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
629if __name__ == '__main__':
630 plotter = asapplotter()
Note: See TracBrowser for help on using the repository browser.