Exemple #1
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))
Exemple #2
0
 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
Exemple #3
0
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)
Exemple #4
0
 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
Exemple #5
0
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
Exemple #6
0
 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)
Exemple #7
0
    # 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()
Exemple #8
0

# -- 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',
Exemple #9
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
Exemple #10
0
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()
Exemple #12
0
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