我想知道如何绘制正弦函数的傅立叶变换。从理论上讲,我希望看到一个矩形函数或看起来像高帽函数的东西。我使用 numpy 的 linspace 定义了一组“x”点,并为每个 x 值相应地计算了 np.sinc。然后我可以轻松地绘制它来展示以 x=0 为中心的简单正弦函数。
然后我使用 scipy.fftpack.fft 计算 sinc 值数组的傅立叶变换,并尝试绘制这些结果,期望看到矩形或顶帽函数。相反,我得到了如下所示的图:
我不确定为什么会发生这种情况以及我可以采取什么措施来解决它。如有任何帮助,我们将不胜感激。
有点晚了,但无论如何,这里有一个答案:
是的,从理论上讲你会期望看到一个矩形函数。然而,
fft
的输出在几个方面与原始(连续)傅里叶变换不同,另请参阅文档(NumPy,但据我所知,算法与scipy.fftpack.fft
相同),所以您需要采取一些额外的步骤才能获得预期的输出。
首先,一些代码(大约)重现您的绘图:
import numpy as np
import matplotlib.pyplot as plt
from math import pi
# Define a time axis, plus some parameters for later use
N = 500
t_start, t_end = -12.5, 12.5
dt = (t_end - t_start)/N
fs = 1/dt # sampling frequency
fN = fs/2 # Nyquist frequency
t = np.linspace(t_start, t_end, N, endpoint = False)
# The sinc function (note that NumPy uses the normalised sinc,
# defined as sin(pi*t)/(pi*t))
f = np.sinc(t)
plt.figure()
plt.plot(t, f)
# The FFT
F = np.fft.fft(f)
plt.figure()
plt.plot(np.real(F))
# Not sure how you produced your fft plot; just plotting F issues a warning
# and discards the complex part of F, resulting in the same plot as above.
问题1:输出偏移
引用 NumPy FFT 文档:结果中的值遵循所谓的“标准”顺序:如果
A = fft(a, n)
,则 A[0]
包含零频率项(信号之和),它始终是纯实数为真实输入。然后 A[1:n/2]
包含正频率项,A[n/2+1:]
包含负频率项,按负频率递减的顺序排列。对于偶数个输入点, A[n/2]
表示正奈奎斯特频率和负奈奎斯特频率,并且对于实数输入也是纯实数。对于奇数个输入点, A[(n-1)/2]
包含最大的正频率,而 A[(n+1)/2]
包含最大的负频率。例程 np.fft.fftfreq(n)
返回一个数组,给出输出中相应元素的频率。例程 np.fft.fftshift(A)
会移动变换及其频率,将零频率分量放在中间,并且 np.fft.ifftshift(A)
会撤消该移动。
不,离散傅立叶变换并不真正包含负频率,但以这种方式思考它对于与连续版本进行比较是很好的(并且完全可以接受,因为 DFT 是周期性的)。
# use fftshift to centre output at zero frequency
F_shifted = np.fft.fftshift(F)
# use fftfreq to get frequency axis
freq = np.fft.fftfreq(N, dt)
freq_shifted = np.fft.fftshift(freq)
plt.figure()
plt.plot(freq_shifted, np.real(F_shifted))
问题2:输出振荡
感谢 @Chris Luengo 的解释:这是因为
fft
期望一个周期性输入信号,其原点 (t = 0) 在第一个元素中。将原点放在中间,即 N/2
处,将给出延迟 sinc 的傅里叶变换,该傅里叶变换相对于 sinc 的傅里叶变换有相移(即乘以复指数;移位定理)。在 DFT 情况下,这表现为在奈奎斯特频率下的复指数振荡(参见例如Wikipedia)。该复指数的大小为 1(频谱中的能量不变),因此如果您绘制输出的绝对值,则不会出现任何振荡。然而,正确的解决方案是移动输入信号,使其起源于第一个元素。
# Plot absolute value of F_shifted, oscillations will have disappeared
plt.figure()
plt.plot(freq_shifted, abs(F_shifted))
# Shift input signal before applying fft
f_shifted = np.fft.ifftshift(f)
# Determine FFT and shift output
F = np.fft.fftshift(np.fft.fft(f_shifted))
plt.figure()
plt.plot(freq_shifted, np.real(F))
问题3:输出幅度关闭
参见问题1下的解释;
fft
的输出按输入信号之和缩放。
# Scale output
tot = sum(f)
F_scaled = 1/tot*F
plt.figure()
plt.plot(freq_shifted, np.real(F_scaled))
最后,输出“角”周围保留的振荡是 rect 函数在那里不连续的结果。为了正确捕获这些不连续性,您需要无限数量的频率。
fft
算法仅包括高达奈奎斯特频率的频率,因此会出现振荡(称为吉布斯现象)。