Example #1
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)
Example #2
0
# 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()

# We calculate and print out the relative error on our estimate of Delta_T from using a Gaussian approximation.
Delta_T_poisson_sparse = xy_fit_poisson_sparse.parameter_values[0]
Delta_T_gaussian_sparse = xy_fit_gaussian_sparse.parameter_values[0]
relative_error_sparse = abs((Delta_T_gaussian_sparse - Delta_T_poisson_sparse) / Delta_T_poisson_sparse)
Example #3
0
# Read in the measurement data from a yaml file.
# For more information on reading/writing kafe2 objects from/to files see TODO
xy_data = XYContainer.from_file("data.yml")

# Create 2 XYFit objects with the same data but with different model functions
linear_fit = XYFit(xy_data=xy_data, model_function=linear_model)
exponential_fit = XYFit(xy_data=xy_data, model_function=exponential_model)

# Optional: Assign LaTeX strings to parameters and model functions.
linear_fit.assign_parameter_latex_names(a='a', b='b')
linear_fit.assign_model_function_latex_expression("{a}{x} + {b}")
exponential_fit.assign_parameter_latex_names(A0='A_0', x0='x_0')
exponential_fit.assign_model_function_latex_expression("{A0} e^{{{x}/{x0}}}")

# Perform the fits.
linear_fit.do_fit()
exponential_fit.do_fit()

# Optional: Print out a report on the result of each fit.
linear_fit.report()
exponential_fit.report()

# Optional: Create a plot of the fit results using Plot.
p = Plot(fit_objects=[linear_fit, exponential_fit], separate_figures=False)
p.plot(fit_info=True)

# Optional: Create a contour plot for the exponential fit to show the parameter correlations.
cpf = ContoursProfiler(exponential_fit)
cpf.plot_profiles_contours_matrix(show_grid_for='contours')

# Show the fit results.
Example #4
0
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
# Note how the actual chi2 profile differs from the parabolic approximation that you would expect with a linear fit.
profiler = ContoursProfiler(nonlinear_fit)
profiler.plot_profiles_contours_matrix(show_grid_for='all')
def expected_activity_per_day(x, Delta_t=5000, T_12_C14=5730):
    # activity = number of radioactive decays
    expected_initial_activity_per_day = expected_initial_num_c14_atoms * np.log(2) / (T_12_C14 * days_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)


# This is where we tell the fit to assume a poisson distribution for our data.
xy_fit = XYFit(
    xy_data=[years_of_death, measured_c14_activity],
    model_function=expected_activity_per_day,
    cost_function=XYCostFunction_NegLogLikelihood(data_point_distribution='poisson')
)

# 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
# Note that since for a Poisson distribution the data error is directly linked to the mean.
# Because of this fits can be performed without explicitly adding data errors.
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()
Example #6
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()
Example #7
0
# Constrain model parameters to measurements
fit.add_parameter_constraint(name='l', value=l, uncertainty=delta_l)
fit.add_parameter_constraint(name='r', value=r, uncertainty=delta_r)
fit.add_parameter_constraint(name='y_0',
                             value=y_0,
                             uncertainty=delta_y_0,
                             relative=True)

# Because the model function is oscillating the fit needs to be initialized with near guesses for unconstrained
# parameters in order to converge
g_initial = 9.81  # initial guess for g
c_initial = 0.01  # initial guess for c
fit.set_parameter_values(g=g_initial, c=c_initial)

# Optional: Set the initial values of the remaining parameters to correspond to their constraint values
# (this may help some minimization algorithms converge)
fit.set_parameter_values(y_0=y_0, l=l, r=r)

# Perform the fit
fit.do_fit()

# Optional: Print out a report on the fit results on the console.
fit.report()

# Optional: plot the fit results
plot = Plot(fit)
plot.plot(fit_info=True)

plt.show()
Example #8
0
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
main_fit = XYFit(xy_data=[U, I], model_function=I_U_model)

# declare errors on U
main_fit.add_error(axis='x', err_val=sigU)
# declare errors on I
main_fit.add_error(axis='y', err_val=sigI)
Example #9
0
from kafe2 import XYContainer, XYFit, Plot
import matplotlib.pyplot as plt

# Create an XYContainer object to hold the xy data for the fit.
xy_data = XYContainer(x_data=[1.0, 2.0, 3.0, 4.0], y_data=[2.3, 4.2, 7.5, 9.4])
# x_data and y_data are combined depending on their order.
# The above translates to the points (1.0, 2.3), (2.0, 4.2), and (4.0, 9.4).

# Important: Specify uncertainties for the data.
xy_data.add_error(axis='x', err_val=0.1)
xy_data.add_error(axis='y', err_val=0.4)

# Create an XYFit object from the xy data container.
# By default, a linear function f=a*x+b will be used as the model function.
line_fit = XYFit(xy_data=xy_data)

# Perform the fit: Find values for a and b that minimize the
#     difference between the model function and the data.
line_fit.do_fit()  # This will throw an exception if no errors were specified.

# Optional: Print out a report on the fit results on the console.
line_fit.report()

# Optional: Create a plot of the fit results using Plot.
plot = Plot(fit_objects=line_fit)  # Create a kafe2 plot object.
plot.plot()  # Do the plot.

# Show the fit result.
plt.show()