def test_warning_no_fit_performed(self): _fit = XYFit(xy_data=self._ref_data) _fit.add_error('y', 0.1) _plot = Plot(fit_objects=_fit) with self.assertWarns(Warning) as w: _plot.plot() self.assertIn("Did you forget to run fit.do_fit()?", str(w.warning))
def _get_xy_fit(xy_data, minimizer, err_x=0.01, err_y=0.01): _xy_fit = XYFit(xy_data=xy_data, model_function=quadratic_model, cost_function='chi2', minimizer=minimizer) _xy_fit.add_error('x', err_x) _xy_fit.add_error('y', err_y) return _xy_fit
class TestXYPlot(unittest.TestCase): def setUp(self): self._ref_data = [[1, 2, 3], [1, 2, 3]] self._ref_dataset_label = 'My Dataset' self._ref_x_label = '$U$ [V]' self._ref_y_label = '$I$ [A]' self._ref_model_label = 'My Model' self._ref_error_label = self._ref_model_label + r' $\pm 1\sigma$' self.fit = XYFit(xy_data=self._ref_data) self.fit.add_error('y', 0.1) self.fit.do_fit() self.fit.data_container.label = self._ref_dataset_label self.fit.data_container.axis_labels = (self._ref_x_label, self._ref_y_label) self.fit.model_label = self._ref_model_label self.plot = Plot(self.fit) def test_labels_after_plotting(self): self.plot.plot() self.assertEqual(self.plot.axes[0]['main'].get_xlabel(), self._ref_x_label) self.assertEqual(self.plot.axes[0]['main'].get_ylabel(), self._ref_y_label) _, labels = self.plot.axes[0]['main'].get_legend_handles_labels() self.assertIn(self._ref_dataset_label, labels) self.assertIn(self._ref_model_label, labels) self.assertIn(self._ref_error_label, labels) def test_remove_labels(self): self.fit.data_container.label = '__del__' self.fit.data_container.axis_labels = ('__del__', '__del__') self.fit.model_label = '__del__' self.plot.plot() _, labels = self.plot.axes[0]['main'].get_legend_handles_labels() self.assertEqual(self.plot.axes[0]['main'].get_xlabel(), '') self.assertEqual(self.plot.axes[0]['main'].get_ylabel(), '') self.assertTrue(len(labels) == 0) def test_warning_no_fit_performed(self): _fit = XYFit(xy_data=self._ref_data) _fit.add_error('y', 0.1) _plot = Plot(fit_objects=_fit) with self.assertWarns(Warning) as w: _plot.plot() self.assertIn("Did you forget to run fit.do_fit()?", str(w.warning)) def test_plot_with_asymmetric_errors(self): self.plot.plot(asymmetric_parameter_errors=True)
def _get_xy_fit(self, xy_data): _err_x = dict(axis="x", err_val=0.01, name="x") if self._x_error is not None else None _err_y = dict(axis="y", err_val=0.1, relative=True, reference="model", name="y") \ if self._relative_model_error else dict(axis="y", err_val=0.01, name="y") if self._x_error is None: _xy_fit = XYFit(xy_data=xy_data, model_function=quadratic_model, cost_function='chi2', minimizer=self._minimizer) else: _xy_fit = XYFit(xy_data=xy_data, model_function=quadratic_model, cost_function='chi2', minimizer=self._minimizer, dynamic_error_algorithm=self._x_error) if _err_x is not None: _xy_fit.add_error(**_err_x) _xy_fit.add_error(**_err_y) return _xy_fit
def construct_multi_fit(shared_x_error): fit_1 = XYFit(xy_data=[U, T], model_function=empirical_T_U_model) fit_1.add_error(axis='y', err_val=sigT) # declare errors on T fit_2 = XYFit(xy_data=[U, I], model_function=I_U_model) fit_2.add_error(axis='y', err_val=sigI) # declare errors on I multi_fit = MultiFit(fit_list=[fit_1, fit_2], minimizer='iminuit') if shared_x_error: multi_fit.add_error(axis='x', err_val=sigU, fits='all') else: fit_1.add_error(axis='x', err_val=sigU) fit_2.add_error(axis='x', err_val=sigU) return multi_fit
def _get_multifit( self, hist_fit=True, xy_fit_1=True, indexed_fit=True, xy_fit_2=True, reverse=False): _fits = [] if hist_fit: _hist_container = HistContainer( n_bins=10, bin_range=(-5, 5), fill_data=self._hist_data) _hist_fit = HistFit(_hist_container) _fits.append(_hist_fit) if xy_fit_1: _xy_fit_1 = XYFit(xy_data=[self._x_data, self._y_data_1]) _xy_fit_1.add_error("y", 1.0) _fits.append(_xy_fit_1) if indexed_fit: _indexed_fit = IndexedFit( self._indexed_data, TestSharedErrorLogic.indexed_model_function) _indexed_fit.add_error(1.0) _fits.append(_indexed_fit) if xy_fit_2: _xy_fit_2 = XYFit(xy_data=[self._x_data, self._y_data_2]) _xy_fit_2.add_error("y", 1.0) _fits.append(_xy_fit_2) if reverse: _fits = reversed(_fits) return MultiFit(_fits)
# activity = number of radioactive decays expected_initial_activity_per_day = expected_initial_num_c14_atoms * np.log(2) / (T_12_C14 * two_min_per_year) total_years_since_death = Delta_t + current_year - x return expected_initial_activity_per_day * np.exp(-np.log(2) * total_years_since_death / T_12_C14) # We define a fit as per normal, with xy data and a model function. # Since no cost function is provided it will use the default (chi2 -> Gaussian data errors). xy_fit_gaussian_sparse = XYFit( xy_data=[years_of_death, measured_c14_activity_sparse], model_function=expected_activity_per_two_min ) # We use the Gaussian approximation of the Poisson distribution sqrt(y) for our y data error # Because we only have about 10 events per measurement this approximation will be bad. xy_fit_gaussian_sparse.add_error(axis='y', err_val=np.sqrt(measured_c14_activity_sparse)) # The half life of carbon-14 is only known with a precision of +-40 years xy_fit_gaussian_sparse.add_parameter_constraint(name='T_12_C14', value=5730, uncertainty=40) # Perform the fit xy_fit_gaussian_sparse.do_fit() # We create another fit, this time with a Poisson distribution, to compare the Gaussian approximation against. xy_fit_poisson_sparse = XYFit( xy_data=[years_of_death, measured_c14_activity_sparse], model_function=expected_activity_per_two_min, cost_function=XYCostFunction_NegLogLikelihood(data_point_distribution='poisson') ) xy_fit_poisson_sparse.add_parameter_constraint(name='T_12_C14', value=5730, uncertainty=40) xy_fit_poisson_sparse.do_fit()
# -- Next, read the data from an external file # load all data into numpy arrays U, I, T = np.loadtxt('OhmsLawExperiment.dat', unpack=True) # data sigU, sigI, sigT = 0.1, 0.1, 0.1 # uncertainties T0 = 273.15 # 0 degrees C as absolute Temperature (in Kelvin) T -= T0 # Measurements are in Kelvin, convert to °C # -- Finally, go through the fitting procedure # Step 1: construct the singular fit objects fit_1 = XYFit(xy_data=[U, T], model_function=empirical_T_U_model) fit_1.add_error(axis='y', err_val=sigT) # declare errors on T fit_2 = XYFit(xy_data=[U, I], model_function=I_U_model) fit_2.add_error(axis='y', err_val=sigI) # declare errors on I # Step 2: construct a MultiFit object multi_fit = MultiFit(fit_list=[fit_1, fit_2], minimizer='iminuit') # Step 3: Add a shared error error for the x axis. multi_fit.add_error(axis='x', err_val=sigU, fits='all') # (Optional): assign names for models and parameters multi_fit.assign_parameter_latex_names(x='U', p2='p_2', p1='p_1', p0='p_0',
derivative of the model function it will vary depending on our choice of model parameters. This distorts our likelihood function - the minimum of a chi2 cost function will no longer be shaped like a parabola (with a model parameter on the x axis and chi2 on the y axis). The effects of this deformation are explained in the non_linear_fit.py example. """ import matplotlib.pyplot as plt from kafe2 import XYContainer, XYFit, Plot from kafe2.fit.tools import ContoursProfiler # Construct a fit with data loaded from a yaml file. The model function is the default of f(x) = a * x + b nonlinear_fit = XYFit(xy_data=XYContainer.from_file('x_errors.yml')) # The x errors are much bigger than the y errors. This will cause a distortion of the likelihood function. nonlinear_fit.add_error('x', 1.0) nonlinear_fit.add_error('y', 0.1) # Perform the fit. nonlinear_fit.do_fit() # Optional: Print out a report on the fit results on the console. # Note the asymmetric_parameter_errors flag nonlinear_fit.report(asymmetric_parameter_errors=True) # Optional: Create a plot of the fit results using Plot. # Note the asymmetric_parameter_errors flag plot = Plot(nonlinear_fit) plot.plot(fit_info=True, asymmetric_parameter_errors=True) # Optional: Calculate a detailed representation of the profile likelihood
def exponential(x, A0=1, tau=1): return A0 * np.exp(-x/tau) # define the data as simple Python lists x = [8.018943e-01, 1.839664e+00, 1.941974e+00, 1.276013e+00, 2.839654e+00, 3.488302e+00, 3.775855e+00, 4.555187e+00, 4.477186e+00, 5.376026e+00] xerr = 3.000000e-01 y = [2.650644e-01, 1.472682e-01, 8.077234e-02, 1.850181e-01, 5.326301e-02, 1.984233e-02, 1.866309e-02, 1.230001e-02, 9.694612e-03, 2.412357e-03] yerr = [1.060258e-01, 5.890727e-02, 3.230893e-02, 7.400725e-02, 2.130520e-02, 7.936930e-03, 7.465238e-03, 4.920005e-03, 3.877845e-03, 9.649427e-04] # create a fit object from the data arrays fit = XYFit(xy_data=[x, y], model_function=exponential) fit.add_error(axis='x', err_val=xerr) # add the x-error to the fit fit.add_error(axis='y', err_val=yerr) # add the y-errors to the fit fit.do_fit() # perform the fit fit.report(asymmetric_parameter_errors=True) # print a report with asymmetric uncertainties # Optional: create a plot plot = Plot(fit) plot.plot(asymmetric_parameter_errors=True, ratio=True) # add the ratio data/function and asymmetric errors # Optional: create the contours profiler cpf = ContoursProfiler(fit) cpf.plot_profiles_contours_matrix() # plot the contour profile matrix for all parameters plt.show()
total_years_since_death = Delta_t + current_year - x return expected_initial_activity_per_day * np.exp( -np.log(2) * total_years_since_death / T_12_C14) ######################################### # This is where things start to change. # ######################################### # We define a fit as per normal, with xy data and a model function. # Since no cost function is provided it will use the default (chi2 -> Gaussian data errors). xy_fit = XYFit(xy_data=[years_of_death, measured_c14_activity], model_function=expected_activity_per_day) # We use the Gaussian approximation of the Poisson distribution sqrt(y) for our y data error xy_fit.add_error(axis='y', err_val=np.sqrt(measured_c14_activity)) # The half life of carbon-14 is only known with a precision of +-40 years xy_fit.add_parameter_constraint(name='T_12_C14', value=5730, uncertainty=40) # Perform the fit xy_fit.do_fit() # Optional: print out a report on the fit results on the console xy_fit.report() # Optional: create a plot of the fit results using Plot xy_plot = Plot(xy_fit) xy_plot.plot(fit_info=True) plt.show()
T0 = 273.15 # 0 degrees C as absolute Temperature (in Kelvin) T -= T0 # Measurements are in Kelvin, convert to °C # -- Finally, go through the fitting procedure # Step 1: perform an "auxiliary" fit to the T(U) data auxiliary_fit = XYFit(xy_data=[U, T], model_function=empirical_T_U_model) # (Optional): Assign names for models and parameters auxiliary_fit.assign_parameter_latex_names(x='U', p2='p_2', p1='p_1', p0='p_0') auxiliary_fit.assign_model_function_expression('{1}*{x}^2 + {2}*{x} + {3}') auxiliary_fit.assign_model_function_latex_expression( r'{1}\,{x}^2 + {2}\,{x} + {3}') # declare errors on U auxiliary_fit.add_error(axis='x', err_val=sigU) # declare errors on T auxiliary_fit.add_error(axis='y', err_val=sigT) # perform the auxiliary fit auxiliary_fit.do_fit() # (Optional) print the results auxiliary_fit.report() # (Optional) plot the results auxiliary_plot = Plot(auxiliary_fit) auxiliary_plot.plot(fit_info=True) # Step 2: perform the main fit