source: trunk/python/asapplotter.py@ 2015

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

New Development: No

JIRA Issue: No (a bug fix)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs: plot 1 panel plot

Put in Release Notes: No

Module(s): asapplotter and sdplot

Description: Fixed a bug which causes Error when plotting a single panel plot.


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