【问题标题】:Unexpected FFT Results with PythonPython 的意外 FFT 结果
【发布时间】:2018-12-28 00:19:07
【问题描述】:

我正在分析本质上是呼吸波形,以 3 种不同的形状构造(数据来自 MRI,因此使用了多个回波时间;如果您想了解一些快速背景知识,请参阅 here)。以下是在某些情况下绘制的两个波形的几个片段:

对于每个波形,我都在尝试执行 DFT 以发现主要频率或呼吸频率。

我的问题是,当我绘制我执行的 DFT 时,我会得到两件事之一,这取决于我使用的 FFT 库。此外,它们都不能代表我的预期。我知道数据并不总是我们想要的样子,但我的数据中显然存在波形,所以我希望是离散的傅里叶变换以在合理的地方产生频率峰值。作为参考,我预计大约 80 到 130 Hz。

我的数据存储在pandas 数据框中,每个回显时间的数据都在一个单独的系列中。我正在应用选择的 FFT 函数(参见下面的代码)并为每个函数接收不同的结果。

SciPy (fftpack)

import pandas as pd
import scipy.fftpack

# temporary copy to maintain data structure
lead_pts_fft_df = lead_pts_df.copy()

# apply a discrete fast Fourier transform to each data series in the data frame
lead_pts_fft_df.magnitude = lead_pts_df.magnitude.apply(scipy.fftpack.fft)
lead_pts_fft_df

NumPy:

import pandas as pd
import numpy as np 

# temporary copy to maintain data structure
lead_pts_fft_df = lead_pts_df.copy()

# apply a discrete fast Fourier transform to each data series in the data frame
lead_pts_fft_df.magnitude = lead_pts_df.magnitude.apply(np.fft.fft)
lead_pts_fft_df

其余相关代码:

ECHO_TIMES = [0.080, 0.200, 0.400] # milliseconds

f_s = 1 / (0.006) # 0.006 = time between samples
freq = np.linspace(0, 29556, 29556) * (f_s / 29556) # (29556 = length of data)

# generate subplots
fig, axes = plt.subplots(3, 1, figsize=(18, 16))

for idx in range(len(ECHO_TIMES)):
    axes[idx].plot(freq, lead_pts_fft_df.magnitude[idx].real, # real part
                   freq, lead_pts_fft_df.magnitude[idx].imag, # imaginary part

    axes[idx].legend() # apply legend to each set of axes

# show the plot
plt.show()

DFT 后 (SciPy fftpack):

后 DFT (NumPy)

Here 是指向用于创建这些图的数据集(在 Dropbox 上)的链接,here 是指向 Jupyter Notebook 的链接。

编辑:

我使用了发布的建议并获取了数据的大小(绝对值),并且还绘制了对数 y 轴。新结果发布在下面。看来我的信号中有一些环绕。我没有使用正确的频率刻度吗?更新后的代码和图表如下。

# generate subplots
fig, axes = plt.subplots(3, 1, figsize=(18, 16))

for idx in range(len(ECHO_TIMES)):
    axes[idx].plot(freq[1::], np.log(np.abs(lead_pts_fft_df.magnitude[idx][1::])),
                   label=lead_pts_df.index[idx], # apply labels
                   color=plot_colors[idx]) # colors
    axes[idx].legend() # apply legend to each set of axes

# show the plot
plt.show()

【问题讨论】:

  • 实际上在您发布之前就发现了这一点。在编辑中修复。谢谢!
  • 输入序列的平均值是多少?这些图显示的值约为 0.99,但垂直轴标签显示“标准化”。图是否代表传递给 FFT 函数的实际数据?
  • 使用傅里叶变换,您通常对实部和虚部不感兴趣(除非您确实需要相位信息)。所以你应该考虑复数值的大小。这是给定频率的“能量”,它将帮助您确定哪些频率对信号的贡献最大。另一件事是信号具有平均值,因此零频率(即常数)很重要,并且主导其他频率的贡献。减去信号的平均值或使用对数 y 尺度。
  • 附带问题...您引用的链接 mriquestions.com 是否提供类似于您在上面绘制的示例数据集文件?
  • @ScottStensland 可能没有;我的数据集来自专有的 MR 扫描仪。如果有帮助,我可以提供给您

标签: python numpy scipy fft dft


【解决方案1】:

我已经解决了我的问题。

Cris Luengothis link 非常有帮助,它帮助我确定了如何正确缩放频率区间并适当地绘制 DFT。

另外:我忘记考虑信号中存在的偏移量。它不仅会导致 DFT 中 0 Hz 处的巨大峰值出现问题,而且它也是转换信号中大部分噪声的原因。我利用scipy.signal.detrend() 消除了这个问题,得到了一个非常合适的 DFT。

# import DFT and signal packages from SciPy
import scipy.fftpack
import scipy.signal

# temporary copy to maintain data structure; original data frame is NOT changed due to ".copy()"
lead_pts_fft_df = lead_pts_df.copy()

# apply a discrete fast Fourier transform to each data series in the data frame AND detrend the signal
lead_pts_fft_df.magnitude = lead_pts_fft_df.magnitude.apply(scipy.signal.detrend)
lead_pts_fft_df.magnitude = lead_pts_fft_df.magnitude.apply(np.fft.fft)
lead_pts_fft_df

相应地安排频率区间:

num_projections = 29556
N = num_projections
T = (6 * 3) / 1000 # 6*3 b/c of the nature of my signal: 1 pt for each waveform collected every third acquisition
xf = np.linspace(0.0, 1.0 / (2.0 * T), num_projections / 2)

然后绘制:

# generate subplots
fig, axes = plt.subplots(3, 1, figsize=(18, 16))

for idx in range(len(ECHO_TIMES)):
    axes[idx].plot(xf, 2.0/num_projections * np.abs(lead_pts_fft_df.magnitude[idx][:num_projections//2]),
                   label=lead_pts_df.index[idx], # apply labels
                   color=plot_colors[idx]) # colors
    axes[idx].legend() # apply legend to each set of axes

# show the plot
plt.show()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-15
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 2017-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多