$\begingroup$

Yes, zero-padding is the issue, however not as you would except...

@Soren is only partially right: you can add zeros at the beginning, middle or end of the signal just as you did, but absolutely not as you wish.

What's the general rule?

Look at how the signal repeats with and without zeros and choose the place that distorts the signal the least.

What does it mean?

In the case of a real, discrete and aperiodic time-space signal, there is a causal relationship between the value at n and the value at n+1. So all these values should be considered as a bloc, adding zeros in the middle would distort it. Here is an obvious reason from your code, you had a proper Gaussian, not something like this:

In the case of your convolution kernel, it's a bit more complicated. What do the last taps (second half) mean? In the aperiodic DTFT (i.e. linear convolution, as opposed to circular), these mean that the convolved values depends of both [n, n+1, n+2, ...] (as expected) but also [len - 1, len - 2, len - 3, ...] (where len corresponds to the end of the array without padding). This "classical" linear convolution can be simulated by padding the end/beginning of the signal. In the periodic DFT (circular convolution), the taps of the second half actually correspond to the values [n-1, n-2, n-3, ...] ( not the values by the end of the signal).



np.convolve and bunch try to do a "classical" linear convolution while you seem to want a non-classical one (zeros added in the middle). Here is a comparison:

As I understood, the actual kernel you want is the one described in "your kernel".

You can easily get the right kernel by fftshifting:

kern = np.fft.fftshift(kern)

This has the effect of centering your DC (using linear phase shifting) and then you can just pad zeros at the beginning/end as much as you wish and use the standard convolution/filtering tools.