Skip to content

Commit

Permalink
DOC: signal.firwin: emphasise cutoff freq is half-amplitude (scipy#21590
Browse files Browse the repository at this point in the history
)

Co-authored-by: Eric Larson <larson.eric.d@gmail.com>
  • Loading branch information
zpotthoff and larsoner authored Oct 9, 2024
1 parent a06de4e commit 4ef4162
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 5 deletions.
30 changes: 30 additions & 0 deletions doc/source/tutorial/signal.rst
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,36 @@ stop-band attenuation of :math:`\approx 60` dB.
>>> plt.grid()
>>> plt.show()

.. note::

It is important to note that the cutoffs for :func:`firwin` and :func:`iirfilter`
are defined differently. For :func:`firwin`, the cutoff-frequency is at
half-amplitude (i.e. -6dB). For :func:`iirfilter`, the cutoff is at half-power
(i.e. -3dB).

.. plot::
:alt: "This code generates an example plot displaying the differences in cutoff frequency between FIR and IIR filters. FIR filters have a cutoff frequency at half-amplitude, while IIR filter cutoffs are at half-power."

>>> import numpy as np
>>> from matplotlib import pyplot as plt
>>> from scipy import signal as sig

>>> fs = 16000
>>> b = sig.firwin(101, 2500, fs=fs)
>>> f, h_fft = sig.freqz(b, fs=fs)
>>> h_amp = 20 * np.log10(np.abs(h_fft))
>>> _, ax = plt.subplots(layout="constrained")
>>> ax.plot(f, h_amp, label="FIR")
>>> ax.grid(True)

>>> b, a = sig.iirfilter(15, 2500, btype="low", fs=fs)
>>> f, h_fft = sig.freqz(b, a, fs=fs)
>>> h_amp = 20 * np.log10(np.abs(h_fft))
>>> ax.plot(f, h_amp, label="IIR")
>>> ax.set(xlim=[2100, 2900], ylim=[-10, 2])
>>> ax.set(xlabel="Frequency (Hz)", ylabel="Amplitude Response [dB]")
>>> ax.legend()

Filter Coefficients
"""""""""""""""""""

Expand Down
4 changes: 3 additions & 1 deletion scipy/signal/_filter_design.py
Original file line number Diff line number Diff line change
Expand Up @@ -2290,7 +2290,9 @@ def iirdesign(wp, ws, gpass, gstop, analog=False, ftype='ellip', output='ba',
For analog filters, `wp` and `ws` are angular frequencies (e.g., rad/s).
Note, that for bandpass and bandstop filters passband must lie strictly
inside stopband or vice versa.
inside stopband or vice versa. Also note that the cutoff at the band edges
for IIR filters is defined as half-power, so -3dB, not half-amplitude (-6dB)
like for `scipy.signal.fiwin`.
gpass : float
The maximum loss in the passband (dB).
gstop : float
Expand Down
12 changes: 8 additions & 4 deletions scipy/signal/_fir_filter_design.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,10 +269,14 @@ def firwin(numtaps, cutoff, *, width=None, window='hamming', pass_zero=True,
Nyquist frequency.
cutoff : float or 1-D array_like
Cutoff frequency of filter (expressed in the same units as `fs`)
OR an array of cutoff frequencies (that is, band edges). In the
latter case, the frequencies in `cutoff` should be positive and
monotonically increasing between 0 and `fs/2`. The values 0 and
`fs/2` must not be included in `cutoff`.
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 -6dB.
In the latter case, the frequencies in `cutoff` should be positive
and monotonically increasing between 0 and `fs/2`. The values 0
and `fs/2` must not be included in `cutoff`. It should be noted
that this is different than the behavior of `scipy.signal.iirdesign`,
where the cutoff is the half-power point (-3dB).
width : float or None, optional
If `width` is not None, then assume it is the approximate width
of the transition region (expressed in the same units as `fs`)
Expand Down

0 comments on commit 4ef4162

Please sign in to comment.