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()
Esempio n. 2
0
    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()

# 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]
Esempio n. 3
0
def damped_harmonic_oscillator(x, y_0, l, r, g, c):
    l_total = l + r  # effective length of the pendulum = length of the string + radius of the steel ball
    omega_0 = np.sqrt(g / l_total)  # phase speed of an undamped pendulum
    omega_d = np.sqrt(omega_0**2 - c**2)  # phase speed of a damped pendulum
    return y_0 * np.exp(
        -c * x) * (np.cos(omega_d * x) + c / omega_d * np.sin(omega_d * x))


# Load data from yaml, contains data and errors
data = XYContainer.from_file(filename='data.yml')

# Create fit object from data and model function
fit = XYFit(xy_data=data, model_function=damped_harmonic_oscillator)

# 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)