Design an IIR Highpass Butterworth Filter using Bilinear Transformation Method in Scipy - Python - GeeksforGeeks

07 Jan, 2022
IIR stands for Infinite Impulse Response, It is one of the striking features of many linear-time invariant systems that are distinguished by having an impulse response h(t)/h(n) which does not become zero after some point but instead continues infinitely.
It basically behaves just like an ordinary digital Highpass Butterworth Filter with an infinite impulse response.
The specifications are as follows:  
Pass band frequency: 2-4 kHz
Stop band frequency: 0-500 Hz
Pass band ripple: 3dB
Stop band attenuation: 20 dB
Sampling frequency: 8 kHz
We will plot the magnitude, phase, impulse, step response of the filter.
Step-by-step Approach:
Step 1: Importing all the necessary libraries.
Python3
# import required libraryimport numpy as npimport scipy.signal as signalimport matplotlib.pyplot as plt
Step 2: Defining user-defined functions mfreqz() and impz(). mfreqz is a function for magnitude and phase plot & impz is a function for impulse and step response.
Python3
def mfreqz(b, a, Fs):        # Compute frequency response of the filter     # using signal.freqz function    wz, hz = signal.freqz(b, a)      # Calculate Magnitude from hz in dB    Mag = 20*np.log10(abs(hz))      # Calculate phase angle in degree from hz    Phase = np.unwrap(np.arctan2(np.imag(hz), np.real(hz)))*(180/np.pi)      # Calculate frequency in Hz from wz    Freq = wz*Fs/(2*np.pi)  # START CODE HERE ### (≈ 1 line of code)      # Plot filter magnitude and phase responses using subplot.    fig = plt.figure(figsize=(10, 6))      # Plot Magnitude response    sub1 = plt.subplot(2, 1, 1)    sub1.plot(Freq, Mag, 'r', linewidth=2)    sub1.axis([1, Fs/2, -100, 5])    sub1.set_title('Magnitude Response', fontsize=20)    sub1.set_xlabel('Frequency [Hz]', fontsize=20)    sub1.set_ylabel('Magnitude [dB]', fontsize=20)    sub1.grid()      # Plot phase angle    sub2 = plt.subplot(2, 1, 2)    sub2.plot(Freq, Phase, 'g', linewidth=2)    sub2.set_ylabel('Phase (degree)', fontsize=20)    sub2.set_xlabel(r'Frequency (Hz)', fontsize=20)    sub2.set_title(r'Phase response', fontsize=20)    sub2.grid()      plt.subplots_adjust(hspace=0.5)    fig.tight_layout()    plt.show()  # Define impz(b,a) to calculate impulse response# and step response of a system input: b= an array# containing numerator coefficients,a= an array containing #denominator coefficientsdef impz(b, a):          # Define the impulse sequence of length 60    impulse = np.repeat(0., 60)    impulse[0] = 1.    x = np.arange(0, 60)      # Compute the impulse response    response = signal.lfilter(b, a, impulse)      # Plot filter impulse and step response:    fig = plt.figure(figsize=(10, 6))    plt.subplot(211)    plt.stem(x, response, 'm', use_line_collection=True)    plt.ylabel('Amplitude', fontsize=15)    plt.xlabel(r'n (samples)', fontsize=15)    plt.title(r'Impulse response', fontsize=15)      plt.subplot(212)    step = np.cumsum(response)  # Compute step response of the system    plt.stem(x, step, 'g', use_line_collection=True)    plt.ylabel('Amplitude', fontsize=15)    plt.xlabel(r'n (samples)', fontsize=15)    plt.title(r'Step response', fontsize=15)    plt.subplots_adjust(hspace=0.5)      fig.tight_layout()    plt.show()
Step 3:Define variables with the given specifications of the filter.
Python3
# Given specificationFs = 8000  # Sampling frequency in Hzfp = 2000  # Pass band frequency in Hzfs = 500  # Stop Band frequency in HzAp = 3  # Pass band ripple in dBAs = 20  # Stop band attenuation in dB  # Compute Sampling parameterTd = 1/Fs
Step 4:Computing the cut-off frequency
Python3
# Compute cut-off frequency in radian/secwp = 2*np.pi*fp  # pass band frequency in radian/secws = 2*np.pi*fs  # stop band frequency in radian/sec
Step 5: Pre-wrapping the cut-off frequency
Python3
# Prewarp the analog frequencyOmega_p = (2/Td)*np.tan(wp*Td/2)  # Prewarped analog passband frequencyOmega_s = (2/Td)*np.tan(ws*Td/2)  # Prewarped analog stopband frequency
Step 6: Computing the Butterworth Filter
Python3
# Compute Butterworth filter order and cutoff frequencyN, wc = signal.buttord(Omega_p, Omega_s, Ap, As, analog=True)  # Print the values of order and cut-off frequencyprint('Order of the filter=', N)print('Cut-off frequency=', wc)
Output:
Step 7: Design analog Butterworth filter using N and wc by signal.butter() function.
Python3
# Design analog Butterworth filter using N and# wc by signal.butter functionb, a = signal.butter(N, wc, 'high', analog=True)  # Perform bilinear Transformationz, p = signal.bilinear(b, a, fs=Fs)  # Print numerator and denomerator coefficients # of the filterprint('Numerator Coefficients:', z)print('Denominator Coefficients:', p)
Output:
Step 8: Plotting the Magnitude & Phase Response
Python3
# Call mfreqz function to plot the# magnitude and phase responsemfreqz(z, p, Fs)
Output:
Step 9: Plotting the impulse & step response
Python3
# Call impz function to plot impulse and # step response of the filterimpz(z, p)
Output:
Below is the implementation:
Python3
# import required libraryimport numpy as npimport scipy.signal as signalimport matplotlib.pyplot as plt  # User defined functions mfreqz for # Magnitude & Phase Responsedef mfreqz(b, a, Fs):          # Compute frequency response of the filter    # using signal.freqz function    wz, hz = signal.freqz(b, a)      # Calculate Magnitude from hz in dB    Mag = 20*np.log10(abs(hz))      # Calculate phase angle in degree from hz    Phase = np.unwrap(np.arctan2(np.imag(hz), np.real(hz)))*(180/np.pi)      # Calculate frequency in Hz from wz    Freq = wz*Fs/(2*np.pi)  # START CODE HERE ### (≈ 1 line of code)      # Plot filter magnitude and phase responses using subplot.    fig = plt.figure(figsize=(10, 6))      # Plot Magnitude response    sub1 = plt.subplot(2, 1, 1)    sub1.plot(Freq, Mag, 'r', linewidth=2)    sub1.axis([1, Fs/2, -100, 5])    sub1.set_title('Magnitude Response', fontsize=20)    sub1.set_xlabel('Frequency [Hz]', fontsize=20)    sub1.set_ylabel('Magnitude [dB]', fontsize=20)    sub1.grid()      # Plot phase angle    sub2 = plt.subplot(2, 1, 2)    sub2.plot(Freq, Phase, 'g', linewidth=2)    sub2.set_ylabel('Phase (degree)', fontsize=20)    sub2.set_xlabel(r'Frequency (Hz)', fontsize=20)    sub2.set_title(r'Phase response', fontsize=20)    sub2.grid()      plt.subplots_adjust(hspace=0.5)    fig.tight_layout()    plt.show()  # Define impz(b,a) to calculate impulse # response and step response of a system# input: b= an array containing numerator # coefficients,a= an array containing #denominator coefficientsdef impz(b, a):          # Define the impulse sequence of length 60    impulse = np.repeat(0., 60)    impulse[0] = 1.    x = np.arange(0, 60)      # Compute the impulse response    response = signal.lfilter(b, a, impulse)      # Plot filter impulse and step response:    fig = plt.figure(figsize=(10, 6))    plt.subplot(211)    plt.stem(x, response, 'm', use_line_collection=True)    plt.ylabel('Amplitude', fontsize=15)    plt.xlabel(r'n (samples)', fontsize=15)    plt.title(r'Impulse response', fontsize=15)      plt.subplot(212)    step = np.cumsum(response)  # Compute step response of the system    plt.stem(x, step, 'g', use_line_collection=True)    plt.ylabel('Amplitude', fontsize=15)    plt.xlabel(r'n (samples)', fontsize=15)    plt.title(r'Step response', fontsize=15)    plt.subplots_adjust(hspace=0.5)      fig.tight_layout()    plt.show()    # Given specificationFs = 8000  # Sampling frequency in Hzfp = 2000  # Pass band frequency in Hzfs = 500  # Stop Band frequency in HzAp = 3  # Pass band ripple in dBAs = 20  # Stop band attenuation in dB  # Compute Sampling parameterTd = 1/Fs  # Compute cut-off frequency in radian/secwp = 2*np.pi*fp  # pass band frequency in radian/secws = 2*np.pi*fs  # stop band frequency in radian/sec  # Prewarp the analog frequencyOmega_p = (2/Td)*np.tan(wp*Td/2)  # Prewarped analog passband frequencyOmega_s = (2/Td)*np.tan(ws*Td/2)  # Prewarped analog stopband frequency  # Compute Butterworth filter order and cutoff frequencyN, wc = signal.buttord(Omega_p, Omega_s, Ap, As, analog=True)  # Print the values of order and cut-off frequencyprint('Order of the filter=', N)print('Cut-off frequency=', wc)  # Design analog Butterworth filter using N and# wc by signal.butter functionb, a = signal.butter(N, wc, 'high', analog=True)  # Perform bilinear Transformationz, p = signal.bilinear(b, a, fs=Fs)  # Print numerator and denomerator coefficients of the filterprint('Numerator Coefficients:', z)print('Denominator Coefficients:', p)  # Call mfreqz function to plot the magnitude# and phase responsemfreqz(z, p, Fs)  # Call impz function to plot impulse and step# response of the filterimpz(z, p)
Output:
gulshankumarar231
Data Visualization
Python-scipy
Python
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
How to Install PIP on Windows ?
How to drop one or multiple columns in Pandas Dataframe
How To Convert Python Dictionary To JSON?
Check if element exists in list in Python
Selecting rows in pandas DataFrame based on conditions
Defaultdict in Python
Python | Get unique values from a list
Python | os.path.join() method
Create a directory in Python
Python | Split string into list of characters