Reputation: 565
I am interested to optimize a function which is the convolution of two functions. The main problem is that my resulting function is completly of scale and i do not understand what np.convolve actually does.
I wrote a small script that should convolve two Gaussian, but the resulting Gaussian is much larger in size than the input functions:
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt
import numpy as np
# https://stackoverflow.com/questions/18088918/combining-two-gaussians-into-another-guassian
def gauss(x, p): # p[0]==mean, p[1]==stdev, p[2]==heightg, p[3]==baseline
a = p[2]
mu = p[0]
sig = p[1]
#base = p[3]
return a * np.exp(-1.0 * ((x - mu)**2.0) / (2.0 * sig**2.0)) #+ base
p0 = [0, 0.3, 1] # Inital guess is a normal distribution
p02 = [0, 0.2, 0.5]
xp = np.linspace(-4, 4, 2000)
convolved = np.convolve(gauss(xp, p0),gauss(xp, p02), mode="same")
fig = plt.figure()
plt.subplot(2, 1, 1)
plt.plot(xp, gauss(xp, p0), lw=3, alpha=2.5)
plt.plot(xp, gauss(xp, p02), lw=3, alpha=2.5)
plt.xlim([-2, 2])
plt.subplot(2, 1, 2)
plt.plot(xp, gauss(xp, p0), lw=3, alpha=2.5)
plt.plot(xp, gauss(xp, p02), lw=3, alpha=2.5)
plt.plot(xp, convolved, lw=3, alpha=2.5,label="too damn high?")
plt.legend()
plt.xlim([-2, 2])
plt.tight_layout()
plt.show()
The resulting gaussian after the convolution is much higher
than what i expected (wikipedia):
Upvotes: 3
Views: 4197
Reputation: 1007
You gotta renormalize for the dx between two x ticks.
Numpy is substituting an integration for a summation, but since the functions takes only the Y values it doesn't care about the volume element on the integration axis which you need to include manually.
I've had to deal with this problem as well and it is a pain when you start doing stuff with dx=1 and than all of a sudden you get a wrong result because of different x axis distribution.
xp = np.linspace(-4, 4, 2000)
dx = xp[1] - xp[0]
convolved = np.convolve(gauss(xp, p0),gauss(xp, p02), mode="same") * dx
!!NOTE: don't put the renormalization inside the function definition. dx should be counted only once because of the integral going into a summation. If you put it inside the function it will actually be counted twice because bot gaussian are generated using it.
PS: To try and understand this better you can try to generate the x axis data with different spacing and without renormalizing you will see that the height of your convolution will differ (the smaller the spacing the greater the height)
fig = plt.figure()
ax = fig.add_subplot(111)
for spacing in (100,500,1000,2000):
spacing += 1
xp = np.linspace(-4, 4, spacing)
dx = xp[1] - xp[0]
convolved = np.convolve(gauss(xp, p01),gauss(xp, p02), mode="same") * dx
ax.plot(xp, convolved, lw=3, alpha=2.5,label="spacing = {:g}".format(8/spacing))
ax.set_title("Convolution with different x spacing. With renormalization")
fig.legend()
plt.show()
Upvotes: 8