source: trunk/python/asapplotter.py@ 2708

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

New Development: No (a bug fix)

JIRA Issue: No

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs:

invoke asapplotter.plotazel (sdplot with plottype="azel") and
asapplotter.plotpointing (sdplot with plottype="pointing")
before invoking asapplotter.plot (sdplot with plottype="spectra") or
asapplotter.plottp (sdplot with plottype="totalpower") after loading
casapy/asap.

Put in Release Notes: No

Module(s): asapplotter and sdplot

Description:

Fixed a bug which caused azel and pointing plot fail when the plot
commands are invoked before running spectral or totalpower plot at
least once after loading casapy/asap.


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