简体   繁体   English

使用Python lfilter过滤信号

[英]Filtering signal with Python lfilter

I'm new with Python and I'm completely stuck when filtering a signal. 我是Python新手,在过滤信号时我完全陷入困境。 This is the code: 这是代码:

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

fs=105e6
fin=70.1e6

N=np.arange(0,21e3,1)

# Create a input sin signal of 70.1 MHz sampled at 105 MHz
x_in=np.sin(2*np.pi*(fin/fs)*N)

# Define the "b" and "a" polynomials to create a CIC filter (R=8,M=2,N=6)
b=np.zeros(97)
b[[0,16,32,48,64,80,96]]=[1,-6,15,-20,15,-6,1]
a=np.zeros(7)
a[[0,1,2,3,4,5,6]]=[1,-6,15,-20,15,-6,1]

w,h=signal.freqz(b,a)
plt.plot(w/max(w),20*np.log10(abs(h)/np.nanmax(h)))
plt.title('CIC Filter Response')

output_nco_cic=signal.lfilter(b,a,x_in)

plt.figure()        
plt.plot(x_in)
plt.title('Input Signal')
plt.figure()        
plt.plot(output_nco_cic)
plt.title('Filtered Signal')

And the plots: 和情节:

输入,滤波和输出信号

As you can see, although the filter transfer function is correct, the output isn't. 如您所见,虽然过滤器传递函数是正确的,但输出不是。 And I can't see why my code isn't working. 我无法理解为什么我的代码不起作用。 I've coded the same in Matlab and the output looks ok. 我在Matlab中编码相同,输出看起来还不错。

Thaks for the help! 多克斯寻求帮助!

I don't find it confusing that this didn't work with Python, but I do find it confusing that it worked with Matlab. 我不觉得这对Python不起作用感到困惑,但我发现它与Matlab一起工作令人困惑。

CIC filters don't work with floating point numbers. CIC过滤器不适用于浮点数。

UPDATE: 更新:

Interestingly, at least with the version of scipy I have, lfilter doesn't work with integer arrays -- I get a NotImplemented error. 有趣的是,至少我使用的scipy版本,lfilter不适用于整数数组 - 我得到一个NotImplemented错误。 Here is a numpy version of a CIC filter that is about twice as fast as a pure Python implementation on my machine: 这是一个CIC过滤器的numpy版本,大约是我机器上纯Python实现的两倍:

# Implements an in-memory CIC decimator using numpy.

from math import log
from numpy import int32, int64, array

def cic_decimator(source, decimation_factor=32, order=5, ibits=1, obits=16):

    # Calculate the total number of bits used internally, and the output
    # shift and mask required.
    numbits = order * int(round(log(decimation_factor) / log(2))) + ibits
    outshift = numbits - obits
    outmask  = (1 << obits) - 1

    # If we need more than 64 bits, we can't do it...
    assert numbits <= 64

    # Create a numpy array with the source
    result = array(source, int64 if numbits > 32 else int32)

    # Do the integration stages
    for i in range(order):
        result.cumsum(out=result)

    # Decimate
    result = array(result[decimation_factor - 1 : : decimation_factor])

    # Do the comb stages.  Iterate backwards through the array,
    # because we use each value before we replace it.
    for i in range(order):
        result[len(result) - 1 : 0 : -1] -= result[len(result) - 2 : : -1]

    # Normalize the output
    result >>= outshift
    result &= outmask
    return result

The code is fine, and lfilter works fine on the float64 arrays that it creates. 代码很好,lfilter在它创建的float64数组上工作正常。 But the denominator polynomial "a" has all its roots at z = 1, which makes the filter "conditionally stable". 但是分母多项式“a”的所有根都在z = 1,这使得滤波器“条件稳定”。 Due to numerically inaccuracy, it will eventually diverge. 由于数字上的不准确性,它最终会发生分歧。 And the input signal at 70.1 MHz is way outside the passband, so it doesn't show up much in the output. 并且70.1 MHz处的输入信号远离通带,因此它在输出中不会显示太多。 If you change the input to 0.701 MHz or thereabouts, and shorten the signal to 1000 samples instead of 21000, you'll see that it works as-is. 如果您将输入更改为0.701 MHz或其左右,并将信号缩短为1000个样本而不是21000,您将看到它按原样工作。 Try these changes and you'll see what happens after that: fin=70.1e4 N=np.arange(0,2000,1) (and to get rid of the divide by zero complaint, add 1.0e-12 inside the log10) 尝试这些更改,你会看到之后会发生什么:fin = 70.1e4 N = np.arange(0,2000,1)(并且为了摆脱除以0的投诉,在log10中添加1.0e-12)

To do a CIC right, you need an implementation that deals correctly with the conditionally stable poles. 要正确执行CIC,您需要一个能够正确处理条件稳定极点的实现。

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

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