source: trunk/python/asapplotter.py@ 2714

Last change on this file since 2714 was 2714, checked in by Kana Sugimoto, 13 years ago

New Development: No

JIRA Issue: No (a minor fix)

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs: unit tests of sdplot

Put in Release Notes: No

Module(s): asapplotter and sdplot

Description: more resetting when new scantable is set to plot.


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