Check the first scipy documentation docs.scipy.org/doc/scipy-0.13.0/reference/generated/scipy.optimize.curve_fit.html:
scipy.optimize.curve_fit
scipy.optimize.curve_fit(f, xdata, ydata, p0=None, sigma=None, **kw)
Use non-linear least squares to fit a function, f, to data.
Assumes ydata = f(xdata, *params) + eps
Explaining the idea
The function to be fitted should take only scalars (not: *p0
).
I want to remind you that you hand over the initialization parameters x0
, y0
, sigma
to the function gauss
during the call of curve_fit
.
You call the initialization p0 = [x0, y0, sigma]
.
The function gauss
returns the value y = y0 * np.exp(-((x - x0) / sigma)**2)
.
Therefore the input values need to be x
, x0
, y0
, sigma
.
The first parameter x
is the data you know together with the result of the function y
. The later three parameters will be fitted - you hand over them as initialization parameters.
Working example
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
# Create data:
x0, sigma = 0, 0.1
y, xe = np.histogram(np.random.normal(x0, sigma, 1000))
x = .5 * (xe[:-1] + xe[1:])
# Function to be fitted
def gauss(x, x0, y0, sigma):
p = [x0, y0, sigma]
return p[1]* np.exp(-((x-p[0])/p[2])**2)
# Initialization parameters
p0 = [1., 1., 1.]
# Fit the data with the function
fit, tmp = curve_fit(gauss, x, y, p0=p0)
# Plot the results
plt.title('Fit parameters:\n x0=%.2e y0=%.2e sigma=%.2e' % (fit[0], fit[1], fit[2]))
# Data
plt.plot(x, y, 'r--')
# Fitted function
x_fine = np.linspace(xe[0], xe[-1], 100)
plt.plot(x_fine, gauss(x_fine, fit[0], fit[1], fit[2]), 'b-')
plt.savefig('Gaussian_fit.png')
plt.show()