source: trunk/python/asapplotter.py@ 1985

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

New Development: No

JIRA Issue: Yes (CAS-1822/ASAP-204)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs:

Put in Release Notes: No

Module(s): asapplotter & sdplot

Description:

for got to commit this. The previous commit of casatoolbar.py depends on this code.


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