SkydivingPanda
SkydivingPanda

Reputation: 143

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?

Upvotes: 4

Views: 3102

Answers (2)

MSeifert
MSeifert

Reputation: 152637

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.

Upvotes: 2

Colin Dickie
Colin Dickie

Reputation: 910

I fear this is a mathematical question on convolution, which I cannot answer. However if you simply wish to center the convolved array on zero (its minima) then the following will provide a 'quick fix':

plt.plot(x + x[np.argmin(conv_array[:conv_array.shape[0]*3/4)]],conv_array)

Upvotes: 0

Related Questions