source: branches/casa-prerelease/pre-asap/python/asapplotter.py@ 2056

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

merged a bug fix in trunk(r2053)

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