bundles / scipy 1.17.1 / scipy / signal / _filter_design / bilinear
function
scipy.signal._filter_design:bilinear
Signature
def bilinear ( b , a , fs = 1.0 ) Summary
Calculate a digital IIR filter from an analog transfer function by utilizing the bilinear transform.
Parameters
b: array_likeCoefficients of the numerator polynomial of the analog transfer function in form of a complex- or real-valued 1d array.
a: array_likeCoefficients of the denominator polynomial of the analog transfer function in form of a complex- or real-valued 1d array.
fs: floatSample rate, as ordinary frequency (e.g., hertz). No pre-warping is done in this function.
Returns
beta: ndarrayCoefficients of the numerator polynomial of the digital transfer function in form of a complex- or real-valued 1d array.
alpha: ndarrayCoefficients of the denominator polynomial of the digital transfer function in form of a complex- or real-valued 1d array.
Notes
The parameters and are 1d arrays of length and . They define the analog transfer function
The bilinear transform [1] is applied by substituting
into , with being the sampling rate. This results in the digital transfer function in the -domain
This expression can be simplified by multiplying numerator and denominator by , with . This allows to be reformulated as
This is the equation implemented to perform the bilinear transform. Note that for large , or can cause a numeric overflow for sufficiently large or .
Array API Standard Support
bilinear has experimental support for Python Array API Standard compatible backends in addition to NumPy. Please consider testing these features by setting an environment variable SCIPY_ARRAY_API=1 and providing CuPy, PyTorch, JAX, or Dask arrays as array arguments. The following combinations of backend and device (or other capability) are supported.
==================== ==================== ==================== Library CPU GPU ==================== ==================== ==================== NumPy ✅ n/a CuPy n/a ✅ PyTorch ✅ ⛔ JAX ⚠️ no JIT ⛔ Dask ⚠️ computes graph n/a ==================== ==================== ====================
CuPy does not accept complex inputs.
See
dev-arrayapifor more information.
Examples
The following example shows the frequency response of an analog bandpass filter and the corresponding digital filter derived by utilitzing the bilinear transform:from scipy import signal import matplotlib.pyplot as plt import numpy as np fs = 100 # sampling frequency om_c = 2 * np.pi * np.array([7, 13]) # corner frequencies bb_s, aa_s = signal.butter(4, om_c, btype='bandpass', analog=True, output='ba') bb_z, aa_z = signal.bilinear(bb_s, aa_s, fs) w_z, H_z = signal.freqz(bb_z, aa_z) # frequency response of digitial filter w_s, H_s = signal.freqs(bb_s, aa_s, worN=w_z*fs) # analog filter response f_z, f_s = w_z * fs / (2*np.pi), w_s / (2*np.pi) Hz_dB, Hs_dB = (20*np.log10(np.abs(H_).clip(1e-10)) for H_ in (H_z, H_s)) fg0, ax0 = plt.subplots()✓
ax0.set_title("Frequency Response of 4-th order Bandpass Filter") ax0.set(xlabel='Frequency $f$ in Hertz', ylabel='Magnitude in dB', xlim=[f_z[1], fs/2], ylim=[-200, 2]) ax0.semilogx(f_z, Hz_dB, alpha=.5, label=r'$|H_z(e^{j 2 \pi f})|$') ax0.semilogx(f_s, Hs_dB, alpha=.5, label=r'$|H_s(j 2 \pi f)|$') ax0.legend()✗
ax0.grid(which='both', axis='x') ax0.grid(which='major', axis='y') plt.show()✓

See also
Aliases
-
scipy.signal.bilinear