casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables
flagplotter.py
Go to the documentation of this file.
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         # Flag plotter relys on supported GUI backends
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         #raise AttributeError(msg)
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         # simply calls scantable.save
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         #asapplotter._plot(self,scan)
00145         # rescale x-range of subplots 5% margins
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         # total number of panles to plot as a whole
00163         nptot = scan.nrow()
00164         # remaining panels to plot
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         #r = 0
00181         r = self._startrow
00182         # total row number of scantable
00183         nr = scan.nrow()
00184         panelcount = 0
00185         allylim = []
00186         allxlim = []
00187         
00188         while r < nr:
00189             # always plot to new panel
00190             self._plotter.subplot(panelcount)
00191             self._plotter.palette(0)
00192             # title and axes labels
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                     # get default label
00207                     lbl = self._get_label(scan, r, 'title')
00208             self._plotter.set_axes('title',lbl)
00209             panelcount += 1
00210             # Now get data to plot
00211             y = scan._getspectrum(r)
00212             # Check for FLAGROW column
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             #llbl = self._get_label(scan, r, mode='legend', userlabel=self._lmap)
00233             #if type(llbl) in (list, tuple):
00234             #    llbl = llbl[0]
00235             #self._plotter.set_line(label=llbl)
00236             self._plotter.set_line(label="data")
00237             #plotit = self._plotter.plot
00238             #if self._hist: plotit = self._plotter.hist
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 # next row
00256 
00257         # Set x- and y- limts of subplots
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         # save the current counter for multi-page plotting
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