我试图用Python对一个信号应用一个具有时间变化的截止频率的带通滤波器。我目前使用的程序是将我的信号分成等长的时间段,然后对每个时间段应用一个具有特定时间参数的滤波器,然后再将信号合并起来。这些参数是基于预先存在的估计。
我遇到的问题是,在每个时间段的边缘有 "波纹",是在应用滤波器后出现的。这导致我的信号出现不连续,干扰了我的滤波后数据分析。
我希望有人能告诉我,在Python中是否有任何现有的程序来实现具有时变参数的过滤器?另外,如果有关于如何解决这个问题的建议,我将非常感激。
EDIT -- 我想做的事情的例子补充如下。
假设我有一个信号x(t)。我想用一个参数为(100,200)Hz的带通滤波器来过滤前半部分。后半部分我想用参数(140,240)Hz来过滤。我对x(t)进行迭代,将我的滤波器应用于每一半,然后将结果重新组合。一些示例代码可能看起来像。
outputArray = np.empty(len(x))
segmentSize = len(x) / 2
filtParams = [(100, 200), (140, 240)]
for i in range(2):
tempData = x[i*segmentSize:(i+1)*segmentSize]
tempFiltered = bandPassFilter(tempData, parameters=filtParams[i])
outputArray[i*segmentSize:(i+1)*segmentSize] = tempFiltered
(为了节省篇幅,我们假设我有一个进行带通滤波的函数)。
正如你所看到的,这些数据段没有重叠,只是被 "粘贴 "回新的数组中。
EDIT 2-- 我的问题的一些示例代码 @H.D.
首先,感谢你到目前为止的重要投入。audiolazy软件包看起来是一个伟大的工具。
我想如果我进一步详细描述我的目标,会更有用一些。正如我已经发布的elsewhere,我正试图提取瞬时频率(使用希尔伯特变换,对一个信号的中频(IF)进行测量。我的数据含有大量的噪声,但我对中频信号所在的带宽有一个很好的估计。然而,我遇到的一个问题是
中频往往是非稳态的。因此,使用 "静态 "滤波器的方法,我经常需要使用一个宽的带通区域,以确保所有的频率都被捕获。
下面的代码演示了增加滤波器带宽对中频信号的影响。它包括一个信号生成函数,一个使用scipy.signal包的带通滤波器的实现,以及一个提取所得滤波信号中频的方法。
from audiolazy import *
import scipy.signal as sig
import numpy as np
from pylab import *
def sineGenerator( ts, f, rate, noiseLevel=None ):
"""generate a sine tone with time, frequency, sample rate and noise specified"""
fs = np.ones(len(ts)) * f
y = np.sin(2*np.pi*fs*ts)
if noiseLevel: y = y + np.random.randn(len(y))/float(noiseLevel)
return y
def bandPassFilter( y, passFreqs, rate, order ):
"""STATIC bandpass filter using scipy.signal Butterworth filter"""
nyquist = rate / 2.0
Wn = np.array([passFreqs[0]/nyquist, passFreqs[1]/nyquist])
z, p, k = sig.butter(order, Wn, btype='bandpass', output='zpk')
b, a = sig.zpk2tf(z, p, k)
return sig.lfilter(b, a, y)
if __name__ == '__main__':
rate = 1e4
ts = np.arange(0, 10, 1/rate)
# CHANGING THE FILTER AFFECTS THE LEVEL OF NOISE
ys = sineGenerator(ts, 600.0, 1e4, noiseLevel=1.0) # a 600Hz signal with noise
filts = [[500, 700], [550, 650], [580, 620]]
for f in filts:
tempFilt = bandPassFilter( ys, f, rate, order=2 )
tempFreq = instantaneousFrequency( tempFilt, rate )
plot( ts[1:], tempFreq, alpha=.7, label=str(f).strip('[]') )
ylim( 500, 750 )
xlabel( 'time' )
ylabel( 'instantaneous frequency (Hz)' )
legend(frameon=False)
title('changing filter passband and instantaneous frequency')
savefig('changingPassBand.png')
在这个例子中,我被迫使用了一个更宽的带通滤波器,这导致了额外的噪声悄悄进入中频数据。
我的想法是,通过使用一个时间变化的滤波器,我可以在某些时间增量上为我的信号 "优化 "滤波器。因此,对于上述信号,我可能想在前5秒过滤580-620Hz,然后在后5秒过滤630-670Hz。从本质上讲,我想尽量减少最终中频信号的噪音。
根据你发送的示例代码,我写了一个函数,使用audiolazy在信号上实现一个静态巴特沃斯滤波器。
def audioLazyFilter( y, rate, Wp, Ws ):
"""implement a Butterworth filter using audiolazy"""
s, Hz = sHz(rate)
Wp = Wp * Hz # Bandpass range in rad/sample
Ws = Ws * Hz # Bandstop range in rad/sample
order, new_wp_divpi = sig.buttord(Wp/np.pi, Ws/np.pi, gpass=dB10(.6), gstop=dB10(.1))
ssfilt = sig.butter(order, new_wp_divpi, btype='bandpass')
filt_butter = ZFilter(ssfilt[0].tolist(), ssfilt[1].tolist())
return list(filt_butter(y))
使用这个滤波器与希尔伯特变换例程一起获得的中频数据与使用scipy.signal获得的数据相比,效果很好。
AL_filtered = audioLazyFilter( ys, rate, np.array([580, 620]), np.array([570, 630]) )
SP_filtered = bandPassFilter( ys, [580, 620], rate, order=2 )
plot(ts[1:], instantaneousFrequency( SP_filtered, 1e4 ), alpha=.75, label='scipy.signal Butterworth filter')
plot(ts[1:], instantaneousFrequency( AL_filtered, 1e4 ), 'r', alpha=.75, label='audiolazy Butterworth filter')
我的问题是,现在我可以将audiolazy Butterworth程序与你在原帖中描述的时变特性结合起来吗?