bundles / scipy latest / scipy / signal / _fir_filter_design / firwin
function
scipy.signal._fir_filter_design:firwin
Signature
def firwin ( numtaps , cutoff , * , width = None , window = hamming , pass_zero = True , scale = True , fs = None ) Summary
FIR filter design using the window method.
Extended Summary
This function computes the coefficients of a finite impulse response filter. The filter will have linear phase; it will be Type I if numtaps is odd and Type II if numtaps is even.
Type II filters always have zero response at the Nyquist frequency, so a ValueError exception is raised if firwin is called with numtaps even and having a passband whose right end is at the Nyquist frequency.
Parameters
numtaps: intLength of the filter (number of coefficients, i.e., the filter order + 1).
numtapsmust be odd if a passband includes the Nyquist frequency.cutoff: float or 1-D array_likeCutoff frequency of filter (expressed in the same units as
fs) or an array of cutoff frequencies (that is, band edges). In the former case, as a float, the cutoff frequency should correspond with the half-amplitude point, where the attenuation will be -6 dB. In the latter case, the frequencies incutoffshould be positive and monotonically increasing between 0 andfs/2. The values 0 andfs/2must not be included incutoff. It should be noted that this is different from the behavior of iirdesign, where the cutoff is the half-power point (-3 dB).width: float or None, optionalIf not
None, then a kaiser window is calculated wherewidthspecifies the approximate width of the transition region (expressed in the same unit asfs). This is achieved by utilizing kaiser_atten to calculate an attenuation which is passed to kaiser_beta for determining the β parameter for the kaiser window. In this case, thewindowargument is ignored.window: string or tuple of string and parameter values, optionalDesired window to use. Default is
'hamming'. The window will be symmetric, unless a suffix'_periodic'is appended to the window name (e.g.,'hamming_perodic') Consult get_window for a list of windows and required parameters.pass_zero: {True, False, 'bandpass', 'lowpass', 'highpass', 'bandstop'}, optionalToggles the zero frequency bin (or DC gain) to be in the passband (
True) or in the stopband (False).'bandstop','lowpass'are synonyms forTrueand'bandpass','highpass'are synonyms forFalse.'lowpass','highpass'additionally requirecutoffto be a scalar value or a length-one array. Default:True.scale: bool, optionalSet to
Trueto scale the coefficients so that the frequency response is exactly unity at a certain frequency. That frequency is either:0 (DC) if the first passband starts at 0 (i.e.,
pass_zeroisTrue)fs/2(the Nyquist frequency) if the first passband ends atfs/2(i.e., the filter is a single band highpass filter); center of first passband otherwise
fs: float, optionalThe sampling frequency of the signal. Each frequency in
cutoffmust be between 0 andfs/2. Default is 2.
Returns
h: ndarrayFIR filter coefficients as 1d array with
numtapsentries.
Raises
: ValueErrorIf any value in
cutoffis less than or equal to 0 or greater than or equal tofs/2, if the values incutoffare not strictly monotonically increasing, or ifnumtapsis even but a passband includes the Nyquist frequency.
Notes
Array API Standard Support
firwin 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 ==================== ==================== ====================
See
dev-arrayapifor more information.
Examples
The following example calculates frequency responses of a 30 Hz low-pass filter with various numbers of taps. The transition region width is 20 Hz. The upper plot shows the gain and the lower plot the phase. The vertical dashed line marks the corner frequency and the gray background the transition region.import matplotlib.pyplot as plt import numpy as np import scipy.signal as signal fs = 200 # sampling frequency and number of taps f_c, width = 30, 20 # corner frequency (-6 dB gain) taps = [20, 40, 60] # number of taps fg, (ax0, ax1) = plt.subplots(2, 1, sharex='all', layout="constrained", figsize=(5, 4))✓
ax0.set_title(rf"Response of ${f_c}\,$Hz low-pass Filter with " + rf"${width}\,$Hz transition region") ax0.set(ylabel="Gain in dB", xlim=(0, fs/2)) ax1.set(xlabel=rf"Frequency $f\,$ in hertz (sampling frequency $f_S={fs}\,$Hz)", ylabel="Phase in Degrees") for n in taps: # calculate filter and plot response: bb = signal.firwin(n, f_c, width=width, fs=fs) f, H = signal.freqz(bb, fs=fs) # calculate frequency response H_dB, H_ph = 20 * np.log10(abs(H)), np.rad2deg(np.unwrap(np.angle(H))) H_ph[H_dB<-150] = np.nan ax0.plot(f, H_dB, alpha=.5, label=rf"{n} taps") ax1.plot(f, H_ph, alpha=.5, label=rf"{n} taps") for ax_ in (ax0, ax1): ax_.axvspan(f_c-width/2, f_c+width/2,color='gray', alpha=.25) ax_.axvline(f_c, color='gray', linestyle='--', alpha=.5) ax_.grid() ax_.legend()✗
plt.show()
✓
import matplotlib.pyplot as plt import numpy as np import scipy.signal as signal fs = 200 # sampling frequency and number of taps n, f_c = 40, 30 # number of taps and corner frequency (-6 dB gain) widths = (2, 10, 25) # width of transition region fg, ax = plt.subplots(1, 1, layout="constrained",)✓
ax.set(title=rf"Response of {n}-tap ${f_c}\,$Hz low-pass Filter", xlabel=rf"Frequency $f\,$ in hertz (sampling frequency $f_S={fs}\,$Hz)", ylabel="Gain in dB", xlim=(0, fs/2)) ax.axvline(f_c, color='gray', linestyle='--', alpha=.7) # mark corner frequency for width in widths: # calculate filter and plot response: bb = signal.firwin(n, f_c, width=width, fs=fs) f, H = signal.freqz(bb, fs=fs) # calculate frequency response H_dB= 20 * np.log10(abs(H)) # convert to dB ax.plot(f, H_dB, alpha=.5, label=rf"width$={width}\,$Hz")✗
ax.grid()
✓ax.legend()
✗plt.show()
✓
import matplotlib.pyplot as plt import numpy as np import scipy.signal as signal fs, n = 200, 80 # sampling frequency and number of taps cutoff = [40, 60] # corner frequencies (-6 dB gain) windows = ('boxcar', 'hamming', 'hann', 'blackman') fg, ax = plt.subplots(1, 1, layout="constrained") # set up plotting✓
ax.set(title=rf"Response of {n}-tap Filter with ${cutoff}\,$Hz passband", xlabel=rf"Frequency $f\,$ in hertz (sampling frequency $f_S={fs}\,$Hz)", ylabel="Gain in dB", xlim=(0, fs/2)) ax.axvspan(*cutoff, color='gray', alpha=.25) # mark passband for win in windows: # calculate filter and plot response: bb = signal.firwin(n, cutoff, window=win, pass_zero=False, fs=fs) f, H = signal.freqz(bb, fs=fs) # calculate frequency response H_dB = 20 * np.log10(abs(H)) # convert to dB ax.plot(f, H_dB, alpha=.5, label=win)✗
ax.grid()
✓ax.legend()
✗plt.show()
✓
from itertools import product import matplotlib.pyplot as plt import numpy as np import scipy.signal as signal cutoffs = [0.5, (.25, .75)] # cutoff parameters fg, axx = plt.subplots(4, 1, sharex='all', layout="constrained", figsize=(5, 4))✓
for ax, (cutoff, pass_zero) in zip(axx, product(cutoffs, (True, False))): ax.set(title=f"firwin(41, {cutoff=}, {pass_zero=}, fs=2)", ylabel="Gain") ax.set_yticks([0.5], minor=True) # mark gain of 0.5 (= -6 dB) ax.grid(which='minor', axis='y') bb = signal.firwin(41, cutoff, pass_zero=pass_zero, fs=2) ff, HH = signal.freqz(bb, fs=2) ax.plot(ff, abs(HH), 'C0-', label="FIR Response") f_d = np.hstack(([0], np.atleast_1d(cutoff), [1])) H_d = np.tile([1, 0] if pass_zero else [0, 1], 2)[:len(f_d)] H_d[-1] = H_d[-2] # account for symmetry at Nyquist frequency ax.step(f_d, H_d, 'k--', where='post', alpha=.3, label="Desired Response") axx[-1].set(xlabel=r"Frequency $f\,$ in hertz (sampling frequency $f_S=2\,$Hz)", xlim=(0, 1))✗
plt.show()
✓
See also
- firls
FIR filter design using least-squares error minimization.
- firwin2
Window method FIR filter design specifying gain-frequency pairs.
- firwin_2d
2D FIR filter design using the window method.
- minimum_phase
Convert a FIR filter to minimum phase
- remez
Calculate the minimax optimal filter using the Remez exchange algorithm.
Aliases
-
scipy.signal.firwin