source: trunk/python/asapplotter.py@ 560

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

bug fix in mode == 'p' indexing

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