I need to numerically solve a convolution. I would like to feed an array at which the convolution is solved into scipy.stats.quad
in one go:
# Python 2.7.12
import numpy as np
from scipy import integrate
def gauss(x, sig, mu):
return(1 / np.sqrt(2*np.pi*sig**2) * np.exp(-(x-mu)**2/(2.*sig**2)))
def PDF_log(x, sig, mu):
mu = np.log(mu)
x = np.asarray(x) # get nans instead of errors for 1/x
a = 1/(x * sig * np.sqrt(2*np.pi)) * np.exp(-(np.log(x)-mu)**2/(2*sig**2))
# make sure negative 'x' are returned to 0., as the function only is
# defined for positive values.
a = np.nan_to_num(a)
return a
def gauss_conv(t, x, sig, mu, sig0, mu0):
a = PDF_log(t, sig, mu) * gauss(x-t, sig0, mu0)
return a
def gauss_log_num(x, sig, mu, sig0, mu0):
return integrate.quad(
gauss_conv,
a=-np.inf, b=np.inf, args=(x, sig, mu, sig0, mu0)
)
mu = 0.3
sig = 0.12
mu0 = 0.
sig0 = 0.05
x = np.array([
0.06581838,
0.11165416,
0.15748993,
0.20332571,
0.24916149,
0.29499726,
0.34083304,
0.38666882,
0.43250459,
0.47834037,
0.52417615,
])
print(gauss_log_num(x, sig, mu, sig0, mu0))
this raises:
Traceback (most recent call last):
File "num_gauss_lognormal.py", line 327, in <module>
test()
File "num_gauss_lognormal.py", line 325, in test
print(gauss_log_num(x, sig, mu, sig0, mu0))
File "num_gauss_lognormal.py", line 163, in gauss_log_num
return ( integrate.quad(gauss_conv, a = -np.inf, b = np.inf, args=(x,sig,mu,sig0,mu0)) )
File "/usr/local/lib/python2.7/dist-packages/scipy/integrate/quadpack.py", line 323, in quad
points)
File "/usr/local/lib/python2.7/dist-packages/scipy/integrate/quadpack.py", line 390, in _quad
return _quadpack._qagie(func,bound,infbounds,args,full_output,epsabs,epsrel,limit)
TypeError: only length-1 arrays can be converted to Python scalars`
If I only evaluate x at a single position, e.g. x[0]
, the convolution works and I get a value. Obviously I could now run a for loop over x
, but this feels like the slowest possible way of doing it.
What do I have to do to evaluate the convolution at every value of x
in one go?