source: trunk/python/asapplotter.py@ 2017

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

New Development: No

JIRA Issue: No (a bug fix)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs: plot 1 panel plot

Put in Release Notes: No

Module(s): asapplotter and sdplot

Description: Fixed a bug which causes Error when plotting a single panel plot.


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