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')
我正在尝试使用 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')