First, we need to import the necessary packages and prepare to make plots.
import numpy as np
from matplotlib import pyplot as plt
import fit
%matplotlib tk
Before doing a fit, you need to make a guess as to the functional form of the data. Best bet is to make a plot, first. Let's load some data and make a plot.
x1, y1 = np.loadtxt('fittable1.csv', delimiter=',', unpack=True)
plt.plot(x1, y1)
The fit
module provides a class, Fit
, whose general purpose is
obvious. A Fit
has three required positional arguments:
x_data
: an np.ndarray
containing the x-data.y_data
: an np.ndarray
containing the y-data.model
: a function guess as to the form of the data. The function
should return an np.ndarray
containing y-values, and it should take
the following inputs.
np.ndarray
of x-valuesfloat
variables are necessary to fit the curve.The particular data we have look linear. A model function fit.linear
is already defined, so we'll use that.
f1 = fit.Fit(x1, y1, fit.linear)
We can print the fit parameters using
Fit.print_results(sig_figs=False)
if sig_figs
is true, only significant digits will be printed.
Otherwise, all digits will be printed.
We can easily get a plot using
Fit.show_plot(new_fig=True)
If new_fig
is true, a new figure will be created. Otherwise, a line
representing the fit will be added to the active axes in pyplot
.
f1.print_results()
f1.show_plot(False)
If we want to use the values of the fit for calculations, we can
access them using one of three attributes, all of which are
dictionary-like objects in which the keys are the variable
names in the model
function.
Fit.fit_values
Fit.fit_errors
Fit.best_fit_parameters
In the first, the values of the dictionary are the fit parameters:
f1.fit_values
In the second, the values of the dictionary are the errors:
f1.fit_errors
In the third, the values of the dictionary are tuples of
(value_of_fit_parameter, error)
.
f1.best_fit_parameters
Divide the slope by the intercept without typing (or copying and pasting) any numbers.
# CISV
f1.fit_values['m']/f1.fit_values['b']
Load some more data and make a plot.
x2, y2 = np.loadtxt('fittable2.csv', delimiter=',', unpack=True)
plt.plot(x2, y2)
This looks quadratic. fit
provides no model function, so we have to
define one.
# CISV
def quadratic(x, a, b, c):
return a*x**2 + b*x + c
Now create the fit, print the parameters, and show the results on the plot.
f2 = fit.Fit(x2, y2, quadratic)
f2.print_results()
f2.show_plot()
This looks pretty good.
Here are the results with significant digits.
f2.print_results(sig_figs=True)
x3, y3 = np.loadtxt('fittable3.csv', delimiter=',', unpack=True)
plt.plot(x3, y3)
# CISV
def gaussian(x, a, b, c):
return a*np.exp( -(x-b)**2/(2*c**2) )
# CISV
f3 = fit.Fit(x3, y3, gaussian)
f3.print_results()
f3.show_plot()
f3.print_results(True)
x4, y4 = np.loadtxt('fittable4.csv', delimiter=',', unpack=True)
plt.plot(x4, y4)
# CISV
def decaying_sine(x, A, b, k, ph0):
return A * np.exp(-b*x) * np.sin(k*x + ph0)
# CISV
f4 = fit.Fit(x4, y4, decaying_sine)
f4.print_results()
f4.show_plot(False)
f4.print_results(True)
x5, y5 = np.loadtxt('fittable5.csv', delimiter=',', unpack=True)
plt.plot(x5, y5)
# CISV
def slit(x, I0, a, d, λ, L):
arg1 = np.pi*a*x/(λ*L)
arg2 = np.pi*d*x/(λ*L)
return I0 * (np.sin(arg1)/arg1)**2 * np.cos(arg2)**2
# CISV
f5 = fit.Fit(x5, y5, slit)
f5.show_plot(False)
f5.print_results()
That's no good! We have to supply some guesses for the parameters.
We create a list with guesses for all parameters, in the order
of those in the model
function signature.
guesses = [I0, a, d, λ, L]
CISV (code line only)
These get supplied to the initial_parameters
argument.
# CISV
guesses = [1.2, 0.04e-3, 0.25e-3, 400e-9, 1.0]
f5b = fit.Fit(x5, y5, slit, initial_parameters=guesses)
f5b.print_results()
f5b.show_plot()
f5b.print_results(True)
This is much better, but some of the values are nonsense---so much so that uncertainties cannot even be estimated for some parameters. We can apply bounds to the guesses by specifying tuples of three floats, instead of single floats. Assume that the wavelength is the only parameter which is not fairly well known.
# CISV
guesses = [(1.20, 1.19, 1.21),
(0.040e-3, 0.039e-3, 0.041e-3),
(0.25e-3, 0.24e-3, 0.26e-3),
650e-9,
(1.00, 0.99, 1.11)]
f5c = fit.Fit(x5, y5, slit, initial_parameters=guesses)
f5c.print_results()
f5c.show_plot()
f5c.print_results(True)