Example #1
0
    def workit(self, xdata, ydata, invvar, action, lower, upper):
        """An internal routine for bspline_extract and bspline_radial which solve a general
        banded correlation matrix which is represented by the variable "action".  This routine
        only solves the linear system once, and stores the coefficients in sset. A non-zero return value
        signifies a failed inversion


        Parameters
        ----------
        xdata : `numpy.ndarray`_
            Independent variable.
        ydata : `numpy.ndarray`_
            Dependent variable.
        invvar : `numpy.ndarray`_
            Inverse variance of `ydata`.
        action : `numpy.ndarray`_
            Banded correlation matrix
        lower  : `numpy.ndarray`_
            A list of pixel positions, each corresponding to the first occurence of position greater than breakpoint indx
        upper  : `numpy.ndarray`_
            Same as lower, but denotes the upper pixel positions

        Returns
        -------
        success : :obj:`int`
            Method error code: 0 is good; -1 is dropped breakpoints,
            try again; -2 is failure, should abort.
        yfit : `numpy.ndarray`_
            Evaluation of the b-spline yfit at the input values.
        """
        goodbk = self.mask[self.nord:]
        # KBW: Interesting: x.sum() is actually a bit faster than np.sum(x)
        nn = goodbk.sum()
        if nn < self.nord:
            warnings.warn(
                'Fewer good break points than order of b-spline. Returning...')
            # KBW: Why is the dtype set to 'f' = np.float32?
            return -2, np.zeros(ydata.shape, dtype=float)

        alpha, beta = solution_arrays(nn, self.npoly, self.nord, ydata, action,
                                      invvar, upper, lower)
        nfull = nn * self.npoly

        # Right now we are not returning the covariance, although it may arise that we should
        #        covariance = alpha
        err, a = cholesky_band(alpha, mininf=1.0e-10 * invvar.sum() / nfull)

        # successful cholseky_band returns -1
        if not isinstance(err, int) or err != -1:
            return self.maskpoints(err), \
                        self.value(xdata, x2=xdata, action=action, upper=upper, lower=lower)[0]

        # NOTE: cholesky_solve ALWAYS returns err == -1; don't even catch it.
        sol = cholesky_solve(a, beta)[1]

        if self.coeff.ndim == 2:
            self.icoeff[:,
                        goodbk] = np.array(a[0, :nfull].T.reshape(self.npoly,
                                                                  nn,
                                                                  order='F'),
                                           dtype=a.dtype)
            self.coeff[:, goodbk] = np.array(sol[:nfull].T.reshape(self.npoly,
                                                                   nn,
                                                                   order='F'),
                                             dtype=sol.dtype)
        else:
            self.icoeff[goodbk] = np.array(a[0, :nfull], dtype=a.dtype)
            self.coeff[goodbk] = np.array(sol[:nfull], dtype=sol.dtype)

        return 0, self.value(xdata,
                             x2=xdata,
                             action=action,
                             upper=upper,
                             lower=lower)[0]
Example #2
0
    def fit(self, xdata, ydata, invvar, x2=None):
        """Calculate a B-spline in the least-squares sense.

        Fit is based on two variables: x which is sorted and spans a large range
        where bkpts are required y which can be described with a low order
        polynomial.

        Parameters
        ----------
        xdata : `numpy.ndarray`_
            Independent variable.
        ydata : `numpy.ndarray`_
            Dependent variable.
        invvar : `numpy.ndarray`_
            Inverse variance of `ydata`.
        x2 : `numpy.ndarray`_, optional
            Orthogonal dependent variable for 2d fits.

        Returns
        -------
        :obj:`tuple`
            A tuple containing an integer error code, and the evaluation of the
            b-spline at the input values.  An error code of -2 is a failure,
            -1 indicates dropped breakpoints, 0 is success, and positive
            integers indicate ill-conditioned breakpoints.
        """
        goodbk = self.mask[self.nord:]
        nn = goodbk.sum()
        if nn < self.nord:
            yfit = np.zeros(ydata.shape, dtype=float)
            return (-2, yfit)
        nfull = nn * self.npoly
        bw = self.npoly * self.nord
        a1, lower, upper = self.action(xdata, x2=x2)
        foo = np.tile(invvar, bw).reshape(bw, invvar.size).transpose()
        a2 = a1 * foo
        alpha = np.zeros((bw, nfull + bw), dtype=float)
        beta = np.zeros((nfull + bw, ), dtype=float)
        bi = np.arange(bw, dtype=int)
        bo = np.arange(bw, dtype=int)
        for k in range(1, bw):
            bi = np.append(bi, np.arange(bw - k, dtype=int) + (bw + 1) * k)
            bo = np.append(bo, np.arange(bw - k, dtype=int) + bw * k)
        for k in range(nn - self.nord + 1):
            itop = k * self.npoly
            ibottom = min(itop, nfull) + bw - 1
            ict = upper[k] - lower[k] + 1
            if ict > 0:
                work = np.dot(a1[lower[k]:upper[k] + 1, :].T,
                              a2[lower[k]:upper[k] + 1, :])
                wb = np.dot(ydata[lower[k]:upper[k] + 1],
                            a2[lower[k]:upper[k] + 1, :])
                alpha.T.flat[bo + itop * bw] += work.flat[bi]
                beta[itop:ibottom + 1] += wb
        min_influence = 1.0e-10 * invvar.sum() / nfull
        errb = cholesky_band(alpha, mininf=min_influence)  # ,verbose=True)
        if isinstance(errb[0], int) and errb[0] == -1:
            a = errb[1]
        else:
            yfit, foo = self.value(xdata,
                                   x2=x2,
                                   action=a1,
                                   upper=upper,
                                   lower=lower)
            return (self.maskpoints(errb[0]), yfit)
        errs = cholesky_solve(a, beta)
        if isinstance(errs[0], int) and errs[0] == -1:
            sol = errs[1]
        else:
            #
            # It is not possible for this to get called, because cholesky_solve
            # has only one return statement, & that statement guarantees that
            # errs[0] == -1
            #
            yfit, foo = self.value(xdata,
                                   x2=x2,
                                   action=a1,
                                   upper=upper,
                                   lower=lower)
            return (self.maskpoints(errs[0]), yfit)
        if self.coeff.ndim == 2:
            # JFH made major bug fix here.
            self.icoeff[:, goodbk] = np.array(a[0,
                                                0:nfull].T.reshape(self.npoly,
                                                                   nn,
                                                                   order='F'),
                                              dtype=a.dtype)
            self.coeff[:, goodbk] = np.array(sol[0:nfull].T.reshape(self.npoly,
                                                                    nn,
                                                                    order='F'),
                                             dtype=sol.dtype)
        else:
            self.icoeff[goodbk] = np.array(a[0, 0:nfull], dtype=a.dtype)
            self.coeff[goodbk] = np.array(sol[0:nfull], dtype=sol.dtype)
        yfit, foo = self.value(xdata,
                               x2=x2,
                               action=a1,
                               upper=upper,
                               lower=lower)
        return (0, yfit)