signal pass lowpass low iir help filtro and python scipy filtering signal-processing

python - pass - scipy help



Filtrando la seƱal con Python lfilter (2)

No me parece confuso que esto no funcione con Python, pero me resulta confuso que funcionó con Matlab.

Los filtros CIC no funcionan con números de coma flotante.

ACTUALIZAR:

Curiosamente, al menos con la versión de scipy que tengo, lfilter no funciona con matrices de enteros, obtengo un error NotImplemented. Aquí hay una versión numpy de un filtro CIC que es aproximadamente el doble de rápido que una implementación pura de Python en mi máquina:

# 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

Soy nuevo con Python y estoy completamente atascado al filtrar una señal. Este es el código:

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'')

Y las tramas:

Como puede ver, aunque la función de transferencia de filtro es correcta, la salida no lo es. Y no puedo ver por qué mi código no funciona. He codificado lo mismo en Matlab y la salida se ve bien.

Thaks por la ayuda!


El código está bien, y lfilter funciona bien en las matrices float64 que crea. Pero el denominador polinomial "a" tiene todas sus raíces en z = 1, lo que hace que el filtro sea "condicionalmente estable". Debido a la inexactitud numérica, eventualmente divergerá. Y la señal de entrada a 70.1 MHz está muy por fuera de la banda de paso, por lo que no aparece mucho en la salida. Si cambia la entrada a 0.701 MHz o menos, y acorta la señal a 1000 muestras en lugar de 21000, verá que funciona tal como está. Pruebe estos cambios y verá lo que sucede después: fin = 70.1e4 N = np.arange (0,2000,1) (y para deshacerse de la división por cero, agregue 1.0e-12 dentro del log10)

Para hacer un CIC correcto, necesita una implementación que maneje correctamente los polos condicionalmente estables.