Beispiel #1
0
    def test_harmonic_oscillator_errors(self):
        """
        Make sure the errors produced by fitting ODE's are the same as when
        fitting an exact solution.
        """
        x, v, t = sf.variables('x, v, t')
        k = sf.Parameter(name='k', value=100)
        m = 1
        a = -k/m * x
        ode_model = sf.ODEModel({sf.D(v, t): a,
                                 sf.D(x, t): v},
                                initial={t: 0, v: 0, x: 1})

        t_data = np.linspace(0, 10, 250)
        np.random.seed(2)
        noise = np.random.normal(1, 0.05, size=t_data.shape)
        x_data = ode_model(t=t_data, k=100).x * noise

        ode_fit = sf.Fit(ode_model, t=t_data, x=x_data)
        ode_result = ode_fit.execute()

        phi = 0
        A = 1
        model = sf.Model({x: A * sf.cos(sf.sqrt(k/m) * t + phi)})
        fit = sf.Fit(model, t=t_data, x=x_data)
        result = fit.execute()

        self.assertAlmostEqual(result.value(k), ode_result.value(k), places=4)
        self.assertAlmostEqual(result.stdev(k) / ode_result.stdev(k), 1, 2)
        self.assertGreaterEqual(result.stdev(k), ode_result.stdev(k))
def test_harmonic_oscillator_errors():
    """
    Make sure the errors produced by fitting ODE's are the same as when
    fitting an exact solution.
    """
    x, v, t = sf.variables('x, v, t')
    k = sf.Parameter(name='k', value=100)
    m = 1
    a = -k/m * x
    ode_model = sf.ODEModel({sf.D(v, t): a,
                             sf.D(x, t): v},
                            initial={t: 0, v: 0, x: 1})

    t_data = np.linspace(0, 10, 250)
    np.random.seed(2)
    noise = np.random.normal(1, 0.05, size=t_data.shape)
    x_data = ode_model(t=t_data, k=100).x * noise

    ode_fit = sf.Fit(ode_model, t=t_data, x=x_data, v=None)
    ode_result = ode_fit.execute()

    phi = 0
    A = 1
    model = sf.Model({x: A * sf.cos(sf.sqrt(k/m) * t + phi)})
    fit = sf.Fit(model, t=t_data, x=x_data)
    result = fit.execute()

    assert result.value(k) == pytest.approx(ode_result.value(k), 1e-4)
    assert result.stdev(k) == pytest.approx(ode_result.stdev(k), 1e-2)
    assert result.stdev(k) >= ode_result.stdev(k)
Beispiel #3
0
def fourier_series(x, f, n=0):
    # Make the parameter objects for all the terms
    a0, *A = parameters(','.join([f'a{i}' for i in range(0, n + 1)]))
    B = parameters(','.join([f'b{i}' for i in range(1, n + 1)]))
    # Construct the series
    series = a0 + sum(ai*cos(i*f*x) + bi*sin(i*f*x)
                     for i, (ai, bi) in enumerate(zip(A, B), start=1))
    return series
Beispiel #4
0
def Fourier_series(x, f, n = 0):
    """Construit la série de Fourier comme modèle de référence pour le fitting."""

    a0, *cos_a = parameters(','.join(['a{}'.format(i) for i in range(0, n + 1)]))
    sin_b = parameters(','.join(['b{}'.format(i) for i in range(1, n + 1)]))
    series = a0 + sum(ai * cos(i * f * x) + bi * sin(i * f * x) for i, (ai, bi) in enumerate(zip(cos_a, sin_b), start=1))

    return series
 def fourier_series(self, x, f, n=2):
     a0, *cos_a = parameters(','.join(
         ['a{}'.format(i) for i in range(0, n + 1)]))
     sin_b = parameters(','.join(['b{}'.format(i)
                                  for i in range(1, n + 1)]))
     series = a0 + sum(
         ai * cos(i * f * x) + bi * sin(i * f * x)
         for i, (ai, bi) in enumerate(zip(cos_a, sin_b), start=1))
     return series
Beispiel #6
0
def test_LogLikelihood_global():
    """
    This is a test for global likelihood fitting to multiple data sets.
    Based on SO question 56006357.
    """
    # creating the data
    mu1, mu2 = .05, -.05
    sigma1, sigma2 = 3.5, 2.5
    n1, n2 = 80, 90
    np.random.seed(42)
    x1 = np.random.vonmises(mu1, sigma1, n1)
    x2 = np.random.vonmises(mu2, sigma2, n2)

    n = 2  # number of components
    xs = variables('x,' + ','.join('x_{}'.format(i) for i in range(1, n + 1)))
    x, xs = xs[0], xs[1:]
    ys = variables(','.join('y_{}'.format(i) for i in range(1, n + 1)))
    mu, kappa = parameters('mu, kappa')
    kappas = parameters(','.join('k_{}'.format(i) for i in range(1, n + 1)),
                        min=0,
                        max=10)
    mu.min, mu.max = -np.pi, np.pi

    template = exp(kappa * cos(x - mu)) / (2 * pi * besseli(0, kappa))

    model = Model({
        y_i: template.subs({
            kappa: k_i,
            x: x_i
        })
        for y_i, x_i, k_i in zip(ys, xs, kappas)
    })

    all_data = {xs[0]: x1, xs[1]: x2, ys[0]: None, ys[1]: None}
    all_params = {'mu': 1}
    all_params.update({k_i.name: 1 for k_i in kappas})

    # Evaluate the loglikelihood and its jacobian and hessian
    logL = LogLikelihood(model, data=all_data)
    eval_numerical = logL(**all_params)
    jac_numerical = logL.eval_jacobian(**all_params)
    hess_numerical = logL.eval_hessian(**all_params)

    # Test the types and shapes of the components.
    assert isinstance(eval_numerical, float)
    assert isinstance(jac_numerical, np.ndarray)
    assert isinstance(hess_numerical, np.ndarray)

    assert eval_numerical.shape == tuple()  # Empty tuple -> scalar
    assert jac_numerical.shape == (3, )
    assert hess_numerical.shape == (
        3,
        3,
    )
def fourier_series(x, f, n=0):
    """
    Returns a symbolic fourier series of order `n`.

    :param n: Order of the fourier series.
    :param x: Independent variable
    :param f: Frequency of the fourier series
    """
    # Make the parameter objects for all the terms
    a0, *cos_a = parameters(','.join(['a{}'.format(i) for i in range(0, n + 1)]))
    sin_b = parameters(','.join(['b{}'.format(i) for i in range(1, n + 1)]))
    # Construct the series
    series = a0 + sum(ai * cos(i * f * x) + bi * sin(i * f * x)
                     for i, (ai, bi) in enumerate(zip(cos_a, sin_b), start=1))
    return series
Beispiel #8
0
    def run(
            self,
            angle=0.02472,
            pixel_to_micron_x=9.81e-8,
            beam_waist_xy=0.5e-6,
            beam_waist_z=2e-6,
            rbc_radius=4e-6,
            s=1,
            tau=0.001,
    ):
        # create parameters for symfit
        distances = self.data.keys()
        v = sf.parameters('v_', value=500, min=0, max=1000)[0]
        d = sf.parameters('D_', value=50, min=0, max=100)[0]
        y0_p = sf.parameters(
            self.create_distance_strings('y0'),
            min=0,
            max=1,
        )
        b_p = sf.parameters(
            self.create_distance_strings('b'),
            value=50,
            min=0,
            max=100,
        )
        # create variables for symfit
        x = sf.variables('x')[0]
        y_var = sf.variables(self.create_distance_strings('y'))

        # create model
        # pixel_to_micron_x
        model = sf.Model({
            y:
            y0 + b * sf.exp(-(dst * pixel_to_micron_x - v * (sf.cos(angle)) * x)**2 / (beam_waist_xy + 0.5 * rbc_radius**2 + 4 * d * x)) * sf.exp(-(x**2) * (v * sf.sin(angle) - pixel_to_micron_x / tau)**2 / (beam_waist_xy + 0.5 * rbc_radius**2 + angle * d * x)) / (4 * d * x + beam_waist_xy + 0.5 * rbc_radius**2)
            for y, y0, b, dst in zip(y_var, y0_p, b_p, distances)
        })
        # dependent variables dict
        data = {y.name: self.data[dst] for y, dst in zip(y_var, distances)}
        # independent variable x
        n_data_points = len(list(self.data.values())[0])
        max_time = n_data_points * tau
        x_data = np.linspace(0, max_time, n_data_points)
        # fit
        fit = sf.Fit(model, x=x_data, **data)
        res = fit.execute()
        return res
Beispiel #9
0
def fourier_series(x, period_list):
    """
    Returns a symbolic fourier series of order `n`.

    :param n: Order of the fourier series.
    :param x: Independent variable
    :param f: Frequency of the fourier series
    """
    # Make the parameter objects for all the terms
    (a0, ) = parameters("a0")
    cos_a = parameters(",".join(
        ["a{}".format(i) for i in range2(len(period_list))]))
    sin_b = parameters(",".join(
        ["b{}".format(i) for i in range2(len(period_list))]))
    # Construct the series
    print(period_list)
    series = a0 + sum(
        ai * cos(2 * math.pi / tau * x) + bi * sin(2 * math.pi / tau * x)
        for (tau, ai, bi) in zip(period_list, cos_a, sin_b))
    return series
Beispiel #10
0
 def do_glob_fit(self):
     """this method performs global fit on the CCPS"""
     # create parameters for symfit
     dist = self.data.keys()
     v = sf.parameters('v_', value=500, min=0, max=1000)[0]
     d = sf.parameters('D_', value=50, min=0, max=100)[0]
     y0_p = sf.parameters(', '.join('y0_{}'.format(key)
                                    for key in self.data.keys()),
                          min=0,
                          max=1)
     b_p = sf.parameters(', '.join('b_{}'.format(key)
                                   for key in self.data.keys()),
                         value=50,
                         min=0,
                         max=100)
     # create variables for symfit
     x = sf.variables('x')[0]
     y_var = sf.variables(', '.join('y_{}'.format(key)
                                    for key in self.data.keys()))
     # get fixed & shared params
     dx, a, w2, a2, tau, s, wz2 = self.get_params()
     # create model
     model = sf.Model({
         y: y0 + b * sf.exp(-(dst * dx - v * (sf.cos(a)) * x)**2 /
                            (w2 + 0.5 * a2 + 4 * d * x)) *
         sf.exp(-(x**2) * (v * sf.sin(a) - dx / tau)**2 /
                (w2 + 0.5 * a2 + a * d * x)) / (4 * d * x + w2 + 0.5 * a2)
         for y, y0, b, dst in zip(y_var, y0_p, b_p, dist)
     })
     # dependent variables dict
     data = {y.name: self.data[dst] for y, dst in zip(y_var, dist)}
     # independent variable x
     max_time = len(self.data[20]) * tau
     x_data = np.linspace(0, max_time, len(self.data[20]))
     # fit
     fit = sf.Fit(model, x=x_data, **data)
     res = fit.execute()
     return res
Beispiel #11
0
def fourier_series(x, f, n=0):
    a0, *cos_a = parameters(",".join([f"a{i}" for i in range(n + 1)]))
    sin_b = parameters(",".join([f"b{i}" for i in range(1, n + 1)]))
    series = a0 + sum(ai * cos(i * f * x) + bi * sin(i * f * x)
                      for i, (ai, bi) in enumerate(zip(cos_a, sin_b), start=1))
    return series
Beispiel #12
0
def test_basinhopping_2d():
    def func2d(x):
        f = np.cos(14.5 * x[0] - 0.3) + (x[1] + 0.2) * x[1] + (x[0] + 0.2) * x[0]
        df = np.zeros(2)
        df[0] = -14.5 * np.sin(14.5 * x[0] - 0.3) + 2. * x[0] + 0.2
        df[1] = 2. * x[1] + 0.2
        return f, df

    def func2d_symfit(x1, x2):
        f = np.cos(14.5 * x1 - 0.3) + (x2 + 0.2) * x2 + (x1 + 0.2) * x1
        return f

    def jac2d_symfit(x1, x2):
        df = np.zeros(2)
        df[0] = -14.5 * np.sin(14.5 * x1 - 0.3) + 2. * x1 + 0.2
        df[1] = 2. * x2 + 0.2
        return df

    np.random.seed(555)
    minimizer_kwargs = {'method': 'BFGS', 'jac': True}
    x0 = [1.0, 1.0]
    res = basinhopping(func2d, x0, minimizer_kwargs=minimizer_kwargs, niter=200)

    np.random.seed(555)
    x1, x2 = parameters('x1, x2', value=x0)

    with pytest.raises(TypeError):
        fit = BasinHopping(
            func2d_symfit, [x1, x2],
            local_minimizer=NelderMead(func2d_symfit, [x1, x2],
                                       jacobian=jac2d_symfit)
        )

    fit = BasinHopping(
        func2d_symfit, [x1, x2],
        local_minimizer=BFGS(func2d_symfit, [x1, x2], jacobian=jac2d_symfit)
    )
    fit_result = fit.execute(niter=200)
    assert isinstance(fit.local_minimizer.jacobian, MinimizeModel)
    assert isinstance(fit.local_minimizer.jacobian.model, CallableNumericalModel)
    assert res.x[0] == fit_result.value(x1)
    assert res.x[1] == fit_result.value(x2)
    assert res.fun == fit_result.objective_value

    # Now compare with the symbolic equivalent
    np.random.seed(555)
    model = cos(14.5 * x1 - 0.3) + (x2 + 0.2) * x2 + (x1 + 0.2) * x1
    fit = Fit(model, minimizer=BasinHopping)
    fit_result = fit.execute()
    assert res.x[0] == fit_result.value(x1)
    assert res.x[1] == fit_result.value(x2)
    assert res.fun == fit_result.objective_value
    assert isinstance(fit.minimizer.local_minimizer, BFGS)

    # Impose constrains
    np.random.seed(555)
    model = cos(14.5 * x1 - 0.3) + (x2 + 0.2) * x2 + (x1 + 0.2) * x1
    fit = Fit(model, minimizer=BasinHopping, constraints=[Eq(x1, x2)])
    fit_result = fit.execute()
    assert fit_result.value(x1) == fit_result.value(x2)
    assert isinstance(fit.minimizer.local_minimizer, SLSQP)

    # Impose bounds
    np.random.seed(555)
    x1.min = 0.0
    model = cos(14.5 * x1 - 0.3) + (x2 + 0.2) * x2 + (x1 + 0.2) * x1
    fit = Fit(model, minimizer=BasinHopping)
    fit_result = fit.execute()
    assert fit_result.value(x1) >= x1.min
    assert isinstance(fit.minimizer.local_minimizer, LBFGSB)
Beispiel #13
0
    def test_basinhopping_2d(self):
        def func2d(x):
            f = np.cos(14.5 * x[0] - 0.3) + (x[1] + 0.2) * x[1] + (x[0] + 0.2) * x[0]
            df = np.zeros(2)
            df[0] = -14.5 * np.sin(14.5 * x[0] - 0.3) + 2. * x[0] + 0.2
            df[1] = 2. * x[1] + 0.2
            return f, df

        def func2d_symfit(x1, x2):
            f = np.cos(14.5 * x1 - 0.3) + (x2 + 0.2) * x2 + (x1 + 0.2) * x1
            return f

        def jac2d_symfit(x1, x2):
            df = np.zeros(2)
            df[0] = -14.5 * np.sin(14.5 * x1 - 0.3) + 2. * x1 + 0.2
            df[1] = 2. * x2 + 0.2
            return df

        np.random.seed(555)
        minimizer_kwargs = {'method': 'BFGS', 'jac': True}
        x0 = [1.0, 1.0]
        res = basinhopping(func2d, x0, minimizer_kwargs=minimizer_kwargs, niter=200)

        np.random.seed(555)
        x1, x2 = parameters('x1, x2', value=x0)
        with self.assertRaises(TypeError):
            fit = BasinHopping(
                func2d_symfit, [x1, x2],
                local_minimizer=NelderMead(func2d_symfit, [x1, x2],
                                           jacobian=jac2d_symfit)
            )
        fit = BasinHopping(
            func2d_symfit, [x1, x2],
            local_minimizer=BFGS(func2d_symfit, [x1, x2], jacobian=jac2d_symfit)
        )
        fit_result = fit.execute(niter=200)
        self.assertIsInstance(fit.local_minimizer.jacobian, MinimizeModel)
        self.assertIsInstance(fit.local_minimizer.jacobian.model, CallableNumericalModel)
        self.assertEqual(res.x[0] / fit_result.value(x1), 1.0)
        self.assertEqual(res.x[1] / fit_result.value(x2), 1.0)
        self.assertEqual(res.fun, fit_result.objective_value)

        # Now compare with the symbolic equivalent
        np.random.seed(555)
        model = cos(14.5 * x1 - 0.3) + (x2 + 0.2) * x2 + (x1 + 0.2) * x1
        fit = Fit(model, minimizer=BasinHopping)
        fit_result = fit.execute()
        self.assertEqual(res.x[0], fit_result.value(x1))
        self.assertEqual(res.x[1], fit_result.value(x2))
        self.assertEqual(res.fun, fit_result.objective_value)
        self.assertIsInstance(fit.minimizer.local_minimizer, BFGS)

        # Impose constrains
        np.random.seed(555)
        model = cos(14.5 * x1 - 0.3) + (x2 + 0.2) * x2 + (x1 + 0.2) * x1
        fit = Fit(model, minimizer=BasinHopping, constraints=[Eq(x1, x2)])
        fit_result = fit.execute()
        self.assertEqual(fit_result.value(x1), fit_result.value(x2))
        self.assertIsInstance(fit.minimizer.local_minimizer, SLSQP)

        # Impose bounds
        np.random.seed(555)
        x1.min = 0.0
        model = cos(14.5 * x1 - 0.3) + (x2 + 0.2) * x2 + (x1 + 0.2) * x1
        fit = Fit(model, minimizer=BasinHopping)
        fit_result = fit.execute()
        self.assertGreaterEqual(fit_result.value(x1), x1.min)
        self.assertIsInstance(fit.minimizer.local_minimizer, LBFGSB)