Python 中的快速傅立叶图
Fast Fourier Plot in Python
我有一个时域振动数据,想用 fft
将其转换为频域数据。然而,FFT 图仅显示零处的大尖峰,除此之外什么都没有。
这是我的振动数据:https://pastebin.com/7RK57kJW
我的代码:
import numpy as np
import matplotlib.pyplot as plt
t = np.arange(3000)
a1_fft= np.fft.fft(a1, axis=0)
freq = np.fft.fftfreq(t.shape[-1])
plt.plot(freq, a1_fft)
我的 FFT 图:
我在这里做错了什么?我很确定我的数据是统一的,这在其他情况下会引发与 fft 类似的问题。
0 处的峰值是直流增益,它非常高,因为您没有对数据进行归一化。另外,傅里叶变换是一个复数,应该分别绘制绝对值和相位。在此代码中,我还仅绘制了正频率:
import numpy as np
import matplotlib.pyplot as plt
#Import data
a1 = np.loadtxt('a1.txt')
plt.plot(a1)
#Normalize a1
a1 -= np.mean(a1)
#Your code
t = np.arange(3000)
a1_fft= np.fft.fft(a1, axis=0)
freq = np.fft.fftfreq(t.shape[-1])
#Only plot positive frequencies
plt.figure()
plt.plot(freq[freq>=0], np.abs(a1_fft)[freq>=0])
FFT 的 bin 对应于 0, df, 2df, 3df, ..., F-2df, F-df
处的频率,其中 df
由 bin 的数量决定,F
是每个 bin 1 个周期。
注意开头的零频率。这称为直流偏移。这是你的数据的平均值。在您显示的数据中,平均值约为 1.32,而正弦波的幅度约为 0.04。您看不到比 DC 项小 33 倍的峰值也就不足为奇了。
有一些常用的可视化数据的方法可以帮助您解决这个问题。一种常见的方法是保持直流偏移但使用对数刻度,至少对于 y 轴:
plt.semilogy(freq, a1_fft)
或
plt.loglog(freq, a1_fft)
您可以做的另一件事是放大图的底部 1/33 左右。您可以手动执行此操作,也可以通过调整显示的 Y 轴的跨度来执行此操作:
p = np.abs(a1_fft[1:]).max() * [-1.1, 1.1]
plt.ylim(p)
如果您已经在绘制绝对值,请使用
p = np.abs(a1_fft[1:]).max() * [-0.1, 1.1]
另一种方法是去除直流偏移。比 建议的更优雅的方法是不显示 DC 项:
plt.plot(freq[1:], a1_fft[1:])
或仅针对正频率:
n = freq.size
plt.plot(freq[1:n//2], a1_fft[1:n//2])
n // 2
处的截止值只是近似值。正确的截止点取决于 FFT 的元素数量是偶数还是奇数。对于偶数,中间 bin 实际具有来自频谱两侧的能量并且经常得到特殊处理。
我有一个时域振动数据,想用 fft
将其转换为频域数据。然而,FFT 图仅显示零处的大尖峰,除此之外什么都没有。
这是我的振动数据:https://pastebin.com/7RK57kJW
我的代码:
import numpy as np
import matplotlib.pyplot as plt
t = np.arange(3000)
a1_fft= np.fft.fft(a1, axis=0)
freq = np.fft.fftfreq(t.shape[-1])
plt.plot(freq, a1_fft)
我的 FFT 图:
我在这里做错了什么?我很确定我的数据是统一的,这在其他情况下会引发与 fft 类似的问题。
0 处的峰值是直流增益,它非常高,因为您没有对数据进行归一化。另外,傅里叶变换是一个复数,应该分别绘制绝对值和相位。在此代码中,我还仅绘制了正频率:
import numpy as np
import matplotlib.pyplot as plt
#Import data
a1 = np.loadtxt('a1.txt')
plt.plot(a1)
#Normalize a1
a1 -= np.mean(a1)
#Your code
t = np.arange(3000)
a1_fft= np.fft.fft(a1, axis=0)
freq = np.fft.fftfreq(t.shape[-1])
#Only plot positive frequencies
plt.figure()
plt.plot(freq[freq>=0], np.abs(a1_fft)[freq>=0])
FFT 的 bin 对应于 0, df, 2df, 3df, ..., F-2df, F-df
处的频率,其中 df
由 bin 的数量决定,F
是每个 bin 1 个周期。
注意开头的零频率。这称为直流偏移。这是你的数据的平均值。在您显示的数据中,平均值约为 1.32,而正弦波的幅度约为 0.04。您看不到比 DC 项小 33 倍的峰值也就不足为奇了。
有一些常用的可视化数据的方法可以帮助您解决这个问题。一种常见的方法是保持直流偏移但使用对数刻度,至少对于 y 轴:
plt.semilogy(freq, a1_fft)
或
plt.loglog(freq, a1_fft)
您可以做的另一件事是放大图的底部 1/33 左右。您可以手动执行此操作,也可以通过调整显示的 Y 轴的跨度来执行此操作:
p = np.abs(a1_fft[1:]).max() * [-1.1, 1.1]
plt.ylim(p)
如果您已经在绘制绝对值,请使用
p = np.abs(a1_fft[1:]).max() * [-0.1, 1.1]
另一种方法是去除直流偏移。比
plt.plot(freq[1:], a1_fft[1:])
或仅针对正频率:
n = freq.size
plt.plot(freq[1:n//2], a1_fft[1:n//2])
n // 2
处的截止值只是近似值。正确的截止点取决于 FFT 的元素数量是偶数还是奇数。对于偶数,中间 bin 实际具有来自频谱两侧的能量并且经常得到特殊处理。