1

Having two datasets which apparently follow an exponential trend, I've fitted a curve into them by means of scipy.optimize.curve_fit(). The x dataset contains no zero and is bounded 0<x<=100, while the y dataset is bounded 0<=y<=1. This is the fitted equation:

def func(x, a, c, d):
    return a * numpy.exp(-c*x)+d

and I've called curve_fit like this:

popt, pcov, infodict, errmsg, ier = curve_fit(func, x1, y1, p0 = (1, 1e-6, 1), full_output=True)

where x1 and y1 are my two datasets. Now, based on this answer, I wanted to perform the Bootstrap Method to make sure I obtained the standard errors on fitted parameters, which I will use to quantify the goodness-of-fit.

Based on the code provided in this answer, given that apparently SciPy does not include anything of the kind, I've made a call to the Bootstrap Method like this:

pfit, perr = fit_bootstrap(pstart, xx, yy, func)

where pfit are the new fitting parameters (to be compared with those given by curve_fit), and perr are the standard errors I am after. p-start in my case is (1, 1e-6,1), xx are the x values used to plot the functions, and yy are the y values coming out of the fitted equation applied to the xx values. Lastly, the fitted function is func=a*numpy.exp(-c*x)+d.

The call raises an error: TypeError: func() takes exactly 4 arguments (2 given). I understand there is a mismatch in terms of arguments, but I don't get the exact point where the fault is. Can anyone please help with this?

Traceback:

TypeError                                 Traceback (most recent call last)
in <module>()
    163     return pfit_bootstrap, perr_bootstrap
    164 
--> 165 pfit, perr = fit_bootstrap(pstart, xx, yy, func)
    166 
    167 print("\nFit parameters and parameter errors from bootstrap method :")

in fit_bootstrap(p0, datax, datay, function, yerr_systematic)
    127 
    128     # Fit first time
--> 129     pfit, perr = optimize.leastsq(errfunc, p0, args=(datax, datay), full_output=0)
    130 
    131 

in leastsq(func, x0, args, Dfun, full_output, col_deriv, ftol, xtol, gtol, maxfev, epsfcn, factor, diag)
    375     if not isinstance(args, tuple):
    376         args = (args,)
--> 377     shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
    378     m = shape[0]
    379     if n > m:

in _check_func(checker, argname, thefunc, x0, args, numinputs, output_shape)
     24 def _check_func(checker, argname, thefunc, x0, args, numinputs,
     25                 output_shape=None):
---> 26     res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
     27     if (output_shape is not None) and (shape(res) != output_shape):
     28         if (output_shape[0] != 1):

in <lambda>(p, x, y)
    124 def fit_bootstrap(p0, datax, datay, function, yerr_systematic=0.0):
    125 
--> 126     errfunc = lambda p, x, y: function(x,p) - y
    127 
    128     # Fit first time

TypeError: func() takes exactly 4 arguments (2 given) 
Community
  • 1
  • 1
FaCoffee
  • 7,609
  • 28
  • 99
  • 174

1 Answers1

2

In the following line you should not pass the func as an argument:

pfit, perr = fit_bootstrap(pstart, xx, yy, func)

If you check the answer you referred to, they pass function named ff. The ff is defined as:

def ff(x, p):
    return func(x,*p)

once you added the definition of "ff", you can change the call to:

pfit, perr = fit_bootstrap(pstart, xx, yy, ff)
Shahram
  • 814
  • 6
  • 10