Changeset 2012


Ignore:
Timestamp:
02/25/11 16:51:50 (13 years ago)
Author:
WataruKawasaki
Message:

New Development: Yes

JIRA Issue: Yes (CAS-2373, CAS-2620)

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed: For Scantable::polyBaseline(), parameters and return value have been changed.

Test Programs:

Put in Release Notes: Yes

Module(s): sdbaseline, sd.linefinder

Description: (1) CAS-2373-related:

(1.1) Modified Scantable::polyBaseline() to have the row-based loop inside.

Now it fits and subtracts baseline for all rows and also output info
about the fitting result to logger and text file, while in the
previous version this method just did baseline fitting/subtraction
for one row only and had to be put inside a row-based loop at the
python side ("poly_baseline()" in scantable.py) and result output had
also to be controlled at the python side. Using a test data from NRO
45m telescope (348,000 rows, 512 channels), the processing time of
scantable.poly_baseline() has reduced from 130 minutes to 5-6 minutes.

(1.2) For accelerating the another polynomial fitting function, namely

scantable.auto_poly_baseline(), added a method
Scantable::autoPolyBaseline(). This basically does the same thing
with Scantable::polyBaseline(), but uses linefinfer also to
automatically flag the line regions.

(1.3) To make linefinder usable in Scantable class, added a method

linefinder.setdata(). This makes it possible to apply linefinder
for a float-list data given as a parameter, without setting scantable,
while it was indispensable to set scantable to use linefinger previously.

(2) CAS-2620-related:

Added Scantable::cubicSplineBaseline() and autoCubicSplineBaseline() for
fit baseline using the cubic spline function. Parameters include npiece
(number of polynomial pieces), clipthresh (clipping threshold), and
clipniter (maximum iteration number).



Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/python/asaplinefind.py

    r1826 r2012  
    101101        self.finder.setscan(scan)
    102102
     103    def set_data(self, spectrum):
     104        """
     105        Set the 'data' (spectrum) to work with
     106        Parameters: a method to allow linefinder work without setting scantable
     107        for the purpose of using linefinder inside some method in scantable
     108        class. (Dec 22, 2010 by W.Kawasaki)
     109        """
     110        if isinstance(spectrum, list) or isinstance(spectrum, tuple):
     111            if not isinstance(spectrum[0], float):
     112                raise RuntimeError, "Parameter 'spectrum' has to be a list or a tuple of float"
     113        else:
     114            raise RuntimeError, "Parameter 'spectrum' has to be a list or a tuple of float"
     115        self.finder.setdata(spectrum)
     116       
    103117    def find_lines(self,nRow=0,mask=[],edge=(0,0)):
    104118        """
  • trunk/python/scantable.py

    r2008 r2012  
    18981898        else: return s
    18991899
     1900
     1901    @asaplog_post_dec
     1902    def cspline_baseline(self, insitu=None, mask=None, npiece=None, clipthresh=None, clipniter=None, plot=None, outlog=None, blfile=None):
     1903        """\
     1904        Return a scan which has been baselined (all rows) by cubic spline function (piecewise cubic polynomial).
     1905        Parameters:
     1906            insitu:     If False a new scantable is returned.
     1907                        Otherwise, the scaling is done in-situ
     1908                        The default is taken from .asaprc (False)
     1909            mask:       An optional mask
     1910            npiece:     Number of pieces. (default is 2)
     1911            clipthresh: Clipping threshold. (default is 3.0, unit: sigma)
     1912            clipniter:  maximum number of iteration of 'clipthresh'-sigma clipping (default is 1)
     1913            plot:   *** CURRENTLY UNAVAILABLE, ALWAYS FALSE ***
     1914                        plot the fit and the residual. In this each
     1915                        indivual fit has to be approved, by typing 'y'
     1916                        or 'n'
     1917            outlog:     Output the coefficients of the best-fit
     1918                        function to logger (default is False)
     1919            blfile:     Name of a text file in which the best-fit
     1920                        parameter values to be written
     1921                        (default is "": no file/logger output)
     1922
     1923        Example:
     1924            # return a scan baselined by a cubic spline consisting of 2 pieces (i.e., 1 internal knot),
     1925            # also with 3-sigma clipping, iteration up to 4 times
     1926            bscan = scan.cspline_baseline(npiece=2,clipthresh=3.0,clipniter=4)
     1927        """
     1928       
     1929        varlist = vars()
     1930       
     1931        if insitu is None: insitu = rcParams["insitu"]
     1932        if insitu:
     1933            workscan = self
     1934        else:
     1935            workscan = self.copy()
     1936
     1937        nchan = workscan.nchan()
     1938       
     1939        if mask is None: mask = [True for i in xrange(nchan)]
     1940        if npiece is None: npiece = 2
     1941        if clipthresh is None: clipthresh = 3.0
     1942        if clipniter is None: clipniter = 1
     1943        if plot is None: plot = False
     1944        if outlog is None: outlog = False
     1945        if blfile is None: blfile = ""
     1946
     1947        outblfile = (blfile != "") and os.path.exists(os.path.expanduser(os.path.expandvars(blfile)))
     1948       
     1949        try:
     1950            #CURRENTLY, PLOT=true UNAVAILABLE UNTIL cubic spline fitting is implemented as a fitter method.
     1951            workscan._cspline_baseline(mask, npiece, clipthresh, clipniter, outlog, blfile)
     1952           
     1953            workscan._add_history("cspline_baseline", varlist)
     1954           
     1955            if insitu:
     1956                self._assign(workscan)
     1957            else:
     1958                return workscan
     1959           
     1960        except RuntimeError, e:
     1961            msg = "The fit failed, possibly because it didn't converge."
     1962            if rcParams["verbose"]:
     1963                asaplog.push(str(e))
     1964                asaplog.push(str(msg))
     1965                return
     1966            else:
     1967                raise RuntimeError(str(e)+'\n'+msg)
     1968
     1969
     1970    def auto_cspline_baseline(self, insitu=None, mask=None, npiece=None, clipthresh=None,
     1971                              clipniter=None, edge=None, threshold=None,
     1972                              chan_avg_limit=None, plot=None, outlog=None, blfile=None):
     1973        """\
     1974        Return a scan which has been baselined (all rows) by cubic spline
     1975        function (piecewise cubic polynomial).
     1976        Spectral lines are detected first using linefinder and masked out
     1977        to avoid them affecting the baseline solution.
     1978
     1979        Parameters:
     1980            insitu:     if False a new scantable is returned.
     1981                        Otherwise, the scaling is done in-situ
     1982                        The default is taken from .asaprc (False)
     1983            mask:       an optional mask retreived from scantable
     1984            npiece:     Number of pieces. (default is 2)
     1985            clipthresh: Clipping threshold. (default is 3.0, unit: sigma)
     1986            clipniter:  maximum number of iteration of 'clipthresh'-sigma clipping (default is 1)
     1987            edge:       an optional number of channel to drop at
     1988                        the edge of spectrum. If only one value is
     1989                        specified, the same number will be dropped
     1990                        from both sides of the spectrum. Default
     1991                        is to keep all channels. Nested tuples
     1992                        represent individual edge selection for
     1993                        different IFs (a number of spectral channels
     1994                        can be different)
     1995            threshold:  the threshold used by line finder. It is
     1996                        better to keep it large as only strong lines
     1997                        affect the baseline solution.
     1998            chan_avg_limit:
     1999                        a maximum number of consequtive spectral
     2000                        channels to average during the search of
     2001                        weak and broad lines. The default is no
     2002                        averaging (and no search for weak lines).
     2003                        If such lines can affect the fitted baseline
     2004                        (e.g. a high order polynomial is fitted),
     2005                        increase this parameter (usually values up
     2006                        to 8 are reasonable). Most users of this
     2007                        method should find the default value sufficient.
     2008            plot:   *** CURRENTLY UNAVAILABLE, ALWAYS FALSE ***
     2009                        plot the fit and the residual. In this each
     2010                        indivual fit has to be approved, by typing 'y'
     2011                        or 'n'
     2012            outlog:     Output the coefficients of the best-fit
     2013                        function to logger (default is False)
     2014            blfile:     Name of a text file in which the best-fit
     2015                        parameter values to be written
     2016                        (default is "": no file/logger output)
     2017
     2018        Example:
     2019            bscan = scan.auto_cspline_baseline(npiece=3, insitu=False)
     2020        """
     2021
     2022        varlist = vars()
     2023
     2024        if insitu is None: insitu = rcParams['insitu']
     2025        if insitu:
     2026            workscan = self
     2027        else:
     2028            workscan = self.copy()
     2029
     2030        nchan = workscan.nchan()
     2031       
     2032        if mask is None: mask = [True for i in xrange(nchan)]
     2033        if npiece is None: npiece = 2
     2034        if clipthresh is None: clipthresh = 3.0
     2035        if clipniter is None: clipniter = 1
     2036        if edge is None: edge = (0, 0)
     2037        if threshold is None: threshold = 3
     2038        if chan_avg_limit is None: chan_avg_limit = 1
     2039        if plot is None: plot = False
     2040        if outlog is None: outlog = False
     2041        if blfile is None: blfile = ""
     2042
     2043        outblfile = (blfile != "") and os.path.exists(os.path.expanduser(os.path.expandvars(blfile)))
     2044       
     2045        from asap.asaplinefind import linefinder
     2046        from asap import _is_sequence_or_number as _is_valid
     2047
     2048        if not (isinstance(edge, list) or isinstance(edge, tuple)): edge = [ edge ]
     2049        individualedge = False;
     2050        if len(edge) > 1: individualedge = isinstance(edge[0], list) or isinstance(edge[0], tuple)
     2051
     2052        if individualedge:
     2053            for edgepar in edge:
     2054                if not _is_valid(edgepar, int):
     2055                    raise ValueError, "Each element of the 'edge' tuple has \
     2056                                       to be a pair of integers or an integer."
     2057        else:
     2058            if not _is_valid(edge, int):
     2059                raise ValueError, "Parameter 'edge' has to be an integer or a \
     2060                                   pair of integers specified as a tuple. \
     2061                                   Nested tuples are allowed \
     2062                                   to make individual selection for different IFs."
     2063
     2064            if len(edge) > 1:
     2065                curedge = edge
     2066            else:
     2067                curedge = edge + edge
     2068
     2069        try:
     2070            #CURRENTLY, PLOT=true UNAVAILABLE UNTIL cubic spline fitting is implemented as a fitter method.
     2071            if individualedge:
     2072                curedge = []
     2073                for i in xrange(len(edge)):
     2074                    curedge += edge[i]
     2075               
     2076            workscan._auto_cspline_baseline(mask, npiece, clipthresh, clipniter, curedge, threshold, chan_avg_limit, outlog, blfile)
     2077
     2078            workscan._add_history("auto_cspline_baseline", varlist)
     2079           
     2080            if insitu:
     2081                self._assign(workscan)
     2082            else:
     2083                return workscan
     2084           
     2085        except RuntimeError, e:
     2086            msg = "The fit failed, possibly because it didn't converge."
     2087            if rcParams["verbose"]:
     2088                asaplog.push(str(e))
     2089                asaplog.push(str(msg))
     2090                return
     2091            else:
     2092                raise RuntimeError(str(e)+'\n'+msg)
     2093
     2094
     2095    @asaplog_post_dec
     2096    def poly_baseline(self, insitu=None, mask=None, order=None, plot=None, outlog=None, blfile=None):
     2097        """\
     2098        Return a scan which has been baselined (all rows) by a polynomial.
     2099        Parameters:
     2100            insitu:     if False a new scantable is returned.
     2101                        Otherwise, the scaling is done in-situ
     2102                        The default is taken from .asaprc (False)
     2103            mask:       an optional mask
     2104            order:      the order of the polynomial (default is 0)
     2105            plot:       plot the fit and the residual. In this each
     2106                        indivual fit has to be approved, by typing 'y'
     2107                        or 'n'
     2108            outlog:     Output the coefficients of the best-fit
     2109                        function to logger (default is False)
     2110            blfile:     Name of a text file in which the best-fit
     2111                        parameter values to be written
     2112                        (default is "": no file/logger output)
     2113
     2114        Example:
     2115            # return a scan baselined by a third order polynomial,
     2116            # not using a mask
     2117            bscan = scan.poly_baseline(order=3)
     2118        """
     2119       
     2120        varlist = vars()
     2121       
     2122        if insitu is None: insitu = rcParams["insitu"]
     2123        if insitu:
     2124            workscan = self
     2125        else:
     2126            workscan = self.copy()
     2127
     2128        nchan = workscan.nchan()
     2129       
     2130        if mask is None: mask = [True for i in xrange(nchan)]
     2131        if order is None: order = 0
     2132        if plot is None: plot = False
     2133        if outlog is None: outlog = False
     2134        if blfile is None: blfile = ""
     2135
     2136        outblfile = (blfile != "") and os.path.exists(os.path.expanduser(os.path.expandvars(blfile)))
     2137       
     2138        try:
     2139            rows = xrange(workscan.nrow())
     2140           
     2141            #if len(rows) > 0: workscan._init_blinfo()
     2142
     2143            if plot:
     2144                if outblfile: blf = open(blfile, "a")
     2145               
     2146                f = fitter()
     2147                f.set_function(lpoly=order)
     2148                for r in rows:
     2149                    f.x = workscan._getabcissa(r)
     2150                    f.y = workscan._getspectrum(r)
     2151                    f.mask = mask_and(mask, workscan._getmask(r))    # (CAS-1434)
     2152                    f.data = None
     2153                    f.fit()
     2154                   
     2155                    f.plot(residual=True)
     2156                    accept_fit = raw_input("Accept fit ( [y]/n ): ")
     2157                    if accept_fit.upper() == "N":
     2158                        #workscan._append_blinfo(None, None, None)
     2159                        continue
     2160                   
     2161                    blpars = f.get_parameters()
     2162                    masklist = workscan.get_masklist(f.mask, row=r, silent=True)
     2163                    #workscan._append_blinfo(blpars, masklist, f.mask)
     2164                    workscan._setspectrum(f.fitter.getresidual(), r)
     2165                   
     2166                    if outblfile:
     2167                        rms = workscan.get_rms(f.mask, r)
     2168                        dataout = workscan.format_blparams_row(blpars["params"], blpars["fixed"], rms, str(masklist), r, True)
     2169                        blf.write(dataout)
     2170
     2171                f._p.unmap()
     2172                f._p = None
     2173
     2174                if outblfile: blf.close()
     2175            else:
     2176                workscan._poly_baseline(mask, order, outlog, blfile)
     2177           
     2178            workscan._add_history("poly_baseline", varlist)
     2179           
     2180            if insitu:
     2181                self._assign(workscan)
     2182            else:
     2183                return workscan
     2184           
     2185        except RuntimeError, e:
     2186            msg = "The fit failed, possibly because it didn't converge."
     2187            if rcParams["verbose"]:
     2188                asaplog.push(str(e))
     2189                asaplog.push(str(msg))
     2190                return
     2191            else:
     2192                raise RuntimeError(str(e)+'\n'+msg)
     2193
     2194
     2195    def auto_poly_baseline(self, insitu=None, mask=None, order=None, edge=None, threshold=None,
     2196                           chan_avg_limit=None, plot=None, outlog=None, blfile=None):
     2197        """\
     2198        Return a scan which has been baselined (all rows) by a polynomial.
     2199        Spectral lines are detected first using linefinder and masked out
     2200        to avoid them affecting the baseline solution.
     2201
     2202        Parameters:
     2203            insitu:     if False a new scantable is returned.
     2204                        Otherwise, the scaling is done in-situ
     2205                        The default is taken from .asaprc (False)
     2206            mask:       an optional mask retreived from scantable
     2207            order:      the order of the polynomial (default is 0)
     2208            edge:       an optional number of channel to drop at
     2209                        the edge of spectrum. If only one value is
     2210                        specified, the same number will be dropped
     2211                        from both sides of the spectrum. Default
     2212                        is to keep all channels. Nested tuples
     2213                        represent individual edge selection for
     2214                        different IFs (a number of spectral channels
     2215                        can be different)
     2216            threshold:  the threshold used by line finder. It is
     2217                        better to keep it large as only strong lines
     2218                        affect the baseline solution.
     2219            chan_avg_limit:
     2220                        a maximum number of consequtive spectral
     2221                        channels to average during the search of
     2222                        weak and broad lines. The default is no
     2223                        averaging (and no search for weak lines).
     2224                        If such lines can affect the fitted baseline
     2225                        (e.g. a high order polynomial is fitted),
     2226                        increase this parameter (usually values up
     2227                        to 8 are reasonable). Most users of this
     2228                        method should find the default value sufficient.
     2229            plot:       plot the fit and the residual. In this each
     2230                        indivual fit has to be approved, by typing 'y'
     2231                        or 'n'
     2232            outlog:     Output the coefficients of the best-fit
     2233                        function to logger (default is False)
     2234            blfile:     Name of a text file in which the best-fit
     2235                        parameter values to be written
     2236                        (default is "": no file/logger output)
     2237
     2238        Example:
     2239            bscan = scan.auto_poly_baseline(order=7, insitu=False)
     2240        """
     2241
     2242        varlist = vars()
     2243
     2244        if insitu is None: insitu = rcParams['insitu']
     2245        if insitu:
     2246            workscan = self
     2247        else:
     2248            workscan = self.copy()
     2249
     2250        nchan = workscan.nchan()
     2251       
     2252        if mask is None: mask = [True for i in xrange(nchan)]
     2253        if order is None: order = 0
     2254        if edge is None: edge = (0, 0)
     2255        if threshold is None: threshold = 3
     2256        if chan_avg_limit is None: chan_avg_limit = 1
     2257        if plot is None: plot = False
     2258        if outlog is None: outlog = False
     2259        if blfile is None: blfile = ""
     2260
     2261        outblfile = (blfile != "") and os.path.exists(os.path.expanduser(os.path.expandvars(blfile)))
     2262       
     2263        from asap.asaplinefind import linefinder
     2264        from asap import _is_sequence_or_number as _is_valid
     2265
     2266        if not (isinstance(edge, list) or isinstance(edge, tuple)): edge = [ edge ]
     2267        individualedge = False;
     2268        if len(edge) > 1: individualedge = isinstance(edge[0], list) or isinstance(edge[0], tuple)
     2269
     2270        if individualedge:
     2271            for edgepar in edge:
     2272                if not _is_valid(edgepar, int):
     2273                    raise ValueError, "Each element of the 'edge' tuple has \
     2274                                       to be a pair of integers or an integer."
     2275        else:
     2276            if not _is_valid(edge, int):
     2277                raise ValueError, "Parameter 'edge' has to be an integer or a \
     2278                                   pair of integers specified as a tuple. \
     2279                                   Nested tuples are allowed \
     2280                                   to make individual selection for different IFs."
     2281
     2282            if len(edge) > 1:
     2283                curedge = edge
     2284            else:
     2285                curedge = edge + edge
     2286
     2287        try:
     2288            rows = xrange(workscan.nrow())
     2289           
     2290            #if len(rows) > 0: workscan._init_blinfo()
     2291
     2292            if plot:
     2293                if outblfile: blf = open(blfile, "a")
     2294               
     2295                fl = linefinder()
     2296                fl.set_options(threshold=threshold,avg_limit=chan_avg_limit)
     2297                fl.set_scan(workscan)
     2298                f = fitter()
     2299                f.set_function(lpoly=order)
     2300
     2301                for r in rows:
     2302                    if individualedge:
     2303                        if len(edge) <= workscan.getif(r):
     2304                            raise RuntimeError, "Number of edge elements appear to " \
     2305                                  "be less than the number of IFs"
     2306                        else:
     2307                            curedge = edge[workscan.getif(r)]
     2308
     2309                    fl.find_lines(r, mask_and(mask, workscan._getmask(r)), curedge)  # (CAS-1434)
     2310
     2311                    f.x = workscan._getabcissa(r)
     2312                    f.y = workscan._getspectrum(r)
     2313                    f.mask = fl.get_mask()
     2314                    f.data = None
     2315                    f.fit()
     2316
     2317                    f.plot(residual=True)
     2318                    accept_fit = raw_input("Accept fit ( [y]/n ): ")
     2319                    if accept_fit.upper() == "N":
     2320                        #workscan._append_blinfo(None, None, None)
     2321                        continue
     2322
     2323                    blpars = f.get_parameters()
     2324                    masklist = workscan.get_masklist(f.mask, row=r, silent=True)
     2325                    #workscan._append_blinfo(blpars, masklist, f.mask)
     2326                    workscan._setspectrum(f.fitter.getresidual(), r)
     2327
     2328                    if outblfile:
     2329                        rms = workscan.get_rms(f.mask, r)
     2330                        dataout = workscan.format_blparams_row(blpars["params"], blpars["fixed"], rms, str(masklist), r, True)
     2331                        blf.write(dataout)
     2332                   
     2333                f._p.unmap()
     2334                f._p = None
     2335
     2336                if outblfile: blf.close()
     2337               
     2338            else:
     2339                if individualedge:
     2340                    curedge = []
     2341                    for i in xrange(len(edge)):
     2342                        curedge += edge[i]
     2343               
     2344                workscan._auto_poly_baseline(mask, order, curedge, threshold, chan_avg_limit, outlog, blfile)
     2345
     2346            workscan._add_history("auto_poly_baseline", varlist)
     2347           
     2348            if insitu:
     2349                self._assign(workscan)
     2350            else:
     2351                return workscan
     2352           
     2353        except RuntimeError, e:
     2354            msg = "The fit failed, possibly because it didn't converge."
     2355            if rcParams["verbose"]:
     2356                asaplog.push(str(e))
     2357                asaplog.push(str(msg))
     2358                return
     2359            else:
     2360                raise RuntimeError(str(e)+'\n'+msg)
     2361
     2362
     2363    ### OBSOLETE ##################################################################
    19002364    @asaplog_post_dec
    19012365    def old_poly_baseline(self, mask=None, order=0, plot=False, uselin=False, insitu=None, rows=None):
    1902         """\
     2366        """
    19032367        Return a scan which has been baselined (all rows) by a polynomial.
    19042368       
     
    19852449            raise RuntimeError(msg)
    19862450
    1987     @asaplog_post_dec
    1988     def poly_baseline(self, mask=None, order=0, plot=False, batch=False, insitu=None, rows=None):
    1989         """\
    1990         Return a scan which has been baselined (all rows) by a polynomial.
    1991         Parameters:
    1992             mask:       an optional mask
    1993             order:      the order of the polynomial (default is 0)
    1994             plot:       plot the fit and the residual. In this each
    1995                         indivual fit has to be approved, by typing 'y'
    1996                         or 'n'. Ignored if batch = True.
    1997             batch:      if True a faster algorithm is used and logs
    1998                         including the fit results are not output
    1999                         (default is False)
    2000             insitu:     if False a new scantable is returned.
    2001                         Otherwise, the scaling is done in-situ
    2002                         The default is taken from .asaprc (False)
    2003             rows:       row numbers of spectra to be baselined.
    2004                         (default is None: for all rows)
    2005         Example:
    2006             # return a scan baselined by a third order polynomial,
    2007             # not using a mask
    2008             bscan = scan.poly_baseline(order=3)
    2009         """
     2451    def _init_blinfo(self):
     2452        """\
     2453        Initialise the following three auxiliary members:
     2454           blpars : parameters of the best-fit baseline,
     2455           masklists : mask data (edge positions of masked channels) and
     2456           actualmask : mask data (in boolean list),
     2457        to keep for use later (including output to logger/text files).
     2458        Used by poly_baseline() and auto_poly_baseline() in case of
     2459        'plot=True'.
     2460        """
     2461        self.blpars = []
     2462        self.masklists = []
     2463        self.actualmask = []
     2464        return
     2465
     2466    def _append_blinfo(self, data_blpars, data_masklists, data_actualmask):
     2467        """\
     2468        Append baseline-fitting related info to blpars, masklist and
     2469        actualmask.
     2470        """
     2471        self.blpars.append(data_blpars)
     2472        self.masklists.append(data_masklists)
     2473        self.actualmask.append(data_actualmask)
     2474        return
    20102475       
    2011         varlist = vars()
    2012        
    2013         if insitu is None: insitu = rcParams["insitu"]
    2014         if insitu:
    2015             workscan = self
    2016         else:
    2017             workscan = self.copy()
    2018 
    2019         nchan = workscan.nchan()
    2020        
    2021         if mask is None:
    2022             mask = [True for i in xrange(nchan)]
    2023 
    2024         try:
    2025             if rows == None:
    2026                 rows = xrange(workscan.nrow())
    2027             elif isinstance(rows, int):
    2028                 rows = [ rows ]
    2029            
    2030             if len(rows) > 0:
    2031                 workscan.blpars = []
    2032                 workscan.masklists = []
    2033                 workscan.actualmask = []
    2034 
    2035             if batch:
    2036                 workscan._poly_baseline_batch(mask, order)
    2037             elif plot:
    2038                 f = fitter()
    2039                 f.set_function(lpoly=order)
    2040                 for r in rows:
    2041                     f.x = workscan._getabcissa(r)
    2042                     f.y = workscan._getspectrum(r)
    2043                     f.mask = mask_and(mask, workscan._getmask(r))    # (CAS-1434)
    2044                     f.data = None
    2045                     f.fit()
    2046                    
    2047                     f.plot(residual=True)
    2048                     accept_fit = raw_input("Accept fit ( [y]/n ): ")
    2049                     if accept_fit.upper() == "N":
    2050                         self.blpars.append(None)
    2051                         self.masklists.append(None)
    2052                         self.actualmask.append(None)
    2053                         continue
    2054                     workscan._setspectrum(f.fitter.getresidual(), r)
    2055                     workscan.blpars.append(f.get_parameters())
    2056                     workscan.masklists.append(workscan.get_masklist(f.mask, row=r))
    2057                     workscan.actualmask.append(f.mask)
    2058                    
    2059                 f._p.unmap()
    2060                 f._p = None
    2061             else:
    2062                 for r in rows:
    2063                     fitparams = workscan._poly_baseline(mask, order, r)
    2064                     params = fitparams.getparameters()
    2065                     fmtd = ", ".join(["p%d = %3.6f" % (i, v) for i, v in enumerate(params)])
    2066                     errors = fitparams.geterrors()
    2067                     fmask = mask_and(mask, workscan._getmask(r))
    2068 
    2069                     workscan.blpars.append({"params":params,
    2070                                             "fixed": fitparams.getfixedparameters(),
    2071                                             "formatted":fmtd, "errors":errors})
    2072                     workscan.masklists.append(workscan.get_masklist(fmask, r, silent=True))
    2073                     workscan.actualmask.append(fmask)
    2074                    
    2075                     asaplog.push(fmtd)
    2076            
    2077             workscan._add_history("poly_baseline", varlist)
    2078            
    2079             if insitu:
    2080                 self._assign(workscan)
    2081             else:
    2082                 return workscan
    2083            
    2084         except RuntimeError, e:
    2085             msg = "The fit failed, possibly because it didn't converge."
    2086             if rcParams["verbose"]:
    2087                 asaplog.push(str(e))
    2088                 asaplog.push(str(msg))
    2089                 return
    2090             else:
    2091                 raise RuntimeError(str(e)+'\n'+msg)
    2092 
    2093 
    2094     def auto_poly_baseline(self, mask=None, edge=(0, 0), order=0,
    2095                            threshold=3, chan_avg_limit=1, plot=False,
    2096                            insitu=None, rows=None):
    2097         """\
    2098         Return a scan which has been baselined (all rows) by a polynomial.
    2099         Spectral lines are detected first using linefinder and masked out
    2100         to avoid them affecting the baseline solution.
    2101 
    2102         Parameters:
    2103 
    2104             mask:       an optional mask retreived from scantable
    2105 
    2106             edge:       an optional number of channel to drop at the edge of
    2107                         spectrum. If only one value is
    2108                         specified, the same number will be dropped from
    2109                         both sides of the spectrum. Default is to keep
    2110                         all channels. Nested tuples represent individual
    2111                         edge selection for different IFs (a number of spectral
    2112                         channels can be different)
    2113 
    2114             order:      the order of the polynomial (default is 0)
    2115 
    2116             threshold:  the threshold used by line finder. It is better to
    2117                         keep it large as only strong lines affect the
    2118                         baseline solution.
    2119 
    2120             chan_avg_limit:
    2121                         a maximum number of consequtive spectral channels to
    2122                         average during the search of weak and broad lines.
    2123                         The default is no averaging (and no search for weak
    2124                         lines). If such lines can affect the fitted baseline
    2125                         (e.g. a high order polynomial is fitted), increase this
    2126                         parameter (usually values up to 8 are reasonable). Most
    2127                         users of this method should find the default value
    2128                         sufficient.
    2129 
    2130             plot:       plot the fit and the residual. In this each
    2131                         indivual fit has to be approved, by typing 'y'
    2132                         or 'n'
    2133 
    2134             insitu:     if False a new scantable is returned.
    2135                         Otherwise, the scaling is done in-situ
    2136                         The default is taken from .asaprc (False)
    2137             rows:       row numbers of spectra to be processed.
    2138                         (default is None: for all rows)
    2139 
    2140 
    2141         Example::
    2142 
    2143             scan2 = scan.auto_poly_baseline(order=7, insitu=False)
    2144 
    2145         """
    2146         if insitu is None: insitu = rcParams['insitu']
    2147         varlist = vars()
    2148         from asap.asaplinefind import linefinder
    2149         from asap import _is_sequence_or_number as _is_valid
    2150 
    2151         # check whether edge is set up for each IF individually
    2152         individualedge = False;
    2153         if len(edge) > 1:
    2154             if isinstance(edge[0], list) or isinstance(edge[0], tuple):
    2155                 individualedge = True;
    2156 
    2157         if not _is_valid(edge, int) and not individualedge:
    2158             raise ValueError, "Parameter 'edge' has to be an integer or a \
    2159             pair of integers specified as a tuple. Nested tuples are allowed \
    2160             to make individual selection for different IFs."
    2161 
    2162         curedge = (0, 0)
    2163         if individualedge:
    2164             for edgepar in edge:
    2165                 if not _is_valid(edgepar, int):
    2166                     raise ValueError, "Each element of the 'edge' tuple has \
    2167                                        to be a pair of integers or an integer."
    2168         else:
    2169             curedge = edge;
    2170 
    2171         if not insitu:
    2172             workscan = self.copy()
    2173         else:
    2174             workscan = self
    2175 
    2176         # setup fitter
    2177         f = fitter()
    2178         f.set_function(lpoly=order)
    2179 
    2180         # setup line finder
    2181         fl = linefinder()
    2182         fl.set_options(threshold=threshold,avg_limit=chan_avg_limit)
    2183 
    2184         fl.set_scan(workscan)
    2185 
    2186         if mask is None:
    2187             mask = _n_bools(workscan.nchan(), True)
    2188        
    2189         if rows is None:
    2190             rows = xrange(workscan.nrow())
    2191         elif isinstance(rows, int):
    2192             rows = [ rows ]
    2193        
    2194         # Save parameters of baseline fits & masklists as a class attribute.
    2195         # NOTICE: It does not reflect changes in scantable!
    2196         if len(rows) > 0:
    2197             self.blpars=[]
    2198             self.masklists=[]
    2199             self.actualmask=[]
    2200         asaplog.push("Processing:")
    2201         for r in rows:
    2202             msg = " Scan[%d] Beam[%d] IF[%d] Pol[%d] Cycle[%d]" % \
    2203                 (workscan.getscan(r), workscan.getbeam(r), workscan.getif(r), \
    2204                  workscan.getpol(r), workscan.getcycle(r))
    2205             asaplog.push(msg, False)
    2206 
    2207             # figure out edge parameter
    2208             if individualedge:
    2209                 if len(edge) >= workscan.getif(r):
    2210                     raise RuntimeError, "Number of edge elements appear to " \
    2211                                         "be less than the number of IFs"
    2212                     curedge = edge[workscan.getif(r)]
    2213 
    2214             actualmask = mask_and(mask, workscan._getmask(r))    # (CAS-1434)
    2215 
    2216             # setup line finder
    2217             fl.find_lines(r, actualmask, curedge)
    2218            
    2219             f.x = workscan._getabcissa(r)
    2220             f.y = workscan._getspectrum(r)
    2221             f.mask = fl.get_mask()
    2222             f.data = None
    2223             f.fit()
    2224 
    2225             # Show mask list
    2226             masklist=workscan.get_masklist(f.mask, row=r, silent=True)
    2227             msg = "mask range: "+str(masklist)
    2228             asaplog.push(msg, False)
    2229 
    2230             if plot:
    2231                 f.plot(residual=True)
    2232                 x = raw_input("Accept fit ( [y]/n ): ")
    2233                 if x.upper() == 'N':
    2234                     self.blpars.append(None)
    2235                     self.masklists.append(None)
    2236                     self.actualmask.append(None)
    2237                     continue
    2238 
    2239             workscan._setspectrum(f.fitter.getresidual(), r)
    2240             self.blpars.append(f.get_parameters())
    2241             self.masklists.append(masklist)
    2242             self.actualmask.append(f.mask)
    2243         if plot:
    2244             f._p.unmap()
    2245             f._p = None
    2246         workscan._add_history("auto_poly_baseline", varlist)
    2247         if insitu:
    2248             self._assign(workscan)
    2249         else:
    2250             return workscan
    2251 
    22522476    @asaplog_post_dec
    22532477    def rotate_linpolphase(self, angle):
     
    27442968            self.set_freqframe(rcParams['scantable.freqframe'])
    27452969
     2970
    27462971    def __getitem__(self, key):
    27472972        if key < 0:
  • trunk/src/STLineFinder.cpp

    r1670 r2012  
    925925  itsNoiseBox = in_noise_box;
    926926  itsUseMedian = in_median;
     927
     928  useScantable = true;
    927929}
    928930
     
    934936  scan=in_scan.getCP();
    935937  AlwaysAssert(!scan.null(),AipsError);
    936 
     938}
     939
     940// set spectrum data to work with. this is a method to allow linefinder work
     941// without setting scantable for the purpose of using linefinder inside some
     942// method in scantable class. (Dec 22, 2010 by W.Kawasaki)
     943void STLineFinder::setData(const std::vector<float> &in_spectrum)
     944{
     945  spectrum = Vector<Float>(in_spectrum);
     946  useScantable = false;
    937947}
    938948
     
    948958                const casa::uInt &whichRow) throw(casa::AipsError)
    949959{
    950   if (scan.null())
     960  if (useScantable && scan.null())
    951961      throw AipsError("STLineFinder::findLines - a scan should be set first,"
    952962                      " use set_scan");
    953963
    954   uInt nchan = scan->nchan(scan->getIF(whichRow));
     964  uInt nchan = useScantable ? scan->nchan(scan->getIF(whichRow)) : spectrum.nelements();
    955965  // set up mask and edge rejection
    956966  // no mask given...
     
    962972  }
    963973  if (mask.nelements()!=nchan)
    964       throw AipsError("STLineFinder::findLines - in_scan and in_mask have different"
    965             "number of spectral channels.");
     974      throw AipsError("STLineFinder::findLines - in_scan and in_mask, or in_spectrum "
     975                      "and in_mask have different number of spectral channels.");
    966976
    967977  // taking flagged channels into account
    968   vector<bool> flaggedChannels = scan->getMask(whichRow);
    969   if (flaggedChannels.size()) {
     978  if (useScantable) {
     979    vector<bool> flaggedChannels = scan->getMask(whichRow);
     980    if (flaggedChannels.size()) {
    970981      // there is a mask set for this row
    971982      if (flaggedChannels.size() != mask.nelements()) {
    972           throw AipsError("STLineFinder::findLines - internal inconsistency: number of mask elements do not match the number of channels");
     983          throw AipsError("STLineFinder::findLines - internal inconsistency: number of "
     984                          "mask elements do not match the number of channels");
    973985      }
    974986      for (size_t ch = 0; ch<mask.nelements(); ++ch) {
    975987           mask[ch] &= flaggedChannels[ch];
    976988      }
     989    }
    977990  }
    978991
     
    10151028      throw AipsError("STLineFinder::findLines - noise_box is supposed to be at least 2 elements");
    10161029
    1017   spectrum.resize();
    1018   spectrum = Vector<Float>(scan->getSpectrum(whichRow));
     1030  if (useScantable) {
     1031    spectrum.resize();
     1032    spectrum = Vector<Float>(scan->getSpectrum(whichRow));
     1033  }
    10191034
    10201035  lines.resize(0); // search from the scratch
     
    11411156{
    11421157  try {
    1143        if (scan.null())
    1144            throw AipsError("STLineFinder::getMask - a scan should be set first,"
    1145                       " use set_scan followed by find_lines");
    1146        DebugAssert(mask.nelements()==scan->getChannels(last_row_used), AipsError);
    1147        /*
    1148        if (!lines.size())
    1149            throw AipsError("STLineFinder::getMask - one have to search for "
     1158    if (useScantable) {
     1159      if (scan.null())
     1160        throw AipsError("STLineFinder::getMask - a scan should be set first,"
     1161                        " use set_scan followed by find_lines");
     1162      DebugAssert(mask.nelements()==scan->getChannels(last_row_used), AipsError);
     1163    }
     1164    /*
     1165    if (!lines.size())
     1166       throw AipsError("STLineFinder::getMask - one have to search for "
    11501167                           "lines first, use find_lines");
    1151        */
    1152        std::vector<bool> res_mask(mask.nelements());
    1153        // iterator through lines
    1154        std::list<std::pair<int,int> >::const_iterator cli=lines.begin();
    1155        for (int ch=0;ch<int(res_mask.size());++ch) {
    1156             if (ch<edge.first || ch>=edge.second) res_mask[ch]=false;
    1157             else if (!mask[ch]) res_mask[ch]=false;
    1158             else {
    1159                     res_mask[ch]=!invert; // no line by default
    1160                     if (cli!=lines.end())
    1161                         if (ch>=cli->first && ch<cli->second)
    1162                              res_mask[ch]=invert; // this is a line
    1163             }
    1164             if (cli!=lines.end())
    1165                 if (ch>=cli->second) {
    1166                     ++cli; // next line in the list
    1167                 }
    1168        }
    1169        return res_mask;
     1168    */
     1169    std::vector<bool> res_mask(mask.nelements());
     1170    // iterator through lines
     1171    std::list<std::pair<int,int> >::const_iterator cli=lines.begin();
     1172    for (int ch=0;ch<int(res_mask.size());++ch) {
     1173      if (ch<edge.first || ch>=edge.second) res_mask[ch]=false;
     1174      else if (!mask[ch]) res_mask[ch]=false;
     1175      else {
     1176        res_mask[ch]=!invert; // no line by default
     1177        if (cli!=lines.end())
     1178          if (ch>=cli->first && ch<cli->second)
     1179            res_mask[ch]=invert; // this is a line
     1180      }
     1181      if (cli!=lines.end())
     1182        if (ch>=cli->second)
     1183          ++cli; // next line in the list
     1184    }
     1185    return res_mask;
    11701186  }
    11711187  catch (const AipsError &ae) {
    1172       throw;
     1188    throw;
    11731189  }
    11741190  catch (const exception &ex) {
    1175       throw AipsError(String("STLineFinder::getMask - STL error: ")+ex.what());
     1191    throw AipsError(String("STLineFinder::getMask - STL error: ")+ex.what());
    11761192  }
    11771193}
     
    11821198                             const throw(casa::AipsError)
    11831199{
    1184   // convert to required abscissa units
    1185   std::vector<double> vel=scan->getAbcissa(last_row_used);
     1200  std::vector<double> vel;
     1201  if (useScantable) {
     1202    // convert to required abscissa units
     1203    vel = scan->getAbcissa(last_row_used);
     1204  } else {
     1205    for (int i = 0; i < spectrum.nelements(); ++i)
     1206      vel.push_back((double)i);
     1207  }
    11861208  std::vector<int> ranges=getLineRangesInChannels();
    11871209  std::vector<double> res(ranges.size());
     
    12021224{
    12031225  try {
    1204        if (scan.null())
    1205            throw AipsError("STLineFinder::getLineRangesInChannels - a scan should be set first,"
    1206                       " use set_scan followed by find_lines");
    1207        DebugAssert(mask.nelements()==scan->getChannels(last_row_used), AipsError);
    1208 
    1209        if (!lines.size())
    1210            throw AipsError("STLineFinder::getLineRangesInChannels - one have to search for "
    1211                            "lines first, use find_lines");
    1212 
    1213        std::vector<int> res(2*lines.size());
    1214        // iterator through lines & result
    1215        std::list<std::pair<int,int> >::const_iterator cli=lines.begin();
    1216        std::vector<int>::iterator ri=res.begin();
    1217        for (;cli!=lines.end() && ri!=res.end();++cli,++ri) {
    1218             *ri=cli->first;
    1219             if (++ri!=res.end())
    1220                 *ri=cli->second-1;
    1221        }
    1222        return res;
    1223   }
    1224   catch (const AipsError &ae) {
    1225       throw;
    1226   }
    1227   catch (const exception &ex) {
    1228       throw AipsError(String("STLineFinder::getLineRanges - STL error: ")+ex.what());
     1226    if (useScantable) {
     1227      if (scan.null())
     1228        throw AipsError("STLineFinder::getLineRangesInChannels - a scan should be set first,"
     1229                        " use set_scan followed by find_lines");
     1230      DebugAssert(mask.nelements()==scan->getChannels(last_row_used), AipsError);
     1231    }
     1232
     1233    if (!lines.size())
     1234      throw AipsError("STLineFinder::getLineRangesInChannels - one have to search for "
     1235                      "lines first, use find_lines");
     1236
     1237    std::vector<int> res(2*lines.size());
     1238    // iterator through lines & result
     1239    std::list<std::pair<int,int> >::const_iterator cli = lines.begin();
     1240    std::vector<int>::iterator ri = res.begin();
     1241    for (; cli != lines.end() && ri != res.end(); ++cli,++ri) {
     1242      *ri = cli->first;
     1243      if (++ri != res.end())
     1244        *ri = cli->second - 1;
     1245    }
     1246    return res;
     1247  } catch (const AipsError &ae) {
     1248    throw;
     1249  } catch (const exception &ex) {
     1250    throw AipsError(String("STLineFinder::getLineRanges - STL error: ") + ex.what());
    12291251  }
    12301252}
  • trunk/src/STLineFinder.h

    r1644 r2012  
    164164   // set the scan to work with (in_scan parameter)
    165165   void setScan(const ScantableWrapper &in_scan) throw(casa::AipsError);
     166
     167   // set spectrum data to work with. this is a method to allow linefinder work
     168   // without setting scantable for the purpose of using linefinder inside some
     169   // method in scantable class. (Dec. 22, 2010 by W.Kawasaki)
     170   void setData(const std::vector<float> &in_spectrum);
    166171
    167172   // search for spectral lines in a row specified by whichRow
     
    257262   // the lowest 80% of deviations (default)
    258263   casa::Bool itsUseMedian;
     264
     265   // true if spectra and mask data should be provided from
     266   // scantable (default = true)
     267   bool useScantable;
    259268};
    260269
  • trunk/src/Scantable.cpp

    r2005 r2012  
    6767#include "STPolStokes.h"
    6868#include "STAttr.h"
     69#include "STLineFinder.h"
    6970#include "MathUtils.h"
    7071
     
    12171218}
    12181219**/
     1220
    12191221void Scantable::setRestFrequencies( const vector<std::string>& name )
    12201222{
     
    17491751  Vector<uChar> flags;
    17501752  flagsCol_.get(uInt(whichrow), flags);
    1751   for (int i = 0; i < flags.size(); i++) {
    1752     if (i==0) {
    1753       flag = flags[i];
    1754     }
    1755     else {
    1756       flag &= flags[i];
    1757     }
    1758     return ((flag >> 7) == 1);
    1759    }
    1760 }
    1761 
    1762 void Scantable::doPolyBaseline(const std::vector<bool>& mask, int order, int rowno, Fitter& fitter)
    1763 {
     1753  flag = flags[0];
     1754  for (int i = 1; i < flags.size(); ++i) {
     1755    flag &= flags[i];
     1756  }
     1757  return ((flag >> 7) == 1);
     1758}
     1759
     1760void Scantable::cubicSplineBaseline(const std::vector<bool>& mask, int nPiece, float thresClip, int nIterClip, bool outLogger, const std::string& blfile) {
     1761  ofstream ofs;
     1762  String coordInfo;
     1763  bool hasSameNchan;
     1764  int firstIF;
     1765  bool outTextFile = false;
     1766
     1767  if (blfile != "") {
     1768    ofs.open(blfile.c_str(), ios::out | ios::app);
     1769    if (ofs) outTextFile = true;
     1770  }
     1771
     1772  if (outLogger || outTextFile) {
     1773    coordInfo = getCoordInfo()[0];
     1774    if (coordInfo == "") coordInfo = "channel";
     1775    hasSameNchan = hasSameNchanOverIFs();
     1776    firstIF = getIF(0);
     1777  }
     1778
     1779  //Fitter fitter = Fitter();
     1780  //fitter.setExpression("cspline", nPiece, thresClip, nIterClip);
     1781
     1782  int nRow = nrow();
     1783  std::vector<bool> chanMask;
     1784
     1785  for (int whichrow = 0; whichrow < nRow; ++whichrow) {
     1786
     1787    chanMask = getCompositeChanMask(whichrow, mask);
     1788    //fitBaseline(chanMask, whichrow, fitter);
     1789    //setSpectrum(fitter.getResidual(), whichrow);
     1790    std::vector<int> pieceRanges;
     1791    std::vector<float> params;
     1792    std::vector<float> res = doCubicSplineFitting(getSpectrum(whichrow), chanMask, pieceRanges, params, nPiece, thresClip, nIterClip);
     1793    setSpectrum(res, whichrow);
     1794
     1795    if (outLogger || outTextFile) {
     1796      std::vector<bool>  fixed;
     1797      fixed.clear();
     1798      float rms = getRms(chanMask, whichrow);
     1799      String masklist = getMaskRangeList(chanMask, whichrow, coordInfo, hasSameNchan, firstIF, true);
     1800
     1801      if (outLogger) {
     1802        LogIO ols(LogOrigin("Scantable", "cubicSplineBaseline()", WHERE));
     1803        ols << formatPiecewiseBaselineParams(pieceRanges, params, fixed, rms, masklist, whichrow, false) << LogIO::POST ;
     1804      }
     1805      if (outTextFile) {
     1806        ofs << formatPiecewiseBaselineParams(pieceRanges, params, fixed, rms, masklist, whichrow, true) << flush;
     1807      }
     1808    }
     1809
     1810  }
     1811
     1812  if (outTextFile) ofs.close();
     1813}
     1814
     1815
     1816void Scantable::autoCubicSplineBaseline(const std::vector<bool>& mask, int nPiece, float thresClip, int nIterClip, const std::vector<int>& edge, float threshold, int chanAvgLimit, bool outLogger, const std::string& blfile)
     1817{
     1818  ofstream ofs;
     1819  String coordInfo;
     1820  bool hasSameNchan;
     1821  int firstIF;
     1822  bool outTextFile = false;
     1823
     1824  if (blfile != "") {
     1825    ofs.open(blfile.c_str(), ios::out | ios::app);
     1826    if (ofs) outTextFile = true;
     1827  }
     1828
     1829  if (outLogger || outTextFile) {
     1830    coordInfo = getCoordInfo()[0];
     1831    if (coordInfo == "") coordInfo = "channel";
     1832    hasSameNchan = hasSameNchanOverIFs();
     1833    firstIF = getIF(0);
     1834  }
     1835
     1836  //Fitter fitter = Fitter();
     1837  //fitter.setExpression("cspline", nPiece, thresClip, nIterClip);
     1838
     1839  int nRow = nrow();
     1840  std::vector<bool> chanMask;
     1841  int minEdgeSize = getIFNos().size()*2;
     1842  STLineFinder lineFinder = STLineFinder();
     1843  lineFinder.setOptions(threshold, 3, chanAvgLimit);
     1844
     1845  for (int whichrow = 0; whichrow < nRow; ++whichrow) {
     1846
     1847    //-------------------------------------------------------
     1848    //chanMask = getCompositeChanMask(whichrow, mask, edge, minEdgeSize, lineFinder);
     1849    //-------------------------------------------------------
     1850    int edgeSize = edge.size();
     1851    std::vector<int> currentEdge;
     1852    if (edgeSize >= 2) {
     1853      int idx = 0;
     1854      if (edgeSize > 2) {
     1855        if (edgeSize < minEdgeSize) {
     1856          throw(AipsError("Length of edge element info is less than that of IFs"));
     1857        }
     1858        idx = 2 * getIF(whichrow);
     1859      }
     1860      currentEdge.push_back(edge[idx]);
     1861      currentEdge.push_back(edge[idx+1]);
     1862    } else {
     1863      throw(AipsError("Wrong length of edge element"));
     1864    }
     1865    lineFinder.setData(getSpectrum(whichrow));
     1866    lineFinder.findLines(getCompositeChanMask(whichrow, mask), currentEdge, whichrow);
     1867    chanMask = lineFinder.getMask();
     1868    //-------------------------------------------------------
     1869
     1870
     1871    //fitBaseline(chanMask, whichrow, fitter);
     1872    //setSpectrum(fitter.getResidual(), whichrow);
     1873    std::vector<int> pieceRanges;
     1874    std::vector<float> params;
     1875    std::vector<float> res = doCubicSplineFitting(getSpectrum(whichrow), chanMask, pieceRanges, params, nPiece, thresClip, nIterClip);
     1876    setSpectrum(res, whichrow);
     1877
     1878    if (outLogger || outTextFile) {
     1879      std::vector<bool> fixed;
     1880      fixed.clear();
     1881      float rms = getRms(chanMask, whichrow);
     1882      String masklist = getMaskRangeList(chanMask, whichrow, coordInfo, hasSameNchan, firstIF, true);
     1883
     1884      if (outLogger) {
     1885        LogIO ols(LogOrigin("Scantable", "autoCubicSplineBaseline()", WHERE));
     1886        ols << formatPiecewiseBaselineParams(pieceRanges, params, fixed, rms, masklist, whichrow, false) << LogIO::POST ;
     1887      }
     1888      if (outTextFile) {
     1889        ofs << formatPiecewiseBaselineParams(pieceRanges, params, fixed, rms, masklist, whichrow, true) << flush;
     1890      }
     1891    }
     1892
     1893  }
     1894
     1895  if (outTextFile) ofs.close();
     1896}
     1897
     1898
     1899std::vector<float> Scantable::doCubicSplineFitting(const std::vector<float>& data, const std::vector<bool>& mask, std::vector<int>& sectionRanges, std::vector<float>& params, int nPiece, float thresClip, int nIterClip) {
     1900  if (nPiece < 1) {
     1901    throw(AipsError("wrong number of the sections for fitting"));
     1902  }
     1903  if (data.size() != mask.size()) {
     1904    throw(AipsError("data and mask have different size"));
     1905  }
     1906
     1907  int nChan = data.size();
     1908  std::vector<int> maskArray;
     1909  std::vector<int> x;
     1910  for (int i = 0; i < nChan; ++i) {
     1911    maskArray.push_back(mask[i] ? 1 : 0);
     1912    if (mask[i]) {
     1913      x.push_back(i);
     1914    }
     1915  }
     1916
     1917  int nData = x.size();
     1918  int nElement = (int)(floor(floor((double)(nData/nPiece))+0.5));
     1919
     1920  std::vector<double> sectionList0, sectionList1, sectionListR;
     1921  sectionList0.push_back((double)x[0]);
     1922  sectionRanges.clear();
     1923  sectionRanges.push_back(x[0]);
     1924  for (int i = 1; i < nPiece; ++i) {
     1925    double valX = (double)x[nElement*i];
     1926    sectionList0.push_back(valX);
     1927    sectionList1.push_back(valX);
     1928    sectionListR.push_back(1.0/valX);
     1929
     1930    sectionRanges.push_back(x[nElement*i]-1);
     1931    sectionRanges.push_back(x[nElement*i]);
     1932  }
     1933  sectionList1.push_back((double)(x[x.size()-1]+1));
     1934  sectionRanges.push_back(x[x.size()-1]);
     1935
     1936  std::vector<double> x1, x2, x3, z1, x1z1, x2z1, x3z1, r1;
     1937  for (int i = 0; i < nChan; ++i) {
     1938    x1.push_back((double)i);
     1939    x2.push_back((double)(i*i));
     1940    x3.push_back((double)(i*i*i));
     1941    z1.push_back((double)data[i]);
     1942    x1z1.push_back(((double)i)*(double)data[i]);
     1943    x2z1.push_back(((double)(i*i))*(double)data[i]);
     1944    x3z1.push_back(((double)(i*i*i))*(double)data[i]);
     1945    r1.push_back(0.0);
     1946  }
     1947
     1948  int currentNData = nData;
     1949  int nDOF = nPiece + 3;  //number of parameters to solve, namely, 4+(nPiece-1).
     1950
     1951  for (int nClip = 0; nClip < nIterClip+1; ++nClip) {
     1952    //xMatrix : horizontal concatenation of the least-sq. matrix (left) and an
     1953    //identity matrix (right).
     1954    //the right part is used to calculate the inverse matrix of the left part.
     1955    double xMatrix[nDOF][2*nDOF];
     1956    double zMatrix[nDOF];
     1957    for (int i = 0; i < nDOF; ++i) {
     1958      for (int j = 0; j < 2*nDOF; ++j) {
     1959        xMatrix[i][j] = 0.0;
     1960      }
     1961      xMatrix[i][nDOF+i] = 1.0;
     1962      zMatrix[i] = 0.0;
     1963    }
     1964
     1965    for (int n = 0; n < nPiece; ++n) {
     1966      for (int i = sectionList0[n]; i < sectionList1[n]; ++i) {
     1967        if (maskArray[i] == 0) continue;
     1968        xMatrix[0][0] += 1.0;
     1969        xMatrix[0][1] += x1[i];
     1970        xMatrix[0][2] += x2[i];
     1971        xMatrix[0][3] += x3[i];
     1972        xMatrix[1][1] += x2[i];
     1973        xMatrix[1][2] += x3[i];
     1974        xMatrix[1][3] += x2[i]*x2[i];
     1975        xMatrix[2][2] += x2[i]*x2[i];
     1976        xMatrix[2][3] += x3[i]*x2[i];
     1977        xMatrix[3][3] += x3[i]*x3[i];
     1978        zMatrix[0] += z1[i];
     1979        zMatrix[1] += x1z1[i];
     1980        zMatrix[2] += x2z1[i];
     1981        zMatrix[3] += x3z1[i];
     1982        for (int j = 0; j < n; ++j) {
     1983          double q = 1.0 - x1[i]*sectionListR[j];
     1984          q = q*q*q;
     1985          xMatrix[0][j+4] += q;
     1986          xMatrix[1][j+4] += q*x1[i];
     1987          xMatrix[2][j+4] += q*x2[i];
     1988          xMatrix[3][j+4] += q*x3[i];
     1989          for (int k = 0; k < j; ++k) {
     1990            double r = 1.0 - x1[i]*sectionListR[k];
     1991            r = r*r*r;
     1992            xMatrix[k+4][j+4] += r*q;
     1993          }
     1994          xMatrix[j+4][j+4] += q*q;
     1995          zMatrix[j+4] += q*z1[i];
     1996        }
     1997      }
     1998    }
     1999
     2000    for (int i = 0; i < nDOF; ++i) {
     2001      for (int j = 0; j < i; ++j) {
     2002        xMatrix[i][j] = xMatrix[j][i];
     2003      }
     2004    }
     2005
     2006    std::vector<double> invDiag;
     2007    for (int i = 0; i < nDOF; ++i) {
     2008      invDiag.push_back(1.0/xMatrix[i][i]);
     2009      for (int j = 0; j < nDOF; ++j) {
     2010        xMatrix[i][j] *= invDiag[i];
     2011      }
     2012    }
     2013
     2014    for (int k = 0; k < nDOF; ++k) {
     2015      for (int i = 0; i < nDOF; ++i) {
     2016        if (i != k) {
     2017          double factor1 = xMatrix[k][k];
     2018          double factor2 = xMatrix[i][k];
     2019          for (int j = k; j < 2*nDOF; ++j) {
     2020            xMatrix[i][j] *= factor1;
     2021            xMatrix[i][j] -= xMatrix[k][j]*factor2;
     2022            xMatrix[i][j] /= factor1;
     2023          }
     2024        }
     2025      }
     2026      double xDiag = xMatrix[k][k];
     2027      for (int j = k; j < 2*nDOF; ++j) {
     2028        xMatrix[k][j] /= xDiag;
     2029      }
     2030    }
     2031   
     2032    for (int i = 0; i < nDOF; ++i) {
     2033      for (int j = 0; j < nDOF; ++j) {
     2034        xMatrix[i][nDOF+j] *= invDiag[j];
     2035      }
     2036    }
     2037    //compute a vector y which consists of the coefficients of the best-fit spline curves
     2038    //(a0,a1,a2,a3(,b3,c3,...)), namely, the ones for the leftmost piece and the ones of
     2039    //cubic terms for the other pieces (in case nPiece>1).
     2040    std::vector<double> y;
     2041    for (int i = 0; i < nDOF; ++i) {
     2042      y.push_back(0.0);
     2043      for (int j = 0; j < nDOF; ++j) {
     2044        y[i] += xMatrix[i][nDOF+j]*zMatrix[j];
     2045      }
     2046    }
     2047
     2048    double a0 = y[0];
     2049    double a1 = y[1];
     2050    double a2 = y[2];
     2051    double a3 = y[3];
     2052    params.clear();
     2053
     2054    for (int n = 0; n < nPiece; ++n) {
     2055      for (int i = sectionList0[n]; i < sectionList1[n]; ++i) {
     2056        r1[i] = a0 + a1*x1[i] + a2*x2[i] + a3*x3[i];
     2057      }
     2058      params.push_back(a0);
     2059      params.push_back(a1);
     2060      params.push_back(a2);
     2061      params.push_back(a3);
     2062
     2063      if (n == nPiece-1) break;
     2064
     2065      double d = y[4+n];
     2066      a0 += d;
     2067      a1 -= 3.0*d*sectionListR[n];
     2068      a2 += 3.0*d*sectionListR[n]*sectionListR[n];
     2069      a3 -= d*sectionListR[n]*sectionListR[n]*sectionListR[n];
     2070    }
     2071
     2072    if ((nClip == nIterClip) || (thresClip <= 0.0)) {
     2073      break;
     2074    } else {
     2075      std::vector<double> rz;
     2076      double stdDev = 0.0;
     2077      for (int i = 0; i < nChan; ++i) {
     2078        double val = abs(r1[i] - z1[i]);
     2079        rz.push_back(val);
     2080        stdDev += val*val*(double)maskArray[i];
     2081      }
     2082      stdDev = sqrt(stdDev/(double)nData);
     2083     
     2084      double thres = stdDev * thresClip;
     2085      int newNData = 0;
     2086      for (int i = 0; i < nChan; ++i) {
     2087        if (rz[i] >= thres) {
     2088          maskArray[i] = 0;
     2089        }
     2090        if (maskArray[i] > 0) {
     2091          newNData++;
     2092        }
     2093      }
     2094      if (newNData == currentNData) {
     2095        break;                   //no additional flag. finish iteration.
     2096      } else {
     2097        currentNData = newNData;
     2098      }
     2099    }
     2100  }
     2101
     2102  std::vector<float> residual;
     2103  for (int i = 0; i < nChan; ++i) {
     2104    residual.push_back((float)(z1[i] - r1[i]));
     2105  }
     2106  return residual;
     2107
     2108}
     2109
     2110void Scantable::fitBaseline(const std::vector<bool>& mask, int whichrow, Fitter& fitter)
     2111{
     2112  std::vector<double> abcsd = getAbcissa(whichrow);
     2113  std::vector<float> abcs;
     2114  for (int i = 0; i < abcsd.size(); ++i) {
     2115    abcs.push_back((float)abcsd[i]);
     2116  }
     2117  std::vector<float> spec = getSpectrum(whichrow);
     2118
     2119  fitter.setData(abcs, spec, mask);
     2120  fitter.lfit();
     2121}
     2122
     2123std::vector<bool> Scantable::getCompositeChanMask(int whichrow, const std::vector<bool>& inMask)
     2124{
     2125  std::vector<bool> chanMask = getMask(whichrow);
     2126  int chanMaskSize = chanMask.size();
     2127  if (chanMaskSize != inMask.size()) {
     2128    throw(AipsError("different mask sizes"));
     2129  }
     2130  for (int i = 0; i < chanMaskSize; ++i) {
     2131    chanMask[i] = chanMask[i] && inMask[i];
     2132  }
     2133
     2134  return chanMask;
     2135}
     2136
     2137/*
     2138std::vector<bool> Scantable::getCompositeChanMask(int whichrow, const std::vector<bool>& inMask, const std::vector<int>& edge, const int minEdgeSize, STLineFinder& lineFinder)
     2139{
     2140  int edgeSize = edge.size();
     2141  std::vector<int> currentEdge;
     2142  if (edgeSize >= 2) {
     2143      int idx = 0;
     2144      if (edgeSize > 2) {
     2145        if (edgeSize < minEdgeSize) {
     2146          throw(AipsError("Length of edge element info is less than that of IFs"));
     2147        }
     2148        idx = 2 * getIF(whichrow);
     2149      }
     2150      currentEdge.push_back(edge[idx]);
     2151      currentEdge.push_back(edge[idx+1]);
     2152  } else {
     2153    throw(AipsError("Wrong length of edge element"));
     2154  }
     2155
     2156  lineFinder.setData(getSpectrum(whichrow));
     2157  lineFinder.findLines(getCompositeChanMask(whichrow, inMask), currentEdge, whichrow);
     2158
     2159  return lineFinder.getMask();
     2160}
     2161*/
     2162
     2163void Scantable::polyBaseline(const std::vector<bool>& mask, int order, bool outLogger, const std::string& blfile)
     2164{
     2165  ofstream ofs;
     2166  String coordInfo;
     2167  bool hasSameNchan;
     2168  int firstIF;
     2169  bool outTextFile = false;
     2170
     2171  if (blfile != "") {
     2172    ofs.open(blfile.c_str(), ios::out | ios::app);
     2173    if (ofs) outTextFile = true;
     2174  }
     2175
     2176  if (outLogger || outTextFile) {
     2177    coordInfo = getCoordInfo()[0];
     2178    if (coordInfo == "") coordInfo = "channel";
     2179    hasSameNchan = hasSameNchanOverIFs();
     2180    firstIF = getIF(0);
     2181  }
     2182
     2183  Fitter fitter = Fitter();
    17642184  fitter.setExpression("poly", order);
    17652185
    1766   std::vector<double> abcsd = getAbcissa(rowno);
    1767   std::vector<float> abcs;
    1768   for (int i = 0; i < abcsd.size(); i++) {
    1769     abcs.push_back((float)abcsd[i]);
    1770   }
    1771   std::vector<float> spec = getSpectrum(rowno);
     2186  int nRow = nrow();
     2187  std::vector<bool> chanMask;
     2188
     2189  for (int whichrow = 0; whichrow < nRow; ++whichrow) {
     2190
     2191    chanMask = getCompositeChanMask(whichrow, mask);
     2192    fitBaseline(chanMask, whichrow, fitter);
     2193    setSpectrum(fitter.getResidual(), whichrow);
     2194   
     2195    if (outLogger || outTextFile) {
     2196      std::vector<float> params = fitter.getParameters();
     2197      std::vector<bool>  fixed  = fitter.getFixedParameters();
     2198      float rms = getRms(chanMask, whichrow);
     2199      String masklist = getMaskRangeList(chanMask, whichrow, coordInfo, hasSameNchan, firstIF, true);
     2200
     2201      if (outLogger) {
     2202        LogIO ols(LogOrigin("Scantable", "polyBaseline()", WHERE));
     2203        ols << formatBaselineParams(params, fixed, rms, masklist, whichrow, false) << LogIO::POST ;
     2204      }
     2205      if (outTextFile) {
     2206        ofs << formatBaselineParams(params, fixed, rms, masklist, whichrow, true) << flush;
     2207      }
     2208    }
     2209
     2210  }
     2211
     2212  if (outTextFile) ofs.close();
     2213}
     2214
     2215void Scantable::autoPolyBaseline(const std::vector<bool>& mask, int order, const std::vector<int>& edge, float threshold, int chanAvgLimit, bool outLogger, const std::string& blfile)
     2216{
     2217  ofstream ofs;
     2218  String coordInfo;
     2219  bool hasSameNchan;
     2220  int firstIF;
     2221  bool outTextFile = false;
     2222
     2223  if (blfile != "") {
     2224    ofs.open(blfile.c_str(), ios::out | ios::app);
     2225    if (ofs) outTextFile = true;
     2226  }
     2227
     2228  if (outLogger || outTextFile) {
     2229    coordInfo = getCoordInfo()[0];
     2230    if (coordInfo == "") coordInfo = "channel";
     2231    hasSameNchan = hasSameNchanOverIFs();
     2232    firstIF = getIF(0);
     2233  }
     2234
     2235  Fitter fitter = Fitter();
     2236  fitter.setExpression("poly", order);
     2237
     2238  int nRow = nrow();
     2239  std::vector<bool> chanMask;
     2240  int minEdgeSize = getIFNos().size()*2;
     2241  STLineFinder lineFinder = STLineFinder();
     2242  lineFinder.setOptions(threshold, 3, chanAvgLimit);
     2243
     2244  for (int whichrow = 0; whichrow < nRow; ++whichrow) {
     2245
     2246    //-------------------------------------------------------
     2247    //chanMask = getCompositeChanMask(whichrow, mask, edge, minEdgeSize, lineFinder);
     2248    //-------------------------------------------------------
     2249    int edgeSize = edge.size();
     2250    std::vector<int> currentEdge;
     2251    if (edgeSize >= 2) {
     2252      int idx = 0;
     2253      if (edgeSize > 2) {
     2254        if (edgeSize < minEdgeSize) {
     2255          throw(AipsError("Length of edge element info is less than that of IFs"));
     2256        }
     2257        idx = 2 * getIF(whichrow);
     2258      }
     2259      currentEdge.push_back(edge[idx]);
     2260      currentEdge.push_back(edge[idx+1]);
     2261    } else {
     2262      throw(AipsError("Wrong length of edge element"));
     2263    }
     2264    lineFinder.setData(getSpectrum(whichrow));
     2265    lineFinder.findLines(getCompositeChanMask(whichrow, mask), currentEdge, whichrow);
     2266    chanMask = lineFinder.getMask();
     2267    //-------------------------------------------------------
     2268
     2269
     2270    fitBaseline(chanMask, whichrow, fitter);
     2271    setSpectrum(fitter.getResidual(), whichrow);
     2272
     2273    if (outLogger || outTextFile) {
     2274      std::vector<float> params = fitter.getParameters();
     2275      std::vector<bool>  fixed  = fitter.getFixedParameters();
     2276      float rms = getRms(chanMask, whichrow);
     2277      String masklist = getMaskRangeList(chanMask, whichrow, coordInfo, hasSameNchan, firstIF, true);
     2278
     2279      if (outLogger) {
     2280        LogIO ols(LogOrigin("Scantable", "autoPolyBaseline()", WHERE));
     2281        ols << formatBaselineParams(params, fixed, rms, masklist, whichrow, false) << LogIO::POST ;
     2282      }
     2283      if (outTextFile) {
     2284        ofs << formatBaselineParams(params, fixed, rms, masklist, whichrow, true) << flush;
     2285      }
     2286    }
     2287
     2288  }
     2289
     2290  if (outTextFile) ofs.close();
     2291}
     2292
     2293
     2294float Scantable::getRms(const std::vector<bool>& mask, int whichrow) {
     2295  Vector<Float> spec;
     2296  specCol_.get(whichrow, spec);
     2297
     2298  float mean = 0.0;
     2299  float smean = 0.0;
     2300  int n = 0;
     2301  for (int i = 0; i < spec.nelements(); ++i) {
     2302    if (mask[i]) {
     2303      mean += spec[i];
     2304      smean += spec[i]*spec[i];
     2305      n++;
     2306    }
     2307  }
     2308
     2309  mean /= (float)n;
     2310  smean /= (float)n;
     2311
     2312  return sqrt(smean - mean*mean);
     2313}
     2314
     2315
     2316std::string Scantable::formatBaselineParamsHeader(int whichrow, const std::string& masklist, bool verbose) const
     2317{
     2318  ostringstream oss;
     2319
     2320  if (verbose) {
     2321    for (int i = 0; i < 60; ++i) {
     2322      oss << "-";
     2323    }
     2324    oss << endl;
     2325    oss <<  " Scan[" << getScan(whichrow)  << "]";
     2326    oss <<  " Beam[" << getBeam(whichrow)  << "]";
     2327    oss <<    " IF[" << getIF(whichrow)    << "]";
     2328    oss <<   " Pol[" << getPol(whichrow)   << "]";
     2329    oss << " Cycle[" << getCycle(whichrow) << "]: " << endl;
     2330    oss << "Fitter range = " << masklist << endl;
     2331    oss << "Baseline parameters" << endl;
     2332    oss << flush;
     2333  }
     2334
     2335  return String(oss);
     2336}
     2337
     2338std::string Scantable::formatBaselineParamsFooter(float rms, bool verbose) const
     2339{
     2340  ostringstream oss;
     2341
     2342  if (verbose) {
     2343    oss << endl;
     2344    oss << "Results of baseline fit" << endl;
     2345    oss << "  rms = " << setprecision(6) << rms << endl;
     2346  }
     2347
     2348  return String(oss);
     2349}
     2350
     2351std::string Scantable::formatPiecewiseBaselineParams(const std::vector<int>& ranges, const std::vector<float>& params, const std::vector<bool>& fixed, float rms, const std::string& masklist, int whichrow, bool verbose) const
     2352{
     2353  ostringstream oss;
     2354  oss << formatBaselineParamsHeader(whichrow, masklist, verbose);
     2355
     2356  if ((params.size() > 0) && (ranges.size() > 0)) {
     2357    if (((ranges.size() % 2) == 0) && ((params.size() % (ranges.size() / 2)) == 0)) {
     2358      int nParam = params.size() / (ranges.size() / 2);
     2359      for (uInt j = 0; j < ranges.size(); j+=2) {
     2360        oss << "[" << ranges[j] << "," << ranges[j+1] << "]";
     2361        for (uInt i = 0; i < nParam; ++i) {
     2362          if (i > 0) {
     2363            oss << ",";
     2364          }
     2365          String fix = ((fixed.size() > 0) && (fixed[i]) && verbose) ? "(fixed)" : "";
     2366          oss << "  p" << i << fix << "= " << setprecision(6) << params[j/2*nParam+i];
     2367        }
     2368      }
     2369    } else {
     2370      oss << "  ";
     2371    }
     2372  } else {
     2373    oss << "  Not fitted";
     2374  }
     2375
     2376  oss << formatBaselineParamsFooter(rms, verbose);
     2377  oss << flush;
     2378
     2379  return String(oss);
     2380}
     2381
     2382std::string Scantable::formatBaselineParams(const std::vector<float>& params, const std::vector<bool>& fixed, float rms, const std::string& masklist, int whichrow, bool verbose) const
     2383{
     2384  ostringstream oss;
     2385  oss << formatBaselineParamsHeader(whichrow, masklist, verbose);
     2386
     2387  if (params.size() > 0) {
     2388    for (uInt i = 0; i < params.size(); ++i) {
     2389      if (i > 0) {
     2390        oss << ",";
     2391      }
     2392      String fix = ((fixed.size() > 0) && (fixed[i]) && verbose) ? "(fixed)" : "";
     2393      oss << "  p" << i << fix << "= " << setprecision(6) << params[i];
     2394    }
     2395  } else {
     2396    oss << "  Not fitted";
     2397  }
     2398
     2399  oss << formatBaselineParamsFooter(rms, verbose);
     2400  oss << flush;
     2401
     2402  return String(oss);
     2403}
     2404
     2405std::string Scantable::getMaskRangeList(const std::vector<bool>& mask, int whichrow, const casa::String& coordInfo, bool hasSameNchan, int firstIF, bool silent)
     2406{
     2407  if (mask.size() < 2) {
     2408    throw(AipsError("The mask elements should be > 1"));
     2409  }
     2410  if (mask.size() != nchan()) {
     2411    throw(AipsError("Number of channels in scantable != number of mask elements"));
     2412  }
     2413
     2414  std::vector<int> startIdx = getMaskEdgeIndices(mask, true);
     2415  std::vector<int> endIdx   = getMaskEdgeIndices(mask, false);
     2416
     2417  if (startIdx.size() != endIdx.size()) {
     2418    throw(AipsError("Numbers of mask start and mask end are not identical"));
     2419  }
     2420  for (int i = 0; i < startIdx.size(); ++i) {
     2421    if (startIdx[i] > endIdx[i]) {
     2422      throw(AipsError("Mask start index > mask end index"));
     2423    }
     2424  }
     2425
     2426  if (!silent) {
     2427    LogIO logOs(LogOrigin("Scantable", "getMaskRangeList()", WHERE));
     2428    logOs << LogIO::WARN << "The current mask window unit is " << coordInfo;
     2429    if (!hasSameNchan) {
     2430      logOs << endl << "This mask is only valid for IF=" << firstIF;
     2431    }
     2432    logOs << LogIO::POST;
     2433  }
     2434
     2435  std::vector<double> abcissa = getAbcissa(whichrow);
     2436  ostringstream oss;
     2437  oss.setf(ios::fixed);
     2438  oss << setprecision(1) << "[";
     2439  for (int i = 0; i < startIdx.size(); ++i) {
     2440    std::vector<float> aMaskRange;
     2441    aMaskRange.push_back((float)abcissa[startIdx[i]]);
     2442    aMaskRange.push_back((float)abcissa[endIdx[i]]);
     2443    sort(aMaskRange.begin(), aMaskRange.end());
     2444    if (i > 0) oss << ",";
     2445    oss << "[" << aMaskRange[0] << "," << aMaskRange[1] << "]";
     2446  }
     2447  oss << "]" << flush;
     2448
     2449  return String(oss);
     2450}
     2451
     2452bool Scantable::hasSameNchanOverIFs()
     2453{
     2454  int nIF = nif(-1);
     2455  int nCh;
     2456  int totalPositiveNChan = 0;
     2457  int nPositiveNChan = 0;
     2458
     2459  for (int i = 0; i < nIF; ++i) {
     2460    nCh = nchan(i);
     2461    if (nCh > 0) {
     2462      totalPositiveNChan += nCh;
     2463      nPositiveNChan++;
     2464    }
     2465  }
     2466
     2467  return (totalPositiveNChan == (nPositiveNChan * nchan(0)));
     2468}
     2469
     2470std::vector<int> Scantable::getMaskEdgeIndices(const std::vector<bool>& mask, bool getStartIndices)
     2471{
     2472  if (mask.size() < 2) {
     2473    throw(AipsError("The mask elements should be > 1"));
     2474  }
     2475  if (mask.size() != nchan()) {
     2476    throw(AipsError("Number of channels in scantable != number of mask elements"));
     2477  }
     2478
     2479  std::vector<int> out;
     2480  int endIdx = mask.size() - 1;
     2481
     2482  if (getStartIndices) {
     2483    if (mask[0]) {
     2484      out.push_back(0);
     2485    }
     2486    for (int i = 0; i < endIdx; ++i) {
     2487      if ((!mask[i]) && mask[i+1]) {
     2488        out.push_back(i+1);
     2489      }
     2490    }
     2491  } else {
     2492    for (int i = 0; i < endIdx; ++i) {
     2493      if (mask[i] && (!mask[i+1])) {
     2494        out.push_back(i);
     2495      }
     2496    }
     2497    if (mask[endIdx]) {
     2498      out.push_back(endIdx);
     2499    }
     2500  }
     2501
     2502  return out;
     2503}
     2504
     2505
     2506/*
     2507STFitEntry Scantable::polyBaseline(const std::vector<bool>& mask, int order, int rowno)
     2508{
     2509  Fitter fitter = Fitter();
     2510  fitter.setExpression("poly", order);
     2511
    17722512  std::vector<bool> fmask = getMask(rowno);
    17732513  if (fmask.size() != mask.size()) {
    17742514    throw(AipsError("different mask sizes"));
    17752515  }
    1776   for (int i = 0; i < fmask.size(); i++) {
     2516  for (int i = 0; i < fmask.size(); ++i) {
    17772517    fmask[i] = fmask[i] && mask[i];
    17782518  }
    1779   fitter.setData(abcs, spec, fmask);
    1780 
    1781   fitter.lfit();
    1782 }
    1783 
    1784 void Scantable::polyBaselineBatch(const std::vector<bool>& mask, int order)
    1785 {
    1786   Fitter fitter = Fitter();
    1787   for (uInt rowno=0; rowno < nrow(); ++rowno) {
    1788     doPolyBaseline(mask, order, rowno, fitter);
    1789     setSpectrum(fitter.getResidual(), rowno);
    1790   }
    1791 }
    1792 
    1793 STFitEntry Scantable::polyBaseline(const std::vector<bool>& mask, int order, int rowno)
    1794 {
    1795   Fitter fitter = Fitter();
    1796   doPolyBaseline(mask, order, rowno, fitter);
     2519
     2520  fitBaseline(fmask, rowno, fitter);
    17972521  setSpectrum(fitter.getResidual(), rowno);
    17982522  return fitter.getFitEntry();
    17992523}
     2524*/
    18002525
    18012526}
  • trunk/src/Scantable.h

    r2005 r2012  
    1616#include <string>
    1717#include <vector>
     18#include <iostream>
     19#include <fstream>
    1820// AIPS++
    1921#include <casa/aips.h>
     
    493495  bool getFlagtraFast(int whichrow);
    494496
    495   void polyBaselineBatch(const std::vector<bool>& mask, int order);
    496   STFitEntry polyBaseline(const std::vector<bool>& mask, int order, int rowno);
     497  void polyBaseline(const std::vector<bool>& mask,
     498                    int order,
     499                    bool outLogger=false,
     500                    const std::string& blfile="");
     501  void autoPolyBaseline(const std::vector<bool>& mask,
     502                        int order,
     503                        const std::vector<int>& edge,
     504                        float threshold=3.0,
     505                        int chanAvgLimit=1,
     506                        bool outLogger=false,
     507                        const std::string& blfile="");
     508  void cubicSplineBaseline(const std::vector<bool>& mask,
     509                           int nPiece,
     510                           float thresClip,
     511                           int nIterClip,
     512                           bool outLogger=false,
     513                           const std::string& blfile="");
     514  void autoCubicSplineBaseline(const std::vector<bool>& mask,
     515                               int nPiece,
     516                               float thresClip,
     517                               int nIterClip,
     518                               const std::vector<int>& edge,
     519                               float threshold=3.0,
     520                               int chanAvgLimit=1,
     521                               bool outLogger=false,
     522                               const std::string& blfile="");
     523  float getRms(const std::vector<bool>& mask, int whichrow);
     524  std::string formatBaselineParams(const std::vector<float>& params,
     525                                   const std::vector<bool>& fixed,
     526                                   float rms,
     527                                   const std::string& masklist,
     528                                   int whichrow,
     529                                   bool verbose=false) const;
     530  std::string formatPiecewiseBaselineParams(const std::vector<int>& ranges,
     531                                            const std::vector<float>& params,
     532                                            const std::vector<bool>& fixed,
     533                                            float rms,
     534                                            const std::string& masklist,
     535                                            int whichrow,
     536                                            bool verbose=false) const;
     537
    497538
    498539private:
     
    608649                                                      const casa::Array<T2>&);
    609650
    610   void doPolyBaseline(const std::vector<bool>& mask, int order, int rowno, Fitter& fitter);
     651  void fitBaseline(const std::vector<bool>& mask, int whichrow, Fitter& fitter);
     652  std::vector<float> doCubicSplineFitting(const std::vector<float>& data,
     653                                          const std::vector<bool>& mask,
     654                                          std::vector<int>& sectionRanges,
     655                                          std::vector<float>& params,
     656                                          int nPiece=2,
     657                                          float thresClip=3.0,
     658                                          int nIterClip=1);
     659  bool hasSameNchanOverIFs();
     660  std::string getMaskRangeList(const std::vector<bool>& mask,
     661                                int whichrow,
     662                                const casa::String& coordInfo,
     663                                bool hasSameNchan,
     664                                int firstIF,
     665                                bool silent=false);
     666  std::vector<int> getMaskEdgeIndices(const std::vector<bool>& mask, bool getStartIndices=true);
     667  std::string formatBaselineParamsHeader(int whichrow, const std::string& masklist, bool verbose) const;
     668  std::string formatBaselineParamsFooter(float rms, bool verbose) const;
     669  std::vector<bool> getCompositeChanMask(int whichrow, const std::vector<bool>& inMask);
     670  //std::vector<bool> getCompositeChanMask(int whichrow, const std::vector<bool>& inMask, const std::vector<int>& edge, const int minEdgeSize, STLineFinder& lineFinder);
    611671
    612672  void applyChanFlag( casa::uInt whichrow, const std::vector<bool>& msk, casa::uChar flagval);
  • trunk/src/ScantableWrapper.h

    r1994 r2012  
    230230  { return table_->getFit(whichrow); }
    231231
    232   void calculateAZEL() { table_->calculateAZEL(); };
     232  void calculateAZEL() { table_->calculateAZEL(); }
    233233
    234234  std::vector<std::string> columnNames() const
     
    257257  { table_->reshapeSpectrum( nmin, nmax ); }
    258258
    259   STFitEntry polyBaseline(const std::vector<bool>& mask, int order, int rowno)
    260   { return table_->polyBaseline(mask, order, rowno); }
    261 
    262   void polyBaselineBatch(const std::vector<bool>& mask, int order)
    263   { table_->polyBaselineBatch(mask, order); }
     259  void polyBaseline(const std::vector<bool>& mask, int order, bool outlog=false, const std::string& blfile="")
     260  { table_->polyBaseline(mask, order, outlog, blfile); }
     261
     262  void autoPolyBaseline(const std::vector<bool>& mask, int order, const std::vector<int>& edge, float threshold=5.0, int chan_avg_limit=1, bool outlog=false, const std::string& blfile="")
     263  { table_->autoPolyBaseline(mask, order, edge, threshold, chan_avg_limit, outlog, blfile); }
     264
     265  void cubicSplineBaseline(const std::vector<bool>& mask, int npiece, float clipthresh, int clipniter, bool outlog=false, const std::string& blfile="")
     266  { table_->cubicSplineBaseline(mask, npiece, clipthresh, clipniter, outlog, blfile); }
     267
     268  void autoCubicSplineBaseline(const std::vector<bool>& mask, int npiece, float clipthresh, int clipniter, const std::vector<int>& edge, float threshold=5.0, int chan_avg_limit=1, bool outlog=false, const std::string& blfile="")
     269  { table_->autoCubicSplineBaseline(mask, npiece, clipthresh, clipniter, edge, threshold, chan_avg_limit, outlog, blfile); }
     270
     271  float getRms(const std::vector<bool>& mask, int whichrow)
     272  { return table_->getRms(mask, whichrow); }
     273
     274  std::string formatBaselineParams(const std::vector<float>& params, const std::vector<bool>& fixed, float rms, const std::string& masklist, int whichrow, bool verbose=false)
     275  { return table_->formatBaselineParams(params, fixed, rms, masklist, whichrow, verbose); }
     276
     277  std::string formatPiecewiseBaselineParams(const std::vector<int>& ranges, const std::vector<float>& params, const std::vector<bool>& fixed, float rms, const std::string& masklist, int whichrow, bool verbose=false)
     278  { return table_->formatPiecewiseBaselineParams(ranges, params, fixed, rms, masklist, whichrow, verbose); }
    264279
    265280  bool getFlagtraFast(int whichrow=0) const
    266     { return table_->getFlagtraFast(whichrow); }
     281  { return table_->getFlagtraFast(whichrow); }
     282
    267283
    268284
  • trunk/src/python_STLineFinder.cpp

    r894 r2012  
    4242         .def("setoptions",&STLineFinder::setOptions)
    4343         .def("setscan",&STLineFinder::setScan)
     44         .def("setdata",&STLineFinder::setData)
    4445         .def("findlines",&STLineFinder::findLines)
    4546         .def("getmask",&STLineFinder::getMask)
  • trunk/src/python_Scantable.cpp

    r1947 r2012  
    143143          boost::python::arg("nmax")=-1) )
    144144    .def("_poly_baseline", &ScantableWrapper::polyBaseline)
    145     .def("_poly_baseline_batch", &ScantableWrapper::polyBaselineBatch)
     145    .def("_auto_poly_baseline", &ScantableWrapper::autoPolyBaseline)
     146    .def("_cspline_baseline", &ScantableWrapper::cubicSplineBaseline)
     147    .def("_auto_cspline_baseline", &ScantableWrapper::autoCubicSplineBaseline)
     148    .def("get_rms", &ScantableWrapper::getRms)
     149    .def("format_blparams_row", &ScantableWrapper::formatBaselineParams)
     150    .def("format_piecewise_blparams_row", &ScantableWrapper::formatPiecewiseBaselineParams)
    146151    .def("_getflagtrafast", &ScantableWrapper::getFlagtraFast,
    147152         (boost::python::arg("whichrow")=0) )
     153    //.def("_sspline_baseline", &ScantableWrapper::smoothingSplineBaseline,
     154    // (boost::python::arg("thres")=3.0,
     155    //  boost::python::arg("niter")=1) )
     156    //.def("_test_cin", &ScantableWrapper::testCin)
    148157  ;
    149158};
Note: See TracChangeset for help on using the changeset viewer.