Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convolution of symmetric arrays with NumPy: why is the result shifted?

I have two numpy arrays. each one containing a kernel-like function centered on zero, perfectly symmetric, both with a length of 101. When I convolve these arrays, should I expect, as a result, another array which is also centered on zero? I am using numpy.convolve, and I always get a resulting kernel array which is not centered on zero, which is not what I want: I need one that is also perfectly centered, not shifted.

My code is more or less like this:

import numpy as np
import matplotlib.pyplot as plt

x = np.array([...])        # x-axis
array1 = np.array([...])   # Blue curve
array2 = np.array([...])   # Green curve
# All arrays are one-dimensional
conv_array = np.convolve(array1, array2, mode='same') # Red curve
conv_array /= max(conv_array) # Normalization

plt.plot(x, array1)
plt.plot(x, array2)
plt.plot(x, conv_array)
plt.show()

The resulting plot of the curves is this: Blue curve = array1, green curve = array2, red curve = convolution result

What do I do to obtain a not-shifted convolved array?

like image 432
SkydivingPanda Avatar asked Oct 12 '25 20:10

SkydivingPanda


1 Answers

One very simple alternative is to use scipy.ndimage.convolve1d instead of numpy.convolve.

import numpy as np
import matplotlib.pyplot as plt
from astropy.modeling import models

# Create a model
x = np.arange(101) - 50       # x-axis
g1 = models.Gaussian1D(amplitude=2, mean=0, stddev=4)
g2 = models.Gaussian1D(amplitude=3, mean=0, stddev=3)
array1 = g1(x)
array2 = 1 - g2(x)

from scipy.ndimage import convolve1d

conv_array2 = convolve1d(array1, array2)
conv_array2 /= conv_array2.max()

# One can also use numpy convolve here
conv_array = np.convolve(array1, array2, mode='same') # Red curve
conv_array /= max(conv_array) # Normalization

plt.plot(x, array1)
plt.plot(x, array2)
plt.plot(x, conv_array) # Is centered on 0
plt.plot(x, conv_array2) # Is centered on 0
plt.show()

I guess the problem is that your arrays are not exactly centered on 0. (So x[50] != 0). And numpy flips the kernel before convolution and therefore you get a shift. Notice if you try my example the numpy.convolve result is also perfectly centered on 0 but I made sure array1 and array2 were centered on 0. From your plot I guess that -22<x<27 (which is not centered)

The reason why I recommend scipy is because I also had a similar problem :-) They just use different definitions: numpy and scipy notice the different signs of the kernel-index.

like image 173
MSeifert Avatar answered Oct 14 '25 10:10

MSeifert