source: trunk/python/asapplotter.py@ 2703

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

New Development: No (just changed the order of methods)

JIRA Issue: No

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs:

Put in Release Notes: No

Module(s):

Description:

No actual change to codes.
Just changed the order of methods for future modifications.


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