source: trunk/python/asapplotter.py@ 1944

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

New Development: No

JIRA Issue: No (Bug fixes)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs:

Put in Release Notes: No

Module(s): asapplotter, sdplot

Description:

Fixed a couple of bugs found in user tests for CASA 3.1

  • Fixed a bug which caused scantables never being sorted at all.
  • Fixed a bug which caused unexpected stacking of spectra in the

last panel of the plot.

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