error in math formulas in python code scipy

Question:

i have small piece of code which produce errormessages (I think because of the math formula). Anyone an idea why?

import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
from scipy.integrate import quad
n = 3
x = np.array([2.1,2.2,2.3,2.4])
y = np.array([0.9,2.1,3.2,17.9])
def func(x, a, b):
    b1 = n*quad(x[n]*np.log(y[n]), 1, n) - quad(x[n], 1, n)*quad(np.log(y[n]), 1, n)
    b2 = n*quad(x[n]**2, 1, n) - (quad(x[n], 1, n))**2
    b = b1 / b2
    a = np.exp(1/n+(quad(np.log(y[n]), 1, n) - b(quad(x[n], 1, n))))
    return a*np.exp(b*x)
popt, pcov = curve_fit(func, x, y)
print popt
plt.plot(x, y)
plt.grid(True)
plt.show()

Errorlog:

Traceback (most recent call last):
  File "F:py-IATLaktat.py", line 20, in <module>
    popt, pcov = curve_fit(func, x, y)
  File "C:Python27libsite-packagesscipyoptimizeminpack.py", line 506, in curve_fit
    res = leastsq(func, p0, args=args, full_output=1, **kw)
  File "C:Python27libsite-packagesscipyoptimizeminpack.py", line 348, in leastsq
    m = _check_func('leastsq', 'func', func, x0, args, n)[0]
  File "C:Python27libsite-packagesscipyoptimizeminpack.py", line 14, in _check_func
    res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
  File "C:Python27libsite-packagesscipyoptimizeminpack.py", line 418, in _general_function
    return function(xdata, *params) - ydata
  File "F:py-IATLaktat.py", line 15, in func
    b1 = n*quad(x[n]*np.log(y[n]), 1, n) - quad(x[n], 1, n)*quad(np.log(y[n]), 1, n)
  File "C:Python27libsite-packagesscipyintegratequadpack.py", line 247, in quad
    retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points)
  File "C:Python27libsite-packagesscipyintegratequadpack.py", line 312, in _quad
    return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
quadpack.error: quad: first argument is not callable

Thanks!

Asked By: littleg

||

Answers:

According to docs, the first argument to quad should be a function to integrate. You have an expression rather than function. To fix that, you can try to introduce anonymous functions to quad calls:

b1 = n*quad(lambda n:x[n]*np.log(y[n]), 1, n) - quad(lambda n:x[n], 1, n) * 
     quad(lambda n:np.log(y[n]), 1, n)

This is untested, but it should work.

Answered By: Andrey Sobolev

Kevin pointed out that the first argument to quad is supposed to be a function and you are putting in a number. I would suggest creating a function

def newfunc(x, y, n):
  # Insert appropriate processing here
  return x[n]*np.log(y[n])

Now put newfunc as the first argument to quad with the appropriate aguments in the calling sequence.

Note that the other calls to quad would require similar modifications.

Answered By: sabbahillel