Python FIR 陷波滤波器适用于 + 和 - 频率,但只需要 + 频率

信息处理 频谱 Python 有限脉冲响应 无限脉冲响应 复杂的
2022-02-03 10:56:53

我已经发布了我所看到的摘要,我只是制作了一个脉冲序列并在其上测试了一个陷波滤波器,仅作为示例。

我还有一个以 0 Hz 为中心的复杂基带信号,这个复杂的基带信号有一个仅在正频率上的复指数 - 这是我需要去除的干扰 - 因此陷波滤波器只去除正频率。我不能在这里发布这段代码,因为代码太多所以我发布了一个脉冲序列和一个陷波滤波器。

我的陷波滤波器适用于正频率和负频率。我不明白为什么在 scipy 中使用 iirfilter 和 lfilter 不能正确处理复杂信号。它将陷波应用于正频率和负频率,而不仅仅是一个。

我在这里想念什么?任何建议表示赞赏!

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

plt.close('all')

#Sampling
Fs = 40e3 # samples per second
Ts = 1/Fs
Ns = int(Fs)            #if =FS then resolution = 1
t = np.arange(Ns) * Ts # time vector for carrier 
fftsize = Ns #Full length FFT
resolution = Fs / fftsize
f = np.arange(-Fs/2, Fs/2,resolution)


#Pulses
pulse_span = 50
pulse_duration = pulse_span*Ts
data = np.random.randint(0,2,int(Ns/pulse_span))
data = (data - 0.5) 

x = np.zeros((Ns))
for i in range(len(data)):
    
    increment_low = i*pulse_span
    increment_high = increment_low + pulse_span
    x[increment_low:increment_high] = data[i]
    
    
#Filter Function
def Implement_Notch_Filter(time, band, freq, ripple, order, filter_type, data):
    from scipy.signal import iirfilter
    fs   = 1/time
    nyq  = fs/2.0
    low  = freq - band/2.0
    high = freq + band/2.0
    low  = low/nyq
    high = high/nyq
    b, a = signal.iirfilter(order, [low, high], rp=ripple, btype='bandstop',
                     analog=False, ftype=filter_type)
    filtered_data = signal.lfilter(b, a, data)
    return filtered_data
x = Implement_Notch_Filter(1/Fs,50,200,0.5,2,'butter',x)



#Spectrum
X = np.fft.fft(x,fftsize)/fftsize
X = np.fft.fftshift(X)
X = abs(X)
X_PSD = 10*np.log10(              abs((X))               **2)
    

fig = plt.figure(2)
ax = fig.add_subplot(111)
ax.title.set_text('Frequency: Spectrum dB ')
ax.plot(f,X_PSD)
plt.ylabel('Power (dBW/' + str(int(resolution)) + ' Hz)')
plt.xlabel('Frequency')
plt.ylim([-80, -20 ])

在此处输入图像描述

3个回答

任何实值系统,例如您的滤波器,在频谱上都是对称的。所以,你观察到的东西是不可避免的。这是真实信号在频谱上总是对称的事实的直接结果,真实系统无法从真实信号中生成复杂信号。

如果你需要一个单面过滤器,它需要很复杂。因此,无需设计具有两个陷波频率的真正陷波滤波器,您只需设计一个 DC 消除陷波滤波器 ( ) 并将其向上移动在频率方面(通过调制脉冲响应,但这并不像使用 FIR 那样容易使用 IIR 来完成,或者通过将信号向下移动、过滤然后向上移动——所有调制/移动都需要用复杂的正弦完成。±fnotchfnotch=0ejfshiftt

您也可以直接设计一个复杂的陷波滤波器,而不是一个实值滤波器。

这是设计复杂陷波 IIR 滤波器的一种方法

  1. 从真正的 IIR 滤波器开始,确定极点、零点和增益
  2. 去除负频率处的所有极点和零点,取增益的根
  3. 转回多项式并作为复数滤波器运行。

我不知道是否scipy.signal.iirfilter()支持复杂的滤波器系数,但 Matlabfilter()肯定支持。如果没有,那么编写自己的就很容易了。

如果你有一个高阶滤波器和/或靠近单位圆的极点,你可能想把它分成几个部分。由于您没有实际值约束,因此您不需要执行二阶部分,您可以简单地执行所有一阶部分:只需将任何极点与最接近的未使用零配对,然后按顺序应用极点/零对。

陷波滤波器是一个很好的选择,因为它在 Nyuist 是平坦的,所以你不会遇到由周期性重复引起的不连续性。高通或低通将是棘手的。

您也可以进行 FIR 设计。

  1. 设计实值 FFR
  2. 执行高分辨率 FFT
  3. 将所有负频率设置为 1
  4. 执行逆 FFT 并将实部和虚部窗口化到所需的长度/精度。

为什么不按照这些说明的第 20 页中的描述实现一个复杂的陷波滤波器。

不过滤方程。

这给出了以下频率响应。

频率响应示例。

您可能希望将 0.9 数字更改为更接近 1。而且我不清楚您要消除的频率是多少。


下面的代码

完整的 Jupyter Notebook 在这里。

# Page 20 of https://courses.engr.illinois.edu/ece401/fa2020/slides/lec14.pdf
import cmath
def Implement_Simple_Notch_Filter(time, freq, data):
    b = [1, -cmath.exp(1j*freq*time*2*3.13145926)]
    a = [1, -0.9*cmath.exp(1j*freq*time*2*3.13145926)]
    filtered_data = signal.lfilter(b, a, data)
    return filtered_data,b,a