source: trunk/python/asapplotter.py@ 1992

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

New Development: Yes

JIRA Issue: Yes (CAS-1306 and ASAP-205)

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed: enabled stack='r' and panel='r' in sdplot as well as

stacking='r' and panelling='r' in asapplotter.set_mode.

Test Programs: run sdplot with either stack='r' or panel='r'.

Or, asapplotter.set_mode with either stacking='r' or panelling='r',
and then asapplotter.plot

Put in Release Notes: Yes

Module(s): sdplot and asapplotter

Description: enabled row based stacking and panelling in sdplot and asapplotter.


  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 56.3 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)
[1819]87 else: return None
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)
[1989]880
[920]881 if n > 1:
882 ganged = rcParams['plotter.ganged']
[1819]883 if self._panelling == 'i':
884 ganged = False
[920]885 if self._rows and self._cols:
886 n = min(n,self._rows*self._cols)
887 self._plotter.set_panels(rows=self._rows,cols=self._cols,
[1819]888 nplots=n,layout=self._panellayout,ganged=ganged)
[920]889 else:
[1819]890 self._plotter.set_panels(rows=n,cols=0,nplots=n,layout=self._panellayout,ganged=ganged)
[920]891 else:
[1819]892 self._plotter.set_panels(layout=self._panellayout)
[1913]893 #r = 0
[1981]894 r = self._startrow
[920]895 nr = scan.nrow()
896 a0,b0 = -1,-1
897 allxlim = []
[1018]898 allylim = []
[1981]899 #newpanel=True
900 newpanel=False
[920]901 panelcount,stackcount = 0,0
[1981]902 # If this is not the first page
903 if r > 0:
904 # panelling value of the prev page
905 a0 = d[self._panelling](r-1)
906 # set the initial stackcount large not to plot
907 # the start row automatically
908 stackcount = nstack
909
[1002]910 while r < nr:
[920]911 a = d[self._panelling](r)
912 b = d[self._stacking](r)
913 if a > a0 and panelcount < n:
914 if n > 1:
915 self._plotter.subplot(panelcount)
916 self._plotter.palette(0)
917 #title
918 xlab = self._abcissa and self._abcissa[panelcount] \
919 or scan._getabcissalabel()
[1897]920 if self._offset and not self._abcissa:
921 xlab += " (relative)"
[920]922 ylab = self._ordinate and self._ordinate[panelcount] \
923 or scan._get_ordinate_label()
[1547]924 self._plotter.set_axes('xlabel', xlab)
925 self._plotter.set_axes('ylabel', ylab)
[1989]926 #lbl = self._get_label(scan, r, self._panelling, self._title)
927 lbl = self._get_label(scan, r, titlemode, self._title)
[920]928 if isinstance(lbl, list) or isinstance(lbl, tuple):
929 if 0 <= panelcount < len(lbl):
930 lbl = lbl[panelcount]
931 else:
932 # get default label
[1989]933 #lbl = self._get_label(scan, r, self._panelling, None)
934 lbl = self._get_label(scan, r, titlemode, None)
[920]935 self._plotter.set_axes('title',lbl)
936 newpanel = True
[1913]937 stackcount = 0
[920]938 panelcount += 1
[1981]939 # save the start row to plot this panel for future revisit.
940 if self._panelling != 'r' and \
941 len(self._panelrows) < self._ipanel+1+panelcount:
942 self._panelrows += [r]
943
[1944]944 #if (b > b0 or newpanel) and stackcount < nstack:
[1989]945 if stackcount < nstack and (newpanel or rowstack or (a == a0 and b > b0)):
[920]946 y = []
947 if len(polmodes):
948 y = scan._getspectrum(r, polmodes[scan.getpol(r)])
949 else:
950 y = scan._getspectrum(r)
951 m = scan._getmask(r)
[1739]952 from numpy import logical_not, logical_and
[920]953 if self._maskselection and len(self._usermask) == len(m):
954 if d[self._stacking](r) in self._maskselection[self._stacking]:
955 m = logical_and(m, self._usermask)
[1739]956 from numpy import ma, array
[1897]957 x = array(scan._getabcissa(r))
958 if self._offset:
959 x += self._offset
[1116]960 y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
[920]961 if self._minmaxx is not None:
962 s,e = self._slice_indeces(x)
963 x = x[s:e]
964 y = y[s:e]
[1096]965 if len(x) > 1024 and rcParams['plotter.decimate']:
966 fac = len(x)/1024
[920]967 x = x[::fac]
968 y = y[::fac]
969 llbl = self._get_label(scan, r, self._stacking, self._lmap)
970 if isinstance(llbl, list) or isinstance(llbl, tuple):
971 if 0 <= stackcount < len(llbl):
972 # use user label
973 llbl = llbl[stackcount]
974 else:
975 # get default label
976 llbl = self._get_label(scan, r, self._stacking, None)
977 self._plotter.set_line(label=llbl)
[1023]978 plotit = self._plotter.plot
979 if self._hist: plotit = self._plotter.hist
[1146]980 if len(x) > 0:
981 plotit(x,y)
982 xlim= self._minmaxx or [min(x),max(x)]
983 allxlim += xlim
984 ylim= self._minmaxy or [ma.minimum(y),ma.maximum(y)]
985 allylim += ylim
[1819]986 else:
987 xlim = self._minmaxx or []
988 allxlim += xlim
989 ylim= self._minmaxy or []
990 allylim += ylim
[920]991 stackcount += 1
[1981]992 a0=a
993 b0=b
[920]994 # last in colour stack -> autoscale x
[1819]995 if stackcount == nstack and len(allxlim) > 0:
[920]996 allxlim.sort()
[1819]997 self._plotter.subplots[panelcount-1]['axes'].set_xlim([allxlim[0],allxlim[-1]])
[1989]998 if ganged:
999 allxlim = [allxlim[0],allxlim[-1]]
1000 else:
1001 # clear
1002 allxlim =[]
[920]1003
1004 newpanel = False
[1981]1005 #a0=a
1006 #b0=b
[920]1007 # ignore following rows
[1981]1008 if (panelcount == n and stackcount == nstack) or (r == nr-1):
[1018]1009 # last panel -> autoscale y if ganged
[1989]1010 #if rcParams['plotter.ganged'] and len(allylim) > 0:
1011 if ganged and len(allylim) > 0:
[1018]1012 allylim.sort()
1013 self._plotter.set_limits(ylim=[allylim[0],allylim[-1]])
[998]1014 break
[920]1015 r+=1 # next row
[1981]1016
1017 # save the current counter for multi-page plotting
1018 self._startrow = r+1
1019 self._ipanel += panelcount
[1913]1020 if self._plotter.figmgr.casabar:
[1981]1021 if self._ipanel >= nptot-1:
[1913]1022 self._plotter.figmgr.casabar.disable_next()
1023 else:
1024 self._plotter.figmgr.casabar.enable_next()
[1981]1025 if self._ipanel + 1 - panelcount > 0:
1026 self._plotter.figmgr.casabar.enable_prev()
1027 else:
1028 self._plotter.figmgr.casabar.disable_prev()
1029
[947]1030 #reset the selector to the scantable's original
1031 scan.set_selection(savesel)
[1824]1032
[1819]1033 #temporary switch-off for older matplotlib
1034 #if self._fp is not None:
1035 if self._fp is not None and getattr(self._plotter.figure,'findobj',False):
[1556]1036 for o in self._plotter.figure.findobj(Text):
1037 o.set_fontproperties(self._fp)
[920]1038
[1910]1039 def _get_sortstring(self, lorders):
1040 d0 = {'s': 'SCANNO', 'b': 'BEAMNO', 'i':'IFNO',
1041 'p': 'POLNO', 'c': 'CYCLENO', 't' : 'TIME', 'r':None, '_r':None }
[1944]1042 if not (type(lorders) == list) and not (type(lorders) == tuple):
[1910]1043 return None
1044 if len(lorders) > 0:
1045 lsorts = []
1046 for order in lorders:
[1989]1047 if order == "r":
1048 # don't sort if row panelling/stacking
1049 return None
[1910]1050 ssort = d0[order]
1051 if ssort:
1052 lsorts.append(ssort)
1053 return lsorts
1054 return None
1055
[1582]1056 def set_selection(self, selection=None, refresh=True, **kw):
[1819]1057 """
1058 Parameters:
1059 selection: a selector object (default unset the selection)
1060 refresh: True (default) or False. If True, the plot is
[1824]1061 replotted based on the new parameter setting(s).
[1819]1062 Otherwise,the parameter(s) are set without replotting.
1063 """
[1582]1064 if selection is None:
1065 # reset
1066 if len(kw) == 0:
1067 self._selection = selector()
1068 else:
1069 # try keywords
1070 for k in kw:
1071 if k not in selector.fields:
1072 raise KeyError("Invalid selection key '%s', valid keys are %s" % (k, selector.fields))
1073 self._selection = selector(**kw)
1074 elif isinstance(selection, selector):
1075 self._selection = selection
1076 else:
1077 raise TypeError("'selection' is not of type selector")
1078
[1910]1079 order = self._get_sortstring([self._panelling,self._stacking])
1080 if order:
1081 self._selection.set_order(order)
[1819]1082 if refresh and self._data: self.plot(self._data)
[920]1083
1084 def _get_selected_n(self, scan):
[1148]1085 d1 = {'b': scan.getbeamnos, 's': scan.getscannos,
[1910]1086 'i': scan.getifnos, 'p': scan.getpolnos, 't': scan.ncycle,
[1989]1087 'r': scan.nrow}#, '_r': False}
[1148]1088 d2 = { 'b': self._selection.get_beams(),
1089 's': self._selection.get_scans(),
1090 'i': self._selection.get_ifs(),
1091 'p': self._selection.get_pols(),
[1910]1092 't': self._selection.get_cycles(),
[1989]1093 'r': False}#, '_r': 1}
[920]1094 n = d2[self._panelling] or d1[self._panelling]()
1095 nstack = d2[self._stacking] or d1[self._stacking]()
[1989]1096 # handle row panelling/stacking
1097 if self._panelling == 'r':
1098 nstack = 1
1099 elif self._stacking == 'r':
1100 n = 1
[920]1101 return n,nstack
1102
1103 def _get_label(self, scan, row, mode, userlabel=None):
[1153]1104 if isinstance(userlabel, list) and len(userlabel) == 0:
1105 userlabel = " "
[947]1106 pms = dict(zip(self._selection.get_pols(),self._selection.get_poltypes()))
[920]1107 if len(pms):
1108 poleval = scan._getpollabel(scan.getpol(row),pms[scan.getpol(row)])
1109 else:
1110 poleval = scan._getpollabel(scan.getpol(row),scan.poltype())
1111 d = {'b': "Beam "+str(scan.getbeam(row)),
[1819]1112 #'s': scan._getsourcename(row),
1113 's': "Scan "+str(scan.getscan(row))+\
1114 " ("+str(scan._getsourcename(row))+")",
[920]1115 'i': "IF"+str(scan.getif(row)),
[964]1116 'p': poleval,
[1910]1117 't': str(scan.get_time(row)),
1118 'r': "row "+str(row),
[1913]1119 #'_r': str(scan.get_time(row))+",\nIF"+str(scan.getif(row))+", "+poleval+", Beam"+str(scan.getbeam(row)) }
1120 '_r': "" }
[920]1121 return userlabel or d[mode]
[1153]1122
[1819]1123 def plotazel(self, scan=None, outfile=None):
[1391]1124 """
[1696]1125 plot azimuth and elevation versus time of a scantable
[1391]1126 """
[1923]1127 visible = rcParams['plotter.gui']
[1696]1128 from matplotlib import pylab as PL
1129 from matplotlib.dates import DateFormatter, timezone
1130 from matplotlib.dates import HourLocator, MinuteLocator,SecondLocator, DayLocator
[1391]1131 from matplotlib.ticker import MultipleLocator
[1739]1132 from numpy import array, pi
[1923]1133 if not visible or not self._visible:
1134 PL.ioff()
1135 from matplotlib.backends.backend_agg import FigureCanvasAgg
1136 PL.gcf().canvas.switch_backends(FigureCanvasAgg)
[1819]1137 self._data = scan
1138 self._outfile = outfile
[1556]1139 dates = self._data.get_time(asdatetime=True)
[1391]1140 t = PL.date2num(dates)
1141 tz = timezone('UTC')
1142 PL.cla()
1143 PL.ioff()
1144 PL.clf()
[1819]1145 # Adjust subplot layouts
[1923]1146 if len(self._panellayout) != 6:
1147 self.set_panellayout(refresh=False)
[1819]1148 lef, bot, rig, top, wsp, hsp = self._panellayout
1149 PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
1150 wspace=wsp,hspace=hsp)
[1824]1151
[1391]1152 tdel = max(t) - min(t)
1153 ax = PL.subplot(2,1,1)
1154 el = array(self._data.get_elevation())*180./pi
1155 PL.ylabel('El [deg.]')
1156 dstr = dates[0].strftime('%Y/%m/%d')
1157 if tdel > 1.0:
1158 dstr2 = dates[len(dates)-1].strftime('%Y/%m/%d')
1159 dstr = dstr + " - " + dstr2
1160 majloc = DayLocator()
1161 minloc = HourLocator(range(0,23,12))
1162 timefmt = DateFormatter("%b%d")
[1696]1163 elif tdel > 24./60.:
1164 timefmt = DateFormatter('%H:%M')
1165 majloc = HourLocator()
1166 minloc = MinuteLocator(30)
[1391]1167 else:
[1696]1168 timefmt = DateFormatter('%H:%M')
1169 majloc = MinuteLocator(interval=5)
1170 minloc = SecondLocator(30)
1171
[1391]1172 PL.title(dstr)
[1819]1173 if tdel == 0.0:
1174 th = (t - PL.floor(t))*24.0
1175 PL.plot(th,el,'o',markersize=2, markerfacecolor='b', markeredgecolor='b')
1176 else:
1177 PL.plot_date(t,el,'o', markersize=2, markerfacecolor='b', markeredgecolor='b',tz=tz)
1178 #ax.grid(True)
1179 ax.xaxis.set_major_formatter(timefmt)
1180 ax.xaxis.set_major_locator(majloc)
1181 ax.xaxis.set_minor_locator(minloc)
[1391]1182 ax.yaxis.grid(True)
[1819]1183 yloc = MultipleLocator(30)
1184 ax.set_ylim(0,90)
1185 ax.yaxis.set_major_locator(yloc)
[1391]1186 if tdel > 1.0:
1187 labels = ax.get_xticklabels()
1188 # PL.setp(labels, fontsize=10, rotation=45)
1189 PL.setp(labels, fontsize=10)
[1819]1190
[1391]1191 # Az plot
1192 az = array(self._data.get_azimuth())*180./pi
1193 if min(az) < 0:
1194 for irow in range(len(az)):
1195 if az[irow] < 0: az[irow] += 360.0
1196
[1819]1197 ax2 = PL.subplot(2,1,2)
1198 #PL.xlabel('Time (UT [hour])')
1199 PL.ylabel('Az [deg.]')
1200 if tdel == 0.0:
1201 PL.plot(th,az,'o',markersize=2, markeredgecolor='b',markerfacecolor='b')
1202 else:
1203 PL.plot_date(t,az,'o', markersize=2,markeredgecolor='b',markerfacecolor='b',tz=tz)
1204 ax2.xaxis.set_major_formatter(timefmt)
1205 ax2.xaxis.set_major_locator(majloc)
1206 ax2.xaxis.set_minor_locator(minloc)
1207 #ax2.grid(True)
1208 ax2.set_ylim(0,360)
[1696]1209 ax2.yaxis.grid(True)
[1819]1210 #hfmt = DateFormatter('%H')
1211 #hloc = HourLocator()
1212 yloc = MultipleLocator(60)
1213 ax2.yaxis.set_major_locator(yloc)
1214 if tdel > 1.0:
1215 labels = ax2.get_xticklabels()
1216 PL.setp(labels, fontsize=10)
1217 PL.xlabel('Time (UT [day])')
1218 else:
1219 PL.xlabel('Time (UT [hour])')
1220
[1391]1221 PL.ion()
1222 PL.draw()
[1819]1223 if (self._outfile is not None):
1224 PL.savefig(self._outfile)
[1391]1225
[1819]1226 def plotpointing(self, scan=None, outfile=None):
[1391]1227 """
1228 plot telescope pointings
1229 """
[1923]1230 visible = rcParams['plotter.gui']
[1696]1231 from matplotlib import pylab as PL
[1819]1232 from numpy import array, pi
[1923]1233 if not visible or not self._visible:
1234 PL.ioff()
1235 from matplotlib.backends.backend_agg import FigureCanvasAgg
1236 PL.gcf().canvas.switch_backends(FigureCanvasAgg)
[1819]1237 self._data = scan
1238 self._outfile = outfile
[1391]1239 dir = array(self._data.get_directionval()).transpose()
1240 ra = dir[0]*180./pi
1241 dec = dir[1]*180./pi
1242 PL.cla()
[1819]1243 #PL.ioff()
[1391]1244 PL.clf()
[1819]1245 # Adjust subplot layouts
[1923]1246 if len(self._panellayout) != 6:
1247 self.set_panellayout(refresh=False)
[1819]1248 lef, bot, rig, top, wsp, hsp = self._panellayout
1249 PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
1250 wspace=wsp,hspace=hsp)
1251 ax = PL.gca()
1252 #ax = PL.axes([0.1,0.1,0.8,0.8])
1253 #ax = PL.axes([0.1,0.1,0.8,0.8])
[1391]1254 ax.set_aspect('equal')
[1696]1255 PL.plot(ra, dec, 'b,')
[1391]1256 PL.xlabel('RA [deg.]')
1257 PL.ylabel('Declination [deg.]')
1258 PL.title('Telescope pointings')
1259 [xmin,xmax,ymin,ymax] = PL.axis()
1260 PL.axis([xmax,xmin,ymin,ymax])
[1819]1261 #PL.ion()
[1391]1262 PL.draw()
[1819]1263 if (self._outfile is not None):
1264 PL.savefig(self._outfile)
1265
1266 # plot total power data
1267 # plotting in time is not yet implemented..
[1862]1268 @asaplog_post_dec
[1819]1269 def plottp(self, scan=None, outfile=None):
1270 if self._plotter.is_dead:
1271 if hasattr(self._plotter.figmgr,'casabar'):
1272 del self._plotter.figmgr.casabar
1273 self._plotter = self._newplotter()
1274 self._plotter.figmgr.casabar=self._newcasabar()
1275 self._plotter.hold()
1276 self._plotter.clear()
1277 from asap import scantable
1278 if not self._data and not scan:
1279 msg = "Input is not a scantable"
1280 raise TypeError(msg)
1281 if isinstance(scan, scantable):
1282 if self._data is not None:
1283 if scan != self._data:
1284 self._data = scan
1285 # reset
1286 self._reset()
1287 else:
1288 self._data = scan
1289 self._reset()
1290 # ranges become invalid when abcissa changes?
1291 #if self._abcunit and self._abcunit != self._data.get_unit():
1292 # self._minmaxx = None
1293 # self._minmaxy = None
1294 # self._abcunit = self._data.get_unit()
1295 # self._datamask = None
1296
1297 # Adjust subplot layouts
1298 if len(self._panellayout) !=6: self.set_panellayout(refresh=False)
1299 lef, bot, rig, top, wsp, hsp = self._panellayout
1300 self._plotter.figure.subplots_adjust(
1301 left=lef,bottom=bot,right=rig,top=top,wspace=wsp,hspace=hsp)
1302 if self._plotter.figmgr.casabar: self._plotter.figmgr.casabar.disable_button()
1303 self._plottp(self._data)
1304 if self._minmaxy is not None:
1305 self._plotter.set_limits(ylim=self._minmaxy)
1306 self._plotter.release()
1307 self._plotter.tidy()
1308 self._plotter.show(hardrefresh=False)
1309 return
1310
1311 def _plottp(self,scan):
1312 """
1313 private method for plotting total power data
1314 """
1315 from numpy import ma, array, arange, logical_not
1316 r=0
1317 nr = scan.nrow()
1318 a0,b0 = -1,-1
1319 allxlim = []
1320 allylim = []
1321 y=[]
1322 self._plotter.set_panels()
1323 self._plotter.palette(0)
1324 #title
1325 #xlab = self._abcissa and self._abcissa[panelcount] \
1326 # or scan._getabcissalabel()
1327 #ylab = self._ordinate and self._ordinate[panelcount] \
1328 # or scan._get_ordinate_label()
1329 xlab = self._abcissa or 'row number' #or Time
1330 ylab = self._ordinate or scan._get_ordinate_label()
1331 self._plotter.set_axes('xlabel',xlab)
1332 self._plotter.set_axes('ylabel',ylab)
1333 lbl = self._get_label(scan, r, 's', self._title)
1334 if isinstance(lbl, list) or isinstance(lbl, tuple):
1335 # if 0 <= panelcount < len(lbl):
1336 # lbl = lbl[panelcount]
1337 # else:
1338 # get default label
1339 lbl = self._get_label(scan, r, self._panelling, None)
1340 self._plotter.set_axes('title',lbl)
1341 y=array(scan._get_column(scan._getspectrum,-1))
1342 m = array(scan._get_column(scan._getmask,-1))
1343 y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
1344 x = arange(len(y))
1345 # try to handle spectral data somewhat...
1346 l,m = y.shape
1347 if m > 1:
1348 y=y.mean(axis=1)
1349 plotit = self._plotter.plot
1350 llbl = self._get_label(scan, r, self._stacking, None)
1351 self._plotter.set_line(label=llbl)
1352 if len(x) > 0:
1353 plotit(x,y)
1354
1355
1356 # forwards to matplotlib.Figure.text
1357 def figtext(self, *args, **kwargs):
1358 """
1359 Add text to figure at location x,y (relative 0-1 coords).
1360 This method forwards *args and **kwargs to a Matplotlib method,
1361 matplotlib.Figure.text.
1362 See the method help for detailed information.
1363 """
1364 self._plotter.text(*args, **kwargs)
1365 # end matplotlib.Figure.text forwarding function
1366
1367
1368 # printing header information
[1862]1369 @asaplog_post_dec
[1819]1370 def print_header(self, plot=True, fontsize=9, logger=False, selstr='', extrastr=''):
1371 """
1372 print data (scantable) header on the plot and/or logger.
1373 Parameters:
[1824]1374 plot: whether or not print header info on the plot.
[1819]1375 fontsize: header font size (valid only plot=True)
1376 logger: whether or not print header info on the logger.
1377 selstr: additional selection string (not verified)
1378 extrastr: additional string to print (not verified)
1379 """
[1859]1380 if not plot and not logger:
1381 return
1382 if not self._data:
1383 raise RuntimeError("No scantable has been set yet.")
[1824]1384 # Now header will be printed on plot and/or logger.
1385 # Get header information and format it.
[1819]1386 ssum=self._data.__str__()
1387 # Print Observation header to the upper-left corner of plot
1388 if plot:
1389 headstr=[ssum[ssum.find('Observer:'):ssum.find('Flux Unit:')]]
1390 headstr.append(ssum[ssum.find('Beams:'):ssum.find('Observer:')]
1391 +ssum[ssum.find('Rest Freqs:'):ssum.find('Abcissa:')])
1392 if extrastr != '': headstr[0]=extrastr+'\n'+headstr[0]
1393 #headstr[1]='Data File: '+(filestr or 'unknown')+'\n'+headstr[1]
1394 ssel='***Selections***\n'+(selstr+self._data.get_selection().__str__() or 'none')
1395 headstr.append(ssel)
1396 nstcol=len(headstr)
[1824]1397
[1819]1398 self._plotter.hold()
1399 for i in range(nstcol):
1400 self._plotter.figure.text(0.03+float(i)/nstcol,0.98,
1401 headstr[i],
1402 horizontalalignment='left',
1403 verticalalignment='top',
1404 fontsize=fontsize)
1405 import time
1406 self._plotter.figure.text(0.99,0.0,
1407 time.strftime("%a %d %b %Y %H:%M:%S %Z"),
1408 horizontalalignment='right',
1409 verticalalignment='bottom',fontsize=8)
1410 self._plotter.release()
1411 del headstr, ssel
1412 if logger:
1413 asaplog.push("----------------\n Plot Summary\n----------------")
1414 asaplog.push(extrastr)
1415 asaplog.push(ssum[ssum.find('Beams:'):])
1416 del ssum
Note: See TracBrowser for help on using the repository browser.