source: trunk/python/asapplotter.py@ 1937

Last change on this file since 1937 was 1927, checked in by Takeshi Nakazato, 14 years ago

New Development: No

JIRA Issue: No

Ready for Test: No

Interface Changes: No

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No

Module(s): Module Names change impacts.

Description: Describe your changes here...

Fixed typo in help text.


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