【发布时间】:2019-06-24 13:38:15
【问题描述】:
我在使用 python 中的 scipy fft 模块获取简单正弦曲线的相位时遇到了麻烦。我密切关注this 教程并将matlab 代码转换为python。但是,无论我将哪个阶段用于输入,图表始终显示 3。我错过了什么?
import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack
import cmath
A=10
fc = 10
phase=60
fs=32#Sampling frequency with oversampling factor of 32
t = np.arange(0,2,1/fs)
#Convert the phase shift to radians from degrees.
phi = phase*np.pi/180
x=A*np.cos(2*np.pi*fc*t+phi)
N=256
X = scipy.fftpack.fftshift(scipy.fftpack.fft(x,N))/N
df=fs/N #Frequency resolution.
sampleindex = np.arange(-N/2,N/2,1) #Ordered index for FFT plot.
f = sampleindex*df #x-axis index continued to ordered frequencies
raw_phases = np.angle(X)
X2=np.copy(X)#Store the FFT results in another array.
#Detect very small numbers and ignore them.
tau = max(abs(X))/10
X2[abs(X)<tau]=0
phase=[cmath.phase(i) for i in X2]
plt.plot(f,phase)
plt.show()
编辑:这是一些更简单的代码。似乎仍然无法获得相位。
y = 28*np.sin(2*np.pi/7*x)
yf = scipy.fftpack.fft(y)
xf = np.linspace(0.0, 1.0/(2.0*T), N/2)
phase = np.angle(yf)
yf = np.abs(yf[:N//2])
phase = phase[:N//2]
xf = xf[1:]
yf = yf[1:]
phase = phase[1:]
yf = yf-np.mean(yf)
#The frequencies seem to always be scaled by 0.1433, not sure why.
c = 2*np.pi/7/0.143301
freqs = xf[yf>np.std(yf)]*c
phases = phase[yf>np.std(yf)]
我得到的频率集中在 2*np.pi/7 附近。但我得到的阶段是:
array([-0.217795 , -0.22007488, -0.22226087, 2.91723935, 2.91524011,
2.91333367])
虽然根本不应该有阶段。
【问题讨论】:
-
您应该计算完整信号的 FFT,而不是前 256 个样本的 FFT。只有当信号中有整数个正弦波周期时,您的实验才会有效。
N参数到scipy.fftpack.fft导致信号被修剪(或零填充)为N样本。别管它。 -
如果我去掉N,向量的长度会从256变为64。需要调查原因。
-
是的,确实,您以 1/32 的步长创建了一个从 0 到 2 的向量 t。说得通。 FFT 始终具有与输入信号一样多的样本。
-
@CrisLuengo 添加了更多使用普通 fft 的代码。我注意到对于这个,频谱的第一个分量总是很大。所以,我不得不忽略它。但是,当我尝试获得相位时,我得到了意想不到的结果。查看我的编辑。
-
零频率包含所有样本值的总和。因为您的信号没有在整数个周期内对正弦波进行采样,所以它的总和不为零。这也是您没有在正弦波频率处获得预期的漂亮峰值的原因。请参阅我的答案以获取一些显示您想看到的内容的简单代码。