source: trunk/python/asapplotter.py@ 2697

Last change on this file since 2697 was 2697, checked in by Kana Sugimoto, 12 years ago

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs: iterate pages

Put in Release Notes: No

Module(s): asapplotter and sdplot

Description: An attempt to speed-up page iterations in ASAP plotter.


  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 79.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
8from matplotlib import _pylab_helpers
9
10import re
11
12def new_asaplot(visible=None,**kwargs):
13 """
14 Returns a new asaplot instance based on the backend settings.
15 """
16 if visible == None:
17 visible = rcParams['plotter.gui']
18
19 backend=matplotlib.get_backend()
20 if not visible:
21 from asap.asaplot import asaplot
22 elif backend == 'TkAgg':
23 from asap.asaplotgui import asaplotgui as asaplot
24 elif backend == 'Qt4Agg':
25 from asap.asaplotgui_qt4 import asaplotgui as asaplot
26 elif backend == 'GTkAgg':
27 from asap.asaplotgui_gtk import asaplotgui as asaplot
28 else:
29 from asap.asaplot import asaplot
30 return asaplot(**kwargs)
31
32class asapplotter:
33 """
34 The ASAP plotter.
35 By default the plotter is set up to plot polarisations
36 'colour stacked' and scantables across panels.
37
38 .. note::
39
40 Currenly it only plots 'spectra' not Tsys or
41 other variables.
42
43 """
44 def __init__(self, visible=None , **kwargs):
45 self._visible = rcParams['plotter.gui']
46 if visible is not None:
47 self._visible = visible
48 self._plotter = None
49 self._inikwg = kwargs
50
51 self._panelling = None
52 self._stacking = None
53 self.set_panelling()
54 self.set_stacking()
55 self._rows = None
56 self._cols = None
57 self._minmaxx = None
58 self._minmaxy = None
59 self._datamask = None
60 self._data = None
61 self._lmap = None
62 self._title = None
63 self._ordinate = None
64 self._abcissa = None
65 self._abcunit = None
66 self._usermask = []
67 self._maskselection = None
68 self._selection = selector()
69 self._hist = rcParams['plotter.histogram']
70 self._fp = FontProperties()
71 self._margins = self.set_margin(refresh=False)
72 self._offset = None
73 self._startrow = 0
74 self._ipanel = -1
75 self._panelrows = []
76 self._headtext={'string': None, 'textobj': None}
77 self._colormap = None
78 self._linestyles = None
79 self._legendloc = None
80
81 def _translate(self, instr):
82 keys = "s b i p t r".split()
83 if isinstance(instr, str):
84 for key in keys:
85 if instr.lower().startswith(key):
86 return key
87 return None
88
89 @asaplog_post_dec
90 def _reload_plotter(self):
91 if self._plotter is not None:
92 #if not self._plotter.is_dead:
93 # # clear lines and axes
94 # try:
95 # self._plotter.clear()
96 # except: # Can't remove when already killed.
97 # pass
98 if self.casabar_exists():
99 del self._plotter.figmgr.casabar
100 self._plotter.quit()
101 del self._plotter
102 asaplog.push('Loading new plotter')
103 self._plotter = new_asaplot(self._visible,**self._inikwg)
104 self._plotter.figmgr.casabar=self._new_custombar()
105 # just to make sure they're set
106 self._plotter.palette(color=0,colormap=self._colormap,
107 linestyle=0,linestyles=self._linestyles)
108 self._plotter.legend(self._legendloc)
109
110 def _new_custombar(self):
111 backend=matplotlib.get_backend()
112 if not self._visible:
113 return None
114 elif backend == "TkAgg":
115 from asap.customgui_tkagg import CustomToolbarTkAgg
116 return CustomToolbarTkAgg(self)
117 elif backend == "Qt4Agg":
118 from asap.customgui_qt4agg import CustomToolbarQT4Agg
119 return CustomToolbarQT4Agg(self)
120 return None
121
122 def casabar_exists(self):
123 if not hasattr(self._plotter.figmgr,'casabar'):
124 return False
125 elif self._plotter.figmgr.casabar:
126 return True
127 return False
128
129 def _assert_plotter(self,action="status",errmsg=None):
130 """
131 Check plot window status. Returns True if plot window is alive.
132 Parameters
133 action: An action to take if the plotter window is not alive.
134 ['status'|'reload'|'halt']
135 The action 'status' simply returns False if asaplot
136 is not alive. When action='reload', plot window is
137 reloaded and the method returns True. Finally, an
138 error is raised when action='halt'.
139 errmsg: An error (warning) message to send to the logger,
140 when plot window is not alive.
141 """
142 isAlive = (self._plotter is not None) and self._plotter._alive()
143 # More tests
144 #if isAlive:
145 # if self._plotter.figmgr:
146 # figmgr = self._plotter.figmgr
147 # figid = figmgr.num
148 # # Make sure figid=0 is what asapplotter expects.
149 # # It might be already destroied/overridden by matplotlib
150 # # commands or other plotting methods using asaplot.
151 # isAlive = _pylab_helpers.Gcf.has_fignum(figid) and \
152 # (figmgr == \
153 # _pylab_helpers.Gcf.get_fig_manager(figid))
154 # else:
155 # isAlive = False
156
157 if isAlive:
158 return True
159 # Plotter is not alive.
160 haltmsg = "Plotter window has not yet been loaded or is closed."
161 if type(errmsg)==str and len(errmsg) > 0:
162 haltmsg = errmsg
163
164 if action.upper().startswith("R"):
165 # reload plotter
166 self._reload_plotter()
167 return True
168 elif action.upper().startswith("H"):
169 # halt
170 asaplog.push(haltmsg)
171 asaplog.post("ERROR")
172 raise RuntimeError(haltmsg)
173 else:
174 if errmsg:
175 asaplog.push(errmsg)
176 asaplog.post("WARN")
177 return False
178
179
180 @asaplog_post_dec
181 def plot(self, scan=None):
182 """
183 Plot a scantable.
184 Parameters:
185 scan: a scantable
186 Note:
187 If a scantable was specified in a previous call
188 to plot, no argument has to be given to 'replot'
189 NO checking is done that the abcissas of the scantable
190 are consistent e.g. all 'channel' or all 'velocity' etc.
191 """
192 if not self._data and not scan:
193 msg = "Input is not a scantable"
194 raise TypeError(msg)
195
196 self._assert_plotter(action="reload")
197 self._plotter.hold()
198 self._reset_counter()
199 #self._plotter.clear()
200 if scan:
201 self.set_data(scan, refresh=False)
202 self._plotter.palette(color=0,colormap=self._colormap,
203 linestyle=0,linestyles=self._linestyles)
204 self._plotter.legend(self._legendloc)
205 self._plot(self._data)
206 if self._minmaxy is not None:
207 self._plotter.set_limits(ylim=self._minmaxy)
208 if self.casabar_exists(): self._plotter.figmgr.casabar.enable_button()
209 self._plotter.release()
210 self._plotter.tidy()
211 self._plotter.show(hardrefresh=False)
212 return
213
214 def gca(self):
215 errmsg = "No axis to retun. Need to plot first."
216 if not self._assert_plotter(action="status",errmsg=errmsg):
217 return None
218 return self._plotter.figure.gca()
219
220 def refresh(self):
221 """Do a soft refresh"""
222 errmsg = "No figure to re-plot. Need to plot first."
223 self._assert_plotter(action="halt",errmsg=errmsg)
224
225 self._plotter.figure.show()
226
227 def create_mask(self, nwin=1, panel=0, color=None):
228 """
229 Interactively define a mask. It retruns a mask that is equivalent to
230 the one created manually with scantable.create_mask.
231 Parameters:
232 nwin: The number of mask windows to create interactively
233 default is 1.
234 panel: Which panel to use for mask selection. This is useful
235 if different IFs are spread over panels (default 0)
236 """
237 ## this method relies on already plotted figure
238 if not self._assert_plotter(action="status") or (self._data is None):
239 msg = "Cannot create mask interactively on plot. Can only create mask after plotting."
240 asaplog.push( msg )
241 asaplog.post( "ERROR" )
242 return []
243 outmask = []
244 self._plotter.subplot(panel)
245 xmin, xmax = self._plotter.axes.get_xlim()
246 marg = 0.05*(xmax-xmin)
247 self._plotter.axes.set_xlim(xmin-marg, xmax+marg)
248 self.refresh()
249
250 def cleanup(lines=False, texts=False, refresh=False):
251 if lines:
252 del self._plotter.axes.lines[-1]
253 if texts:
254 del self._plotter.axes.texts[-1]
255 if refresh:
256 self.refresh()
257
258 for w in xrange(nwin):
259 wpos = []
260 self.text(0.05,1.0, "Add start boundary",
261 coords="relative", fontsize=10)
262 point = self._plotter.get_point()
263 cleanup(texts=True)
264 if point is None:
265 continue
266 wpos.append(point[0])
267 self.axvline(wpos[0], color=color)
268 self.text(0.05,1.0, "Add end boundary", coords="relative", fontsize=10)
269 point = self._plotter.get_point()
270 cleanup(texts=True, lines=True)
271 if point is None:
272 self.refresh()
273 continue
274 wpos.append(point[0])
275 self.axvspan(wpos[0], wpos[1], alpha=0.1,
276 edgecolor=color, facecolor=color)
277 ymin, ymax = self._plotter.axes.get_ylim()
278 outmask.append(wpos)
279
280 self._plotter.axes.set_xlim(xmin, xmax)
281 self.refresh()
282 if len(outmask) > 0:
283 return self._data.create_mask(*outmask)
284 return []
285
286 # forwards to matplotlib axes
287 def text(self, *args, **kwargs):
288 self._assert_plotter(action="reload")
289 if kwargs.has_key("interactive"):
290 if kwargs.pop("interactive"):
291 pos = self._plotter.get_point()
292 args = tuple(pos)+args
293 self._axes_callback("text", *args, **kwargs)
294
295 text.__doc__ = matplotlib.axes.Axes.text.__doc__
296
297 def arrow(self, *args, **kwargs):
298 self._assert_plotter(action="reload")
299 if kwargs.has_key("interactive"):
300 if kwargs.pop("interactive"):
301 pos = self._plotter.get_region()
302 dpos = (pos[0][0], pos[0][1],
303 pos[1][0]-pos[0][0],
304 pos[1][1] - pos[0][1])
305 args = dpos + args
306 self._axes_callback("arrow", *args, **kwargs)
307
308 arrow.__doc__ = matplotlib.axes.Axes.arrow.__doc__
309
310 def annotate(self, text, xy=None, xytext=None, **kwargs):
311 self._assert_plotter(action="reload")
312 if kwargs.has_key("interactive"):
313 if kwargs.pop("interactive"):
314 xy = self._plotter.get_point()
315 xytext = self._plotter.get_point()
316 if not kwargs.has_key("arrowprops"):
317 kwargs["arrowprops"] = dict(arrowstyle="->")
318 self._axes_callback("annotate", text, xy, xytext, **kwargs)
319
320 annotate.__doc__ = matplotlib.axes.Axes.annotate.__doc__
321
322 def axvline(self, *args, **kwargs):
323 self._assert_plotter(action="reload")
324 if kwargs.has_key("interactive"):
325 if kwargs.pop("interactive"):
326 pos = self._plotter.get_point()
327 args = (pos[0],)+args
328 self._axes_callback("axvline", *args, **kwargs)
329
330 axvline.__doc__ = matplotlib.axes.Axes.axvline.__doc__
331
332 def axhline(self, *args, **kwargs):
333 self._assert_plotter(action="reload")
334 if kwargs.has_key("interactive"):
335 if kwargs.pop("interactive"):
336 pos = self._plotter.get_point()
337 args = (pos[1],)+args
338 self._axes_callback("axhline", *args, **kwargs)
339
340 axhline.__doc__ = matplotlib.axes.Axes.axhline.__doc__
341
342 def axvspan(self, *args, **kwargs):
343 self._assert_plotter(action="reload")
344 if kwargs.has_key("interactive"):
345 if kwargs.pop("interactive"):
346 pos = self._plotter.get_region()
347 dpos = (pos[0][0], pos[1][0])
348 args = dpos + args
349 self._axes_callback("axvspan", *args, **kwargs)
350 # hack to preventy mpl from redrawing the patch
351 # it seem to convert the patch into lines on every draw.
352 # This doesn't happen in a test script???
353 #del self._plotter.axes.patches[-1]
354
355 axvspan.__doc__ = matplotlib.axes.Axes.axvspan.__doc__
356
357 def axhspan(self, *args, **kwargs):
358 self._assert_plotter(action="reload")
359 if kwargs.has_key("interactive"):
360 if kwargs.pop("interactive"):
361 pos = self._plotter.get_region()
362 dpos = (pos[0][1], pos[1][1])
363 args = dpos + args
364 self._axes_callback("axhspan", *args, **kwargs)
365 # hack to preventy mpl from redrawing the patch
366 # it seem to convert the patch into lines on every draw.
367 # This doesn't happen in a test script???
368 #del self._plotter.axes.patches[-1]
369
370 axhspan.__doc__ = matplotlib.axes.Axes.axhspan.__doc__
371
372 def _axes_callback(self, axesfunc, *args, **kwargs):
373 self._assert_plotter(action="reload")
374 panel = 0
375 if kwargs.has_key("panel"):
376 panel = kwargs.pop("panel")
377 coords = None
378 if kwargs.has_key("coords"):
379 coords = kwargs.pop("coords")
380 if coords.lower() == 'world':
381 kwargs["transform"] = self._plotter.axes.transData
382 elif coords.lower() == 'relative':
383 kwargs["transform"] = self._plotter.axes.transAxes
384 self._plotter.subplot(panel)
385 self._plotter.axes.set_autoscale_on(False)
386 getattr(self._plotter.axes, axesfunc)(*args, **kwargs)
387 self._plotter.show(False)
388 self._plotter.axes.set_autoscale_on(True)
389 # end matplotlib.axes fowarding functions
390
391 @asaplog_post_dec
392 def set_data(self, scan, refresh=True):
393 """
394 Set a scantable to plot.
395 Parameters:
396 scan: a scantable
397 refresh: True (default) or False. If True, the plot is
398 replotted based on the new parameter setting(s).
399 Otherwise,the parameter(s) are set without replotting.
400 Note:
401 The user specified masks and data selections will be reset
402 if a new scantable is set. This method should be called before
403 setting data selections (set_selection) and/or masks (set_mask).
404 """
405 from asap import scantable
406 if isinstance(scan, scantable):
407 if (self._data is not None) and (scan != self._data):
408 del self._data
409 msg = "A new scantable is set to the plotter. "\
410 "The masks and data selections are reset."
411 asaplog.push( msg )
412 self._data = scan
413 # reset
414 self._reset()
415 else:
416 msg = "Input is not a scantable"
417 raise TypeError(msg)
418
419 # ranges become invalid when unit changes
420 if self._abcunit and self._abcunit != self._data.get_unit():
421 self._minmaxx = None
422 self._minmaxy = None
423 self._abcunit = self._data.get_unit()
424 self._datamask = None
425 if refresh: self.plot()
426
427 @asaplog_post_dec
428 def set_mode(self, stacking=None, panelling=None, refresh=True):
429 """
430 Set the plots look and feel, i.e. what you want to see on the plot.
431 Parameters:
432 stacking: tell the plotter which variable to plot
433 as line colour overlays (default 'pol')
434 panelling: tell the plotter which variable to plot
435 across multiple panels (default 'scan'
436 refresh: True (default) or False. If True, the plot is
437 replotted based on the new parameter setting(s).
438 Otherwise,the parameter(s) are set without replotting.
439 Note:
440 Valid modes are:
441 'beam' 'Beam' 'b': Beams
442 'if' 'IF' 'i': IFs
443 'pol' 'Pol' 'p': Polarisations
444 'scan' 'Scan' 's': Scans
445 'time' 'Time' 't': Times
446 'row' 'Row' 'r': Rows
447 When either 'stacking' or 'panelling' is set to 'row',
448 the other parameter setting is ignored.
449 """
450 msg = "Invalid mode"
451 if not self.set_panelling(panelling) or \
452 not self.set_stacking(stacking):
453 raise TypeError(msg)
454 #if self._panelling == 'r':
455 # self._stacking = '_r'
456 #if self._stacking == 'r':
457 # self._panelling = '_r'
458 if refresh and self._data: self.plot(self._data)
459 return
460
461 def set_panelling(self, what=None):
462 """Set the 'panelling' mode i.e. which type of spectra should be
463 spread across different panels.
464 """
465
466 mode = what
467 if mode is None:
468 mode = rcParams['plotter.panelling']
469 md = self._translate(mode)
470 if md:
471 self._panelling = md
472 self._title = None
473 #if md == 'r':
474 # self._stacking = '_r'
475 # you need to reset counters for multi page plotting
476 self._reset_counters()
477 return True
478 return False
479
480 def set_layout(self,rows=None,cols=None,refresh=True):
481 """
482 Set the multi-panel layout, i.e. how many rows and columns plots
483 are visible.
484 Parameters:
485 rows: The number of rows of plots
486 cols: The number of columns of plots
487 refresh: True (default) or False. If True, the plot is
488 replotted based on the new parameter setting(s).
489 Otherwise,the parameter(s) are set without replotting.
490 Note:
491 If no argument is given, the potter reverts to its auto-plot
492 behaviour.
493 """
494 self._rows = rows
495 self._cols = cols
496 if refresh and self._data: self.plot(self._data)
497 return
498
499 def set_stacking(self, what=None):
500 """Set the 'stacking' mode i.e. which type of spectra should be
501 overlayed.
502 """
503 mode = what
504 if mode is None:
505 mode = rcParams['plotter.stacking']
506 md = self._translate(mode)
507 if md:
508 self._stacking = md
509 self._lmap = None
510 #if md == 'r':
511 # self._panelling = '_r'
512 # you need to reset counters for multi page plotting
513 self._reset_counters()
514 return True
515 return False
516
517 def _reset_counters(self):
518 self._startrow = 0
519 self._ipanel = -1
520 self._panelrows = []
521
522 def set_range(self,xstart=None,xend=None,ystart=None,yend=None,refresh=True, offset=None):
523 """
524 Set the range of interest on the abcissa of the plot
525 Parameters:
526 [x,y]start,[x,y]end: The start and end points of the 'zoom' window
527 refresh: True (default) or False. If True, the plot is
528 replotted based on the new parameter setting(s).
529 Otherwise,the parameter(s) are set without replotting.
530 offset: shift the abcissa by the given amount. The abcissa label will
531 have '(relative)' appended to it.
532 Note:
533 These become non-sensical when the unit changes.
534 use plotter.set_range() without parameters to reset
535
536 """
537 self._offset = offset
538 if xstart is None and xend is None:
539 self._minmaxx = None
540 else:
541 self._minmaxx = [xstart,xend]
542 if ystart is None and yend is None:
543 self._minmaxy = None
544 else:
545 self._minmaxy = [ystart,yend]
546 if refresh and self._data: self.plot(self._data)
547 return
548
549 def set_legend(self, mp=None, fontsize = None, mode = 0, refresh=True):
550 """
551 Specify a mapping for the legend instead of using the default
552 indices:
553 Parameters:
554 mp: a list of 'strings'. This should have the same length
555 as the number of elements on the legend and then maps
556 to the indeces in order. It is possible to uses latex
557 math expression. These have to be enclosed in r'',
558 e.g. r'$x^{2}$'
559 fontsize: The font size of the label (default None)
560 mode: where to display the legend
561 Any other value for loc else disables the legend:
562 0: auto
563 1: upper right
564 2: upper left
565 3: lower left
566 4: lower right
567 5: right
568 6: center left
569 7: center right
570 8: lower center
571 9: upper center
572 10: center
573 refresh: True (default) or False. If True, the plot is
574 replotted based on the new parameter setting(s).
575 Otherwise,the parameter(s) are set without replotting.
576
577 Example:
578 If the data has two IFs/rest frequencies with index 0 and 1
579 for CO and SiO:
580 plotter.set_stacking('i')
581 plotter.set_legend(['CO','SiO'])
582 plotter.plot()
583 plotter.set_legend([r'$^{12}CO$', r'SiO'])
584 """
585 self._lmap = mp
586 #self._plotter.legend(mode)
587 self._legendloc = mode
588 if isinstance(fontsize, int):
589 from matplotlib import rc as rcp
590 rcp('legend', fontsize=fontsize)
591 if refresh and self._data: self.plot(self._data)
592 return
593
594 def set_title(self, title=None, fontsize=None, refresh=True):
595 """
596 Set the title of sub-plots. If multiple sub-plots are plotted,
597 multiple titles have to be specified.
598 Parameters:
599 title: a list of titles of sub-plots.
600 fontsize: a font size of titles (integer)
601 refresh: True (default) or False. If True, the plot is
602 replotted based on the new parameter setting(s).
603 Otherwise,the parameter(s) are set without replotting.
604 Example:
605 # two panels are visible on the plotter
606 plotter.set_title(['First Panel','Second Panel'])
607 """
608 self._title = title
609 if isinstance(fontsize, int):
610 from matplotlib import rc as rcp
611 rcp('axes', titlesize=fontsize)
612 if refresh and self._data: self.plot(self._data)
613 return
614
615 def set_ordinate(self, ordinate=None, fontsize=None, refresh=True):
616 """
617 Set the y-axis label of the plot. If multiple panels are plotted,
618 multiple labels have to be specified.
619 Parameters:
620 ordinate: a list of ordinate labels. None (default) let
621 data determine the labels
622 fontsize: a font size of vertical axis labels (integer)
623 refresh: True (default) or False. If True, the plot is
624 replotted based on the new parameter setting(s).
625 Otherwise,the parameter(s) are set without replotting.
626 Example:
627 # two panels are visible on the plotter
628 plotter.set_ordinate(['First Y-Axis','Second Y-Axis'])
629 """
630 self._ordinate = ordinate
631 if isinstance(fontsize, int):
632 from matplotlib import rc as rcp
633 rcp('axes', labelsize=fontsize)
634 rcp('ytick', labelsize=fontsize)
635 if refresh and self._data: self.plot(self._data)
636 return
637
638 def set_abcissa(self, abcissa=None, fontsize=None, refresh=True):
639 """
640 Set the x-axis label of the plot. If multiple panels are plotted,
641 multiple labels have to be specified.
642 Parameters:
643 abcissa: a list of abcissa labels. None (default) let
644 data determine the labels
645 fontsize: a font size of horizontal axis labels (integer)
646 refresh: True (default) or False. If True, the plot is
647 replotted based on the new parameter setting(s).
648 Otherwise,the parameter(s) are set without replotting.
649 Example:
650 # two panels are visible on the plotter
651 plotter.set_ordinate(['First X-Axis','Second X-Axis'])
652 """
653 self._abcissa = abcissa
654 if isinstance(fontsize, int):
655 from matplotlib import rc as rcp
656 rcp('axes', labelsize=fontsize)
657 rcp('xtick', labelsize=fontsize)
658 if refresh and self._data: self.plot(self._data)
659 return
660
661 def set_colors(self, colmap, refresh=True):
662 """
663 Set the colours to be used. The plotter will cycle through
664 these colours when lines are overlaid (stacking mode).
665 Parameters:
666 colmap: a list of colour names
667 refresh: True (default) or False. If True, the plot is
668 replotted based on the new parameter setting(s).
669 Otherwise,the parameter(s) are set without replotting.
670 Example:
671 plotter.set_colors('red green blue')
672 # If for example four lines are overlaid e.g I Q U V
673 # 'I' will be 'red', 'Q' will be 'green', U will be 'blue'
674 # and 'V' will be 'red' again.
675 """
676 #if isinstance(colmap,str):
677 # colmap = colmap.split()
678 #self._plotter.palette(0, colormap=colmap)
679 self._colormap = colmap
680 if refresh and self._data: self.plot(self._data)
681
682 # alias for english speakers
683 set_colours = set_colors
684
685 def set_histogram(self, hist=True, linewidth=None, refresh=True):
686 """
687 Enable/Disable histogram-like plotting.
688 Parameters:
689 hist: True (default) or False. The fisrt default
690 is taken from the .asaprc setting
691 plotter.histogram
692 linewidth: a line width
693 refresh: True (default) or False. If True, the plot is
694 replotted based on the new parameter setting(s).
695 Otherwise,the parameter(s) are set without replotting.
696 """
697 self._hist = hist
698 if isinstance(linewidth, float) or isinstance(linewidth, int):
699 from matplotlib import rc as rcp
700 rcp('lines', linewidth=linewidth)
701 if refresh and self._data: self.plot(self._data)
702
703 def set_linestyles(self, linestyles=None, linewidth=None, refresh=True):
704 """
705 Set the linestyles to be used. The plotter will cycle through
706 these linestyles when lines are overlaid (stacking mode) AND
707 only one color has been set.
708 Parameters:
709 linestyles: a list of linestyles to use.
710 'line', 'dashed', 'dotted', 'dashdot',
711 'dashdotdot' and 'dashdashdot' are
712 possible
713 linewidth: a line width
714 refresh: True (default) or False. If True, the plot is
715 replotted based on the new parameter setting(s).
716 Otherwise,the parameter(s) are set without replotting.
717 Example:
718 plotter.set_colors('black')
719 plotter.set_linestyles('line dashed dotted dashdot')
720 # If for example four lines are overlaid e.g I Q U V
721 # 'I' will be 'solid', 'Q' will be 'dashed',
722 # U will be 'dotted' and 'V' will be 'dashdot'.
723 """
724 #if isinstance(linestyles,str):
725 # linestyles = linestyles.split()
726 #self._plotter.palette(color=0,linestyle=0,linestyles=linestyles)
727 self._linestyles = linestyles
728 if isinstance(linewidth, float) or isinstance(linewidth, int):
729 from matplotlib import rc as rcp
730 rcp('lines', linewidth=linewidth)
731 if refresh and self._data: self.plot(self._data)
732
733 def set_font(self, refresh=True,**kwargs):
734 """
735 Set font properties.
736 Parameters:
737 family: one of 'sans-serif', 'serif', 'cursive', 'fantasy', 'monospace'
738 style: one of 'normal' (or 'roman'), 'italic' or 'oblique'
739 weight: one of 'normal or 'bold'
740 size: the 'general' font size, individual elements can be adjusted
741 seperately
742 refresh: True (default) or False. If True, the plot is
743 replotted based on the new parameter setting(s).
744 Otherwise,the parameter(s) are set without replotting.
745 """
746 from matplotlib import rc as rcp
747 fdict = {}
748 for k,v in kwargs.iteritems():
749 if v:
750 fdict[k] = v
751 self._fp = FontProperties(**fdict)
752 if refresh and self._data: self.plot(self._data)
753
754 def set_margin(self,margin=[],refresh=True):
755 """
756 Set margins between subplots and plot edges.
757 Parameters:
758 margin: a list of margins in figure coordinate (0-1),
759 i.e., fraction of the figure width or height.
760 The order of elements should be:
761 [left, bottom, right, top, horizontal space btw panels,
762 vertical space btw panels].
763 refresh: True (default) or False. If True, the plot is
764 replotted based on the new parameter setting(s).
765 Otherwise,the parameter(s) are set without replotting.
766 Note
767 * When margin is not specified, the values are reset to the defaults
768 of matplotlib.
769 * If any element is set to be None, the current value is adopted.
770 """
771 if margin == []: self._margins=self._reset_margin()
772 else:
773 self._margins=[None]*6
774 self._margins[0:len(margin)]=margin
775 #print "panel margin set to ",self._margins
776 if refresh and self._data: self.plot(self._data)
777
778 def _reset_margin(self):
779 ks=map(lambda x: 'figure.subplot.'+x,
780 ['left','bottom','right','top','hspace','wspace'])
781 return map(matplotlib.rcParams.get,ks)
782
783 def plot_lines(self, linecat=None, doppler=0.0, deltachan=10, rotate=90.0,
784 location=None):
785 """
786 Plot a line catalog.
787 Parameters:
788 linecat: the linecatalog to plot
789 doppler: the velocity shift to apply to the frequencies
790 deltachan: the number of channels to include each side of the
791 line to determine a local maximum/minimum
792 rotate: the rotation (in degrees) for the text label (default 90.0)
793 location: the location of the line annotation from the 'top',
794 'bottom' or alternate (None - the default)
795 Notes:
796 If the spectrum is flagged no line will be drawn in that location.
797 """
798 errmsg = "Cannot plot spectral lines. Need to plot scantable first."
799 self._assert_plotter(action="halt",errmsg=errmsg)
800 if not self._data:
801 raise RuntimeError("No scantable has been plotted yet.")
802 from asap._asap import linecatalog
803 if not isinstance(linecat, linecatalog):
804 raise ValueError("'linecat' isn't of type linecatalog.")
805 if not self._data.get_unit().endswith("Hz"):
806 raise RuntimeError("Can only overlay linecatalogs when data is in frequency.")
807 from numpy import ma
808 for j in range(len(self._plotter.subplots)):
809 self._plotter.subplot(j)
810 lims = self._plotter.axes.get_xlim()
811 for row in range(linecat.nrow()):
812 # get_frequency returns MHz
813 base = { "GHz": 1000.0, "MHz": 1.0, "Hz": 1.0e-6 }
814 restf = linecat.get_frequency(row)/base[self._data.get_unit()]
815 c = 299792.458
816 freq = restf*(1.0-doppler/c)
817 if lims[0] < freq < lims[1]:
818 if location is None:
819 loc = 'bottom'
820 if row%2: loc='top'
821 else: loc = location
822 maxys = []
823 for line in self._plotter.axes.lines:
824 v = line._x
825 asc = v[0] < v[-1]
826
827 idx = None
828 if not asc:
829 if v[len(v)-1] <= freq <= v[0]:
830 i = len(v)-1
831 while i>=0 and v[i] < freq:
832 idx = i
833 i-=1
834 else:
835 if v[0] <= freq <= v[len(v)-1]:
836 i = 0
837 while i<len(v) and v[i] < freq:
838 idx = i
839 i+=1
840 if idx is not None:
841 lower = idx - deltachan
842 upper = idx + deltachan
843 if lower < 0: lower = 0
844 if upper > len(v): upper = len(v)
845 s = slice(lower, upper)
846 y = line._y[s]
847 maxy = ma.maximum(y)
848 if isinstance( maxy, float):
849 maxys.append(maxy)
850 if len(maxys):
851 peak = max(maxys)
852 if peak > self._plotter.axes.get_ylim()[1]:
853 loc = 'bottom'
854 else:
855 continue
856 self._plotter.vline_with_label(freq, peak,
857 linecat.get_name(row),
858 location=loc, rotate=rotate)
859 self._plotter.show(hardrefresh=False)
860
861
862 def save(self, filename=None, orientation=None, dpi=None):
863 """
864 Save the plot to a file. The known formats are 'png', 'ps', 'eps'.
865 Parameters:
866 filename: The name of the output file. This is optional
867 and autodetects the image format from the file
868 suffix. If non filename is specified a file
869 called 'yyyymmdd_hhmmss.png' is created in the
870 current directory.
871 orientation: optional parameter for postscript only (not eps).
872 'landscape', 'portrait' or None (default) are valid.
873 If None is choosen for 'ps' output, the plot is
874 automatically oriented to fill the page.
875 dpi: The dpi of the output non-ps plot
876 """
877 errmsg = "Cannot save figure. Need to plot first."
878 self._assert_plotter(action="halt",errmsg=errmsg)
879
880 self._plotter.save(filename,orientation,dpi)
881 return
882
883 @asaplog_post_dec
884 def set_mask(self, mask=None, selection=None, refresh=True):
885 """
886 Set a plotting mask for a specific polarization.
887 This is useful for masking out 'noise' Pangle outside a source.
888 Parameters:
889 mask: a mask from scantable.create_mask
890 selection: the spectra to apply the mask to.
891 refresh: True (default) or False. If True, the plot is
892 replotted based on the new parameter setting(s).
893 Otherwise,the parameter(s) are set without replotting.
894 Example:
895 select = selector()
896 select.setpolstrings('Pangle')
897 plotter.set_mask(mymask, select)
898 """
899 if not self._data:
900 msg = "Can only set mask after a first call to plot()"
901 raise RuntimeError(msg)
902 if len(mask):
903 if isinstance(mask, list) or isinstance(mask, tuple):
904 self._usermask = array(mask)
905 else:
906 self._usermask = mask
907 if mask is None and selection is None:
908 self._usermask = []
909 self._maskselection = None
910 if isinstance(selection, selector):
911 self._maskselection = {'b': selection.get_beams(),
912 's': selection.get_scans(),
913 'i': selection.get_ifs(),
914 'p': selection.get_pols(),
915 't': [] }
916 else:
917 self._maskselection = None
918 if refresh: self.plot(self._data)
919
920 def _slice_indeces(self, data):
921 mn = self._minmaxx[0]
922 mx = self._minmaxx[1]
923 asc = data[0] < data[-1]
924 start=0
925 end = len(data)-1
926 inc = 1
927 if not asc:
928 start = len(data)-1
929 end = 0
930 inc = -1
931 # find min index
932 #while start > 0 and data[start] < mn:
933 # start+= inc
934 minind=start
935 for ind in xrange(start,end+inc,inc):
936 if data[ind] > mn: break
937 minind=ind
938 # find max index
939 #while end > 0 and data[end] > mx:
940 # end-=inc
941 #if end > 0: end +=1
942 maxind=end
943 for ind in xrange(end,start-inc,-inc):
944 if data[ind] < mx: break
945 maxind=ind
946 start=minind
947 end=maxind
948 if start > end:
949 return end,start+1
950 elif start < end:
951 return start,end+1
952 else:
953 return start,end
954
955 def _reset(self):
956 self._usermask = []
957 self._usermaskspectra = None
958 self._offset = None
959 self.set_selection(None, False)
960 self._reset_header()
961
962 def _reset_header(self):
963 self._headtext={'string': None, 'textobj': None}
964
965 def _reset_counter(self):
966 self._startrow = 0
967 self._ipanel = -1
968 self._reset_header()
969 self._panelrows = []
970 if self.casabar_exists():
971 self._plotter.figmgr.casabar.set_pagecounter(1)
972
973 def _plot(self, scan):
974 savesel = scan.get_selection()
975 sel = savesel + self._selection
976 order = self._get_sortstring([self._panelling,self._stacking])
977 if order:
978 sel.set_order(order)
979 scan.set_selection(sel)
980 d = {'b': scan.getbeam, 's': scan.getscan,
981 'i': scan.getif, 'p': scan.getpol, 't': scan.get_time,
982 'r': int}#, '_r': int}
983
984 polmodes = dict(zip(sel.get_pols(), sel.get_poltypes()))
985 # this returns either a tuple of numbers or a length (ncycles)
986 # convert this into lengths
987 n0,nstack0 = self._get_selected_n(scan)
988 if isinstance(n0, int): n = n0
989 else: n = len(n0)
990 if isinstance(nstack0, int): nstack = nstack0
991 else: nstack = len(nstack0)
992 # In case of row stacking
993 rowstack = False
994 titlemode = self._panelling
995 if self._stacking == "r" and self._panelling != "r":
996 rowstack = True
997 titlemode = '_r'
998 nptot = n
999 maxpanel, maxstack = 16,16
1000 if nstack > maxstack:
1001 msg ="Scan to be overlayed contains more than %d selections.\n" \
1002 "Selecting first %d selections..." % (maxstack, maxstack)
1003 asaplog.push(msg)
1004 asaplog.post('WARN')
1005 nstack = min(nstack,maxstack)
1006 #n = min(n-self._ipanel-1,maxpanel)
1007 n = n-self._ipanel-1
1008 # the number of panels in this page
1009 if self._rows and self._cols:
1010 n = min(n,self._rows*self._cols)
1011 else:
1012 n = min(n,maxpanel)
1013
1014 firstpage = (self._ipanel < 0)
1015 #ganged = False
1016 ganged = rcParams['plotter.ganged']
1017 if self._panelling == 'i':
1018 ganged = False
1019 if not firstpage:
1020 # not the first page just clear the axis
1021 nx = self._plotter.cols
1022 ipaxx = n - nx - 1 #the max panel id to supress x-label
1023 for ip in xrange(len(self._plotter.subplots)):
1024 self._plotter.subplot(ip)
1025 self._plotter.clear()
1026 self._plotter.axes.set_visible((ip<n))
1027 if ganged:
1028 self._plotter.axes.xaxis.label.set_visible((ip > ipaxx))
1029 if ip <= ipaxx:
1030 map(lambda x: x.set_visible(False), \
1031 self._plotter.axes.get_xticklabels())
1032 self._plotter.axes.yaxis.label.set_visible((ip % nx)==0)
1033 if ip % nx:
1034 map(lambda y: y.set_visible(False), \
1035 self._plotter.axes.get_yticklabels())
1036 elif (n > 1 and self._rows and self._cols):
1037 self._plotter.set_panels(rows=self._rows,cols=self._cols,
1038 nplots=n,margin=self._margins,
1039 ganged=ganged)
1040 else:
1041 self._plotter.set_panels(rows=n,cols=0,nplots=n,
1042 margin=self._margins,ganged=ganged)
1043 #r = 0
1044 r = self._startrow
1045 nr = scan.nrow()
1046 a0,b0 = -1,-1
1047 allxlim = []
1048 allylim = []
1049 #newpanel=True
1050 newpanel=False
1051 panelcount,stackcount = 0,0
1052 # If this is not the first page
1053 if r > 0:
1054 # panelling value of the prev page
1055 a0 = d[self._panelling](r-1)
1056 # set the initial stackcount large not to plot
1057 # the start row automatically
1058 stackcount = nstack
1059
1060 while r < nr:
1061 a = d[self._panelling](r)
1062 b = d[self._stacking](r)
1063 if a > a0 and panelcount < n:
1064 if n > 1:
1065 self._plotter.subplot(panelcount)
1066 self._plotter.palette(0)
1067 #title
1068 xlab = self._abcissa and self._abcissa[panelcount] \
1069 or scan._getabcissalabel()
1070 if self._offset and not self._abcissa:
1071 xlab += " (relative)"
1072 ylab = self._ordinate and self._ordinate[panelcount] \
1073 or scan._get_ordinate_label()
1074 self._plotter.set_axes('xlabel', xlab)
1075 self._plotter.set_axes('ylabel', ylab)
1076 #lbl = self._get_label(scan, r, self._panelling, self._title)
1077 lbl = self._get_label(scan, r, titlemode, self._title)
1078 if isinstance(lbl, list) or isinstance(lbl, tuple):
1079 if 0 <= panelcount < len(lbl):
1080 lbl = lbl[panelcount]
1081 else:
1082 # get default label
1083 #lbl = self._get_label(scan, r, self._panelling, None)
1084 lbl = self._get_label(scan, r, titlemode, None)
1085 self._plotter.set_axes('title',lbl)
1086 newpanel = True
1087 stackcount = 0
1088 panelcount += 1
1089 # save the start row to plot this panel for future revisit.
1090 if self._panelling != 'r' and \
1091 len(self._panelrows) < self._ipanel+1+panelcount:
1092 self._panelrows += [r]
1093
1094 #if (b > b0 or newpanel) and stackcount < nstack:
1095 if stackcount < nstack and (newpanel or \
1096 rowstack or (a == a0 and b > b0)):
1097 y = []
1098 if len(polmodes):
1099 y = scan._getspectrum(r, polmodes[scan.getpol(r)])
1100 else:
1101 y = scan._getspectrum(r)
1102 # flag application
1103 mr = scan._getflagrow(r)
1104 from numpy import ma, array
1105 if mr:
1106 y = ma.masked_array(y,mask=mr)
1107 else:
1108 m = scan._getmask(r)
1109 from numpy import logical_not, logical_and
1110 if self._maskselection and len(self._usermask) == len(m):
1111 if d[self._stacking](r) in self._maskselection[self._stacking]:
1112 m = logical_and(m, self._usermask)
1113 y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
1114
1115 x = array(scan._getabcissa(r))
1116 if self._offset:
1117 x += self._offset
1118 if self._minmaxx is not None:
1119 s,e = self._slice_indeces(x)
1120 x = x[s:e]
1121 y = y[s:e]
1122 if len(x) > 1024 and rcParams['plotter.decimate']:
1123 fac = len(x)/1024
1124 x = x[::fac]
1125 y = y[::fac]
1126 llbl = self._get_label(scan, r, self._stacking, self._lmap)
1127 if isinstance(llbl, list) or isinstance(llbl, tuple):
1128 if 0 <= stackcount < len(llbl):
1129 # use user label
1130 llbl = llbl[stackcount]
1131 else:
1132 # get default label
1133 llbl = self._get_label(scan, r, self._stacking, None)
1134 self._plotter.set_line(label=llbl)
1135 plotit = self._plotter.plot
1136 if self._hist: plotit = self._plotter.hist
1137 if len(x) > 0 and not mr:
1138 plotit(x,y)
1139 xlim= self._minmaxx or [min(x),max(x)]
1140 allxlim += xlim
1141 ylim= self._minmaxy or [ma.minimum(y),ma.maximum(y)]
1142 allylim += ylim
1143 else:
1144 xlim = self._minmaxx or []
1145 allxlim += xlim
1146 ylim= self._minmaxy or []
1147 allylim += ylim
1148 stackcount += 1
1149 a0=a
1150 b0=b
1151 # last in colour stack -> autoscale x
1152 if stackcount == nstack and len(allxlim) > 0:
1153 allxlim.sort()
1154 self._plotter.subplots[panelcount-1]['axes'].set_xlim([allxlim[0],allxlim[-1]])
1155 if ganged:
1156 allxlim = [allxlim[0],allxlim[-1]]
1157 else:
1158 # clear
1159 allxlim =[]
1160
1161 newpanel = False
1162 #a0=a
1163 #b0=b
1164 # ignore following rows
1165 if (panelcount == n and stackcount == nstack) or (r == nr-1):
1166 # last panel -> autoscale y if ganged
1167 #if rcParams['plotter.ganged'] and len(allylim) > 0:
1168 if ganged and len(allylim) > 0:
1169 allylim.sort()
1170 self._plotter.set_limits(ylim=[allylim[0],allylim[-1]])
1171 break
1172 r+=1 # next row
1173
1174 # save the current counter for multi-page plotting
1175 self._startrow = r+1
1176 self._ipanel += panelcount
1177 if self.casabar_exists():
1178 if self._ipanel >= nptot-1:
1179 self._plotter.figmgr.casabar.disable_next()
1180 else:
1181 self._plotter.figmgr.casabar.enable_next()
1182 if self._ipanel + 1 - panelcount > 0:
1183 self._plotter.figmgr.casabar.enable_prev()
1184 else:
1185 self._plotter.figmgr.casabar.disable_prev()
1186
1187 #reset the selector to the scantable's original
1188 scan.set_selection(savesel)
1189
1190 #temporary switch-off for older matplotlib
1191 #if self._fp is not None:
1192 if self._fp is not None and getattr(self._plotter.figure,'findobj',False):
1193 for o in self._plotter.figure.findobj(Text):
1194 if not self._headtext['textobj'] or \
1195 not (o in self._headtext['textobj']):
1196 o.set_fontproperties(self._fp)
1197
1198 def _get_sortstring(self, lorders):
1199 d0 = {'s': 'SCANNO', 'b': 'BEAMNO', 'i':'IFNO',
1200 'p': 'POLNO', 'c': 'CYCLENO', 't' : 'TIME', 'r':None, '_r':None }
1201 if not (type(lorders) == list) and not (type(lorders) == tuple):
1202 return None
1203 if len(lorders) > 0:
1204 lsorts = []
1205 for order in lorders:
1206 if order == "r":
1207 # don't sort if row panelling/stacking
1208 return None
1209 ssort = d0[order]
1210 if ssort:
1211 lsorts.append(ssort)
1212 return lsorts
1213 return None
1214
1215 def set_selection(self, selection=None, refresh=True, **kw):
1216 """
1217 Parameters:
1218 selection: a selector object (default unset the selection)
1219 refresh: True (default) or False. If True, the plot is
1220 replotted based on the new parameter setting(s).
1221 Otherwise,the parameter(s) are set without replotting.
1222 """
1223 if selection is None:
1224 # reset
1225 if len(kw) == 0:
1226 self._selection = selector()
1227 else:
1228 # try keywords
1229 for k in kw:
1230 if k not in selector.fields:
1231 raise KeyError("Invalid selection key '%s', valid keys are %s" % (k, selector.fields))
1232 self._selection = selector(**kw)
1233 elif isinstance(selection, selector):
1234 self._selection = selection
1235 else:
1236 raise TypeError("'selection' is not of type selector")
1237
1238 order = self._get_sortstring([self._panelling,self._stacking])
1239 if order:
1240 self._selection.set_order(order)
1241 if refresh and self._data:
1242 self.plot()
1243
1244 def _get_selected_n(self, scan):
1245 d1 = {'b': scan.getbeamnos, 's': scan.getscannos,
1246 'i': scan.getifnos, 'p': scan.getpolnos, 't': scan.ncycle,
1247 'r': scan.nrow}#, '_r': False}
1248 d2 = { 'b': self._selection.get_beams(),
1249 's': self._selection.get_scans(),
1250 'i': self._selection.get_ifs(),
1251 'p': self._selection.get_pols(),
1252 't': self._selection.get_cycles(),
1253 'r': False}#, '_r': 1}
1254 n = d2[self._panelling] or d1[self._panelling]()
1255 nstack = d2[self._stacking] or d1[self._stacking]()
1256 # handle row panelling/stacking
1257 if self._panelling == 'r':
1258 nstack = 1
1259 elif self._stacking == 'r':
1260 n = 1
1261 return n,nstack
1262
1263 def _get_label(self, scan, row, mode, userlabel=None):
1264 if isinstance(userlabel, list) and len(userlabel) == 0:
1265 userlabel = " "
1266 pms = dict(zip(self._selection.get_pols(),self._selection.get_poltypes()))
1267 if len(pms):
1268 poleval = scan._getpollabel(scan.getpol(row),pms[scan.getpol(row)])
1269 else:
1270 poleval = scan._getpollabel(scan.getpol(row),scan.poltype())
1271 d = {'b': "Beam "+str(scan.getbeam(row)),
1272 #'s': scan._getsourcename(row),
1273 's': "Scan "+str(scan.getscan(row))+\
1274 " ("+str(scan._getsourcename(row))+")",
1275 'i': "IF"+str(scan.getif(row)),
1276 'p': poleval,
1277 't': str(scan.get_time(row)),
1278 'r': "row "+str(row),
1279 #'_r': str(scan.get_time(row))+",\nIF"+str(scan.getif(row))+", "+poleval+", Beam"+str(scan.getbeam(row)) }
1280 '_r': "" }
1281 return userlabel or d[mode]
1282
1283 def plotazel(self, scan=None, outfile=None):
1284 """
1285 plot azimuth and elevation versus time of a scantable
1286 """
1287 visible = rcParams['plotter.gui']
1288 from matplotlib import pylab as PL
1289 from matplotlib.dates import DateFormatter
1290 from pytz import timezone
1291 from matplotlib.dates import HourLocator, MinuteLocator,SecondLocator, DayLocator
1292 from matplotlib.ticker import MultipleLocator
1293 from numpy import array, pi
1294 if not visible or not self._visible:
1295 PL.ioff()
1296 from matplotlib.backends.backend_agg import FigureCanvasAgg
1297 PL.gcf().canvas.switch_backends(FigureCanvasAgg)
1298 self._data = scan
1299 dates = self._data.get_time(asdatetime=True)
1300 t = PL.date2num(dates)
1301 tz = timezone('UTC')
1302 PL.cla()
1303 PL.ioff()
1304 PL.clf()
1305 # Adjust subplot margins
1306 if not self._margins or len(self._margins) != 6:
1307 self.set_margin(refresh=False)
1308 lef, bot, rig, top, wsp, hsp = self._margins
1309 PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
1310 wspace=wsp,hspace=hsp)
1311
1312 tdel = max(t) - min(t)
1313 ax = PL.subplot(2,1,1)
1314 el = array(self._data.get_elevation())*180./pi
1315 PL.ylabel('El [deg.]')
1316 dstr = dates[0].strftime('%Y/%m/%d')
1317 if tdel > 1.0:
1318 dstr2 = dates[len(dates)-1].strftime('%Y/%m/%d')
1319 dstr = dstr + " - " + dstr2
1320 majloc = DayLocator()
1321 minloc = HourLocator(range(0,23,12))
1322 timefmt = DateFormatter("%b%d")
1323 elif tdel > 24./60.:
1324 timefmt = DateFormatter('%H:%M')
1325 majloc = HourLocator()
1326 minloc = MinuteLocator(30)
1327 else:
1328 timefmt = DateFormatter('%H:%M')
1329 majloc = MinuteLocator(interval=5)
1330 minloc = SecondLocator(30)
1331
1332 PL.title(dstr)
1333 if tdel == 0.0:
1334 th = (t - PL.floor(t))*24.0
1335 PL.plot(th,el,'o',markersize=2, markerfacecolor='b', markeredgecolor='b')
1336 else:
1337 PL.plot_date(t,el,'o', markersize=2, markerfacecolor='b', markeredgecolor='b',tz=tz)
1338 #ax.grid(True)
1339 ax.xaxis.set_major_formatter(timefmt)
1340 ax.xaxis.set_major_locator(majloc)
1341 ax.xaxis.set_minor_locator(minloc)
1342 ax.yaxis.grid(True)
1343 yloc = MultipleLocator(30)
1344 ax.set_ylim(0,90)
1345 ax.yaxis.set_major_locator(yloc)
1346 if tdel > 1.0:
1347 labels = ax.get_xticklabels()
1348 # PL.setp(labels, fontsize=10, rotation=45)
1349 PL.setp(labels, fontsize=10)
1350
1351 # Az plot
1352 az = array(self._data.get_azimuth())*180./pi
1353 if min(az) < 0:
1354 for irow in range(len(az)):
1355 if az[irow] < 0: az[irow] += 360.0
1356
1357 ax2 = PL.subplot(2,1,2)
1358 #PL.xlabel('Time (UT [hour])')
1359 PL.ylabel('Az [deg.]')
1360 if tdel == 0.0:
1361 PL.plot(th,az,'o',markersize=2, markeredgecolor='b',markerfacecolor='b')
1362 else:
1363 PL.plot_date(t,az,'o', markersize=2,markeredgecolor='b',markerfacecolor='b',tz=tz)
1364 ax2.xaxis.set_major_formatter(timefmt)
1365 ax2.xaxis.set_major_locator(majloc)
1366 ax2.xaxis.set_minor_locator(minloc)
1367 #ax2.grid(True)
1368 ax2.set_ylim(0,360)
1369 ax2.yaxis.grid(True)
1370 #hfmt = DateFormatter('%H')
1371 #hloc = HourLocator()
1372 yloc = MultipleLocator(60)
1373 ax2.yaxis.set_major_locator(yloc)
1374 if tdel > 1.0:
1375 labels = ax2.get_xticklabels()
1376 PL.setp(labels, fontsize=10)
1377 PL.xlabel('Time (UT [day])')
1378 else:
1379 PL.xlabel('Time (UT [hour])')
1380
1381 PL.ion()
1382 PL.draw()
1383 if matplotlib.get_backend() == 'Qt4Agg': PL.gcf().show()
1384 if (outfile is not None):
1385 PL.savefig(outfile)
1386
1387
1388 def plotpointing2(self, scan=None, colorby='', showline=False, projection=''):
1389 """
1390 plot telescope pointings
1391 Parameters:
1392 infile : input filename or scantable instance
1393 colorby : change color by either
1394 'type'(source type)|'scan'|'if'|'pol'|'beam'
1395 showline : show dotted line
1396 projection : projection type either
1397 ''(no projection [deg])|'coord'(not implemented)
1398 """
1399 from numpy import array, pi
1400 from asap import scantable
1401 # check for scantable
1402 if isinstance(scan, scantable):
1403 if self._data is not None:
1404 if scan != self._data:
1405 self._data = scan
1406 # reset
1407 self._reset()
1408 else:
1409 self._data = scan
1410 self._reset()
1411 if not self._data:
1412 msg = "Input is not a scantable"
1413 raise TypeError(msg)
1414 # check for color mode
1415 validtypes=['type','scan','if','pol', 'beam']
1416 stype = None
1417 if (colorby in validtypes):
1418 stype = colorby[0]
1419 elif len(colorby) > 0:
1420 msg = "Invalid choice of 'colorby' (choices: %s)" % str(validtypes)
1421 raise ValueError(msg)
1422 self._assert_plotter(action="reload")
1423 self._plotter.hold()
1424 self._reset_counter()
1425 if self.casabar_exists():
1426 self._plotter.figmgr.casabar.disable_button()
1427 # for now, only one plot
1428 self._plotter.set_panels(rows=1,cols=1)
1429 # first panel
1430 self._plotter.subplot(0)
1431 # first color and linestyles
1432 self._plotter.palette(0)
1433 self.gca().set_aspect('equal')
1434 basesel = scan.get_selection()
1435 attrback = self._plotter.get_line()
1436 marker = "o"
1437 if showline:
1438 basesel.set_order(["TIME"])
1439 scan.set_selection(basesel)
1440 if not (stype in ["t", "s"]):
1441 marker += ":"
1442 self._plotter.set_line(markersize=3, markeredgewidth=0)
1443
1444 if not stype:
1445 selIds = [""] # cheating
1446 sellab = "all points"
1447 elif stype == 't':
1448 selIds = range(15)
1449 sellab = "src type "
1450 else:
1451 selIds = getattr(self._data,'get'+colorby+'nos')()
1452 sellab = colorby.upper()
1453 selFunc = "set_"+colorby+"s"
1454 for idx in selIds:
1455 sel = selector() + basesel
1456 if stype:
1457 bid = getattr(basesel,'get_'+colorby+"s")()
1458 if (len(bid) > 0) and (not idx in bid):
1459 # base selection doesn't contain idx
1460 # Note summation of selector is logical sum if
1461 continue
1462 getattr(sel, selFunc)([idx])
1463 if not sel.is_empty():
1464 try:
1465 self._data.set_selection(sel)
1466 except RuntimeError, instance:
1467 if stype == 't' and str(instance).startswith("Selection contains no data."):
1468 continue
1469 else:
1470 self._data.set_selection(basesel)
1471 raise RuntimeError, instance
1472 if self._data.nrow() == 0:
1473 self._data.set_selection(basesel)
1474 continue
1475 print "Plotting direction of %s = %s" % (colorby, str(idx))
1476 # getting data to plot
1477 dir = array(self._data.get_directionval()).transpose()
1478 ra = dir[0]*180./pi
1479 dec = dir[1]*180./pi
1480 # actual plot
1481 self._plotter.set_line(label=(sellab+str(idx)))
1482 self._plotter.plot(ra,dec,marker)
1483
1484 # restore original selection
1485 self._data.set_selection(basesel)
1486 # need to plot scan pattern explicitly
1487 if showline and (stype in ["t", "s"]):
1488 dir = array(self._data.get_directionval()).transpose()
1489 ra = dir[0]*180./pi
1490 dec = dir[1]*180./pi
1491 self._plotter.set_line(label="scan pattern")
1492 self._plotter.plot(ra,dec,":")
1493 # set color for only this line
1494 self._plotter.lines[-1][0].set_color("gray")
1495
1496 xlab = 'RA [deg.]'
1497 ylab = 'Declination [deg.]'
1498 self._plotter.set_axes('xlabel', xlab)
1499 self._plotter.set_axes('ylabel', ylab)
1500 self._plotter.set_axes('title', 'Telescope pointings')
1501 if stype: self._plotter.legend(self._legendloc)
1502 else: self._plotter.legend(None)
1503 # reverse x-axis
1504 xmin, xmax = self.gca().get_xlim()
1505 self._plotter.set_limits(xlim=[xmax,xmin])
1506
1507 self._plotter.release()
1508 self._plotter.show(hardrefresh=False)
1509 # reset line settings
1510 self._plotter.set_line(**attrback)
1511 return
1512
1513 def plotpointing(self, scan=None, outfile=None):
1514 """
1515 plot telescope pointings
1516 """
1517 visible = rcParams['plotter.gui']
1518 from matplotlib import pylab as PL
1519 from numpy import array, pi
1520 if not visible or not self._visible:
1521 PL.ioff()
1522 from matplotlib.backends.backend_agg import FigureCanvasAgg
1523 PL.gcf().canvas.switch_backends(FigureCanvasAgg)
1524 self._data = scan
1525 dir = array(self._data.get_directionval()).transpose()
1526 ra = dir[0]*180./pi
1527 dec = dir[1]*180./pi
1528 PL.cla()
1529 #PL.ioff()
1530 PL.clf()
1531 # Adjust subplot margins
1532 if not self._margins or len(self._margins) != 6:
1533 self.set_margin(refresh=False)
1534 lef, bot, rig, top, wsp, hsp = self._margins
1535 PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
1536 wspace=wsp,hspace=hsp)
1537 ax = PL.gca()
1538 #ax = PL.axes([0.1,0.1,0.8,0.8])
1539 #ax = PL.axes([0.1,0.1,0.8,0.8])
1540 ax.set_aspect('equal')
1541 PL.plot(ra, dec, 'b,')
1542 PL.xlabel('RA [deg.]')
1543 PL.ylabel('Declination [deg.]')
1544 PL.title('Telescope pointings')
1545 [xmin,xmax,ymin,ymax] = PL.axis()
1546 PL.axis([xmax,xmin,ymin,ymax])
1547 PL.ion()
1548 PL.draw()
1549 if matplotlib.get_backend() == 'Qt4Agg': PL.gcf().show()
1550 if (outfile is not None):
1551 PL.savefig(outfile)
1552
1553 # plot total power data
1554 # plotting in time is not yet implemented..
1555 @asaplog_post_dec
1556 def plottp(self, scan=None):
1557 from asap import scantable
1558 if not self._data and not scan:
1559 msg = "Input is not a scantable"
1560 raise TypeError(msg)
1561 if isinstance(scan, scantable):
1562 if self._data is not None:
1563 if scan != self._data:
1564 self._data = scan
1565 # reset
1566 self._reset()
1567 else:
1568 self._data = scan
1569 self._reset()
1570 # ranges become invalid when abcissa changes?
1571 #if self._abcunit and self._abcunit != self._data.get_unit():
1572 # self._minmaxx = None
1573 # self._minmaxy = None
1574 # self._abcunit = self._data.get_unit()
1575 # self._datamask = None
1576
1577 self._assert_plotter(action="reload")
1578 self._plotter.hold()
1579 self._plotter.clear()
1580 # Adjust subplot margins
1581 if not self._margins or len(self._margins) !=6:
1582 self.set_margin(refresh=False)
1583 lef, bot, rig, top, wsp, hsp = self._margins
1584 self._plotter.figure.subplots_adjust(
1585 left=lef,bottom=bot,right=rig,top=top,wspace=wsp,hspace=hsp)
1586 if self.casabar_exists(): self._plotter.figmgr.casabar.disable_button()
1587 self._plottp(self._data)
1588 if self._minmaxy is not None:
1589 self._plotter.set_limits(ylim=self._minmaxy)
1590 self._plotter.release()
1591 self._plotter.tidy()
1592 self._plotter.show(hardrefresh=False)
1593 return
1594
1595 def _plottp(self,scan):
1596 """
1597 private method for plotting total power data
1598 """
1599 from numpy import ma, array, arange, logical_not
1600 r=0
1601 nr = scan.nrow()
1602 a0,b0 = -1,-1
1603 allxlim = []
1604 allylim = []
1605 y=[]
1606 self._plotter.set_panels()
1607 self._plotter.palette(0)
1608 #title
1609 #xlab = self._abcissa and self._abcissa[panelcount] \
1610 # or scan._getabcissalabel()
1611 #ylab = self._ordinate and self._ordinate[panelcount] \
1612 # or scan._get_ordinate_label()
1613 xlab = self._abcissa or 'row number' #or Time
1614 ylab = self._ordinate or scan._get_ordinate_label()
1615 self._plotter.set_axes('xlabel',xlab)
1616 self._plotter.set_axes('ylabel',ylab)
1617 lbl = self._get_label(scan, r, 's', self._title)
1618 if isinstance(lbl, list) or isinstance(lbl, tuple):
1619 # if 0 <= panelcount < len(lbl):
1620 # lbl = lbl[panelcount]
1621 # else:
1622 # get default label
1623 lbl = self._get_label(scan, r, self._panelling, None)
1624 self._plotter.set_axes('title',lbl)
1625 y=array(scan._get_column(scan._getspectrum,-1))
1626 m = array(scan._get_column(scan._getmask,-1))
1627 y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
1628 x = arange(len(y))
1629 # try to handle spectral data somewhat...
1630 l,m = y.shape
1631 if m > 1:
1632 y=y.mean(axis=1)
1633 plotit = self._plotter.plot
1634 llbl = self._get_label(scan, r, self._stacking, None)
1635 self._plotter.set_line(label=llbl)
1636 if len(x) > 0:
1637 plotit(x,y)
1638
1639
1640 # forwards to matplotlib.Figure.text
1641 def figtext(self, *args, **kwargs):
1642 """
1643 Add text to figure at location x,y (relative 0-1 coords).
1644 This method forwards *args and **kwargs to a Matplotlib method,
1645 matplotlib.Figure.text.
1646 See the method help for detailed information.
1647 """
1648 self._assert_plotter(action="reload")
1649 self._plotter.text(*args, **kwargs)
1650 # end matplotlib.Figure.text forwarding function
1651
1652
1653 # printing header information
1654 @asaplog_post_dec
1655 def print_header(self, plot=True, fontsize=9, logger=False, selstr='', extrastr=''):
1656 """
1657 print data (scantable) header on the plot and/or logger.
1658 To plot the header on the plot, this method should be called after
1659 plotting spectra by the method, asapplotter.plot.
1660 Parameters:
1661 plot: whether or not print header info on the plot.
1662 fontsize: header font size (valid only plot=True)
1663 logger: whether or not print header info on the logger.
1664 selstr: additional selection string (not verified)
1665 extrastr: additional string to print at the beginning (not verified)
1666 """
1667 if not plot and not logger:
1668 return
1669 if not self._data:
1670 raise RuntimeError("No scantable has been set yet.")
1671 # Now header will be printed on plot and/or logger.
1672 # Get header information and format it.
1673 ssum=self._data._list_header()
1674 # Print Observation header to the upper-left corner of plot
1675 headstr=[ssum[0:ssum.find('Obs. Type:')]]
1676 headstr.append(ssum[ssum.find('Obs. Type:'):ssum.find('Flux Unit:')])
1677 if extrastr != '':
1678 headstr[0]=extrastr+'\n'+headstr[0]
1679 self._headtext['extrastr'] = extrastr
1680 if selstr != '':
1681 selstr += '\n'
1682 self._headtext['selstr'] = selstr
1683 ssel=(selstr+self._data.get_selection().__str__()+self._selection.__str__() or 'none')
1684 headstr.append('***Selections***\n'+ssel)
1685
1686 if plot:
1687 errmsg = "Can plot header only after the first call to plot()."
1688 self._assert_plotter(action="halt",errmsg=errmsg)
1689 self._plotter.hold()
1690 self._header_plot(headstr,fontsize=fontsize)
1691 #import time
1692 #self._plotter.figure.text(0.99,0.01,
1693 # time.strftime("%a %d %b %Y %H:%M:%S %Z"),
1694 # horizontalalignment='right',
1695 # verticalalignment='bottom',fontsize=8)
1696 self._plotter.release()
1697 if logger:
1698 selstr = "Selections: "+ssel
1699 asaplog.push("----------------\n Plot Summary\n----------------")
1700 asaplog.push(extrastr)
1701 asaplog.push(ssum[0:ssum.find('Selection:')]\
1702 + selstr)
1703 self._headtext['string'] = headstr
1704 del ssel, ssum, headstr
1705
1706 def _header_plot(self, texts, fontsize=9):
1707 self._headtext['textobj']=[]
1708 nstcol=len(texts)
1709 for i in range(nstcol):
1710 self._headtext['textobj'].append(
1711 self._plotter.figure.text(0.03+float(i)/nstcol,0.98,
1712 texts[i],
1713 horizontalalignment='left',
1714 verticalalignment='top',
1715 fontsize=fontsize))
1716
1717 def clear_header(self):
1718 if not self._headtext['textobj']:
1719 asaplog.push("No header has been plotted. Exit without any operation")
1720 asaplog.post("WARN")
1721 elif self._assert_plotter(action="status"):
1722 self._plotter.hold()
1723 for textobj in self._headtext['textobj']:
1724 #if textobj.get_text() in self._headstring:
1725 try:
1726 textobj.remove()
1727 except NotImplementedError:
1728 self._plotter.figure.texts.pop(self._plotter.figure.texts.index(textobj))
1729 self._plotter.release()
1730 self._reset_header()
1731
1732 # plot spectra by pointing
1733 @asaplog_post_dec
1734 def plotgrid(self, scan=None,center=None,spacing=None,rows=None,cols=None):
1735 """
1736 Plot spectra based on direction.
1737
1738 Parameters:
1739 scan: a scantable to plot
1740 center: the grid center direction (a list) of plots in the
1741 unit of DIRECTION column.
1742 (default) the center of map region
1743 spacing: a list of horizontal (R.A.) and vertical (Dec.)
1744 spacing in the unit of DIRECTION column.
1745 (default) Calculated by the extent of map region and
1746 the number of rows and cols to cover
1747 rows: number of panels (grid points) in horizontal direction
1748 cols: number of panels (grid points) in vertical direction
1749
1750 Note:
1751 - Only the first IFNO, POLNO, and BEAM in the scantable will be
1752 plotted.
1753 - This method doesn't re-grid and average spectra in scantable. Use
1754 asapgrid module to re-grid spectra before plotting with this method.
1755 Only the first spectrum is plotted in case there are multiple
1756 spectra which belong to a grid.
1757 """
1758 from asap import scantable
1759 from numpy import array, ma, cos
1760 if not self._data and not scan:
1761 msg = "No scantable is specified to plot"
1762 raise TypeError(msg)
1763 if scan:
1764 self.set_data(scan, refresh=False)
1765 del scan
1766
1767 # Rows and cols
1768 if rows:
1769 self._rows = int(rows)
1770 else:
1771 msg = "Number of rows to plot are not specified. "
1772 if self._rows:
1773 msg += "Using previous value = %d" % (self._rows)
1774 asaplog.push(msg)
1775 else:
1776 self._rows = 1
1777 msg += "Setting rows = %d" % (self._rows)
1778 asaplog.post()
1779 asaplog.push(msg)
1780 asaplog.post("WARN")
1781 if cols:
1782 self._cols = int(cols)
1783 else:
1784 msg = "Number of cols to plot are not specified. "
1785 if self._cols:
1786 msg += "Using previous value = %d" % (self._cols)
1787 asaplog.push(msg)
1788 else:
1789 self._cols = 1
1790 msg += "Setting cols = %d" % (self._cols)
1791 asaplog.post()
1792 asaplog.push(msg)
1793 asaplog.post("WARN")
1794
1795 # Center and spacing
1796 dirarr = array(self._data.get_directionval()).transpose()
1797 print "Pointing range: (x, y) = (%f - %f, %f - %f)" %\
1798 (dirarr[0].min(),dirarr[0].max(),dirarr[1].min(),dirarr[1].max())
1799 dircent = [0.5*(dirarr[0].max() + dirarr[0].min()),
1800 0.5*(dirarr[1].max() + dirarr[1].min())]
1801 del dirarr
1802 if center is None:
1803 #asaplog.post()
1804 asaplog.push("Grid center is not specified. Automatically calculated from pointing center.")
1805 #asaplog.post("WARN")
1806 #center = [dirarr[0].mean(), dirarr[1].mean()]
1807 center = dircent
1808 elif (type(center) in (list, tuple)) and len(center) > 1:
1809 from numpy import pi
1810 # make sure center_x is in +-pi of pointing center
1811 # (assumes dirs are in rad)
1812 rotnum = round(abs(center[0] - dircent[0])/(2*pi))
1813 if center[0] < dircent[0]: rotnum *= -1
1814 cenx = center[0] - rotnum*2*pi
1815 center = [cenx, center[1]]
1816 else:
1817 msg = "Direction of grid center should be a list of float (R.A., Dec.)"
1818 raise ValueError, msg
1819 asaplog.push("Grid center: (%f, %f) " % (center[0],center[1]))
1820
1821 if spacing is None:
1822 #asaplog.post()
1823 asaplog.push("Grid spacing not specified. Automatically calculated from map coverage")
1824 #asaplog.post("WARN")
1825 # automatically get spacing
1826 dirarr = array(self._data.get_directionval()).transpose()
1827 wx = 2. * max(abs(dirarr[0].max()-center[0]),
1828 abs(dirarr[0].min()-center[0]))
1829 wy = 2. * max(abs(dirarr[1].max()-center[1]),
1830 abs(dirarr[1].min()-center[1]))
1831 ## slightly expand area to plot the edges
1832 #wx *= 1.1
1833 #wy *= 1.1
1834 xgrid = wx/max(self._cols-1.,1.)
1835 #xgrid = wx/float(max(self._cols,1.))
1836 xgrid *= cos(center[1])
1837 ygrid = wy/max(self._rows-1.,1.)
1838 #ygrid = wy/float(max(self._rows,1.))
1839 # single pointing (identical R.A. and/or Dec. for all spectra.)
1840 if xgrid == 0:
1841 xgrid = 1.
1842 if ygrid == 0:
1843 ygrid = 1.
1844 # spacing should be negative to transpose plot
1845 spacing = [- xgrid, - ygrid]
1846 del dirarr, xgrid, ygrid
1847 #elif isinstance(spacing, str):
1848 # # spacing is a quantity
1849 elif (type(spacing) in (list, tuple)) and len(spacing) > 1:
1850 for i in xrange(2):
1851 val = spacing[i]
1852 if not isinstance(val, float):
1853 raise TypeError("spacing should be a list of float")
1854 if val > 0.:
1855 spacing[i] = -val
1856 spacing = spacing[0:2]
1857 else:
1858 msg = "Invalid spacing."
1859 raise TypeError(msg)
1860 asaplog.push("Spacing: (%f, %f) (projected)" % (spacing[0],spacing[1]))
1861
1862 ntotpl = self._rows * self._cols
1863 ifs = self._data.getifnos()
1864 if len(ifs) > 1:
1865 msg = "Found multiple IFs in scantable. Only the first IF (IFNO=%d) will be plotted." % ifs[0]
1866 asaplog.post()
1867 asaplog.push(msg)
1868 asaplog.post("WARN")
1869 pols = self._data.getpolnos()
1870 if len(pols) > 1:
1871 msg = "Found multiple POLs in scantable. Only the first POL (POLNO=%d) will be plotted." % pols[0]
1872 asaplog.post()
1873 asaplog.push(msg)
1874 asaplog.post("WARN")
1875 beams = self._data.getbeamnos()
1876 if len(beams) > 1:
1877 msg = "Found multiple BEAMs in scantable. Only the first BEAM (BEAMNO=%d) will be plotted." % beams[0]
1878 asaplog.post()
1879 asaplog.push(msg)
1880 asaplog.post("WARN")
1881 self._data.set_selection(ifs=[ifs[0]],pols=[pols[0]],beams=[beams[0]])
1882 if self._data.nrow() > ntotpl:
1883 msg = "Scantable is finely sampled than plotting grids. "\
1884 + "Only the first spectrum is plotted in each grid."
1885 asaplog.post()
1886 asaplog.push(msg)
1887 asaplog.post("WARN")
1888
1889 self._assert_plotter(action="reload")
1890 self._plotter.hold()
1891 self._reset_counter()
1892 self._plotter.legend()
1893
1894 # Adjust subplot margins
1895 if not self._margins or len(self._margins) !=6:
1896 self.set_margin(refresh=False)
1897 self._plotter.set_panels(rows=self._rows,cols=self._cols,
1898 nplots=ntotpl,margin=self._margins,ganged=True)
1899 if self.casabar_exists():
1900 self._plotter.figmgr.casabar.enable_button()
1901 # Plot helper
1902 from asap._asap import plothelper as plhelper
1903 ph = plhelper(self._data)
1904 ph.set_gridval(self._cols, self._rows, spacing[0], spacing[1],
1905 center[0], center[1], epoch="J2000", projname="SIN")
1906 # Actual plot
1907 npl = 0
1908 for irow in range(self._data.nrow()):
1909 (ix, iy) = ph.get_gpos(irow)
1910 #print("asapplotter.plotgrid: (ix, iy) = (%f, %f)" % (ix, iy))
1911 if ix < 0 or ix >= self._cols:
1912 #print "Row %d : Out of X-range (x = %f) ... skipped" % (irow, pos[0])
1913 continue
1914 ix = int(ix)
1915 if iy < 0 or iy >= self._rows:
1916 #print "Row %d : Out of Y-range (y = %f) ... skipped" % (irow,pos[1])
1917 continue
1918 iy = int(iy)
1919 ipanel = ix + iy*self._rows
1920 #print("Resolved panel Id (%d, %d): %d" % (ix, iy, ipanel))
1921 if len(self._plotter.subplots[ipanel]['lines']) > 0:
1922 #print "Row %d : panel %d lready plotted ... skipped" % (irow,ipanel)
1923 # a spectrum already plotted in the panel
1924 continue
1925 # Plotting this row
1926 #print "PLOTTING row %d (panel=%d)" % (irow, ipanel)
1927 npl += 1
1928 self._plotter.subplot(ipanel)
1929 self._plotter.palette(0,colormap=self._colormap, \
1930 linestyle=0,linestyles=self._linestyles)
1931 xlab = self._abcissa and self._abcissa[ipanel] \
1932 or self._data._getabcissalabel(irow)
1933 if self._offset and not self._abcissa:
1934 xlab += " (relative)"
1935 ylab = self._ordinate and self._ordinate[ipanel] \
1936 or self._data._get_ordinate_label()
1937 self._plotter.set_axes('xlabel', xlab)
1938 self._plotter.set_axes('ylabel', ylab)
1939 lbl = self._data.get_direction(irow)
1940 self._plotter.set_axes('title',lbl)
1941
1942 y = self._data._getspectrum(irow)
1943 # flag application
1944 mr = self._data._getflagrow(irow)
1945 if mr: # FLAGROW=True
1946 y = ma.masked_array(y,mask=mr)
1947 else:
1948 m = self._data._getmask(irow)
1949 from numpy import logical_not, logical_and
1950 ### user mask is not available so far
1951 #if self._maskselection and len(self._usermask) == len(m):
1952 # if d[self._stacking](irow) in self._maskselection[self._stacking]:
1953 # m = logical_and(m, self._usermask)
1954 y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
1955
1956 x = array(self._data._getabcissa(irow))
1957 if self._offset:
1958 x += self._offset
1959 if self._minmaxx is not None:
1960 s,e = self._slice_indeces(x)
1961 x = x[s:e]
1962 y = y[s:e]
1963 if len(x) > 1024 and rcParams['plotter.decimate']:
1964 fac = len(x)/1024
1965 x = x[::fac]
1966 y = y[::fac]
1967 self._plotter.set_line(label=lbl)
1968 plotit = self._plotter.plot
1969 if self._hist: plotit = self._plotter.hist
1970 if len(x) > 0 and not mr:
1971 plotit(x,y)
1972# xlim= self._minmaxx or [min(x),max(x)]
1973# allxlim += xlim
1974# ylim= self._minmaxy or [ma.minimum(y),ma.maximum(y)]
1975# allylim += ylim
1976# else:
1977# xlim = self._minmaxx or []
1978# allxlim += xlim
1979# ylim= self._minmaxy or []
1980# allylim += ylim
1981
1982 if npl >= ntotpl:
1983 break
1984
1985 if self._minmaxy is not None:
1986 self._plotter.set_limits(ylim=self._minmaxy)
1987 self._plotter.release()
1988 self._plotter.tidy()
1989 self._plotter.show(hardrefresh=False)
1990 return
Note: See TracBrowser for help on using the repository browser.