source: trunk/python/asapplotter.py@ 554

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

Fixed asaprc set_mode issues.
Fixed set_cursor range detection

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