离散傅里叶变换:如何正确使用ffthift与fft

时间:2011-10-12 17:02:56

标签: python numpy fft

我想在numpy数组Y上数值计算FFT。为了测试,我使用高斯函数Y = exp(-x ^ 2)。 (符号)傅立叶变换是Y'=常数* exp(-k ^ 2/4)。

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

天真的方法失败了:

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)

实数(Y_k)在正值和负值之间跳跃,这对应于跳跃阶段,这在符号结果中不存在。这当然是不可取的。 (结果在技术上是正确的,因为abs(Y_k)给出了预期的ifft(Y_k)为Y的振幅。)

这里,函数fftshift()使数组k单调递增并相应地改变Y_k。通过对两个向量应用此操作,不会更改对zip(k,Y_k)。

此更改似乎可以解决问题:

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

如果需要单调的Y和Y_k,这是使用fft()函数的正确方法吗?

以上的反向操作是:

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

对于这种情况,documentation明确指出Y_k必须与fft()和fftfreq()的输出进行排序兼容,我们可以通过应用ifftshift()来实现。

这些问题一直困扰着我很长时间:fft()和ifft()的输出和输入数组总是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],其中'frequency'是自变量?

Fourier Transform of a Gaussian is not a Gaussian上的答案没有回答我的问题。

2 个答案:

答案 0 :(得分:3)

FFT可以被认为是产生每个具有幅度和相位的设定矢量。 fft_shift操作将相位角为零的参考点从FFT孔径边缘更改为原始输入数据矢量的中心。

当完成此操作时,结果的相位(以及因此复矢量的实部)有时不那么“跳跃”,特别是如果某些输入函数被加窗使得它在FFT孔径的边缘周围是不连续的。或者,如果输入围绕FFT孔径的中心对称,则在fft_shift之后FFT结果的相位将始终为零。

fft_shift可以通过N / 2的向量旋转来完成,或者通过简单地在FFT结果中翻转交替的符号位来完成,这可能对CPU dcache更友好。

答案 1 :(得分:2)

fft(和ifft)的输出定义如下:http://docs.scipy.org/doc/numpy/reference/routines.fft.html#background-information

这是例程计算的内容,不多也不少。观察到离散傅立叶变换与连续傅里叶变换有很大不同。对于密集采样函数,两者之间存在关系,但除了fftshift之外,该关系还涉及相位因子和缩放。这是你在情节中看到的振荡的原因。您可以根据上述DFT的数学公式自行计算出必要的相位因子。