Inverse filtering using Python

2024/10/11 18:16:25

Given an impulse response h and output y (both one-dimensional arrays), I'm trying to find a way to compute the inverse filter x such that h * x = y, where * denotes the convolution product.

For example, suppose that the impulse response h is [1,0.5], and the output is a step function (that is, consists of all 1s). One can figure out that the first coefficients should be [1, 0.5, 0.75], which yields an output of [1, 1, 1, 0.375]. The last term contains an error, but this is not really an issue as I'm only concerned with the output up to a certain maximum time.

I would like to automate and 'scale up' this inverse filtering to a longer, more complex impulse response function. So far, the only way I've figured out to get the coefficients is by generating the series expansion of the Z-transform using sympy. (Note that the Z-transform of a step function is 1/(1-z)).

However, I've noticed that sympy is quite slow in computing the coefficients: it takes 0.8 seconds even for a simple, short example, as demonstrated by the script below:

import numpy as np
from scipy import signal
from sympy import Symbol, series
import timeh = np.array([1,0.5])           # Impulse response function
y = np.array([1,1,1,1,1])       # Ideal output is a step functionmy_x = np.array([1,0.5,0.75])   # Inverse filter response (calculated manually)my_y = signal.convolve(h,my_x)  # Actual output (should be close to ideal output)print(my_y)start = time.time()
z = Symbol('z')
print(series(1/((1-z)*(1+z/2)),z))
end = time.time()
print("The power series expansion took "+str(end - start)+" seconds to complete.")

This produces the output:

[ 1.     1.     1.     0.375]
1 + z/2 + 3*z**2/4 + 5*z**3/8 + 11*z**4/16 + 21*z**5/32 + O(z**6)
The power series expansion took 0.798881053925 seconds to complete.

In short, the coefficients of the power expansion match the desired filter response, but it seems cumbersome to me to use sympy to do this. Is there a better way to compute inverse filter coefficients in Python?

Answer

This is called deconvolution: scipy.signal.deconvolve will do this for you. Example where you know the original input signal x:

import numpy as np
import scipy.signal as signal# We want to try and recover x from y, where y is made like this:
x = np.array([0.5, 2.2, -1.8, -0.1])
h = np.array([1.0, 0.5])
y = signal.convolve(x, h)# This is called deconvolution:
xRecovered, xRemainder = signal.deconvolve(y, h)
# >>> xRecovered
# array([ 0.5,  2.2, -1.8, -0.1])
# >>> xRemainder
# array([  0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
#          0.00000000e+00,  -1.38777878e-17])# Check the answer
assert(np.allclose(xRecovered, x))
assert(np.allclose(xRemainder, 0))

It sounds like you don’t know the original signal, so your xRemainder will not be 0 to machine precision—it’ll represent noise in the recorded signal y.

https://en.xdnf.cn/q/69747.html

Related Q&A

Quadruple Precision Eigenvalues, Eigenvectors and Matrix Logarithms

I am attempting to diagonalize matrices in quadruple precision, and to take their logarithms. Is there a language in which I can accomplish this using built-in functions?Note, the languages/packages i…

How to use pyinstaller with pipenv / pyenv

I am trying to ship an executable from my python script which lives inside a virtual environment using pipenv which again relies on pyenv for python versioning. For that, I want to us pyinstaller. Wha…

Sending DHCP Discover using python scapy

I am new to python and learning some network programming, I wish to send an DHCP Packet through my tap interface to my DHCP server and expecting some response from it. I tried with several packet build…

cnf argument for tkinter widgets

So, Im digging through the code here and in every class (almost) I see an argument cnf={} to the constructor, but unless Ive missed it, it is not explicitly stated what cnf is / expected to contain. Ca…

python exceptions.UnicodeDecodeError: ascii codec cant decode byte 0xa7 in

I am using scrapy with python and I have this code in a python item piplinedef process_item(self, item, spider):import pdb; pdb.set_trace()ID = str(uuid.uuid5(uuid.NAMESPACE_DNS, item[link]))I got this…

Trace Bug which happends only sometimes in CI

I have a strange bug in python code which only happens sometimes in CI.We cant reproduce it.Where is the test code:response=self.admin_client.post(url, post) self.assertEqual(200, response.status_code,…

Limit neural network output to subset of trained classes

Is it possible to pass a vector to a trained neural network so it only chooses from a subset of the classes it was trained to recognize. For example, I have a network trained to recognize numbers and l…

Unable to fully remove border of PyQt QGraphicsView

I have tried calling self.setStyleSheet("background: transparent; border: transparent;") on a QGraphicsView, but it still leaves a 1 pixel border on the top edge. I have also tried replacing …

SqlAlchemy non persistent column

I am trying to define a model using sqlalchemy such that one of the columns i only need in memory for processing, i do not have a corresponding database column for that. I need it such that when i save…

Creating command line alias with python

I want to create command line aliases in one of my python scripts. Ive tried os.system(), subprocess.call() (with and without shell=True), and subprocess.Popen() but I had no luck with any of these me…