numpy.fft.fft() 在 Python 中实施

numpy.fft.fft() implementation in Python

我正在尝试使用 fft 函数获取周期信号的频谱。然后绘制变换的幅度和相位。幅度图还可以,但相位图完全出乎意料。 例如,我使用函数 Sin³(t) 和 Cos³(t)。我使用的代码是:

import matplotlib.pyplot as plt
import numpy.fft as nf
import math
import numpy as np
pi = math.pi

N=512

# Sin³(x)
t=np.linspace(-4*pi,4*pi,N+1);t=t[:-1]
y=(np.sin(t))**3
Y=nf.fftshift(nf.fft(y))/N
w=np.linspace(-64,64,N+1);w=w[:-1]

plt.figure("0")
plt.subplot(2,1,1)
plt.plot(w,abs(Y),'ro',lw=2)
plt.xlim((-4,4))
plt.ylabel(r"$|Y|$",size=16)
plt.title("Spectrum of sin\u00B3(t)")
plt.grid(True)
plt.subplot(2,1,2)
ii=np.where(abs(Y)>1e-3)
plt.plot(w[ii],np.angle(Y[ii]),'go',lw=2)
plt.xlim((-4,4))
plt.ylabel(r"Phase of $Y$",size=16)
plt.xlabel(r"$\omega$",size=16)
plt.grid(True)

# Cos³(x)

t=np.linspace(-4*pi,4*pi,N+1);t=t[:-1]
y=(np.cos(t))**3
Y=nf.fftshift(nf.fft(y))/N
w=np.linspace(-64,64,N+1);w=w[:-1]

plt.figure("1")
plt.subplot(2,1,1)
plt.plot(w,abs(Y),'ro',lw=2)
plt.xlim((-4,4))
plt.ylabel(r"$|Y|$",size=16)
plt.title("Spectrum of cos\u00B3(t)")
plt.grid(True)
plt.subplot(2,1,2)
ii=np.where(abs(Y)>1e-3)
plt.plot(w[ii],(np.angle(Y[ii])),'go',lw=2)
plt.xlim((-4,4))
plt.ylabel(r"Phase of $Y$",size=16)
plt.xlabel(r"$\omega$",size=16)
plt.grid(True) 

得到的地块是:

i) 对于 Sin³(t) - Magnitude and Phase of Spectrum of Sin³(t)

ii) 对于 Cos³(t) - Magnitude and Phase of Spectrum of Cos³(t)

正如您在上面的链接中看到的,两个函数的量级都很好。 Spectrum of Sin³(t) 的相位符合预期。

由于 Cos³(t) 是实数且为偶数,并且根据复指数展开表明系数的相位为 0。但是绘制的图表显示了完全不同的答案(参见 2):在w=-3 相位接近 5 弧度。我犯了什么错误,实现FFT的正确方法是什么。

np.fft 表现符合预期;是你的阴谋造成了混乱。致电 plt.tight_layout() 应该可以帮助您解决问题:

如果仔细查看 cos³(t) 相位的 y 轴,您会发现所有值都有一个 1e-17 预因子。所以在 w = -3 时,相位 而不是 接近 5 弧度,它实际上接近 5e-17 弧度(对于所有意图和目的来说都是零)。

我在调查这个的时候整理了你的代码:

import matplotlib.pyplot as plt
import numpy.fft as nf
import numpy as np

plt.rcParams['axes.grid'] = True

pi = np.pi
N = 512

t = np.linspace(-4*pi, 4*pi, N+1)[:-1]


def fft_func(x, func, N):
    y = func(x) ** 3
    Y = nf.fftshift(nf.fft(y)) / N
    w = np.linspace(-64, 64, N+1)[:-1]
    return y, Y, w


def plot_mag_phase(w, Y, func_name):
    fig, ax = plt.subplots(2, 1)

    ii = np.where(abs(Y) > 1e-3)

    ax[0].plot(w, abs(Y), 'ro', lw=2)
    ax[1].plot(w[ii], np.angle(Y[ii]), 'go', lw=2)

    ax[0].set_xlim(-4, 4)
    ax[1].set_xlim(-4, 4)

    ax[0].set_ylabel("$|Y|$", size=16)
    ax[1].set_ylabel("Phase of $Y$", size=16)

    ax[0].set_title("Spectrum of {}\u00B3(t)".format(func_name))
    ax[1].set_xlabel(r'$\omega$', size=16)

    fig.tight_layout()

# sin x ^ 3
y, Y, w = fft_func(t, np.sin, N)
plot_mag_phase(w, Y, 'sin')

# cos x ^ 3
y, Y, w = fft_func(t, np.cos, N)
plot_mag_phase(w, Y, 'cos')