簡體   English   中英

圖形帶通濾波器

[英]Band pass filter for Graph

我正在嘗試為我的圖表做一個帶通濾波器。 下面是我的代碼。 從黃油濾波器開始的代碼是我在嘗試執行帶通濾波器時添加的。 但是,出現的圖表似乎與我的原始圖表沒有什么不同。 我可以知道我錯過了什么嗎? 我的帶通濾波器編碼是否正確?

from scipy import misc
from scipy import signal
import scipy as sp


for column in df.columns:
    print(df.iloc[:, [1]])
    plt.figure('Train data: Jitter (Local)')
    plt.title('Feature: Jitter (Local)')
    plt.plot(df.iloc[:, [1]])
    plt.show()
    
    def butter_bandpass_filter(data, lowcut, highcut, fs, order=5):
        nyq = 0.5 * fs
        low = lowcut / nyq
        high = highcut / nyq
        b, a = butter(order, [low, high], btype='band', analog=True)
        y = lfilter(b, a, data)
        return y
    plt.show()

有兩個主要問題:1)您在循環中定義過濾 function ,但沒有調用它。 2)您正在設計一個模擬濾波器並像數字濾波器一樣使用它。

  1. 添加對過濾 function 的調用,例如: output = butter_bandpass_filter(data, lowcut, highcut, fs, order) 您需要替換所有這些參數的值。 在此之后我將提供一個大示例來演示它們的用法。

  2. 將模擬=真更改為模擬=假。 這樣,您將獲得 lfilter 工作所需的數字濾波器。 您還可以通過使用以 Hz 為單位的原始截止頻率並將 fs=fs 添加到您的 butter 命令來節省一些代碼行。 這也顯示在下面的示例中。 當您想在現實世界中設計濾波器時,會使用模擬濾波器設計,例如使用電阻器、電容器和電感器等分立元件時。

還有第三個問題,即您應該使用 SOS 系數以獲得更好的數值穩定性。 我在下面的示例中包含了它,因此您可以使用它並查看效果。 SciPy 建議您始終使用“sos”。

下面是我為你寫的一個小操場/沙盒代碼。 它在 f1 和 f2 Hz 處生成兩個正弦波,然后生成兩個帶通濾波器。 其中一個旨在提取 f1(和周圍頻率)和另一個 f2(和周圍頻率)。 我沒有在您的代碼中看到示例數據,所以我不確定您的數據框是如何設置的。

我鼓勵您嘗試的一件事是將 sos_mode=True 更改為 sos_mode=False (即使用“ba”系數)。 您會在第一個濾波器的帶通濾波器響應中看到,由於數值問題,它確實變得失真,而第二個濾波器很好。

如果您仍有疑問,請盡情享受並告訴我。 而且,是的,如果您不想查看過濾器響應而只想使用 SOS 模式,您可以從我寫的設計 function 中刪除很多代碼。

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

Fs = 10e3  #Sampling rate of 1kHz
Ts = 1./Fs # Sampling period is inverse of sampling rate

########### Generate Example Input 
#    I'll generate an input x that's composed of two sinusoids
#      at frequencies f1 and f2 that are defined from time=Tstart
#       to time=Tend
Tstart = -25e-3 # time to start
Tend = 125e-3   # time to end
t = np.arange(Tstart,Tend,Ts) # start, stop, step
f1 = 100 # frequency of first sinusoid
f2 = 400
x = np.sin(2 * np.pi * f1 * t) + np.sin(2 * np.pi * f2 * t)

########### Filter Design Function
#     Just design a filter - don't actually filter
def design_butter_bandpass_filter(lowcut, highcut, Fs, order=5, sos_mode=True, view_it=True):
    # The digital filter design that you need for lfilter
    #  the parameter fs=Fs lets us skip the manual Hz -> rad/s conversion
    if sos_mode:
      sos_digital = signal.butter(order, [lowcut, highcut], btype='band', fs=Fs, analog=False, output='sos')
    else:
      b_digital, a_digital = signal.butter(order, [lowcut, highcut], btype='band', fs=Fs, analog=False, output='ba')

    if view_it:
      if sos_mode:
        w, h = signal.sosfreqz(sos_digital, fs=Fs, worN=range(lowcut * 3 // 4,highcut * 5 // 4))
      else:
        w, h = signal.freqz(b_digital, a_digital, fs=Fs, worN=range(lowcut * 3 // 4,highcut * 5 // 4))
      plt.semilogx(w, 20 * np.log10(abs(h)))
      plt.title('Butterworth filter frequency response ' + 'SOS mode' if sos_mode else 'BA mode')
      plt.xlabel('Frequency [radians / second]')
      plt.ylabel('Amplitude [dB]')
      plt.margins(0, 0.1)
      plt.grid(which='both', axis='both')
      plt.axvline(lowcut, color='green') # lower cutoff frequency
      plt.axvline(highcut, color='green') # upper cutoff frequency
      plt.show()

    if sos_mode:
      return sos_digital
    else:
      return (b_digital, a_digital)


########### Filter Design using the Filter Design Function

# Common parameters
filter_order = 5
sos_mode = True

# Design a filter to extract the first sinusoid.  You only need to do this once, unless the cutoffs or order change
lower_cutoff1 = f1 - 50
upper_cutoff1 = f1 + 50
filt1 = design_butter_bandpass_filter(lower_cutoff1, upper_cutoff1, Fs, filter_order, sos_mode)

# Design a filter to extract the second sinusoid.  You only need to do this once, unless the cutoffs or order change
lower_cutoff2 = f2 - 50
upper_cutoff2 = f2 + 50
filt2 = design_butter_bandpass_filter(lower_cutoff2, upper_cutoff2, Fs, filter_order, sos_mode)


########### Signal Filtering

# Filter the signal using your filter coefficients
if sos_mode:
  y1 = signal.sosfilt(filt1, x)
  y2 = signal.sosfilt(filt2, x)
else:
  y1 = signal.lfilter(filt1[0], filt1[1], x)
  y2 = signal.lfilter(filt2[0], filt2[1], x)


########### Plotting

# Plot the data
fig, ax = plt.subplots(3,1);
fig.tight_layout()
ax0 = ax[0]
ax0.set_title(f'Input Signal - sinusoids at {f1} Hz and {f2} Hz')
ax0.plot(t,x)

ax1 = ax[1]
ax1.set_title(f'Filtered Signal - bandpass filtered from {lower_cutoff1} Hz to {upper_cutoff1} Hz')
ax1.plot(t,y1)

ax2 = ax[2]
ax2.set_title(f'Filtered Signal - bandpass filtered from {lower_cutoff2} Hz to {upper_cutoff2} Hz')
ax2.plot(t,y2)
plt.show()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM