I am trying to write a curve fitting function which returns the optimal parameters a, b and c, here is a simplified example:
import numpy
import scipy
from scipy.optimize import curve_fit
def f(x, a, b, c):
return x * 2*a + 4*b - 5*c
xdata = numpy.array([1,3,6,8,10])
ydata = numpy.array([ 0.91589774, 4.91589774, 10.91589774, 14.91589774, 18.91589774])
popt, pcov = scipy.optimize.curve_fit(f, xdata, ydata)
This works fine, but I want to give the user a chance to supply some (or none) of the parameters a, b or c, in which case they should be treated as constants and not estimated. How can I write f so that it fits only the parameters not supplied by the user?
Basically, I need to define f dynamically with the correct arguments. For instance if a was known by the user, f becomes:
def f(x, b, c):
a = global_version_of_a
return x * 2*a + 4*b - 5*c
Taking a page from the collections.namedtuple playbook, you can use exec to “dynamically” define
func:Note the line
You can pass whatever parameters you like to make_model. The parameters you pass to
make_modelbecome fixed constants infunc. Whatever parameters remain become free parameters thatoptimize.curve_fitwill try to fit.For example, above, a=3 and b=1 become fixed constants in
func. Actually, theexecstatement places them infunc‘s global namespace.funcis thus defined as a function ofxand the single parameterc. Note the return value forpoptis an array of length 1 corresponding to the remaining free parameterc.Regarding
textwrap.dedent: In the above example, the call totextwrap.dedentis unnecessary. But in a “real-life” script, wherefuncstris defined inside a function or at a deeper indentation level,textwrap.dedentallows you to writeinstead of the visually unappealing
Some people prefer
but I find quoting each line separately and adding explicit EOL characters a bit onerous. It does save you a function call however.