| [2155] | 1 | import os
 | 
|---|
 | 2 | import matplotlib, numpy
 | 
|---|
 | 3 | from asap.logging import asaplog, asaplog_post_dec
 | 
|---|
 | 4 | from matplotlib.patches import Rectangle
 | 
|---|
 | 5 | from asap.parameters import rcParams
 | 
|---|
| [2170] | 6 | from asap import scantable
 | 
|---|
| [2155] | 7 | from asap._asap import stmath
 | 
|---|
| [2172] | 8 | from asap.utils import _n_bools, mask_not, mask_or
 | 
|---|
| [2155] | 9 | 
 | 
|---|
 | 10 | ######################################
 | 
|---|
 | 11 | ##    Add CASA custom toolbar       ##
 | 
|---|
 | 12 | ######################################
 | 
|---|
 | 13 | class CustomToolbarCommon:
 | 
|---|
 | 14 |     def __init__(self,parent):
 | 
|---|
 | 15 |         self.plotter = parent
 | 
|---|
 | 16 |         #self.figmgr=self.plotter._plotter.figmgr
 | 
|---|
 | 17 | 
 | 
|---|
 | 18 |     ### select the nearest spectrum in pick radius
 | 
|---|
 | 19 |     ###    and display spectral value on the toolbar.
 | 
|---|
 | 20 |     def _select_spectrum(self,event):
 | 
|---|
 | 21 |         # Do not fire event when in zooming/panning mode
 | 
|---|
 | 22 |         mode = self.figmgr.toolbar.mode
 | 
|---|
 | 23 |         if not mode == '':
 | 
|---|
 | 24 |             return
 | 
|---|
 | 25 |             # When selected point is out of panels
 | 
|---|
 | 26 |         if event.inaxes == None:
 | 
|---|
 | 27 |             return
 | 
|---|
 | 28 |         # If not left button
 | 
|---|
 | 29 |         if event.button != 1:
 | 
|---|
 | 30 |             return
 | 
|---|
 | 31 | 
 | 
|---|
 | 32 |         xclick = event.xdata
 | 
|---|
 | 33 |         yclick = event.ydata
 | 
|---|
 | 34 |         dist2 = 1000.
 | 
|---|
 | 35 |         pickline = None
 | 
|---|
 | 36 |         # If the pannel has picable objects
 | 
|---|
 | 37 |         pflag = False
 | 
|---|
 | 38 |         for lin in event.inaxes.lines:
 | 
|---|
 | 39 |             if not lin.pickable():
 | 
|---|
 | 40 |                 continue
 | 
|---|
 | 41 |             pflag = True
 | 
|---|
 | 42 |             flag,pind = lin.contains(event)
 | 
|---|
 | 43 |             if not flag:
 | 
|---|
 | 44 |                 continue
 | 
|---|
 | 45 |             # Get nearest point
 | 
|---|
 | 46 |             inds = pind['ind']
 | 
|---|
 | 47 |             xlin = lin.get_xdata()
 | 
|---|
 | 48 |             ylin = lin.get_ydata()
 | 
|---|
 | 49 |             for i in inds:
 | 
|---|
 | 50 |                 d2=(xlin[i]-xclick)**2+(ylin[i]-yclick)**2
 | 
|---|
 | 51 |                 if dist2 >= d2:
 | 
|---|
 | 52 |                     dist2 = d2
 | 
|---|
 | 53 |                     pickline = lin
 | 
|---|
 | 54 |         # No pickcable line in the pannel
 | 
|---|
 | 55 |         if not pflag:
 | 
|---|
 | 56 |             return
 | 
|---|
 | 57 |         # Pickable but too far from mouse position
 | 
|---|
 | 58 |         elif pickline is None:
 | 
|---|
 | 59 |             picked = 'No line selected.'
 | 
|---|
 | 60 |             self.figmgr.toolbar.set_message(picked)
 | 
|---|
 | 61 |             return
 | 
|---|
 | 62 |         del pind, inds, xlin, ylin
 | 
|---|
 | 63 |         # Spectra are Picked
 | 
|---|
 | 64 |         theplot = self.plotter._plotter
 | 
|---|
 | 65 |         thetoolbar = self.figmgr.toolbar
 | 
|---|
 | 66 |         thecanvas = self.figmgr.canvas
 | 
|---|
 | 67 |         # Disconnect the default motion notify event
 | 
|---|
 | 68 |         # Notice! the other buttons are also diabled!!!
 | 
|---|
 | 69 |         thecanvas.mpl_disconnect(thetoolbar._idDrag)
 | 
|---|
 | 70 |         # Get picked spectrum
 | 
|---|
 | 71 |         xdata = pickline.get_xdata()
 | 
|---|
 | 72 |         ydata = pickline.get_ydata()
 | 
|---|
 | 73 |         titl = pickline.get_label()
 | 
|---|
 | 74 |         titp = event.inaxes.title.get_text()
 | 
|---|
 | 75 |         panel0 = event.inaxes
 | 
|---|
 | 76 |         picked = "Selected: '"+titl+"' in panel '"+titp+"'."
 | 
|---|
 | 77 |         thetoolbar.set_message(picked)
 | 
|---|
 | 78 |         # Generate a navigation window
 | 
|---|
 | 79 |         #naviwin=Navigationwindow(titp,titl)
 | 
|---|
 | 80 |         #------------------------------------------------------#
 | 
|---|
 | 81 |         # Show spectrum data at mouse position
 | 
|---|
 | 82 |         def spec_data(event):
 | 
|---|
 | 83 |             # Getting spectrum data of neiboring point
 | 
|---|
 | 84 |             xclick = event.xdata
 | 
|---|
 | 85 |             if event.inaxes != panel0:
 | 
|---|
 | 86 |                 return
 | 
|---|
 | 87 |             ipoint = len(xdata)-1
 | 
|---|
 | 88 |             for i in range(len(xdata)-1):
 | 
|---|
 | 89 |                 xl = xclick - xdata[i]
 | 
|---|
 | 90 |                 xr = xclick - xdata[i+1]
 | 
|---|
 | 91 |                 if xl*xr <= 0.:
 | 
|---|
 | 92 |                     ipoint = i
 | 
|---|
 | 93 |                     break
 | 
|---|
 | 94 |             # Output spectral value on the navigation window
 | 
|---|
 | 95 |             posi = '[ %s, %s ]:  x = %.2f   value = %.2f'\
 | 
|---|
 | 96 |                    %(titl,titp,xdata[ipoint],ydata[ipoint])
 | 
|---|
 | 97 |             #naviwin.posi.set(posi)
 | 
|---|
 | 98 |             thetoolbar.set_message(posi)
 | 
|---|
 | 99 |         #------------------------------------------------------#
 | 
|---|
 | 100 |         # Disconnect from mouse events
 | 
|---|
 | 101 |         def discon(event):
 | 
|---|
 | 102 |             #naviwin.window.destroy()
 | 
|---|
 | 103 |             theplot.register('motion_notify',None)
 | 
|---|
 | 104 |             # Re-activate the default motion_notify_event
 | 
|---|
 | 105 |             thetoolbar._idDrag = thecanvas.mpl_connect('motion_notify_event',
 | 
|---|
 | 106 |                                                        thetoolbar.mouse_move)
 | 
|---|
 | 107 |             theplot.register('button_release',None)
 | 
|---|
 | 108 |             return
 | 
|---|
 | 109 |         #------------------------------------------------------#
 | 
|---|
 | 110 |         # Show data value along with mouse movement
 | 
|---|
 | 111 |         theplot.register('motion_notify',spec_data)
 | 
|---|
 | 112 |         # Finish events when mouse button is released
 | 
|---|
 | 113 |         theplot.register('button_release',discon)
 | 
|---|
 | 114 | 
 | 
|---|
 | 115 | 
 | 
|---|
| [2172] | 116 |     ### Notation
 | 
|---|
| [2155] | 117 |     def _mod_note(self,event):
 | 
|---|
 | 118 |         # Do not fire event when in zooming/panning mode
 | 
|---|
 | 119 |         if not self.figmgr.toolbar.mode == '':
 | 
|---|
 | 120 |             return
 | 
|---|
 | 121 |         if event.button == 1:
 | 
|---|
 | 122 |             self.notewin.load_textwindow(event)
 | 
|---|
 | 123 |         elif event.button == 3 and self._note_picked(event):
 | 
|---|
 | 124 |             self.notewin.load_modmenu(event)
 | 
|---|
 | 125 |         return
 | 
|---|
 | 126 | 
 | 
|---|
 | 127 |     def _note_picked(self,event):
 | 
|---|
 | 128 |         # just briefly check if any texts are picked
 | 
|---|
 | 129 |         for textobj in self.canvas.figure.texts:
 | 
|---|
 | 130 |             if textobj.contains(event)[0]:
 | 
|---|
 | 131 |                 return True
 | 
|---|
 | 132 |         for ax in self.canvas.figure.axes:
 | 
|---|
 | 133 |             for textobj in ax.texts:
 | 
|---|
 | 134 |                 if textobj.contains(event)[0]:
 | 
|---|
 | 135 |                     return True
 | 
|---|
 | 136 |         #print "No text picked"
 | 
|---|
 | 137 |         return False
 | 
|---|
 | 138 | 
 | 
|---|
| [2172] | 139 | 
 | 
|---|
 | 140 |     ### Purely plotter based statistics calculation of a selected area.
 | 
|---|
 | 141 |     ### No access to scantable
 | 
|---|
 | 142 |     def _single_mask(self,event):
 | 
|---|
 | 143 |         # Do not fire event when in zooming/panning mode
 | 
|---|
 | 144 |         if not self.figmgr.toolbar.mode == '':
 | 
|---|
 | 145 |             return
 | 
|---|
 | 146 |         # When selected point is out of panels
 | 
|---|
 | 147 |         if event.inaxes == None:
 | 
|---|
 | 148 |             return
 | 
|---|
 | 149 |         if event.button == 1:
 | 
|---|
 | 150 |             exclude=False
 | 
|---|
 | 151 |         elif event.button == 3:
 | 
|---|
 | 152 |             exclude=True
 | 
|---|
 | 153 |         else:
 | 
|---|
 | 154 |             return
 | 
|---|
 | 155 | 
 | 
|---|
 | 156 |         self._thisregion = {'axes': event.inaxes,'xs': event.x,
 | 
|---|
 | 157 |                             'worldx': [event.xdata,event.xdata],
 | 
|---|
 | 158 |                             'invert': exclude}
 | 
|---|
 | 159 |         self.xold = event.x
 | 
|---|
 | 160 |         self.xdataold = event.xdata
 | 
|---|
 | 161 | 
 | 
|---|
 | 162 |         self.plotter._plotter.register('button_press',None)
 | 
|---|
 | 163 |         self.plotter._plotter.register('motion_notify', self._xspan_draw)
 | 
|---|
 | 164 |         self.plotter._plotter.register('button_press', self._xspan_end)
 | 
|---|
 | 165 | 
 | 
|---|
 | 166 |     def _xspan_draw(self,event):
 | 
|---|
 | 167 |         if event.inaxes == self._thisregion['axes']:
 | 
|---|
 | 168 |             xnow = event.x
 | 
|---|
 | 169 |             self.xold = xnow
 | 
|---|
 | 170 |             self.xdataold = event.xdata
 | 
|---|
 | 171 |         else:
 | 
|---|
 | 172 |             xnow = self.xold
 | 
|---|
 | 173 |         try: self.lastspan
 | 
|---|
 | 174 |         except AttributeError: pass
 | 
|---|
 | 175 |         else:
 | 
|---|
 | 176 |             if self.lastspan: self._remove_span(self.lastspan)
 | 
|---|
 | 177 | 
 | 
|---|
| [2324] | 178 |         self.lastspan = self._draw_span(self._thisregion['axes'],
 | 
|---|
 | 179 |                                         self._thisregion['xs'], xnow, fill="")
 | 
|---|
| [2172] | 180 |         del xnow
 | 
|---|
 | 181 | 
 | 
|---|
 | 182 |     def _draw_span(self,axes,x0,x1,**kwargs):
 | 
|---|
 | 183 |         pass
 | 
|---|
 | 184 | 
 | 
|---|
 | 185 |     def _remove_span(self,span):
 | 
|---|
 | 186 |         pass
 | 
|---|
 | 187 | 
 | 
|---|
 | 188 |     @asaplog_post_dec
 | 
|---|
 | 189 |     def _xspan_end(self,event):
 | 
|---|
 | 190 |         if not self.figmgr.toolbar.mode == '':
 | 
|---|
 | 191 |             return
 | 
|---|
 | 192 |         #if event.button != 1:
 | 
|---|
 | 193 |         #    return
 | 
|---|
 | 194 | 
 | 
|---|
 | 195 |         try: self.lastspan
 | 
|---|
 | 196 |         except AttributeError: pass
 | 
|---|
 | 197 |         else:
 | 
|---|
 | 198 |             self._remove_span(self.lastspan)
 | 
|---|
 | 199 |             del self.lastspan
 | 
|---|
 | 200 |         if event.inaxes == self._thisregion['axes']:
 | 
|---|
 | 201 |             xdataend = event.xdata
 | 
|---|
 | 202 |         else:
 | 
|---|
 | 203 |             xdataend = self.xdataold
 | 
|---|
 | 204 | 
 | 
|---|
 | 205 |         self._thisregion['worldx'][1] = xdataend
 | 
|---|
 | 206 |         # print statistics of spectra in subplot
 | 
|---|
 | 207 |         self._subplot_stats(self._thisregion)
 | 
|---|
 | 208 |         
 | 
|---|
 | 209 |         # release event
 | 
|---|
 | 210 |         self.plotter._plotter.register('button_press',None)
 | 
|---|
 | 211 |         self.plotter._plotter.register('motion_notify',None)
 | 
|---|
 | 212 |         # Clear up region selection
 | 
|---|
 | 213 |         self._thisregion = None
 | 
|---|
 | 214 |         self.xdataold = None
 | 
|---|
 | 215 |         self.xold = None
 | 
|---|
 | 216 |         # finally recover region selection event
 | 
|---|
 | 217 |         self.plotter._plotter.register('button_press',self._single_mask)
 | 
|---|
 | 218 | 
 | 
|---|
 | 219 |     def _subplot_stats(self,selection):
 | 
|---|
 | 220 |         statstr = ['max', 'min', 'median', 'mean', 'sum', 'std'] #'rms']
 | 
|---|
 | 221 |         panelstr = selection['axes'].title.get_text()
 | 
|---|
 | 222 |         ssep = "-"*70
 | 
|---|
 | 223 |         asaplog.push(ssep)
 | 
|---|
 | 224 |         asaplog.post()
 | 
|---|
 | 225 |         for line in selection['axes'].lines:
 | 
|---|
| [2324] | 226 |             # Don't include annotations
 | 
|---|
 | 227 |             if line.get_label().startswith("_"):
 | 
|---|
 | 228 |                 continue
 | 
|---|
| [2172] | 229 |             label = panelstr + ", "+line.get_label()
 | 
|---|
 | 230 |             x = line.get_xdata()
 | 
|---|
| [2324] | 231 |             newmsk = None
 | 
|---|
 | 232 |             selmsk = self._create_flag_from_array(x,
 | 
|---|
 | 233 |                                                   selection['worldx'],
 | 
|---|
 | 234 |                                                   selection['invert'])
 | 
|---|
 | 235 |             ydat = None
 | 
|---|
| [2172] | 236 |             y = line.get_ydata()
 | 
|---|
| [2324] | 237 |             if numpy.ma.isMaskedArray(y):
 | 
|---|
| [2172] | 238 |                 ydat = y.data
 | 
|---|
 | 239 |                 basemsk = y.mask
 | 
|---|
 | 240 |             else:
 | 
|---|
 | 241 |                 ydat = y
 | 
|---|
 | 242 |                 basemsk = False
 | 
|---|
 | 243 |             if not isinstance(basemsk, bool):
 | 
|---|
 | 244 |                 # should be ndarray
 | 
|---|
| [2324] | 245 |                 newmsk = mask_or(selmsk, basemsk)
 | 
|---|
| [2172] | 246 |             elif basemsk:
 | 
|---|
 | 247 |                 # the whole original spectrum is flagged
 | 
|---|
 | 248 |                 newmsk = basemsk
 | 
|---|
 | 249 |             else:
 | 
|---|
 | 250 |                 # no channel was flagged originally
 | 
|---|
 | 251 |                 newmsk = selmsk
 | 
|---|
| [2324] | 252 |             mdata = numpy.ma.masked_array(ydat, mask=newmsk)
 | 
|---|
| [2172] | 253 |             statval = {}
 | 
|---|
 | 254 |             for stat in statstr:
 | 
|---|
| [2324] | 255 |                 # need to get the stat functions from the ma module!!!
 | 
|---|
 | 256 |                 statval[stat] = getattr(numpy.ma,stat)(mdata)
 | 
|---|
 | 257 |             self._print_stats(statval, statstr=statstr, label=label,\
 | 
|---|
| [2172] | 258 |                               mask=selection['worldx'],\
 | 
|---|
 | 259 |                               unmask=selection['invert'])
 | 
|---|
 | 260 |             asaplog.push(ssep)
 | 
|---|
 | 261 |             asaplog.post()
 | 
|---|
 | 262 | 
 | 
|---|
 | 263 |     def _create_flag_from_array(self,x,masklist,invert):
 | 
|---|
 | 264 |         # Return True for channels which should be EXCLUDED (flag)
 | 
|---|
 | 265 |         if len(masklist) <= 1:
 | 
|---|
 | 266 |             asaplog.push()
 | 
|---|
 | 267 |             asaplog.post("masklist should be a list of 2 elements")
 | 
|---|
 | 268 |             asaplog.push("ERROR")
 | 
|---|
 | 269 |         n = len(x)
 | 
|---|
 | 270 |         # Base mask: flag out all channels
 | 
|---|
 | 271 |         mask = _n_bools(n, True)
 | 
|---|
 | 272 |         minval = min(masklist[0:2])
 | 
|---|
 | 273 |         maxval = max(masklist[0:2])
 | 
|---|
 | 274 |         for i in range(n):
 | 
|---|
 | 275 |             if minval <= x[i] <= maxval:
 | 
|---|
 | 276 |                 mask[i] = False
 | 
|---|
 | 277 |         if invert:
 | 
|---|
 | 278 |             mask = mask_not(mask)
 | 
|---|
 | 279 |         return mask
 | 
|---|
 | 280 | 
 | 
|---|
 | 281 |     @asaplog_post_dec
 | 
|---|
 | 282 |     def _print_stats(self,stats,statstr=None,label="",mask=None,unmask=False):
 | 
|---|
 | 283 |         if not isinstance(stats,dict) or len(stats) == 0:
 | 
|---|
 | 284 |             asaplog.post()
 | 
|---|
 | 285 |             asaplog.push("Invalid statistic value")
 | 
|---|
 | 286 |             asaplog.post("ERROR")
 | 
|---|
 | 287 |         maskstr = "Not available"
 | 
|---|
 | 288 |         if mask:
 | 
|---|
 | 289 |             masktype = "mask"
 | 
|---|
 | 290 |             maskstr = str(mask)
 | 
|---|
 | 291 |             if unmask: masktype = "unmask"
 | 
|---|
 | 292 | 
 | 
|---|
 | 293 |         sout = label + ", " + masktype + " = " + maskstr + "\n"
 | 
|---|
 | 294 |         statvals = []
 | 
|---|
 | 295 |         if not len(statstr):
 | 
|---|
 | 296 |             statstr = stats.keys()
 | 
|---|
 | 297 |         for key in statstr:
 | 
|---|
 | 298 |             sout += key.ljust(10)
 | 
|---|
 | 299 |             statvals.append(stats.pop(key))
 | 
|---|
 | 300 |         sout += "\n"
 | 
|---|
 | 301 |         sout += ("%f "*len(statstr) % tuple(statvals))
 | 
|---|
 | 302 |         asaplog.push(sout)
 | 
|---|
| [2324] | 303 |         #del sout, maskstr, masktype, statvals, key, stats, statstr, mask, label
 | 
|---|
| [2172] | 304 | 
 | 
|---|
 | 305 | 
 | 
|---|
| [2155] | 306 |     ### Page chages
 | 
|---|
 | 307 |     ### go to the previous page
 | 
|---|
 | 308 |     def prev_page(self):
 | 
|---|
 | 309 |         self.figmgr.toolbar.set_message('plotting the previous page')
 | 
|---|
 | 310 |         #self._pause_buttons(operation="start",msg='plotting the previous page')
 | 
|---|
 | 311 |         self._new_page(goback=True)
 | 
|---|
 | 312 |         #self._pause_buttons(operation="end")
 | 
|---|
 | 313 | 
 | 
|---|
 | 314 |     ### go to the next page
 | 
|---|
 | 315 |     def next_page(self):
 | 
|---|
 | 316 |         self.figmgr.toolbar.set_message('plotting the next page')
 | 
|---|
 | 317 |         #self._pause_buttons(operation="start",msg='plotting the next page')
 | 
|---|
 | 318 |         self._new_page(goback=False)
 | 
|---|
 | 319 |         #self._pause_buttons(operation="end")
 | 
|---|
 | 320 | 
 | 
|---|
 | 321 |     ### actual plotting of the new page
 | 
|---|
 | 322 |     def _new_page(self,goback=False):
 | 
|---|
 | 323 |         top = None
 | 
|---|
 | 324 |         header = self.plotter._headtext
 | 
|---|
 | 325 |         reset = False
 | 
|---|
 | 326 |         doheader = (isinstance(header['textobj'],list) and \
 | 
|---|
 | 327 |                     len(header['textobj']) > 0)
 | 
|---|
 | 328 |         if self.plotter._startrow <= 0:
 | 
|---|
 | 329 |             msg = "The page counter is reset due to chages of plot settings. "
 | 
|---|
 | 330 |             msg += "Plotting from the first page."
 | 
|---|
 | 331 |             asaplog.push(msg)
 | 
|---|
 | 332 |             asaplog.post('WARN')
 | 
|---|
 | 333 |             reset = True
 | 
|---|
 | 334 |             goback = False
 | 
|---|
 | 335 |             if doheader:
 | 
|---|
 | 336 |                 extrastr = selstr = ''
 | 
|---|
 | 337 |                 if header.has_key('extrastr'):
 | 
|---|
 | 338 |                     extrastr = header['extrastr']
 | 
|---|
 | 339 |                 if header.has_key('selstr'):
 | 
|---|
 | 340 |                     selstr = header['selstr']
 | 
|---|
 | 341 |             self.plotter._reset_header()
 | 
|---|
 | 342 |         if doheader:
 | 
|---|
 | 343 |             top = self.plotter._plotter.figure.subplotpars.top
 | 
|---|
 | 344 |             fontsize = header['textobj'][0].get_fontproperties().get_size()
 | 
|---|
 | 345 | 
 | 
|---|
 | 346 |         self.plotter._plotter.hold()
 | 
|---|
 | 347 |         if goback:
 | 
|---|
 | 348 |             self._set_prevpage_counter()
 | 
|---|
 | 349 |         #self.plotter._plotter.clear()
 | 
|---|
 | 350 |         self.plotter._plot(self.plotter._data)
 | 
|---|
 | 351 |         self.set_pagecounter(self._get_pagenum())
 | 
|---|
 | 352 |         # Plot header information
 | 
|---|
 | 353 |         if header['textobj']:
 | 
|---|
 | 354 |             if top and top != self.plotter._margins[3]:
 | 
|---|
 | 355 |                 # work around for sdplot in CASA. complete checking in future?
 | 
|---|
 | 356 |                 self.plotter._plotter.figure.subplots_adjust(top=top)
 | 
|---|
 | 357 |             if reset:
 | 
|---|
 | 358 |                 self.plotter.print_header(plot=True,fontsize=fontsize,selstr=selstr, extrastr=extrastr)
 | 
|---|
 | 359 |             else:
 | 
|---|
 | 360 |                 self.plotter._header_plot(header['string'],fontsize=fontsize)
 | 
|---|
 | 361 |         self.plotter._plotter.release()
 | 
|---|
 | 362 |         self.plotter._plotter.tidy()
 | 
|---|
 | 363 |         self.plotter._plotter.show(hardrefresh=False)
 | 
|---|
 | 364 |         del top
 | 
|---|
 | 365 | 
 | 
|---|
 | 366 |     ### calculate the panel ID and start row to plot the previous page
 | 
|---|
 | 367 |     def _set_prevpage_counter(self):
 | 
|---|
 | 368 |         # set row and panel counters to those of the 1st panel of previous page
 | 
|---|
 | 369 |         maxpanel = 16
 | 
|---|
 | 370 |         # the ID of the last panel in current plot
 | 
|---|
 | 371 |         lastpanel = self.plotter._ipanel
 | 
|---|
 | 372 |         # the number of current subplots
 | 
|---|
 | 373 |         currpnum = len(self.plotter._plotter.subplots)
 | 
|---|
 | 374 |         # the nuber of previous subplots
 | 
|---|
 | 375 |         prevpnum = None
 | 
|---|
 | 376 |         if self.plotter._rows and self.plotter._cols:
 | 
|---|
 | 377 |             # when user set layout
 | 
|---|
 | 378 |             prevpnum = self.plotter._rows*self.plotter._cols
 | 
|---|
 | 379 |         else:
 | 
|---|
 | 380 |             # no user specification
 | 
|---|
 | 381 |             prevpnum = maxpanel
 | 
|---|
 | 382 | 
 | 
|---|
 | 383 |         start_ipanel = max(lastpanel-currpnum-prevpnum+1, 0)
 | 
|---|
 | 384 |         # set the pannel ID of the last panel of prev-prev page
 | 
|---|
 | 385 |         self.plotter._ipanel = start_ipanel-1
 | 
|---|
 | 386 |         if self.plotter._panelling == 'r':
 | 
|---|
 | 387 |             self.plotter._startrow = start_ipanel
 | 
|---|
 | 388 |         else:
 | 
|---|
 | 389 |             # the start row number of the next panel
 | 
|---|
 | 390 |             self.plotter._startrow = self.plotter._panelrows[start_ipanel]
 | 
|---|
 | 391 |         del lastpanel,currpnum,prevpnum,start_ipanel
 | 
|---|
 | 392 | 
 | 
|---|
 | 393 |     ### refresh the page counter
 | 
|---|
 | 394 |     def set_pagecounter(self,page):
 | 
|---|
 | 395 |         nwidth = int(numpy.ceil(numpy.log10(max(page,1))))+1
 | 
|---|
 | 396 |         nwidth = max(nwidth,4)
 | 
|---|
 | 397 |         formatstr = '%'+str(nwidth)+'d'
 | 
|---|
 | 398 |         self.show_pagenum(page,formatstr)
 | 
|---|
 | 399 | 
 | 
|---|
 | 400 |     def show_pagenum(self,pagenum,formatstr):
 | 
|---|
 | 401 |         # passed to backend dependent class
 | 
|---|
 | 402 |         pass        
 | 
|---|
 | 403 | 
 | 
|---|
 | 404 |     def _get_pagenum(self):
 | 
|---|
 | 405 |         maxpanel = 16
 | 
|---|
 | 406 |         # get the ID of last panel in the current page
 | 
|---|
 | 407 |         idlastpanel = self.plotter._ipanel
 | 
|---|
 | 408 |         if self.plotter._rows and self.plotter._cols:
 | 
|---|
 | 409 |             ppp = self.plotter._rows*self.plotter._cols
 | 
|---|
 | 410 |         else:
 | 
|---|
 | 411 |             ppp = maxpanel
 | 
|---|
 | 412 |         return int(idlastpanel/ppp)+1
 | 
|---|
 | 413 | 
 | 
|---|
 | 414 |     # pause buttons for slow operations. implemented at a backend dependent class
 | 
|---|
 | 415 |     def _pause_buttons(self,operation="end",msg=""):
 | 
|---|
 | 416 |         pass
 | 
|---|
 | 417 | 
 | 
|---|
 | 418 | 
 | 
|---|
 | 419 | 
 | 
|---|
 | 420 | 
 | 
|---|
 | 421 | ######################################
 | 
|---|
 | 422 | ##    Notation box window           ##
 | 
|---|
 | 423 | ######################################
 | 
|---|
 | 424 | class NotationWindowCommon:
 | 
|---|
 | 425 |     """
 | 
|---|
 | 426 |     A base class to define the functions that the backend-based
 | 
|---|
 | 427 |     GUI notation class must implement to print/modify/delete notes on a canvas.
 | 
|---|
 | 428 | 
 | 
|---|
 | 429 |     The following methods *must* be implemented in the backend-based
 | 
|---|
 | 430 |     parent class:
 | 
|---|
 | 431 |         _get_note : get text in text box
 | 
|---|
 | 432 |         _get_anchval : get anchor value selected
 | 
|---|
 | 433 |     """
 | 
|---|
 | 434 |     def __init__(self,master=None):
 | 
|---|
 | 435 |         #self.parent = master
 | 
|---|
 | 436 |         self.canvas = master
 | 
|---|
 | 437 |         self.event = None
 | 
|---|
 | 438 |         self.note = None
 | 
|---|
 | 439 |         self.anchors = ["figure","axes","data"]
 | 
|---|
 | 440 |         self.seltext = {}
 | 
|---|
 | 441 |         self.numnote = 0
 | 
|---|
 | 442 | 
 | 
|---|
 | 443 |     @asaplog_post_dec
 | 
|---|
 | 444 |     def print_text(self):
 | 
|---|
 | 445 |         """
 | 
|---|
 | 446 |         Print a note on a canvas specified with the Notation window.
 | 
|---|
 | 447 |         Called when 'print' button selected on the window.
 | 
|---|
 | 448 |         """
 | 
|---|
 | 449 |         anchor = self.anchors[self._get_anchval()]
 | 
|---|
 | 450 |         notestr = self._get_note().rstrip("\n")
 | 
|---|
 | 451 |         if len(notestr.strip()) == 0:
 | 
|---|
 | 452 |             #self._clear_textbox()
 | 
|---|
 | 453 |             #print "Empty string!"
 | 
|---|
 | 454 |             return
 | 
|---|
 | 455 | 
 | 
|---|
 | 456 |         myaxes = None
 | 
|---|
 | 457 |         calcpos = True
 | 
|---|
 | 458 |         xpos = None
 | 
|---|
 | 459 |         ypos = None
 | 
|---|
 | 460 |         if self.seltext:
 | 
|---|
 | 461 |             # You are modifying a text
 | 
|---|
 | 462 |             mycanvas = self.canvas
 | 
|---|
 | 463 |             oldanch = self.seltext['anchor']
 | 
|---|
 | 464 |             if oldanch != 'figure':
 | 
|---|
 | 465 |                 myaxes = self.seltext['parent']
 | 
|---|
 | 466 |             calcpos = (anchor != oldanch)
 | 
|---|
 | 467 |             if not calcpos:
 | 
|---|
 | 468 |                 # printing text in the same coord.
 | 
|---|
 | 469 |                 # you don't have to recalc position
 | 
|---|
 | 470 |                 parent = self.seltext['parent']
 | 
|---|
 | 471 |                 transform = self.seltext['textobj'].get_transform()
 | 
|---|
 | 472 |                 (xpos, ypos) = self.seltext['textobj'].get_position()
 | 
|---|
 | 473 |             elif anchor == "figure":
 | 
|---|
 | 474 |                 # converting from "axes"/"data" -> "figure"
 | 
|---|
 | 475 |                 (x, y) = self.seltext['textobj']._get_xy_display()
 | 
|---|
 | 476 |             elif oldanch == "data":
 | 
|---|
 | 477 |                 # converting from "data" -> "axes".
 | 
|---|
 | 478 |                 # need xdata & ydata in the axes
 | 
|---|
 | 479 |                 (x, y) = self.seltext['textobj'].get_position()
 | 
|---|
 | 480 |             else:
 | 
|---|
 | 481 |                 # converting "figure"/"axes" -> "data"
 | 
|---|
 | 482 |                 # need to calculate xdata & ydata in the axes
 | 
|---|
 | 483 |                 pixpos = self.seltext['textobj']._get_xy_display()
 | 
|---|
 | 484 |                 (w,h) = mycanvas.get_width_height()
 | 
|---|
 | 485 |                 relpos = (pixpos[0]/float(w), pixpos[1]/float(h))
 | 
|---|
 | 486 |                 if not myaxes:
 | 
|---|
 | 487 |                     myaxes = self._get_axes_from_pos(relpos,mycanvas)
 | 
|---|
 | 488 |                     if not myaxes:
 | 
|---|
 | 489 |                         raise RuntimeError, "Axes resolution failed!"
 | 
|---|
 | 490 |                 (x, y) = self._convert_pix2dat(relpos,myaxes)
 | 
|---|
 | 491 |             self._remove_seltext()
 | 
|---|
 | 492 |         elif self.event:
 | 
|---|
 | 493 |             mycanvas = self.event.canvas
 | 
|---|
 | 494 |             myaxes = self.event.inaxes
 | 
|---|
 | 495 |             if myaxes and (anchor != "figure"):
 | 
|---|
 | 496 |                 x = self.event.xdata
 | 
|---|
 | 497 |                 y = self.event.ydata
 | 
|---|
 | 498 |             else:
 | 
|---|
 | 499 |                 x = self.event.x
 | 
|---|
 | 500 |                 y = self.event.y
 | 
|---|
 | 501 |         else:
 | 
|---|
 | 502 |             raise RuntimeError, "No valid position to print data"
 | 
|---|
 | 503 |             return
 | 
|---|
 | 504 | 
 | 
|---|
 | 505 |         # now you know 
 | 
|---|
 | 506 |         picker = True
 | 
|---|
 | 507 |         # alignment of the text: ha (horizontal), va (vertical)
 | 
|---|
 | 508 |         ha = 'left'
 | 
|---|
 | 509 |         #va = 'center'
 | 
|---|
 | 510 |         va = 'top'
 | 
|---|
 | 511 |         if not calcpos:
 | 
|---|
 | 512 |             # you aready know parent, tansform, xpos and ypos
 | 
|---|
 | 513 |             pass
 | 
|---|
 | 514 |         elif anchor == "figure":
 | 
|---|
 | 515 |             # text instance will be appended to mycanvas.figure.texts
 | 
|---|
 | 516 |             parent = mycanvas.figure
 | 
|---|
 | 517 |             transform = parent.transFigure
 | 
|---|
 | 518 |             (w,h) = mycanvas.get_width_height()
 | 
|---|
 | 519 |             xpos = x/float(w)
 | 
|---|
 | 520 |             ypos = y/float(h)            
 | 
|---|
 | 521 |         elif myaxes:
 | 
|---|
 | 522 |             ## text instance will be appended to myaxes.texts
 | 
|---|
 | 523 |             parent = myaxes
 | 
|---|
 | 524 |             if anchor == "axes":
 | 
|---|
 | 525 |                 transform = myaxes.transAxes
 | 
|---|
 | 526 |                 lims = myaxes.get_xlim()
 | 
|---|
 | 527 |                 xpos = (x-lims[0])/(lims[1]-lims[0])
 | 
|---|
 | 528 |                 lims = myaxes.get_ylim()
 | 
|---|
 | 529 |                 ypos = (y-lims[0])/(lims[1]-lims[0])
 | 
|---|
 | 530 |             else:
 | 
|---|
 | 531 |                 # anchored on "data"
 | 
|---|
 | 532 |                 transform = myaxes.transData
 | 
|---|
 | 533 |                 xpos = x
 | 
|---|
 | 534 |                 ypos = y
 | 
|---|
 | 535 |         parent.text(xpos,ypos,notestr,transform=transform,
 | 
|---|
 | 536 |                     ha=ha,va=va,picker=picker)
 | 
|---|
 | 537 |         mycanvas.draw()
 | 
|---|
 | 538 | 
 | 
|---|
 | 539 |         self.numnote += 1
 | 
|---|
 | 540 | 
 | 
|---|
 | 541 |         #self._clear_textbox()
 | 
|---|
 | 542 |         msg = "Added note: '"+notestr+"'"
 | 
|---|
 | 543 |         msg += " @["+str(xpos)+", "+str(ypos)+"] ("+anchor+"-coord)"
 | 
|---|
 | 544 |         msg += "\ntotal number of notes are "+str(self.numnote)
 | 
|---|
 | 545 |         asaplog.push( msg )
 | 
|---|
 | 546 | 
 | 
|---|
 | 547 |     def _get_axes_from_pos(self,pos,canvas):
 | 
|---|
 | 548 |         """helper function to get axes of a position in a plot (fig-coord)"""
 | 
|---|
 | 549 |         if len(pos) != 2:
 | 
|---|
 | 550 |             raise ValueError, "pixel position should have 2 elements"
 | 
|---|
 | 551 |         for axes in canvas.figure.axes:
 | 
|---|
 | 552 |             ##check if pos is in the axes
 | 
|---|
 | 553 |             #if axes.contains_point(pos): ### seems not working
 | 
|---|
 | 554 |             #    return axes
 | 
|---|
 | 555 |             try:
 | 
|---|
 | 556 |                 axbox = axes.get_position().get_points()
 | 
|---|
 | 557 |             except AttributeError: ### WORKAROUND for old matplotlib
 | 
|---|
 | 558 |                 axbox = self._oldpos2new(axes.get_position())
 | 
|---|
 | 559 |             if (axbox[0][0] <= pos[0] <= axbox[1][0]) and \
 | 
|---|
 | 560 |                (axbox[0][1] <= pos[1] <= axbox[1][1]):
 | 
|---|
 | 561 |                 return axes
 | 
|---|
 | 562 |         return None
 | 
|---|
 | 563 | 
 | 
|---|
 | 564 |     ### WORKAROUND for old matplotlib
 | 
|---|
 | 565 |     def _oldpos2new(self,oldpos=None):
 | 
|---|
 | 566 |         return [[oldpos[0],oldpos[1]],[oldpos[0]+oldpos[2],oldpos[1]+oldpos[3]]]
 | 
|---|
 | 567 |         
 | 
|---|
 | 568 |     def _convert_pix2dat(self,pos,axes):
 | 
|---|
 | 569 |         """
 | 
|---|
 | 570 |         helper function to convert a position in figure-coord (0-1) to
 | 
|---|
 | 571 |         data-coordinate of the axes        
 | 
|---|
 | 572 |         """
 | 
|---|
 | 573 |         # convert a relative position from lower-left of the canvas
 | 
|---|
 | 574 |         # to a data in axes
 | 
|---|
 | 575 |         if len(pos) != 2:
 | 
|---|
 | 576 |             raise ValueError, "pixel position should have 2 elements"
 | 
|---|
 | 577 |         # left-/bottom-pixel, and pixel width & height of the axes
 | 
|---|
 | 578 |         bbox = axes.get_position()
 | 
|---|
 | 579 |         try: 
 | 
|---|
 | 580 |             axpos = bbox.get_points()
 | 
|---|
 | 581 |         except AttributeError: ### WORKAROUND for old matplotlib
 | 
|---|
 | 582 |             axpos = self._oldpos2new(bbox)
 | 
|---|
 | 583 |         # check pos value
 | 
|---|
 | 584 |         if (pos[0] < axpos[0][0]) or (pos[1] < axpos[0][1]) \
 | 
|---|
 | 585 |                or (pos[0] > axpos[1][0]) or (pos[1] > axpos[1][1]):
 | 
|---|
 | 586 |             raise ValueError, "The position is out of the axes"
 | 
|---|
 | 587 |         xlims = axes.get_xlim()
 | 
|---|
 | 588 |         ylims = axes.get_ylim()
 | 
|---|
 | 589 |         wdat = xlims[1] - xlims[0]
 | 
|---|
 | 590 |         hdat = ylims[1] - ylims[0]
 | 
|---|
 | 591 |         xdat = xlims[0] + wdat*(pos[0] - axpos[0][0])/(axpos[1][0] - axpos[0][0])
 | 
|---|
 | 592 |         ydat = ylims[0] + hdat*(pos[1] - axpos[0][1])/(axpos[1][1] - axpos[0][1])
 | 
|---|
 | 593 |         return (xdat, ydat)
 | 
|---|
 | 594 | 
 | 
|---|
 | 595 |     @asaplog_post_dec
 | 
|---|
 | 596 |     def _get_selected_text(self,event):
 | 
|---|
 | 597 |         """helper function to return a dictionary of the nearest note to the event."""
 | 
|---|
 | 598 |         (w,h) = event.canvas.get_width_height()
 | 
|---|
 | 599 |         dist2 = w*w+h*h
 | 
|---|
 | 600 |         selected = {}
 | 
|---|
 | 601 |         for textobj in self.canvas.figure.texts:
 | 
|---|
 | 602 |             if textobj.contains(event)[0]:
 | 
|---|
 | 603 |                 d2 = self._get_text_dist2(event,textobj)
 | 
|---|
 | 604 |                 if dist2 >= d2:
 | 
|---|
 | 605 |                     dist2 = d2
 | 
|---|
 | 606 |                     selected = {'anchor': 'figure', \
 | 
|---|
 | 607 |                                 'parent': event.canvas.figure, 'textobj': textobj}
 | 
|---|
 | 608 |                     msg = "Fig loop: a text, '"+textobj.get_text()+"', at "
 | 
|---|
 | 609 |                     msg += str(textobj.get_position())+" detected"
 | 
|---|
 | 610 |                     #print msg
 | 
|---|
 | 611 |         for ax in self.canvas.figure.axes:
 | 
|---|
 | 612 |             for textobj in ax.texts:
 | 
|---|
 | 613 |                 if textobj.contains(event)[0]:
 | 
|---|
 | 614 |                     d2 = self._get_text_dist2(event,textobj)
 | 
|---|
 | 615 |                     if dist2 >= d2:
 | 
|---|
 | 616 |                         anchor='axes'
 | 
|---|
 | 617 |                         if ax.transData == textobj.get_transform():
 | 
|---|
 | 618 |                             anchor = 'data'                    
 | 
|---|
 | 619 |                         selected = {'anchor': anchor, \
 | 
|---|
 | 620 |                                     'parent': ax, 'textobj': textobj}
 | 
|---|
 | 621 |                         msg = "Ax loop: a text, '"+textobj.get_text()+"', at "
 | 
|---|
 | 622 |                         msg += str(textobj.get_position())+" detected"
 | 
|---|
 | 623 |                         #print msg 
 | 
|---|
 | 624 | 
 | 
|---|
 | 625 |         if selected:
 | 
|---|
 | 626 |             msg = "Selected (modify/delete): '"+selected['textobj'].get_text()
 | 
|---|
 | 627 |             msg += "' @"+str(selected['textobj'].get_position())
 | 
|---|
 | 628 |             msg += " ("+selected['anchor']+"-coord)"
 | 
|---|
 | 629 |             asaplog.push(msg)
 | 
|---|
 | 630 | 
 | 
|---|
 | 631 |         return selected
 | 
|---|
 | 632 | 
 | 
|---|
 | 633 |     def _get_text_dist2(self,event,textobj):
 | 
|---|
 | 634 |         """
 | 
|---|
 | 635 |         helper function to calculate square of distance between
 | 
|---|
 | 636 |         a event position and a text object. 
 | 
|---|
 | 637 |         """
 | 
|---|
 | 638 |         (x,y) = textobj._get_xy_display()
 | 
|---|
 | 639 |         return (x-event.x)**2+(y-event.y)**2
 | 
|---|
 | 640 | 
 | 
|---|
 | 641 |     def delete_note(self):
 | 
|---|
 | 642 |         """
 | 
|---|
 | 643 |         Remove selected note.
 | 
|---|
 | 644 |         """
 | 
|---|
 | 645 |         #print "You selected 'OK'"
 | 
|---|
 | 646 |         self._remove_seltext()
 | 
|---|
 | 647 |         self.canvas.draw()
 | 
|---|
 | 648 | 
 | 
|---|
 | 649 |     @asaplog_post_dec
 | 
|---|
 | 650 |     def _remove_seltext(self):
 | 
|---|
 | 651 |         """helper function to remove the selected note"""
 | 
|---|
 | 652 |         if len(self.seltext) < 3:
 | 
|---|
 | 653 |             raise ValueError, "Don't under stand selected text obj."
 | 
|---|
 | 654 |             return
 | 
|---|
 | 655 |         try:
 | 
|---|
 | 656 |             self.seltext['textobj'].remove()
 | 
|---|
 | 657 |         except NotImplementedError:
 | 
|---|
 | 658 |                 self.seltext['parent'].texts.pop(self.seltext['parent'].texts.index(self.seltext['textobj']))
 | 
|---|
 | 659 |         self.numnote -= 1
 | 
|---|
 | 660 | 
 | 
|---|
 | 661 |         textobj = self.seltext['textobj']
 | 
|---|
 | 662 |         msg = "Deleted note: '"+textobj.get_text()+"'"
 | 
|---|
 | 663 |         msg += "@"+str(textobj.get_position())\
 | 
|---|
 | 664 |                +" ("+self.seltext['anchor']+"-coord)"
 | 
|---|
 | 665 |         msg += "\ntotal number of notes are "+str(self.numnote)
 | 
|---|
 | 666 |         asaplog.push( msg )
 | 
|---|
 | 667 | 
 | 
|---|
 | 668 |         self.seltext = {}
 | 
|---|
 | 669 | 
 | 
|---|
 | 670 |     @asaplog_post_dec
 | 
|---|
 | 671 |     def cancel_delete(self):
 | 
|---|
 | 672 |         """
 | 
|---|
 | 673 |         Cancel deleting the selected note.
 | 
|---|
 | 674 |         Called when 'cancel' button selected on confirmation dialog.
 | 
|---|
 | 675 |         """
 | 
|---|
 | 676 |         asaplog.push( "Cancel deleting: '"+self.seltext['textobj'].get_text()+"'" )
 | 
|---|
 | 677 |         self.seltext = {}
 | 
|---|
 | 678 | 
 | 
|---|
 | 679 | 
 | 
|---|
 | 680 | 
 | 
|---|
 | 681 | ###########################################
 | 
|---|
 | 682 | ##    Add CASA custom Flag toolbar       ##
 | 
|---|
 | 683 | ###########################################
 | 
|---|
 | 684 | class CustomFlagToolbarCommon:
 | 
|---|
 | 685 |     def __init__(self,parent):
 | 
|---|
 | 686 |         self.plotter=parent
 | 
|---|
 | 687 |         #self.figmgr=self.plotter._plotter.figmgr
 | 
|---|
 | 688 |         self._selregions = {}
 | 
|---|
 | 689 |         self._selpanels = []
 | 
|---|
 | 690 |         self._polygons = []
 | 
|---|
 | 691 |         self._thisregion = None
 | 
|---|
 | 692 |         self.xdataold=None
 | 
|---|
 | 693 | 
 | 
|---|
 | 694 |     ### select the nearest spectrum in pick radius
 | 
|---|
 | 695 |     ###    and display spectral value on the toolbar.
 | 
|---|
 | 696 |     def _select_spectrum(self,event):
 | 
|---|
 | 697 |         # Do not fire event when in zooming/panning mode
 | 
|---|
 | 698 |         mode = self.figmgr.toolbar.mode
 | 
|---|
 | 699 |         if not mode == '':
 | 
|---|
 | 700 |             return
 | 
|---|
 | 701 |             # When selected point is out of panels
 | 
|---|
 | 702 |         if event.inaxes == None:
 | 
|---|
 | 703 |             return
 | 
|---|
 | 704 |         # If not left button
 | 
|---|
 | 705 |         if event.button != 1:
 | 
|---|
 | 706 |             return
 | 
|---|
 | 707 | 
 | 
|---|
 | 708 |         xclick = event.xdata
 | 
|---|
 | 709 |         yclick = event.ydata
 | 
|---|
 | 710 |         dist2 = 1000.
 | 
|---|
 | 711 |         pickline = None
 | 
|---|
 | 712 |         # If the pannel has picable objects
 | 
|---|
 | 713 |         pflag = False
 | 
|---|
 | 714 |         for lin in event.inaxes.lines:
 | 
|---|
 | 715 |             if not lin.pickable():
 | 
|---|
 | 716 |                 continue
 | 
|---|
 | 717 |             pflag = True
 | 
|---|
 | 718 |             flag,pind = lin.contains(event)
 | 
|---|
 | 719 |             if not flag:
 | 
|---|
 | 720 |                 continue
 | 
|---|
 | 721 |             # Get nearest point
 | 
|---|
 | 722 |             inds = pind['ind']
 | 
|---|
 | 723 |             xlin = lin.get_xdata()
 | 
|---|
 | 724 |             ylin = lin.get_ydata()
 | 
|---|
 | 725 |             for i in inds:
 | 
|---|
 | 726 |                 d2=(xlin[i]-xclick)**2+(ylin[i]-yclick)**2
 | 
|---|
 | 727 |                 if dist2 >= d2:
 | 
|---|
 | 728 |                     dist2 = d2
 | 
|---|
 | 729 |                     pickline = lin
 | 
|---|
 | 730 |         # No pickcable line in the pannel
 | 
|---|
 | 731 |         if not pflag:
 | 
|---|
 | 732 |             return
 | 
|---|
 | 733 |         # Pickable but too far from mouse position
 | 
|---|
 | 734 |         elif pickline is None:
 | 
|---|
 | 735 |             picked = 'No line selected.'
 | 
|---|
 | 736 |             self.figmgr.toolbar.set_message(picked)
 | 
|---|
 | 737 |             return
 | 
|---|
 | 738 |         del pind, inds, xlin, ylin
 | 
|---|
 | 739 |         # Spectra are Picked
 | 
|---|
 | 740 |         theplot = self.plotter._plotter
 | 
|---|
 | 741 |         thetoolbar = self.figmgr.toolbar
 | 
|---|
 | 742 |         thecanvas = self.figmgr.canvas
 | 
|---|
 | 743 |         # Disconnect the default motion notify event
 | 
|---|
 | 744 |         # Notice! the other buttons are also diabled!!!
 | 
|---|
 | 745 |         thecanvas.mpl_disconnect(thetoolbar._idDrag)
 | 
|---|
 | 746 |         # Get picked spectrum
 | 
|---|
 | 747 |         xdata = pickline.get_xdata()
 | 
|---|
 | 748 |         ydata = pickline.get_ydata()
 | 
|---|
 | 749 |         titl = pickline.get_label()
 | 
|---|
 | 750 |         titp = event.inaxes.title.get_text()
 | 
|---|
 | 751 |         panel0 = event.inaxes
 | 
|---|
 | 752 |         picked = "Selected: '"+titl+"' in panel '"+titp+"'."
 | 
|---|
 | 753 |         thetoolbar.set_message(picked)
 | 
|---|
 | 754 |         # Generate a navigation window
 | 
|---|
 | 755 |         #naviwin=Navigationwindow(titp,titl)
 | 
|---|
 | 756 |         #------------------------------------------------------#
 | 
|---|
 | 757 |         # Show spectrum data at mouse position
 | 
|---|
 | 758 |         def spec_data(event):
 | 
|---|
 | 759 |             # Getting spectrum data of neiboring point
 | 
|---|
 | 760 |             xclick = event.xdata
 | 
|---|
 | 761 |             if event.inaxes != panel0:
 | 
|---|
 | 762 |                 return
 | 
|---|
 | 763 |             ipoint = len(xdata)-1
 | 
|---|
 | 764 |             for i in range(len(xdata)-1):
 | 
|---|
 | 765 |                 xl = xclick-xdata[i]
 | 
|---|
 | 766 |                 xr = xclick-xdata[i+1]
 | 
|---|
 | 767 |                 if xl*xr <= 0.:
 | 
|---|
 | 768 |                     ipoint = i
 | 
|---|
 | 769 |                     break
 | 
|---|
 | 770 |             # Output spectral value on the navigation window
 | 
|---|
 | 771 |             posi = '[ %s, %s ]:  x = %.2f   value = %.2f'\
 | 
|---|
 | 772 |                   %(titl,titp,xdata[ipoint],ydata[ipoint])
 | 
|---|
 | 773 |             #naviwin.posi.set(posi)
 | 
|---|
 | 774 |             thetoolbar.set_message(posi)
 | 
|---|
 | 775 |         #------------------------------------------------------#
 | 
|---|
 | 776 |         # Disconnect from mouse events
 | 
|---|
 | 777 |         def discon(event):
 | 
|---|
 | 778 |             #naviwin.window.destroy()
 | 
|---|
 | 779 |             theplot.register('motion_notify',None)
 | 
|---|
 | 780 |             # Re-activate the default motion_notify_event
 | 
|---|
 | 781 |             thetoolbar._idDrag=thecanvas.mpl_connect('motion_notify_event',
 | 
|---|
 | 782 |                                                      thetoolbar.mouse_move)
 | 
|---|
 | 783 |             theplot.register('button_release',None)
 | 
|---|
 | 784 |             return
 | 
|---|
 | 785 |         #------------------------------------------------------#
 | 
|---|
 | 786 |         # Show data value along with mouse movement
 | 
|---|
 | 787 |         theplot.register('motion_notify',spec_data)
 | 
|---|
 | 788 |         # Finish events when mouse button is released
 | 
|---|
 | 789 |         theplot.register('button_release',discon)
 | 
|---|
 | 790 | 
 | 
|---|
 | 791 | 
 | 
|---|
 | 792 |     ### Notation
 | 
|---|
 | 793 |     def _mod_note(self,event):
 | 
|---|
 | 794 |         # Do not fire event when in zooming/panning mode
 | 
|---|
 | 795 |         if not self.figmgr.toolbar.mode == '':
 | 
|---|
 | 796 |             return
 | 
|---|
 | 797 |         if event.button == 1:
 | 
|---|
 | 798 |             self.notewin.load_textwindow(event)
 | 
|---|
 | 799 |         elif event.button == 3 and self._note_picked(event):
 | 
|---|
 | 800 |             self.notewin.load_modmenu(event)
 | 
|---|
 | 801 |         return
 | 
|---|
 | 802 | 
 | 
|---|
 | 803 |     def _note_picked(self,event):
 | 
|---|
 | 804 |         # just briefly check if any texts are picked
 | 
|---|
 | 805 |         for textobj in self.canvas.figure.texts:
 | 
|---|
 | 806 |             if textobj.contains(event)[0]:
 | 
|---|
 | 807 |                 return True
 | 
|---|
 | 808 |         for ax in self.canvas.figure.axes:
 | 
|---|
 | 809 |             for textobj in ax.texts:
 | 
|---|
 | 810 |                 if textobj.contains(event)[0]:
 | 
|---|
 | 811 |                     return True
 | 
|---|
 | 812 |         return False
 | 
|---|
 | 813 | 
 | 
|---|
 | 814 |     ### Region/Panel selection & oparations
 | 
|---|
 | 815 |     ### add regions to selections
 | 
|---|
 | 816 |     @asaplog_post_dec
 | 
|---|
 | 817 |     def _add_region(self,event):
 | 
|---|
 | 818 |         if not self.figmgr.toolbar.mode == '':
 | 
|---|
 | 819 |             return
 | 
|---|
 | 820 |         if event.button != 1 or event.inaxes == None:
 | 
|---|
 | 821 |             return
 | 
|---|
 | 822 |         # this row resolution assumes row panelling
 | 
|---|
 | 823 |         irow = int(self._getrownum(event.inaxes))
 | 
|---|
 | 824 |         if irow in self._selpanels:
 | 
|---|
 | 825 |             msg = "The whole spectrum is already selected"
 | 
|---|
 | 826 |             asaplog.post()
 | 
|---|
 | 827 |             asaplog.push(msg)
 | 
|---|
 | 828 |             asaplog.post('WARN')
 | 
|---|
 | 829 |             return
 | 
|---|
 | 830 |         self._thisregion = {'axes': event.inaxes,'xs': event.x,
 | 
|---|
 | 831 |                             'worldx': [event.xdata,event.xdata]}
 | 
|---|
 | 832 |         self.plotter._plotter.register('button_press',None)
 | 
|---|
| [2171] | 833 |         self.xold = event.x
 | 
|---|
 | 834 |         self.xdataold = event.xdata
 | 
|---|
| [2155] | 835 |         self.plotter._plotter.register('motion_notify', self._xspan_draw)
 | 
|---|
 | 836 |         self.plotter._plotter.register('button_press', self._xspan_end)
 | 
|---|
 | 837 | 
 | 
|---|
 | 838 |     def _xspan_draw(self,event):
 | 
|---|
 | 839 |         if event.inaxes == self._thisregion['axes']:
 | 
|---|
 | 840 |             xnow = event.x
 | 
|---|
| [2171] | 841 |             self.xold = xnow
 | 
|---|
 | 842 |             self.xdataold = event.xdata
 | 
|---|
| [2155] | 843 |         else:
 | 
|---|
| [2171] | 844 |             xnow = self.xold
 | 
|---|
| [2155] | 845 |         try: self.lastspan
 | 
|---|
 | 846 |         except AttributeError: pass
 | 
|---|
| [2172] | 847 |         else:
 | 
|---|
 | 848 |             if self.lastspan: self._remove_span(self.lastspan)
 | 
|---|
| [2155] | 849 | 
 | 
|---|
 | 850 |         #self.lastspan = self._draw_span(self._thisregion['axes'],self._thisregion['xs'],xnow,fill="#555555",stipple="gray50")
 | 
|---|
 | 851 |         self.lastspan = self._draw_span(self._thisregion['axes'],self._thisregion['xs'],xnow,fill="")
 | 
|---|
 | 852 |         del xnow
 | 
|---|
 | 853 | 
 | 
|---|
 | 854 |     def _draw_span(self,axes,x0,x1,**kwargs):
 | 
|---|
 | 855 |         pass
 | 
|---|
 | 856 | 
 | 
|---|
 | 857 |     def _remove_span(self,span):
 | 
|---|
 | 858 |         pass
 | 
|---|
 | 859 | 
 | 
|---|
 | 860 |     @asaplog_post_dec
 | 
|---|
 | 861 |     def _xspan_end(self,event):
 | 
|---|
 | 862 |         if not self.figmgr.toolbar.mode == '':
 | 
|---|
 | 863 |             return
 | 
|---|
 | 864 |         if event.button != 1:
 | 
|---|
 | 865 |             return
 | 
|---|
 | 866 | 
 | 
|---|
 | 867 |         try: self.lastspan
 | 
|---|
 | 868 |         except AttributeError: pass
 | 
|---|
 | 869 |         else:
 | 
|---|
 | 870 |             self._remove_span(self.lastspan)
 | 
|---|
 | 871 |             del self.lastspan
 | 
|---|
 | 872 |         if event.inaxes == self._thisregion['axes']:
 | 
|---|
 | 873 |             xdataend = event.xdata
 | 
|---|
 | 874 |         else:
 | 
|---|
| [2172] | 875 |             xdataend = self.xdataold
 | 
|---|
| [2155] | 876 | 
 | 
|---|
 | 877 |         self._thisregion['worldx'][1] = xdataend
 | 
|---|
 | 878 |         lregion = self._thisregion['worldx']
 | 
|---|
 | 879 |         pregion = self._thisregion['axes'].axvspan(lregion[0],lregion[1],
 | 
|---|
 | 880 |                                                    facecolor='0.7')
 | 
|---|
 | 881 |         self.plotter._plotter.canvas.draw()
 | 
|---|
 | 882 |         self._polygons.append(pregion)
 | 
|---|
 | 883 |         srow = self._getrownum(self._thisregion['axes'])
 | 
|---|
 | 884 |         irow = int(srow)
 | 
|---|
 | 885 |         if not self._selregions.has_key(srow):
 | 
|---|
 | 886 |             self._selregions[srow] = []
 | 
|---|
 | 887 |         self._selregions[srow].append(lregion)
 | 
|---|
| [2172] | 888 |         del lregion, pregion, xdataend
 | 
|---|
| [2155] | 889 |         sout = "selected region: "+str(self._thisregion['worldx'])+\
 | 
|---|
 | 890 |               "(@row "+str(self._getrownum(self._thisregion['axes']))+")"
 | 
|---|
 | 891 |         asaplog.push(sout)
 | 
|---|
 | 892 | 
 | 
|---|
 | 893 |         # release event
 | 
|---|
 | 894 |         self.plotter._plotter.register('button_press',None)
 | 
|---|
 | 895 |         self.plotter._plotter.register('motion_notify',None)
 | 
|---|
 | 896 |         # Clear up region selection
 | 
|---|
 | 897 |         self._thisregion = None
 | 
|---|
 | 898 |         self.xdataold = None
 | 
|---|
| [2172] | 899 |         self.xold = None
 | 
|---|
| [2155] | 900 |         # finally recover region selection event
 | 
|---|
 | 901 |         self.plotter._plotter.register('button_press',self._add_region)
 | 
|---|
 | 902 | 
 | 
|---|
 | 903 |     ### add panels to selections
 | 
|---|
 | 904 |     @asaplog_post_dec
 | 
|---|
 | 905 |     def _add_panel(self,event):
 | 
|---|
 | 906 |         if not self.figmgr.toolbar.mode == '':
 | 
|---|
 | 907 |             return
 | 
|---|
 | 908 |         if event.button != 1 or event.inaxes == None:
 | 
|---|
 | 909 |             return
 | 
|---|
 | 910 |         selax = event.inaxes
 | 
|---|
 | 911 |         # this row resolution assumes row panelling
 | 
|---|
 | 912 |         srow = self._getrownum(selax)
 | 
|---|
 | 913 |         irow = int(srow)
 | 
|---|
 | 914 |         if srow:
 | 
|---|
 | 915 |             self._selpanels.append(irow)
 | 
|---|
 | 916 |         shadow = Rectangle((0,0),1,1,facecolor='0.7',transform=selax.transAxes,visible=True)
 | 
|---|
 | 917 |         self._polygons.append(selax.add_patch(shadow))
 | 
|---|
 | 918 |         #self.plotter._plotter.show(False)
 | 
|---|
 | 919 |         self.plotter._plotter.canvas.draw()
 | 
|---|
 | 920 |         asaplog.push("row "+str(irow)+" is selected")
 | 
|---|
 | 921 |         ## check for region selection of the spectra and overwrite it.
 | 
|---|
 | 922 |         ##!!!! currently disabled for consistency with flag tools !!!!
 | 
|---|
 | 923 |         #if self._selregions.has_key(srow):
 | 
|---|
 | 924 |         #    self._selregions.pop(srow)
 | 
|---|
 | 925 |         #    msg = "The whole spectrum is selected for row="+srow+". Region selection will be overwritten."
 | 
|---|
 | 926 |         #    asaplog.push(msg)
 | 
|---|
 | 927 | 
 | 
|---|
 | 928 |     def _getrownum(self,axis):
 | 
|---|
 | 929 |         ### returns the row number of selected spectrum as a string ###
 | 
|---|
 | 930 |         plabel = axis.get_title()
 | 
|---|
 | 931 |         if plabel.startswith("row "):
 | 
|---|
 | 932 |             return plabel.strip("row ")
 | 
|---|
 | 933 |         return None
 | 
|---|
 | 934 | 
 | 
|---|
 | 935 |     def _any_selection(self):
 | 
|---|
 | 936 |         ### returns if users have selected any spectrum or region ###
 | 
|---|
 | 937 |         if len(self._selpanels) or len(self._selregions):
 | 
|---|
 | 938 |             return True
 | 
|---|
 | 939 |         return False
 | 
|---|
 | 940 | 
 | 
|---|
 | 941 |     def _plot_selections(self,regions=None,panels=None):
 | 
|---|
 | 942 |         ### mark panels/spectra selections in the page
 | 
|---|
 | 943 |         if not self._any_selection() and not (regions or panels):
 | 
|---|
 | 944 |             return
 | 
|---|
 | 945 |         regions = regions or self._selregions.copy() or {}
 | 
|---|
 | 946 |         panels = panels or self._selpanels or []
 | 
|---|
 | 947 |         if not isinstance(regions,dict):
 | 
|---|
 | 948 |             asaplog.post()
 | 
|---|
 | 949 |             asaplog.push("Invalid region specification")
 | 
|---|
 | 950 |             asaplog.post('ERROR')
 | 
|---|
 | 951 |         if not isinstance(panels,list):
 | 
|---|
 | 952 |             asaplog.post()
 | 
|---|
 | 953 |             asaplog.push("Invalid panel specification")
 | 
|---|
 | 954 |             asaplog.post('ERROR')
 | 
|---|
 | 955 |         strow = self._getrownum(self.plotter._plotter.subplots[0]['axes'])
 | 
|---|
 | 956 |         enrow = self._getrownum(self.plotter._plotter.subplots[-1]['axes'])
 | 
|---|
 | 957 |         for irow in range(int(strow),int(enrow)+1):
 | 
|---|
 | 958 |             if regions.has_key(str(irow)):
 | 
|---|
 | 959 |                 ax = self.plotter._plotter.subplots[irow - int(strow)]['axes']
 | 
|---|
 | 960 |                 mlist = regions.pop(str(irow))
 | 
|---|
 | 961 |                 for i in range(len(mlist)):
 | 
|---|
 | 962 |                     self._polygons.append(ax.axvspan(mlist[i][0],mlist[i][1],
 | 
|---|
 | 963 |                                                      facecolor='0.7'))
 | 
|---|
 | 964 |                 del ax,mlist
 | 
|---|
 | 965 |             if irow in panels:
 | 
|---|
 | 966 |                 ax = self.plotter._plotter.subplots[irow - int(strow)]['axes']
 | 
|---|
 | 967 |                 shadow = Rectangle((0,0),1,1,facecolor='0.7',
 | 
|---|
 | 968 |                                    transform=ax.transAxes,visible=True)
 | 
|---|
 | 969 |                 self._polygons.append(ax.add_patch(shadow))
 | 
|---|
 | 970 |                 del ax,shadow
 | 
|---|
 | 971 |         self.plotter._plotter.canvas.draw()
 | 
|---|
 | 972 |         del regions,panels,strow,enrow
 | 
|---|
 | 973 | 
 | 
|---|
 | 974 |     def _clear_selection_plot(self, refresh=True):
 | 
|---|
 | 975 |         ### clear up polygons which mark selected spectra and regions ###
 | 
|---|
 | 976 |         if len(self._polygons) > 0:
 | 
|---|
 | 977 |             for shadow in self._polygons:
 | 
|---|
 | 978 |                 shadow.remove()
 | 
|---|
 | 979 |             if refresh: self.plotter._plotter.canvas.draw()
 | 
|---|
 | 980 |         self._polygons = []
 | 
|---|
 | 981 | 
 | 
|---|
 | 982 |     def _clearup_selections(self, refresh=True):
 | 
|---|
 | 983 |         # clear-up selection and polygons
 | 
|---|
 | 984 |         self._selpanels = []
 | 
|---|
 | 985 |         self._selregions = {}
 | 
|---|
 | 986 |         self._clear_selection_plot(refresh=refresh)
 | 
|---|
 | 987 | 
 | 
|---|
 | 988 |     ### clear up selections
 | 
|---|
 | 989 |     def cancel_select(self):
 | 
|---|
 | 990 |         self.figmgr.toolbar.set_message('selections canceled')
 | 
|---|
 | 991 |         # clear-up selection and polygons
 | 
|---|
 | 992 |         self._clearup_selections(refresh=True)
 | 
|---|
 | 993 | 
 | 
|---|
 | 994 |     ### flag selected spectra/regions
 | 
|---|
 | 995 |     @asaplog_post_dec
 | 
|---|
 | 996 |     def flag(self):
 | 
|---|
 | 997 |         if not self._any_selection():
 | 
|---|
 | 998 |             msg = "No selection to be Flagged"
 | 
|---|
 | 999 |             asaplog.post()
 | 
|---|
 | 1000 |             asaplog.push(msg)
 | 
|---|
 | 1001 |             asaplog.post('WARN')
 | 
|---|
 | 1002 |             return
 | 
|---|
 | 1003 |         self._pause_buttons(operation="start",msg="Flagging data...")
 | 
|---|
 | 1004 |         self._flag_operation(rows=self._selpanels,
 | 
|---|
 | 1005 |                              regions=self._selregions,unflag=False)
 | 
|---|
 | 1006 |         sout = "Flagged:\n"
 | 
|---|
 | 1007 |         sout += "  rows = "+str(self._selpanels)+"\n"
 | 
|---|
 | 1008 |         sout += "  regions: "+str(self._selregions)
 | 
|---|
 | 1009 |         asaplog.push(sout)
 | 
|---|
 | 1010 |         del sout
 | 
|---|
 | 1011 |         self.plotter._ismodified = True
 | 
|---|
 | 1012 |         self._clearup_selections(refresh=False)
 | 
|---|
 | 1013 |         self._plot_page(pagemode="current")
 | 
|---|
 | 1014 |         self._pause_buttons(operation="end")
 | 
|---|
 | 1015 | 
 | 
|---|
 | 1016 |     ### unflag selected spectra/regions
 | 
|---|
 | 1017 |     @asaplog_post_dec
 | 
|---|
 | 1018 |     def unflag(self):
 | 
|---|
 | 1019 |         if not self._any_selection():
 | 
|---|
 | 1020 |             msg = "No selection to be Flagged"
 | 
|---|
 | 1021 |             asaplog.push(msg)
 | 
|---|
 | 1022 |             asaplog.post('WARN')
 | 
|---|
 | 1023 |             return
 | 
|---|
 | 1024 |         self._pause_buttons(operation="start",msg="Unflagging data...")
 | 
|---|
 | 1025 |         self._flag_operation(rows=self._selpanels,
 | 
|---|
 | 1026 |                              regions=self._selregions,unflag=True)
 | 
|---|
 | 1027 |         sout = "Unflagged:\n"
 | 
|---|
 | 1028 |         sout += "  rows = "+str(self._selpanels)+"\n"
 | 
|---|
 | 1029 |         sout += "  regions: "+str(self._selregions)
 | 
|---|
 | 1030 |         asaplog.push(sout)
 | 
|---|
 | 1031 |         del sout
 | 
|---|
 | 1032 |         self.plotter._ismodified = True
 | 
|---|
 | 1033 |         self._clearup_selections(refresh=False)
 | 
|---|
 | 1034 |         self._plot_page(pagemode="current")
 | 
|---|
 | 1035 |         self._pause_buttons(operation="end")
 | 
|---|
 | 1036 | 
 | 
|---|
 | 1037 |     ### actual flag operation
 | 
|---|
 | 1038 |     @asaplog_post_dec
 | 
|---|
 | 1039 |     def _flag_operation(self,rows=None,regions=None,unflag=False):
 | 
|---|
 | 1040 |         scan = self.plotter._data
 | 
|---|
 | 1041 |         if not scan:
 | 
|---|
 | 1042 |             asaplog.post()
 | 
|---|
 | 1043 |             asaplog.push("Invalid scantable")
 | 
|---|
 | 1044 |             asaplog.post("ERROR")
 | 
|---|
 | 1045 |         if isinstance(rows,list) and len(rows) > 0:
 | 
|---|
 | 1046 |             scan.flag_row(rows=rows,unflag=unflag)
 | 
|---|
 | 1047 |         if isinstance(regions,dict) and len(regions) > 0:
 | 
|---|
 | 1048 |             for srow, masklist in regions.iteritems():
 | 
|---|
 | 1049 |                 if not isinstance(masklist,list) or len(masklist) ==0:
 | 
|---|
 | 1050 |                     msg = "Ignoring invalid region selection for row = "+srow
 | 
|---|
 | 1051 |                     asaplog.post()
 | 
|---|
 | 1052 |                     asaplog.push(msg)
 | 
|---|
 | 1053 |                     asaplog.post("WARN")
 | 
|---|
 | 1054 |                     continue
 | 
|---|
 | 1055 |                 irow = int(srow)
 | 
|---|
 | 1056 |                 mask = scan.create_mask(masklist,invert=False,row=irow)
 | 
|---|
 | 1057 |                 scan.flag(row=irow,mask=mask,unflag=unflag)
 | 
|---|
 | 1058 |                 del irow, mask
 | 
|---|
 | 1059 |             del srow, masklist
 | 
|---|
 | 1060 |         del scan
 | 
|---|
 | 1061 | 
 | 
|---|
 | 1062 |     ### show statistics of selected spectra/regions
 | 
|---|
 | 1063 |     @asaplog_post_dec
 | 
|---|
 | 1064 |     def stat_cal(self):
 | 
|---|
 | 1065 |         if not self._any_selection():
 | 
|---|
 | 1066 |             msg = "No selection to be calculated"
 | 
|---|
 | 1067 |             asaplog.push(msg)
 | 
|---|
 | 1068 |             asaplog.post('WARN')
 | 
|---|
 | 1069 |             return
 | 
|---|
 | 1070 |         self._selected_stats(rows=self._selpanels,regions=self._selregions)
 | 
|---|
 | 1071 |         self._clearup_selections(refresh=True)
 | 
|---|
 | 1072 | 
 | 
|---|
 | 1073 |     @asaplog_post_dec
 | 
|---|
 | 1074 |     def _selected_stats(self,rows=None,regions=None):
 | 
|---|
 | 1075 |         scan = self.plotter._data
 | 
|---|
 | 1076 |         if not scan:
 | 
|---|
 | 1077 |             asaplog.post()
 | 
|---|
 | 1078 |             asaplog.push("Invalid scantable")
 | 
|---|
 | 1079 |             asaplog.post("ERROR")
 | 
|---|
 | 1080 |         mathobj = stmath( rcParams['insitu'] )
 | 
|---|
 | 1081 |         statval = {}
 | 
|---|
 | 1082 |         statstr = ['max', 'min', 'mean', 'median', 'sum', 'stddev', 'rms']
 | 
|---|
| [2324] | 1083 |         if isinstance(rows, list) and len(rows) > 0:
 | 
|---|
| [2155] | 1084 |             for irow in rows:
 | 
|---|
 | 1085 |                 for stat in statstr:
 | 
|---|
 | 1086 |                     statval[stat] = mathobj._statsrow(scan,[],stat,irow)[0]
 | 
|---|
 | 1087 |                 self._print_stats(scan,irow,statval,statstr=statstr)
 | 
|---|
 | 1088 |             del irow
 | 
|---|
 | 1089 |         if isinstance(regions,dict) and len(regions) > 0:
 | 
|---|
 | 1090 |             for srow, masklist in regions.iteritems():
 | 
|---|
 | 1091 |                 if not isinstance(masklist,list) or len(masklist) ==0:
 | 
|---|
 | 1092 |                     msg = "Ignoring invalid region selection for row = "+srow
 | 
|---|
 | 1093 |                     asaplog.post()
 | 
|---|
 | 1094 |                     asaplog.push(msg)
 | 
|---|
 | 1095 |                     asaplog.post("WARN")
 | 
|---|
 | 1096 |                     continue
 | 
|---|
 | 1097 |                 irow = int(srow)
 | 
|---|
 | 1098 |                 mask = scan.create_mask(masklist,invert=False,row=irow)
 | 
|---|
 | 1099 |                 for stat in statstr:
 | 
|---|
 | 1100 |                     statval[stat] = mathobj._statsrow(scan,mask,stat,irow)[0]
 | 
|---|
| [2324] | 1101 |                 self._print_stats(scan,irow,statval,statstr=statstr,
 | 
|---|
 | 1102 |                                   mask=masklist)
 | 
|---|
| [2155] | 1103 |                 del irow, mask
 | 
|---|
 | 1104 |             del srow, masklist
 | 
|---|
 | 1105 |         del scan, statval, mathobj
 | 
|---|
 | 1106 | 
 | 
|---|
 | 1107 |     @asaplog_post_dec
 | 
|---|
 | 1108 |     def _print_stats(self,scan,row,stats,statstr=None,mask=None):
 | 
|---|
 | 1109 |         if not isinstance(scan, scantable):
 | 
|---|
 | 1110 |             asaplog.post()
 | 
|---|
 | 1111 |             asaplog.push("Invalid scantable")
 | 
|---|
 | 1112 |             asaplog.post("ERROR")
 | 
|---|
 | 1113 |         if row < 0 or row > scan.nrow():
 | 
|---|
 | 1114 |             asaplog.post()
 | 
|---|
 | 1115 |             asaplog.push("Invalid row number")
 | 
|---|
 | 1116 |             asaplog.post("ERROR")
 | 
|---|
 | 1117 |         if not isinstance(stats,dict) or len(stats) == 0:
 | 
|---|
 | 1118 |             asaplog.post()
 | 
|---|
 | 1119 |             asaplog.push("Invalid statistic value")
 | 
|---|
 | 1120 |             asaplog.post("ERROR")
 | 
|---|
 | 1121 |         maskstr = "All"
 | 
|---|
 | 1122 |         if mask:
 | 
|---|
 | 1123 |             maskstr = str(mask)
 | 
|---|
 | 1124 |         ssep = "-"*70+"\n"
 | 
|---|
 | 1125 |         sout = ssep
 | 
|---|
 | 1126 |         sout += ("Row=%d  Scan=%d  IF=%d  Pol=%d  Time=%s  mask=%s" % \
 | 
|---|
 | 1127 |                  (row, scan.getscan(row), scan.getif(row), scan.getpol(row), scan.get_time(row),maskstr))
 | 
|---|
 | 1128 |         sout += "\n"
 | 
|---|
 | 1129 |         statvals = []
 | 
|---|
 | 1130 |         if not len(statstr):
 | 
|---|
 | 1131 |             statstr = stats.keys()
 | 
|---|
 | 1132 |         for key in statstr:
 | 
|---|
 | 1133 |             sout += key.ljust(10)
 | 
|---|
 | 1134 |             statvals.append(stats.pop(key))
 | 
|---|
 | 1135 |         sout += "\n"
 | 
|---|
 | 1136 |         sout += ("%f "*len(statstr) % tuple(statvals))
 | 
|---|
 | 1137 |         sout += "\n"+ssep
 | 
|---|
 | 1138 |         asaplog.push(sout)
 | 
|---|
 | 1139 |         del sout, ssep, maskstr, statvals, key, scan, row, stats, statstr, mask
 | 
|---|
 | 1140 | 
 | 
|---|
 | 1141 |     ### Page chages
 | 
|---|
 | 1142 |     ### go to the previous page
 | 
|---|
 | 1143 |     def prev_page(self):
 | 
|---|
 | 1144 |         self._pause_buttons(operation="start",msg='plotting the previous page')
 | 
|---|
 | 1145 |         self._clear_selection_plot(refresh=False)
 | 
|---|
 | 1146 |         self._plot_page(pagemode="prev")
 | 
|---|
 | 1147 |         self._plot_selections()
 | 
|---|
 | 1148 |         self._pause_buttons(operation="end")
 | 
|---|
 | 1149 | 
 | 
|---|
 | 1150 |     ### go to the next page
 | 
|---|
 | 1151 |     def next_page(self):
 | 
|---|
 | 1152 |         self._pause_buttons(operation="start",msg='plotting the next page')
 | 
|---|
 | 1153 |         self._clear_selection_plot(refresh=False)
 | 
|---|
 | 1154 |         self._plot_page(pagemode="next")
 | 
|---|
 | 1155 |         self._plot_selections()
 | 
|---|
 | 1156 |         self._pause_buttons(operation="end")
 | 
|---|
 | 1157 | 
 | 
|---|
 | 1158 |     ### actual plotting of the new page
 | 
|---|
 | 1159 |     def _plot_page(self,pagemode="next"):
 | 
|---|
 | 1160 |         if self.plotter._startrow <= 0:
 | 
|---|
 | 1161 |             msg = "The page counter is reset due to chages of plot settings. "
 | 
|---|
 | 1162 |             msg += "Plotting from the first page."
 | 
|---|
 | 1163 |             asaplog.post()
 | 
|---|
 | 1164 |             asaplog.push(msg)
 | 
|---|
 | 1165 |             asaplog.post('WARN')
 | 
|---|
 | 1166 |             goback = False
 | 
|---|
 | 1167 | 
 | 
|---|
 | 1168 |         self.plotter._plotter.hold()
 | 
|---|
 | 1169 |         self.plotter._plotter.legend(1)
 | 
|---|
 | 1170 |         self._set_plot_counter(pagemode)
 | 
|---|
 | 1171 |         self.plotter._plot(self.plotter._data)
 | 
|---|
 | 1172 |         self.set_pagecounter(self._get_pagenum())
 | 
|---|
 | 1173 |         self.plotter._plotter.release()
 | 
|---|
 | 1174 |         self.plotter._plotter.tidy()
 | 
|---|
 | 1175 |         self.plotter._plotter.show(hardrefresh=False)
 | 
|---|
 | 1176 | 
 | 
|---|
 | 1177 |     ### calculate the panel ID and start row to plot a page
 | 
|---|
 | 1178 |     #def _set_prevpage_counter(self):
 | 
|---|
 | 1179 |     def _set_plot_counter(self, pagemode):
 | 
|---|
 | 1180 |         ## page operation should be either "previous", "current", or "next"
 | 
|---|
 | 1181 |         availpage = ["p","c","n"]
 | 
|---|
 | 1182 |         pageop = pagemode[0].lower()
 | 
|---|
 | 1183 |         if not (pageop in availpage):
 | 
|---|
 | 1184 |             asaplog.post()
 | 
|---|
 | 1185 |             asaplog.push("Invalid page operation")
 | 
|---|
 | 1186 |             asaplog.post("ERROR")
 | 
|---|
 | 1187 |         if pageop == "n":
 | 
|---|
 | 1188 |             # nothing necessary to plot the next page
 | 
|---|
 | 1189 |             return
 | 
|---|
 | 1190 |         # set row and panel counters to those of the 1st panel of previous page
 | 
|---|
 | 1191 |         maxpanel = 16
 | 
|---|
 | 1192 |         # the ID of the last panel in current plot
 | 
|---|
 | 1193 |         lastpanel = self.plotter._ipanel
 | 
|---|
 | 1194 |         # the number of current subplots
 | 
|---|
 | 1195 |         currpnum = len(self.plotter._plotter.subplots)
 | 
|---|
 | 1196 | 
 | 
|---|
 | 1197 |         # the nuber of previous subplots
 | 
|---|
 | 1198 |         start_ipanel = None
 | 
|---|
 | 1199 |         if pageop == "c":
 | 
|---|
 | 1200 |             start_ipanel = max(lastpanel-currpnum+1, 0)
 | 
|---|
 | 1201 |         else:
 | 
|---|
 | 1202 |             ## previous page
 | 
|---|
 | 1203 |             prevpnum = None
 | 
|---|
 | 1204 |             if self.plotter._rows and self.plotter._cols:
 | 
|---|
 | 1205 |                 # when user set layout
 | 
|---|
 | 1206 |                 prevpnum = self.plotter._rows*self.plotter._cols
 | 
|---|
 | 1207 |             else:
 | 
|---|
 | 1208 |                 # no user specification
 | 
|---|
 | 1209 |                 prevpnum = maxpanel
 | 
|---|
 | 1210 |             start_ipanel = max(lastpanel-currpnum-prevpnum+1, 0)
 | 
|---|
 | 1211 |             del prevpnum
 | 
|---|
 | 1212 | 
 | 
|---|
 | 1213 |         # set the pannel ID of the last panel of the prev(-prev) page
 | 
|---|
 | 1214 |         self.plotter._ipanel = start_ipanel-1
 | 
|---|
 | 1215 |         if self.plotter._panelling == 'r':
 | 
|---|
 | 1216 |             self.plotter._startrow = start_ipanel
 | 
|---|
 | 1217 |         else:
 | 
|---|
 | 1218 |             # the start row number of the next panel
 | 
|---|
 | 1219 |             self.plotter._startrow = self.plotter._panelrows[start_ipanel]
 | 
|---|
 | 1220 |         del lastpanel,currpnum,start_ipanel
 | 
|---|
 | 1221 | 
 | 
|---|
 | 1222 |     ### refresh the page counter
 | 
|---|
 | 1223 |     def set_pagecounter(self,page):
 | 
|---|
 | 1224 |         nwidth = int(numpy.ceil(numpy.log10(max(page,1))))+1
 | 
|---|
 | 1225 |         nwidth = max(nwidth,4)
 | 
|---|
 | 1226 |         formatstr = '%'+str(nwidth)+'d'
 | 
|---|
 | 1227 |         self.show_pagenum(page,formatstr)
 | 
|---|
 | 1228 | 
 | 
|---|
 | 1229 |     def show_pagenum(self,pagenum,formatstr):
 | 
|---|
 | 1230 |         # passed to backend dependent class
 | 
|---|
 | 1231 |         pass
 | 
|---|
 | 1232 | 
 | 
|---|
 | 1233 |     def _get_pagenum(self):
 | 
|---|
 | 1234 |         maxpanel = 16
 | 
|---|
 | 1235 |         # get the ID of last panel in the current page
 | 
|---|
 | 1236 |         idlastpanel = self.plotter._ipanel
 | 
|---|
 | 1237 |         if self.plotter._rows and self.plotter._cols:
 | 
|---|
 | 1238 |             ppp = self.plotter._rows*self.plotter._cols
 | 
|---|
 | 1239 |         else:
 | 
|---|
 | 1240 |             ppp = maxpanel
 | 
|---|
 | 1241 |         return int(idlastpanel/ppp)+1
 | 
|---|
 | 1242 | 
 | 
|---|
 | 1243 |     # pause buttons for slow operations. implemented at a backend dependent class
 | 
|---|
 | 1244 |     def _pause_buttons(self,operation="end",msg=""):
 | 
|---|
 | 1245 |         pass
 | 
|---|