source: trunk/python/asapplotter.py@ 602

Last change on this file since 602 was 600, checked in by mar637, 20 years ago

Fixed asap0008 and asap0014

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