I'm trying to estimate two parameter values A
and B
of an ODE using curve_fit
, and then fit the solution to this ODE to my data set, plotting the results.
My code:
def model(I,t,A,B):
dIdt = A*(2000 - I) + B*(2000 - I)*(I/2000)
return dIdt
xData = # this is an np.array of my x values
yData = # this is an np.array of my y values
plt.plot(xData, yData, 'r.-', label='experimental-data') #This part of the code seems to work
initialGuess = [1.0,1.0]
popt, pcov = curve_fit(model, xData, yData, initialGuess) #This is where the error is
print(popt)
xFit = np.arange(0.0, 5.0, 0.01)
I0 = 0
t = np.linspace(0,60)
I = odeint(model,I0,t) #This is where i integrate the ODE to obtain I(t).
plt.plot(xFit, I(xFit, *popt), 'r', label='fit params: a=%5.3f, b=%5.3f' % tuple(popt))
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()
The error I am getting is
model() missing 1 required positional argument: 'B'.
I roughly understand what's going on: my model() function takes in 4 arguments at the beginning: I,t,A and B. However, somewhere along the line, the code only recognizes these first 3 arguments, and leaves out B. I am not sure how to fix this.
I have tried a few things:
curve_fit
line , and this gave me a new errorImproper input: N=3 must not exceed M=1
which makes me think, that the initialGuess entry isn't the problem.
Changed model
in the error line to model()
, which gave me the error
model() missing 4 required positional arguments: 'I', 't', 'A', and 'B'
Working off this, I changed model
to model(I,t,A,B)
, which ends up giving me name 'A' is not defined
And now I am lost.
All of these errors are happening in the same line, so I've tried changing things in there, but perhaps I am missing something else. Most of the online sources that touch on this error mention having to instantiate a class instance, but I'm unsure what this means in this context, I have not defined a class in the code.
I hope I've made my confusion clear, any guidance would be appreciated.
Perform curve_fit from scipy.optimize with model
function (see https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html):
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
def model(i, a, b):
return a * (2_000 - i)\
+ b * (2_000 - i)\
* (i / 2_000)
xData = np.array(range(10))
yData = model(xData, 1, 1)
initialGuess = [1.0, 1.0]
popt, pcov = curve_fit(f=model,
xdata=xData,
ydata=yData,
p0=initialGuess
)
print(popt)
Returns:
[1. 1.]
Next, Perform integration using odeint
from scipy.integrate
:
from scipy.integrate import odeint
xFit = np.arange(0.0, 5.0, 0.1)
I0 = 0
t = np.linspace(0, 60)
a, b = 1, 1
def model(i, t, a, b):
return a * (2_000 - i)\
+ b * (2_000 - i)\
* (i / 2_000)
I = odeint(model, I0, t, args=(a, b))
plt.plot(xFit, I[:, 0], 'b', label= 'fit params: a=%5.3f, b=%5.3f' % tuple(popt))
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()
Reveals the plot (see https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.odeint.html):