Reputation: 577
Im kind of a rookie in programming and especially in curve fitting. But I tried to curve fit a model into some measurements I did with Python and Numpy.
I succeeded in plotting a "fitted" curve into one set of data. Well, it seemed like it did. It turned out that the function just uses the initial guesses and does not try to actually fit a curve. I tested this by using the same initial guesses with different data sets. This was the result:
and the output of fitParams
are fitCovariances
(which seems to be quite weird values):
[ 540. 2.5 2. ]
[[ inf inf inf]
[ inf inf inf]
[ inf inf inf]]
The output of def fitFunc()
are just the initial guess values repeatedly.
I first tried my script for the 5th data set, which seemed some what alright. But you can see that every "fitted curve" is exactly the same and it just uses the initial guess.
This is the script:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import scipy
import math
import csv
import matplotlib as mpl
mpl.rcParams['text.usetex']=True
mpl.rcParams['text.latex.unicode']=True
#model
def fitFunc(P_max, x, x_0, w_z):
print P_max
print x_0
print w_z
return 0.5 * P_max * (1 - scipy.special.erf((scipy.sqrt(2) * (x - x_0)) / w_z))
fig = plt.figure()
#for-loop to read and curve fit for all data sets
for n in range (1,7):
x_model = np.linspace(-1,6,5000)
y_model = []
x = []
P = []
name = 'data_' + str(n)
with open(name + '.csv', 'rb') as f:
data = csv.reader(f, delimiter = ';')
for row in data:
x.append(float(row[1]))
P.append(float(row[2]))
fitParams, fitCovariances = curve_fit(fitFunc, np.array(x), np.array(P), [540, 2.5, 2])
print fitParams
print fitCovariances
for i in range(0, len(x_model)):
y_model.append(fitFunc(fitParams[0], x_model[i], fitParams[1], fitParams[2]))
ax = fig.add_subplot(2,3,n, axisbg='white')
ax.scatter(x,P)
ax.plot(x_model,y_model)
ax.set_xlim([0, 6])
ax.set_ylim([0, 600])
ax.set_xlabel(r'\Delta x')
ax.set_ylabel(r'P (\mu W)')
plt.tight_layout()
plt.show()
I can't really find what Im doing wrong. I hope you guys can help me. Thanks :)
Note: you can download the data files here to try the script with the same data.
Upvotes: 0
Views: 4477
Reputation: 35109
Your only problem is the definition of fitFunc
. From help(curve_fit)
:
Parameters ---------- f : callable The model function, f(x, ...). It must take the independent variable as the first argument and the parameters to fit as separate remaining arguments.
This implies that you have to move your x
input to become the first parameter of your function. This only affects 2 lines: your definition of fitFunc
,
#def fitFunc(P_max, x, x_0, w_z): #original
def fitFunc(x, P_max, x_0, w_z):
print(P_max)
print(x_0)
print(w_z)
return 0.5 * P_max * (1 - scipy.special.erf((scipy.sqrt(2) * (x - x_0)) / w_z))
and the explicit call to fitFunc
when plotting:
for i in range(0, len(x_model)):
y_model.append(fitFunc(x_model[i], fitParams[0], fitParams[1], fitParams[2]))
I think both you and scipy did pretty well :)
Efficiency note:
I don't see a reason why your fitFunc
wouldn't work with vector-valued x
input (and it does). Which means you can spare the loop over i
when plotting the fitted model, you can just say
y_model = fitFunc(x_model, fitParams[0], fitParams[1], fitParams[2])
Upvotes: 4