예제 #1
0
    def test_curvefit_simplecovariance(self):
        def func(x, a, b):
            return a * np.exp(-b * x)

        def jac(x, a, b):
            e = np.exp(-b * x)
            return np.vstack((e, -a * x * e)).T

        np.random.seed(0)
        xdata = np.linspace(0, 4, 50)
        y = func(xdata, 2.5, 1.3)
        ydata = y + 0.2 * np.random.normal(size=len(xdata))

        sigma = np.zeros(len(xdata)) + 0.2
        covar = np.diag(sigma**2)

        for jac1, jac2 in [(jac, jac), (None, None)]:
            for absolute_sigma in [False, True]:
                popt1, pcov1 = curve_fit(func,
                                         xdata,
                                         ydata,
                                         sigma=sigma,
                                         jac=jac1,
                                         absolute_sigma=absolute_sigma)
                popt2, pcov2 = curve_fit(func,
                                         xdata,
                                         ydata,
                                         sigma=covar,
                                         jac=jac2,
                                         absolute_sigma=absolute_sigma)

                assert_allclose(popt1, popt2, atol=1e-14)
                assert_allclose(pcov1, pcov2, atol=1e-14)
예제 #2
0
    def test_bounds(self):
        def f(x, a, b):
            return a * np.exp(-b * x)

        xdata = np.linspace(0, 1, 11)
        ydata = f(xdata, 2., 2.)

        # The minimum w/out bounds is at [2., 2.],
        # and with bounds it's at [1.5, smth].
        bounds = ([1., 0], [1.5, 3.])
        for method in [None, 'trf', 'dogbox']:
            popt, pcov = curve_fit(f,
                                   xdata,
                                   ydata,
                                   bounds=bounds,
                                   method=method)
            assert_allclose(popt[0], 1.5)

        # With bounds, the starting estimate is feasible.
        popt, pcov = curve_fit(f,
                               xdata,
                               ydata,
                               method='trf',
                               bounds=([0., 0], [0.6, np.inf]))
        assert_allclose(popt[0], 0.6)

        # method='lm' doesn't support bounds.
        assert_raises(ValueError,
                      curve_fit,
                      f,
                      xdata,
                      ydata,
                      bounds=bounds,
                      method='lm')
예제 #3
0
    def test_dtypes2(self):
        # regression test for gh-7117: curve_fit fails if
        # both inputs are float32
        def hyperbola(x, s_1, s_2, o_x, o_y, c):
            b_2 = (s_1 + s_2) / 2
            b_1 = (s_2 - s_1) / 2
            return o_y + b_1 * (x - o_x) + b_2 * np.sqrt(
                (x - o_x)**2 + c**2 / 4)

        min_fit = np.array([-3.0, 0.0, -2.0, -10.0, 0.0])
        max_fit = np.array([0.0, 3.0, 3.0, 0.0, 10.0])
        guess = np.array([-2.5 / 3.0, 4 / 3.0, 1.0, -4.0, 0.5])

        params = [-2, .4, -1, -5, 9.5]
        xdata = np.array([-32, -16, -8, 4, 4, 8, 16, 32])
        ydata = hyperbola(xdata, *params)

        # run optimization twice, with xdata being float32 and float64
        popt_64, _ = curve_fit(f=hyperbola,
                               xdata=xdata,
                               ydata=ydata,
                               p0=guess,
                               bounds=(min_fit, max_fit))

        xdata = xdata.astype(np.float32)
        ydata = hyperbola(xdata, *params)

        popt_32, _ = curve_fit(f=hyperbola,
                               xdata=xdata,
                               ydata=ydata,
                               p0=guess,
                               bounds=(min_fit, max_fit))

        assert_allclose(popt_32, popt_64, atol=2e-5)
예제 #4
0
    def test_curvefit_covariance(self):
        def funcp(x, a, b):
            rotn = np.array([[1. / np.sqrt(2), -1. / np.sqrt(2), 0],
                             [1. / np.sqrt(2), 1. / np.sqrt(2), 0],
                             [0, 0, 1.0]])
            return rotn.dot(a * np.exp(-b * x))

        def jacp(x, a, b):
            rotn = np.array([[1. / np.sqrt(2), -1. / np.sqrt(2), 0],
                             [1. / np.sqrt(2), 1. / np.sqrt(2), 0],
                             [0, 0, 1.0]])
            e = np.exp(-b * x)
            return rotn.dot(np.vstack((e, -a * x * e)).T)

        def func(x, a, b):
            return a * np.exp(-b * x)

        def jac(x, a, b):
            e = np.exp(-b * x)
            return np.vstack((e, -a * x * e)).T

        np.random.seed(0)
        xdata = np.arange(1, 4)
        y = func(xdata, 2.5, 1.0)
        ydata = y + 0.2 * np.random.normal(size=len(xdata))
        sigma = np.zeros(len(xdata)) + 0.2
        covar = np.diag(sigma**2)
        # Get a rotation matrix, and obtain ydatap = R ydata
        # Chisq = ydata^T C^{-1} ydata
        #       = ydata^T R^T R C^{-1} R^T R ydata
        #       = ydatap^T Cp^{-1} ydatap
        # Cp^{-1} = R C^{-1} R^T
        # Cp      = R C R^T, since R^-1 = R^T
        rotn = np.array([[1. / np.sqrt(2), -1. / np.sqrt(2), 0],
                         [1. / np.sqrt(2), 1. / np.sqrt(2), 0], [0, 0, 1.0]])
        ydatap = rotn.dot(ydata)
        covarp = rotn.dot(covar).dot(rotn.T)

        for jac1, jac2 in [(jac, jacp), (None, None)]:
            for absolute_sigma in [False, True]:
                popt1, pcov1 = curve_fit(func,
                                         xdata,
                                         ydata,
                                         sigma=sigma,
                                         jac=jac1,
                                         absolute_sigma=absolute_sigma)
                popt2, pcov2 = curve_fit(funcp,
                                         xdata,
                                         ydatap,
                                         sigma=covarp,
                                         jac=jac2,
                                         absolute_sigma=absolute_sigma)

                assert_allclose(popt1, popt2, rtol=1.2e-7, atol=1e-14)
                assert_allclose(pcov1, pcov2, rtol=1.2e-7, atol=1e-14)
예제 #5
0
    def test_args_in_kwargs(self):
        # Ensure that `args` cannot be passed as keyword argument to `curve_fit`

        def func(x, a, b):
            return a * x + b

        with assert_raises(ValueError):
            curve_fit(func,
                      xdata=[1, 2, 3, 4],
                      ydata=[5, 9, 13, 17],
                      p0=[1],
                      args=(1, ))
예제 #6
0
 def test_broadcast_y(self):
     xdata = np.arange(10)
     target = 4.7 * xdata**2 + 3.5 * xdata + np.random.rand(len(xdata))
     fit_func = lambda x, a, b: a * x**2 + b * x - target
     for method in ['lm', 'trf', 'dogbox']:
         popt0, pcov0 = curve_fit(fit_func,
                                  xdata=xdata,
                                  ydata=np.zeros_like(xdata),
                                  method=method)
         popt1, pcov1 = curve_fit(fit_func,
                                  xdata=xdata,
                                  ydata=0,
                                  method=method)
         assert_allclose(pcov0, pcov1)
예제 #7
0
    def test_regression_2639(self):
        # This test fails if epsfcn in leastsq is too large.
        x = [
            574.14200000000005, 574.154, 574.16499999999996,
            574.17700000000002, 574.18799999999999, 574.19899999999996,
            574.21100000000001, 574.22199999999998, 574.23400000000004, 574.245
        ]
        y = [
            859.0, 997.0, 1699.0, 2604.0, 2013.0, 1964.0, 2435.0, 1550.0,
            949.0, 841.0
        ]
        guess = [
            574.1861428571428, 574.2155714285715, 1302.0, 1302.0,
            0.0035019999999983615, 859.0
        ]
        good = [
            5.74177150e+02, 5.74209188e+02, 1.74187044e+03, 1.58646166e+03,
            1.0068462e-02, 8.57450661e+02
        ]

        def f_double_gauss(x, x0, x1, A0, A1, sigma, c):
            return (A0 * np.exp(-(x - x0)**2 / (2. * sigma**2)) +
                    A1 * np.exp(-(x - x1)**2 / (2. * sigma**2)) + c)

        popt, pcov = curve_fit(f_double_gauss, x, y, guess, maxfev=10000)
        assert_allclose(popt, good, rtol=1e-5)
예제 #8
0
    def test_array_like(self):
        # Test sequence input. Regression test for gh-3037.
        def f_linear(x, a, b):
            return a * x + b

        x = [1, 2, 3, 4]
        y = [3, 5, 7, 9]
        assert_allclose(curve_fit(f_linear, x, y)[0], [2, 1], atol=1e-10)
예제 #9
0
    def test_maxfev_and_bounds(self):
        # gh-6340: with no bounds, curve_fit accepts parameter maxfev (via leastsq)
        # but with bounds, the parameter is `max_nfev` (via least_squares)
        x = np.arange(0, 10)
        y = 2 * x
        popt1, _ = curve_fit(lambda x, p: p * x,
                             x,
                             y,
                             bounds=(0, 3),
                             maxfev=100)
        popt2, _ = curve_fit(lambda x, p: p * x,
                             x,
                             y,
                             bounds=(0, 3),
                             max_nfev=100)

        assert_allclose(popt1, 2, atol=1e-14)
        assert_allclose(popt2, 2, atol=1e-14)
예제 #10
0
    def test_one_argument(self):
        def func(x, a):
            return x**a

        popt, pcov = curve_fit(func, self.x, self.y)
        assert_(len(popt) == 1)
        assert_(pcov.shape == (1, 1))
        assert_almost_equal(popt[0], 1.9149, decimal=4)
        assert_almost_equal(pcov[0, 0], 0.0016, decimal=4)

        # Test if we get the same with full_output. Regression test for #1415.
        # Also test if check_finite can be turned off.
        res = curve_fit(func,
                        self.x,
                        self.y,
                        full_output=1,
                        check_finite=False)
        (popt2, pcov2, infodict, errmsg, ier) = res
        assert_array_almost_equal(popt, popt2)
예제 #11
0
    def test_two_argument(self):
        def func(x, a, b):
            return b * x**a

        popt, pcov = curve_fit(func, self.x, self.y)
        assert_(len(popt) == 2)
        assert_(pcov.shape == (2, 2))
        assert_array_almost_equal(popt, [1.7989, 1.1642], decimal=4)
        assert_array_almost_equal(pcov, [[0.0852, -0.1260], [-0.1260, 0.1912]],
                                  decimal=4)
예제 #12
0
    def test_jac(self):
        # Test that Jacobian callable is handled correctly and
        # weighted if sigma is provided.
        def f(x, a, b):
            return a * np.exp(-b * x)

        def jac(x, a, b):
            e = np.exp(-b * x)
            return np.vstack((e, -a * x * e)).T

        xdata = np.linspace(0, 1, 11)
        ydata = f(xdata, 2., 2.)

        # Test numerical options for least_squares backend.
        for method in ['trf', 'dogbox']:
            for scheme in ['2-point', '3-point', 'cs']:
                popt, pcov = curve_fit(f,
                                       xdata,
                                       ydata,
                                       jac=scheme,
                                       method=method)
                assert_allclose(popt, [2, 2])

        # Test the analytic option.
        for method in ['lm', 'trf', 'dogbox']:
            popt, pcov = curve_fit(f, xdata, ydata, method=method, jac=jac)
            assert_allclose(popt, [2, 2])

        # Now add an outlier and provide sigma.
        ydata[5] = 100
        sigma = np.ones(xdata.shape[0])
        sigma[5] = 200
        for method in ['lm', 'trf', 'dogbox']:
            popt, pcov = curve_fit(f,
                                   xdata,
                                   ydata,
                                   sigma=sigma,
                                   method=method,
                                   jac=jac)
            # Still the optimization process is influenced somehow,
            # have to set rtol=1e-3.
            assert_allclose(popt, [2, 2], rtol=1e-3)
예제 #13
0
    def test_bounds_p0(self):
        # This test is for issue #5719. The problem was that an initial guess
        # was ignored when 'trf' or 'dogbox' methods were invoked.
        def f(x, a):
            return np.sin(x + a)

        xdata = np.linspace(-2 * np.pi, 2 * np.pi, 40)
        ydata = np.sin(xdata)
        bounds = (-3 * np.pi, 3 * np.pi)
        for method in ['trf', 'dogbox']:
            popt_1, _ = curve_fit(f, xdata, ydata, p0=2.1 * np.pi)
            popt_2, _ = curve_fit(f,
                                  xdata,
                                  ydata,
                                  p0=2.1 * np.pi,
                                  bounds=bounds,
                                  method=method)

            # If the initial guess is ignored, then popt_2 would be close 0.
            assert_allclose(popt_1, popt_2)
예제 #14
0
    def test_method_argument(self):
        def f(x, a, b):
            return a * np.exp(-b * x)

        xdata = np.linspace(0, 1, 11)
        ydata = f(xdata, 2., 2.)

        for method in ['trf', 'dogbox', 'lm', None]:
            popt, pcov = curve_fit(f, xdata, ydata, method=method)
            assert_allclose(popt, [2., 2.])

        assert_raises(ValueError, curve_fit, f, xdata, ydata, method='unknown')
예제 #15
0
    def test_func_is_classmethod(self):
        class test_self:
            """This class tests if curve_fit passes the correct number of
               arguments when the model function is a class instance method.
            """
            def func(self, x, a, b):
                return b * x**a

        test_self_inst = test_self()
        popt, pcov = curve_fit(test_self_inst.func, self.x, self.y)
        assert_(pcov.shape == (2, 2))
        assert_array_almost_equal(popt, [1.7989, 1.1642], decimal=4)
        assert_array_almost_equal(pcov, [[0.0852, -0.1260], [-0.1260, 0.1912]],
                                  decimal=4)
예제 #16
0
    def test_dtypes(self):
        # regression test for gh-9581: curve_fit fails if x and y dtypes differ
        x = np.arange(-3, 5)
        y = 1.5 * x + 3.0 + 0.5 * np.sin(x)

        def func(x, a, b):
            return a * x + b

        for method in ['lm', 'trf', 'dogbox']:
            for dtx in [np.float32, np.float64]:
                for dty in [np.float32, np.float64]:
                    x = x.astype(dtx)
                    y = y.astype(dty)

                with warnings.catch_warnings():
                    warnings.simplefilter("error", OptimizeWarning)
                    p, cov = curve_fit(func, x, y, method=method)

                    assert np.isfinite(cov).all()
                    assert not np.allclose(p, 1)  # curve_fit's initial value
예제 #17
0
    def test_full_output(self):
        def f(x, a, b):
            return a * np.exp(-b * x)

        xdata = np.linspace(0, 1, 11)
        ydata = f(xdata, 2., 2.)

        for method in ['trf', 'dogbox', 'lm', None]:
            popt, pcov, infodict, errmsg, ier = curve_fit(f,
                                                          xdata,
                                                          ydata,
                                                          method=method,
                                                          full_output=True)
            assert_allclose(popt, [2., 2.])
            assert "nfev" in infodict
            assert "fvec" in infodict
            if method == 'lm' or method is None:
                assert "fjac" in infodict
                assert "ipvt" in infodict
                assert "qtf" in infodict
            assert isinstance(errmsg, str)
            assert ier in (1, 2, 3, 4)
예제 #18
0
    def test_pcov(self):
        xdata = np.array([0, 1, 2, 3, 4, 5])
        ydata = np.array([1, 1, 5, 7, 8, 12])
        sigma = np.array([1, 2, 1, 2, 1, 2])

        def f(x, a, b):
            return a * x + b

        for method in ['lm', 'trf', 'dogbox']:
            popt, pcov = curve_fit(f,
                                   xdata,
                                   ydata,
                                   p0=[2, 0],
                                   sigma=sigma,
                                   method=method)
            perr_scaled = np.sqrt(np.diag(pcov))
            assert_allclose(perr_scaled, [0.20659803, 0.57204404], rtol=1e-3)

            popt, pcov = curve_fit(f,
                                   xdata,
                                   ydata,
                                   p0=[2, 0],
                                   sigma=3 * sigma,
                                   method=method)
            perr_scaled = np.sqrt(np.diag(pcov))
            assert_allclose(perr_scaled, [0.20659803, 0.57204404], rtol=1e-3)

            popt, pcov = curve_fit(f,
                                   xdata,
                                   ydata,
                                   p0=[2, 0],
                                   sigma=sigma,
                                   absolute_sigma=True,
                                   method=method)
            perr = np.sqrt(np.diag(pcov))
            assert_allclose(perr, [0.30714756, 0.85045308], rtol=1e-3)

            popt, pcov = curve_fit(f,
                                   xdata,
                                   ydata,
                                   p0=[2, 0],
                                   sigma=3 * sigma,
                                   absolute_sigma=True,
                                   method=method)
            perr = np.sqrt(np.diag(pcov))
            assert_allclose(perr, [3 * 0.30714756, 3 * 0.85045308], rtol=1e-3)

        # infinite variances

        def f_flat(x, a, b):
            return a * x

        pcov_expected = np.array([np.inf] * 4).reshape(2, 2)

        with suppress_warnings() as sup:
            sup.filter(OptimizeWarning,
                       "Covariance of the parameters could not be estimated")
            popt, pcov = curve_fit(f_flat,
                                   xdata,
                                   ydata,
                                   p0=[2, 0],
                                   sigma=sigma)
            popt1, pcov1 = curve_fit(f, xdata[:2], ydata[:2], p0=[2, 0])

        assert_(pcov.shape == (2, 2))
        assert_array_equal(pcov, pcov_expected)

        assert_(pcov1.shape == (2, 2))
        assert_array_equal(pcov1, pcov_expected)
예제 #19
0
    def test_data_point_number_validation(self):
        def func(x, a, b, c, d, e):
            return a * np.exp(-b * x) + c + d + e

        with assert_raises(TypeError, match="The number of func parameters="):
            curve_fit(func, xdata=[1, 2, 3, 4], ydata=[5, 9, 13, 17])
예제 #20
0
 def test_None_x(self):  # Added in GH10196
     popt, pcov = curve_fit(lambda _, a: a * np.arange(10), None,
                            2 * np.arange(10))
     assert_allclose(popt, [2.])