source: trunk/python/asapplotter.py@ 2693

Last change on this file since 2693 was 2693, checked in by Kana Sugimoto, 12 years ago

New Development: Yes

JIRA Issue: Yes (Trac-287)

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed: a new method, asapplotter.plotpointings2

Test Programs:

Put in Release Notes: No

Module(s): asapplotter, sdplot

Description:

a new method, asapplotter.plotpointings2, is created.
This method will be supposed to replace asapplotter.plotpointing
in near future if there's no issue found.
plotpointings2 plots pointing directions of a scantable.
It is possible to plot pointings of different source type, scanno,
ifno, polno, or beamno in different colors by setting the 'colorby'
paramter. When showline=True, the scan pattern is plotted in dotted
line.
This function alway plots pointings on ASAP plotter and works properly
with custom toolbar.


  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 78.1 KB
RevLine 
[1824]1from asap.parameters import rcParams
2from asap.selector import selector
3from asap.scantable import scantable
[1862]4from asap.logging import asaplog, asaplog_post_dec
[1153]5import matplotlib.axes
[1556]6from matplotlib.font_manager import FontProperties
7from matplotlib.text import Text
[2535]8from matplotlib import _pylab_helpers
[1556]9
[1317]10import re
[203]11
[2150]12def new_asaplot(visible=None,**kwargs):
13 """
14 Returns a new asaplot instance based on the backend settings.
15 """
16 if visible == None:
17 visible = rcParams['plotter.gui']
18
19 backend=matplotlib.get_backend()
20 if not visible:
21 from asap.asaplot import asaplot
22 elif backend == 'TkAgg':
23 from asap.asaplotgui import asaplotgui as asaplot
24 elif backend == 'Qt4Agg':
25 from asap.asaplotgui_qt4 import asaplotgui as asaplot
26 elif backend == 'GTkAgg':
27 from asap.asaplotgui_gtk import asaplotgui as asaplot
28 else:
29 from asap.asaplot import asaplot
30 return asaplot(**kwargs)
31
[203]32class asapplotter:
[226]33 """
34 The ASAP plotter.
35 By default the plotter is set up to plot polarisations
36 'colour stacked' and scantables across panels.
[1858]37
38 .. note::
39
[226]40 Currenly it only plots 'spectra' not Tsys or
41 other variables.
[1858]42
[226]43 """
[1563]44 def __init__(self, visible=None , **kwargs):
[734]45 self._visible = rcParams['plotter.gui']
46 if visible is not None:
47 self._visible = visible
[2451]48 self._plotter = None
49 self._inikwg = kwargs
[710]50
[554]51 self._panelling = None
52 self._stacking = None
53 self.set_panelling()
54 self.set_stacking()
[377]55 self._rows = None
56 self._cols = None
[525]57 self._minmaxx = None
58 self._minmaxy = None
[710]59 self._datamask = None
[203]60 self._data = None
[607]61 self._lmap = None
[226]62 self._title = None
[257]63 self._ordinate = None
64 self._abcissa = None
[709]65 self._abcunit = None
[920]66 self._usermask = []
67 self._maskselection = None
68 self._selection = selector()
[1023]69 self._hist = rcParams['plotter.histogram']
[1556]70 self._fp = FontProperties()
[2037]71 self._margins = self.set_margin(refresh=False)
[1897]72 self._offset = None
[1981]73 self._startrow = 0
74 self._ipanel = -1
75 self._panelrows = []
[2053]76 self._headtext={'string': None, 'textobj': None}
[2451]77 self._colormap = None
78 self._linestyles = None
79 self._legendloc = None
[1023]80
[920]81 def _translate(self, instr):
[1910]82 keys = "s b i p t r".split()
[920]83 if isinstance(instr, str):
84 for key in keys:
85 if instr.lower().startswith(key):
86 return key
87 return None
88
[2535]89 @asaplog_post_dec
[2451]90 def _reload_plotter(self):
91 if self._plotter is not None:
[2535]92 #if not self._plotter.is_dead:
93 # # clear lines and axes
94 # try:
95 # self._plotter.clear()
96 # except: # Can't remove when already killed.
97 # pass
[2451]98 if self.casabar_exists():
99 del self._plotter.figmgr.casabar
100 self._plotter.quit()
101 del self._plotter
[2535]102 asaplog.push('Loading new plotter')
[2451]103 self._plotter = new_asaplot(self._visible,**self._inikwg)
104 self._plotter.figmgr.casabar=self._new_custombar()
105 # just to make sure they're set
106 self._plotter.palette(color=0,colormap=self._colormap,
107 linestyle=0,linestyles=self._linestyles)
108 self._plotter.legend(self._legendloc)
[710]109
[2173]110 def _new_custombar(self):
[1819]111 backend=matplotlib.get_backend()
[2168]112 if not self._visible:
113 return None
114 elif backend == "TkAgg":
[2155]115 from asap.customgui_tkagg import CustomToolbarTkAgg
[1819]116 return CustomToolbarTkAgg(self)
[2168]117 elif backend == "Qt4Agg":
118 from asap.customgui_qt4agg import CustomToolbarQT4Agg
119 return CustomToolbarQT4Agg(self)
[1995]120 return None
[1819]121
[2147]122 def casabar_exists(self):
123 if not hasattr(self._plotter.figmgr,'casabar'):
124 return False
125 elif self._plotter.figmgr.casabar:
126 return True
127 return False
128
[2453]129 def _assert_plotter(self,action="status",errmsg=None):
[2451]130 """
[2453]131 Check plot window status. Returns True if plot window is alive.
[2451]132 Parameters
[2453]133 action: An action to take if the plotter window is not alive.
134 ['status'|'reload'|'halt']
135 The action 'status' simply returns False if asaplot
136 is not alive. When action='reload', plot window is
137 reloaded and the method returns True. Finally, an
138 error is raised when action='halt'.
[2451]139 errmsg: An error (warning) message to send to the logger,
[2453]140 when plot window is not alive.
[2451]141 """
[2538]142 isAlive = (self._plotter is not None) and self._plotter._alive()
[2535]143 # More tests
[2538]144 #if isAlive:
145 # if self._plotter.figmgr:
146 # figmgr = self._plotter.figmgr
147 # figid = figmgr.num
148 # # Make sure figid=0 is what asapplotter expects.
149 # # It might be already destroied/overridden by matplotlib
150 # # commands or other plotting methods using asaplot.
151 # isAlive = _pylab_helpers.Gcf.has_fignum(figid) and \
152 # (figmgr == \
153 # _pylab_helpers.Gcf.get_fig_manager(figid))
154 # else:
155 # isAlive = False
[2535]156
157 if isAlive:
[2451]158 return True
159 # Plotter is not alive.
160 haltmsg = "Plotter window has not yet been loaded or is closed."
161 if type(errmsg)==str and len(errmsg) > 0:
162 haltmsg = errmsg
163
[2453]164 if action.upper().startswith("R"):
[2451]165 # reload plotter
166 self._reload_plotter()
167 return True
[2453]168 elif action.upper().startswith("H"):
[2451]169 # halt
170 asaplog.push(haltmsg)
171 asaplog.post("ERROR")
172 raise RuntimeError(haltmsg)
173 else:
174 if errmsg:
175 asaplog.push(errmsg)
176 asaplog.post("WARN")
177 return False
178
179
[1862]180 @asaplog_post_dec
[935]181 def plot(self, scan=None):
[203]182 """
[920]183 Plot a scantable.
[203]184 Parameters:
[920]185 scan: a scantable
[203]186 Note:
[920]187 If a scantable was specified in a previous call
[203]188 to plot, no argument has to be given to 'replot'
[920]189 NO checking is done that the abcissas of the scantable
[203]190 are consistent e.g. all 'channel' or all 'velocity' etc.
191 """
[2451]192 if not self._data and not scan:
193 msg = "Input is not a scantable"
194 raise TypeError(msg)
[1981]195 self._startrow = 0
196 self._ipanel = -1
[2056]197 self._reset_header()
[2451]198 self._panelrows = []
199
[2453]200 self._assert_plotter(action="reload")
[2147]201 if self.casabar_exists():
[1984]202 self._plotter.figmgr.casabar.set_pagecounter(1)
[2451]203
[600]204 self._plotter.hold()
[1945]205 #self._plotter.clear()
[1897]206 if scan:
207 self.set_data(scan, refresh=False)
[2451]208 self._plotter.palette(color=0,colormap=self._colormap,
209 linestyle=0,linestyles=self._linestyles)
210 self._plotter.legend(self._legendloc)
[920]211 self._plot(self._data)
[709]212 if self._minmaxy is not None:
213 self._plotter.set_limits(ylim=self._minmaxy)
[2147]214 if self.casabar_exists(): self._plotter.figmgr.casabar.enable_button()
[203]215 self._plotter.release()
[1153]216 self._plotter.tidy()
217 self._plotter.show(hardrefresh=False)
[203]218 return
219
[1572]220 def gca(self):
[2451]221 errmsg = "No axis to retun. Need to plot first."
[2453]222 if not self._assert_plotter(action="status",errmsg=errmsg):
[2451]223 return None
[1572]224 return self._plotter.figure.gca()
225
[1550]226 def refresh(self):
[1572]227 """Do a soft refresh"""
[2451]228 errmsg = "No figure to re-plot. Need to plot first."
[2453]229 self._assert_plotter(action="halt",errmsg=errmsg)
[2451]230
[1550]231 self._plotter.figure.show()
232
[1555]233 def create_mask(self, nwin=1, panel=0, color=None):
[1597]234 """
[1927]235 Interactively define a mask. It retruns a mask that is equivalent to
[1597]236 the one created manually with scantable.create_mask.
237 Parameters:
238 nwin: The number of mask windows to create interactively
239 default is 1.
240 panel: Which panel to use for mask selection. This is useful
241 if different IFs are spread over panels (default 0)
242 """
[2451]243 ## this method relies on already plotted figure
[2453]244 if not self._assert_plotter(action="status") or (self._data is None):
[2451]245 msg = "Cannot create mask interactively on plot. Can only create mask after plotting."
246 asaplog.push( msg )
247 asaplog.post( "ERROR" )
[1555]248 return []
[1547]249 outmask = []
[1549]250 self._plotter.subplot(panel)
251 xmin, xmax = self._plotter.axes.get_xlim()
[1548]252 marg = 0.05*(xmax-xmin)
[1549]253 self._plotter.axes.set_xlim(xmin-marg, xmax+marg)
[1550]254 self.refresh()
[1695]255
[1555]256 def cleanup(lines=False, texts=False, refresh=False):
257 if lines:
258 del self._plotter.axes.lines[-1]
259 if texts:
260 del self._plotter.axes.texts[-1]
261 if refresh:
262 self.refresh()
263
264 for w in xrange(nwin):
[1547]265 wpos = []
[1695]266 self.text(0.05,1.0, "Add start boundary",
[1555]267 coords="relative", fontsize=10)
268 point = self._plotter.get_point()
269 cleanup(texts=True)
270 if point is None:
271 continue
272 wpos.append(point[0])
[1695]273 self.axvline(wpos[0], color=color)
[1551]274 self.text(0.05,1.0, "Add end boundary", coords="relative", fontsize=10)
[1555]275 point = self._plotter.get_point()
276 cleanup(texts=True, lines=True)
277 if point is None:
278 self.refresh()
279 continue
280 wpos.append(point[0])
281 self.axvspan(wpos[0], wpos[1], alpha=0.1,
282 edgecolor=color, facecolor=color)
283 ymin, ymax = self._plotter.axes.get_ylim()
[1547]284 outmask.append(wpos)
[1153]285
[1555]286 self._plotter.axes.set_xlim(xmin, xmax)
287 self.refresh()
288 if len(outmask) > 0:
289 return self._data.create_mask(*outmask)
290 return []
291
[1153]292 # forwards to matplotlib axes
293 def text(self, *args, **kwargs):
[2453]294 self._assert_plotter(action="reload")
[1547]295 if kwargs.has_key("interactive"):
296 if kwargs.pop("interactive"):
297 pos = self._plotter.get_point()
298 args = tuple(pos)+args
[1153]299 self._axes_callback("text", *args, **kwargs)
[1547]300
[1358]301 text.__doc__ = matplotlib.axes.Axes.text.__doc__
[1559]302
[1153]303 def arrow(self, *args, **kwargs):
[2453]304 self._assert_plotter(action="reload")
[1547]305 if kwargs.has_key("interactive"):
306 if kwargs.pop("interactive"):
307 pos = self._plotter.get_region()
308 dpos = (pos[0][0], pos[0][1],
309 pos[1][0]-pos[0][0],
310 pos[1][1] - pos[0][1])
311 args = dpos + args
[1153]312 self._axes_callback("arrow", *args, **kwargs)
[1547]313
[1358]314 arrow.__doc__ = matplotlib.axes.Axes.arrow.__doc__
[1559]315
316 def annotate(self, text, xy=None, xytext=None, **kwargs):
[2453]317 self._assert_plotter(action="reload")
[1559]318 if kwargs.has_key("interactive"):
319 if kwargs.pop("interactive"):
320 xy = self._plotter.get_point()
321 xytext = self._plotter.get_point()
322 if not kwargs.has_key("arrowprops"):
323 kwargs["arrowprops"] = dict(arrowstyle="->")
324 self._axes_callback("annotate", text, xy, xytext, **kwargs)
325
326 annotate.__doc__ = matplotlib.axes.Axes.annotate.__doc__
327
[1153]328 def axvline(self, *args, **kwargs):
[2453]329 self._assert_plotter(action="reload")
[1547]330 if kwargs.has_key("interactive"):
331 if kwargs.pop("interactive"):
332 pos = self._plotter.get_point()
333 args = (pos[0],)+args
[1153]334 self._axes_callback("axvline", *args, **kwargs)
[1559]335
[1358]336 axvline.__doc__ = matplotlib.axes.Axes.axvline.__doc__
[1547]337
[1153]338 def axhline(self, *args, **kwargs):
[2453]339 self._assert_plotter(action="reload")
[1547]340 if kwargs.has_key("interactive"):
341 if kwargs.pop("interactive"):
342 pos = self._plotter.get_point()
343 args = (pos[1],)+args
[1153]344 self._axes_callback("axhline", *args, **kwargs)
[1559]345
[1358]346 axhline.__doc__ = matplotlib.axes.Axes.axhline.__doc__
[1547]347
[1153]348 def axvspan(self, *args, **kwargs):
[2453]349 self._assert_plotter(action="reload")
[1547]350 if kwargs.has_key("interactive"):
351 if kwargs.pop("interactive"):
352 pos = self._plotter.get_region()
353 dpos = (pos[0][0], pos[1][0])
354 args = dpos + args
[1153]355 self._axes_callback("axvspan", *args, **kwargs)
356 # hack to preventy mpl from redrawing the patch
357 # it seem to convert the patch into lines on every draw.
358 # This doesn't happen in a test script???
[1547]359 #del self._plotter.axes.patches[-1]
360
[1358]361 axvspan.__doc__ = matplotlib.axes.Axes.axvspan.__doc__
[1232]362
[1153]363 def axhspan(self, *args, **kwargs):
[2453]364 self._assert_plotter(action="reload")
[1547]365 if kwargs.has_key("interactive"):
366 if kwargs.pop("interactive"):
367 pos = self._plotter.get_region()
368 dpos = (pos[0][1], pos[1][1])
369 args = dpos + args
[1232]370 self._axes_callback("axhspan", *args, **kwargs)
[1153]371 # hack to preventy mpl from redrawing the patch
372 # it seem to convert the patch into lines on every draw.
373 # This doesn't happen in a test script???
[1547]374 #del self._plotter.axes.patches[-1]
[1559]375
[1358]376 axhspan.__doc__ = matplotlib.axes.Axes.axhspan.__doc__
[1153]377
378 def _axes_callback(self, axesfunc, *args, **kwargs):
[2453]379 self._assert_plotter(action="reload")
[1153]380 panel = 0
381 if kwargs.has_key("panel"):
382 panel = kwargs.pop("panel")
383 coords = None
384 if kwargs.has_key("coords"):
385 coords = kwargs.pop("coords")
386 if coords.lower() == 'world':
387 kwargs["transform"] = self._plotter.axes.transData
388 elif coords.lower() == 'relative':
389 kwargs["transform"] = self._plotter.axes.transAxes
390 self._plotter.subplot(panel)
391 self._plotter.axes.set_autoscale_on(False)
392 getattr(self._plotter.axes, axesfunc)(*args, **kwargs)
393 self._plotter.show(False)
394 self._plotter.axes.set_autoscale_on(True)
395 # end matplotlib.axes fowarding functions
396
[1862]397 @asaplog_post_dec
[1819]398 def set_data(self, scan, refresh=True):
399 """
[1824]400 Set a scantable to plot.
[1819]401 Parameters:
402 scan: a scantable
403 refresh: True (default) or False. If True, the plot is
[1824]404 replotted based on the new parameter setting(s).
[1819]405 Otherwise,the parameter(s) are set without replotting.
406 Note:
407 The user specified masks and data selections will be reset
408 if a new scantable is set. This method should be called before
[1824]409 setting data selections (set_selection) and/or masks (set_mask).
[1819]410 """
411 from asap import scantable
412 if isinstance(scan, scantable):
[2604]413 if (self._data is not None) and (scan != self._data):
414 del self._data
415 msg = "A new scantable is set to the plotter. "\
416 "The masks and data selections are reset."
417 asaplog.push( msg )
418 self._data = scan
419 # reset
420 self._reset()
[1819]421 else:
422 msg = "Input is not a scantable"
423 raise TypeError(msg)
[1547]424
[1819]425 # ranges become invalid when unit changes
426 if self._abcunit and self._abcunit != self._data.get_unit():
427 self._minmaxx = None
428 self._minmaxy = None
429 self._abcunit = self._data.get_unit()
430 self._datamask = None
431 if refresh: self.plot()
432
[1862]433 @asaplog_post_dec
[1819]434 def set_mode(self, stacking=None, panelling=None, refresh=True):
[203]435 """
[377]436 Set the plots look and feel, i.e. what you want to see on the plot.
[203]437 Parameters:
438 stacking: tell the plotter which variable to plot
[1217]439 as line colour overlays (default 'pol')
[203]440 panelling: tell the plotter which variable to plot
441 across multiple panels (default 'scan'
[1819]442 refresh: True (default) or False. If True, the plot is
[1824]443 replotted based on the new parameter setting(s).
[1819]444 Otherwise,the parameter(s) are set without replotting.
[203]445 Note:
446 Valid modes are:
447 'beam' 'Beam' 'b': Beams
448 'if' 'IF' 'i': IFs
449 'pol' 'Pol' 'p': Polarisations
450 'scan' 'Scan' 's': Scans
451 'time' 'Time' 't': Times
[1989]452 'row' 'Row' 'r': Rows
453 When either 'stacking' or 'panelling' is set to 'row',
454 the other parameter setting is ignored.
[203]455 """
[753]456 msg = "Invalid mode"
457 if not self.set_panelling(panelling) or \
458 not self.set_stacking(stacking):
[1859]459 raise TypeError(msg)
[1989]460 #if self._panelling == 'r':
461 # self._stacking = '_r'
462 #if self._stacking == 'r':
463 # self._panelling = '_r'
[1819]464 if refresh and self._data: self.plot(self._data)
[203]465 return
466
[554]467 def set_panelling(self, what=None):
[1858]468 """Set the 'panelling' mode i.e. which type of spectra should be
469 spread across different panels.
470 """
471
[554]472 mode = what
473 if mode is None:
474 mode = rcParams['plotter.panelling']
475 md = self._translate(mode)
[203]476 if md:
[554]477 self._panelling = md
[226]478 self._title = None
[1989]479 #if md == 'r':
480 # self._stacking = '_r'
[1981]481 # you need to reset counters for multi page plotting
482 self._reset_counters()
[203]483 return True
484 return False
485
[1819]486 def set_layout(self,rows=None,cols=None,refresh=True):
[377]487 """
488 Set the multi-panel layout, i.e. how many rows and columns plots
489 are visible.
490 Parameters:
491 rows: The number of rows of plots
492 cols: The number of columns of plots
[1819]493 refresh: True (default) or False. If True, the plot is
[1824]494 replotted based on the new parameter setting(s).
[1819]495 Otherwise,the parameter(s) are set without replotting.
[377]496 Note:
497 If no argument is given, the potter reverts to its auto-plot
498 behaviour.
499 """
500 self._rows = rows
501 self._cols = cols
[1819]502 if refresh and self._data: self.plot(self._data)
[377]503 return
504
[709]505 def set_stacking(self, what=None):
[1858]506 """Set the 'stacking' mode i.e. which type of spectra should be
507 overlayed.
508 """
[554]509 mode = what
[709]510 if mode is None:
511 mode = rcParams['plotter.stacking']
[554]512 md = self._translate(mode)
[203]513 if md:
514 self._stacking = md
[226]515 self._lmap = None
[1989]516 #if md == 'r':
517 # self._panelling = '_r'
[1981]518 # you need to reset counters for multi page plotting
519 self._reset_counters()
[203]520 return True
521 return False
522
[1981]523 def _reset_counters(self):
524 self._startrow = 0
525 self._ipanel = -1
526 self._panelrows = []
527
[1897]528 def set_range(self,xstart=None,xend=None,ystart=None,yend=None,refresh=True, offset=None):
[203]529 """
530 Set the range of interest on the abcissa of the plot
531 Parameters:
[525]532 [x,y]start,[x,y]end: The start and end points of the 'zoom' window
[1819]533 refresh: True (default) or False. If True, the plot is
[1824]534 replotted based on the new parameter setting(s).
[1819]535 Otherwise,the parameter(s) are set without replotting.
[1897]536 offset: shift the abcissa by the given amount. The abcissa label will
537 have '(relative)' appended to it.
[203]538 Note:
539 These become non-sensical when the unit changes.
540 use plotter.set_range() without parameters to reset
541
542 """
[1897]543 self._offset = offset
[525]544 if xstart is None and xend is None:
545 self._minmaxx = None
[600]546 else:
547 self._minmaxx = [xstart,xend]
[525]548 if ystart is None and yend is None:
549 self._minmaxy = None
[600]550 else:
[709]551 self._minmaxy = [ystart,yend]
[1819]552 if refresh and self._data: self.plot(self._data)
[203]553 return
[709]554
[1819]555 def set_legend(self, mp=None, fontsize = None, mode = 0, refresh=True):
[203]556 """
557 Specify a mapping for the legend instead of using the default
558 indices:
559 Parameters:
[1101]560 mp: a list of 'strings'. This should have the same length
561 as the number of elements on the legend and then maps
562 to the indeces in order. It is possible to uses latex
563 math expression. These have to be enclosed in r'',
564 e.g. r'$x^{2}$'
565 fontsize: The font size of the label (default None)
566 mode: where to display the legend
567 Any other value for loc else disables the legend:
[1096]568 0: auto
569 1: upper right
570 2: upper left
571 3: lower left
572 4: lower right
573 5: right
574 6: center left
575 7: center right
576 8: lower center
577 9: upper center
578 10: center
[1819]579 refresh: True (default) or False. If True, the plot is
[1824]580 replotted based on the new parameter setting(s).
[1819]581 Otherwise,the parameter(s) are set without replotting.
[203]582
583 Example:
[485]584 If the data has two IFs/rest frequencies with index 0 and 1
[203]585 for CO and SiO:
586 plotter.set_stacking('i')
[710]587 plotter.set_legend(['CO','SiO'])
[203]588 plotter.plot()
[710]589 plotter.set_legend([r'$^{12}CO$', r'SiO'])
[203]590 """
591 self._lmap = mp
[2451]592 #self._plotter.legend(mode)
593 self._legendloc = mode
[1101]594 if isinstance(fontsize, int):
595 from matplotlib import rc as rcp
596 rcp('legend', fontsize=fontsize)
[1819]597 if refresh and self._data: self.plot(self._data)
[226]598 return
599
[1819]600 def set_title(self, title=None, fontsize=None, refresh=True):
[710]601 """
[2451]602 Set the title of sub-plots. If multiple sub-plots are plotted,
[710]603 multiple titles have to be specified.
[1819]604 Parameters:
[2451]605 title: a list of titles of sub-plots.
606 fontsize: a font size of titles (integer)
[1819]607 refresh: True (default) or False. If True, the plot is
[1824]608 replotted based on the new parameter setting(s).
[1819]609 Otherwise,the parameter(s) are set without replotting.
[710]610 Example:
611 # two panels are visible on the plotter
[2451]612 plotter.set_title(['First Panel','Second Panel'])
[710]613 """
[226]614 self._title = title
[1101]615 if isinstance(fontsize, int):
616 from matplotlib import rc as rcp
617 rcp('axes', titlesize=fontsize)
[1819]618 if refresh and self._data: self.plot(self._data)
[226]619 return
620
[1819]621 def set_ordinate(self, ordinate=None, fontsize=None, refresh=True):
[710]622 """
623 Set the y-axis label of the plot. If multiple panels are plotted,
624 multiple labels have to be specified.
[1021]625 Parameters:
626 ordinate: a list of ordinate labels. None (default) let
627 data determine the labels
[2451]628 fontsize: a font size of vertical axis labels (integer)
[1819]629 refresh: True (default) or False. If True, the plot is
[1824]630 replotted based on the new parameter setting(s).
[1819]631 Otherwise,the parameter(s) are set without replotting.
[710]632 Example:
633 # two panels are visible on the plotter
[2451]634 plotter.set_ordinate(['First Y-Axis','Second Y-Axis'])
[710]635 """
[257]636 self._ordinate = ordinate
[1101]637 if isinstance(fontsize, int):
638 from matplotlib import rc as rcp
639 rcp('axes', labelsize=fontsize)
640 rcp('ytick', labelsize=fontsize)
[1819]641 if refresh and self._data: self.plot(self._data)
[257]642 return
643
[1819]644 def set_abcissa(self, abcissa=None, fontsize=None, refresh=True):
[710]645 """
646 Set the x-axis label of the plot. If multiple panels are plotted,
647 multiple labels have to be specified.
[1021]648 Parameters:
649 abcissa: a list of abcissa labels. None (default) let
650 data determine the labels
[2451]651 fontsize: a font size of horizontal axis labels (integer)
[1819]652 refresh: True (default) or False. If True, the plot is
[1824]653 replotted based on the new parameter setting(s).
[1819]654 Otherwise,the parameter(s) are set without replotting.
[710]655 Example:
656 # two panels are visible on the plotter
[2451]657 plotter.set_ordinate(['First X-Axis','Second X-Axis'])
[710]658 """
[257]659 self._abcissa = abcissa
[1101]660 if isinstance(fontsize, int):
661 from matplotlib import rc as rcp
662 rcp('axes', labelsize=fontsize)
663 rcp('xtick', labelsize=fontsize)
[1819]664 if refresh and self._data: self.plot(self._data)
[257]665 return
666
[1819]667 def set_colors(self, colmap, refresh=True):
[377]668 """
[1217]669 Set the colours to be used. The plotter will cycle through
670 these colours when lines are overlaid (stacking mode).
[1021]671 Parameters:
[1217]672 colmap: a list of colour names
[1819]673 refresh: True (default) or False. If True, the plot is
[1824]674 replotted based on the new parameter setting(s).
[1819]675 Otherwise,the parameter(s) are set without replotting.
[710]676 Example:
[2451]677 plotter.set_colors('red green blue')
[710]678 # If for example four lines are overlaid e.g I Q U V
679 # 'I' will be 'red', 'Q' will be 'green', U will be 'blue'
680 # and 'V' will be 'red' again.
681 """
[2451]682 #if isinstance(colmap,str):
683 # colmap = colmap.split()
684 #self._plotter.palette(0, colormap=colmap)
685 self._colormap = colmap
[1819]686 if refresh and self._data: self.plot(self._data)
[710]687
[1217]688 # alias for english speakers
689 set_colours = set_colors
690
[1819]691 def set_histogram(self, hist=True, linewidth=None, refresh=True):
[1021]692 """
693 Enable/Disable histogram-like plotting.
694 Parameters:
695 hist: True (default) or False. The fisrt default
696 is taken from the .asaprc setting
697 plotter.histogram
[2451]698 linewidth: a line width
[1819]699 refresh: True (default) or False. If True, the plot is
[1824]700 replotted based on the new parameter setting(s).
[1819]701 Otherwise,the parameter(s) are set without replotting.
[1021]702 """
[1023]703 self._hist = hist
[1101]704 if isinstance(linewidth, float) or isinstance(linewidth, int):
705 from matplotlib import rc as rcp
706 rcp('lines', linewidth=linewidth)
[1819]707 if refresh and self._data: self.plot(self._data)
[1023]708
[1819]709 def set_linestyles(self, linestyles=None, linewidth=None, refresh=True):
[710]710 """
[734]711 Set the linestyles to be used. The plotter will cycle through
712 these linestyles when lines are overlaid (stacking mode) AND
713 only one color has been set.
[710]714 Parameters:
[2451]715 linestyles: a list of linestyles to use.
[710]716 'line', 'dashed', 'dotted', 'dashdot',
717 'dashdotdot' and 'dashdashdot' are
718 possible
[2451]719 linewidth: a line width
[1819]720 refresh: True (default) or False. If True, the plot is
[1824]721 replotted based on the new parameter setting(s).
[1819]722 Otherwise,the parameter(s) are set without replotting.
[710]723 Example:
[2451]724 plotter.set_colors('black')
725 plotter.set_linestyles('line dashed dotted dashdot')
[710]726 # If for example four lines are overlaid e.g I Q U V
727 # 'I' will be 'solid', 'Q' will be 'dashed',
728 # U will be 'dotted' and 'V' will be 'dashdot'.
729 """
[2451]730 #if isinstance(linestyles,str):
731 # linestyles = linestyles.split()
732 #self._plotter.palette(color=0,linestyle=0,linestyles=linestyles)
733 self._linestyles = linestyles
[1101]734 if isinstance(linewidth, float) or isinstance(linewidth, int):
735 from matplotlib import rc as rcp
736 rcp('lines', linewidth=linewidth)
[1819]737 if refresh and self._data: self.plot(self._data)
[710]738
[1819]739 def set_font(self, refresh=True,**kwargs):
[1101]740 """
741 Set font properties.
742 Parameters:
743 family: one of 'sans-serif', 'serif', 'cursive', 'fantasy', 'monospace'
744 style: one of 'normal' (or 'roman'), 'italic' or 'oblique'
745 weight: one of 'normal or 'bold'
746 size: the 'general' font size, individual elements can be adjusted
747 seperately
[1819]748 refresh: True (default) or False. If True, the plot is
[1824]749 replotted based on the new parameter setting(s).
[1819]750 Otherwise,the parameter(s) are set without replotting.
[1101]751 """
752 from matplotlib import rc as rcp
[1547]753 fdict = {}
754 for k,v in kwargs.iteritems():
755 if v:
756 fdict[k] = v
[1556]757 self._fp = FontProperties(**fdict)
[1819]758 if refresh and self._data: self.plot(self._data)
[1101]759
[2037]760 def set_margin(self,margin=[],refresh=True):
[1819]761 """
[2037]762 Set margins between subplots and plot edges.
[1819]763 Parameters:
[2037]764 margin: a list of margins in figure coordinate (0-1),
[1824]765 i.e., fraction of the figure width or height.
[1819]766 The order of elements should be:
767 [left, bottom, right, top, horizontal space btw panels,
[1824]768 vertical space btw panels].
[1819]769 refresh: True (default) or False. If True, the plot is
[1824]770 replotted based on the new parameter setting(s).
[1819]771 Otherwise,the parameter(s) are set without replotting.
772 Note
[2037]773 * When margin is not specified, the values are reset to the defaults
[1819]774 of matplotlib.
[1824]775 * If any element is set to be None, the current value is adopted.
[1819]776 """
[2037]777 if margin == []: self._margins=self._reset_margin()
[1824]778 else:
[2037]779 self._margins=[None]*6
780 self._margins[0:len(margin)]=margin
781 #print "panel margin set to ",self._margins
[1819]782 if refresh and self._data: self.plot(self._data)
783
[2037]784 def _reset_margin(self):
[1819]785 ks=map(lambda x: 'figure.subplot.'+x,
786 ['left','bottom','right','top','hspace','wspace'])
787 return map(matplotlib.rcParams.get,ks)
788
[1259]789 def plot_lines(self, linecat=None, doppler=0.0, deltachan=10, rotate=90.0,
[1146]790 location=None):
791 """
[1158]792 Plot a line catalog.
793 Parameters:
794 linecat: the linecatalog to plot
[1168]795 doppler: the velocity shift to apply to the frequencies
[1158]796 deltachan: the number of channels to include each side of the
797 line to determine a local maximum/minimum
[1927]798 rotate: the rotation (in degrees) for the text label (default 90.0)
[1158]799 location: the location of the line annotation from the 'top',
800 'bottom' or alternate (None - the default)
[1165]801 Notes:
802 If the spectrum is flagged no line will be drawn in that location.
[1146]803 """
[2451]804 errmsg = "Cannot plot spectral lines. Need to plot scantable first."
[2453]805 self._assert_plotter(action="halt",errmsg=errmsg)
[1259]806 if not self._data:
807 raise RuntimeError("No scantable has been plotted yet.")
[1146]808 from asap._asap import linecatalog
[1259]809 if not isinstance(linecat, linecatalog):
810 raise ValueError("'linecat' isn't of type linecatalog.")
811 if not self._data.get_unit().endswith("Hz"):
812 raise RuntimeError("Can only overlay linecatalogs when data is in frequency.")
[1739]813 from numpy import ma
[1146]814 for j in range(len(self._plotter.subplots)):
815 self._plotter.subplot(j)
816 lims = self._plotter.axes.get_xlim()
[1153]817 for row in range(linecat.nrow()):
[1259]818 # get_frequency returns MHz
819 base = { "GHz": 1000.0, "MHz": 1.0, "Hz": 1.0e-6 }
820 restf = linecat.get_frequency(row)/base[self._data.get_unit()]
[1165]821 c = 299792.458
[1174]822 freq = restf*(1.0-doppler/c)
[1146]823 if lims[0] < freq < lims[1]:
824 if location is None:
825 loc = 'bottom'
[1153]826 if row%2: loc='top'
[1146]827 else: loc = location
[1153]828 maxys = []
829 for line in self._plotter.axes.lines:
830 v = line._x
831 asc = v[0] < v[-1]
832
833 idx = None
834 if not asc:
835 if v[len(v)-1] <= freq <= v[0]:
836 i = len(v)-1
837 while i>=0 and v[i] < freq:
838 idx = i
839 i-=1
840 else:
841 if v[0] <= freq <= v[len(v)-1]:
842 i = 0
843 while i<len(v) and v[i] < freq:
844 idx = i
845 i+=1
846 if idx is not None:
847 lower = idx - deltachan
848 upper = idx + deltachan
849 if lower < 0: lower = 0
850 if upper > len(v): upper = len(v)
851 s = slice(lower, upper)
[1167]852 y = line._y[s]
[1165]853 maxy = ma.maximum(y)
854 if isinstance( maxy, float):
855 maxys.append(maxy)
[1164]856 if len(maxys):
857 peak = max(maxys)
[1165]858 if peak > self._plotter.axes.get_ylim()[1]:
859 loc = 'bottom'
[1164]860 else:
861 continue
[1157]862 self._plotter.vline_with_label(freq, peak,
863 linecat.get_name(row),
864 location=loc, rotate=rotate)
[1153]865 self._plotter.show(hardrefresh=False)
[1146]866
[1153]867
[710]868 def save(self, filename=None, orientation=None, dpi=None):
869 """
[1927]870 Save the plot to a file. The known formats are 'png', 'ps', 'eps'.
[377]871 Parameters:
872 filename: The name of the output file. This is optional
873 and autodetects the image format from the file
874 suffix. If non filename is specified a file
875 called 'yyyymmdd_hhmmss.png' is created in the
876 current directory.
[709]877 orientation: optional parameter for postscript only (not eps).
878 'landscape', 'portrait' or None (default) are valid.
879 If None is choosen for 'ps' output, the plot is
880 automatically oriented to fill the page.
[710]881 dpi: The dpi of the output non-ps plot
[377]882 """
[2451]883 errmsg = "Cannot save figure. Need to plot first."
[2453]884 self._assert_plotter(action="halt",errmsg=errmsg)
[2451]885
[709]886 self._plotter.save(filename,orientation,dpi)
[377]887 return
[709]888
[1862]889 @asaplog_post_dec
[1819]890 def set_mask(self, mask=None, selection=None, refresh=True):
[525]891 """
[734]892 Set a plotting mask for a specific polarization.
[2451]893 This is useful for masking out 'noise' Pangle outside a source.
[734]894 Parameters:
[920]895 mask: a mask from scantable.create_mask
896 selection: the spectra to apply the mask to.
[1819]897 refresh: True (default) or False. If True, the plot is
[1824]898 replotted based on the new parameter setting(s).
[1819]899 Otherwise,the parameter(s) are set without replotting.
[734]900 Example:
[920]901 select = selector()
[2451]902 select.setpolstrings('Pangle')
[920]903 plotter.set_mask(mymask, select)
[734]904 """
[710]905 if not self._data:
[920]906 msg = "Can only set mask after a first call to plot()"
[1859]907 raise RuntimeError(msg)
[920]908 if len(mask):
909 if isinstance(mask, list) or isinstance(mask, tuple):
910 self._usermask = array(mask)
[710]911 else:
[920]912 self._usermask = mask
913 if mask is None and selection is None:
914 self._usermask = []
915 self._maskselection = None
916 if isinstance(selection, selector):
[947]917 self._maskselection = {'b': selection.get_beams(),
918 's': selection.get_scans(),
919 'i': selection.get_ifs(),
920 'p': selection.get_pols(),
[920]921 't': [] }
[710]922 else:
[920]923 self._maskselection = None
[1819]924 if refresh: self.plot(self._data)
[710]925
[709]926 def _slice_indeces(self, data):
927 mn = self._minmaxx[0]
928 mx = self._minmaxx[1]
929 asc = data[0] < data[-1]
930 start=0
931 end = len(data)-1
932 inc = 1
933 if not asc:
934 start = len(data)-1
935 end = 0
936 inc = -1
937 # find min index
[1819]938 #while start > 0 and data[start] < mn:
939 # start+= inc
940 minind=start
941 for ind in xrange(start,end+inc,inc):
942 if data[ind] > mn: break
943 minind=ind
[709]944 # find max index
[1819]945 #while end > 0 and data[end] > mx:
946 # end-=inc
947 #if end > 0: end +=1
948 maxind=end
949 for ind in xrange(end,start-inc,-inc):
950 if data[ind] < mx: break
951 maxind=ind
952 start=minind
953 end=maxind
[709]954 if start > end:
[1819]955 return end,start+1
956 elif start < end:
957 return start,end+1
958 else:
959 return start,end
[709]960
[710]961 def _reset(self):
[920]962 self._usermask = []
[710]963 self._usermaskspectra = None
[1897]964 self._offset = None
[920]965 self.set_selection(None, False)
[2051]966 self._reset_header()
[920]967
[2051]968 def _reset_header(self):
[2053]969 self._headtext={'string': None, 'textobj': None}
[2051]970
[920]971 def _plot(self, scan):
[947]972 savesel = scan.get_selection()
973 sel = savesel + self._selection
[1910]974 order = self._get_sortstring([self._panelling,self._stacking])
975 if order:
976 sel.set_order(order)
[947]977 scan.set_selection(sel)
[920]978 d = {'b': scan.getbeam, 's': scan.getscan,
[1949]979 'i': scan.getif, 'p': scan.getpol, 't': scan.get_time,
[1989]980 'r': int}#, '_r': int}
[920]981
[2650]982 polmodes = dict(zip(sel.get_pols(), sel.get_poltypes()))
[1148]983 # this returns either a tuple of numbers or a length (ncycles)
984 # convert this into lengths
985 n0,nstack0 = self._get_selected_n(scan)
986 if isinstance(n0, int): n = n0
[1175]987 else: n = len(n0)
[1148]988 if isinstance(nstack0, int): nstack = nstack0
[1175]989 else: nstack = len(nstack0)
[1989]990 # In case of row stacking
991 rowstack = False
992 titlemode = self._panelling
993 if self._stacking == "r" and self._panelling != "r":
994 rowstack = True
995 titlemode = '_r'
[1913]996 nptot = n
[1582]997 maxpanel, maxstack = 16,16
[1913]998 if nstack > maxstack:
999 msg ="Scan to be overlayed contains more than %d selections.\n" \
1000 "Selecting first %d selections..." % (maxstack, maxstack)
[920]1001 asaplog.push(msg)
[1861]1002 asaplog.post('WARN')
[998]1003 nstack = min(nstack,maxstack)
[2038]1004 #n = min(n-self._ipanel-1,maxpanel)
1005 n = n-self._ipanel-1
[2011]1006
1007 ganged = False
[920]1008 if n > 1:
1009 ganged = rcParams['plotter.ganged']
[1819]1010 if self._panelling == 'i':
1011 ganged = False
[920]1012 if self._rows and self._cols:
1013 n = min(n,self._rows*self._cols)
1014 self._plotter.set_panels(rows=self._rows,cols=self._cols,
[2650]1015 nplots=n,margin=self._margins,
1016 ganged=ganged)
[920]1017 else:
[2038]1018 n = min(n,maxpanel)
[2650]1019 self._plotter.set_panels(rows=n,cols=0,nplots=n,
1020 margin=self._margins,ganged=ganged)
[920]1021 else:
[2037]1022 self._plotter.set_panels(margin=self._margins)
[1913]1023 #r = 0
[1981]1024 r = self._startrow
[920]1025 nr = scan.nrow()
1026 a0,b0 = -1,-1
1027 allxlim = []
[1018]1028 allylim = []
[1981]1029 #newpanel=True
1030 newpanel=False
[920]1031 panelcount,stackcount = 0,0
[1981]1032 # If this is not the first page
1033 if r > 0:
1034 # panelling value of the prev page
1035 a0 = d[self._panelling](r-1)
1036 # set the initial stackcount large not to plot
1037 # the start row automatically
1038 stackcount = nstack
1039
[1002]1040 while r < nr:
[920]1041 a = d[self._panelling](r)
1042 b = d[self._stacking](r)
1043 if a > a0 and panelcount < n:
1044 if n > 1:
1045 self._plotter.subplot(panelcount)
1046 self._plotter.palette(0)
1047 #title
1048 xlab = self._abcissa and self._abcissa[panelcount] \
1049 or scan._getabcissalabel()
[1897]1050 if self._offset and not self._abcissa:
1051 xlab += " (relative)"
[920]1052 ylab = self._ordinate and self._ordinate[panelcount] \
1053 or scan._get_ordinate_label()
[1547]1054 self._plotter.set_axes('xlabel', xlab)
1055 self._plotter.set_axes('ylabel', ylab)
[1989]1056 #lbl = self._get_label(scan, r, self._panelling, self._title)
1057 lbl = self._get_label(scan, r, titlemode, self._title)
[920]1058 if isinstance(lbl, list) or isinstance(lbl, tuple):
1059 if 0 <= panelcount < len(lbl):
1060 lbl = lbl[panelcount]
1061 else:
1062 # get default label
[1989]1063 #lbl = self._get_label(scan, r, self._panelling, None)
1064 lbl = self._get_label(scan, r, titlemode, None)
[920]1065 self._plotter.set_axes('title',lbl)
1066 newpanel = True
[1913]1067 stackcount = 0
[920]1068 panelcount += 1
[1981]1069 # save the start row to plot this panel for future revisit.
1070 if self._panelling != 'r' and \
1071 len(self._panelrows) < self._ipanel+1+panelcount:
1072 self._panelrows += [r]
1073
[1944]1074 #if (b > b0 or newpanel) and stackcount < nstack:
[2650]1075 if stackcount < nstack and (newpanel or \
1076 rowstack or (a == a0 and b > b0)):
[920]1077 y = []
1078 if len(polmodes):
1079 y = scan._getspectrum(r, polmodes[scan.getpol(r)])
1080 else:
1081 y = scan._getspectrum(r)
[1995]1082 # flag application
1083 mr = scan._getflagrow(r)
[1739]1084 from numpy import ma, array
[1995]1085 if mr:
1086 y = ma.masked_array(y,mask=mr)
1087 else:
1088 m = scan._getmask(r)
1089 from numpy import logical_not, logical_and
1090 if self._maskselection and len(self._usermask) == len(m):
[2277]1091 if d[self._stacking](r) in self._maskselection[self._stacking]:
[1995]1092 m = logical_and(m, self._usermask)
[2277]1093 y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
[1995]1094
[1897]1095 x = array(scan._getabcissa(r))
1096 if self._offset:
1097 x += self._offset
[920]1098 if self._minmaxx is not None:
1099 s,e = self._slice_indeces(x)
1100 x = x[s:e]
1101 y = y[s:e]
[1096]1102 if len(x) > 1024 and rcParams['plotter.decimate']:
1103 fac = len(x)/1024
[920]1104 x = x[::fac]
1105 y = y[::fac]
1106 llbl = self._get_label(scan, r, self._stacking, self._lmap)
1107 if isinstance(llbl, list) or isinstance(llbl, tuple):
1108 if 0 <= stackcount < len(llbl):
1109 # use user label
1110 llbl = llbl[stackcount]
1111 else:
1112 # get default label
1113 llbl = self._get_label(scan, r, self._stacking, None)
1114 self._plotter.set_line(label=llbl)
[1023]1115 plotit = self._plotter.plot
1116 if self._hist: plotit = self._plotter.hist
[1995]1117 if len(x) > 0 and not mr:
[1146]1118 plotit(x,y)
1119 xlim= self._minmaxx or [min(x),max(x)]
1120 allxlim += xlim
1121 ylim= self._minmaxy or [ma.minimum(y),ma.maximum(y)]
1122 allylim += ylim
[1819]1123 else:
1124 xlim = self._minmaxx or []
1125 allxlim += xlim
1126 ylim= self._minmaxy or []
1127 allylim += ylim
[920]1128 stackcount += 1
[1981]1129 a0=a
1130 b0=b
[920]1131 # last in colour stack -> autoscale x
[1819]1132 if stackcount == nstack and len(allxlim) > 0:
[920]1133 allxlim.sort()
[1819]1134 self._plotter.subplots[panelcount-1]['axes'].set_xlim([allxlim[0],allxlim[-1]])
[1989]1135 if ganged:
1136 allxlim = [allxlim[0],allxlim[-1]]
1137 else:
1138 # clear
1139 allxlim =[]
[920]1140
1141 newpanel = False
[1981]1142 #a0=a
1143 #b0=b
[920]1144 # ignore following rows
[1981]1145 if (panelcount == n and stackcount == nstack) or (r == nr-1):
[1018]1146 # last panel -> autoscale y if ganged
[1989]1147 #if rcParams['plotter.ganged'] and len(allylim) > 0:
1148 if ganged and len(allylim) > 0:
[1018]1149 allylim.sort()
1150 self._plotter.set_limits(ylim=[allylim[0],allylim[-1]])
[998]1151 break
[920]1152 r+=1 # next row
[1981]1153
1154 # save the current counter for multi-page plotting
1155 self._startrow = r+1
1156 self._ipanel += panelcount
[2147]1157 if self.casabar_exists():
[1981]1158 if self._ipanel >= nptot-1:
[1913]1159 self._plotter.figmgr.casabar.disable_next()
1160 else:
1161 self._plotter.figmgr.casabar.enable_next()
[1981]1162 if self._ipanel + 1 - panelcount > 0:
1163 self._plotter.figmgr.casabar.enable_prev()
1164 else:
1165 self._plotter.figmgr.casabar.disable_prev()
1166
[947]1167 #reset the selector to the scantable's original
1168 scan.set_selection(savesel)
[1824]1169
[1819]1170 #temporary switch-off for older matplotlib
1171 #if self._fp is not None:
1172 if self._fp is not None and getattr(self._plotter.figure,'findobj',False):
[1556]1173 for o in self._plotter.figure.findobj(Text):
1174 o.set_fontproperties(self._fp)
[920]1175
[1910]1176 def _get_sortstring(self, lorders):
1177 d0 = {'s': 'SCANNO', 'b': 'BEAMNO', 'i':'IFNO',
1178 'p': 'POLNO', 'c': 'CYCLENO', 't' : 'TIME', 'r':None, '_r':None }
[1944]1179 if not (type(lorders) == list) and not (type(lorders) == tuple):
[1910]1180 return None
1181 if len(lorders) > 0:
1182 lsorts = []
1183 for order in lorders:
[1989]1184 if order == "r":
1185 # don't sort if row panelling/stacking
1186 return None
[1910]1187 ssort = d0[order]
1188 if ssort:
1189 lsorts.append(ssort)
1190 return lsorts
1191 return None
1192
[1582]1193 def set_selection(self, selection=None, refresh=True, **kw):
[1819]1194 """
1195 Parameters:
1196 selection: a selector object (default unset the selection)
1197 refresh: True (default) or False. If True, the plot is
[1824]1198 replotted based on the new parameter setting(s).
[1819]1199 Otherwise,the parameter(s) are set without replotting.
1200 """
[1582]1201 if selection is None:
1202 # reset
1203 if len(kw) == 0:
1204 self._selection = selector()
1205 else:
1206 # try keywords
1207 for k in kw:
1208 if k not in selector.fields:
1209 raise KeyError("Invalid selection key '%s', valid keys are %s" % (k, selector.fields))
1210 self._selection = selector(**kw)
1211 elif isinstance(selection, selector):
1212 self._selection = selection
1213 else:
1214 raise TypeError("'selection' is not of type selector")
1215
[1910]1216 order = self._get_sortstring([self._panelling,self._stacking])
1217 if order:
1218 self._selection.set_order(order)
[2650]1219 if refresh and self._data:
1220 self.plot()
[920]1221
1222 def _get_selected_n(self, scan):
[1148]1223 d1 = {'b': scan.getbeamnos, 's': scan.getscannos,
[1910]1224 'i': scan.getifnos, 'p': scan.getpolnos, 't': scan.ncycle,
[1989]1225 'r': scan.nrow}#, '_r': False}
[1148]1226 d2 = { 'b': self._selection.get_beams(),
1227 's': self._selection.get_scans(),
1228 'i': self._selection.get_ifs(),
1229 'p': self._selection.get_pols(),
[1910]1230 't': self._selection.get_cycles(),
[1989]1231 'r': False}#, '_r': 1}
[920]1232 n = d2[self._panelling] or d1[self._panelling]()
1233 nstack = d2[self._stacking] or d1[self._stacking]()
[1989]1234 # handle row panelling/stacking
1235 if self._panelling == 'r':
1236 nstack = 1
1237 elif self._stacking == 'r':
1238 n = 1
[920]1239 return n,nstack
1240
1241 def _get_label(self, scan, row, mode, userlabel=None):
[1153]1242 if isinstance(userlabel, list) and len(userlabel) == 0:
1243 userlabel = " "
[947]1244 pms = dict(zip(self._selection.get_pols(),self._selection.get_poltypes()))
[920]1245 if len(pms):
1246 poleval = scan._getpollabel(scan.getpol(row),pms[scan.getpol(row)])
1247 else:
1248 poleval = scan._getpollabel(scan.getpol(row),scan.poltype())
1249 d = {'b': "Beam "+str(scan.getbeam(row)),
[1819]1250 #'s': scan._getsourcename(row),
1251 's': "Scan "+str(scan.getscan(row))+\
1252 " ("+str(scan._getsourcename(row))+")",
[920]1253 'i': "IF"+str(scan.getif(row)),
[964]1254 'p': poleval,
[1910]1255 't': str(scan.get_time(row)),
1256 'r': "row "+str(row),
[1913]1257 #'_r': str(scan.get_time(row))+",\nIF"+str(scan.getif(row))+", "+poleval+", Beam"+str(scan.getbeam(row)) }
1258 '_r': "" }
[920]1259 return userlabel or d[mode]
[1153]1260
[1819]1261 def plotazel(self, scan=None, outfile=None):
[1391]1262 """
[1696]1263 plot azimuth and elevation versus time of a scantable
[1391]1264 """
[1923]1265 visible = rcParams['plotter.gui']
[1696]1266 from matplotlib import pylab as PL
[2586]1267 from matplotlib.dates import DateFormatter
1268 from pytz import timezone
[1696]1269 from matplotlib.dates import HourLocator, MinuteLocator,SecondLocator, DayLocator
[1391]1270 from matplotlib.ticker import MultipleLocator
[1739]1271 from numpy import array, pi
[1923]1272 if not visible or not self._visible:
1273 PL.ioff()
1274 from matplotlib.backends.backend_agg import FigureCanvasAgg
1275 PL.gcf().canvas.switch_backends(FigureCanvasAgg)
[1819]1276 self._data = scan
[1556]1277 dates = self._data.get_time(asdatetime=True)
[1391]1278 t = PL.date2num(dates)
1279 tz = timezone('UTC')
1280 PL.cla()
1281 PL.ioff()
1282 PL.clf()
[2037]1283 # Adjust subplot margins
[2576]1284 if not self._margins or len(self._margins) != 6:
[2037]1285 self.set_margin(refresh=False)
1286 lef, bot, rig, top, wsp, hsp = self._margins
[1819]1287 PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
1288 wspace=wsp,hspace=hsp)
[1824]1289
[1391]1290 tdel = max(t) - min(t)
1291 ax = PL.subplot(2,1,1)
1292 el = array(self._data.get_elevation())*180./pi
1293 PL.ylabel('El [deg.]')
1294 dstr = dates[0].strftime('%Y/%m/%d')
1295 if tdel > 1.0:
1296 dstr2 = dates[len(dates)-1].strftime('%Y/%m/%d')
1297 dstr = dstr + " - " + dstr2
1298 majloc = DayLocator()
1299 minloc = HourLocator(range(0,23,12))
1300 timefmt = DateFormatter("%b%d")
[1696]1301 elif tdel > 24./60.:
1302 timefmt = DateFormatter('%H:%M')
1303 majloc = HourLocator()
1304 minloc = MinuteLocator(30)
[1391]1305 else:
[1696]1306 timefmt = DateFormatter('%H:%M')
1307 majloc = MinuteLocator(interval=5)
1308 minloc = SecondLocator(30)
1309
[1391]1310 PL.title(dstr)
[1819]1311 if tdel == 0.0:
1312 th = (t - PL.floor(t))*24.0
1313 PL.plot(th,el,'o',markersize=2, markerfacecolor='b', markeredgecolor='b')
1314 else:
1315 PL.plot_date(t,el,'o', markersize=2, markerfacecolor='b', markeredgecolor='b',tz=tz)
1316 #ax.grid(True)
1317 ax.xaxis.set_major_formatter(timefmt)
1318 ax.xaxis.set_major_locator(majloc)
1319 ax.xaxis.set_minor_locator(minloc)
[1391]1320 ax.yaxis.grid(True)
[1819]1321 yloc = MultipleLocator(30)
1322 ax.set_ylim(0,90)
1323 ax.yaxis.set_major_locator(yloc)
[1391]1324 if tdel > 1.0:
1325 labels = ax.get_xticklabels()
1326 # PL.setp(labels, fontsize=10, rotation=45)
1327 PL.setp(labels, fontsize=10)
[1819]1328
[1391]1329 # Az plot
1330 az = array(self._data.get_azimuth())*180./pi
1331 if min(az) < 0:
1332 for irow in range(len(az)):
1333 if az[irow] < 0: az[irow] += 360.0
1334
[1819]1335 ax2 = PL.subplot(2,1,2)
1336 #PL.xlabel('Time (UT [hour])')
1337 PL.ylabel('Az [deg.]')
1338 if tdel == 0.0:
1339 PL.plot(th,az,'o',markersize=2, markeredgecolor='b',markerfacecolor='b')
1340 else:
1341 PL.plot_date(t,az,'o', markersize=2,markeredgecolor='b',markerfacecolor='b',tz=tz)
1342 ax2.xaxis.set_major_formatter(timefmt)
1343 ax2.xaxis.set_major_locator(majloc)
1344 ax2.xaxis.set_minor_locator(minloc)
1345 #ax2.grid(True)
1346 ax2.set_ylim(0,360)
[1696]1347 ax2.yaxis.grid(True)
[1819]1348 #hfmt = DateFormatter('%H')
1349 #hloc = HourLocator()
1350 yloc = MultipleLocator(60)
1351 ax2.yaxis.set_major_locator(yloc)
1352 if tdel > 1.0:
1353 labels = ax2.get_xticklabels()
1354 PL.setp(labels, fontsize=10)
1355 PL.xlabel('Time (UT [day])')
1356 else:
1357 PL.xlabel('Time (UT [hour])')
1358
[1391]1359 PL.ion()
1360 PL.draw()
[2416]1361 if matplotlib.get_backend() == 'Qt4Agg': PL.gcf().show()
[2576]1362 if (outfile is not None):
1363 PL.savefig(outfile)
[1391]1364
[2693]1365
1366 def plotpointing2(self, scan=None, colorby='', showline=False, projection=''):
1367 """
1368 plot telescope pointings
1369 Parameters:
1370 infile : input filename or scantable instance
1371 colorby : change color by either
1372 'type'(source type)|'scan'|'if'|'pol'|'beam'
1373 showline : show dotted line
1374 projection : projection type either
1375 ''(no projection [deg])|'coord'(not implemented)
1376 """
1377 from numpy import array, pi
1378 from asap import scantable
1379 # check for scantable
1380 if isinstance(scan, scantable):
1381 if self._data is not None:
1382 if scan != self._data:
1383 self._data = scan
1384 # reset
1385 self._reset()
1386 else:
1387 self._data = scan
1388 self._reset()
1389 if not self._data:
1390 msg = "Input is not a scantable"
1391 raise TypeError(msg)
1392 # check for color mode
1393 validtypes=['type','scan','if','pol', 'beam']
1394 stype = None
1395 if (colorby in validtypes):
1396 stype = colorby[0]
1397 elif len(colorby) > 0:
1398 msg = "Invalid choice of 'colorby' (choices: %s)" % str(validtypes)
1399 raise ValueError(msg)
1400 self._assert_plotter(action="reload")
1401 self._plotter.hold()
1402 if self.casabar_exists(): self._plotter.figmgr.casabar.disable_button()
1403 # for now, only one plot
1404 self._plotter.set_panels(rows=1,cols=1)
1405 # first panel
1406 self._plotter.subplot(0)
1407 # first color and linestyles
1408 self._plotter.palette(0)
1409 self.gca().set_aspect('equal')
1410 basesel = scan.get_selection()
1411 marker = "+"
1412 if showline:
1413 basesel.set_order(["TIME"])
1414 scan.set_selection(basesel)
1415 if not (stype in ["t", "s"]):
1416 marker = "+:"
1417 if not stype:
1418 selIds = [""] # cheating
1419 sellab = "all points"
1420 elif stype == 't':
1421 selIds = range(15)
1422 sellab = "src type "
1423 else:
1424 selIds = getattr(self._data,'get'+colorby+'nos')()
1425 sellab = colorby.upper()
1426 selFunc = "set_"+colorby+"s"
1427 for idx in selIds:
1428 sel = selector() + basesel
1429 if stype:
1430 bid = getattr(basesel,'get_'+colorby+"s")()
1431 if (len(bid) > 0) and (not idx in bid):
1432 # base selection doesn't contain idx
1433 # Note summation of selector is logical sum if
1434 continue
1435 getattr(sel, selFunc)([idx])
1436 if not sel.is_empty():
1437 try:
1438 self._data.set_selection(sel)
1439 except RuntimeError, instance:
1440 if stype == 't' and str(instance).startswith("Selection contains no data."):
1441 continue
1442 else:
1443 self._data.set_selection(basesel)
1444 raise RuntimeError, instance
1445 if self._data.nrow() == 0:
1446 self._data.set_selection(basesel)
1447 continue
1448 print "Plotting direction of %s = %s" % (colorby, str(idx))
1449 dir = array(self._data.get_directionval()).transpose()
1450 ra = dir[0]*180./pi
1451 dec = dir[1]*180./pi
1452 self._plotter.set_line(label=(sellab+str(idx)))
1453 self._plotter.plot(ra,dec,marker)
1454
1455 # restore original selection
1456 self._data.set_selection(basesel)
1457 # need to plot scan pattern explicitly
1458 if showline and (stype in ["t", "s"]):
1459 dir = array(self._data.get_directionval()).transpose()
1460 ra = dir[0]*180./pi
1461 dec = dir[1]*180./pi
1462 self._plotter.set_line(label="scan pattern")
1463 self._plotter.plot(ra,dec,":")
1464
1465 xlab = 'RA [deg.]'
1466 ylab = 'Declination [deg.]'
1467 self._plotter.set_axes('xlabel', xlab)
1468 self._plotter.set_axes('ylabel', ylab)
1469 self._plotter.set_axes('title', 'Telescope pointings')
1470 if stype: self._plotter.legend(self._legendloc)
1471 else: self._plotter.legend(None)
1472 # reverse x-axis
1473 xmin, xmax = self.gca().get_xlim()
1474 self._plotter.set_limits(xlim=[xmax,xmin])
1475
1476 self._plotter.release()
1477 self._plotter.show(hardrefresh=False)
1478 return
1479
[1819]1480 def plotpointing(self, scan=None, outfile=None):
[1391]1481 """
1482 plot telescope pointings
1483 """
[1923]1484 visible = rcParams['plotter.gui']
[1696]1485 from matplotlib import pylab as PL
[1819]1486 from numpy import array, pi
[1923]1487 if not visible or not self._visible:
1488 PL.ioff()
1489 from matplotlib.backends.backend_agg import FigureCanvasAgg
1490 PL.gcf().canvas.switch_backends(FigureCanvasAgg)
[1819]1491 self._data = scan
[1391]1492 dir = array(self._data.get_directionval()).transpose()
1493 ra = dir[0]*180./pi
1494 dec = dir[1]*180./pi
1495 PL.cla()
[1819]1496 #PL.ioff()
[1391]1497 PL.clf()
[2037]1498 # Adjust subplot margins
[2576]1499 if not self._margins or len(self._margins) != 6:
[2037]1500 self.set_margin(refresh=False)
1501 lef, bot, rig, top, wsp, hsp = self._margins
[1819]1502 PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
1503 wspace=wsp,hspace=hsp)
1504 ax = PL.gca()
1505 #ax = PL.axes([0.1,0.1,0.8,0.8])
1506 #ax = PL.axes([0.1,0.1,0.8,0.8])
[1391]1507 ax.set_aspect('equal')
[1696]1508 PL.plot(ra, dec, 'b,')
[1391]1509 PL.xlabel('RA [deg.]')
1510 PL.ylabel('Declination [deg.]')
1511 PL.title('Telescope pointings')
1512 [xmin,xmax,ymin,ymax] = PL.axis()
1513 PL.axis([xmax,xmin,ymin,ymax])
[2416]1514 PL.ion()
[1391]1515 PL.draw()
[2416]1516 if matplotlib.get_backend() == 'Qt4Agg': PL.gcf().show()
[2576]1517 if (outfile is not None):
1518 PL.savefig(outfile)
[1819]1519
1520 # plot total power data
1521 # plotting in time is not yet implemented..
[1862]1522 @asaplog_post_dec
[2576]1523 def plottp(self, scan=None):
[1819]1524 from asap import scantable
1525 if not self._data and not scan:
1526 msg = "Input is not a scantable"
1527 raise TypeError(msg)
1528 if isinstance(scan, scantable):
1529 if self._data is not None:
1530 if scan != self._data:
1531 self._data = scan
1532 # reset
1533 self._reset()
1534 else:
1535 self._data = scan
1536 self._reset()
1537 # ranges become invalid when abcissa changes?
1538 #if self._abcunit and self._abcunit != self._data.get_unit():
1539 # self._minmaxx = None
1540 # self._minmaxy = None
1541 # self._abcunit = self._data.get_unit()
1542 # self._datamask = None
1543
[2693]1544 self._assert_plotter(action="reload")
1545 self._plotter.hold()
1546 self._plotter.clear()
[2037]1547 # Adjust subplot margins
[2576]1548 if not self._margins or len(self._margins) !=6:
1549 self.set_margin(refresh=False)
[2037]1550 lef, bot, rig, top, wsp, hsp = self._margins
[1819]1551 self._plotter.figure.subplots_adjust(
1552 left=lef,bottom=bot,right=rig,top=top,wspace=wsp,hspace=hsp)
[2147]1553 if self.casabar_exists(): self._plotter.figmgr.casabar.disable_button()
[1819]1554 self._plottp(self._data)
1555 if self._minmaxy is not None:
1556 self._plotter.set_limits(ylim=self._minmaxy)
1557 self._plotter.release()
1558 self._plotter.tidy()
1559 self._plotter.show(hardrefresh=False)
1560 return
1561
1562 def _plottp(self,scan):
1563 """
1564 private method for plotting total power data
1565 """
1566 from numpy import ma, array, arange, logical_not
1567 r=0
1568 nr = scan.nrow()
1569 a0,b0 = -1,-1
1570 allxlim = []
1571 allylim = []
1572 y=[]
1573 self._plotter.set_panels()
1574 self._plotter.palette(0)
1575 #title
1576 #xlab = self._abcissa and self._abcissa[panelcount] \
1577 # or scan._getabcissalabel()
1578 #ylab = self._ordinate and self._ordinate[panelcount] \
1579 # or scan._get_ordinate_label()
1580 xlab = self._abcissa or 'row number' #or Time
1581 ylab = self._ordinate or scan._get_ordinate_label()
1582 self._plotter.set_axes('xlabel',xlab)
1583 self._plotter.set_axes('ylabel',ylab)
1584 lbl = self._get_label(scan, r, 's', self._title)
1585 if isinstance(lbl, list) or isinstance(lbl, tuple):
1586 # if 0 <= panelcount < len(lbl):
1587 # lbl = lbl[panelcount]
1588 # else:
1589 # get default label
1590 lbl = self._get_label(scan, r, self._panelling, None)
1591 self._plotter.set_axes('title',lbl)
1592 y=array(scan._get_column(scan._getspectrum,-1))
1593 m = array(scan._get_column(scan._getmask,-1))
1594 y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
1595 x = arange(len(y))
1596 # try to handle spectral data somewhat...
1597 l,m = y.shape
1598 if m > 1:
1599 y=y.mean(axis=1)
1600 plotit = self._plotter.plot
1601 llbl = self._get_label(scan, r, self._stacking, None)
1602 self._plotter.set_line(label=llbl)
1603 if len(x) > 0:
1604 plotit(x,y)
1605
1606
1607 # forwards to matplotlib.Figure.text
1608 def figtext(self, *args, **kwargs):
1609 """
1610 Add text to figure at location x,y (relative 0-1 coords).
1611 This method forwards *args and **kwargs to a Matplotlib method,
1612 matplotlib.Figure.text.
1613 See the method help for detailed information.
1614 """
[2453]1615 self._assert_plotter(action="reload")
[1819]1616 self._plotter.text(*args, **kwargs)
1617 # end matplotlib.Figure.text forwarding function
1618
1619
1620 # printing header information
[1862]1621 @asaplog_post_dec
[2053]1622 def print_header(self, plot=True, fontsize=9, logger=False, selstr='', extrastr=''):
[1819]1623 """
1624 print data (scantable) header on the plot and/or logger.
[2056]1625 To plot the header on the plot, this method should be called after
1626 plotting spectra by the method, asapplotter.plot.
[1819]1627 Parameters:
[1824]1628 plot: whether or not print header info on the plot.
[2053]1629 fontsize: header font size (valid only plot=True)
[1819]1630 logger: whether or not print header info on the logger.
1631 selstr: additional selection string (not verified)
[2053]1632 extrastr: additional string to print at the beginning (not verified)
[1819]1633 """
[1859]1634 if not plot and not logger:
1635 return
1636 if not self._data:
1637 raise RuntimeError("No scantable has been set yet.")
[1824]1638 # Now header will be printed on plot and/or logger.
1639 # Get header information and format it.
[2112]1640 ssum=self._data._list_header()
[1819]1641 # Print Observation header to the upper-left corner of plot
[2290]1642 headstr=[ssum[0:ssum.find('Obs. Type:')]]
1643 headstr.append(ssum[ssum.find('Obs. Type:'):ssum.find('Flux Unit:')])
[2053]1644 if extrastr != '':
1645 headstr[0]=extrastr+'\n'+headstr[0]
1646 self._headtext['extrastr'] = extrastr
[2112]1647 if selstr != '':
1648 selstr += '\n'
1649 self._headtext['selstr'] = selstr
[2056]1650 ssel=(selstr+self._data.get_selection().__str__()+self._selection.__str__() or 'none')
[2053]1651 headstr.append('***Selections***\n'+ssel)
[1824]1652
[2051]1653 if plot:
[2451]1654 errmsg = "Can plot header only after the first call to plot()."
[2453]1655 self._assert_plotter(action="halt",errmsg=errmsg)
[1819]1656 self._plotter.hold()
[2053]1657 self._header_plot(headstr,fontsize=fontsize)
[1819]1658 import time
[2106]1659 self._plotter.figure.text(0.99,0.01,
[1819]1660 time.strftime("%a %d %b %Y %H:%M:%S %Z"),
1661 horizontalalignment='right',
1662 verticalalignment='bottom',fontsize=8)
1663 self._plotter.release()
1664 if logger:
[2053]1665 selstr = "Selections: "+ssel
[1819]1666 asaplog.push("----------------\n Plot Summary\n----------------")
[2053]1667 asaplog.push(extrastr)
[2290]1668 asaplog.push(ssum[0:ssum.find('Selection:')]\
[2112]1669 + selstr)
[2053]1670 self._headtext['string'] = headstr
1671 del ssel, ssum, headstr
[2051]1672
[2053]1673 def _header_plot(self, texts, fontsize=9):
1674 self._headtext['textobj']=[]
1675 nstcol=len(texts)
1676 for i in range(nstcol):
1677 self._headtext['textobj'].append(
1678 self._plotter.figure.text(0.03+float(i)/nstcol,0.98,
1679 texts[i],
1680 horizontalalignment='left',
1681 verticalalignment='top',
1682 fontsize=fontsize))
1683
1684 def clear_header(self):
1685 if not self._headtext['textobj']:
1686 asaplog.push("No header has been plotted. Exit without any operation")
1687 asaplog.post("WARN")
[2453]1688 elif self._assert_plotter(action="status"):
[2053]1689 self._plotter.hold()
1690 for textobj in self._headtext['textobj']:
1691 #if textobj.get_text() in self._headstring:
1692 try:
1693 textobj.remove()
1694 except NotImplementedError:
1695 self._plotter.figure.texts.pop(self._plotter.figure.texts.index(textobj))
1696 self._plotter.release()
1697 self._reset_header()
[2576]1698
1699 # plot spectra by pointing
1700 @asaplog_post_dec
1701 def plotgrid(self, scan=None,center=None,spacing=None,rows=None,cols=None):
1702 """
1703 Plot spectra based on direction.
1704
1705 Parameters:
1706 scan: a scantable to plot
1707 center: the grid center direction (a list) of plots in the
1708 unit of DIRECTION column.
1709 (default) the center of map region
1710 spacing: a list of horizontal (R.A.) and vertical (Dec.)
1711 spacing in the unit of DIRECTION column.
1712 (default) Calculated by the extent of map region and
1713 the number of rows and cols to cover
1714 rows: number of panels (grid points) in horizontal direction
1715 cols: number of panels (grid points) in vertical direction
1716
1717 Note:
1718 - Only the first IFNO, POLNO, and BEAM in the scantable will be
1719 plotted.
1720 - This method doesn't re-grid and average spectra in scantable. Use
1721 asapgrid module to re-grid spectra before plotting with this method.
1722 Only the first spectrum is plotted in case there are multiple
1723 spectra which belong to a grid.
1724 """
1725 from asap import scantable
[2607]1726 from numpy import array, ma, cos
[2576]1727 if not self._data and not scan:
1728 msg = "No scantable is specified to plot"
1729 raise TypeError(msg)
[2604]1730 if scan:
1731 self.set_data(scan, refresh=False)
1732 del scan
1733
[2576]1734 # Rows and cols
1735 if rows:
1736 self._rows = int(rows)
1737 else:
1738 msg = "Number of rows to plot are not specified. "
1739 if self._rows:
1740 msg += "Using previous value = %d" % (self._rows)
1741 asaplog.push(msg)
1742 else:
1743 self._rows = 1
1744 msg += "Setting rows = %d" % (self._rows)
1745 asaplog.post()
1746 asaplog.push(msg)
1747 asaplog.post("WARN")
1748 if cols:
1749 self._cols = int(cols)
1750 else:
1751 msg = "Number of cols to plot are not specified. "
1752 if self._cols:
1753 msg += "Using previous value = %d" % (self._cols)
1754 asaplog.push(msg)
1755 else:
1756 self._cols = 1
1757 msg += "Setting cols = %d" % (self._cols)
1758 asaplog.post()
1759 asaplog.push(msg)
1760 asaplog.post("WARN")
1761
1762 # Center and spacing
[2691]1763 dirarr = array(self._data.get_directionval()).transpose()
1764 print "Pointing range: (x, y) = (%f - %f, %f - %f)" %\
1765 (dirarr[0].min(),dirarr[0].max(),dirarr[1].min(),dirarr[1].max())
1766 dircent = [0.5*(dirarr[0].max() + dirarr[0].min()),
1767 0.5*(dirarr[1].max() + dirarr[1].min())]
1768 del dirarr
[2607]1769 if center is None:
1770 #asaplog.post()
[2576]1771 asaplog.push("Grid center is not specified. Automatically calculated from pointing center.")
[2607]1772 #asaplog.post("WARN")
[2576]1773 #center = [dirarr[0].mean(), dirarr[1].mean()]
[2691]1774 center = dircent
[2607]1775 elif (type(center) in (list, tuple)) and len(center) > 1:
[2691]1776 from numpy import pi
1777 # make sure center_x is in +-pi of pointing center
1778 # (assumes dirs are in rad)
1779 rotnum = round(abs(center[0] - dircent[0])/(2*pi))
1780 if center[0] < dircent[0]: rotnum *= -1
1781 cenx = center[0] - rotnum*2*pi
1782 center = [cenx, center[1]]
[2607]1783 else:
1784 msg = "Direction of grid center should be a list of float (R.A., Dec.)"
1785 raise ValueError, msg
[2576]1786 asaplog.push("Grid center: (%f, %f) " % (center[0],center[1]))
1787
1788 if spacing is None:
[2607]1789 #asaplog.post()
[2576]1790 asaplog.push("Grid spacing not specified. Automatically calculated from map coverage")
[2607]1791 #asaplog.post("WARN")
[2576]1792 # automatically get spacing
1793 dirarr = array(self._data.get_directionval()).transpose()
1794 wx = 2. * max(abs(dirarr[0].max()-center[0]),
1795 abs(dirarr[0].min()-center[0]))
1796 wy = 2. * max(abs(dirarr[1].max()-center[1]),
1797 abs(dirarr[1].min()-center[1]))
[2607]1798 ## slightly expand area to plot the edges
[2691]1799 #wx *= 1.1
1800 #wy *= 1.1
[2607]1801 xgrid = wx/max(self._cols-1.,1.)
[2691]1802 #xgrid = wx/float(max(self._cols,1.))
1803 xgrid *= cos(center[1])
[2607]1804 ygrid = wy/max(self._rows-1.,1.)
[2691]1805 #ygrid = wy/float(max(self._rows,1.))
1806 # single pointing (identical R.A. and/or Dec. for all spectra.)
[2576]1807 if xgrid == 0:
1808 xgrid = 1.
1809 if ygrid == 0:
1810 ygrid = 1.
1811 # spacing should be negative to transpose plot
1812 spacing = [- xgrid, - ygrid]
1813 del dirarr, xgrid, ygrid
1814 #elif isinstance(spacing, str):
1815 # # spacing is a quantity
[2607]1816 elif (type(spacing) in (list, tuple)) and len(spacing) > 1:
[2602]1817 for i in xrange(2):
1818 val = spacing[i]
1819 if not isinstance(val, float):
[2576]1820 raise TypeError("spacing should be a list of float")
[2602]1821 if val > 0.:
1822 spacing[i] = -val
[2576]1823 spacing = spacing[0:2]
1824 else:
1825 msg = "Invalid spacing."
1826 raise TypeError(msg)
[2607]1827 asaplog.push("Spacing: (%f, %f) (projected)" % (spacing[0],spacing[1]))
[2576]1828
1829 ntotpl = self._rows * self._cols
1830 ifs = self._data.getifnos()
1831 if len(ifs) > 1:
1832 msg = "Found multiple IFs in scantable. Only the first IF (IFNO=%d) will be plotted." % ifs[0]
1833 asaplog.post()
1834 asaplog.push(msg)
1835 asaplog.post("WARN")
1836 pols = self._data.getpolnos()
1837 if len(pols) > 1:
1838 msg = "Found multiple POLs in scantable. Only the first POL (POLNO=%d) will be plotted." % pols[0]
1839 asaplog.post()
1840 asaplog.push(msg)
1841 asaplog.post("WARN")
1842 beams = self._data.getbeamnos()
1843 if len(beams) > 1:
1844 msg = "Found multiple BEAMs in scantable. Only the first BEAM (BEAMNO=%d) will be plotted." % beams[0]
1845 asaplog.post()
1846 asaplog.push(msg)
1847 asaplog.post("WARN")
1848 self._data.set_selection(ifs=[ifs[0]],pols=[pols[0]],beams=[beams[0]])
1849 if self._data.nrow() > ntotpl:
1850 msg = "Scantable is finely sampled than plotting grids. "\
1851 + "Only the first spectrum is plotted in each grid."
1852 asaplog.post()
1853 asaplog.push(msg)
1854 asaplog.post("WARN")
1855
1856 self._assert_plotter(action="reload")
1857 self._plotter.hold()
[2693]1858 #self._plotter.clear() #all artists are cleared at set_panels
[2604]1859 self._plotter.legend()
[2691]1860
[2576]1861 # Adjust subplot margins
1862 if not self._margins or len(self._margins) !=6:
1863 self.set_margin(refresh=False)
1864 self._plotter.set_panels(rows=self._rows,cols=self._cols,
[2693]1865 nplots=ntotpl,margin=self._margins,ganged=True)
[2603]1866 if self.casabar_exists():
1867 self._plotter.figmgr.casabar.set_pagecounter(1)
1868 self._plotter.figmgr.casabar.enable_button()
[2691]1869 # Plot helper
1870 from asap._asap import plothelper as plhelper
1871 ph = plhelper(self._data)
1872 ph.set_gridval(self._cols, self._rows, spacing[0], spacing[1],
1873 center[0], center[1], epoch="J2000", projname="SIN")
[2576]1874 # Actual plot
1875 npl = 0
1876 for irow in range(self._data.nrow()):
[2691]1877 (ix, iy) = ph.get_gpos(irow)
1878 #print("asapplotter.plotgrid: (ix, iy) = (%f, %f)" % (ix, iy))
[2576]1879 if ix < 0 or ix >= self._cols:
[2602]1880 #print "Row %d : Out of X-range (x = %f) ... skipped" % (irow, pos[0])
[2576]1881 continue
[2691]1882 ix = int(ix)
1883 if iy < 0 or iy >= self._rows:
[2602]1884 #print "Row %d : Out of Y-range (y = %f) ... skipped" % (irow,pos[1])
[2576]1885 continue
[2691]1886 iy = int(iy)
1887 ipanel = ix + iy*self._rows
1888 #print("Resolved panel Id (%d, %d): %d" % (ix, iy, ipanel))
[2576]1889 if len(self._plotter.subplots[ipanel]['lines']) > 0:
[2602]1890 #print "Row %d : panel %d lready plotted ... skipped" % (irow,ipanel)
[2576]1891 # a spectrum already plotted in the panel
1892 continue
1893 # Plotting this row
[2602]1894 #print "PLOTTING row %d (panel=%d)" % (irow, ipanel)
[2576]1895 npl += 1
1896 self._plotter.subplot(ipanel)
[2602]1897 self._plotter.palette(0,colormap=self._colormap, \
1898 linestyle=0,linestyles=self._linestyles)
[2576]1899 xlab = self._abcissa and self._abcissa[ipanel] \
[2603]1900 or self._data._getabcissalabel(irow)
[2576]1901 if self._offset and not self._abcissa:
1902 xlab += " (relative)"
1903 ylab = self._ordinate and self._ordinate[ipanel] \
[2603]1904 or self._data._get_ordinate_label()
[2576]1905 self._plotter.set_axes('xlabel', xlab)
1906 self._plotter.set_axes('ylabel', ylab)
1907 lbl = self._data.get_direction(irow)
1908 self._plotter.set_axes('title',lbl)
1909
[2603]1910 y = self._data._getspectrum(irow)
[2576]1911 # flag application
[2603]1912 mr = self._data._getflagrow(irow)
[2576]1913 if mr: # FLAGROW=True
1914 y = ma.masked_array(y,mask=mr)
1915 else:
[2603]1916 m = self._data._getmask(irow)
[2576]1917 from numpy import logical_not, logical_and
1918 ### user mask is not available so far
1919 #if self._maskselection and len(self._usermask) == len(m):
1920 # if d[self._stacking](irow) in self._maskselection[self._stacking]:
1921 # m = logical_and(m, self._usermask)
1922 y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
1923
[2603]1924 x = array(self._data._getabcissa(irow))
[2576]1925 if self._offset:
1926 x += self._offset
1927 if self._minmaxx is not None:
1928 s,e = self._slice_indeces(x)
1929 x = x[s:e]
1930 y = y[s:e]
1931 if len(x) > 1024 and rcParams['plotter.decimate']:
1932 fac = len(x)/1024
1933 x = x[::fac]
1934 y = y[::fac]
1935 self._plotter.set_line(label=lbl)
1936 plotit = self._plotter.plot
1937 if self._hist: plotit = self._plotter.hist
1938 if len(x) > 0 and not mr:
1939 plotit(x,y)
1940# xlim= self._minmaxx or [min(x),max(x)]
1941# allxlim += xlim
1942# ylim= self._minmaxy or [ma.minimum(y),ma.maximum(y)]
1943# allylim += ylim
1944# else:
1945# xlim = self._minmaxx or []
1946# allxlim += xlim
1947# ylim= self._minmaxy or []
1948# allylim += ylim
1949
1950 if npl >= ntotpl:
1951 break
1952
1953 if self._minmaxy is not None:
1954 self._plotter.set_limits(ylim=self._minmaxy)
1955 self._plotter.release()
1956 self._plotter.tidy()
1957 self._plotter.show(hardrefresh=False)
1958 return
Note: See TracBrowser for help on using the repository browser.