开发者

Discrete Fourier Transform: How to use fftshift correctly with fft

开发者 https://www.devze.com 2023-04-12 08:36 出处:网络
I want numerically compute the FFT on a numpy array Y. For testing, I\'m using the Gaussian function Y = exp(-x^2). The (symbolic) Fourier Transform is Y\' = constant * exp(-k^2/4).

I want numerically compute the FFT on a numpy array Y. For testing, I'm using the Gaussian function Y = exp(-x^2). The (symbolic) Fourier Transform is Y' = constant * exp(-k^2/4).

import numpy
X = numpy.arange(-100,100)
Y = numpy.exp(-(X/5.0)**2)

The naive approach fails:

from numpy.fft import *
from matplotlib import pyplot

def plotReIm(x,y):
    f = pyplot.figure()
    ax = f.add_subplot(111)
    ax.plot(x, numpy.real(y), 'b', label='R()')
    ax.plot(x, numpy.imag(y), 'r:', label='I()')
    ax.plot(x, numpy.abs(y), 'k--', label='abs()')
    ax.legend()


Y_k = fftshift(fft(Y))
k = fftshift(fftfreq(len(Y)))
plotReIm(k,Y_k)

real(Y_k) jumps between positive and negative values, which correspond to a jumping phase, which is not present in the symbolic result. This is certainly not desirable. (The result is technically correct in the sense that abs(Y_k) gives the amplitudes as expected ifft(Y_k) is Y.)

Here, the function fftshift() renders the array k monotonically increasing and changes Y_k accordingly. The pairs zip(k, Y_k) are not changed by applying this operation to both vectors.

This changes appears to fix the issue:

Y_k = fftshift(fft(ifftshift(Y)))
k = fftshift(fftfreq(len(Y)))
plotReIm(k,Y_k)

Is this the correct way to employ the fft() function if monotonic Y and Y_k are required?

开发者_JAVA技巧

The reverse operation of the above is:

Yx = fftshift(ifft(ifftshift(Y_k)))
x = fftshift(fftfreq(len(Y_k), k[1] - k[0]))
plotReIm(x,Yx) 

For this case, the documentation clearly states that Y_k must be sorted compatible with the output of fft() and fftfreq(), which we can achieve by applying ifftshift().

Those questions have been bothering me for a long time: Are the output and input arrays of both fft() and ifft() always such that a[0] should contain the zero frequency term, a[1:n/2+1] should contain the positive-frequency terms, and a[n/2+1:] should contain the negative-frequency terms, in order of decreasingly negative frequency [numpy reference], where 'frequency' is the independent variable?

The answer on Fourier Transform of a Gaussian is not a Gaussian does not answer my question.


The FFT can be thought of as producing a set vectors each with an amplitude and phase. The fft_shift operation changes the reference point for a phase angle of zero, from the edge of the FFT aperture, to the center of the original input data vector.

The phase (and thus the real component of the complex vector) of the result is sometimes less "jumpy" when this is done, especially if some input function is windowed such that it is discontinuous around the edges of the FFT aperture. Or if the input is symmetric around the center of the FFT aperture, the phase of the FFT result will always be zero after an fft_shift.

An fft_shift can be done by a vector rotate of N/2, or by simply flipping alternating sign bits in the FFT result, which may be more CPU dcache friendly.


The definition for the output of fft (and ifft) is here: http://docs.scipy.org/doc/numpy/reference/routines.fft.html#background-information

This is what the routines compute, no more and no less. Observe that the discrete Fourier transform is rather different from the continuous Fourier transform. For a densely sampled function there is a relation between the two, but the relation also involves phase factors and scaling in addition to fftshift. This is the cause of the oscillations you see in your plot. The necessary phase factor you can work out yourself from the above mathematical formula for the DFT.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号