source: branches/parallel/python/asapplotter.py@ 2021

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

New Development: No

JIRA Issue: Yes (CAS-2775)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs: plot spectra with FLAGROW=1

Put in Release Notes: No

Module(s): asapplotter, sdplot

Description:

Proper handling of FLAGROW values in sdplot/asapplotter.
Also, proper handling of plotrange for totally flagged spectra.


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