source: trunk/python/asapplotter.py@ 1911

Last change on this file since 1911 was 1910, checked in by Kana Sugimoto, 14 years ago

New Development: Yes/No

JIRA Issue: Yes (CAS-1822)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs:

Put in Release Notes: No

Module(s): ASAP plotter and sdplot

Description: enabled row panelling


  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 53.9 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
8
[1317]9import re
[203]10
11class asapplotter:
[226]12 """
13 The ASAP plotter.
14 By default the plotter is set up to plot polarisations
15 'colour stacked' and scantables across panels.
[1858]16
17 .. note::
18
[226]19 Currenly it only plots 'spectra' not Tsys or
20 other variables.
[1858]21
[226]22 """
[1563]23 def __init__(self, visible=None , **kwargs):
[734]24 self._visible = rcParams['plotter.gui']
25 if visible is not None:
26 self._visible = visible
[1563]27 self._plotter = self._newplotter(**kwargs)
[1819]28 # additional tool bar
29 self._plotter.figmgr.casabar=self._newcasabar()
[710]30
[554]31 self._panelling = None
32 self._stacking = None
33 self.set_panelling()
34 self.set_stacking()
[377]35 self._rows = None
36 self._cols = None
[203]37 self._autoplot = False
[525]38 self._minmaxx = None
39 self._minmaxy = None
[710]40 self._datamask = None
[203]41 self._data = None
[607]42 self._lmap = None
[226]43 self._title = None
[257]44 self._ordinate = None
45 self._abcissa = None
[709]46 self._abcunit = None
[920]47 self._usermask = []
48 self._maskselection = None
49 self._selection = selector()
[1023]50 self._hist = rcParams['plotter.histogram']
[1556]51 self._fp = FontProperties()
[1819]52 self._panellayout = self.set_panellayout(refresh=False)
[1897]53 self._offset = None
[1910]54 ###-S
55 #self._rowcount = 0
56 ###-E
[1023]57
[920]58 def _translate(self, instr):
[1910]59 keys = "s b i p t r".split()
[920]60 if isinstance(instr, str):
61 for key in keys:
62 if instr.lower().startswith(key):
63 return key
64 return None
65
[1563]66 def _newplotter(self, **kwargs):
[1819]67 backend=matplotlib.get_backend()
68 if not self._visible:
69 from asap.asaplot import asaplot
70 elif backend == 'TkAgg':
[710]71 from asap.asaplotgui import asaplotgui as asaplot
[1819]72 elif backend == 'Qt4Agg':
73 from asap.asaplotgui_qt4 import asaplotgui as asaplot
74 elif backend == 'GTkAgg':
75 from asap.asaplotgui_gtk import asaplotgui as asaplot
[710]76 else:
77 from asap.asaplot import asaplot
[1563]78 return asaplot(**kwargs)
[710]79
[1819]80 def _newcasabar(self):
81 backend=matplotlib.get_backend()
82 if self._visible and backend == "TkAgg":
83 from asap.casatoolbar import CustomToolbarTkAgg
84 return CustomToolbarTkAgg(self)
85 else: return None
86
[1862]87 @asaplog_post_dec
[935]88 def plot(self, scan=None):
[203]89 """
[920]90 Plot a scantable.
[203]91 Parameters:
[920]92 scan: a scantable
[203]93 Note:
[920]94 If a scantable was specified in a previous call
[203]95 to plot, no argument has to be given to 'replot'
[920]96 NO checking is done that the abcissas of the scantable
[203]97 are consistent e.g. all 'channel' or all 'velocity' etc.
98 """
[1910]99 ###-S
100 #self._rowcount = 0
101 ###-E
[710]102 if self._plotter.is_dead:
[1819]103 if hasattr(self._plotter.figmgr,'casabar'):
104 del self._plotter.figmgr.casabar
[710]105 self._plotter = self._newplotter()
[1819]106 self._plotter.figmgr.casabar=self._newcasabar()
[600]107 self._plotter.hold()
[203]108 self._plotter.clear()
[935]109 if not self._data and not scan:
[1101]110 msg = "Input is not a scantable"
111 raise TypeError(msg)
[1897]112 if scan:
113 self.set_data(scan, refresh=False)
[920]114 self._plot(self._data)
[709]115 if self._minmaxy is not None:
116 self._plotter.set_limits(ylim=self._minmaxy)
[1819]117 if self._plotter.figmgr.casabar: self._plotter.figmgr.casabar.enable_button()
[203]118 self._plotter.release()
[1153]119 self._plotter.tidy()
120 self._plotter.show(hardrefresh=False)
[203]121 return
122
[1572]123 def gca(self):
124 return self._plotter.figure.gca()
125
[1550]126 def refresh(self):
[1572]127 """Do a soft refresh"""
[1550]128 self._plotter.figure.show()
129
[1555]130 def create_mask(self, nwin=1, panel=0, color=None):
[1597]131 """
132 Interactively define a mask.It retruns a mask that is equivalent to
133 the one created manually with scantable.create_mask.
134 Parameters:
135 nwin: The number of mask windows to create interactively
136 default is 1.
137 panel: Which panel to use for mask selection. This is useful
138 if different IFs are spread over panels (default 0)
139 """
[1555]140 if self._data is None:
141 return []
[1547]142 outmask = []
[1549]143 self._plotter.subplot(panel)
144 xmin, xmax = self._plotter.axes.get_xlim()
[1548]145 marg = 0.05*(xmax-xmin)
[1549]146 self._plotter.axes.set_xlim(xmin-marg, xmax+marg)
[1550]147 self.refresh()
[1695]148
[1555]149 def cleanup(lines=False, texts=False, refresh=False):
150 if lines:
151 del self._plotter.axes.lines[-1]
152 if texts:
153 del self._plotter.axes.texts[-1]
154 if refresh:
155 self.refresh()
156
157 for w in xrange(nwin):
[1547]158 wpos = []
[1695]159 self.text(0.05,1.0, "Add start boundary",
[1555]160 coords="relative", fontsize=10)
161 point = self._plotter.get_point()
162 cleanup(texts=True)
163 if point is None:
164 continue
165 wpos.append(point[0])
[1695]166 self.axvline(wpos[0], color=color)
[1551]167 self.text(0.05,1.0, "Add end boundary", coords="relative", fontsize=10)
[1555]168 point = self._plotter.get_point()
169 cleanup(texts=True, lines=True)
170 if point is None:
171 self.refresh()
172 continue
173 wpos.append(point[0])
174 self.axvspan(wpos[0], wpos[1], alpha=0.1,
175 edgecolor=color, facecolor=color)
176 ymin, ymax = self._plotter.axes.get_ylim()
[1547]177 outmask.append(wpos)
[1153]178
[1555]179 self._plotter.axes.set_xlim(xmin, xmax)
180 self.refresh()
181 if len(outmask) > 0:
182 return self._data.create_mask(*outmask)
183 return []
184
[1153]185 # forwards to matplotlib axes
186 def text(self, *args, **kwargs):
[1547]187 if kwargs.has_key("interactive"):
188 if kwargs.pop("interactive"):
189 pos = self._plotter.get_point()
190 args = tuple(pos)+args
[1153]191 self._axes_callback("text", *args, **kwargs)
[1547]192
[1358]193 text.__doc__ = matplotlib.axes.Axes.text.__doc__
[1559]194
[1153]195 def arrow(self, *args, **kwargs):
[1547]196 if kwargs.has_key("interactive"):
197 if kwargs.pop("interactive"):
198 pos = self._plotter.get_region()
199 dpos = (pos[0][0], pos[0][1],
200 pos[1][0]-pos[0][0],
201 pos[1][1] - pos[0][1])
202 args = dpos + args
[1153]203 self._axes_callback("arrow", *args, **kwargs)
[1547]204
[1358]205 arrow.__doc__ = matplotlib.axes.Axes.arrow.__doc__
[1559]206
207 def annotate(self, text, xy=None, xytext=None, **kwargs):
208 if kwargs.has_key("interactive"):
209 if kwargs.pop("interactive"):
210 xy = self._plotter.get_point()
211 xytext = self._plotter.get_point()
212 if not kwargs.has_key("arrowprops"):
213 kwargs["arrowprops"] = dict(arrowstyle="->")
214 self._axes_callback("annotate", text, xy, xytext, **kwargs)
215
216 annotate.__doc__ = matplotlib.axes.Axes.annotate.__doc__
217
[1153]218 def axvline(self, *args, **kwargs):
[1547]219 if kwargs.has_key("interactive"):
220 if kwargs.pop("interactive"):
221 pos = self._plotter.get_point()
222 args = (pos[0],)+args
[1153]223 self._axes_callback("axvline", *args, **kwargs)
[1559]224
[1358]225 axvline.__doc__ = matplotlib.axes.Axes.axvline.__doc__
[1547]226
[1153]227 def axhline(self, *args, **kwargs):
[1547]228 if kwargs.has_key("interactive"):
229 if kwargs.pop("interactive"):
230 pos = self._plotter.get_point()
231 args = (pos[1],)+args
[1153]232 self._axes_callback("axhline", *args, **kwargs)
[1559]233
[1358]234 axhline.__doc__ = matplotlib.axes.Axes.axhline.__doc__
[1547]235
[1153]236 def axvspan(self, *args, **kwargs):
[1547]237 if kwargs.has_key("interactive"):
238 if kwargs.pop("interactive"):
239 pos = self._plotter.get_region()
240 dpos = (pos[0][0], pos[1][0])
241 args = dpos + args
[1153]242 self._axes_callback("axvspan", *args, **kwargs)
243 # hack to preventy mpl from redrawing the patch
244 # it seem to convert the patch into lines on every draw.
245 # This doesn't happen in a test script???
[1547]246 #del self._plotter.axes.patches[-1]
247
[1358]248 axvspan.__doc__ = matplotlib.axes.Axes.axvspan.__doc__
[1232]249
[1153]250 def axhspan(self, *args, **kwargs):
[1547]251 if kwargs.has_key("interactive"):
252 if kwargs.pop("interactive"):
253 pos = self._plotter.get_region()
254 dpos = (pos[0][1], pos[1][1])
255 args = dpos + args
[1232]256 self._axes_callback("axhspan", *args, **kwargs)
[1153]257 # hack to preventy mpl from redrawing the patch
258 # it seem to convert the patch into lines on every draw.
259 # This doesn't happen in a test script???
[1547]260 #del self._plotter.axes.patches[-1]
[1559]261
[1358]262 axhspan.__doc__ = matplotlib.axes.Axes.axhspan.__doc__
[1153]263
264 def _axes_callback(self, axesfunc, *args, **kwargs):
265 panel = 0
266 if kwargs.has_key("panel"):
267 panel = kwargs.pop("panel")
268 coords = None
269 if kwargs.has_key("coords"):
270 coords = kwargs.pop("coords")
271 if coords.lower() == 'world':
272 kwargs["transform"] = self._plotter.axes.transData
273 elif coords.lower() == 'relative':
274 kwargs["transform"] = self._plotter.axes.transAxes
275 self._plotter.subplot(panel)
276 self._plotter.axes.set_autoscale_on(False)
277 getattr(self._plotter.axes, axesfunc)(*args, **kwargs)
278 self._plotter.show(False)
279 self._plotter.axes.set_autoscale_on(True)
280 # end matplotlib.axes fowarding functions
281
[1862]282 @asaplog_post_dec
[1819]283 def set_data(self, scan, refresh=True):
284 """
[1824]285 Set a scantable to plot.
[1819]286 Parameters:
287 scan: a scantable
288 refresh: True (default) or False. If True, the plot is
[1824]289 replotted based on the new parameter setting(s).
[1819]290 Otherwise,the parameter(s) are set without replotting.
291 Note:
292 The user specified masks and data selections will be reset
293 if a new scantable is set. This method should be called before
[1824]294 setting data selections (set_selection) and/or masks (set_mask).
[1819]295 """
296 from asap import scantable
297 if isinstance(scan, scantable):
298 if self._data is not None:
299 if scan != self._data:
300 self._data = scan
301 # reset
302 self._reset()
[1897]303 msg = "A new scantable is set to the plotter. "\
304 "The masks and data selections are reset."
[1819]305 asaplog.push( msg )
306 else:
307 self._data = scan
308 self._reset()
309 else:
310 msg = "Input is not a scantable"
311 raise TypeError(msg)
[1547]312
[1819]313 # ranges become invalid when unit changes
314 if self._abcunit and self._abcunit != self._data.get_unit():
315 self._minmaxx = None
316 self._minmaxy = None
317 self._abcunit = self._data.get_unit()
318 self._datamask = None
319 if refresh: self.plot()
320
[1862]321 @asaplog_post_dec
[1819]322 def set_mode(self, stacking=None, panelling=None, refresh=True):
[203]323 """
[377]324 Set the plots look and feel, i.e. what you want to see on the plot.
[203]325 Parameters:
326 stacking: tell the plotter which variable to plot
[1217]327 as line colour overlays (default 'pol')
[203]328 panelling: tell the plotter which variable to plot
329 across multiple panels (default 'scan'
[1819]330 refresh: True (default) or False. If True, the plot is
[1824]331 replotted based on the new parameter setting(s).
[1819]332 Otherwise,the parameter(s) are set without replotting.
[203]333 Note:
334 Valid modes are:
335 'beam' 'Beam' 'b': Beams
336 'if' 'IF' 'i': IFs
337 'pol' 'Pol' 'p': Polarisations
338 'scan' 'Scan' 's': Scans
339 'time' 'Time' 't': Times
340 """
[753]341 msg = "Invalid mode"
342 if not self.set_panelling(panelling) or \
343 not self.set_stacking(stacking):
[1859]344 raise TypeError(msg)
[1910]345 if self._panelling == 'r':
346 self._stacking = '_r'
[1819]347 if refresh and self._data: self.plot(self._data)
[203]348 return
349
[554]350 def set_panelling(self, what=None):
[1858]351 """Set the 'panelling' mode i.e. which type of spectra should be
352 spread across different panels.
353 """
354
[554]355 mode = what
356 if mode is None:
357 mode = rcParams['plotter.panelling']
358 md = self._translate(mode)
[203]359 if md:
[554]360 self._panelling = md
[226]361 self._title = None
[1910]362 if self._panelling == 'r':
363 self._stacking = '_r'
[203]364 return True
365 return False
366
[1819]367 def set_layout(self,rows=None,cols=None,refresh=True):
[377]368 """
369 Set the multi-panel layout, i.e. how many rows and columns plots
370 are visible.
371 Parameters:
372 rows: The number of rows of plots
373 cols: The number of columns of plots
[1819]374 refresh: True (default) or False. If True, the plot is
[1824]375 replotted based on the new parameter setting(s).
[1819]376 Otherwise,the parameter(s) are set without replotting.
[377]377 Note:
378 If no argument is given, the potter reverts to its auto-plot
379 behaviour.
380 """
381 self._rows = rows
382 self._cols = cols
[1819]383 if refresh and self._data: self.plot(self._data)
[377]384 return
385
[709]386 def set_stacking(self, what=None):
[1858]387 """Set the 'stacking' mode i.e. which type of spectra should be
388 overlayed.
389 """
[554]390 mode = what
[709]391 if mode is None:
392 mode = rcParams['plotter.stacking']
[554]393 md = self._translate(mode)
[203]394 if md:
395 self._stacking = md
[226]396 self._lmap = None
[203]397 return True
398 return False
399
[1897]400 def set_range(self,xstart=None,xend=None,ystart=None,yend=None,refresh=True, offset=None):
[203]401 """
402 Set the range of interest on the abcissa of the plot
403 Parameters:
[525]404 [x,y]start,[x,y]end: The start and end points of the 'zoom' window
[1819]405 refresh: True (default) or False. If True, the plot is
[1824]406 replotted based on the new parameter setting(s).
[1819]407 Otherwise,the parameter(s) are set without replotting.
[1897]408 offset: shift the abcissa by the given amount. The abcissa label will
409 have '(relative)' appended to it.
[203]410 Note:
411 These become non-sensical when the unit changes.
412 use plotter.set_range() without parameters to reset
413
414 """
[1897]415 self._offset = offset
[525]416 if xstart is None and xend is None:
417 self._minmaxx = None
[600]418 else:
419 self._minmaxx = [xstart,xend]
[525]420 if ystart is None and yend is None:
421 self._minmaxy = None
[600]422 else:
[709]423 self._minmaxy = [ystart,yend]
[1819]424 if refresh and self._data: self.plot(self._data)
[203]425 return
[709]426
[1819]427 def set_legend(self, mp=None, fontsize = None, mode = 0, refresh=True):
[203]428 """
429 Specify a mapping for the legend instead of using the default
430 indices:
431 Parameters:
[1101]432 mp: a list of 'strings'. This should have the same length
433 as the number of elements on the legend and then maps
434 to the indeces in order. It is possible to uses latex
435 math expression. These have to be enclosed in r'',
436 e.g. r'$x^{2}$'
437 fontsize: The font size of the label (default None)
438 mode: where to display the legend
439 Any other value for loc else disables the legend:
[1096]440 0: auto
441 1: upper right
442 2: upper left
443 3: lower left
444 4: lower right
445 5: right
446 6: center left
447 7: center right
448 8: lower center
449 9: upper center
450 10: center
[1819]451 refresh: True (default) or False. If True, the plot is
[1824]452 replotted based on the new parameter setting(s).
[1819]453 Otherwise,the parameter(s) are set without replotting.
[203]454
455 Example:
[485]456 If the data has two IFs/rest frequencies with index 0 and 1
[203]457 for CO and SiO:
458 plotter.set_stacking('i')
[710]459 plotter.set_legend(['CO','SiO'])
[203]460 plotter.plot()
[710]461 plotter.set_legend([r'$^{12}CO$', r'SiO'])
[203]462 """
463 self._lmap = mp
[1096]464 self._plotter.legend(mode)
[1101]465 if isinstance(fontsize, int):
466 from matplotlib import rc as rcp
467 rcp('legend', fontsize=fontsize)
[1819]468 if refresh and self._data: self.plot(self._data)
[226]469 return
470
[1819]471 def set_title(self, title=None, fontsize=None, refresh=True):
[710]472 """
473 Set the title of the plot. If multiple panels are plotted,
474 multiple titles have to be specified.
[1819]475 Parameters:
476 refresh: True (default) or False. If True, the plot is
[1824]477 replotted based on the new parameter setting(s).
[1819]478 Otherwise,the parameter(s) are set without replotting.
[710]479 Example:
480 # two panels are visible on the plotter
481 plotter.set_title(["First Panel","Second Panel"])
482 """
[226]483 self._title = title
[1101]484 if isinstance(fontsize, int):
485 from matplotlib import rc as rcp
486 rcp('axes', titlesize=fontsize)
[1819]487 if refresh and self._data: self.plot(self._data)
[226]488 return
489
[1819]490 def set_ordinate(self, ordinate=None, fontsize=None, refresh=True):
[710]491 """
492 Set the y-axis label of the plot. If multiple panels are plotted,
493 multiple labels have to be specified.
[1021]494 Parameters:
495 ordinate: a list of ordinate labels. None (default) let
496 data determine the labels
[1819]497 refresh: True (default) or False. If True, the plot is
[1824]498 replotted based on the new parameter setting(s).
[1819]499 Otherwise,the parameter(s) are set without replotting.
[710]500 Example:
501 # two panels are visible on the plotter
502 plotter.set_ordinate(["First Y-Axis","Second Y-Axis"])
503 """
[257]504 self._ordinate = ordinate
[1101]505 if isinstance(fontsize, int):
506 from matplotlib import rc as rcp
507 rcp('axes', labelsize=fontsize)
508 rcp('ytick', labelsize=fontsize)
[1819]509 if refresh and self._data: self.plot(self._data)
[257]510 return
511
[1819]512 def set_abcissa(self, abcissa=None, fontsize=None, refresh=True):
[710]513 """
514 Set the x-axis label of the plot. If multiple panels are plotted,
515 multiple labels have to be specified.
[1021]516 Parameters:
517 abcissa: a list of abcissa labels. None (default) let
518 data determine the labels
[1819]519 refresh: True (default) or False. If True, the plot is
[1824]520 replotted based on the new parameter setting(s).
[1819]521 Otherwise,the parameter(s) are set without replotting.
[710]522 Example:
523 # two panels are visible on the plotter
524 plotter.set_ordinate(["First X-Axis","Second X-Axis"])
525 """
[257]526 self._abcissa = abcissa
[1101]527 if isinstance(fontsize, int):
528 from matplotlib import rc as rcp
529 rcp('axes', labelsize=fontsize)
530 rcp('xtick', labelsize=fontsize)
[1819]531 if refresh and self._data: self.plot(self._data)
[257]532 return
533
[1819]534 def set_colors(self, colmap, refresh=True):
[377]535 """
[1217]536 Set the colours to be used. The plotter will cycle through
537 these colours when lines are overlaid (stacking mode).
[1021]538 Parameters:
[1217]539 colmap: a list of colour names
[1819]540 refresh: True (default) or False. If True, the plot is
[1824]541 replotted based on the new parameter setting(s).
[1819]542 Otherwise,the parameter(s) are set without replotting.
[710]543 Example:
544 plotter.set_colors("red green blue")
545 # If for example four lines are overlaid e.g I Q U V
546 # 'I' will be 'red', 'Q' will be 'green', U will be 'blue'
547 # and 'V' will be 'red' again.
548 """
[1217]549 if isinstance(colmap,str):
550 colmap = colmap.split()
551 self._plotter.palette(0, colormap=colmap)
[1819]552 if refresh and self._data: self.plot(self._data)
[710]553
[1217]554 # alias for english speakers
555 set_colours = set_colors
556
[1819]557 def set_histogram(self, hist=True, linewidth=None, refresh=True):
[1021]558 """
559 Enable/Disable histogram-like plotting.
560 Parameters:
561 hist: True (default) or False. The fisrt default
562 is taken from the .asaprc setting
563 plotter.histogram
[1819]564 refresh: True (default) or False. If True, the plot is
[1824]565 replotted based on the new parameter setting(s).
[1819]566 Otherwise,the parameter(s) are set without replotting.
[1021]567 """
[1023]568 self._hist = hist
[1101]569 if isinstance(linewidth, float) or isinstance(linewidth, int):
570 from matplotlib import rc as rcp
571 rcp('lines', linewidth=linewidth)
[1819]572 if refresh and self._data: self.plot(self._data)
[1023]573
[1819]574 def set_linestyles(self, linestyles=None, linewidth=None, refresh=True):
[710]575 """
[734]576 Set the linestyles to be used. The plotter will cycle through
577 these linestyles when lines are overlaid (stacking mode) AND
578 only one color has been set.
[710]579 Parameters:
580 linestyles: a list of linestyles to use.
581 'line', 'dashed', 'dotted', 'dashdot',
582 'dashdotdot' and 'dashdashdot' are
583 possible
[1819]584 refresh: True (default) or False. If True, the plot is
[1824]585 replotted based on the new parameter setting(s).
[1819]586 Otherwise,the parameter(s) are set without replotting.
[710]587 Example:
588 plotter.set_colors("black")
589 plotter.set_linestyles("line dashed dotted dashdot")
590 # If for example four lines are overlaid e.g I Q U V
591 # 'I' will be 'solid', 'Q' will be 'dashed',
592 # U will be 'dotted' and 'V' will be 'dashdot'.
593 """
594 if isinstance(linestyles,str):
595 linestyles = linestyles.split()
596 self._plotter.palette(color=0,linestyle=0,linestyles=linestyles)
[1101]597 if isinstance(linewidth, float) or isinstance(linewidth, int):
598 from matplotlib import rc as rcp
599 rcp('lines', linewidth=linewidth)
[1819]600 if refresh and self._data: self.plot(self._data)
[710]601
[1819]602 def set_font(self, refresh=True,**kwargs):
[1101]603 """
604 Set font properties.
605 Parameters:
606 family: one of 'sans-serif', 'serif', 'cursive', 'fantasy', 'monospace'
607 style: one of 'normal' (or 'roman'), 'italic' or 'oblique'
608 weight: one of 'normal or 'bold'
609 size: the 'general' font size, individual elements can be adjusted
610 seperately
[1819]611 refresh: True (default) or False. If True, the plot is
[1824]612 replotted based on the new parameter setting(s).
[1819]613 Otherwise,the parameter(s) are set without replotting.
[1101]614 """
615 from matplotlib import rc as rcp
[1547]616 fdict = {}
617 for k,v in kwargs.iteritems():
618 if v:
619 fdict[k] = v
[1556]620 self._fp = FontProperties(**fdict)
[1819]621 if refresh and self._data: self.plot(self._data)
[1101]622
[1819]623 def set_panellayout(self,layout=[],refresh=True):
624 """
625 Set the layout of subplots.
626 Parameters:
627 layout: a list of subplots layout in figure coordinate (0-1),
[1824]628 i.e., fraction of the figure width or height.
[1819]629 The order of elements should be:
630 [left, bottom, right, top, horizontal space btw panels,
[1824]631 vertical space btw panels].
[1819]632 refresh: True (default) or False. If True, the plot is
[1824]633 replotted based on the new parameter setting(s).
[1819]634 Otherwise,the parameter(s) are set without replotting.
635 Note
636 * When layout is not specified, the values are reset to the defaults
637 of matplotlib.
[1824]638 * If any element is set to be None, the current value is adopted.
[1819]639 """
640 if layout == []: self._panellayout=self._reset_panellayout()
[1824]641 else:
[1819]642 self._panellayout=[None]*6
643 self._panellayout[0:len(layout)]=layout
644 #print "panel layout set to ",self._panellayout
645 if refresh and self._data: self.plot(self._data)
646
647 def _reset_panellayout(self):
648 ks=map(lambda x: 'figure.subplot.'+x,
649 ['left','bottom','right','top','hspace','wspace'])
650 return map(matplotlib.rcParams.get,ks)
651
[1259]652 def plot_lines(self, linecat=None, doppler=0.0, deltachan=10, rotate=90.0,
[1146]653 location=None):
654 """
[1158]655 Plot a line catalog.
656 Parameters:
657 linecat: the linecatalog to plot
[1168]658 doppler: the velocity shift to apply to the frequencies
[1158]659 deltachan: the number of channels to include each side of the
660 line to determine a local maximum/minimum
[1259]661 rotate: the rotation (in degrees) )for the text label (default 90.0)
[1158]662 location: the location of the line annotation from the 'top',
663 'bottom' or alternate (None - the default)
[1165]664 Notes:
665 If the spectrum is flagged no line will be drawn in that location.
[1146]666 """
[1259]667 if not self._data:
668 raise RuntimeError("No scantable has been plotted yet.")
[1146]669 from asap._asap import linecatalog
[1259]670 if not isinstance(linecat, linecatalog):
671 raise ValueError("'linecat' isn't of type linecatalog.")
672 if not self._data.get_unit().endswith("Hz"):
673 raise RuntimeError("Can only overlay linecatalogs when data is in frequency.")
[1739]674 from numpy import ma
[1146]675 for j in range(len(self._plotter.subplots)):
676 self._plotter.subplot(j)
677 lims = self._plotter.axes.get_xlim()
[1153]678 for row in range(linecat.nrow()):
[1259]679 # get_frequency returns MHz
680 base = { "GHz": 1000.0, "MHz": 1.0, "Hz": 1.0e-6 }
681 restf = linecat.get_frequency(row)/base[self._data.get_unit()]
[1165]682 c = 299792.458
[1174]683 freq = restf*(1.0-doppler/c)
[1146]684 if lims[0] < freq < lims[1]:
685 if location is None:
686 loc = 'bottom'
[1153]687 if row%2: loc='top'
[1146]688 else: loc = location
[1153]689 maxys = []
690 for line in self._plotter.axes.lines:
691 v = line._x
692 asc = v[0] < v[-1]
693
694 idx = None
695 if not asc:
696 if v[len(v)-1] <= freq <= v[0]:
697 i = len(v)-1
698 while i>=0 and v[i] < freq:
699 idx = i
700 i-=1
701 else:
702 if v[0] <= freq <= v[len(v)-1]:
703 i = 0
704 while i<len(v) and v[i] < freq:
705 idx = i
706 i+=1
707 if idx is not None:
708 lower = idx - deltachan
709 upper = idx + deltachan
710 if lower < 0: lower = 0
711 if upper > len(v): upper = len(v)
712 s = slice(lower, upper)
[1167]713 y = line._y[s]
[1165]714 maxy = ma.maximum(y)
715 if isinstance( maxy, float):
716 maxys.append(maxy)
[1164]717 if len(maxys):
718 peak = max(maxys)
[1165]719 if peak > self._plotter.axes.get_ylim()[1]:
720 loc = 'bottom'
[1164]721 else:
722 continue
[1157]723 self._plotter.vline_with_label(freq, peak,
724 linecat.get_name(row),
725 location=loc, rotate=rotate)
[1153]726 self._plotter.show(hardrefresh=False)
[1146]727
[1153]728
[710]729 def save(self, filename=None, orientation=None, dpi=None):
730 """
[377]731 Save the plot to a file. The know formats are 'png', 'ps', 'eps'.
732 Parameters:
733 filename: The name of the output file. This is optional
734 and autodetects the image format from the file
735 suffix. If non filename is specified a file
736 called 'yyyymmdd_hhmmss.png' is created in the
737 current directory.
[709]738 orientation: optional parameter for postscript only (not eps).
739 'landscape', 'portrait' or None (default) are valid.
740 If None is choosen for 'ps' output, the plot is
741 automatically oriented to fill the page.
[710]742 dpi: The dpi of the output non-ps plot
[377]743 """
[709]744 self._plotter.save(filename,orientation,dpi)
[377]745 return
[709]746
[1862]747 @asaplog_post_dec
[1819]748 def set_mask(self, mask=None, selection=None, refresh=True):
[525]749 """
[734]750 Set a plotting mask for a specific polarization.
751 This is useful for masking out "noise" Pangle outside a source.
752 Parameters:
[920]753 mask: a mask from scantable.create_mask
754 selection: the spectra to apply the mask to.
[1819]755 refresh: True (default) or False. If True, the plot is
[1824]756 replotted based on the new parameter setting(s).
[1819]757 Otherwise,the parameter(s) are set without replotting.
[734]758 Example:
[920]759 select = selector()
760 select.setpolstrings("Pangle")
761 plotter.set_mask(mymask, select)
[734]762 """
[710]763 if not self._data:
[920]764 msg = "Can only set mask after a first call to plot()"
[1859]765 raise RuntimeError(msg)
[920]766 if len(mask):
767 if isinstance(mask, list) or isinstance(mask, tuple):
768 self._usermask = array(mask)
[710]769 else:
[920]770 self._usermask = mask
771 if mask is None and selection is None:
772 self._usermask = []
773 self._maskselection = None
774 if isinstance(selection, selector):
[947]775 self._maskselection = {'b': selection.get_beams(),
776 's': selection.get_scans(),
777 'i': selection.get_ifs(),
778 'p': selection.get_pols(),
[920]779 't': [] }
[710]780 else:
[920]781 self._maskselection = None
[1819]782 if refresh: self.plot(self._data)
[710]783
[709]784 def _slice_indeces(self, data):
785 mn = self._minmaxx[0]
786 mx = self._minmaxx[1]
787 asc = data[0] < data[-1]
788 start=0
789 end = len(data)-1
790 inc = 1
791 if not asc:
792 start = len(data)-1
793 end = 0
794 inc = -1
795 # find min index
[1819]796 #while start > 0 and data[start] < mn:
797 # start+= inc
798 minind=start
799 for ind in xrange(start,end+inc,inc):
800 if data[ind] > mn: break
801 minind=ind
[709]802 # find max index
[1819]803 #while end > 0 and data[end] > mx:
804 # end-=inc
805 #if end > 0: end +=1
806 maxind=end
807 for ind in xrange(end,start-inc,-inc):
808 if data[ind] < mx: break
809 maxind=ind
810 start=minind
811 end=maxind
[709]812 if start > end:
[1819]813 return end,start+1
814 elif start < end:
815 return start,end+1
816 else:
817 return start,end
[709]818
[710]819 def _reset(self):
[920]820 self._usermask = []
[710]821 self._usermaskspectra = None
[1897]822 self._offset = None
[920]823 self.set_selection(None, False)
824
825 def _plot(self, scan):
[947]826 savesel = scan.get_selection()
827 sel = savesel + self._selection
[1910]828 order = self._get_sortstring([self._panelling,self._stacking])
829 if order:
830 sel.set_order(order)
[947]831 scan.set_selection(sel)
[920]832 d = {'b': scan.getbeam, 's': scan.getscan,
[1910]833 'i': scan.getif, 'p': scan.getpol, 't': scan._gettime,
834 'r': int, '_r': int}
[920]835
[1148]836 polmodes = dict(zip(self._selection.get_pols(),
837 self._selection.get_poltypes()))
838 # this returns either a tuple of numbers or a length (ncycles)
839 # convert this into lengths
840 n0,nstack0 = self._get_selected_n(scan)
841 if isinstance(n0, int): n = n0
[1175]842 else: n = len(n0)
[1910]843 ###-S
844 #nptot = n
845 ###-E
[1148]846 if isinstance(nstack0, int): nstack = nstack0
[1175]847 else: nstack = len(nstack0)
[1582]848 maxpanel, maxstack = 16,16
[1910]849 ###-S
[920]850 if n > maxpanel or nstack > maxstack:
[1910]851 #if nstack > maxstack:
852 ###-E
853 ###-S
[1148]854 maxn = 0
855 if nstack > maxstack: maxn = maxstack
856 if n > maxpanel: maxn = maxpanel
[920]857 msg ="Scan to be plotted contains more than %d selections.\n" \
[1148]858 "Selecting first %d selections..." % (maxn, maxn)
[1910]859 #msg ="Scan to be overlayed contains more than %d selections.\n" \
860 # "Selecting first %d selections..." % (maxstack, maxstack)
861 ###-E
[920]862 asaplog.push(msg)
[1861]863 asaplog.post('WARN')
[1910]864 ###-S
[920]865 n = min(n,maxpanel)
[1910]866 ###-E
[998]867 nstack = min(nstack,maxstack)
[1910]868 ###-S
869 #n = min(n,maxpanel)
870 ###-E
871
[920]872 if n > 1:
873 ganged = rcParams['plotter.ganged']
[1819]874 if self._panelling == 'i':
875 ganged = False
[920]876 if self._rows and self._cols:
877 n = min(n,self._rows*self._cols)
878 self._plotter.set_panels(rows=self._rows,cols=self._cols,
[1819]879# nplots=n,ganged=ganged)
880 nplots=n,layout=self._panellayout,ganged=ganged)
[920]881 else:
[1819]882# self._plotter.set_panels(rows=n,cols=0,nplots=n,ganged=ganged)
883 self._plotter.set_panels(rows=n,cols=0,nplots=n,layout=self._panellayout,ganged=ganged)
[920]884 else:
[1819]885# self._plotter.set_panels()
886 self._plotter.set_panels(layout=self._panellayout)
[1910]887 ###-S
888 r = 0
889 #r = self._rowcount
890 ###-E
[920]891 nr = scan.nrow()
892 a0,b0 = -1,-1
893 allxlim = []
[1018]894 allylim = []
[920]895 newpanel=True
896 panelcount,stackcount = 0,0
[1002]897 while r < nr:
[920]898 a = d[self._panelling](r)
899 b = d[self._stacking](r)
900 if a > a0 and panelcount < n:
901 if n > 1:
902 self._plotter.subplot(panelcount)
903 self._plotter.palette(0)
904 #title
905 xlab = self._abcissa and self._abcissa[panelcount] \
906 or scan._getabcissalabel()
[1897]907 if self._offset and not self._abcissa:
908 xlab += " (relative)"
[920]909 ylab = self._ordinate and self._ordinate[panelcount] \
910 or scan._get_ordinate_label()
[1547]911 self._plotter.set_axes('xlabel', xlab)
912 self._plotter.set_axes('ylabel', ylab)
[920]913 lbl = self._get_label(scan, r, self._panelling, self._title)
914 if isinstance(lbl, list) or isinstance(lbl, tuple):
915 if 0 <= panelcount < len(lbl):
916 lbl = lbl[panelcount]
917 else:
918 # get default label
919 lbl = self._get_label(scan, r, self._panelling, None)
920 self._plotter.set_axes('title',lbl)
921 newpanel = True
922 stackcount =0
923 panelcount += 1
924 if (b > b0 or newpanel) and stackcount < nstack:
925 y = []
926 if len(polmodes):
927 y = scan._getspectrum(r, polmodes[scan.getpol(r)])
928 else:
929 y = scan._getspectrum(r)
930 m = scan._getmask(r)
[1739]931 from numpy import logical_not, logical_and
[920]932 if self._maskselection and len(self._usermask) == len(m):
933 if d[self._stacking](r) in self._maskselection[self._stacking]:
934 m = logical_and(m, self._usermask)
[1739]935 from numpy import ma, array
[1897]936 x = array(scan._getabcissa(r))
937 if self._offset:
938 x += self._offset
[1116]939 y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
[920]940 if self._minmaxx is not None:
941 s,e = self._slice_indeces(x)
942 x = x[s:e]
943 y = y[s:e]
[1096]944 if len(x) > 1024 and rcParams['plotter.decimate']:
945 fac = len(x)/1024
[920]946 x = x[::fac]
947 y = y[::fac]
948 llbl = self._get_label(scan, r, self._stacking, self._lmap)
949 if isinstance(llbl, list) or isinstance(llbl, tuple):
950 if 0 <= stackcount < len(llbl):
951 # use user label
952 llbl = llbl[stackcount]
953 else:
954 # get default label
955 llbl = self._get_label(scan, r, self._stacking, None)
956 self._plotter.set_line(label=llbl)
[1023]957 plotit = self._plotter.plot
958 if self._hist: plotit = self._plotter.hist
[1146]959 if len(x) > 0:
960 plotit(x,y)
961 xlim= self._minmaxx or [min(x),max(x)]
962 allxlim += xlim
963 ylim= self._minmaxy or [ma.minimum(y),ma.maximum(y)]
964 allylim += ylim
[1819]965 else:
966 xlim = self._minmaxx or []
967 allxlim += xlim
968 ylim= self._minmaxy or []
969 allylim += ylim
[920]970 stackcount += 1
971 # last in colour stack -> autoscale x
[1819]972 if stackcount == nstack and len(allxlim) > 0:
[920]973 allxlim.sort()
[1819]974 self._plotter.subplots[panelcount-1]['axes'].set_xlim([allxlim[0],allxlim[-1]])
[920]975 # clear
976 allxlim =[]
977
978 newpanel = False
979 a0=a
980 b0=b
981 # ignore following rows
982 if (panelcount == n) and (stackcount == nstack):
[1018]983 # last panel -> autoscale y if ganged
[1819]984 if rcParams['plotter.ganged'] and len(allylim) > 0:
[1018]985 allylim.sort()
986 self._plotter.set_limits(ylim=[allylim[0],allylim[-1]])
[998]987 break
[920]988 r+=1 # next row
[1910]989 ###-S
990 #self._rowcount = r+1
991 #if self._rowcount > 0: enable prev button
992 #if self._rowcount >= nr: disable next button
993 ###-E
[947]994 #reset the selector to the scantable's original
995 scan.set_selection(savesel)
[1824]996
[1819]997 #temporary switch-off for older matplotlib
998 #if self._fp is not None:
999 if self._fp is not None and getattr(self._plotter.figure,'findobj',False):
[1556]1000 for o in self._plotter.figure.findobj(Text):
1001 o.set_fontproperties(self._fp)
[920]1002
[1910]1003 def _get_sortstring(self, lorders):
1004 d0 = {'s': 'SCANNO', 'b': 'BEAMNO', 'i':'IFNO',
1005 'p': 'POLNO', 'c': 'CYCLENO', 't' : 'TIME', 'r':None, '_r':None }
1006 if not (type(lorders) == list) or not (type(lorders) == tuple):
1007 return None
1008 if len(lorders) > 0:
1009 lsorts = []
1010 for order in lorders:
1011 ssort = d0[order]
1012 if ssort:
1013 lsorts.append(ssort)
1014 return lsorts
1015 return None
1016
[1582]1017 def set_selection(self, selection=None, refresh=True, **kw):
[1819]1018 """
1019 Parameters:
1020 selection: a selector object (default unset the selection)
1021 refresh: True (default) or False. If True, the plot is
[1824]1022 replotted based on the new parameter setting(s).
[1819]1023 Otherwise,the parameter(s) are set without replotting.
1024 """
[1582]1025 if selection is None:
1026 # reset
1027 if len(kw) == 0:
1028 self._selection = selector()
1029 else:
1030 # try keywords
1031 for k in kw:
1032 if k not in selector.fields:
1033 raise KeyError("Invalid selection key '%s', valid keys are %s" % (k, selector.fields))
1034 self._selection = selector(**kw)
1035 elif isinstance(selection, selector):
1036 self._selection = selection
1037 else:
1038 raise TypeError("'selection' is not of type selector")
1039
[1910]1040 order = self._get_sortstring([self._panelling,self._stacking])
1041 if order:
1042 self._selection.set_order(order)
[1819]1043 if refresh and self._data: self.plot(self._data)
[920]1044
1045 def _get_selected_n(self, scan):
[1148]1046 d1 = {'b': scan.getbeamnos, 's': scan.getscannos,
[1910]1047 'i': scan.getifnos, 'p': scan.getpolnos, 't': scan.ncycle,
1048 'r': scan.nrow, '_r': False}
[1148]1049 d2 = { 'b': self._selection.get_beams(),
1050 's': self._selection.get_scans(),
1051 'i': self._selection.get_ifs(),
1052 'p': self._selection.get_pols(),
[1910]1053 't': self._selection.get_cycles(),
1054 'r': False, '_r': 1}
[920]1055 n = d2[self._panelling] or d1[self._panelling]()
1056 nstack = d2[self._stacking] or d1[self._stacking]()
1057 return n,nstack
1058
1059 def _get_label(self, scan, row, mode, userlabel=None):
[1153]1060 if isinstance(userlabel, list) and len(userlabel) == 0:
1061 userlabel = " "
[947]1062 pms = dict(zip(self._selection.get_pols(),self._selection.get_poltypes()))
[920]1063 if len(pms):
1064 poleval = scan._getpollabel(scan.getpol(row),pms[scan.getpol(row)])
1065 else:
1066 poleval = scan._getpollabel(scan.getpol(row),scan.poltype())
1067 d = {'b': "Beam "+str(scan.getbeam(row)),
[1819]1068 #'s': scan._getsourcename(row),
1069 's': "Scan "+str(scan.getscan(row))+\
1070 " ("+str(scan._getsourcename(row))+")",
[920]1071 'i': "IF"+str(scan.getif(row)),
[964]1072 'p': poleval,
[1910]1073 't': str(scan.get_time(row)),
1074 'r': "row "+str(row),
1075 '_r': str(scan.get_time(row))+",\nIF"+str(scan.getif(row))+", "+poleval+", Beam"+str(scan.getbeam(row)) }
[920]1076 return userlabel or d[mode]
[1153]1077
[1819]1078 def plotazel(self, scan=None, outfile=None):
1079 #def plotazel(self):
[1391]1080 """
[1696]1081 plot azimuth and elevation versus time of a scantable
[1391]1082 """
[1696]1083 from matplotlib import pylab as PL
1084 from matplotlib.dates import DateFormatter, timezone
1085 from matplotlib.dates import HourLocator, MinuteLocator,SecondLocator, DayLocator
[1391]1086 from matplotlib.ticker import MultipleLocator
[1739]1087 from numpy import array, pi
[1819]1088 self._data = scan
1089 self._outfile = outfile
[1556]1090 dates = self._data.get_time(asdatetime=True)
[1391]1091 t = PL.date2num(dates)
1092 tz = timezone('UTC')
1093 PL.cla()
1094 PL.ioff()
1095 PL.clf()
[1819]1096 # Adjust subplot layouts
1097 if len(self._panellayout) !=6: self.set_panellayout(refresh=False)
1098 lef, bot, rig, top, wsp, hsp = self._panellayout
1099 PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
1100 wspace=wsp,hspace=hsp)
[1824]1101
[1391]1102 tdel = max(t) - min(t)
1103 ax = PL.subplot(2,1,1)
1104 el = array(self._data.get_elevation())*180./pi
1105 PL.ylabel('El [deg.]')
1106 dstr = dates[0].strftime('%Y/%m/%d')
1107 if tdel > 1.0:
1108 dstr2 = dates[len(dates)-1].strftime('%Y/%m/%d')
1109 dstr = dstr + " - " + dstr2
1110 majloc = DayLocator()
1111 minloc = HourLocator(range(0,23,12))
1112 timefmt = DateFormatter("%b%d")
[1696]1113 elif tdel > 24./60.:
1114 timefmt = DateFormatter('%H:%M')
1115 majloc = HourLocator()
1116 minloc = MinuteLocator(30)
[1391]1117 else:
[1696]1118 timefmt = DateFormatter('%H:%M')
1119 majloc = MinuteLocator(interval=5)
1120 minloc = SecondLocator(30)
1121
[1391]1122 PL.title(dstr)
[1819]1123 if tdel == 0.0:
1124 th = (t - PL.floor(t))*24.0
1125 PL.plot(th,el,'o',markersize=2, markerfacecolor='b', markeredgecolor='b')
1126 else:
1127 PL.plot_date(t,el,'o', markersize=2, markerfacecolor='b', markeredgecolor='b',tz=tz)
1128 #ax.grid(True)
1129 ax.xaxis.set_major_formatter(timefmt)
1130 ax.xaxis.set_major_locator(majloc)
1131 ax.xaxis.set_minor_locator(minloc)
[1391]1132 ax.yaxis.grid(True)
[1819]1133 yloc = MultipleLocator(30)
1134 ax.set_ylim(0,90)
1135 ax.yaxis.set_major_locator(yloc)
[1391]1136 if tdel > 1.0:
1137 labels = ax.get_xticklabels()
1138 # PL.setp(labels, fontsize=10, rotation=45)
1139 PL.setp(labels, fontsize=10)
[1819]1140
[1391]1141 # Az plot
1142 az = array(self._data.get_azimuth())*180./pi
1143 if min(az) < 0:
1144 for irow in range(len(az)):
1145 if az[irow] < 0: az[irow] += 360.0
1146
[1819]1147 ax2 = PL.subplot(2,1,2)
1148 #PL.xlabel('Time (UT [hour])')
1149 PL.ylabel('Az [deg.]')
1150 if tdel == 0.0:
1151 PL.plot(th,az,'o',markersize=2, markeredgecolor='b',markerfacecolor='b')
1152 else:
1153 PL.plot_date(t,az,'o', markersize=2,markeredgecolor='b',markerfacecolor='b',tz=tz)
1154 ax2.xaxis.set_major_formatter(timefmt)
1155 ax2.xaxis.set_major_locator(majloc)
1156 ax2.xaxis.set_minor_locator(minloc)
1157 #ax2.grid(True)
1158 ax2.set_ylim(0,360)
[1696]1159 ax2.yaxis.grid(True)
[1819]1160 #hfmt = DateFormatter('%H')
1161 #hloc = HourLocator()
1162 yloc = MultipleLocator(60)
1163 ax2.yaxis.set_major_locator(yloc)
1164 if tdel > 1.0:
1165 labels = ax2.get_xticklabels()
1166 PL.setp(labels, fontsize=10)
1167 PL.xlabel('Time (UT [day])')
1168 else:
1169 PL.xlabel('Time (UT [hour])')
1170
[1391]1171 PL.ion()
1172 PL.draw()
[1819]1173 if (self._outfile is not None):
1174 PL.savefig(self._outfile)
[1391]1175
[1819]1176 def plotpointing(self, scan=None, outfile=None):
1177 #def plotpointing(self):
[1391]1178 """
1179 plot telescope pointings
1180 """
[1696]1181 from matplotlib import pylab as PL
[1819]1182 from numpy import array, pi
1183 self._data = scan
1184 self._outfile = outfile
[1391]1185 dir = array(self._data.get_directionval()).transpose()
1186 ra = dir[0]*180./pi
1187 dec = dir[1]*180./pi
1188 PL.cla()
[1819]1189 #PL.ioff()
[1391]1190 PL.clf()
[1819]1191 # Adjust subplot layouts
1192 if len(self._panellayout) !=6: self.set_panellayout(refresh=False)
1193 lef, bot, rig, top, wsp, hsp = self._panellayout
1194 PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
1195 wspace=wsp,hspace=hsp)
1196 ax = PL.gca()
1197 #ax = PL.axes([0.1,0.1,0.8,0.8])
1198 #ax = PL.axes([0.1,0.1,0.8,0.8])
[1391]1199 ax.set_aspect('equal')
[1696]1200 PL.plot(ra, dec, 'b,')
[1391]1201 PL.xlabel('RA [deg.]')
1202 PL.ylabel('Declination [deg.]')
1203 PL.title('Telescope pointings')
1204 [xmin,xmax,ymin,ymax] = PL.axis()
1205 PL.axis([xmax,xmin,ymin,ymax])
[1819]1206 #PL.ion()
[1391]1207 PL.draw()
[1819]1208 if (self._outfile is not None):
1209 PL.savefig(self._outfile)
1210
1211 # plot total power data
1212 # plotting in time is not yet implemented..
[1862]1213 @asaplog_post_dec
[1819]1214 def plottp(self, scan=None, outfile=None):
1215 if self._plotter.is_dead:
1216 if hasattr(self._plotter.figmgr,'casabar'):
1217 del self._plotter.figmgr.casabar
1218 self._plotter = self._newplotter()
1219 self._plotter.figmgr.casabar=self._newcasabar()
1220 self._plotter.hold()
1221 self._plotter.clear()
1222 from asap import scantable
1223 if not self._data and not scan:
1224 msg = "Input is not a scantable"
1225 raise TypeError(msg)
1226 if isinstance(scan, scantable):
1227 if self._data is not None:
1228 if scan != self._data:
1229 self._data = scan
1230 # reset
1231 self._reset()
1232 else:
1233 self._data = scan
1234 self._reset()
1235 # ranges become invalid when abcissa changes?
1236 #if self._abcunit and self._abcunit != self._data.get_unit():
1237 # self._minmaxx = None
1238 # self._minmaxy = None
1239 # self._abcunit = self._data.get_unit()
1240 # self._datamask = None
1241
1242 # Adjust subplot layouts
1243 if len(self._panellayout) !=6: self.set_panellayout(refresh=False)
1244 lef, bot, rig, top, wsp, hsp = self._panellayout
1245 self._plotter.figure.subplots_adjust(
1246 left=lef,bottom=bot,right=rig,top=top,wspace=wsp,hspace=hsp)
1247 if self._plotter.figmgr.casabar: self._plotter.figmgr.casabar.disable_button()
1248 self._plottp(self._data)
1249 if self._minmaxy is not None:
1250 self._plotter.set_limits(ylim=self._minmaxy)
1251 self._plotter.release()
1252 self._plotter.tidy()
1253 self._plotter.show(hardrefresh=False)
1254 return
1255
1256 def _plottp(self,scan):
1257 """
1258 private method for plotting total power data
1259 """
1260 from numpy import ma, array, arange, logical_not
1261 r=0
1262 nr = scan.nrow()
1263 a0,b0 = -1,-1
1264 allxlim = []
1265 allylim = []
1266 y=[]
1267 self._plotter.set_panels()
1268 self._plotter.palette(0)
1269 #title
1270 #xlab = self._abcissa and self._abcissa[panelcount] \
1271 # or scan._getabcissalabel()
1272 #ylab = self._ordinate and self._ordinate[panelcount] \
1273 # or scan._get_ordinate_label()
1274 xlab = self._abcissa or 'row number' #or Time
1275 ylab = self._ordinate or scan._get_ordinate_label()
1276 self._plotter.set_axes('xlabel',xlab)
1277 self._plotter.set_axes('ylabel',ylab)
1278 lbl = self._get_label(scan, r, 's', self._title)
1279 if isinstance(lbl, list) or isinstance(lbl, tuple):
1280 # if 0 <= panelcount < len(lbl):
1281 # lbl = lbl[panelcount]
1282 # else:
1283 # get default label
1284 lbl = self._get_label(scan, r, self._panelling, None)
1285 self._plotter.set_axes('title',lbl)
1286 y=array(scan._get_column(scan._getspectrum,-1))
1287 m = array(scan._get_column(scan._getmask,-1))
1288 y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
1289 x = arange(len(y))
1290 # try to handle spectral data somewhat...
1291 l,m = y.shape
1292 if m > 1:
1293 y=y.mean(axis=1)
1294 plotit = self._plotter.plot
1295 llbl = self._get_label(scan, r, self._stacking, None)
1296 self._plotter.set_line(label=llbl)
1297 if len(x) > 0:
1298 plotit(x,y)
1299
1300
1301 # forwards to matplotlib.Figure.text
1302 def figtext(self, *args, **kwargs):
1303 """
1304 Add text to figure at location x,y (relative 0-1 coords).
1305 This method forwards *args and **kwargs to a Matplotlib method,
1306 matplotlib.Figure.text.
1307 See the method help for detailed information.
1308 """
1309 self._plotter.text(*args, **kwargs)
1310 # end matplotlib.Figure.text forwarding function
1311
1312
1313 # printing header information
[1862]1314 @asaplog_post_dec
[1819]1315 def print_header(self, plot=True, fontsize=9, logger=False, selstr='', extrastr=''):
1316 """
1317 print data (scantable) header on the plot and/or logger.
1318 Parameters:
[1824]1319 plot: whether or not print header info on the plot.
[1819]1320 fontsize: header font size (valid only plot=True)
1321 autoscale: whether or not autoscale the plot (valid only plot=True)
1322 logger: whether or not print header info on the logger.
1323 selstr: additional selection string (not verified)
1324 extrastr: additional string to print (not verified)
1325 """
[1859]1326 if not plot and not logger:
1327 return
1328 if not self._data:
1329 raise RuntimeError("No scantable has been set yet.")
[1824]1330 # Now header will be printed on plot and/or logger.
1331 # Get header information and format it.
[1819]1332 ssum=self._data.__str__()
1333 # Print Observation header to the upper-left corner of plot
1334 if plot:
1335 headstr=[ssum[ssum.find('Observer:'):ssum.find('Flux Unit:')]]
1336 headstr.append(ssum[ssum.find('Beams:'):ssum.find('Observer:')]
1337 +ssum[ssum.find('Rest Freqs:'):ssum.find('Abcissa:')])
1338 if extrastr != '': headstr[0]=extrastr+'\n'+headstr[0]
1339 #headstr[1]='Data File: '+(filestr or 'unknown')+'\n'+headstr[1]
1340 ssel='***Selections***\n'+(selstr+self._data.get_selection().__str__() or 'none')
1341 headstr.append(ssel)
1342 nstcol=len(headstr)
[1824]1343
[1819]1344 self._plotter.hold()
1345 for i in range(nstcol):
1346 self._plotter.figure.text(0.03+float(i)/nstcol,0.98,
1347 headstr[i],
1348 horizontalalignment='left',
1349 verticalalignment='top',
1350 fontsize=fontsize)
1351 import time
1352 self._plotter.figure.text(0.99,0.0,
1353 time.strftime("%a %d %b %Y %H:%M:%S %Z"),
1354 horizontalalignment='right',
1355 verticalalignment='bottom',fontsize=8)
1356 self._plotter.release()
1357 del headstr, ssel
1358 if logger:
1359 asaplog.push("----------------\n Plot Summary\n----------------")
1360 asaplog.push(extrastr)
1361 asaplog.push(ssum[ssum.find('Beams:'):])
1362 del ssum
Note: See TracBrowser for help on using the repository browser.