source: trunk/python/asapplotter.py@ 2149

Last change on this file since 2149 was 2147, checked in by Kana Sugimoto, 13 years ago

New Development: No

JIRA Issue: No (a minor imporvement)

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed: added a method asapplotter.casabar_exist()

Test Programs:

Put in Release Notes: No

Module(s): asapplotter, sdplot

Description:

added a method asapplotter.casabar_exist() which tells whether or not casa toolbar exists.


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