00001 from asap.asapplotter import asapplotter
00002 from asap.logging import asaplog, asaplog_post_dec
00003
00004 from asap.parameters import rcParams
00005 from asap.selector import selector
00006 from asap.scantable import scantable
00007 import matplotlib.axes
00008 from matplotlib.font_manager import FontProperties
00009 from matplotlib.text import Text
00010
00011 class flagplotter(asapplotter):
00012 """
00013 The flag plotter
00014 Only row based panneling is allowed.
00015
00016 Example:
00017 scan = asa p.scantable(filename='your_filename',average=False)
00018 guiflagger = asap.flagplotter(visible=True)
00019 guiflagger.plot(scan)
00020 ### flag/Unflag data graphically.
00021 guiflagger.save_data(name='flagged_file.asap',format='ASAP')
00022
00023 NOTICE:
00024 The flagged data is not saved until you explicitly run scantable.save
00025 """
00026 def __init__(self, visible=None, **kwargs):
00027 self._scan = None
00028 asapplotter.__init__(self,visible=visible, **kwargs)
00029 self._assert_plotter(action='reload')
00030 self._plotter._set_window_title('Flag Plotter')
00031 self._panelling = 'r'
00032 self.set_stacking('scan')
00033 self._ismodified = False
00034 self._showflagged = False
00035 self.set_colors("blue gray",False)
00036
00037 def _new_custombar(self):
00038 backend = matplotlib.get_backend()
00039
00040 if not self._visible:
00041 asaplog.push("GUI backend is not available")
00042 asaplog.post("ERROR")
00043 elif backend == "TkAgg":
00044 from asap.customgui_tkagg import CustomFlagToolbarTkAgg
00045 return CustomFlagToolbarTkAgg(self)
00046 elif backend == "Qt4Agg":
00047 from asap.customgui_qt4agg import CustomFlagToolbarQT4Agg
00048 return CustomFlagToolbarQT4Agg(self)
00049 else:
00050 asaplog.push("Unsupported backend for interactive flagging. Use either TkAgg or PyQt4Agg")
00051 asaplog.post("ERROR")
00052
00053 def set_showflagged(self, show):
00054 """ Whether or not plotting flagged data"""
00055 if type(show) == bool:
00056 self._showflagged = show
00057 else:
00058 raise TypeError, "Input parameter should be a bool."
00059
00060 @asaplog_post_dec
00061 def _invalid_func(self, name):
00062 msg = "Invalid function 'flagplotter."+name+"'"
00063
00064 asaplog.push(msg)
00065 asaplog.post('ERROR')
00066
00067 def set_panelling(self,which='r'):
00068 """ This function is not available for the class flagplotter """
00069 if which.lower().startswith('r'):
00070 return
00071 msg = "Pannel setting is fixed to row mode in 'flagplotter'"
00072 asaplog.push(msg)
00073 asaplog.post('ERROR')
00074 self._panelling = 'r'
00075
00076 def set_range(self,xstart=None,xend=None,ystart=None,yend=None,refresh=False, offset=None):
00077 """ This function is not available for the class flagplotter """
00078 msg = "Plot range setting is not allowed in 'flagplotter'"
00079 asaplog.push(msg)
00080 asaplog.post('ERROR')
00081 self._panelling = 'r'
00082
00083 def plotazel(self,*args,**kwargs):
00084 """ This function is not available for the class flagplotter """
00085 self._invalid_func(name='plotazel')
00086
00087 def plotpointing(self,*args,**kwargs):
00088 """ This function is not available for the class flagplotter """
00089 self._invalid_func(name='plotpointing')
00090
00091 def plottp(self,*args,**kwargs):
00092 """ This function is not available for the class flagplotter """
00093 self._invalid_func(name='plottp')
00094
00095 def save_data(self, name=None, format=None, overwrite=False):
00096 """
00097 Store the plotted scantable on disk.
00098 This function simply redirects call to scantable.save()
00099
00100 Parameters:
00101
00102 name: the name of the outputfile. For format "ASCII"
00103 this is the root file name (data in 'name'.txt
00104 and header in 'name'_header.txt)
00105
00106 format: an optional file format. Default is ASAP.
00107 Allowed are:
00108 * 'ASAP' (save as ASAP [aips++] Table),
00109 * 'SDFITS' (save as SDFITS file)
00110 * 'ASCII' (saves as ascii text file)
00111 * 'MS2' (saves as an casacore MeasurementSet V2)
00112 * 'FITS' (save as image FITS - not readable by class)
00113 * 'CLASS' (save as FITS readable by CLASS)
00114
00115 overwrite: If the file should be overwritten if it exists.
00116 The default False is to return with warning
00117 without writing the output. USE WITH CARE.
00118 """
00119 if not self._data:
00120 raise RuntimeError("No scantable has been set yet.")
00121
00122 self._data.save(name,format,overwrite)
00123
00124 def set_data(self, scan, refresh=True):
00125 if self._is_new_scan(scan):
00126 self._ismodified = False
00127 asapplotter.set_data(self, scan, refresh)
00128 set_data.__doc__ = asapplotter.set_data.__doc__
00129
00130 @asaplog_post_dec
00131 def plot(self, scan=None):
00132 if self._is_new_scan(scan):
00133 self._ismodified = False
00134 if not self._showflagged:
00135 self.set_legend(mode=None,refresh=False)
00136 elif not self._legendloc:
00137 self.set_legend(mode=1,refresh=False)
00138 asapplotter.plot(self,scan)
00139 plot.__doc__ = asapplotter.plot.__doc__
00140
00141 @asaplog_post_dec
00142 def _plot(self, scan):
00143 self._plot_with_flag(scan,self._showflagged)
00144
00145
00146 ganged = (self._plotter.axes._sharex != None)
00147 if ganged:
00148 np = 1
00149 else:
00150 np = len(self._plotter.subplots)
00151 for ip in xrange(np):
00152 ax = self._plotter.subplots[ip]['axes']
00153 lim0 = ax.get_xlim()
00154 offset = (lim0[1]-lim0[0])*0.05
00155 ax.set_xlim(lim0[0]-offset,lim0[1]+offset)
00156 del ax, lim0, offset
00157 _plot.__doc__ = asapplotter._plot.__doc__
00158
00159
00160 @asaplog_post_dec
00161 def _plot_with_flag(self, scan, showflag=False):
00162
00163 nptot = scan.nrow()
00164
00165 n = nptot - self._ipanel - 1
00166 ganged = False
00167 maxpanel = 25
00168
00169 if n > 1:
00170 ganged = rcParams['plotter.ganged']
00171 if self._rows and self._cols:
00172 n = min(n,self._rows*self._cols)
00173 self._plotter.set_panels(rows=self._rows,cols=self._cols,
00174 nplots=n,margin=self._margins,ganged=ganged)
00175 else:
00176 n = min(n,maxpanel)
00177 self._plotter.set_panels(rows=n,cols=0,nplots=n,margin=self._margins,ganged=ganged)
00178 else:
00179 self._plotter.set_panels(margin=self._margins)
00180
00181 r = self._startrow
00182
00183 nr = scan.nrow()
00184 panelcount = 0
00185 allylim = []
00186 allxlim = []
00187
00188 while r < nr:
00189
00190 self._plotter.subplot(panelcount)
00191 self._plotter.palette(0)
00192
00193 xlab = self._abcissa and self._abcissa[panelcount] \
00194 or scan._getabcissalabel()
00195 if self._offset and not self._abcissa:
00196 xlab += " (relative)"
00197 ylab = self._ordinate and self._ordinate[panelcount] \
00198 or scan._get_ordinate_label()
00199 self._plotter.set_axes('xlabel', xlab)
00200 self._plotter.set_axes('ylabel', ylab)
00201 lbl = self._get_label(scan, r, mode='title', userlabel=self._title)
00202 if type(lbl) in (list, tuple):
00203 if 0 <= panelcount < len(lbl):
00204 lbl = lbl[panelcount]
00205 else:
00206
00207 lbl = self._get_label(scan, r, 'title')
00208 self._plotter.set_axes('title',lbl)
00209 panelcount += 1
00210
00211 y = scan._getspectrum(r)
00212
00213 mr = scan._getflagrow(r)
00214 from numpy import ma, array
00215 if mr:
00216 ys = ma.masked_array(y,mask=mr)
00217 if showflag:
00218 yf = ma.masked_array(y, mask=(not mr))
00219 else:
00220 m = scan._getmask(r)
00221 from numpy import logical_not, logical_and
00222 if self._maskselection and len(self._usermask) == len(m):
00223 if d[self._stacking](r) in self._maskselection[self._stacking]:
00224 m = logical_and(m, self._usermask)
00225 ys = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
00226 if showflag:
00227 yf = ma.masked_array(y,mask=m)
00228
00229 x = array(scan._getabcissa(r))
00230 if self._offset:
00231 x += self._offset
00232
00233
00234
00235
00236 self._plotter.set_line(label="data")
00237
00238
00239 self._plotter.plot(x,ys)
00240 if showflag:
00241 self._plotter.set_line(label="flagged")
00242 self._plotter.plot(x,yf)
00243 ylim = self._minmaxy or [min(y),max(y)]
00244 xlim= self._minmaxx or [min(x),max(x)]
00245 elif mr or ys.mask.all():
00246 ylim = self._minmaxy or []
00247 xlim = self._minmaxx or []
00248 else:
00249 ylim = self._minmaxy or [ma.minimum(ys),ma.maximum(ys)]
00250 xlim= self._minmaxx or [min(x),max(x)]
00251 allylim += ylim
00252 allxlim += xlim
00253 if (panelcount == n) or (r == nr-1):
00254 break
00255 r+=1
00256
00257
00258 if ganged:
00259 xlim = None
00260 ylim = None
00261 if len(allylim) > 0:
00262 allylim.sort()
00263 ylim = allylim[0],allylim[-1]
00264 if len(allxlim) > 0:
00265 allxlim.sort()
00266 xlim = allxlim[0],allxlim[-1]
00267 self._plotter.set_limits(xlim=xlim,ylim=ylim)
00268
00269
00270 self._startrow = r+1
00271 self._ipanel += panelcount
00272 if self.casabar_exists():
00273 if self._ipanel >= nptot-1:
00274 self._plotter.figmgr.casabar.disable_next()
00275 else:
00276 self._plotter.figmgr.casabar.enable_next()
00277 if self._ipanel + 1 - panelcount > 0:
00278 self._plotter.figmgr.casabar.enable_prev()
00279 else:
00280 self._plotter.figmgr.casabar.disable_prev()
00281
00282
00283
00284 def _get_label(self, scan, row, mode='title', userlabel=None):
00285 if isinstance(userlabel, list) and len(userlabel) == 0:
00286 userlabel = " "
00287 elif not mode.upper().startswith('T'):
00288 pms = dict(zip(self._selection.get_pols(), \
00289 self._selection.get_poltypes()))
00290 if len(pms):
00291 poleval = scan._getpollabel(scan.getpol(row), \
00292 pms[scan.getpol(row)])
00293 else:
00294 poleval = scan._getpollabel(scan.getpol(row),scan.poltype())
00295 label = "IF%d, POL %s, Scan%d" % \
00296 (scan.getif(row),poleval,scan.getscan(row))
00297 else:
00298 label = "row %d" % (row)
00299
00300 return userlabel or label
00301
00302
00303 def _is_new_scan(self,scan):
00304 if isinstance(scan, scantable):
00305 if self._data is not None:
00306 if scan != self._data:
00307 return True
00308 else:
00309 return True
00310 return False