예제 #1
0
def fit_data(data, guess=10.0, use_err=False):

    x_data = data[:, 0]
    y_data = 1 - data[:, 1]
    if use_err:
        data_err = data[:, 2]

    x, y = sf.variables('x, y')
    pKa, n = sf.parameters('pKa, n')
    model = sf.Model({y: (10**(n * (pKa - x)) + 1)**-1.0})
    pKa.value = guess
    n.value = 1
    if use_err:
        fit = sf.Fit(model,
                     x=x_data,
                     y=y_data,
                     sigma_y=data_err,
                     minimizer=Powell,
                     absolute_sigma=True)
    else:
        fit = sf.Fit(model, x=x_data, y=y_data, minimizer=Powell)
    result = fit.execute()

    print("pKa.....................................", result.value(pKa), '+/-',
          result.stdev(pKa))
    print("n.......................................", result.value(n), '+/-',
          result.stdev(n))
    print("Regression coefficent:................", result.r_squared, '\n')

    x_out = np.arange(min(x_data), max(x_data), 10**-3.0)
    y_out = fit.model(x=x_out, **result.params)[0]

    return x_out, y_out, result.value(pKa), result.stdev(
        pKa), result.r_squared, result.value(n), result.stdev(n)
예제 #2
0
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)
def fit_plane(xyz):
    """
    Fit a plane to the point coordinates in xyz.

    Dev note: An alternative implementation is possible that omits the `f`
    variable, and thus has one fewer degree of freedom. This means the fit is
    easier and maybe more precise. This could be tested. The notebook
    req4.1_fit_plane.ipynb in the explore repository
    (https://github.com/sundial-pointcloud-geometry/explore) has some notes on
    this. The problem with those models where f is just zero and the named
    symfit model is created for one of x, y or z instead is that you have to
    divide by one of the a, b or c parameters respectively. If one of these
    turns out to be zero, symfit will not find a fit. A solution would be
    to actually create three models and try another if one of them fails to
    converge.
    """
    a, b, c, d = sf.parameters('a, b, c, d')
    x, y, z, f = sf.variables('x, y, z, f')
    plane_model = {f: x * a + y * b + z * c + d}

    plane_fit = sf.Fit(plane_model, x=xyz[0], y=xyz[1], z=xyz[2],
                       f=np.zeros_like(xyz[0]),
                       constraints=[sf.Equality(a**2 + b**2 + c**2, 1)])  # keep plane normal a unit vector

    plane_fit_result = plane_fit.execute()

    return plane_fit_result
def test_ODE_stdev():
    """
    Make sure that parameters from ODEModels get standard deviations.
    """
    x, v, t = sf.variables('x, v, t')
    k = sf.Parameter(name='k')

    k.min = 0
    k.value = 10
    a = -k * x

    model = sf.ODEModel({
        sf.D(v, t): a,
        sf.D(x, t): v,
    },
                        initial={
                            v: 0,
                            x: 1,
                            t: 0
                        })
    t_data = np.linspace(0, 10, 150)
    noise = np.random.normal(1, 0.05, t_data.shape)
    x_data = model(t=t_data, k=11).x * noise
    v_data = model(t=t_data, k=11).v * noise
    fit = sf.Fit(model, t=t_data, x=x_data, v=v_data)
    result = fit.execute()
    assert result.stdev(k) is not None
    assert np.isfinite(result.stdev(k))
예제 #5
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
예제 #6
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
예제 #7
0
파일: tikhonov.py 프로젝트: tBuLi/Tikhonov
    def generator_execute(self, *, k_start=0, **minimizer_kwargs):
        """
        Hand over the rains to :mod:`symfit`, and regularize that inversion. Use
        this in case of a very expensive calculation, so the results can e.g.
        be written to disk.

        :param k_start:
        :param minimizer_kwargs:
        :return: generator over the subfits per data set, starting from dataset
            ``k_start``.
        """
        # Select the symbols which depend on all the data sets
        global_symbols = []
        local_symbols = {}
        for s in self.model.ordered_symbols:
            if isinstance(s, sf.MatrixSymbol) and N_sets in s.shape:
                global_symbols.append(s)
                # Turn into a vector
                local_symbols[s] = s.func(*s.args[:-1], 1)

        local_model = self.localize_model(local_symbols)

        for set_index in range(k_start, self.shapes[N_sets]):
            # Select the right component
            data = self.data.copy()
            for s in global_symbols:
                if s in data:
                    # Select the component, but maintain shape
                    data[s] = data[s][:, set_index][..., None]

            fit = sf.Fit(local_model, **key2str(data), **self.fit_options)
            fit_result = fit.execute(**minimizer_kwargs)

            model_ans = fit.model(**key2str(fit.independent_data),
                                  **fit_result.params)
            fit_result.model_ans = model_ans

            yield fit_result
예제 #8
0
                       ['$B_0$']).setaxis('$B_0$', x_finer).set_units(
                           '$B_0$', d.get_units('$B_0$'))
 plot(d, label='data')
 plot(guess_nddata, ':', label='guess')
 model = s.Model({y_var: dVoigt})
 if interactive:
     guess = InteractiveGuess(model,
                              y=d.data.real,
                              B=d.getaxis('$B_0$'),
                              n_points=500)
     guess.execute()
     logger.info(strm(guess))
 y_var = s.Variable('y')
 logger.info(strm("about to run fit"))
 fit = s.Fit(
     model, d.getaxis('$B_0$'), d.data.real
 )  # really want to use minpack here, but gives "not proper array of floats
 fit_result = fit.execute()
 logger.info(strm("fit is done"))
 plt.figure()
 plt.title('data with fit')
 plot(d, '.', label='data')
 fit_nddata = nddata(
     fit.model(B=x_finer, **fit_result.params).y, [-1],
     ['$B_0$']).setaxis('$B_0$', x_finer)
 plot(fit_nddata, label='fit')
 logger.info(strm(fit_result))
 conc_list.append(concentration)
 R_list.append(fit_result.params['R'])
 sigma_list.append(fit_result.params['sigma'])
 A_list.append(fit_result.params['A'])
예제 #9
0
                                         t: 0.0,
                                         S: S_0,
                                         I: I_0,
                                         R: R_0,
                                         D: D_0
                                     })

    idx = sorted_data["country"] == country
    x = sorted_data[idx]["days_since_100_cases"].values
    y = sorted_data[idx]["cumulative_deaths"].values

    fit = sf.Fit(
        ode_model[country],
        t=x,
        S=None,
        I=None,
        R=None,
        D=y,
        minimizer=[DifferentialEvolution, BFGS],
    )
    fit_result[country] = fit.execute(DifferentialEvolution={
        "seed": 0,
        "tol": 1e-2,
        "maxiter": 5
    },
                                      BFGS={"tol": 1e-6})
    print(fit_result[country])

logger.info("Inferencing...")
n_days = 365  # Daily predictions
예제 #10
0
    def fit_lanes(self, points_left, points_right, fit_globally=False) -> dict:
        """
        Applies and returns a polynomial fit for given points along the left and right lane line.

        Both lanes are described by a second order polynomial x(y) = ay^2 + by + x0. In the `fit_globally` case,
        a and b are modeled as equal, making the lines perfectly parallel. Otherwise, each line is fit independent of
        the other. The parameters of the model are returned in a dictionary with keys 'al', 'bl', 'x0l' for the left
        lane parameters and 'ar', 'br', 'x0r' for the right lane.

        :param points_left: Two lists of the x and y positions along the left lane line.
        :param points_right: Two lists of the x and y positions along the right lane line.
        :param fit_globally: Set True to use the global, parallel line fit model. In practice this does not allays work.
        :return: fit_vals, a dictionary containing the fitting parameters for the left and right lane as above.
        """
        xl, yl = points_left
        xr, yr = points_right

        fit_vals = {}
        if fit_globally:
            # Define global model to fit
            x_left, y_left, x_right, y_right = symfit.variables(
                'x_left, y_left, x_right, y_right')
            a, b, x0_left, x0_right = symfit.parameters(
                'a, b, x0_left, x0_right')

            model = symfit.Model({
                x_left:
                a * y_left**2 + b * y_left + x0_left,
                x_right:
                a * y_right**2 + b * y_right + x0_right
            })

            # Apply fit
            xl, yl = points_left
            xr, yr = points_right
            fit = symfit.Fit(model,
                             x_left=xl,
                             y_left=yl,
                             x_right=xr,
                             y_right=yr)
            fit = fit.execute()
            fit_vals.update({
                'ar': fit.value(a),
                'al': fit.value(a),
                'bl': fit.value(b),
                'br': fit.value(b),
                'x0l': fit.value(x0_left),
                'x0r': fit.value(x0_right)
            })

        else:
            # Fit lines independently
            x, y = symfit.variables('x, y')
            a, b, x0 = symfit.parameters('a, b, x0')

            model = symfit.Model({
                x: a * y**2 + b * y + x0,
            })

            # Apply fit on left
            fit = symfit.Fit(model, x=xl, y=yl)
            fit = fit.execute()
            fit_vals.update({
                'al': fit.value(a),
                'bl': fit.value(b),
                'x0l': fit.value(x0)
            })

            # Apply fit on right
            fit = symfit.Fit(model, x=xr, y=yr)
            fit = fit.execute()
            fit_vals.update({
                'ar': fit.value(a),
                'br': fit.value(b),
                'x0r': fit.value(x0)
            })

        return fit_vals