| 1 | from asap.parameters import rcParams
 | 
|---|
| 2 | from asap.selector import selector
 | 
|---|
| 3 | from asap.scantable import scantable
 | 
|---|
| 4 | from asap.logging import asaplog, asaplog_post_dec
 | 
|---|
| 5 | import matplotlib.axes
 | 
|---|
| 6 | from matplotlib.font_manager import FontProperties
 | 
|---|
| 7 | from matplotlib.text import Text
 | 
|---|
| 8 | from matplotlib import _pylab_helpers
 | 
|---|
| 9 | 
 | 
|---|
| 10 | import re
 | 
|---|
| 11 | 
 | 
|---|
| 12 | def 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 | 
 | 
|---|
| 32 | class 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 |         # new layout is set. need to reset counters for multi page plotting
 | 
|---|
| 520 |         self._reset_counters()
 | 
|---|
| 521 |         if refresh and self._data: self.plot(self._data)
 | 
|---|
| 522 |         return
 | 
|---|
| 523 | 
 | 
|---|
| 524 |     def set_range(self,xstart=None,xend=None,ystart=None,yend=None,refresh=True, offset=None):
 | 
|---|
| 525 |         """
 | 
|---|
| 526 |         Set the range of interest on the abcissa of the plot
 | 
|---|
| 527 |         Parameters:
 | 
|---|
| 528 |             [x,y]start,[x,y]end:  The start and end points of the 'zoom' window
 | 
|---|
| 529 |             refresh:  True (default) or False. If True, the plot is
 | 
|---|
| 530 |                       replotted based on the new parameter setting(s).
 | 
|---|
| 531 |                       Otherwise,the parameter(s) are set without replotting.
 | 
|---|
| 532 |             offset:   shift the abcissa by the given amount. The abcissa label will
 | 
|---|
| 533 |                       have '(relative)' appended to it.
 | 
|---|
| 534 |         Note:
 | 
|---|
| 535 |             These become non-sensical when the unit changes.
 | 
|---|
| 536 |             use plotter.set_range() without parameters to reset
 | 
|---|
| 537 | 
 | 
|---|
| 538 |         """
 | 
|---|
| 539 |         self._offset = offset
 | 
|---|
| 540 |         if xstart is None and xend is None:
 | 
|---|
| 541 |             self._minmaxx = None
 | 
|---|
| 542 |         else:
 | 
|---|
| 543 |             self._minmaxx = [xstart,xend]
 | 
|---|
| 544 |         if ystart is None and yend is None:
 | 
|---|
| 545 |             self._minmaxy = None
 | 
|---|
| 546 |         else:
 | 
|---|
| 547 |             self._minmaxy = [ystart,yend]
 | 
|---|
| 548 |         if refresh and self._data: self.plot(self._data)
 | 
|---|
| 549 |         return
 | 
|---|
| 550 | 
 | 
|---|
| 551 |     def set_legend(self, mp=None, fontsize = None, mode = 0, refresh=True):
 | 
|---|
| 552 |         """
 | 
|---|
| 553 |         Specify a mapping for the legend instead of using the default
 | 
|---|
| 554 |         indices:
 | 
|---|
| 555 |         Parameters:
 | 
|---|
| 556 |             mp:        a list of 'strings'. This should have the same length
 | 
|---|
| 557 |                        as the number of elements on the legend and then maps
 | 
|---|
| 558 |                        to the indeces in order. It is possible to uses latex
 | 
|---|
| 559 |                        math expression. These have to be enclosed in r'',
 | 
|---|
| 560 |                        e.g. r'$x^{2}$'
 | 
|---|
| 561 |             fontsize:  The font size of the label (default None)
 | 
|---|
| 562 |             mode:      where to display the legend
 | 
|---|
| 563 |                        Any other value for loc else disables the legend:
 | 
|---|
| 564 |                         0: auto
 | 
|---|
| 565 |                         1: upper right
 | 
|---|
| 566 |                         2: upper left
 | 
|---|
| 567 |                         3: lower left
 | 
|---|
| 568 |                         4: lower right
 | 
|---|
| 569 |                         5: right
 | 
|---|
| 570 |                         6: center left
 | 
|---|
| 571 |                         7: center right
 | 
|---|
| 572 |                         8: lower center
 | 
|---|
| 573 |                         9: upper center
 | 
|---|
| 574 |                         10: center
 | 
|---|
| 575 |             refresh:    True (default) or False. If True, the plot is
 | 
|---|
| 576 |                         replotted based on the new parameter setting(s).
 | 
|---|
| 577 |                         Otherwise,the parameter(s) are set without replotting.
 | 
|---|
| 578 | 
 | 
|---|
| 579 |         Example:
 | 
|---|
| 580 |              If the data has two IFs/rest frequencies with index 0 and 1
 | 
|---|
| 581 |              for CO and SiO:
 | 
|---|
| 582 |              plotter.set_stacking('i')
 | 
|---|
| 583 |              plotter.set_legend(['CO','SiO'])
 | 
|---|
| 584 |              plotter.plot()
 | 
|---|
| 585 |              plotter.set_legend([r'$^{12}CO$', r'SiO'])
 | 
|---|
| 586 |         """
 | 
|---|
| 587 |         self._lmap = mp
 | 
|---|
| 588 |         #self._plotter.legend(mode)
 | 
|---|
| 589 |         self._legendloc = mode
 | 
|---|
| 590 |         if isinstance(fontsize, int):
 | 
|---|
| 591 |             from matplotlib import rc as rcp
 | 
|---|
| 592 |             rcp('legend', fontsize=fontsize)
 | 
|---|
| 593 |         if refresh and self._data: self.plot(self._data)
 | 
|---|
| 594 |         return
 | 
|---|
| 595 | 
 | 
|---|
| 596 |     def set_title(self, title=None, fontsize=None, refresh=True):
 | 
|---|
| 597 |         """
 | 
|---|
| 598 |         Set the title of sub-plots. If multiple sub-plots are plotted,
 | 
|---|
| 599 |         multiple titles have to be specified.
 | 
|---|
| 600 |         Parameters:
 | 
|---|
| 601 |             title:      a list of titles of sub-plots.
 | 
|---|
| 602 |             fontsize:   a font size of titles (integer)
 | 
|---|
| 603 |             refresh:    True (default) or False. If True, the plot is
 | 
|---|
| 604 |                         replotted based on the new parameter setting(s).
 | 
|---|
| 605 |                         Otherwise,the parameter(s) are set without replotting.
 | 
|---|
| 606 |         Example:
 | 
|---|
| 607 |              # two panels are visible on the plotter
 | 
|---|
| 608 |              plotter.set_title(['First Panel','Second Panel'])
 | 
|---|
| 609 |         """
 | 
|---|
| 610 |         self._title = title
 | 
|---|
| 611 |         if isinstance(fontsize, int):
 | 
|---|
| 612 |             from matplotlib import rc as rcp
 | 
|---|
| 613 |             rcp('axes', titlesize=fontsize)
 | 
|---|
| 614 |         if refresh and self._data: self.plot(self._data)
 | 
|---|
| 615 |         return
 | 
|---|
| 616 | 
 | 
|---|
| 617 |     def set_ordinate(self, ordinate=None, fontsize=None, refresh=True):
 | 
|---|
| 618 |         """
 | 
|---|
| 619 |         Set the y-axis label of the plot. If multiple panels are plotted,
 | 
|---|
| 620 |         multiple labels have to be specified.
 | 
|---|
| 621 |         Parameters:
 | 
|---|
| 622 |             ordinate:    a list of ordinate labels. None (default) let
 | 
|---|
| 623 |                          data determine the labels
 | 
|---|
| 624 |             fontsize:    a font size of vertical axis labels (integer)
 | 
|---|
| 625 |             refresh:     True (default) or False. If True, the plot is
 | 
|---|
| 626 |                          replotted based on the new parameter setting(s).
 | 
|---|
| 627 |                          Otherwise,the parameter(s) are set without replotting.
 | 
|---|
| 628 |         Example:
 | 
|---|
| 629 |              # two panels are visible on the plotter
 | 
|---|
| 630 |              plotter.set_ordinate(['First Y-Axis','Second Y-Axis'])
 | 
|---|
| 631 |         """
 | 
|---|
| 632 |         self._ordinate = ordinate
 | 
|---|
| 633 |         if isinstance(fontsize, int):
 | 
|---|
| 634 |             from matplotlib import rc as rcp
 | 
|---|
| 635 |             rcp('axes', labelsize=fontsize)
 | 
|---|
| 636 |             rcp('ytick', labelsize=fontsize)
 | 
|---|
| 637 |         if refresh and self._data: self.plot(self._data)
 | 
|---|
| 638 |         return
 | 
|---|
| 639 | 
 | 
|---|
| 640 |     def set_abcissa(self, abcissa=None, fontsize=None, refresh=True):
 | 
|---|
| 641 |         """
 | 
|---|
| 642 |         Set the x-axis label of the plot. If multiple panels are plotted,
 | 
|---|
| 643 |         multiple labels have to be specified.
 | 
|---|
| 644 |         Parameters:
 | 
|---|
| 645 |             abcissa:     a list of abcissa labels. None (default) let
 | 
|---|
| 646 |                          data determine the labels
 | 
|---|
| 647 |             fontsize:    a font size of horizontal axis labels (integer)
 | 
|---|
| 648 |             refresh:     True (default) or False. If True, the plot is
 | 
|---|
| 649 |                          replotted based on the new parameter setting(s).
 | 
|---|
| 650 |                          Otherwise,the parameter(s) are set without replotting.
 | 
|---|
| 651 |         Example:
 | 
|---|
| 652 |              # two panels are visible on the plotter
 | 
|---|
| 653 |              plotter.set_ordinate(['First X-Axis','Second X-Axis'])
 | 
|---|
| 654 |         """
 | 
|---|
| 655 |         self._abcissa = abcissa
 | 
|---|
| 656 |         if isinstance(fontsize, int):
 | 
|---|
| 657 |             from matplotlib import rc as rcp
 | 
|---|
| 658 |             rcp('axes', labelsize=fontsize)
 | 
|---|
| 659 |             rcp('xtick', labelsize=fontsize)
 | 
|---|
| 660 |         if refresh and self._data: self.plot(self._data)
 | 
|---|
| 661 |         return
 | 
|---|
| 662 | 
 | 
|---|
| 663 |     def set_histogram(self, hist=True, linewidth=None, refresh=True):
 | 
|---|
| 664 |         """
 | 
|---|
| 665 |         Enable/Disable histogram-like plotting.
 | 
|---|
| 666 |         Parameters:
 | 
|---|
| 667 |             hist:        True (default) or False. The fisrt default
 | 
|---|
| 668 |                          is taken from the .asaprc setting
 | 
|---|
| 669 |                          plotter.histogram
 | 
|---|
| 670 |             linewidth:   a line width
 | 
|---|
| 671 |             refresh:     True (default) or False. If True, the plot is
 | 
|---|
| 672 |                          replotted based on the new parameter setting(s).
 | 
|---|
| 673 |                          Otherwise,the parameter(s) are set without replotting.
 | 
|---|
| 674 |         """
 | 
|---|
| 675 |         self._hist = hist
 | 
|---|
| 676 |         if isinstance(linewidth, float) or isinstance(linewidth, int):
 | 
|---|
| 677 |             from matplotlib import rc as rcp
 | 
|---|
| 678 |             rcp('lines', linewidth=linewidth)
 | 
|---|
| 679 |         if refresh and self._data: self.plot(self._data)
 | 
|---|
| 680 | 
 | 
|---|
| 681 |     def set_colors(self, colmap, refresh=True):
 | 
|---|
| 682 |         """
 | 
|---|
| 683 |         Set the colours to be used. The plotter will cycle through
 | 
|---|
| 684 |         these colours when lines are overlaid (stacking mode).
 | 
|---|
| 685 |         Parameters:
 | 
|---|
| 686 |             colmap:     a list of colour names
 | 
|---|
| 687 |             refresh:    True (default) or False. If True, the plot is
 | 
|---|
| 688 |                         replotted based on the new parameter setting(s).
 | 
|---|
| 689 |                         Otherwise,the parameter(s) are set without replotting.
 | 
|---|
| 690 |         Example:
 | 
|---|
| 691 |              plotter.set_colors('red green blue')
 | 
|---|
| 692 |              # If for example four lines are overlaid e.g I Q U V
 | 
|---|
| 693 |              # 'I' will be 'red', 'Q' will be 'green', U will be 'blue'
 | 
|---|
| 694 |              # and 'V' will be 'red' again.
 | 
|---|
| 695 |         """
 | 
|---|
| 696 |         #if isinstance(colmap,str):
 | 
|---|
| 697 |         #    colmap = colmap.split()
 | 
|---|
| 698 |         #self._plotter.palette(0, colormap=colmap)
 | 
|---|
| 699 |         self._colormap = colmap
 | 
|---|
| 700 |         if refresh and self._data: self.plot(self._data)
 | 
|---|
| 701 | 
 | 
|---|
| 702 |     # alias for english speakers
 | 
|---|
| 703 |     set_colours = set_colors
 | 
|---|
| 704 | 
 | 
|---|
| 705 |     def set_linestyles(self, linestyles=None, linewidth=None, refresh=True):
 | 
|---|
| 706 |         """
 | 
|---|
| 707 |         Set the linestyles to be used. The plotter will cycle through
 | 
|---|
| 708 |         these linestyles when lines are overlaid (stacking mode) AND
 | 
|---|
| 709 |         only one color has been set.
 | 
|---|
| 710 |         Parameters:
 | 
|---|
| 711 |             linestyles:      a list of linestyles to use.
 | 
|---|
| 712 |                              'line', 'dashed', 'dotted', 'dashdot',
 | 
|---|
| 713 |                              'dashdotdot' and 'dashdashdot' are
 | 
|---|
| 714 |                              possible
 | 
|---|
| 715 |             linewidth:       a line width
 | 
|---|
| 716 |             refresh:         True (default) or False. If True, the plot is
 | 
|---|
| 717 |                              replotted based on the new parameter setting(s).
 | 
|---|
| 718 |                              Otherwise,the parameter(s) are set without replotting.
 | 
|---|
| 719 |         Example:
 | 
|---|
| 720 |              plotter.set_colors('black')
 | 
|---|
| 721 |              plotter.set_linestyles('line dashed dotted dashdot')
 | 
|---|
| 722 |              # If for example four lines are overlaid e.g I Q U V
 | 
|---|
| 723 |              # 'I' will be 'solid', 'Q' will be 'dashed',
 | 
|---|
| 724 |              # U will be 'dotted' and 'V' will be 'dashdot'.
 | 
|---|
| 725 |         """
 | 
|---|
| 726 |         #if isinstance(linestyles,str):
 | 
|---|
| 727 |         #    linestyles = linestyles.split()
 | 
|---|
| 728 |         #self._plotter.palette(color=0,linestyle=0,linestyles=linestyles)
 | 
|---|
| 729 |         self._linestyles = linestyles
 | 
|---|
| 730 |         if isinstance(linewidth, float) or isinstance(linewidth, int):
 | 
|---|
| 731 |             from matplotlib import rc as rcp
 | 
|---|
| 732 |             rcp('lines', linewidth=linewidth)
 | 
|---|
| 733 |         if refresh and self._data: self.plot(self._data)
 | 
|---|
| 734 | 
 | 
|---|
| 735 |     def set_font(self, refresh=True,**kwargs):
 | 
|---|
| 736 |         """
 | 
|---|
| 737 |         Set font properties.
 | 
|---|
| 738 |         Parameters:
 | 
|---|
| 739 |             family:    one of 'sans-serif', 'serif', 'cursive', 'fantasy', 'monospace'
 | 
|---|
| 740 |             style:     one of 'normal' (or 'roman'), 'italic'  or 'oblique'
 | 
|---|
| 741 |             weight:    one of 'normal or 'bold'
 | 
|---|
| 742 |             size:      the 'general' font size, individual elements can be adjusted
 | 
|---|
| 743 |                        seperately
 | 
|---|
| 744 |             refresh:   True (default) or False. If True, the plot is
 | 
|---|
| 745 |                        replotted based on the new parameter setting(s).
 | 
|---|
| 746 |                        Otherwise,the parameter(s) are set without replotting.
 | 
|---|
| 747 |         """
 | 
|---|
| 748 |         from matplotlib import rc as rcp
 | 
|---|
| 749 |         fdict = {}
 | 
|---|
| 750 |         for k,v in kwargs.iteritems():
 | 
|---|
| 751 |             if v:
 | 
|---|
| 752 |                 fdict[k] = v
 | 
|---|
| 753 |         self._fp = FontProperties(**fdict)
 | 
|---|
| 754 |         if refresh and self._data: self.plot(self._data)
 | 
|---|
| 755 | 
 | 
|---|
| 756 |     def set_margin(self,margin=[],refresh=True):
 | 
|---|
| 757 |         """
 | 
|---|
| 758 |         Set margins between subplots and plot edges.
 | 
|---|
| 759 |         Parameters:
 | 
|---|
| 760 |             margin:   a list of margins in figure coordinate (0-1),
 | 
|---|
| 761 |                       i.e., fraction of the figure width or height.
 | 
|---|
| 762 |                       The order of elements should be:
 | 
|---|
| 763 |                       [left, bottom, right, top, horizontal space btw panels,
 | 
|---|
| 764 |                       vertical space btw panels].
 | 
|---|
| 765 |             refresh:  True (default) or False. If True, the plot is
 | 
|---|
| 766 |                       replotted based on the new parameter setting(s).
 | 
|---|
| 767 |                       Otherwise,the parameter(s) are set without replotting.
 | 
|---|
| 768 |         Note
 | 
|---|
| 769 |         * When margin is not specified, the values are reset to the defaults
 | 
|---|
| 770 |           of matplotlib.
 | 
|---|
| 771 |         * If any element is set to be None, the current value is adopted.
 | 
|---|
| 772 |         """
 | 
|---|
| 773 |         if margin == []: self._margins=self._reset_margin()
 | 
|---|
| 774 |         else:
 | 
|---|
| 775 |             self._margins=[None]*6
 | 
|---|
| 776 |             self._margins[0:len(margin)]=margin
 | 
|---|
| 777 |         #print "panel margin set to ",self._margins
 | 
|---|
| 778 |         if refresh and self._data: self.plot(self._data)
 | 
|---|
| 779 | 
 | 
|---|
| 780 |     def _reset_margin(self):
 | 
|---|
| 781 |         ks=map(lambda x: 'figure.subplot.'+x,
 | 
|---|
| 782 |                ['left','bottom','right','top','hspace','wspace'])
 | 
|---|
| 783 |         return map(matplotlib.rcParams.get,ks)
 | 
|---|
| 784 | 
 | 
|---|
| 785 |     def plot_lines(self, linecat=None, doppler=0.0, deltachan=10, rotate=90.0,
 | 
|---|
| 786 |                    location=None):
 | 
|---|
| 787 |         """
 | 
|---|
| 788 |         Plot a line catalog.
 | 
|---|
| 789 |         Parameters:
 | 
|---|
| 790 |             linecat:      the linecatalog to plot
 | 
|---|
| 791 |             doppler:      the velocity shift to apply to the frequencies
 | 
|---|
| 792 |             deltachan:    the number of channels to include each side of the
 | 
|---|
| 793 |                           line to determine a local maximum/minimum
 | 
|---|
| 794 |             rotate:       the rotation (in degrees) for the text label (default 90.0)
 | 
|---|
| 795 |             location:     the location of the line annotation from the 'top',
 | 
|---|
| 796 |                           'bottom' or alternate (None - the default)
 | 
|---|
| 797 |         Notes:
 | 
|---|
| 798 |         If the spectrum is flagged no line will be drawn in that location.
 | 
|---|
| 799 |         """
 | 
|---|
| 800 |         errmsg = "Cannot plot spectral lines. Need to plot scantable first."
 | 
|---|
| 801 |         self._assert_plotter(action="halt",errmsg=errmsg)
 | 
|---|
| 802 |         if not self._data:
 | 
|---|
| 803 |             raise RuntimeError("No scantable has been plotted yet.")
 | 
|---|
| 804 |         from asap._asap import linecatalog
 | 
|---|
| 805 |         if not isinstance(linecat, linecatalog):
 | 
|---|
| 806 |             raise ValueError("'linecat' isn't of type linecatalog.")
 | 
|---|
| 807 |         if not self._data.get_unit().endswith("Hz"):
 | 
|---|
| 808 |             raise RuntimeError("Can only overlay linecatalogs when data is in frequency.")
 | 
|---|
| 809 |         from numpy import ma
 | 
|---|
| 810 |         for j in range(len(self._plotter.subplots)):
 | 
|---|
| 811 |             self._plotter.subplot(j)
 | 
|---|
| 812 |             lims = self._plotter.axes.get_xlim()
 | 
|---|
| 813 |             for row in range(linecat.nrow()):
 | 
|---|
| 814 |                 # get_frequency returns MHz
 | 
|---|
| 815 |                 base = { "GHz": 1000.0, "MHz": 1.0, "Hz": 1.0e-6 }
 | 
|---|
| 816 |                 restf = linecat.get_frequency(row)/base[self._data.get_unit()]
 | 
|---|
| 817 |                 c = 299792.458
 | 
|---|
| 818 |                 freq = restf*(1.0-doppler/c)
 | 
|---|
| 819 |                 if lims[0] < freq < lims[1]:
 | 
|---|
| 820 |                     if location is None:
 | 
|---|
| 821 |                         loc = 'bottom'
 | 
|---|
| 822 |                         if row%2: loc='top'
 | 
|---|
| 823 |                     else: loc = location
 | 
|---|
| 824 |                     maxys = []
 | 
|---|
| 825 |                     for line in self._plotter.axes.lines:
 | 
|---|
| 826 |                         v = line._x
 | 
|---|
| 827 |                         asc = v[0] < v[-1]
 | 
|---|
| 828 | 
 | 
|---|
| 829 |                         idx = None
 | 
|---|
| 830 |                         if not asc:
 | 
|---|
| 831 |                             if v[len(v)-1] <= freq <= v[0]:
 | 
|---|
| 832 |                                 i = len(v)-1
 | 
|---|
| 833 |                                 while i>=0 and v[i] < freq:
 | 
|---|
| 834 |                                     idx = i
 | 
|---|
| 835 |                                     i-=1
 | 
|---|
| 836 |                         else:
 | 
|---|
| 837 |                            if v[0] <= freq <= v[len(v)-1]:
 | 
|---|
| 838 |                                 i = 0
 | 
|---|
| 839 |                                 while  i<len(v) and v[i] < freq:
 | 
|---|
| 840 |                                     idx = i
 | 
|---|
| 841 |                                     i+=1
 | 
|---|
| 842 |                         if idx is not None:
 | 
|---|
| 843 |                             lower = idx - deltachan
 | 
|---|
| 844 |                             upper = idx + deltachan
 | 
|---|
| 845 |                             if lower < 0: lower = 0
 | 
|---|
| 846 |                             if upper > len(v): upper = len(v)
 | 
|---|
| 847 |                             s = slice(lower, upper)
 | 
|---|
| 848 |                             y = line._y[s]
 | 
|---|
| 849 |                             maxy = ma.maximum(y)
 | 
|---|
| 850 |                             if isinstance( maxy, float):
 | 
|---|
| 851 |                                 maxys.append(maxy)
 | 
|---|
| 852 |                     if len(maxys):
 | 
|---|
| 853 |                         peak = max(maxys)
 | 
|---|
| 854 |                         if peak > self._plotter.axes.get_ylim()[1]:
 | 
|---|
| 855 |                             loc = 'bottom'
 | 
|---|
| 856 |                     else:
 | 
|---|
| 857 |                         continue
 | 
|---|
| 858 |                     self._plotter.vline_with_label(freq, peak,
 | 
|---|
| 859 |                                                    linecat.get_name(row),
 | 
|---|
| 860 |                                                    location=loc, rotate=rotate)
 | 
|---|
| 861 |         self._plotter.show(hardrefresh=False)
 | 
|---|
| 862 | 
 | 
|---|
| 863 | 
 | 
|---|
| 864 |     def set_selection(self, selection=None, refresh=True, **kw):
 | 
|---|
| 865 |         """
 | 
|---|
| 866 |         Parameters:
 | 
|---|
| 867 |             selection:  a selector object (default unset the selection)
 | 
|---|
| 868 |             refresh:    True (default) or False. If True, the plot is
 | 
|---|
| 869 |                         replotted based on the new parameter setting(s).
 | 
|---|
| 870 |                         Otherwise,the parameter(s) are set without replotting.
 | 
|---|
| 871 |         """
 | 
|---|
| 872 |         if selection is None:
 | 
|---|
| 873 |             # reset
 | 
|---|
| 874 |             if len(kw) == 0:
 | 
|---|
| 875 |                 self._selection = selector()
 | 
|---|
| 876 |             else:
 | 
|---|
| 877 |                 # try keywords
 | 
|---|
| 878 |                 for k in kw:
 | 
|---|
| 879 |                     if k not in selector.fields:
 | 
|---|
| 880 |                         raise KeyError("Invalid selection key '%s', valid keys are %s" % (k, selector.fields))
 | 
|---|
| 881 |                 self._selection = selector(**kw)
 | 
|---|
| 882 |         elif isinstance(selection, selector):
 | 
|---|
| 883 |             self._selection = selection
 | 
|---|
| 884 |         else:
 | 
|---|
| 885 |             raise TypeError("'selection' is not of type selector")
 | 
|---|
| 886 | 
 | 
|---|
| 887 |         order = self._get_sortstring([self._panelling,self._stacking])
 | 
|---|
| 888 |         if order:
 | 
|---|
| 889 |             self._selection.set_order(order)
 | 
|---|
| 890 |         if refresh and self._data: 
 | 
|---|
| 891 |             self.plot()
 | 
|---|
| 892 | 
 | 
|---|
| 893 |     @asaplog_post_dec
 | 
|---|
| 894 |     def set_mask(self, mask=None, selection=None, refresh=True):
 | 
|---|
| 895 |         """
 | 
|---|
| 896 |         Set a plotting mask for a specific polarization.
 | 
|---|
| 897 |         This is useful for masking out 'noise' Pangle outside a source.
 | 
|---|
| 898 |         Parameters:
 | 
|---|
| 899 |              mask:           a mask from scantable.create_mask
 | 
|---|
| 900 |              selection:      the spectra to apply the mask to.
 | 
|---|
| 901 |              refresh:        True (default) or False. If True, the plot is
 | 
|---|
| 902 |                              replotted based on the new parameter setting(s).
 | 
|---|
| 903 |                              Otherwise,the parameter(s) are set without replotting.
 | 
|---|
| 904 |         Example:
 | 
|---|
| 905 |              select = selector()
 | 
|---|
| 906 |              select.setpolstrings('Pangle')
 | 
|---|
| 907 |              plotter.set_mask(mymask, select)
 | 
|---|
| 908 |         """
 | 
|---|
| 909 |         if not self._data:
 | 
|---|
| 910 |             msg = "Can only set mask after a first call to plot()"
 | 
|---|
| 911 |             raise RuntimeError(msg)
 | 
|---|
| 912 |         if (mask is not None) and len(mask):
 | 
|---|
| 913 |             if isinstance(mask, list) or isinstance(mask, tuple):
 | 
|---|
| 914 |                 self._usermask = array(mask)
 | 
|---|
| 915 |             else:
 | 
|---|
| 916 |                 self._usermask = mask
 | 
|---|
| 917 |         if mask is None and selection is None:
 | 
|---|
| 918 |             self._usermask = []
 | 
|---|
| 919 |             self._maskselection = None
 | 
|---|
| 920 |         if isinstance(selection, selector):
 | 
|---|
| 921 |             self._maskselection = {'b': selection.get_beams(),
 | 
|---|
| 922 |                                    's': selection.get_scans(),
 | 
|---|
| 923 |                                    'i': selection.get_ifs(),
 | 
|---|
| 924 |                                    'p': selection.get_pols(),
 | 
|---|
| 925 |                                    't': [] }
 | 
|---|
| 926 |         else:
 | 
|---|
| 927 |             self._maskselection = None
 | 
|---|
| 928 |         if refresh: self.plot(self._data)
 | 
|---|
| 929 | 
 | 
|---|
| 930 | 
 | 
|---|
| 931 |     ### Reset methods ###
 | 
|---|
| 932 |     def _reset(self):
 | 
|---|
| 933 |         """Reset method called when new data is set"""
 | 
|---|
| 934 |         # reset selections and masks
 | 
|---|
| 935 |         self.set_selection(None, False)
 | 
|---|
| 936 |         self.set_mask(None, None, False)
 | 
|---|
| 937 |         # reset offset
 | 
|---|
| 938 |         self._offset = None
 | 
|---|
| 939 |         # reset header
 | 
|---|
| 940 |         self._reset_header()
 | 
|---|
| 941 |         # reset labels
 | 
|---|
| 942 |         self._lmap = None # related to stack
 | 
|---|
| 943 |         self.set_title(None, None, False)
 | 
|---|
| 944 |         self.set_ordinate(None, None, False)
 | 
|---|
| 945 |         self.set_abcissa(None, None, False)
 | 
|---|
| 946 | 
 | 
|---|
| 947 |     def _reset_header(self):
 | 
|---|
| 948 |         self._headtext={'string': None, 'textobj': None}
 | 
|---|
| 949 | 
 | 
|---|
| 950 |     def _reset_counter(self):
 | 
|---|
| 951 |         self._startrow = 0
 | 
|---|
| 952 |         self._ipanel = -1
 | 
|---|
| 953 |         self._panelrows = []
 | 
|---|
| 954 |         self._reset_header()
 | 
|---|
| 955 |         if self.casabar_exists():
 | 
|---|
| 956 |             self._plotter.figmgr.casabar.set_pagecounter(1)
 | 
|---|
| 957 | 
 | 
|---|
| 958 |     def _reset_counters(self):
 | 
|---|
| 959 |         self._startrow = 0
 | 
|---|
| 960 |         self._ipanel = -1
 | 
|---|
| 961 |         self._panelrows = []
 | 
|---|
| 962 | 
 | 
|---|
| 963 | 
 | 
|---|
| 964 |     ### Actual scantable plot methods ###
 | 
|---|
| 965 |     @asaplog_post_dec
 | 
|---|
| 966 |     def plot(self, scan=None):
 | 
|---|
| 967 |         """
 | 
|---|
| 968 |         Plot a scantable.
 | 
|---|
| 969 |         Parameters:
 | 
|---|
| 970 |             scan:   a scantable
 | 
|---|
| 971 |         Note:
 | 
|---|
| 972 |             If a scantable was specified in a previous call
 | 
|---|
| 973 |             to plot, no argument has to be given to 'replot'
 | 
|---|
| 974 |             NO checking is done that the abcissas of the scantable
 | 
|---|
| 975 |             are consistent e.g. all 'channel' or all 'velocity' etc.
 | 
|---|
| 976 |         """
 | 
|---|
| 977 |         self._plotmode = "spectra"
 | 
|---|
| 978 |         if not self._data and not scan:
 | 
|---|
| 979 |             msg = "Input is not a scantable"
 | 
|---|
| 980 |             raise TypeError(msg)
 | 
|---|
| 981 | 
 | 
|---|
| 982 |         self._assert_plotter(action="reload")
 | 
|---|
| 983 |         self._plotter.hold()
 | 
|---|
| 984 |         self._reset_counter()
 | 
|---|
| 985 |         #self._plotter.clear()
 | 
|---|
| 986 |         if scan: 
 | 
|---|
| 987 |             self.set_data(scan, refresh=False)
 | 
|---|
| 988 |         self._plotter.palette(color=0,colormap=self._colormap,
 | 
|---|
| 989 |                               linestyle=0,linestyles=self._linestyles)
 | 
|---|
| 990 |         self._plotter.legend(self._legendloc)
 | 
|---|
| 991 |         self._plot(self._data)
 | 
|---|
| 992 |         if self._minmaxy is not None:
 | 
|---|
| 993 |             self._plotter.set_limits(ylim=self._minmaxy)
 | 
|---|
| 994 |         if self.casabar_exists(): self._plotter.figmgr.casabar.enable_button()
 | 
|---|
| 995 |         self._plotter.release()
 | 
|---|
| 996 |         self._plotter.tidy()
 | 
|---|
| 997 |         self._plotter.show(hardrefresh=False)
 | 
|---|
| 998 |         return
 | 
|---|
| 999 | 
 | 
|---|
| 1000 |     def _plot(self, scan):
 | 
|---|
| 1001 |         savesel = scan.get_selection()
 | 
|---|
| 1002 |         sel = savesel +  self._selection
 | 
|---|
| 1003 |         order = self._get_sortstring([self._panelling,self._stacking])
 | 
|---|
| 1004 |         if order:
 | 
|---|
| 1005 |             sel.set_order(order)
 | 
|---|
| 1006 |         scan.set_selection(sel)
 | 
|---|
| 1007 |         d = {'b': scan.getbeam, 's': scan.getscan,
 | 
|---|
| 1008 |              'i': scan.getif, 'p': scan.getpol, 't': scan.get_time,
 | 
|---|
| 1009 |              'r': int}#, '_r': int}
 | 
|---|
| 1010 | 
 | 
|---|
| 1011 |         polmodes = dict(zip(sel.get_pols(), sel.get_poltypes()))
 | 
|---|
| 1012 |         # this returns either a tuple of numbers or a length  (ncycles)
 | 
|---|
| 1013 |         # convert this into lengths
 | 
|---|
| 1014 |         n0,nstack0 = self._get_selected_n(scan)
 | 
|---|
| 1015 |         if isinstance(n0, int): n = n0
 | 
|---|
| 1016 |         else: n = len(n0)
 | 
|---|
| 1017 |         if isinstance(nstack0, int): nstack = nstack0
 | 
|---|
| 1018 |         else: nstack = len(nstack0)
 | 
|---|
| 1019 |         # In case of row stacking
 | 
|---|
| 1020 |         rowstack = False
 | 
|---|
| 1021 |         titlemode = self._panelling
 | 
|---|
| 1022 |         if self._stacking == "r" and self._panelling != "r":
 | 
|---|
| 1023 |             rowstack = True
 | 
|---|
| 1024 |             titlemode = '_r'
 | 
|---|
| 1025 |         nptot = n
 | 
|---|
| 1026 |         maxpanel, maxstack = 16,16
 | 
|---|
| 1027 |         if nstack > maxstack:
 | 
|---|
| 1028 |             msg ="Scan to be overlayed contains more than %d selections.\n" \
 | 
|---|
| 1029 |                   "Selecting first %d selections..." % (maxstack, maxstack)
 | 
|---|
| 1030 |             asaplog.push(msg)
 | 
|---|
| 1031 |             asaplog.post('WARN')
 | 
|---|
| 1032 |             nstack = min(nstack,maxstack)
 | 
|---|
| 1033 |         #n = min(n-self._ipanel-1,maxpanel)
 | 
|---|
| 1034 |         n = n-self._ipanel-1
 | 
|---|
| 1035 |         # the number of panels in this page
 | 
|---|
| 1036 |         if self._rows and self._cols:
 | 
|---|
| 1037 |             n = min(n,self._rows*self._cols)
 | 
|---|
| 1038 |         else:
 | 
|---|
| 1039 |             n = min(n,maxpanel)
 | 
|---|
| 1040 | 
 | 
|---|
| 1041 |         firstpage = (self._ipanel < 0)
 | 
|---|
| 1042 |         #ganged = False
 | 
|---|
| 1043 |         ganged = rcParams['plotter.ganged']
 | 
|---|
| 1044 |         if self._panelling == 'i':
 | 
|---|
| 1045 |             ganged = False
 | 
|---|
| 1046 |         if (not firstpage) and \
 | 
|---|
| 1047 |                self._plotter._subplotsOk(self._rows, self._cols, n):
 | 
|---|
| 1048 |             # Not the first page and subplot number is ok.
 | 
|---|
| 1049 |             # Just clear the axis
 | 
|---|
| 1050 |             nx = self._plotter.cols
 | 
|---|
| 1051 |             ipaxx = n - nx - 1 #the max panel id to supress x-label
 | 
|---|
| 1052 |             for ip in xrange(len(self._plotter.subplots)):
 | 
|---|
| 1053 |                 self._plotter.subplot(ip)
 | 
|---|
| 1054 |                 self._plotter.clear()
 | 
|---|
| 1055 |                 self._plotter.axes.set_visible((ip<n))
 | 
|---|
| 1056 |                 if ganged:
 | 
|---|
| 1057 |                     self._plotter.axes.xaxis.label.set_visible((ip > ipaxx))
 | 
|---|
| 1058 |                     if ip <= ipaxx:
 | 
|---|
| 1059 |                         map(lambda x: x.set_visible(False), \
 | 
|---|
| 1060 |                             self._plotter.axes.get_xticklabels())
 | 
|---|
| 1061 |                     self._plotter.axes.yaxis.label.set_visible((ip % nx)==0)
 | 
|---|
| 1062 |                     if ip % nx:
 | 
|---|
| 1063 |                         map(lambda y: y.set_visible(False), \
 | 
|---|
| 1064 |                             self._plotter.axes.get_yticklabels())
 | 
|---|
| 1065 |         elif (n > 1 and self._rows and self._cols):
 | 
|---|
| 1066 |                 self._plotter.set_panels(rows=self._rows,cols=self._cols,
 | 
|---|
| 1067 |                                          nplots=n,margin=self._margins,
 | 
|---|
| 1068 |                                          ganged=ganged)
 | 
|---|
| 1069 |         else:
 | 
|---|
| 1070 |             self._plotter.set_panels(rows=n,cols=0,nplots=n,
 | 
|---|
| 1071 |                                      margin=self._margins,ganged=ganged)
 | 
|---|
| 1072 |         #r = 0
 | 
|---|
| 1073 |         r = self._startrow
 | 
|---|
| 1074 |         nr = scan.nrow()
 | 
|---|
| 1075 |         a0,b0 = -1,-1
 | 
|---|
| 1076 |         allxlim = []
 | 
|---|
| 1077 |         allylim = []
 | 
|---|
| 1078 |         #newpanel=True
 | 
|---|
| 1079 |         newpanel=False
 | 
|---|
| 1080 |         panelcount,stackcount = 0,0
 | 
|---|
| 1081 |         # If this is not the first page
 | 
|---|
| 1082 |         if r > 0:
 | 
|---|
| 1083 |             # panelling value of the prev page 
 | 
|---|
| 1084 |             a0 = d[self._panelling](r-1)
 | 
|---|
| 1085 |             # set the initial stackcount large not to plot
 | 
|---|
| 1086 |             # the start row automatically
 | 
|---|
| 1087 |             stackcount = nstack
 | 
|---|
| 1088 | 
 | 
|---|
| 1089 |         while r < nr:
 | 
|---|
| 1090 |             a = d[self._panelling](r)
 | 
|---|
| 1091 |             b = d[self._stacking](r)
 | 
|---|
| 1092 |             if a > a0 and panelcount < n:
 | 
|---|
| 1093 |                 if n > 1:
 | 
|---|
| 1094 |                     self._plotter.subplot(panelcount)
 | 
|---|
| 1095 |                 self._plotter.palette(0)
 | 
|---|
| 1096 |                 #title
 | 
|---|
| 1097 |                 xlab = self._abcissa and self._abcissa[panelcount] \
 | 
|---|
| 1098 |                        or scan._getabcissalabel()
 | 
|---|
| 1099 |                 if self._offset and not self._abcissa:
 | 
|---|
| 1100 |                     xlab += " (relative)"
 | 
|---|
| 1101 |                 ylab = self._ordinate and self._ordinate[panelcount] \
 | 
|---|
| 1102 |                        or scan._get_ordinate_label()
 | 
|---|
| 1103 |                 self._plotter.set_axes('xlabel', xlab)
 | 
|---|
| 1104 |                 self._plotter.set_axes('ylabel', ylab)
 | 
|---|
| 1105 |                 #lbl = self._get_label(scan, r, self._panelling, self._title)
 | 
|---|
| 1106 |                 lbl = self._get_label(scan, r, titlemode, self._title)
 | 
|---|
| 1107 |                 if isinstance(lbl, list) or isinstance(lbl, tuple):
 | 
|---|
| 1108 |                     if 0 <= panelcount < len(lbl):
 | 
|---|
| 1109 |                         lbl = lbl[panelcount]
 | 
|---|
| 1110 |                     else:
 | 
|---|
| 1111 |                         # get default label
 | 
|---|
| 1112 |                         #lbl = self._get_label(scan, r, self._panelling, None)
 | 
|---|
| 1113 |                         lbl = self._get_label(scan, r, titlemode, None)
 | 
|---|
| 1114 |                 self._plotter.set_axes('title',lbl)
 | 
|---|
| 1115 |                 newpanel = True
 | 
|---|
| 1116 |                 stackcount = 0
 | 
|---|
| 1117 |                 panelcount += 1
 | 
|---|
| 1118 |                 # save the start row to plot this panel for future revisit.
 | 
|---|
| 1119 |                 if self._panelling != 'r' and \
 | 
|---|
| 1120 |                        len(self._panelrows) < self._ipanel+1+panelcount:
 | 
|---|
| 1121 |                     self._panelrows += [r]
 | 
|---|
| 1122 |                     
 | 
|---|
| 1123 |             #if (b > b0 or newpanel) and stackcount < nstack:
 | 
|---|
| 1124 |             if stackcount < nstack and (newpanel or \
 | 
|---|
| 1125 |                                             rowstack or (a == a0 and b > b0)):
 | 
|---|
| 1126 |                 y = []
 | 
|---|
| 1127 |                 if len(polmodes):
 | 
|---|
| 1128 |                     y = scan._getspectrum(r, polmodes[scan.getpol(r)])
 | 
|---|
| 1129 |                 else:
 | 
|---|
| 1130 |                     y = scan._getspectrum(r)
 | 
|---|
| 1131 |                 # flag application
 | 
|---|
| 1132 |                 mr = scan._getflagrow(r)
 | 
|---|
| 1133 |                 from numpy import ma, array
 | 
|---|
| 1134 |                 if mr:
 | 
|---|
| 1135 |                     y = ma.masked_array(y,mask=mr)
 | 
|---|
| 1136 |                 else:
 | 
|---|
| 1137 |                     m = scan._getmask(r)
 | 
|---|
| 1138 |                     from numpy import logical_not, logical_and
 | 
|---|
| 1139 |                     if self._maskselection and len(self._usermask) == len(m):
 | 
|---|
| 1140 |                         if d[self._stacking](r) in self._maskselection[self._stacking]:
 | 
|---|
| 1141 |                             m = logical_and(m, self._usermask)
 | 
|---|
| 1142 |                     y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
 | 
|---|
| 1143 | 
 | 
|---|
| 1144 |                 x = array(scan._getabcissa(r))
 | 
|---|
| 1145 |                 if self._offset:
 | 
|---|
| 1146 |                     x += self._offset
 | 
|---|
| 1147 |                 if self._minmaxx is not None:
 | 
|---|
| 1148 |                     s,e = self._slice_indeces(x)
 | 
|---|
| 1149 |                     x = x[s:e]
 | 
|---|
| 1150 |                     y = y[s:e]
 | 
|---|
| 1151 |                 if len(x) > 1024 and rcParams['plotter.decimate']:
 | 
|---|
| 1152 |                     fac = len(x)/1024
 | 
|---|
| 1153 |                     x = x[::fac]
 | 
|---|
| 1154 |                     y = y[::fac]
 | 
|---|
| 1155 |                 llbl = self._get_label(scan, r, self._stacking, self._lmap)
 | 
|---|
| 1156 |                 if isinstance(llbl, list) or isinstance(llbl, tuple):
 | 
|---|
| 1157 |                     if 0 <= stackcount < len(llbl):
 | 
|---|
| 1158 |                         # use user label
 | 
|---|
| 1159 |                         llbl = llbl[stackcount]
 | 
|---|
| 1160 |                     else:
 | 
|---|
| 1161 |                         # get default label
 | 
|---|
| 1162 |                         llbl = self._get_label(scan, r, self._stacking, None)
 | 
|---|
| 1163 |                 self._plotter.set_line(label=llbl)
 | 
|---|
| 1164 |                 plotit = self._plotter.plot
 | 
|---|
| 1165 |                 if self._hist: plotit = self._plotter.hist
 | 
|---|
| 1166 |                 if len(x) > 0 and not mr:
 | 
|---|
| 1167 |                     plotit(x,y)
 | 
|---|
| 1168 |                     xlim= self._minmaxx or [min(x),max(x)]
 | 
|---|
| 1169 |                     allxlim += xlim
 | 
|---|
| 1170 |                     ylim= self._minmaxy or [ma.minimum(y),ma.maximum(y)]
 | 
|---|
| 1171 |                     allylim += ylim
 | 
|---|
| 1172 |                 else:
 | 
|---|
| 1173 |                     xlim = self._minmaxx or []
 | 
|---|
| 1174 |                     allxlim += xlim
 | 
|---|
| 1175 |                     ylim= self._minmaxy or []
 | 
|---|
| 1176 |                     allylim += ylim
 | 
|---|
| 1177 |                 stackcount += 1
 | 
|---|
| 1178 |                 a0=a
 | 
|---|
| 1179 |                 b0=b
 | 
|---|
| 1180 |                 # last in colour stack -> autoscale x
 | 
|---|
| 1181 |                 if stackcount == nstack and len(allxlim) > 0:
 | 
|---|
| 1182 |                     allxlim.sort()
 | 
|---|
| 1183 |                     self._plotter.subplots[panelcount-1]['axes'].set_xlim([allxlim[0],allxlim[-1]])
 | 
|---|
| 1184 |                     if ganged:
 | 
|---|
| 1185 |                         allxlim = [allxlim[0],allxlim[-1]]
 | 
|---|
| 1186 |                     else:
 | 
|---|
| 1187 |                         # clear
 | 
|---|
| 1188 |                         allxlim =[]
 | 
|---|
| 1189 | 
 | 
|---|
| 1190 |             newpanel = False
 | 
|---|
| 1191 |             #a0=a
 | 
|---|
| 1192 |             #b0=b
 | 
|---|
| 1193 |             # ignore following rows
 | 
|---|
| 1194 |             if (panelcount == n and stackcount == nstack) or (r == nr-1):
 | 
|---|
| 1195 |                 # last panel -> autoscale y if ganged
 | 
|---|
| 1196 |                 #if rcParams['plotter.ganged'] and len(allylim) > 0:
 | 
|---|
| 1197 |                 if ganged and len(allylim) > 0:
 | 
|---|
| 1198 |                     allylim.sort()
 | 
|---|
| 1199 |                     self._plotter.set_limits(ylim=[allylim[0],allylim[-1]])
 | 
|---|
| 1200 |                 break
 | 
|---|
| 1201 |             r+=1 # next row
 | 
|---|
| 1202 | 
 | 
|---|
| 1203 |         # save the current counter for multi-page plotting
 | 
|---|
| 1204 |         self._startrow = r+1
 | 
|---|
| 1205 |         self._ipanel += panelcount
 | 
|---|
| 1206 |         if self.casabar_exists():
 | 
|---|
| 1207 |             if self._ipanel >= nptot-1:
 | 
|---|
| 1208 |                 self._plotter.figmgr.casabar.disable_next()
 | 
|---|
| 1209 |             else:
 | 
|---|
| 1210 |                 self._plotter.figmgr.casabar.enable_next()
 | 
|---|
| 1211 |             if self._ipanel + 1 - panelcount > 0:
 | 
|---|
| 1212 |                 self._plotter.figmgr.casabar.enable_prev()
 | 
|---|
| 1213 |             else:
 | 
|---|
| 1214 |                 self._plotter.figmgr.casabar.disable_prev()
 | 
|---|
| 1215 | 
 | 
|---|
| 1216 |         #reset the selector to the scantable's original
 | 
|---|
| 1217 |         scan.set_selection(savesel)
 | 
|---|
| 1218 | 
 | 
|---|
| 1219 |         #temporary switch-off for older matplotlib
 | 
|---|
| 1220 |         #if self._fp is not None:
 | 
|---|
| 1221 |         if self._fp is not None and \
 | 
|---|
| 1222 |                getattr(self._plotter.figure,'findobj',False):
 | 
|---|
| 1223 |             for o in self._plotter.figure.findobj(Text):
 | 
|---|
| 1224 |                 if not self._headtext['textobj'] or \
 | 
|---|
| 1225 |                    not (o in self._headtext['textobj']):
 | 
|---|
| 1226 |                     o.set_fontproperties(self._fp)
 | 
|---|
| 1227 | 
 | 
|---|
| 1228 |     def _get_sortstring(self, lorders):
 | 
|---|
| 1229 |         d0 = {'s': 'SCANNO', 'b': 'BEAMNO', 'i':'IFNO',
 | 
|---|
| 1230 |               'p': 'POLNO', 'c': 'CYCLENO', 't' : 'TIME', 'r':None, '_r':None }
 | 
|---|
| 1231 |         if not (type(lorders) == list) and not (type(lorders) == tuple):
 | 
|---|
| 1232 |             return None
 | 
|---|
| 1233 |         if len(lorders) > 0:
 | 
|---|
| 1234 |             lsorts = []
 | 
|---|
| 1235 |             for order in lorders:
 | 
|---|
| 1236 |                 if order == "r":
 | 
|---|
| 1237 |                     # don't sort if row panelling/stacking
 | 
|---|
| 1238 |                     return None
 | 
|---|
| 1239 |                 ssort = d0[order]
 | 
|---|
| 1240 |                 if ssort:
 | 
|---|
| 1241 |                     lsorts.append(ssort)
 | 
|---|
| 1242 |             return lsorts
 | 
|---|
| 1243 |         return None
 | 
|---|
| 1244 | 
 | 
|---|
| 1245 |     def _get_selected_n(self, scan):
 | 
|---|
| 1246 |         d1 = {'b': scan.getbeamnos, 's': scan.getscannos,
 | 
|---|
| 1247 |              'i': scan.getifnos, 'p': scan.getpolnos, 't': scan.ncycle,
 | 
|---|
| 1248 |              'r': scan.nrow}#, '_r': False}
 | 
|---|
| 1249 |         d2 = { 'b': self._selection.get_beams(),
 | 
|---|
| 1250 |                's': self._selection.get_scans(),
 | 
|---|
| 1251 |                'i': self._selection.get_ifs(),
 | 
|---|
| 1252 |                'p': self._selection.get_pols(),
 | 
|---|
| 1253 |                't': self._selection.get_cycles(),
 | 
|---|
| 1254 |                'r': False}#, '_r': 1}
 | 
|---|
| 1255 |         n =  d2[self._panelling] or d1[self._panelling]()
 | 
|---|
| 1256 |         nstack = d2[self._stacking] or d1[self._stacking]()
 | 
|---|
| 1257 |         # handle row panelling/stacking
 | 
|---|
| 1258 |         if self._panelling == 'r':
 | 
|---|
| 1259 |             nstack = 1
 | 
|---|
| 1260 |         elif self._stacking == 'r':
 | 
|---|
| 1261 |             n = 1
 | 
|---|
| 1262 |         return n,nstack
 | 
|---|
| 1263 | 
 | 
|---|
| 1264 |     def _get_label(self, scan, row, mode, userlabel=None):
 | 
|---|
| 1265 |         if isinstance(userlabel, list) and len(userlabel) == 0:
 | 
|---|
| 1266 |             userlabel = " "
 | 
|---|
| 1267 |         pms = dict(zip(self._selection.get_pols(),self._selection.get_poltypes()))
 | 
|---|
| 1268 |         if len(pms):
 | 
|---|
| 1269 |             poleval = scan._getpollabel(scan.getpol(row),pms[scan.getpol(row)])
 | 
|---|
| 1270 |         else:
 | 
|---|
| 1271 |             poleval = scan._getpollabel(scan.getpol(row),scan.poltype())
 | 
|---|
| 1272 |         d = {'b': "Beam "+str(scan.getbeam(row)),
 | 
|---|
| 1273 |              #'s': scan._getsourcename(row),
 | 
|---|
| 1274 |              's': "Scan "+str(scan.getscan(row))+\
 | 
|---|
| 1275 |                   " ("+str(scan._getsourcename(row))+")",
 | 
|---|
| 1276 |              'i': "IF"+str(scan.getif(row)),
 | 
|---|
| 1277 |              'p': poleval,
 | 
|---|
| 1278 |              't': str(scan.get_time(row)),
 | 
|---|
| 1279 |              'r': "row "+str(row),
 | 
|---|
| 1280 |              #'_r': str(scan.get_time(row))+",\nIF"+str(scan.getif(row))+", "+poleval+", Beam"+str(scan.getbeam(row)) }
 | 
|---|
| 1281 |              '_r': "" }
 | 
|---|
| 1282 |         return userlabel or d[mode]
 | 
|---|
| 1283 | 
 | 
|---|
| 1284 |     def _slice_indeces(self, data):
 | 
|---|
| 1285 |         mn = self._minmaxx[0]
 | 
|---|
| 1286 |         mx = self._minmaxx[1]
 | 
|---|
| 1287 |         asc = data[0] < data[-1]
 | 
|---|
| 1288 |         start=0
 | 
|---|
| 1289 |         end = len(data)-1
 | 
|---|
| 1290 |         inc = 1
 | 
|---|
| 1291 |         if not asc:
 | 
|---|
| 1292 |             start = len(data)-1
 | 
|---|
| 1293 |             end = 0
 | 
|---|
| 1294 |             inc = -1
 | 
|---|
| 1295 |         # find min index
 | 
|---|
| 1296 |         #while start > 0 and data[start] < mn:
 | 
|---|
| 1297 |         #    start+= inc
 | 
|---|
| 1298 |         minind=start
 | 
|---|
| 1299 |         for ind in xrange(start,end+inc,inc):
 | 
|---|
| 1300 |             if data[ind] > mn: break
 | 
|---|
| 1301 |             minind=ind
 | 
|---|
| 1302 |         # find max index
 | 
|---|
| 1303 |         #while end > 0 and data[end] > mx:
 | 
|---|
| 1304 |         #    end-=inc
 | 
|---|
| 1305 |         #if end > 0: end +=1
 | 
|---|
| 1306 |         maxind=end
 | 
|---|
| 1307 |         for ind in xrange(end,start-inc,-inc):
 | 
|---|
| 1308 |             if data[ind] < mx: break
 | 
|---|
| 1309 |             maxind=ind
 | 
|---|
| 1310 |         start=minind
 | 
|---|
| 1311 |         end=maxind
 | 
|---|
| 1312 |         if start > end:
 | 
|---|
| 1313 |             return end,start+1
 | 
|---|
| 1314 |         elif start < end:
 | 
|---|
| 1315 |             return start,end+1
 | 
|---|
| 1316 |         else:
 | 
|---|
| 1317 |             return start,end
 | 
|---|
| 1318 | 
 | 
|---|
| 1319 |     def _get_date_axis_setup(self, dates, axlim=None):
 | 
|---|
| 1320 |         """
 | 
|---|
| 1321 |         Returns proper axis title and formatters for a list of dates
 | 
|---|
| 1322 |         Input
 | 
|---|
| 1323 |             dates : a list of datetime objects returned by,
 | 
|---|
| 1324 |                     e.g. scantable.get_time(asdatetime=True)
 | 
|---|
| 1325 |             axlim : a tuple of min and max day range in the plot axis.
 | 
|---|
| 1326 |                     if defined, the values are taken into account.
 | 
|---|
| 1327 |         Output
 | 
|---|
| 1328 |             a set of
 | 
|---|
| 1329 |             * date axis title string
 | 
|---|
| 1330 |             * formatter of date axis 
 | 
|---|
| 1331 |             * major axis locator
 | 
|---|
| 1332 |             * minor axis locator
 | 
|---|
| 1333 |         """
 | 
|---|
| 1334 |         from matplotlib import pylab as PL
 | 
|---|
| 1335 |         from matplotlib.dates import DateFormatter
 | 
|---|
| 1336 |         from matplotlib.dates import HourLocator, MinuteLocator,SecondLocator, DayLocator, YearLocator, MonthLocator
 | 
|---|
| 1337 |         t = PL.date2num(dates)
 | 
|---|
| 1338 |         tmin = min(t)
 | 
|---|
| 1339 |         tmax = max(t)
 | 
|---|
| 1340 |         if axlim is not None:
 | 
|---|
| 1341 |             tmin = min(tmin, min(axlim))
 | 
|---|
| 1342 |             tmax = max(tmax, max(axlim))
 | 
|---|
| 1343 |         tdel = tmax - tmin # interval in day
 | 
|---|
| 1344 |         dstr = dates[0].strftime('%Y/%m/%d')
 | 
|---|
| 1345 |         if tdel > 365.0: # >1year (also the case for single or very small time range)
 | 
|---|
| 1346 |             majloc = YearLocator()
 | 
|---|
| 1347 |             minloc = MonthLocator(range(1,12,6))
 | 
|---|
| 1348 |             timefmt = DateFormatter('%Y/%m/%d')
 | 
|---|
| 1349 |         elif tdel > 1.0: # >1day
 | 
|---|
| 1350 |             dstr2 = dates[len(dates)-1].strftime('%Y/%m/%d')
 | 
|---|
| 1351 |             dstr = dstr + " - " + dstr2
 | 
|---|
| 1352 |             majloc = DayLocator()
 | 
|---|
| 1353 |             minloc = HourLocator(range(0,23,12))
 | 
|---|
| 1354 |             timefmt = DateFormatter("%b%d")
 | 
|---|
| 1355 |         elif tdel > 24./60.: # 9.6h - 1day
 | 
|---|
| 1356 |             timefmt = DateFormatter('%H:%M')
 | 
|---|
| 1357 |             majloc = HourLocator()
 | 
|---|
| 1358 |             minloc = MinuteLocator(range(0,60,30))
 | 
|---|
| 1359 |         elif tdel > 2./24.: # 2h-9.6h
 | 
|---|
| 1360 |             timefmt = DateFormatter('%H:%M')
 | 
|---|
| 1361 |             majloc = HourLocator()
 | 
|---|
| 1362 |             minloc = MinuteLocator(range(0,60,10))
 | 
|---|
| 1363 |         elif tdel> 10./24./60.: # 10min-2h
 | 
|---|
| 1364 |             timefmt = DateFormatter('%H:%M')
 | 
|---|
| 1365 |             majloc = MinuteLocator(range(0,60,10))
 | 
|---|
| 1366 |             minloc = MinuteLocator()
 | 
|---|
| 1367 |         else: # <10min
 | 
|---|
| 1368 |             timefmt = DateFormatter('%H:%M')
 | 
|---|
| 1369 |             majloc = MinuteLocator()
 | 
|---|
| 1370 |             minloc = SecondLocator(30)
 | 
|---|
| 1371 |         return (dstr, timefmt, majloc, minloc)
 | 
|---|
| 1372 | 
 | 
|---|
| 1373 |     def plotazel(self, scan=None, outfile=None):
 | 
|---|
| 1374 |         """
 | 
|---|
| 1375 |         plot azimuth and elevation versus time of a scantable
 | 
|---|
| 1376 |         """
 | 
|---|
| 1377 |         self._plotmode = "azel"
 | 
|---|
| 1378 |         visible = rcParams['plotter.gui']
 | 
|---|
| 1379 |         from matplotlib import pylab as PL
 | 
|---|
| 1380 |         from pytz import timezone
 | 
|---|
| 1381 |         from matplotlib.ticker import MultipleLocator
 | 
|---|
| 1382 |         from numpy import array, pi, ma
 | 
|---|
| 1383 |         if self._plotter and (PL.gcf() == self._plotter.figure):
 | 
|---|
| 1384 |             # the current figure is ASAP plotter. Use mpl plotter
 | 
|---|
| 1385 |             figids = PL.get_fignums()
 | 
|---|
| 1386 |             PL.figure(max(figids[-1],1))
 | 
|---|
| 1387 | 
 | 
|---|
| 1388 |         if not visible or not self._visible:
 | 
|---|
| 1389 |             PL.ioff()
 | 
|---|
| 1390 |             from matplotlib.backends.backend_agg import FigureCanvasAgg
 | 
|---|
| 1391 |             PL.gcf().canvas.switch_backends(FigureCanvasAgg)
 | 
|---|
| 1392 |         self._data = scan
 | 
|---|
| 1393 |         dates = self._data.get_time(asdatetime=True)
 | 
|---|
| 1394 |         # for flag handling
 | 
|---|
| 1395 |         mask = [ self._data._is_all_chan_flagged(i) for i in range(self._data.nrow())]
 | 
|---|
| 1396 |         t = PL.date2num(dates)
 | 
|---|
| 1397 |         tz = timezone('UTC')
 | 
|---|
| 1398 |         PL.cla()
 | 
|---|
| 1399 |         PL.ioff()
 | 
|---|
| 1400 |         PL.clf()
 | 
|---|
| 1401 |         # Adjust subplot margins
 | 
|---|
| 1402 |         if not self._margins or len(self._margins) != 6:
 | 
|---|
| 1403 |             self.set_margin(refresh=False)
 | 
|---|
| 1404 |         lef, bot, rig, top, wsp, hsp = self._margins
 | 
|---|
| 1405 |         PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
 | 
|---|
| 1406 |                                  wspace=wsp,hspace=hsp)
 | 
|---|
| 1407 | 
 | 
|---|
| 1408 |         tdel = max(t) - min(t) # interval in day
 | 
|---|
| 1409 |         ax = PL.subplot(2,1,1)
 | 
|---|
| 1410 |         el = ma.masked_array(array(self._data.get_elevation())*180./pi, mask)
 | 
|---|
| 1411 |         PL.ylabel('El [deg.]')
 | 
|---|
| 1412 |         (dstr, timefmt, majloc, minloc) = self._get_date_axis_setup(dates)
 | 
|---|
| 1413 |         
 | 
|---|
| 1414 |         PL.title(dstr)
 | 
|---|
| 1415 |         if tdel == 0.0:
 | 
|---|
| 1416 |             th = (t - PL.floor(t))*24.0
 | 
|---|
| 1417 |             PL.plot(th,el,'o',markersize=2, markerfacecolor='b', markeredgecolor='b')
 | 
|---|
| 1418 |         else:
 | 
|---|
| 1419 |             PL.plot_date(t,el,'o', markersize=2, markerfacecolor='b', markeredgecolor='b',tz=tz)
 | 
|---|
| 1420 |             #ax.xaxis.set_major_formatter(timefmt)
 | 
|---|
| 1421 |             #ax.xaxis.set_major_locator(majloc)
 | 
|---|
| 1422 |             #ax.xaxis.set_minor_locator(minloc)
 | 
|---|
| 1423 |         ax.yaxis.grid(True)
 | 
|---|
| 1424 |         ax.set_ylim(0,90)
 | 
|---|
| 1425 |         #yloc = MultipleLocator(30)
 | 
|---|
| 1426 |         #ax.yaxis.set_major_locator(yloc)
 | 
|---|
| 1427 |         if tdel > 1.0:
 | 
|---|
| 1428 |             labels = ax.get_xticklabels()
 | 
|---|
| 1429 |         #    PL.setp(labels, fontsize=10, rotation=45)
 | 
|---|
| 1430 |             PL.setp(labels, fontsize=10)
 | 
|---|
| 1431 | 
 | 
|---|
| 1432 |         # Az plot
 | 
|---|
| 1433 |         az = ma.masked_array(array(self._data.get_azimuth())*180./pi, mask)
 | 
|---|
| 1434 |         if min(az) < 0:
 | 
|---|
| 1435 |             for irow in range(len(az)):
 | 
|---|
| 1436 |                 if az[irow] < 0: az[irow] += 360.0
 | 
|---|
| 1437 | 
 | 
|---|
| 1438 |         ax2 = PL.subplot(2,1,2)
 | 
|---|
| 1439 |         #PL.xlabel('Time (UT [hour])')
 | 
|---|
| 1440 |         PL.ylabel('Az [deg.]')
 | 
|---|
| 1441 |         if tdel == 0.0:
 | 
|---|
| 1442 |             PL.plot(th,az,'o',markersize=2, markeredgecolor='b',markerfacecolor='b')
 | 
|---|
| 1443 |         else:
 | 
|---|
| 1444 |             PL.plot_date(t,az,'o', markersize=2,markeredgecolor='b',markerfacecolor='b',tz=tz)
 | 
|---|
| 1445 |             #ax2.xaxis.set_major_formatter(timefmt)
 | 
|---|
| 1446 |             #ax2.xaxis.set_major_locator(majloc)
 | 
|---|
| 1447 |             #ax2.xaxis.set_minor_locator(minloc)
 | 
|---|
| 1448 |         ax2.set_ylim(0,360)
 | 
|---|
| 1449 |         ax2.yaxis.grid(True)
 | 
|---|
| 1450 |         #hfmt = DateFormatter('%H')
 | 
|---|
| 1451 |         #hloc = HourLocator()
 | 
|---|
| 1452 |         #yloc = MultipleLocator(60)
 | 
|---|
| 1453 |         #ax2.yaxis.set_major_locator(yloc)
 | 
|---|
| 1454 |         if tdel > 1.0:
 | 
|---|
| 1455 |             labels = ax2.get_xticklabels()
 | 
|---|
| 1456 |             PL.setp(labels, fontsize=10)
 | 
|---|
| 1457 |         #    PL.xlabel('Time (UT [day])')
 | 
|---|
| 1458 |         #else:
 | 
|---|
| 1459 |         #    PL.xlabel('Time (UT [hour])')
 | 
|---|
| 1460 |         PL.xlabel('Time (UT)')
 | 
|---|
| 1461 | 
 | 
|---|
| 1462 |         PL.ion()
 | 
|---|
| 1463 |         PL.draw()
 | 
|---|
| 1464 |         if matplotlib.get_backend() == 'Qt4Agg': PL.gcf().show()
 | 
|---|
| 1465 |         if (outfile is not None):
 | 
|---|
| 1466 |            PL.savefig(outfile)
 | 
|---|
| 1467 | 
 | 
|---|
| 1468 | 
 | 
|---|
| 1469 |     def plotpointing2(self, scan=None, colorby='', showline=False, projection=''):
 | 
|---|
| 1470 |         """
 | 
|---|
| 1471 |         plot telescope pointings
 | 
|---|
| 1472 |         Parameters:
 | 
|---|
| 1473 |             scan    : input scantable instance
 | 
|---|
| 1474 |             colorby : change color by either
 | 
|---|
| 1475 |                       'type'(source type)|'scan'|'if'|'pol'|'beam'
 | 
|---|
| 1476 |             showline : show dotted line
 | 
|---|
| 1477 |             projection : projection type either
 | 
|---|
| 1478 |                          ''(no projection [deg])|'coord'(not implemented)
 | 
|---|
| 1479 |         """
 | 
|---|
| 1480 |         self._plotmode = "pointing"
 | 
|---|
| 1481 |         from numpy import array, pi, ma
 | 
|---|
| 1482 |         from asap import scantable
 | 
|---|
| 1483 |         # check for scantable
 | 
|---|
| 1484 |         if isinstance(scan, scantable):
 | 
|---|
| 1485 |             if self._data is not None:
 | 
|---|
| 1486 |                 if scan != self._data:
 | 
|---|
| 1487 |                     self._data = scan
 | 
|---|
| 1488 |                     # reset
 | 
|---|
| 1489 |                     self._reset()
 | 
|---|
| 1490 |             else:
 | 
|---|
| 1491 |                 self._data = scan
 | 
|---|
| 1492 |                 self._reset()
 | 
|---|
| 1493 |         if not self._data:
 | 
|---|
| 1494 |             msg = "Input is not a scantable"
 | 
|---|
| 1495 |             raise TypeError(msg)
 | 
|---|
| 1496 |         # check for color mode
 | 
|---|
| 1497 |         validtypes=['type','scan','if','pol', 'beam']
 | 
|---|
| 1498 |         stype = None
 | 
|---|
| 1499 |         if (colorby in validtypes):
 | 
|---|
| 1500 |             stype = colorby[0]
 | 
|---|
| 1501 |         elif len(colorby) > 0:
 | 
|---|
| 1502 |             msg = "Invalid choice of 'colorby' (choices: %s)" % str(validtypes)
 | 
|---|
| 1503 |             raise ValueError(msg)
 | 
|---|
| 1504 |         self._assert_plotter(action="reload")
 | 
|---|
| 1505 |         self._plotter.hold()
 | 
|---|
| 1506 |         self._reset_counter()
 | 
|---|
| 1507 |         if self.casabar_exists():
 | 
|---|
| 1508 |             self._plotter.figmgr.casabar.disable_button()
 | 
|---|
| 1509 |         # for now, only one plot
 | 
|---|
| 1510 |         self._plotter.set_panels(rows=1,cols=1)
 | 
|---|
| 1511 |         # first panel
 | 
|---|
| 1512 |         self._plotter.subplot(0)
 | 
|---|
| 1513 |         # first color and linestyles
 | 
|---|
| 1514 |         self._plotter.palette(0)
 | 
|---|
| 1515 |         self.gca().set_aspect('equal')
 | 
|---|
| 1516 |         basesel = scan.get_selection()
 | 
|---|
| 1517 |         attrback = self._plotter.get_line()
 | 
|---|
| 1518 |         marker = "o"
 | 
|---|
| 1519 |         if showline:
 | 
|---|
| 1520 |             basesel.set_order(["TIME"])
 | 
|---|
| 1521 |             scan.set_selection(basesel)
 | 
|---|
| 1522 |             if not (stype in ["t", "s"]):
 | 
|---|
| 1523 |                 marker += ":"
 | 
|---|
| 1524 |         self._plotter.set_line(markersize=3, markeredgewidth=0)
 | 
|---|
| 1525 | 
 | 
|---|
| 1526 |         if not stype:
 | 
|---|
| 1527 |             selIds = [""] # cheating
 | 
|---|
| 1528 |             sellab = "all points"
 | 
|---|
| 1529 |         elif stype == 't':
 | 
|---|
| 1530 |             selIds = range(15)
 | 
|---|
| 1531 |             sellab = "src type "
 | 
|---|
| 1532 |         else:
 | 
|---|
| 1533 |             selIds = getattr(self._data,'get'+colorby+'nos')()
 | 
|---|
| 1534 |             sellab = colorby.upper()
 | 
|---|
| 1535 |         selFunc = "set_"+colorby+"s"
 | 
|---|
| 1536 |         for idx in selIds:
 | 
|---|
| 1537 |             sel = selector() + basesel
 | 
|---|
| 1538 |             if stype:
 | 
|---|
| 1539 |                 bid = getattr(basesel,'get_'+colorby+"s")()
 | 
|---|
| 1540 |                 if (len(bid) > 0) and (not idx in bid):
 | 
|---|
| 1541 |                     # base selection doesn't contain idx
 | 
|---|
| 1542 |                     # Note summation of selector is logical sum if 
 | 
|---|
| 1543 |                     continue
 | 
|---|
| 1544 |                 getattr(sel, selFunc)([idx])
 | 
|---|
| 1545 |             if not sel.is_empty():
 | 
|---|
| 1546 |                 try:
 | 
|---|
| 1547 |                     self._data.set_selection(sel)
 | 
|---|
| 1548 |                 except RuntimeError, instance:
 | 
|---|
| 1549 |                     if stype == 't' and str(instance).startswith("Selection contains no data."):
 | 
|---|
| 1550 |                         continue
 | 
|---|
| 1551 |                     else:
 | 
|---|
| 1552 |                         self._data.set_selection(basesel)
 | 
|---|
| 1553 |                         raise RuntimeError, instance
 | 
|---|
| 1554 |             if self._data.nrow() == 0:
 | 
|---|
| 1555 |                 self._data.set_selection(basesel)
 | 
|---|
| 1556 |                 continue
 | 
|---|
| 1557 |             #print "Plotting direction of %s = %s" % (colorby, str(idx))
 | 
|---|
| 1558 |             # getting data to plot
 | 
|---|
| 1559 |             dir = array(self._data.get_directionval()).transpose()
 | 
|---|
| 1560 |             # for flag handling
 | 
|---|
| 1561 |             mask = [ self._data._is_all_chan_flagged(i) for i in range(self._data.nrow())]
 | 
|---|
| 1562 |             ra = dir[0]*180./pi
 | 
|---|
| 1563 |             dec = ma.masked_array(dir[1]*180./pi, mask)
 | 
|---|
| 1564 |             # actual plot
 | 
|---|
| 1565 |             self._plotter.set_line(label=(sellab+str(idx)))
 | 
|---|
| 1566 |             self._plotter.plot(ra,dec,marker)
 | 
|---|
| 1567 | 
 | 
|---|
| 1568 |         # restore original selection
 | 
|---|
| 1569 |         self._data.set_selection(basesel)
 | 
|---|
| 1570 |         # need to plot scan pattern explicitly
 | 
|---|
| 1571 |         if showline and (stype in ["t", "s"]):
 | 
|---|
| 1572 |             dir = array(self._data.get_directionval()).transpose()
 | 
|---|
| 1573 |             ra = dir[0]*180./pi
 | 
|---|
| 1574 |             dec = dir[1]*180./pi
 | 
|---|
| 1575 |             self._plotter.set_line(label="scan pattern")
 | 
|---|
| 1576 |             self._plotter.plot(ra,dec,":")
 | 
|---|
| 1577 |             # set color for only this line
 | 
|---|
| 1578 |             self._plotter.lines[-1][0].set_color("gray")
 | 
|---|
| 1579 | 
 | 
|---|
| 1580 |         xlab = 'RA [deg.]'
 | 
|---|
| 1581 |         ylab = 'Declination [deg.]'
 | 
|---|
| 1582 |         self._plotter.set_axes('xlabel', xlab)
 | 
|---|
| 1583 |         self._plotter.set_axes('ylabel', ylab)
 | 
|---|
| 1584 |         self._plotter.set_axes('title', 'Telescope pointings')
 | 
|---|
| 1585 |         if stype: self._plotter.legend(self._legendloc)
 | 
|---|
| 1586 |         else: self._plotter.legend(None)
 | 
|---|
| 1587 |         # reverse x-axis
 | 
|---|
| 1588 |         xmin, xmax = self.gca().get_xlim()
 | 
|---|
| 1589 |         ymin, ymax = self.gca().get_ylim()
 | 
|---|
| 1590 |         # expand plotrange if xmin==xmax or ymin==ymax
 | 
|---|
| 1591 |         if abs(ymax-ymin) < 1.e-3: #~4arcsec
 | 
|---|
| 1592 |             delx = 0.5*abs(xmax - xmin)
 | 
|---|
| 1593 |             if delx < 5.e-4:
 | 
|---|
| 1594 |                 dxy = 5.e-4 #~2arcsec
 | 
|---|
| 1595 |                 (ymin, ymax) = (ymin-dxy, ymax+dxy)
 | 
|---|
| 1596 |                 (xmin, xmax) = (xmin-dxy, xmax+dxy)
 | 
|---|
| 1597 |             (ymin, ymax) = (ymin-delx, ymax+delx)
 | 
|---|
| 1598 |         elif abs(xmax-xmin) < 1.e-3:
 | 
|---|
| 1599 |             dely = 0.5*abs(ymax - ymin)
 | 
|---|
| 1600 |             (xmin, xmax) = (xmin-dely, xmax+dely)
 | 
|---|
| 1601 |         self._plotter.set_limits(xlim=[xmax,xmin], ylim=[ymin, ymax])
 | 
|---|
| 1602 | 
 | 
|---|
| 1603 |         self._plotter.release()
 | 
|---|
| 1604 |         self._plotter.show(hardrefresh=False)
 | 
|---|
| 1605 |         # reset line settings
 | 
|---|
| 1606 |         self._plotter.set_line(**attrback)
 | 
|---|
| 1607 |         return
 | 
|---|
| 1608 | 
 | 
|---|
| 1609 |     def plotpointing(self, scan=None, outfile=None):
 | 
|---|
| 1610 |         """
 | 
|---|
| 1611 |         plot telescope pointings
 | 
|---|
| 1612 |         """
 | 
|---|
| 1613 |         visible = rcParams['plotter.gui']
 | 
|---|
| 1614 |         from matplotlib import pylab as PL
 | 
|---|
| 1615 |         from numpy import array, pi
 | 
|---|
| 1616 |         if self._plotter and (PL.gcf() == self._plotter.figure):
 | 
|---|
| 1617 |             # the current figure is ASAP plotter. Use mpl plotter
 | 
|---|
| 1618 |             figids = PL.get_fignums()
 | 
|---|
| 1619 |             PL.figure(max(figids[-1],1))
 | 
|---|
| 1620 | 
 | 
|---|
| 1621 |         if not visible or not self._visible:
 | 
|---|
| 1622 |             PL.ioff()
 | 
|---|
| 1623 |             from matplotlib.backends.backend_agg import FigureCanvasAgg
 | 
|---|
| 1624 |             PL.gcf().canvas.switch_backends(FigureCanvasAgg)
 | 
|---|
| 1625 |         self._data = scan
 | 
|---|
| 1626 |         dir = array(self._data.get_directionval()).transpose()
 | 
|---|
| 1627 |         ra = dir[0]*180./pi
 | 
|---|
| 1628 |         dec = dir[1]*180./pi
 | 
|---|
| 1629 |         PL.cla()
 | 
|---|
| 1630 |         #PL.ioff()
 | 
|---|
| 1631 |         PL.clf()
 | 
|---|
| 1632 |         # Adjust subplot margins
 | 
|---|
| 1633 |         if not self._margins or len(self._margins) != 6:
 | 
|---|
| 1634 |             self.set_margin(refresh=False)
 | 
|---|
| 1635 |         lef, bot, rig, top, wsp, hsp = self._margins
 | 
|---|
| 1636 |         PL.gcf().subplots_adjust(left=lef,bottom=bot,right=rig,top=top,
 | 
|---|
| 1637 |                                  wspace=wsp,hspace=hsp)
 | 
|---|
| 1638 |         ax = PL.gca()
 | 
|---|
| 1639 |         #ax = PL.axes([0.1,0.1,0.8,0.8])
 | 
|---|
| 1640 |         #ax = PL.axes([0.1,0.1,0.8,0.8])
 | 
|---|
| 1641 |         ax.set_aspect('equal')
 | 
|---|
| 1642 |         PL.plot(ra, dec, 'b,')
 | 
|---|
| 1643 |         PL.xlabel('RA [deg.]')
 | 
|---|
| 1644 |         PL.ylabel('Declination [deg.]')
 | 
|---|
| 1645 |         PL.title('Telescope pointings')
 | 
|---|
| 1646 |         [xmin,xmax,ymin,ymax] = PL.axis()
 | 
|---|
| 1647 |         PL.axis([xmax,xmin,ymin,ymax])
 | 
|---|
| 1648 |         PL.ion()
 | 
|---|
| 1649 |         PL.draw()
 | 
|---|
| 1650 |         if matplotlib.get_backend() == 'Qt4Agg': PL.gcf().show()
 | 
|---|
| 1651 |         if (outfile is not None):
 | 
|---|
| 1652 |            PL.savefig(outfile)
 | 
|---|
| 1653 | 
 | 
|---|
| 1654 |     # plot total power data
 | 
|---|
| 1655 |     # plotting in time is not yet implemented..
 | 
|---|
| 1656 |     @asaplog_post_dec
 | 
|---|
| 1657 |     def plottp(self, scan=None, colorby=''):
 | 
|---|
| 1658 |         """
 | 
|---|
| 1659 |         Plot averaged spectra (total power) in time or in row ID (colorby='')
 | 
|---|
| 1660 |         Parameters:
 | 
|---|
| 1661 |             scan    : input scantable instance
 | 
|---|
| 1662 |             colorby : change color by either
 | 
|---|
| 1663 |                       'type'(source type)|'scan'|'if'|'pol'|'beam'|''
 | 
|---|
| 1664 |         """
 | 
|---|
| 1665 |         self._plotmode = "totalpower"
 | 
|---|
| 1666 |         from asap import scantable
 | 
|---|
| 1667 |         if not self._data and not scan:
 | 
|---|
| 1668 |             msg = "Input is not a scantable"
 | 
|---|
| 1669 |             raise TypeError(msg)
 | 
|---|
| 1670 |         if isinstance(scan, scantable):
 | 
|---|
| 1671 |             if self._data is not None:
 | 
|---|
| 1672 |                 if scan != self._data:
 | 
|---|
| 1673 |                     self._data = scan
 | 
|---|
| 1674 |                     # reset
 | 
|---|
| 1675 |                     self._reset()
 | 
|---|
| 1676 |             else:
 | 
|---|
| 1677 |                 self._data = scan
 | 
|---|
| 1678 |                 self._reset()
 | 
|---|
| 1679 |         # ranges become invalid when abcissa changes?
 | 
|---|
| 1680 |         #if self._abcunit and self._abcunit != self._data.get_unit():
 | 
|---|
| 1681 |         #    self._minmaxx = None
 | 
|---|
| 1682 |         #    self._minmaxy = None
 | 
|---|
| 1683 |         #    self._abcunit = self._data.get_unit()
 | 
|---|
| 1684 | 
 | 
|---|
| 1685 |         self._assert_plotter(action="reload")
 | 
|---|
| 1686 |         self._plotter.hold()
 | 
|---|
| 1687 |         self._plotter.clear()
 | 
|---|
| 1688 |         # Adjust subplot margins
 | 
|---|
| 1689 |         if not self._margins or len(self._margins) !=6:
 | 
|---|
| 1690 |             self.set_margin(refresh=False)
 | 
|---|
| 1691 |         lef, bot, rig, top, wsp, hsp = self._margins
 | 
|---|
| 1692 |         self._plotter.figure.subplots_adjust(
 | 
|---|
| 1693 |             left=lef,bottom=bot,right=rig,top=top,wspace=wsp,hspace=hsp)
 | 
|---|
| 1694 |         if self.casabar_exists(): self._plotter.figmgr.casabar.disable_button()
 | 
|---|
| 1695 |         if len(colorby) == 0:
 | 
|---|
| 1696 |             self._plottp(self._data)
 | 
|---|
| 1697 |         else:
 | 
|---|
| 1698 |             self._plottp_in_time(self._data,colorby)
 | 
|---|
| 1699 |         if self._minmaxy is not None:
 | 
|---|
| 1700 |             self._plotter.set_limits(ylim=self._minmaxy)
 | 
|---|
| 1701 |         self._plotter.release()
 | 
|---|
| 1702 |         self._plotter.tidy()
 | 
|---|
| 1703 |         self._plotter.show(hardrefresh=False)
 | 
|---|
| 1704 |         return
 | 
|---|
| 1705 | 
 | 
|---|
| 1706 |     def _plottp_in_time(self,scan,colorby):
 | 
|---|
| 1707 |         """
 | 
|---|
| 1708 |         private method for plotting total power data in time
 | 
|---|
| 1709 |         Parameters:
 | 
|---|
| 1710 |             scan    : input scantable instance
 | 
|---|
| 1711 |             colorby : change color by either
 | 
|---|
| 1712 |                       'type'(source type)|'scan'|'if'|'pol'|'beam'
 | 
|---|
| 1713 |         """
 | 
|---|
| 1714 |         from numpy import ma, array, arange, logical_not
 | 
|---|
| 1715 |         r=0
 | 
|---|
| 1716 |         nr = scan.nrow()
 | 
|---|
| 1717 |         a0,b0 = -1,-1
 | 
|---|
| 1718 |         allxlim = []
 | 
|---|
| 1719 |         allylim = []
 | 
|---|
| 1720 |         y=[]
 | 
|---|
| 1721 |         self._plotter.set_panels()
 | 
|---|
| 1722 |         self._plotter.palette(0)
 | 
|---|
| 1723 |         # check of overlay settings
 | 
|---|
| 1724 |         time_types = ['type','scan'] # time dependent meta-data
 | 
|---|
| 1725 |         misc_types = ['if','pol','beam'] # time independent meta-data
 | 
|---|
| 1726 |         validtypes=time_types + misc_types
 | 
|---|
| 1727 |         stype = None
 | 
|---|
| 1728 |         col_msg = "Invalid choice of 'colorby' (choices: %s)" % str(validtypes)
 | 
|---|
| 1729 |         colorby = colorby.lower()
 | 
|---|
| 1730 |         if (colorby in validtypes):
 | 
|---|
| 1731 |             stype = colorby[0]
 | 
|---|
| 1732 |         elif len(colorby) > 0:
 | 
|---|
| 1733 |             raise ValueError(col_msg)
 | 
|---|
| 1734 |         if not stype:
 | 
|---|
| 1735 |             raise ValueError(col_msg)
 | 
|---|
| 1736 |         # Selection and sort order
 | 
|---|
| 1737 |         basesel = scan.get_selection()
 | 
|---|
| 1738 |         if colorby in misc_types: misc_types.pop(misc_types.index(colorby))
 | 
|---|
| 1739 |         sel_lbl = ""
 | 
|---|
| 1740 |         for meta in misc_types:
 | 
|---|
| 1741 |             idx = getattr(scan,'get'+meta+'nos')()
 | 
|---|
| 1742 |             if len(idx) > 1: getattr(basesel, 'set_'+meta+'s')([idx[0]])
 | 
|---|
| 1743 |             sel_lbl += ("%s%d, " % (meta.upper(), idx[0]))
 | 
|---|
| 1744 |         sel_lbl = sel_lbl.rstrip(', ')
 | 
|---|
| 1745 |         scan.set_selection(basesel)
 | 
|---|
| 1746 |         if len(sel_lbl) > 0:
 | 
|---|
| 1747 |             asaplog.push("Selection contains multiple IFs/Pols/Beams. Plotting the first ones: %s" % sel_lbl)
 | 
|---|
| 1748 |             asaplog.post("WARN")
 | 
|---|
| 1749 |         if stype == 't':
 | 
|---|
| 1750 |             selIds = range(15)
 | 
|---|
| 1751 |             sellab = "src type "
 | 
|---|
| 1752 |         else:
 | 
|---|
| 1753 |             selIds = getattr(scan,'get'+colorby+'nos')()
 | 
|---|
| 1754 |             sellab = colorby.upper()
 | 
|---|
| 1755 |         selFunc = "set_"+colorby+"s"
 | 
|---|
| 1756 |         basesel.set_order(["TIME"])
 | 
|---|
| 1757 |         # define axes labels
 | 
|---|
| 1758 |         xlab = self._abcissa or 'Time (UTC)'
 | 
|---|
| 1759 |         ylab = self._ordinate or scan._get_ordinate_label()
 | 
|---|
| 1760 |         self._plotter.set_axes('xlabel',xlab)
 | 
|---|
| 1761 |         self._plotter.set_axes('ylabel',ylab)
 | 
|---|
| 1762 |         # define the panel title
 | 
|---|
| 1763 |         if len(sel_lbl) > 0: lbl = sel_lbl
 | 
|---|
| 1764 |         else: lbl = self._get_label(scan, r, 's', self._title)
 | 
|---|
| 1765 |         if isinstance(lbl, list) or isinstance(lbl, tuple):
 | 
|---|
| 1766 |             # get default label
 | 
|---|
| 1767 |             lbl = self._get_label(scan, r, self._panelling, None)
 | 
|---|
| 1768 |         self._plotter.set_axes('title',lbl)
 | 
|---|
| 1769 |         # linestyle
 | 
|---|
| 1770 |         lstyle = '' if colorby in time_types else ':'
 | 
|---|
| 1771 |         alldates = []
 | 
|---|
| 1772 |         for idx in selIds:
 | 
|---|
| 1773 |             sel = selector() + basesel
 | 
|---|
| 1774 |             bid = getattr(basesel,'get_'+colorby+"s")()
 | 
|---|
| 1775 |             if (len(bid) > 0) and (not idx in bid):
 | 
|---|
| 1776 |                 # base selection doesn't contain idx
 | 
|---|
| 1777 |                 # Note summation of selector is logical sum if 
 | 
|---|
| 1778 |                 continue
 | 
|---|
| 1779 |             getattr(sel, selFunc)([idx])
 | 
|---|
| 1780 |             if not sel.is_empty():
 | 
|---|
| 1781 |                 try:
 | 
|---|
| 1782 |                     scan.set_selection(sel)
 | 
|---|
| 1783 |                 except RuntimeError, instance:
 | 
|---|
| 1784 |                     if stype == 't' and str(instance).startswith("Selection contains no data."):
 | 
|---|
| 1785 |                         continue
 | 
|---|
| 1786 |                     else:
 | 
|---|
| 1787 |                         scan.set_selection(basesel)
 | 
|---|
| 1788 |                         raise RuntimeError, instance
 | 
|---|
| 1789 |             if scan.nrow() == 0:
 | 
|---|
| 1790 |                 scan.set_selection(basesel)
 | 
|---|
| 1791 |                 continue
 | 
|---|
| 1792 |             y=array(scan._get_column(scan._getspectrum,-1))
 | 
|---|
| 1793 |             m = array(scan._get_column(scan._getmask,-1))
 | 
|---|
| 1794 |             y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
 | 
|---|
| 1795 |             # try to handle spectral data somewhat...
 | 
|---|
| 1796 |             try:
 | 
|---|
| 1797 |                 l,m = y.shape
 | 
|---|
| 1798 |             except ValueError, e:
 | 
|---|
| 1799 |                 raise ValueError(str(e)+" This error usually occurs when you select multiple spws with different number of channels. Try selecting single spw and retry.")
 | 
|---|
| 1800 |             if m > 1:
 | 
|---|
| 1801 |                 y=y.mean(axis=1)
 | 
|---|
| 1802 |             # flag handling
 | 
|---|
| 1803 |             m = [ scan._is_all_chan_flagged(i) for i in range(scan.nrow()) ]
 | 
|---|
| 1804 |             y = ma.masked_array(y,mask=m)
 | 
|---|
| 1805 |             if len(y) == 0: continue
 | 
|---|
| 1806 |             # line label
 | 
|---|
| 1807 |             llbl=sellab+str(idx)
 | 
|---|
| 1808 |             from matplotlib.dates import date2num
 | 
|---|
| 1809 |             from pytz import timezone
 | 
|---|
| 1810 |             dates = self._data.get_time(asdatetime=True)
 | 
|---|
| 1811 |             alldates += list(dates)
 | 
|---|
| 1812 |             x = date2num(dates)
 | 
|---|
| 1813 |             tz = timezone('UTC')
 | 
|---|
| 1814 |             # get color
 | 
|---|
| 1815 |             lc = self._plotter.colormap[self._plotter.color]
 | 
|---|
| 1816 |             self._plotter.palette( (self._plotter.color+1) % len(self._plotter.colormap) )
 | 
|---|
| 1817 |             # actual plotting
 | 
|---|
| 1818 |             self._plotter.axes.plot_date(x,y,tz=tz,label=llbl,linestyle=lstyle,color=lc,
 | 
|---|
| 1819 |                                          marker='o',markersize=3,markeredgewidth=0)
 | 
|---|
| 1820 | 
 | 
|---|
| 1821 |         # legend and axis formatting
 | 
|---|
| 1822 |         ax = self.gca()
 | 
|---|
| 1823 |         (dstr, timefmt, majloc, minloc) = self._get_date_axis_setup(alldates, ax.get_xlim())
 | 
|---|
| 1824 |         ax.xaxis.set_major_formatter(timefmt)
 | 
|---|
| 1825 |         ax.xaxis.set_major_locator(majloc)
 | 
|---|
| 1826 |         ax.xaxis.set_minor_locator(minloc)
 | 
|---|
| 1827 |         self._plotter.axes.legend(loc=self._legendloc)
 | 
|---|
| 1828 | 
 | 
|---|
| 1829 |     def _plottp(self,scan):
 | 
|---|
| 1830 |         """
 | 
|---|
| 1831 |         private method for plotting total power data
 | 
|---|
| 1832 |         """
 | 
|---|
| 1833 |         from numpy import ma, array, arange, logical_not
 | 
|---|
| 1834 |         r=0
 | 
|---|
| 1835 |         nr = scan.nrow()
 | 
|---|
| 1836 |         a0,b0 = -1,-1
 | 
|---|
| 1837 |         allxlim = []
 | 
|---|
| 1838 |         allylim = []
 | 
|---|
| 1839 |         y=[]
 | 
|---|
| 1840 |         self._plotter.set_panels()
 | 
|---|
| 1841 |         self._plotter.palette(0)
 | 
|---|
| 1842 |         #title
 | 
|---|
| 1843 |         #xlab = self._abcissa and self._abcissa[panelcount] \
 | 
|---|
| 1844 |         #       or scan._getabcissalabel()
 | 
|---|
| 1845 |         #ylab = self._ordinate and self._ordinate[panelcount] \
 | 
|---|
| 1846 |         #       or scan._get_ordinate_label()
 | 
|---|
| 1847 |         xlab = self._abcissa or 'row number' #or Time
 | 
|---|
| 1848 |         ylab = self._ordinate or scan._get_ordinate_label()
 | 
|---|
| 1849 |         self._plotter.set_axes('xlabel',xlab)
 | 
|---|
| 1850 |         self._plotter.set_axes('ylabel',ylab)
 | 
|---|
| 1851 |         lbl = self._get_label(scan, r, 's', self._title)
 | 
|---|
| 1852 |         if isinstance(lbl, list) or isinstance(lbl, tuple):
 | 
|---|
| 1853 |         #    if 0 <= panelcount < len(lbl):
 | 
|---|
| 1854 |         #        lbl = lbl[panelcount]
 | 
|---|
| 1855 |         #    else:
 | 
|---|
| 1856 |                 # get default label
 | 
|---|
| 1857 |              lbl = self._get_label(scan, r, self._panelling, None)
 | 
|---|
| 1858 |         self._plotter.set_axes('title',lbl)
 | 
|---|
| 1859 |         y=array(scan._get_column(scan._getspectrum,-1))
 | 
|---|
| 1860 |         m = array(scan._get_column(scan._getmask,-1))
 | 
|---|
| 1861 |         y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
 | 
|---|
| 1862 |         x = arange(len(y))
 | 
|---|
| 1863 |         # try to handle spectral data somewhat...
 | 
|---|
| 1864 |         try:
 | 
|---|
| 1865 |             l,m = y.shape
 | 
|---|
| 1866 |         except ValueError, e:
 | 
|---|
| 1867 |                 raise ValueError(str(e)+" This error usually occurs when you select multiple spws with different number of channels. Try selecting single spw and retry.")
 | 
|---|
| 1868 |         if m > 1:
 | 
|---|
| 1869 |             y=y.mean(axis=1)
 | 
|---|
| 1870 |         # flag handling
 | 
|---|
| 1871 |         m = [ scan._is_all_chan_flagged(i) for i in range(scan.nrow()) ]
 | 
|---|
| 1872 |         y = ma.masked_array(y,mask=m)
 | 
|---|
| 1873 |         plotit = self._plotter.plot
 | 
|---|
| 1874 |         llbl = self._get_label(scan, r, self._stacking, None)
 | 
|---|
| 1875 |         self._plotter.set_line(label=llbl)
 | 
|---|
| 1876 |         if len(x) > 0:
 | 
|---|
| 1877 |             plotit(x,y)
 | 
|---|
| 1878 | 
 | 
|---|
| 1879 | 
 | 
|---|
| 1880 |     # printing header information
 | 
|---|
| 1881 |     @asaplog_post_dec
 | 
|---|
| 1882 |     def print_header(self, plot=True, fontsize=9, logger=False, selstr='', extrastr=''):
 | 
|---|
| 1883 |         """
 | 
|---|
| 1884 |         print data (scantable) header on the plot and/or logger.
 | 
|---|
| 1885 |         To plot the header on the plot, this method should be called after
 | 
|---|
| 1886 |         plotting spectra by the method, asapplotter.plot.
 | 
|---|
| 1887 |         Parameters:
 | 
|---|
| 1888 |             plot:      whether or not print header info on the plot.
 | 
|---|
| 1889 |             fontsize:  header font size (valid only plot=True)
 | 
|---|
| 1890 |             logger:    whether or not print header info on the logger.
 | 
|---|
| 1891 |             selstr:    additional selection string (not verified)
 | 
|---|
| 1892 |             extrastr:  additional string to print at the beginning (not verified)
 | 
|---|
| 1893 |         """
 | 
|---|
| 1894 |         if not plot and not logger:
 | 
|---|
| 1895 |             return
 | 
|---|
| 1896 |         if not self._data:
 | 
|---|
| 1897 |             raise RuntimeError("No scantable has been set yet.")
 | 
|---|
| 1898 |         # Now header will be printed on plot and/or logger.
 | 
|---|
| 1899 |         # Get header information and format it.
 | 
|---|
| 1900 |         ssum=self._data._list_header()
 | 
|---|
| 1901 |         # Print Observation header to the upper-left corner of plot
 | 
|---|
| 1902 |         headstr=[ssum[0:ssum.find('Obs. Type:')]]
 | 
|---|
| 1903 |         headstr.append(ssum[ssum.find('Obs. Type:'):ssum.find('Flux Unit:')])
 | 
|---|
| 1904 |         if extrastr != '':
 | 
|---|
| 1905 |             headstr[0]=extrastr+'\n'+headstr[0]
 | 
|---|
| 1906 |             self._headtext['extrastr'] = extrastr
 | 
|---|
| 1907 |         if selstr != '':
 | 
|---|
| 1908 |             selstr += '\n'
 | 
|---|
| 1909 |             self._headtext['selstr'] = selstr
 | 
|---|
| 1910 |         #ssel=(selstr+self._data.get_selection().__str__()+self._selection.__str__() or 'none')
 | 
|---|
| 1911 |         curr_selstr = selstr+self._data.get_selection().__str__() or "none"
 | 
|---|
| 1912 |         ssel=(curr_selstr+"\n" +self._selection.__str__())
 | 
|---|
| 1913 |         headstr.append('\n\n***Selections***\n'+ssel.replace('$','\$'))
 | 
|---|
| 1914 | 
 | 
|---|
| 1915 |         if plot:
 | 
|---|
| 1916 |             errmsg = "Can plot header only after the first call to plot()."
 | 
|---|
| 1917 |             self._assert_plotter(action="halt",errmsg=errmsg)
 | 
|---|
| 1918 |             self._plotter.hold()
 | 
|---|
| 1919 |             self._header_plot(headstr,fontsize=fontsize)
 | 
|---|
| 1920 |             #import time
 | 
|---|
| 1921 |             #self._plotter.figure.text(0.99,0.01,
 | 
|---|
| 1922 |             #                time.strftime("%a %d %b %Y  %H:%M:%S %Z"),
 | 
|---|
| 1923 |             #                horizontalalignment='right',
 | 
|---|
| 1924 |             #                verticalalignment='bottom',fontsize=8)
 | 
|---|
| 1925 |             self._plotter.release()
 | 
|---|
| 1926 |         if logger:
 | 
|---|
| 1927 |             selstr = "Selections:    "+ssel
 | 
|---|
| 1928 |             asaplog.push("----------------\n  Plot Summary\n----------------")
 | 
|---|
| 1929 |             asaplog.push(extrastr)
 | 
|---|
| 1930 |             asaplog.push(ssum[0:ssum.find('Selection:')]\
 | 
|---|
| 1931 |                          + selstr)
 | 
|---|
| 1932 |         self._headtext['string'] = headstr
 | 
|---|
| 1933 |         del ssel, ssum, headstr
 | 
|---|
| 1934 | 
 | 
|---|
| 1935 |     def _header_plot(self, texts, fontsize=9):
 | 
|---|
| 1936 |         self._headtext['textobj']=[]
 | 
|---|
| 1937 |         nstcol=len(texts)
 | 
|---|
| 1938 |         for i in range(nstcol):
 | 
|---|
| 1939 |             self._headtext['textobj'].append(
 | 
|---|
| 1940 |                 self._plotter.figure.text(0.03+float(i)/nstcol,0.98,
 | 
|---|
| 1941 |                                           texts[i],
 | 
|---|
| 1942 |                                           horizontalalignment='left',
 | 
|---|
| 1943 |                                           verticalalignment='top',
 | 
|---|
| 1944 |                                           fontsize=fontsize))
 | 
|---|
| 1945 | 
 | 
|---|
| 1946 |     def clear_header(self):
 | 
|---|
| 1947 |         if not self._headtext['textobj']:
 | 
|---|
| 1948 |             asaplog.push("No header has been plotted. Exit without any operation")
 | 
|---|
| 1949 |             asaplog.post("WARN")
 | 
|---|
| 1950 |         elif self._assert_plotter(action="status"):
 | 
|---|
| 1951 |             self._plotter.hold()
 | 
|---|
| 1952 |             for textobj in self._headtext['textobj']:
 | 
|---|
| 1953 |                 #if textobj.get_text() in self._headstring:
 | 
|---|
| 1954 |                 try:
 | 
|---|
| 1955 |                     textobj.remove()
 | 
|---|
| 1956 |                 except NotImplementedError:
 | 
|---|
| 1957 |                     self._plotter.figure.texts.pop(self._plotter.figure.texts.index(textobj))
 | 
|---|
| 1958 |             self._plotter.release()
 | 
|---|
| 1959 |         self._reset_header()
 | 
|---|
| 1960 | 
 | 
|---|
| 1961 |     # plot spectra by pointing
 | 
|---|
| 1962 |     @asaplog_post_dec
 | 
|---|
| 1963 |     def plotgrid(self, scan=None,center="",spacing=[],rows=None,cols=None):
 | 
|---|
| 1964 |         """
 | 
|---|
| 1965 |         Plot spectra based on direction.
 | 
|---|
| 1966 |         
 | 
|---|
| 1967 |         Parameters:
 | 
|---|
| 1968 |             scan:      a scantable to plot
 | 
|---|
| 1969 |             center:    the grid center direction (a string)
 | 
|---|
| 1970 |                        (default) the center of map region
 | 
|---|
| 1971 |                        (example) 'J2000 19h30m00s -25d00m00s'
 | 
|---|
| 1972 |             spacing:   a list of horizontal (R.A.) and vertical (Dec.)
 | 
|---|
| 1973 |                        spacing.
 | 
|---|
| 1974 |                        (default) Calculated by the extent of map region and
 | 
|---|
| 1975 |                        (example) ['1arcmin', '1arcmin']
 | 
|---|
| 1976 |                        the number of rows and cols to cover
 | 
|---|
| 1977 |             rows:      number of panels (grid points) in horizontal direction
 | 
|---|
| 1978 |             cols:      number of panels (grid points) in vertical direction
 | 
|---|
| 1979 | 
 | 
|---|
| 1980 |         Note:
 | 
|---|
| 1981 |         - Only the first IFNO, POLNO, and BEAM in the scantable will be
 | 
|---|
| 1982 |         plotted.
 | 
|---|
| 1983 |         - This method doesn't re-grid and average spectra in scantable. Use
 | 
|---|
| 1984 |         asapgrid module to re-grid spectra before plotting with this method.
 | 
|---|
| 1985 |         Only the first spectrum is plotted in case there are multiple
 | 
|---|
| 1986 |         spectra which belong to a grid.
 | 
|---|
| 1987 |         """
 | 
|---|
| 1988 |         self._plotmode = "grid"
 | 
|---|
| 1989 |         from asap import scantable
 | 
|---|
| 1990 |         from numpy import array, ma, cos
 | 
|---|
| 1991 |         if not self._data and not scan:
 | 
|---|
| 1992 |             msg = "No scantable is specified to plot"
 | 
|---|
| 1993 |             raise TypeError(msg)
 | 
|---|
| 1994 |         if scan: 
 | 
|---|
| 1995 |             self.set_data(scan, refresh=False)
 | 
|---|
| 1996 |             del scan
 | 
|---|
| 1997 | 
 | 
|---|
| 1998 |         # Rows and cols
 | 
|---|
| 1999 |         if (self._rows is None):
 | 
|---|
| 2000 |             rows = max(1, rows)
 | 
|---|
| 2001 |         if (self._cols is None):
 | 
|---|
| 2002 |             cols = max(1, cols)
 | 
|---|
| 2003 |         self.set_layout(rows,cols,False)
 | 
|---|
| 2004 | 
 | 
|---|
| 2005 |         # Select the first IF, POL, and BEAM for plotting
 | 
|---|
| 2006 |         ntotpl = self._rows * self._cols
 | 
|---|
| 2007 |         ifs = self._data.getifnos()
 | 
|---|
| 2008 |         if len(ifs) > 1:
 | 
|---|
| 2009 |             msg = "Found multiple IFs in scantable. Only the first IF (IFNO=%d) will be plotted." % ifs[0]
 | 
|---|
| 2010 |             asaplog.post()
 | 
|---|
| 2011 |             asaplog.push(msg)
 | 
|---|
| 2012 |             asaplog.post("WARN")
 | 
|---|
| 2013 |         pols = self._data.getpolnos()
 | 
|---|
| 2014 |         if len(pols) > 1:
 | 
|---|
| 2015 |             msg = "Found multiple POLs in scantable. Only the first POL (POLNO=%d) will be plotted." % pols[0]
 | 
|---|
| 2016 |             asaplog.post()
 | 
|---|
| 2017 |             asaplog.push(msg)
 | 
|---|
| 2018 |             asaplog.post("WARN")
 | 
|---|
| 2019 |         beams = self._data.getbeamnos()
 | 
|---|
| 2020 |         if len(beams) > 1:
 | 
|---|
| 2021 |             msg = "Found multiple BEAMs in scantable. Only the first BEAM (BEAMNO=%d) will be plotted." % beams[0]
 | 
|---|
| 2022 |             asaplog.post()
 | 
|---|
| 2023 |             asaplog.push(msg)
 | 
|---|
| 2024 |             asaplog.post("WARN")
 | 
|---|
| 2025 |         self._data.set_selection(ifs=[ifs[0]],pols=[pols[0]],beams=[beams[0]])
 | 
|---|
| 2026 |         if self._data.nrow() > ntotpl:
 | 
|---|
| 2027 |             msg = "Scantable is finely sampled than plotting grids. "\
 | 
|---|
| 2028 |                   + "Only the first spectrum is plotted in each grid."
 | 
|---|
| 2029 |             asaplog.post()
 | 
|---|
| 2030 |             asaplog.push(msg)
 | 
|---|
| 2031 |             asaplog.post("WARN")
 | 
|---|
| 2032 | 
 | 
|---|
| 2033 |         # Prepare plotter
 | 
|---|
| 2034 |         self._assert_plotter(action="reload")
 | 
|---|
| 2035 |         self._plotter.hold()
 | 
|---|
| 2036 |         self._reset_counter()
 | 
|---|
| 2037 |         self._plotter.legend()
 | 
|---|
| 2038 | 
 | 
|---|
| 2039 |         # Adjust subplot margins
 | 
|---|
| 2040 |         if not self._margins or len(self._margins) !=6:
 | 
|---|
| 2041 |             self.set_margin(refresh=False)
 | 
|---|
| 2042 |         self._plotter.set_panels(rows=self._rows,cols=self._cols,
 | 
|---|
| 2043 |                                  nplots=ntotpl,margin=self._margins,ganged=True)        
 | 
|---|
| 2044 |         if self.casabar_exists():
 | 
|---|
| 2045 |             self._plotter.figmgr.casabar.enable_button()
 | 
|---|
| 2046 |         # Plot helper
 | 
|---|
| 2047 |         from asap._asap import plothelper as plhelper
 | 
|---|
| 2048 |         ph = plhelper(self._data)
 | 
|---|
| 2049 |         #ph.set_gridval(self._cols, self._rows, spacing[0], spacing[1],
 | 
|---|
| 2050 |         #                  center[0], center[1], epoch="J2000", projname="SIN")
 | 
|---|
| 2051 |         if type(spacing) in (list, tuple, array):
 | 
|---|
| 2052 |             if len(spacing) == 0:
 | 
|---|
| 2053 |                 spacing = ["", ""]
 | 
|---|
| 2054 |             elif len(spacing) == 1:
 | 
|---|
| 2055 |                 spacing = [spacing[0], spacing[0]]
 | 
|---|
| 2056 |         else:
 | 
|---|
| 2057 |             spacing = [spacing, spacing]
 | 
|---|
| 2058 |         ph.set_grid(self._cols, self._rows, spacing[0], spacing[1], \
 | 
|---|
| 2059 |                     center, projname="SIN")
 | 
|---|
| 2060 | 
 | 
|---|
| 2061 |         # Actual plot
 | 
|---|
| 2062 |         npl = 0
 | 
|---|
| 2063 |         for irow in range(self._data.nrow()):
 | 
|---|
| 2064 |             (ix, iy) = ph.get_gpos(irow)
 | 
|---|
| 2065 |             #print("asapplotter.plotgrid: (ix, iy) = (%f, %f)" % (ix, iy))
 | 
|---|
| 2066 |             if ix < 0 or ix >= self._cols:
 | 
|---|
| 2067 |                 #print "Row %d : Out of X-range (x = %f) ... skipped" % (irow, pos[0])
 | 
|---|
| 2068 |                 continue
 | 
|---|
| 2069 |             ix = int(ix)
 | 
|---|
| 2070 |             if iy < 0 or iy >= self._rows:
 | 
|---|
| 2071 |                 #print "Row %d : Out of Y-range (y = %f) ... skipped" % (irow,pos[1])
 | 
|---|
| 2072 |                 continue
 | 
|---|
| 2073 |             iy = int(iy)
 | 
|---|
| 2074 |             ipanel = ix + iy*self._rows
 | 
|---|
| 2075 |             #print("Resolved panel Id (%d, %d): %d" % (ix, iy, ipanel))
 | 
|---|
| 2076 |             if len(self._plotter.subplots[ipanel]['lines']) > 0:
 | 
|---|
| 2077 |                 #print "Row %d : panel %d lready plotted ... skipped" % (irow,ipanel)
 | 
|---|
| 2078 |                 # a spectrum already plotted in the panel
 | 
|---|
| 2079 |                 continue
 | 
|---|
| 2080 |             # Plotting this row
 | 
|---|
| 2081 |             #print "PLOTTING row %d (panel=%d)" % (irow, ipanel)
 | 
|---|
| 2082 |             npl += 1
 | 
|---|
| 2083 |             self._plotter.subplot(ipanel)
 | 
|---|
| 2084 |             self._plotter.palette(0,colormap=self._colormap, \
 | 
|---|
| 2085 |                                   linestyle=0,linestyles=self._linestyles)
 | 
|---|
| 2086 |             xlab = self._abcissa and self._abcissa[ipanel] \
 | 
|---|
| 2087 |                    or self._data._getabcissalabel(irow)
 | 
|---|
| 2088 |             if self._offset and not self._abcissa:
 | 
|---|
| 2089 |                 xlab += " (relative)"
 | 
|---|
| 2090 |             ylab = self._ordinate and self._ordinate[ipanel] \
 | 
|---|
| 2091 |                    or self._data._get_ordinate_label()
 | 
|---|
| 2092 |             self._plotter.set_axes('xlabel', xlab)
 | 
|---|
| 2093 |             self._plotter.set_axes('ylabel', ylab)
 | 
|---|
| 2094 |             lbl = self._data.get_direction(irow)
 | 
|---|
| 2095 |             self._plotter.set_axes('title',lbl)
 | 
|---|
| 2096 | 
 | 
|---|
| 2097 |             y = self._data._getspectrum(irow)
 | 
|---|
| 2098 |             # flag application
 | 
|---|
| 2099 |             mr = self._data._getflagrow(irow)
 | 
|---|
| 2100 |             if mr:  # FLAGROW=True
 | 
|---|
| 2101 |                 y = ma.masked_array(y,mask=mr)
 | 
|---|
| 2102 |             else:
 | 
|---|
| 2103 |                 m = self._data._getmask(irow)
 | 
|---|
| 2104 |                 from numpy import logical_not, logical_and
 | 
|---|
| 2105 |                 ### user mask is not available so far
 | 
|---|
| 2106 |                 #if self._maskselection and len(self._usermask) == len(m):
 | 
|---|
| 2107 |                 #    if d[self._stacking](irow) in self._maskselection[self._stacking]:
 | 
|---|
| 2108 |                 #            m = logical_and(m, self._usermask)
 | 
|---|
| 2109 |                 y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
 | 
|---|
| 2110 | 
 | 
|---|
| 2111 |             x = array(self._data._getabcissa(irow))
 | 
|---|
| 2112 |             if self._offset:
 | 
|---|
| 2113 |                 x += self._offset
 | 
|---|
| 2114 |             if self._minmaxx is not None:
 | 
|---|
| 2115 |                 s,e = self._slice_indeces(x)
 | 
|---|
| 2116 |                 x = x[s:e]
 | 
|---|
| 2117 |                 y = y[s:e]
 | 
|---|
| 2118 |             if len(x) > 1024 and rcParams['plotter.decimate']:
 | 
|---|
| 2119 |                 fac = len(x)/1024
 | 
|---|
| 2120 |                 x = x[::fac]
 | 
|---|
| 2121 |                 y = y[::fac]
 | 
|---|
| 2122 |             self._plotter.set_line(label=lbl)
 | 
|---|
| 2123 |             plotit = self._plotter.plot
 | 
|---|
| 2124 |             if self._hist: plotit = self._plotter.hist
 | 
|---|
| 2125 |             if len(x) > 0 and not mr:
 | 
|---|
| 2126 |                 plotit(x,y)
 | 
|---|
| 2127 | #                 xlim= self._minmaxx or [min(x),max(x)]
 | 
|---|
| 2128 | #                 allxlim += xlim
 | 
|---|
| 2129 | #                 ylim= self._minmaxy or [ma.minimum(y),ma.maximum(y)]
 | 
|---|
| 2130 | #                 allylim += ylim
 | 
|---|
| 2131 | #             else:
 | 
|---|
| 2132 | #                 xlim = self._minmaxx or []
 | 
|---|
| 2133 | #                 allxlim += xlim
 | 
|---|
| 2134 | #                 ylim= self._minmaxy or []
 | 
|---|
| 2135 | #                 allylim += ylim
 | 
|---|
| 2136 |             
 | 
|---|
| 2137 |             if npl >= ntotpl:
 | 
|---|
| 2138 |                 break
 | 
|---|
| 2139 |             
 | 
|---|
| 2140 |         if self._minmaxy is not None:
 | 
|---|
| 2141 |             self._plotter.set_limits(ylim=self._minmaxy)
 | 
|---|
| 2142 |         self._plotter.release()
 | 
|---|
| 2143 |         self._plotter.tidy()
 | 
|---|
| 2144 |         self._plotter.show(hardrefresh=False)
 | 
|---|
| 2145 |         return
 | 
|---|