source: trunk/python/asapplotter.py@ 1985

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

New Development: No

JIRA Issue: Yes (CAS-1822/ASAP-204)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs:

Put in Release Notes: No

Module(s): asapplotter & sdplot

Description:

for got to commit this. The previous commit of casatoolbar.py depends on this code.


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