def test_unequal_data(self): """ Test to make sure finite differences work with data of unequal length. """ x_1, x_2, y_1, y_2 = sf.variables('x_1, x_2, y_1, y_2') y0, a_1, a_2, b_1, b_2 = sf.parameters('y0, a_1, a_2, b_1, b_2') model = sf.Model({ y_1: a_1 * x_1**2 + b_1 * x_1 + y0, y_2: a_2 * x_2**2 + b_2 * x_2 + y0, }) # Generate data from this model xdata1 = np.linspace(0, 10) xdata2 = xdata1[::2] # Only every other point. exact = model.eval_jacobian(x_1=xdata1, x_2=xdata2, a_1=101.3, b_1=0.5, a_2=56.3, b_2=1.1111, y0=10.8) approx = model.finite_difference(x_1=xdata1, x_2=xdata2, a_1=101.3, b_1=0.5, a_2=56.3, b_2=1.1111, y0=10.8) self._assert_equal(exact, approx, rtol=1e-4) model = sf.Model({ y_1: a_1 * x_1**2 + b_1 * x_1, y_2: a_2 * x_2**2 + b_2 * x_2, }) exact = model.eval_jacobian(x_1=xdata1, x_2=xdata2, a_1=101.3, b_1=0.5, a_2=56.3, b_2=1.1111) approx = model.finite_difference(x_1=xdata1, x_2=xdata2, a_1=101.3, b_1=0.5, a_2=56.3, b_2=1.1111) self._assert_equal(exact, approx, rtol=1e-4) model = sf.Model({ y_1: a_1 * x_1**2 + b_1 * x_1, }) exact = model.eval_jacobian(x_1=xdata1, a_1=101.3, b_1=0.5) approx = model.finite_difference(x_1=xdata1, a_1=101.3, b_1=0.5) self._assert_equal(exact, approx, rtol=1e-4)
def test_unequal_data(): """ Test to make sure finite differences work with data of unequal length. """ x_1, x_2, y_1, y_2 = sf.variables('x_1, x_2, y_1, y_2') y0, a_1, a_2, b_1, b_2 = sf.parameters('y0, a_1, a_2, b_1, b_2') model = sf.Model({ y_1: a_1 * x_1**2 + b_1 * x_1 + y0, y_2: a_2 * x_2**2 + b_2 * x_2 + y0, }) # Generate data from this model xdata1 = np.linspace(0, 10) xdata2 = xdata1[::2] # Only every other point. exact = model.eval_jacobian(x_1=xdata1, x_2=xdata2, a_1=101.3, b_1=0.5, a_2=56.3, b_2=1.1111, y0=10.8) approx = model.finite_difference(x_1=xdata1, x_2=xdata2, a_1=101.3, b_1=0.5, a_2=56.3, b_2=1.1111, y0=10.8) # First axis is the number of components assert len(exact) == 2 assert len(approx) == 2 # Second axis is the number of parameters, same for all components for exact_comp, approx_comp, xdata in zip(exact, approx, [xdata1, xdata2]): assert len(exact_comp) == len(model.params) assert len(approx_comp) == len(model.params) for exact_elem, approx_elem in zip(exact_comp, approx_comp): assert exact_elem.shape == xdata.shape assert approx_elem.shape == xdata.shape _assert_equal(exact, approx, rel=1e-4) model = sf.Model({ y_1: a_1 * x_1**2 + b_1 * x_1, y_2: a_2 * x_2**2 + b_2 * x_2, }) exact = model.eval_jacobian(x_1=xdata1, x_2=xdata2, a_1=101.3, b_1=0.5, a_2=56.3, b_2=1.1111) approx = model.finite_difference(x_1=xdata1, x_2=xdata2, a_1=101.3, b_1=0.5, a_2=56.3, b_2=1.1111) _assert_equal(exact, approx, rel=1e-4) model = sf.Model({ y_1: a_1 * x_1**2 + b_1 * x_1, }) exact = model.eval_jacobian(x_1=xdata1, a_1=101.3, b_1=0.5) approx = model.finite_difference(x_1=xdata1, a_1=101.3, b_1=0.5) _assert_equal(exact, approx, rel=1e-4)
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)
def test_multi_indep(): ''' Tests the case with multiple components, multiple parameters and multiple independent variables ''' w, x, y, z = sf.variables('w, x, y, z') a, b, c = sf.parameters('a, b, c') model = sf.Model({ y: 3 * a * x**2 + b * x * w - c, z: sf.exp(a * x - b) + c * w }) x_data = np.arange(10) / 10 w_data = np.arange(10) exact = model.eval_jacobian(x=x_data, w=w_data, a=3.5, b=2, c=5) approx = model.finite_difference(x=x_data, w=w_data, a=3.5, b=2, c=5) _assert_equal(exact, approx) exact = model.eval_jacobian(x=0.3, w=w_data, a=3.5, b=2, c=5) approx = model.finite_difference(x=0.3, w=w_data, a=3.5, b=2, c=5) _assert_equal(exact, approx) exact = model.eval_jacobian(x=0.3, w=5, a=3.5, b=2, c=5) approx = model.finite_difference(x=0.3, w=5, a=3.5, b=2, c=5) _assert_equal(exact, approx)
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 laplace_dataset(): """Sample pytest fixture. See more at: http://doc.pytest.org/en/latest/fixture.html """ t, f, s, F = sf.variables('t, f, s, F') model = sf.Model({f: t * sf.exp(-t)}) laplace_model = sf.Model( {F: sf.laplace_transform(model[f], t, s, noconds=True)}) epsilon = 0.01 # 1 percent noise s_data = np.linspace(0, 10, 101)[1:] F_data = laplace_model(s=s_data).F F_sigma = epsilon * F_data np.random.seed(42) F_data = np.random.normal(F_data, F_sigma) # Reshape to matrices F_data = F_data[:, None] F_sigma = F_sigma[:, None] M_mat = 1 / (s_data[None, :] + s_data[:, None]) delta = np.atleast_2d(np.linalg.norm(F_sigma)**2) return {M_y: M_mat, y: F_data, y_stdev: F_sigma, d: delta}
def test_multi_multi_model(): '''Tests the case with multiple components and multiple parameters''' x, y, z = sf.variables('x, y, z') a, b, c = sf.parameters('a, b, c') model = sf.Model({y: 3 * a * x**2 + b * x - c, z: sf.exp(a * x - b) * c}) x_data = np.arange(10) exact = model.eval_jacobian(x=x_data, a=3.5, b=2, c=5) approx = model.finite_difference(x=x_data, a=3.5, b=2, c=5) _assert_equal(exact, approx, rel=1e-3) exact = model.eval_jacobian(x=3, a=3.5, b=2, c=5) approx = model.finite_difference(x=3, a=3.5, b=2, c=5) _assert_equal(exact, approx, rel=1e-3)
def test_multi_1_model(): '''Tests the case with multiple components and one parameter''' x, y, z = sf.variables('x, y, z') a, = sf.parameters('a') model = sf.Model({y: 3 * a * x**2, z: sf.exp(a * x)}) x_data = np.arange(10) exact = model.eval_jacobian(x=x_data, a=3.5) approx = model.finite_difference(x=x_data, a=3.5) _assert_equal(exact, approx) exact = model.eval_jacobian(x=3, a=3.5) approx = model.finite_difference(x=3, a=3.5) _assert_equal(exact, approx)
def test_1_multi_model(): '''Tests the case with 1 component and multiple parameters''' x, y = sf.variables('x, y') a, b = sf.parameters('a, b') model = sf.Model({y: 3 * a * x**2 - sf.exp(b) * x}) x_data = np.arange(10) exact = model.eval_jacobian(x=x_data, a=3.5, b=2) approx = model.finite_difference(x=x_data, a=3.5, b=2) _assert_equal(exact, approx) exact = model.eval_jacobian(x=3, a=3.5, b=2) approx = model.finite_difference(x=3, a=3.5, b=2) _assert_equal(exact, approx)
def test_1_1_model(): '''Tests the case with 1 component and 1 parameter''' x, y = sf.variables('x, y') a = sf.Parameter(name='a') model = sf.Model({y: 3 * a * x**2}) x_data = np.arange(10) exact = model.eval_jacobian(x=x_data, a=3.5) approx = model.finite_difference(x=x_data, a=3.5) _assert_equal(exact, approx) exact = model.eval_jacobian(x=3, a=3.5) approx = model.finite_difference(x=3, a=3.5) _assert_equal(exact, approx)
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
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
B_center: B_center.value, R: R.value, A: A.value, sigma: sigma.value }), modules=[{ 'ImmutableMatrix': ndarray }, 'numpy', 'scipy']) x_finer = r_[d.getaxis('$B_0$')[0]:d.getaxis('$B_0$')[-1]:500j] result = model_lambda(x_finer) guess_nddata = nddata(result, [-1], ['$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()
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