# Impulse Invariant Transformation with Python

One of several technique of designing a digital IIR(Infinite Impulse Response) filter from an analog filter is Impulse Invariant Transformation. The basic idea behind IIT is to equate the impulse response of the analog filter with that of the digital filter. This is achieved by sampling the impulse response of the analog filter at a certain sampling rate and then scaling it appropriately to obtain the impulse response of the digital filter. Once the impulse response is obtained, it can be transformed back into the frequency domain to obtain the digital filter's frequency response. The IIT method has some limitations, such as it can only be applied to stable analog filters, and the resulting digital filter's frequency response may deviate significantly from the analog filter's frequency response at high frequencies. Nonetheless, IIT is a popular and simple method for designing digital filters from analog filters.

An analog filter described by Laplace transform is,

$$H(s) = \sum_{i=1}^{N}\frac{A_i}{s-p_i}$$    --->(1)

or, $$H(s) =\frac{A_1}{s-p_1} + \frac{A_2}{s-p_2} +\frac{A_3}{s-p_3} +....+\frac{A_N}{s-p_N}$$

where $$A_i = A_1, A_2...A_N$$ are the coefficients of partial fraction expansion and $$p_i = p_1, p_2...p_N$$ are the poles.

Also $$s=\sigma +j\Omega$$ is the Laplace operator.  $$\sigma$$ is the attenuation factor and $$\Omega$$ is the analog frequency.

A digital IIR filter is obtained using the following substitution.

$$\frac{1}{s-p_i} = \frac{1}{1-e^{p_i T}z^{-1}}$$ --->(2)

After transformation the digital filter transfer function is,

$$H(z) = \sum_{i=1}^{N}\frac{A_i}{1-e^{p_i T}z^{-1}}$$    --->(3)

The digital filter is represented in Z-Transform notation.

Impulse Invariant Transformation with Python Program

The python program code below is an implementation of an analog to digital filter using the impulse invariant transformation method. The filter being transformed is a second-order low-pass filter, H(s) = 2 / (s^2 + 3s + 2), with a sampling frequency of fs = 1 Hz.

  import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import cont2discrete, zpk2tf, tf2sos, sosfreqz, sos2zpk

# Analog filter, H(s) = 2 / (s^2 + 3s + 2)
b = np.array([2])  # numerator coeff of analog filter
a = np.array([1, 3, 2])  # denominator coeff of analog filter
fs = 1  # sampling frequency

# Impulse invariant transformation
dt = 1/fs
num_d, den_d, _ = cont2discrete((b, a), dt)

# Convert to numerator/denominator form
bz, az = zpk2tf([], np.roots(den_d), num_d)

# Convert to second-order sections form
sos = tf2sos(bz, az)

# Plot frequency response of digital filter H(z)
w, h = sosfreqz(sos)
plt.plot(w/np.pi, np.abs(h))
plt.title('Frequency Response of Low-Pass Filter')
plt.ylabel('Magnitude')
plt.show()

# Plot zero and poles of the filter
z, p, k = sos2zpk(sos)
plt.plot(np.real(z), np.imag(z), 'o', label='Zeros')
plt.plot(np.real(p), np.imag(p), 'x', label='Poles')
plt.title('Pole-Zero Plot of Low-Pass Filter')
plt.xlabel('Real')
plt.ylabel('Imaginary')
plt.legend()
plt.grid()
plt.show()



The first step is to define the numerator and denominator coefficients of the analog filter using NumPy arrays. The impulse invariant transformation is then applied using the cont2discrete() function from the scipy.signal module, which returns the numerator and denominator coefficients of the corresponding digital filter in impulse response form.

The impulse response coefficients are then converted to numerator/denominator form using the zpk2tf() function, which converts the zeros, poles, and gain of the transfer function to numerator and denominator coefficients. These coefficients are then converted to the second-order sections (SOS) form using the tf2sos() function.

The frequency response of the digital filter is plotted using the sosfreqz() function, which returns the frequency response of a digital filter in terms of its second-order sections. The plot shows the magnitude of the frequency response of the low-pass filter as a function of the normalized frequency (x pi rad/sample).

Finally, the zeros and poles of the digital filter are plotted using the sos2zpk() function. This function converts the SOS coefficients back to zeros, poles, and gain form, which are then plotted on the complex plane. The plot shows the zeros as circles and the poles as crosses.

In summary, the code demonstrates how to transform an analog filter to digital filter using the impulse invariant transformation method in Python. The frequency response and pole-zero plot of the resulting digital filter are also plotted. Python program was used to illustrate the concepts and math behind the impulse invariant transformation method and how it is used to design digital filters from analog filters. Other method to convert an analog filter to digital filter is Bilinear Transformation method.