简体   繁体   English

如何在 python 中将频域转换为时域

[英]How to convert from frequency domain to time domain in python

I know this is basic for signal processing, but, I am not sure what is wrong about my approach.我知道这是信号处理的基础,但是,我不确定我的方法有什么问题。 I have a signal that behaves as damped sine signal with a sampling frequency of 5076Hz and 15,000 number of samples.我有一个信号表现为阻尼正弦信号,采样频率为 5076Hz,样本数为 15,000。 I found from the following website how to convert a signal from a time domain to frequency domain and managed to get the FFT and frequency values.我从以下网站找到了如何将信号从时域转换为频域并设法获得 FFT 和频率值。 The code can be found below the link:代码可以在下面的链接中找到:

Machine Learning with Signal Processing Techniques 使用信号处理技术进行机器学习

def get_fft_values(y_values, T_s, N, f_s):
    f_values = np.linspace(0.0, 1.0/(2.0*T), N//2)
    fft_values_ = np.fft.rfft(y_values)
    fft_values = 2.0/N * np.abs(fft_values_[0:N//2])
    return f_values, fft_values

I managed to get the frequency and FFT values.我设法获得了频率和 FFT 值。 However, I need to implement filters to remove some noise from the signal, so, I created the following functions to implement the filter part:但是,我需要实现滤波器来去除信号中的一些噪声,因此,我创建了以下函数来实现滤波器部分:

def butter_bandpass(lowcut, highcut, fs, order):
    nyq = 0.5 * fs
    low = lowcut / nyq
    high = highcut / nyq
    b, a = butter(order, [low, high], btype='bandpass', output='ba')
    return b, a

def butter_bandpass_filter(data, lowcut, highcut, fs, order):
    b, a = butter_bandpass(lowcut, highcut, fs, order=order)
    y = filtfilt(b=b, a=a, x=data)
    # y = lfilter(b=b, a=a, x=data)
    return y

I know that I would need to implement the following steps:我知道我需要执行以下步骤:

  • Convert to the frequency domain转换为频域
  • apply a bandpass filter to get rid of frequencies you don't care about应用带通滤波器以消除您不关心的频率
  • convert back to the time domain by inverse Fourier transform通过傅里叶逆变换转换回时域

So, I created the following inverse transform function, but, I can't get the filtered signal back and the amplitudes don't almost match the original signal.因此,我创建了以下逆变换 function,但是,我无法恢复滤波后的信号,并且幅度与原始信号几乎不匹配。 (For my case, I need to resample) (对于我的情况,我需要重新采样)

def get_ifft_values(fft_values, T, N, f_s):
    # Time axis:
    N = 9903
    S_T = 1 / S_F
    t_n = S_T * N  # seconds of sampling
    # Obtaining data in order to plot the graph:
    x_time = np.linspace(0, t_n, N)
    ifft_val = np.fft.irfft(fft_values, n=N)
    y_s, x_time = scipy.signal.resample(x=ifft_val, num=N, t=x_time)
    return x_time, y_s

What am I doing wrong here?我在这里做错了什么?

Edit 1:编辑1:

Based on the answer from @Han-Kwang Nienhuys.基于@Han-Kwang Nienhuys 的回答。 I edited the above code and applied it to the approach below:我编辑了上面的代码并将其应用于以下方法:

##### Converting the signal into fft:
f_val, fft_val = get_fft_values(y_values=y, T=S_T, N=N, f_s=S_F)
# Applying bandpass filter:
fft_filt_val = butter_bandpass_filter(data=fft_val, lowcut=50, highcut=600, fs=S_F, order=2)
# Applying the inverse transform of the frequency domain:
x_time, y = get_ifft_values(fft_values=fft_filt_val, T=S_T, N=N, f_s=S_F)

Here are the results from the signal:以下是信号的结果:

  • FFT of the original signal:原始信号的 FFT:

原始信号的 FFT

  • Filtered FFT of the original signal:原始信号的滤波 FFT:

从 FFT 值过滤 FFT

  • Converted Signal from Filtered FFT:从滤波 FFT 转换的信号:

从滤波 FFT 转换的信号

  • Without Applying the bandpass filter:不应用带通滤波器:

不应用带通滤波器

There are several issues:有几个问题:

  • You are using np.fft.fft , which is a complex-valued discrete Fourier transform, containing frequencies up to twice the Nyqvist frequency.您正在使用np.fft.fft ,它是一个复值离散傅立叶变换,包含的频率高达 Nyqvist 频率的两倍。 The frequencies above the Nyqvist frequency can be interpreted equivalently as negative frequencies.高于 Nyqvist 频率的频率可以等效地解释为负频率。 You are indeed using a frequency slice [:N//2] , but if you want the inverse transform to work, you also need to deal with the other half of the spectrum.您确实在使用频率切片[:N//2] ,但是如果您希望逆变换起作用,您还需要处理频谱的另一半。
  • Don't take the absolute values of the FFT data.不要取 FFT 数据的绝对值。 The filter must operate on the complex-valued coefficients.滤波器必须对复值系数进行操作。
  • If you use scipy.signal.filtfilt : that function operates on time-domain data, not on frequency-domain data.如果您使用scipy.signal.filtfilt : function 对时域数据进行操作,而不是对频域数据进行操作。

For real-valued input data, it's much easier to use a real-valued FFT, which will behave more like you expect:对于实值输入数据,使用实值 FFT 要容易得多,它的行为更像您的预期:

n = len(y)
yf = np.fft.rfft(y)
fstep = f_sampling / n
freqs = np.arange(len(yf)) * fstep

To transform back, use np.fft.irfft .要转换回来,请使用np.fft.irfft

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM