Reputation: 41
I'm relatively new to Python and the FFT function. I'm trying to use the numpy.fft.fft() function to transform a square pulse (1-D diffraction slit function) to a sinc function (1-D diffraction pattern), and make the output plot identical to the analytical transform of the square pulse, given by the equation:
F(u) = sin(πau)/(πu)
However, I am having trouble formatting the FFT to make it look identical to the analytical function. This is my minimal working code:
a = 40.0 # slit width
N = 5000 # sample points
T = 100.0 # sample spacing
x = np.linspace(-T/2.0,T/2.0,N)
y = np.piecewise(x,[abs(x)>a/2,abs(x)<=a/2],[0,1]) # make 1-D square pulse array
dx = x[1] - x[0]
yf = np.fft.fft(y) * dx # Fourier transform
xf = np.fft.fftfreq(N,d=dx)
xf = np.fft.fftshift(xf)
yf = np.fft.fftshift(yf)
plt.figure(1)
plt.plot(xf,yf)
f = np.sin(np.pi*a*x)/(np.pi*x) # analytical transform function
plt.figure(2)
plt.plot(x,f)
plt.show()
I think I need to adjust the frequencies for the FFT, but I'm not sure. Any help is greatly appreciated!
Upvotes: 3
Views: 1752
Reputation: 114831
You have a discrete signal with finite length. When you use the FFT to compute the Fourier transform of that signal, you are assuming that the signal is periodic. That is, your signal is not a single rectangular pulse; it is a repeating pulse. The analytic result that applies in this case is the periodic sinc function (also known as the aliased sinc function or the Dirichlet function), one form of which is
f(x) = sin(n*x/2) / (n*sin(x/2))
This function is available as scipy.special.diric
. Just recently I
added an example to the docstring of diric
to show exactly what you
are asking. Here's the example. (It won't appear in a released version
of scipy until version 0.17.)
Standard imports:
>>> import numpy as np
>>> from scipy import special
Create a small rectangular pulse for the demonstration:
>>> m = 8
>>> k = 3
>>> x = np.zeros(m)
>>> x[:k] = 1
Use the FFT to compute the Fourier transform of x
, and
inspect the magnitudes of the coefficients:
>>> np.abs(np.fft.fft(x))
array([ 3. , 2.41421356, 1. , 0.41421356, 1. ,
0.41421356, 1. , 2.41421356])
Now find the same values (up to sign) using diric
. We multiply
by k
to account for the different scaling conventions of
numpy.fft.fft
and diric
:
>>> theta = np.linspace(0, 2*np.pi, m, endpoint=False)
>>> k * special.diric(theta, k)
array([ 3. , 2.41421356, 1. , -0.41421356, -1. ,
-0.41421356, 1. , 2.41421356])
Upvotes: 2