source: trunk/python/asapplotter.py@ 2147

Last change on this file since 2147 was 2147, checked in by Kana Sugimoto, 14 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
Line 
1from asap.parameters import rcParams
2from asap.selector import selector
3from asap.scantable import scantable
4from asap.logging import asaplog, asaplog_post_dec
5import matplotlib.axes
6from matplotlib.font_manager import FontProperties
7from matplotlib.text import Text
8
9import re
10
11class asapplotter:
12 """
13 The ASAP plotter.
14 By default the plotter is set up to plot polarisations
15 'colour stacked' and scantables across panels.
16
17 .. note::
18
19 Currenly it only plots 'spectra' not Tsys or
20 other variables.
21
22 """
23 def __init__(self, visible=None , **kwargs):
24 self._visible = rcParams['plotter.gui']
25 if visible is not None:
26 self._visible = visible
27 self._plotter = self._newplotter(**kwargs)
28 # additional tool bar
29 self._plotter.figmgr.casabar=self._newcasabar()
30
31 self._panelling = None
32 self._stacking = None
33 self.set_panelling()
34 self.set_stacking()
35 self._rows = None
36 self._cols = None
37 self._autoplot = False
38 self._minmaxx = None
39 self._minmaxy = None
40 self._datamask = None
41 self._data = None
42 self._lmap = None
43 self._title = None
44 self._ordinate = None
45 self._abcissa = None
46 self._abcunit = None
47 self._usermask = []
48 self._maskselection = None
49 self._selection = selector()
50 self._hist = rcParams['plotter.histogram']
51 self._fp = FontProperties()
52 self._margins = self.set_margin(refresh=False)
53 self._offset = None
54 self._startrow = 0
55 self._ipanel = -1
56 self._panelrows = []
57 self._headtext={'string': None, 'textobj': None}
58
59 def _translate(self, instr):
60 keys = "s b i p t r".split()
61 if isinstance(instr, str):
62 for key in keys:
63 if instr.lower().startswith(key):
64 return key
65 return None
66
67 def _newplotter(self, **kwargs):
68 backend=matplotlib.get_backend()
69 if not self._visible:
70 from asap.asaplot import asaplot
71 elif backend == 'TkAgg':
72 from asap.asaplotgui import asaplotgui as asaplot
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
77 else:
78 from asap.asaplot import asaplot
79 return asaplot(**kwargs)
80
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)
86 #from asap.casatoolbar import CustomFlagToolbarTkAgg
87 #return CustomFlagToolbarTkAgg(self)
88 return None
89
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
97 @asaplog_post_dec
98 def plot(self, scan=None):
99 """
100 Plot a scantable.
101 Parameters:
102 scan: a scantable
103 Note:
104 If a scantable was specified in a previous call
105 to plot, no argument has to be given to 'replot'
106 NO checking is done that the abcissas of the scantable
107 are consistent e.g. all 'channel' or all 'velocity' etc.
108 """
109 self._startrow = 0
110 self._ipanel = -1
111 self._reset_header()
112 if self._plotter.is_dead:
113 if self.casabar_exists():
114 del self._plotter.figmgr.casabar
115 self._plotter = self._newplotter()
116 self._plotter.figmgr.casabar=self._newcasabar()
117 if self.casabar_exists():
118 self._plotter.figmgr.casabar.set_pagecounter(1)
119 self._panelrows = []
120 self._plotter.hold()
121 #self._plotter.clear()
122 if not self._data and not scan:
123 msg = "Input is not a scantable"
124 raise TypeError(msg)
125 if scan:
126 self.set_data(scan, refresh=False)
127 self._plot(self._data)
128 if self._minmaxy is not None:
129 self._plotter.set_limits(ylim=self._minmaxy)
130 if self.casabar_exists(): self._plotter.figmgr.casabar.enable_button()
131 self._plotter.release()
132 self._plotter.tidy()
133 self._plotter.show(hardrefresh=False)
134 return
135
136 def gca(self):
137 return self._plotter.figure.gca()
138
139 def refresh(self):
140 """Do a soft refresh"""
141 self._plotter.figure.show()
142
143 def create_mask(self, nwin=1, panel=0, color=None):
144 """
145 Interactively define a mask. It retruns a mask that is equivalent to
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 """
153 if self._data is None:
154 return []
155 outmask = []
156 self._plotter.subplot(panel)
157 xmin, xmax = self._plotter.axes.get_xlim()
158 marg = 0.05*(xmax-xmin)
159 self._plotter.axes.set_xlim(xmin-marg, xmax+marg)
160 self.refresh()
161
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):
171 wpos = []
172 self.text(0.05,1.0, "Add start boundary",
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])
179 self.axvline(wpos[0], color=color)
180 self.text(0.05,1.0, "Add end boundary", coords="relative", fontsize=10)
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()
190 outmask.append(wpos)
191
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
198 # forwards to matplotlib axes
199 def text(self, *args, **kwargs):
200 if kwargs.has_key("interactive"):
201 if kwargs.pop("interactive"):
202 pos = self._plotter.get_point()
203 args = tuple(pos)+args
204 self._axes_callback("text", *args, **kwargs)
205
206 text.__doc__ = matplotlib.axes.Axes.text.__doc__
207
208 def arrow(self, *args, **kwargs):
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
216 self._axes_callback("arrow", *args, **kwargs)
217
218 arrow.__doc__ = matplotlib.axes.Axes.arrow.__doc__
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
231 def axvline(self, *args, **kwargs):
232 if kwargs.has_key("interactive"):
233 if kwargs.pop("interactive"):
234 pos = self._plotter.get_point()
235 args = (pos[0],)+args
236 self._axes_callback("axvline", *args, **kwargs)
237
238 axvline.__doc__ = matplotlib.axes.Axes.axvline.__doc__
239
240 def axhline(self, *args, **kwargs):
241 if kwargs.has_key("interactive"):
242 if kwargs.pop("interactive"):
243 pos = self._plotter.get_point()
244 args = (pos[1],)+args
245 self._axes_callback("axhline", *args, **kwargs)
246
247 axhline.__doc__ = matplotlib.axes.Axes.axhline.__doc__
248
249 def axvspan(self, *args, **kwargs):
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
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???
259 #del self._plotter.axes.patches[-1]
260
261 axvspan.__doc__ = matplotlib.axes.Axes.axvspan.__doc__
262
263 def axhspan(self, *args, **kwargs):
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
269 self._axes_callback("axhspan", *args, **kwargs)
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???
273 #del self._plotter.axes.patches[-1]
274
275 axhspan.__doc__ = matplotlib.axes.Axes.axhspan.__doc__
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
295 @asaplog_post_dec
296 def set_data(self, scan, refresh=True):
297 """
298 Set a scantable to plot.
299 Parameters:
300 scan: a scantable
301 refresh: True (default) or False. If True, the plot is
302 replotted based on the new parameter setting(s).
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
307 setting data selections (set_selection) and/or masks (set_mask).
308 """
309 from asap import scantable
310 if isinstance(scan, scantable):
311 if self._data is not None:
312 if scan != self._data:
313 del self._data
314 self._data = scan
315 # reset
316 self._reset()
317 msg = "A new scantable is set to the plotter. "\
318 "The masks and data selections are reset."
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)
326
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
335 @asaplog_post_dec
336 def set_mode(self, stacking=None, panelling=None, refresh=True):
337 """
338 Set the plots look and feel, i.e. what you want to see on the plot.
339 Parameters:
340 stacking: tell the plotter which variable to plot
341 as line colour overlays (default 'pol')
342 panelling: tell the plotter which variable to plot
343 across multiple panels (default 'scan'
344 refresh: True (default) or False. If True, the plot is
345 replotted based on the new parameter setting(s).
346 Otherwise,the parameter(s) are set without replotting.
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
354 'row' 'Row' 'r': Rows
355 When either 'stacking' or 'panelling' is set to 'row',
356 the other parameter setting is ignored.
357 """
358 msg = "Invalid mode"
359 if not self.set_panelling(panelling) or \
360 not self.set_stacking(stacking):
361 raise TypeError(msg)
362 #if self._panelling == 'r':
363 # self._stacking = '_r'
364 #if self._stacking == 'r':
365 # self._panelling = '_r'
366 if refresh and self._data: self.plot(self._data)
367 return
368
369 def set_panelling(self, what=None):
370 """Set the 'panelling' mode i.e. which type of spectra should be
371 spread across different panels.
372 """
373
374 mode = what
375 if mode is None:
376 mode = rcParams['plotter.panelling']
377 md = self._translate(mode)
378 if md:
379 self._panelling = md
380 self._title = None
381 #if md == 'r':
382 # self._stacking = '_r'
383 # you need to reset counters for multi page plotting
384 self._reset_counters()
385 return True
386 return False
387
388 def set_layout(self,rows=None,cols=None,refresh=True):
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
395 refresh: True (default) or False. If True, the plot is
396 replotted based on the new parameter setting(s).
397 Otherwise,the parameter(s) are set without replotting.
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
404 if refresh and self._data: self.plot(self._data)
405 return
406
407 def set_stacking(self, what=None):
408 """Set the 'stacking' mode i.e. which type of spectra should be
409 overlayed.
410 """
411 mode = what
412 if mode is None:
413 mode = rcParams['plotter.stacking']
414 md = self._translate(mode)
415 if md:
416 self._stacking = md
417 self._lmap = None
418 #if md == 'r':
419 # self._panelling = '_r'
420 # you need to reset counters for multi page plotting
421 self._reset_counters()
422 return True
423 return False
424
425 def _reset_counters(self):
426 self._startrow = 0
427 self._ipanel = -1
428 self._panelrows = []
429
430 def set_range(self,xstart=None,xend=None,ystart=None,yend=None,refresh=True, offset=None):
431 """
432 Set the range of interest on the abcissa of the plot
433 Parameters:
434 [x,y]start,[x,y]end: The start and end points of the 'zoom' window
435 refresh: True (default) or False. If True, the plot is
436 replotted based on the new parameter setting(s).
437 Otherwise,the parameter(s) are set without replotting.
438 offset: shift the abcissa by the given amount. The abcissa label will
439 have '(relative)' appended to it.
440 Note:
441 These become non-sensical when the unit changes.
442 use plotter.set_range() without parameters to reset
443
444 """
445 self._offset = offset
446 if xstart is None and xend is None:
447 self._minmaxx = None
448 else:
449 self._minmaxx = [xstart,xend]
450 if ystart is None and yend is None:
451 self._minmaxy = None
452 else:
453 self._minmaxy = [ystart,yend]
454 if refresh and self._data: self.plot(self._data)
455 return
456
457 def set_legend(self, mp=None, fontsize = None, mode = 0, refresh=True):
458 """
459 Specify a mapping for the legend instead of using the default
460 indices:
461 Parameters:
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:
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
481 refresh: True (default) or False. If True, the plot is
482 replotted based on the new parameter setting(s).
483 Otherwise,the parameter(s) are set without replotting.
484
485 Example:
486 If the data has two IFs/rest frequencies with index 0 and 1
487 for CO and SiO:
488 plotter.set_stacking('i')
489 plotter.set_legend(['CO','SiO'])
490 plotter.plot()
491 plotter.set_legend([r'$^{12}CO$', r'SiO'])
492 """
493 self._lmap = mp
494 self._plotter.legend(mode)
495 if isinstance(fontsize, int):
496 from matplotlib import rc as rcp
497 rcp('legend', fontsize=fontsize)
498 if refresh and self._data: self.plot(self._data)
499 return
500
501 def set_title(self, title=None, fontsize=None, refresh=True):
502 """
503 Set the title of the plot. If multiple panels are plotted,
504 multiple titles have to be specified.
505 Parameters:
506 refresh: True (default) or False. If True, the plot is
507 replotted based on the new parameter setting(s).
508 Otherwise,the parameter(s) are set without replotting.
509 Example:
510 # two panels are visible on the plotter
511 plotter.set_title(["First Panel","Second Panel"])
512 """
513 self._title = title
514 if isinstance(fontsize, int):
515 from matplotlib import rc as rcp
516 rcp('axes', titlesize=fontsize)
517 if refresh and self._data: self.plot(self._data)
518 return
519
520 def set_ordinate(self, ordinate=None, fontsize=None, refresh=True):
521 """
522 Set the y-axis label of the plot. If multiple panels are plotted,
523 multiple labels have to be specified.
524 Parameters:
525 ordinate: a list of ordinate labels. None (default) let
526 data determine the labels
527 refresh: True (default) or False. If True, the plot is
528 replotted based on the new parameter setting(s).
529 Otherwise,the parameter(s) are set without replotting.
530 Example:
531 # two panels are visible on the plotter
532 plotter.set_ordinate(["First Y-Axis","Second Y-Axis"])
533 """
534 self._ordinate = ordinate
535 if isinstance(fontsize, int):
536 from matplotlib import rc as rcp
537 rcp('axes', labelsize=fontsize)
538 rcp('ytick', labelsize=fontsize)
539 if refresh and self._data: self.plot(self._data)
540 return
541
542 def set_abcissa(self, abcissa=None, fontsize=None, refresh=True):
543 """
544 Set the x-axis label of the plot. If multiple panels are plotted,
545 multiple labels have to be specified.
546 Parameters:
547 abcissa: a list of abcissa labels. None (default) let
548 data determine the labels
549 refresh: True (default) or False. If True, the plot is
550 replotted based on the new parameter setting(s).
551 Otherwise,the parameter(s) are set without replotting.
552 Example:
553 # two panels are visible on the plotter
554 plotter.set_ordinate(["First X-Axis","Second X-Axis"])
555 """
556 self._abcissa = abcissa
557 if isinstance(fontsize, int):
558 from matplotlib import rc as rcp
559 rcp('axes', labelsize=fontsize)
560 rcp('xtick', labelsize=fontsize)
561 if refresh and self._data: self.plot(self._data)
562 return
563
564 def set_colors(self, colmap, refresh=True):
565 """
566 Set the colours to be used. The plotter will cycle through
567 these colours when lines are overlaid (stacking mode).
568 Parameters:
569 colmap: a list of colour names
570 refresh: True (default) or False. If True, the plot is
571 replotted based on the new parameter setting(s).
572 Otherwise,the parameter(s) are set without replotting.
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 """
579 if isinstance(colmap,str):
580 colmap = colmap.split()
581 self._plotter.palette(0, colormap=colmap)
582 if refresh and self._data: self.plot(self._data)
583
584 # alias for english speakers
585 set_colours = set_colors
586
587 def set_histogram(self, hist=True, linewidth=None, refresh=True):
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
594 refresh: True (default) or False. If True, the plot is
595 replotted based on the new parameter setting(s).
596 Otherwise,the parameter(s) are set without replotting.
597 """
598 self._hist = hist
599 if isinstance(linewidth, float) or isinstance(linewidth, int):
600 from matplotlib import rc as rcp
601 rcp('lines', linewidth=linewidth)
602 if refresh and self._data: self.plot(self._data)
603
604 def set_linestyles(self, linestyles=None, linewidth=None, refresh=True):
605 """
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.
609 Parameters:
610 linestyles: a list of linestyles to use.
611 'line', 'dashed', 'dotted', 'dashdot',
612 'dashdotdot' and 'dashdashdot' are
613 possible
614 refresh: True (default) or False. If True, the plot is
615 replotted based on the new parameter setting(s).
616 Otherwise,the parameter(s) are set without replotting.
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)
627 if isinstance(linewidth, float) or isinstance(linewidth, int):
628 from matplotlib import rc as rcp
629 rcp('lines', linewidth=linewidth)
630 if refresh and self._data: self.plot(self._data)
631
632 def set_font(self, refresh=True,**kwargs):
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
641 refresh: True (default) or False. If True, the plot is
642 replotted based on the new parameter setting(s).
643 Otherwise,the parameter(s) are set without replotting.
644 """
645 from matplotlib import rc as rcp
646 fdict = {}
647 for k,v in kwargs.iteritems():
648 if v:
649 fdict[k] = v
650 self._fp = FontProperties(**fdict)
651 if refresh and self._data: self.plot(self._data)
652
653 def set_margin(self,margin=[],refresh=True):
654 """
655 Set margins between subplots and plot edges.
656 Parameters:
657 margin: a list of margins in figure coordinate (0-1),
658 i.e., fraction of the figure width or height.
659 The order of elements should be:
660 [left, bottom, right, top, horizontal space btw panels,
661 vertical space btw panels].
662 refresh: True (default) or False. If True, the plot is
663 replotted based on the new parameter setting(s).
664 Otherwise,the parameter(s) are set without replotting.
665 Note
666 * When margin is not specified, the values are reset to the defaults
667 of matplotlib.
668 * If any element is set to be None, the current value is adopted.
669 """
670 if margin == []: self._margins=self._reset_margin()
671 else:
672 self._margins=[None]*6
673 self._margins[0:len(margin)]=margin
674 #print "panel margin set to ",self._margins
675 if refresh and self._data: self.plot(self._data)
676
677 def _reset_margin(self):
678 ks=map(lambda x: 'figure.subplot.'+x,
679 ['left','bottom','right','top','hspace','wspace'])
680 return map(matplotlib.rcParams.get,ks)
681
682 def plot_lines(self, linecat=None, doppler=0.0, deltachan=10, rotate=90.0,
683 location=None):
684 """
685 Plot a line catalog.
686 Parameters:
687 linecat: the linecatalog to plot
688 doppler: the velocity shift to apply to the frequencies
689 deltachan: the number of channels to include each side of the
690 line to determine a local maximum/minimum
691 rotate: the rotation (in degrees) for the text label (default 90.0)
692 location: the location of the line annotation from the 'top',
693 'bottom' or alternate (None - the default)
694 Notes:
695 If the spectrum is flagged no line will be drawn in that location.
696 """
697 if not self._data:
698 raise RuntimeError("No scantable has been plotted yet.")
699 from asap._asap import linecatalog
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.")
704 from numpy import ma
705 for j in range(len(self._plotter.subplots)):
706 self._plotter.subplot(j)
707 lims = self._plotter.axes.get_xlim()
708 for row in range(linecat.nrow()):
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()]
712 c = 299792.458
713 freq = restf*(1.0-doppler/c)
714 if lims[0] < freq < lims[1]:
715 if location is None:
716 loc = 'bottom'
717 if row%2: loc='top'
718 else: loc = location
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)
743 y = line._y[s]
744 maxy = ma.maximum(y)
745 if isinstance( maxy, float):
746 maxys.append(maxy)
747 if len(maxys):
748 peak = max(maxys)
749 if peak > self._plotter.axes.get_ylim()[1]:
750 loc = 'bottom'
751 else:
752 continue
753 self._plotter.vline_with_label(freq, peak,
754 linecat.get_name(row),
755 location=loc, rotate=rotate)
756 self._plotter.show(hardrefresh=False)
757
758
759 def save(self, filename=None, orientation=None, dpi=None):
760 """
761 Save the plot to a file. The known formats are 'png', 'ps', 'eps'.
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.
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.
772 dpi: The dpi of the output non-ps plot
773 """
774 self._plotter.save(filename,orientation,dpi)
775 return
776
777 @asaplog_post_dec
778 def set_mask(self, mask=None, selection=None, refresh=True):
779 """
780 Set a plotting mask for a specific polarization.
781 This is useful for masking out "noise" Pangle outside a source.
782 Parameters:
783 mask: a mask from scantable.create_mask
784 selection: the spectra to apply the mask to.
785 refresh: True (default) or False. If True, the plot is
786 replotted based on the new parameter setting(s).
787 Otherwise,the parameter(s) are set without replotting.
788 Example:
789 select = selector()
790 select.setpolstrings("Pangle")
791 plotter.set_mask(mymask, select)
792 """
793 if not self._data:
794 msg = "Can only set mask after a first call to plot()"
795 raise RuntimeError(msg)
796 if len(mask):
797 if isinstance(mask, list) or isinstance(mask, tuple):
798 self._usermask = array(mask)
799 else:
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):
805 self._maskselection = {'b': selection.get_beams(),
806 's': selection.get_scans(),
807 'i': selection.get_ifs(),
808 'p': selection.get_pols(),
809 't': [] }
810 else:
811 self._maskselection = None
812 if refresh: self.plot(self._data)
813
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
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
832 # find max index
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
842 if start > end:
843 return end,start+1
844 elif start < end:
845 return start,end+1
846 else:
847 return start,end
848
849 def _reset(self):
850 self._usermask = []
851 self._usermaskspectra = None
852 self._offset = None
853 self.set_selection(None, False)
854 self._reset_header()
855
856 def _reset_header(self):
857 self._headtext={'string': None, 'textobj': None}
858
859 def _plot(self, scan):
860 savesel = scan.get_selection()
861 sel = savesel + self._selection
862 order = self._get_sortstring([self._panelling,self._stacking])
863 if order:
864 sel.set_order(order)
865 scan.set_selection(sel)
866 d = {'b': scan.getbeam, 's': scan.getscan,
867 'i': scan.getif, 'p': scan.getpol, 't': scan.get_time,
868 'r': int}#, '_r': int}
869
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
876 else: n = len(n0)
877 if isinstance(nstack0, int): nstack = nstack0
878 else: nstack = len(nstack0)
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'
885 nptot = n
886 maxpanel, maxstack = 16,16
887 if nstack > maxstack:
888 msg ="Scan to be overlayed contains more than %d selections.\n" \
889 "Selecting first %d selections..." % (maxstack, maxstack)
890 asaplog.push(msg)
891 asaplog.post('WARN')
892 nstack = min(nstack,maxstack)
893 #n = min(n-self._ipanel-1,maxpanel)
894 n = n-self._ipanel-1
895
896 ganged = False
897 if n > 1:
898 ganged = rcParams['plotter.ganged']
899 if self._panelling == 'i':
900 ganged = False
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,
904 nplots=n,margin=self._margins,ganged=ganged)
905 else:
906 n = min(n,maxpanel)
907 self._plotter.set_panels(rows=n,cols=0,nplots=n,margin=self._margins,ganged=ganged)
908 else:
909 self._plotter.set_panels(margin=self._margins)
910 #r = 0
911 r = self._startrow
912 nr = scan.nrow()
913 a0,b0 = -1,-1
914 allxlim = []
915 allylim = []
916 #newpanel=True
917 newpanel=False
918 panelcount,stackcount = 0,0
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
927 while r < nr:
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()
937 if self._offset and not self._abcissa:
938 xlab += " (relative)"
939 ylab = self._ordinate and self._ordinate[panelcount] \
940 or scan._get_ordinate_label()
941 self._plotter.set_axes('xlabel', xlab)
942 self._plotter.set_axes('ylabel', ylab)
943 #lbl = self._get_label(scan, r, self._panelling, self._title)
944 lbl = self._get_label(scan, r, titlemode, self._title)
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
950 #lbl = self._get_label(scan, r, self._panelling, None)
951 lbl = self._get_label(scan, r, titlemode, None)
952 self._plotter.set_axes('title',lbl)
953 newpanel = True
954 stackcount = 0
955 panelcount += 1
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
961 #if (b > b0 or newpanel) and stackcount < nstack:
962 if stackcount < nstack and (newpanel or rowstack or (a == a0 and b > b0)):
963 y = []
964 if len(polmodes):
965 y = scan._getspectrum(r, polmodes[scan.getpol(r)])
966 else:
967 y = scan._getspectrum(r)
968 # flag application
969 mr = scan._getflagrow(r)
970 from numpy import ma, array
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
981 x = array(scan._getabcissa(r))
982 if self._offset:
983 x += self._offset
984 if self._minmaxx is not None:
985 s,e = self._slice_indeces(x)
986 x = x[s:e]
987 y = y[s:e]
988 if len(x) > 1024 and rcParams['plotter.decimate']:
989 fac = len(x)/1024
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)
1001 plotit = self._plotter.plot
1002 if self._hist: plotit = self._plotter.hist
1003 if len(x) > 0 and not mr:
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
1009 else:
1010 xlim = self._minmaxx or []
1011 allxlim += xlim
1012 ylim= self._minmaxy or []
1013 allylim += ylim
1014 stackcount += 1
1015 a0=a
1016 b0=b
1017 # last in colour stack -> autoscale x
1018 if stackcount == nstack and len(allxlim) > 0:
1019 allxlim.sort()
1020 self._plotter.subplots[panelcount-1]['axes'].set_xlim([allxlim[0],allxlim[-1]])
1021 if ganged:
1022 allxlim = [allxlim[0],allxlim[-1]]
1023 else:
1024 # clear
1025 allxlim =[]
1026
1027 newpanel = False
1028 #a0=a
1029 #b0=b
1030 # ignore following rows
1031 if (panelcount == n and stackcount == nstack) or (r == nr-1):
1032 # last panel -> autoscale y if ganged
1033 #if rcParams['plotter.ganged'] and len(allylim) > 0:
1034 if ganged and len(allylim) > 0:
1035 allylim.sort()
1036 self._plotter.set_limits(ylim=[allylim[0],allylim[-1]])
1037 break
1038 r+=1 # next row
1039
1040 # save the current counter for multi-page plotting
1041 self._startrow = r+1
1042 self._ipanel += panelcount
1043 if self.casabar_exists():
1044 if self._ipanel >= nptot-1:
1045 self._plotter.figmgr.casabar.disable_next()
1046 else:
1047 self._plotter.figmgr.casabar.enable_next()
1048 if self._ipanel + 1 - panelcount > 0:
1049 self._plotter.figmgr.casabar.enable_prev()
1050 else:
1051 self._plotter.figmgr.casabar.disable_prev()
1052
1053 #reset the selector to the scantable's original
1054 scan.set_selection(savesel)
1055
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):
1059 for o in self._plotter.figure.findobj(Text):
1060 o.set_fontproperties(self._fp)
1061
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 }
1065 if not (type(lorders) == list) and not (type(lorders) == tuple):
1066 return None
1067 if len(lorders) > 0:
1068 lsorts = []
1069 for order in lorders:
1070 if order == "r":
1071 # don't sort if row panelling/stacking
1072 return None
1073 ssort = d0[order]
1074 if ssort:
1075 lsorts.append(ssort)
1076 return lsorts
1077 return None
1078
1079 def set_selection(self, selection=None, refresh=True, **kw):
1080 """
1081 Parameters:
1082 selection: a selector object (default unset the selection)
1083 refresh: True (default) or False. If True, the plot is
1084 replotted based on the new parameter setting(s).
1085 Otherwise,the parameter(s) are set without replotting.
1086 """
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
1102 order = self._get_sortstring([self._panelling,self._stacking])
1103 if order:
1104 self._selection.set_order(order)
1105 if refresh and self._data: self.plot(self._data)
1106
1107 def _get_selected_n(self, scan):
1108 d1 = {'b': scan.getbeamnos, 's': scan.getscannos,
1109 'i': scan.getifnos, 'p': scan.getpolnos, 't': scan.ncycle,
1110 'r': scan.nrow}#, '_r': False}
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(),
1115 't': self._selection.get_cycles(),
1116 'r': False}#, '_r': 1}
1117 n = d2[self._panelling] or d1[self._panelling]()
1118 nstack = d2[self._stacking] or d1[self._stacking]()
1119 # handle row panelling/stacking
1120 if self._panelling == 'r':
1121 nstack = 1
1122 elif self._stacking == 'r':
1123 n = 1
1124 return n,nstack
1125
1126 def _get_label(self, scan, row, mode, userlabel=None):
1127 if isinstance(userlabel, list) and len(userlabel) == 0:
1128 userlabel = " "
1129 pms = dict(zip(self._selection.get_pols(),self._selection.get_poltypes()))
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)),
1135 #'s': scan._getsourcename(row),
1136 's': "Scan "+str(scan.getscan(row))+\
1137 " ("+str(scan._getsourcename(row))+")",
1138 'i': "IF"+str(scan.getif(row)),
1139 'p': poleval,
1140 't': str(scan.get_time(row)),
1141 'r': "row "+str(row),
1142 #'_r': str(scan.get_time(row))+",\nIF"+str(scan.getif(row))+", "+poleval+", Beam"+str(scan.getbeam(row)) }
1143 '_r': "" }
1144 return userlabel or d[mode]
1145
1146 def plotazel(self, scan=None, outfile=None):
1147 """
1148 plot azimuth and elevation versus time of a scantable
1149 """
1150 visible = rcParams['plotter.gui']
1151 from matplotlib import pylab as PL
1152 from matplotlib.dates import DateFormatter, timezone
1153 from matplotlib.dates import HourLocator, MinuteLocator,SecondLocator, DayLocator
1154 from matplotlib.ticker import MultipleLocator
1155 from numpy import array, pi
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)
1160 self._data = scan
1161 self._outfile = outfile
1162 dates = self._data.get_time(asdatetime=True)
1163 t = PL.date2num(dates)
1164 tz = timezone('UTC')
1165 PL.cla()
1166 PL.ioff()
1167 PL.clf()
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
1172 PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
1173 wspace=wsp,hspace=hsp)
1174
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")
1186 elif tdel > 24./60.:
1187 timefmt = DateFormatter('%H:%M')
1188 majloc = HourLocator()
1189 minloc = MinuteLocator(30)
1190 else:
1191 timefmt = DateFormatter('%H:%M')
1192 majloc = MinuteLocator(interval=5)
1193 minloc = SecondLocator(30)
1194
1195 PL.title(dstr)
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)
1205 ax.yaxis.grid(True)
1206 yloc = MultipleLocator(30)
1207 ax.set_ylim(0,90)
1208 ax.yaxis.set_major_locator(yloc)
1209 if tdel > 1.0:
1210 labels = ax.get_xticklabels()
1211 # PL.setp(labels, fontsize=10, rotation=45)
1212 PL.setp(labels, fontsize=10)
1213
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
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)
1232 ax2.yaxis.grid(True)
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
1244 PL.ion()
1245 PL.draw()
1246 if (self._outfile is not None):
1247 PL.savefig(self._outfile)
1248
1249 def plotpointing(self, scan=None, outfile=None):
1250 """
1251 plot telescope pointings
1252 """
1253 visible = rcParams['plotter.gui']
1254 from matplotlib import pylab as PL
1255 from numpy import array, pi
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)
1260 self._data = scan
1261 self._outfile = outfile
1262 dir = array(self._data.get_directionval()).transpose()
1263 ra = dir[0]*180./pi
1264 dec = dir[1]*180./pi
1265 PL.cla()
1266 #PL.ioff()
1267 PL.clf()
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
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])
1277 ax.set_aspect('equal')
1278 PL.plot(ra, dec, 'b,')
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])
1284 #PL.ion()
1285 PL.draw()
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..
1291 @asaplog_post_dec
1292 def plottp(self, scan=None, outfile=None):
1293 if self._plotter.is_dead:
1294 if self.casabar_exists():
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
1320 # Adjust subplot margins
1321 if len(self._margins) !=6: self.set_margin(refresh=False)
1322 lef, bot, rig, top, wsp, hsp = self._margins
1323 self._plotter.figure.subplots_adjust(
1324 left=lef,bottom=bot,right=rig,top=top,wspace=wsp,hspace=hsp)
1325 if self.casabar_exists(): self._plotter.figmgr.casabar.disable_button()
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
1392 @asaplog_post_dec
1393 def print_header(self, plot=True, fontsize=9, logger=False, selstr='', extrastr=''):
1394 """
1395 print data (scantable) header on the plot and/or logger.
1396 To plot the header on the plot, this method should be called after
1397 plotting spectra by the method, asapplotter.plot.
1398 Parameters:
1399 plot: whether or not print header info on the plot.
1400 fontsize: header font size (valid only plot=True)
1401 logger: whether or not print header info on the logger.
1402 selstr: additional selection string (not verified)
1403 extrastr: additional string to print at the beginning (not verified)
1404 """
1405 if not plot and not logger:
1406 return
1407 if not self._data:
1408 raise RuntimeError("No scantable has been set yet.")
1409 # Now header will be printed on plot and/or logger.
1410 # Get header information and format it.
1411 ssum=self._data._list_header()
1412 # Print Observation header to the upper-left corner of plot
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
1419 if selstr != '':
1420 selstr += '\n'
1421 self._headtext['selstr'] = selstr
1422 ssel=(selstr+self._data.get_selection().__str__()+self._selection.__str__() or 'none')
1423 headstr.append('***Selections***\n'+ssel)
1424
1425 if plot:
1426 self._plotter.hold()
1427 self._header_plot(headstr,fontsize=fontsize)
1428 import time
1429 self._plotter.figure.text(0.99,0.01,
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:
1435 selstr = "Selections: "+ssel
1436 asaplog.push("----------------\n Plot Summary\n----------------")
1437 asaplog.push(extrastr)
1438 asaplog.push(ssum[ssum.find('Beams:'):ssum.find('Selection:')]\
1439 #+ selstr + ssum[ssum.find('Scan Source'):])
1440 + selstr)
1441 self._headtext['string'] = headstr
1442 del ssel, ssum, headstr
1443
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.