2

I am a noob in convolution and I am using Python. I am trying to convolve a 1D array with a 1D Gaussian and my array is

B = [0.011,0.022,.032,0.027,0.025,0.033,0.045,0.063,0.09,0.13,0.17,0.21].

The FWHM of the Gaussian is 5. So I calculated the sigma to be 5/2.385 = ~2.09 Now, I have 2 options:

  1. Generate a Gaussian Kernal using standard equation for Gaussian and use np.convolve(array, Gaussian) Gaussian equation I used

  2. Use scipy.ndimage.gaussian_filter1d Since both are convolution tasks, theoretically both are supposed to give similar outputs. But it is not so. Why is it so?

I have attached an image where I have plotted the array vs another equally spaced array

A = [1.0, 3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0, 21.0, 23.0].

The array (B) plotted against equally spaced array (A) Basically, I want to plot the convolved array and the non-convolved array together vs A. How do I do it?

Gufran Hasan
  • 8,910
  • 7
  • 38
  • 51
Nithin Mohan
  • 23
  • 1
  • 5

1 Answers1

6

Why do numpy.convolve and scipy.ndimage.gaussian_filter1d?

It is because the two functions handle the edge differently; at least the default settings do. If you take a simple peak in the centre with zeros everywhere else, the result is actually the same (as you can see below). By default scipy.ndimage.gaussian_filter1d reflects the data on the edges while numpy.convolve virtually puts zeros to fill the data. So if in scipy.ndimage.gaussian_filter1d you chose the mode='constant' with the default value cval=0 and numpy.convolve in mode=same to produce a similar size array, the results are, as you can see below, the same.

Depending on what you want to do with your data, you have to decide how the edges should be treated.

Concerning on how to plot this, I hope that my example code explains this.

import matplotlib.pyplot as plt
import numpy as np
from scipy.ndimage.filters import gaussian_filter1d

def gaussian( x , s):
    return 1./np.sqrt( 2. * np.pi * s**2 ) * np.exp( -x**2 / ( 2. * s**2 ) )

myData = np.zeros(25)
myData[ 12 ] = 1
myGaussian = np.fromiter( (gaussian( x , 1 ) for x in range( -3, 4, 1 ) ), np.float )
filterdData = gaussian_filter1d( myData, 1 )

myFilteredData = np.convolve( myData, myGaussian, mode='same' )
fig = plt.figure(1)

ax = fig.add_subplot( 2, 1, 1 )
ax.plot( myData, marker='x', label='peak' )
ax.plot( filterdData, marker='^',label='filter1D smeared peak' )
ax.plot( myGaussian, marker='v',label='test Gaussian' )
ax.plot( myFilteredData, marker='v', linestyle=':' ,label='convolve smeared peak' )
ax.legend( bbox_to_anchor=( 1.05, 1 ), loc=2 )

B = [0.011,0.022,.032,0.027,0.025,0.033,0.045,0.063,0.09,0.13,0.17,0.21]
myGaussian = np.fromiter( ( gaussian( x , 2.09 ) for x in range( -4, 5, 1 ) ), np.float )
bx = fig.add_subplot( 2, 1, 2 )
bx.plot( B, label='data: B' )
bx.plot( gaussian_filter1d( B, 2.09 ), label='filter1d, refl' )
bx.plot( myGaussian, label='test Gaussian' )
bx.plot(  np.convolve( B, myGaussian, mode='same' ), label='Gaussian smear' )
bx.plot( gaussian_filter1d( B, 2.09, mode='constant' ), linestyle=':', label='filter1d, constant')
bx.legend( bbox_to_anchor=(1.05, 1), loc=2 )
plt.tight_layout()
plt.show()

Providing the following image:

Several convolve "configurations"

mikuszefski
  • 3,943
  • 1
  • 25
  • 38
  • Thank you so much for the quick response. It was really helpful to understand the concept. – Nithin Mohan Oct 03 '18 at 05:21
  • @NithinMohan you are welcome; feel free to mark the answer as correct or upvote. – mikuszefski Oct 04 '18 at 06:22
  • Thanks again. I have marked the answer as correct. I could not upvote as I am new to Stack Overflow it says 'It takes 15 reputations to upvote'. – Nithin Mohan Oct 04 '18 at 11:31
  • @NithinMohan Thanks. If you continue on SE you'll reach the 15 soon. See you around. – mikuszefski Oct 04 '18 at 12:53
  • @mikuszefski Can you explain why you took `range( -3, 4, 1 )` and `range( -4, 5, 1 )` for the gaussian? – beliz Oct 30 '20 at 13:08
  • @beliz Hi, that is actually quite some time ago that I did that. looking back, I'd say that for the example it is, with a reasonable sigma, a reasonable symmetric coverage; that's all, no other specific reason. – mikuszefski Oct 31 '20 at 14:45
  • @mikuszefski how can I choose such values? I have an array that I would like perform convolution with Gaussians but I haven't been able to do so. Maybe if I can choose the correct values I can manage it without asking another question... – beliz Nov 05 '20 at 12:29
  • @beliz Hi, I am not sure that there is a general formula. This depends strongly on what you want to do with it. Maybe we can chat about this, as it does not seem to match the criteria for a question here – mikuszefski Nov 05 '20 at 15:30
  • @mikuszefski can you check my question? https://stackoverflow.com/questions/64749175/smoothing-a-curve-with-many-peaks-with-gaussian – beliz Nov 09 '20 at 09:43