source: trunk/python/asapplotter.py@ 1964

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

New Development: No

JIRA Issue: No (a bug fix)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs:

Put in Release Notes: No

Module(s): asapplotter and sdplot

Description:

Fixed a bug that empty panel is created for data with short integration time (<1s).
modified asapplotter._plot to get time stamp calling scantable.get_time instead
of scantable._gettime.

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