source: trunk/python/asapplotter.py@ 2044

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

New Development: Yes

JIRA Issue: Yes (CAS-2894/ASAP-237)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs:

Put in Release Notes: Yes

Module(s): asapplotter, sdplot

Description: discarded 16 panels limit when column and row numbers of subplots are set by asapplotter.set_layout.


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