将滤波器系数存储在 python 中

Storing filter coefficients in python

我有一个 python 文件,它从 ECG 设备获取实时数据,并将其发送到网站。 ECG 设备的采样频率为 200 Hz,python 代码每秒获取此数据。我想过滤这些数据,所以对于每批(1 秒)我调用另一个包含我的过滤器的 python 文件。每个过滤器都有一些系数,例如从 scipy.signal.butter(order, norm_cut, btype='low', analog=False, output='ba') 中找到的系数,但系数将始终保持不变。所以我的问题是,有没有办法将这些系数作为全局变量存储在文件中?所以它不会在它被调用的每一秒都计算这些。

代码结构是这样的: Main.py

from filters import ecgfilter
while True:
    raw = fetch_data()
    cleaned = ecgfilter(raw, fs=200)
    send2web(cleaned)

filters.py

def butterLowpass(cutoff:float, fs:float, order=5)->np.ndarray:
    norm_cut = cutoff/(0.5*fs)
    b, a = signal.butter(order, norm_cut, btype='low', analog=False, output='ba')
    return b, a

def lowpassFilter(data, cutoff:float, fs:float, order=5):
    b, a = butterLowpass(cutoff, fs, order)
    filtered = signal.lfilter(b,a,data)
    return filtered

def butterHighpass(cutoff:float, fs:float, order=5)->np.ndarray:
    
    norm_cut = cutoff/(0.5*fs)
    b, a = signal.butter(order, norm_cut, btype='high', analog=False, output='ba')
    return b, a

def highpassFilter(data, cutoff:float, fs:float, order=5):
    b, a = butterHighpass(cutoff, fs, order)
    filtered = signal.lfilter(b,a,data)
    return filtered
def notchFilter(cutoff:float, fs:float, Q:float):
    norm_cut = cutoff/(0.5*fs)
    b, a = signal.iirnotch(norm_cut, Q)
    return b, a

def notch(data, powerline_freq:float, fs:float, Q:float):
    b, a = notchFilter(powerline_freq, fs, Q)
    signal = signal.lfilter(b,a,data)
    return signal

def ecgfilter(raw, Fs=200.0):
    data = raw
    high_filt = highpassFilter(signal, cutoff=0.5, fs=Fs)
    loHi = lowpassFilter(high_filt, cutoff=40.0, fs=Fs)
    filtered = notch(loHi,50.0, Fs, 25)
    return filtered

如您所见,b,我要存储的系数,a 最小化调用。想将它们存储在一个文件中,但仍然会导致很多调用。

注意:Ofc 我本可以获取更大批量的数据,但重点是将这些数据实时流式传输到网站,这样它看起来就不会连续了。

您可以将滤波器系数存储在 file-level 全局变量中(示例如下)。

我建议使用 SOS-form 而不是 ba-form; SOS-form 具有更好的数值属性。

如果您正在处理 1s 块中的数据,但您没有删除任何数据,请查看初始条件输入和(对应的“最终条件”输出)以lfilter and sosfilt

代码存储系数示例:

import numpy as np
from scipy import signal


FSAMPLE = 200 # Hz
LOW_CUT = 40 # Hz
LOW_ORDER = 5
_LOWSOS = signal.butter(LOW_ORDER,
                        LOW_CUT/(0.5*FSAMPLE),
                        output='sos')


def lowpassfilter(raw, Fs=200.0):
    return signal.sosfilt(_LOWSOS, raw)