Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python的意外FFT结果_Python_Numpy_Scipy_Fft_Dft - Fatal编程技术网

Python的意外FFT结果

Python的意外FFT结果,python,numpy,scipy,fft,dft,Python,Numpy,Scipy,Fft,Dft,我在分析呼吸波形,它有3种不同的形状(数据来源于核磁共振成像,所以使用了多次回波;看看你是否想要一些快速的背景)。以下是在某些情况下绘制的两个波形的两段: 对于每一个波形,我都会尝试进行DFT,以发现呼吸的主频 我的问题是,当我绘制我执行的DFT时,我会得到两件事中的一件,这取决于我使用的FFT库。此外,它们都不能代表我的期望。我知道数据并非总是按照我们想要的方式显示,但我的数据中显然存在波形,因此我希望离散傅里叶变换能够在合理的地方产生频率峰值。作为这里的参考,我期望大约80到130赫兹 我

我在分析呼吸波形,它有3种不同的形状(数据来源于核磁共振成像,所以使用了多次回波;看看你是否想要一些快速的背景)。以下是在某些情况下绘制的两个波形的两段:

对于每一个波形,我都会尝试进行DFT,以发现呼吸的主频

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

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

SciPy(
fftpack

努比:

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)

是指向用于创建这些绘图的数据集(在Dropbox上)的链接,也是指向Jupyter笔记本的链接

编辑:

我使用了发布的建议,获取了数据的大小(绝对值),并用对数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()

我已经解决了我的问题

非常有帮助,这有助于我确定如何正确缩放频率箱并适当绘制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()

实际上是在你发布之前捕捉到的。在编辑中修复。非常感谢。输入序列的平均值是多少?曲线图显示的值约为0.99,但纵轴标签上显示“标准化”。图是否代表传递给FFT函数的实际数据?使用傅里叶变换,您通常对实部和虚部不感兴趣(除非您实际需要相位信息)。所以你应该考虑复杂值的大小。这是给定频率下的“能量”,这将帮助您确定哪些频率对信号贡献最大。另一件事是信号有一个平均值,因此零频率,即常数,是重要的,并支配其他频率的贡献。要么减去信号的平均值,要么使用对数刻度。附带问题。。。您所指的链接是否提供了与上面绘制的类似的示例数据集文件?@ScottStensland可能没有;我的数据集来自专有的MR扫描仪。如果有帮助的话,我可以提供给你
# 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()