0

There is an answer to this very question here however the solution doesn't seem to work for me.

my function is the following:

def slopefunction_cf(xin,amp,phase,off,freq,intercept,t):
    fitted =np.zeros((4,12))

    for im in t:        
        fitted[:,im-1] = intercept[im-1]+[amp*np.sin(freq*(im)+phase)+off]*xin
    return fitted.ravel()

where intercept and t are additional arguments, that in leastsq I would pass as args=

I tried:

popt, pcov = curve_fit(slopefunction_cf, np.arange(0,4), datain, p0=paramin, args=(intercept,t) )

and get the error:

TypeError: func_wrapped() takes exactly 1 argument (3 given)

Then I tried what suggested in the answer I linked and transformed it to:

def define_var_args(interceptin,tin):
    def slopefunction_cf(xin,amp,phase,off,freq):
        intercept = interceptin
        t = tin
        fitted =np.zeros((4,12))

        for im in t:        
            fitted[:,im-1] = intercept[im-1]+[amp*np.sin(freq*(im)+phase)+off]*xin
        return fitted.ravel()

and then called curve_fit:

popt, pcov = curve_fit(define_var_args(intercept, t), np.arange(0,4), datain, p0=paramin )

but I get the following error (i copied everything)

--> 115 popt, pcov = curve_fit(define_var_args(interceptconus, t), np.arange(0,4), datain.ravel(), p0=paramin )
    116 
    117 print popt

/software/centos6/x86_64/canopy-1.7.4/Canopy_64bit/User/lib/python2.7/site-packages/scipy/optimize/minpack.pyc in curve_fit(f, xdata, ydata, p0, sigma, absolute_sigma, check_finite, bounds, method, jac, **kwargs)
    734         # Remove full_output from kwargs, otherwise we're passing it in twice.
    735         return_full = kwargs.pop('full_output', False)
--> 736         res = leastsq(func, p0, Dfun=jac, full_output=1, **kwargs)
    737         popt, pcov, infodict, errmsg, ier = res
    738         cost = np.sum(infodict['fvec'] ** 2)

/software/centos6/x86_64/canopy-1.7.4/Canopy_64bit/User/lib/python2.7/site-packages/scipy/optimize/minpack.pyc 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:

/software/centos6/x86_64/canopy-1.7.4/Canopy_64bit/User/lib/python2.7/site-packages/scipy/optimize/minpack.pyc 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):

/software/centos6/x86_64/canopy-1.7.4/Canopy_64bit/User/lib/python2.7/site-packages/scipy/optimize/minpack.pyc in func_wrapped(params)
    452     if transform is None:
    453         def func_wrapped(params):
--> 454             return func(xdata, *params) - ydata
    455     elif transform.ndim == 1:
    456         def func_wrapped(params):

TypeError: 'NoneType' object is not callable

I am not even sure what the error is - if the code or something in my data? it's a bit obscure.

Is there another way to pass additional parameters?

EDIT: Adding some data and slight change to the above function

t = np.arange(1,13)
paramin = [0.40569370873086791, 1, -0.88134718450091365, 0.5]
datain = [-3.45083921, -3.405628  , -2.57401114, -1.7632551 , -1.29342567,
   -1.44200248, -2.05366981, -2.51467815, -2.79597983, -2.95528074,
   -2.90766603, -3.60850134, -3.90036107, -3.87760971, -3.18549774,
   -2.43304533, -2.1734368 , -2.43953997, -3.1183866 , -3.57696154,
   -3.72915335, -3.67344888, -3.29697388, -4.10385938, -4.88945667,
   -4.82385939, -4.10568684, -3.50093464, -3.26766599, -3.78206157,
   -4.51782818, -4.95149472, -4.93689182, -4.75850421, -4.22849458,
   -4.91811193, -5.34080606, -5.40676402, -4.66050702, -4.29447163,
   -4.16430688, -4.75008652, -5.57106708, -5.58801663, -5.96637981,
   -5.51549722, -4.94026303, -5.42975354]
intercept = [-3.39651633, -3.33601661, -2.55447417, -1.69869584, -1.26867791,
       -1.41340658, -2.02249291, -2.56860547, -2.74926044, -2.91082705,
       -2.78895263, -3.57335517]

I already "raveled" datain, so I modified the function at the beginning of my question. using these data I reproduce my error in a new notebook.

SOLUTION:

I had two issues in my code: 1) I was not returning the nested function 2) I did not put xin as an argument of the nested function 3) I had to put the star before the p

this now works

def define_extravar(interceptin,tin):
    def slopefunction_cf(xin,*p):
        intercept = interceptin
        t = tin
        fitted =np.zeros((4,12))
        amp,phase,off,freq = p

        for im in t:        
            fitted[:,im-1] = intercept[im-1]+[amp*np.sin(freq*(im)+phase)+off]*xin
        return fitted.ravel()
    return slopefunction_cf
claude
  • 549
  • 8
  • 25
  • Could you add some data so that we can reproduce the error? – Cleb Jan 31 '18 at 21:49
  • 1
    "Not callable" means the thing you are trying to use as a function is not actually a function. In this case, it means `define_var_args` (the first argument of `curve_fit`) has not been defined. We don't have a reproducible example here, so this is as far as it can go; voting to close. –  Jan 31 '18 at 22:56
  • added the data - thanks for the help – claude Feb 01 '18 at 20:45
  • I found the issue and will modify the text accordingly. – claude Feb 01 '18 at 21:19
  • I'd say if you do not want to use `leastsq` but insist on `curve_fit` the easiest way to pass fixed value parameters is a `global param` – mikuszefski Feb 02 '18 at 10:50
  • 1
    The other option might be to have a look at [`lmfit`](https://lmfit.github.io/lmfit-py/) which allows to fix parameters. – mikuszefski Feb 02 '18 at 10:51
  • thanks I will look into that as well. – claude Feb 02 '18 at 14:42

0 Answers0