.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/sparsefilterdesign.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_sparsefilterdesign.py: ===================== Sparse filter design. ===================== Sparse filters can be easily designed. You just need to decide if you want to minimize the approximation error subject to complexity of minimize the complexity subject to the approximation error. .. GENERATED FROM PYTHON SOURCE LINES 10-23 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from mplsignal import freqz_fir from fird.constraint import MaxNonzeroCoefficientsConstraint, PiecewiseLinearConstraint from fird.designer import FIRDesigner from fird.objective import ( L1CoefficientsObjective, MaxNonzeroCoefficientsObjective, PiecewiseLinearObjective, ) .. GENERATED FROM PYTHON SOURCE LINES 24-25 Let us start by designing a lowpass filter of order 31, but with at most ten of the sixteen variables/coefficients being zero (20 of the 32 taps due to symmetry). .. GENERATED FROM PYTHON SOURCE LINES 26-38 .. code-block:: Python o = PiecewiseLinearObjective([0, 0.2, 0.37, 1], [1, 1, 0, 0]) c = MaxNonzeroCoefficientsConstraint(10) d = FIRDesigner(31, o, c) d.solve() h31_10 = d.get_impulse_response() fig, ax = plt.subplots() freqz_fir(h31_10, ax=ax, style="magnitude") ax.set_ylim(-60, 5) fig.suptitle("Sparse filter with at most 10 non-zero coefficients") fig.show() .. image-sg:: /examples/images/sphx_glr_sparsefilterdesign_001.png :alt: Sparse filter with at most 10 non-zero coefficients :srcset: /examples/images/sphx_glr_sparsefilterdesign_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 39-40 The alternative is to design a filter of order 31 minimizing the number of non-zero coefficients subject to a given approximation error. .. GENERATED FROM PYTHON SOURCE LINES 40-52 .. code-block:: Python c = PiecewiseLinearConstraint([0, 0.2, 0.37, 1], [1, 1, 0, 0], [0.01, 0.01]) o = MaxNonzeroCoefficientsObjective() d = FIRDesigner(31, o, c) d.solve() h31_sparse = d.get_impulse_response() fig, ax = plt.subplots() freqz_fir(h31_sparse, ax=ax, style="magnitude") ax.set_ylim(-60, 5) fig.suptitle("Sparse filter with at most $-40$ dB approximation error.") fig.show() .. image-sg:: /examples/images/sphx_glr_sparsefilterdesign_002.png :alt: Sparse filter with at most $-40$ dB approximation error. :srcset: /examples/images/sphx_glr_sparsefilterdesign_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 53-54 The impulse responses of the designed filters can be examined to see the sparsity. .. GENERATED FROM PYTHON SOURCE LINES 54-64 .. code-block:: Python print("Non-zero filter taps in h31_10:", np.count_nonzero(h31_10)) print("Non-zero filter taps in h31_sparse:", np.count_nonzero(h31_sparse)) fig, ax = plt.subplots(2, 1, layout="constrained") ax[0].stem(h31_10) ax[0].set_title("Impulse response of h31_10") ax[1].stem(h31_sparse) ax[1].set_title("Impulse response of h31_sparse") fig.show() .. image-sg:: /examples/images/sphx_glr_sparsefilterdesign_003.png :alt: Impulse response of h31_10, Impulse response of h31_sparse :srcset: /examples/images/sphx_glr_sparsefilterdesign_003.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Non-zero filter taps in h31_10: 20 Non-zero filter taps in h31_sparse: 22 .. GENERATED FROM PYTHON SOURCE LINES 65-66 It is also possible to convert between constraints and objectives. For instance, the previous design can be done by converting the constraint to an objective. .. GENERATED FROM PYTHON SOURCE LINES 66-72 .. code-block:: Python cconv = o.to_constraint(10) oconv = c.to_objective() d = FIRDesigner(31, oconv, cconv) d.solve() h31_10_conv = d.get_impulse_response() .. GENERATED FROM PYTHON SOURCE LINES 73-74 The results asshould be the the same. .. GENERATED FROM PYTHON SOURCE LINES 74-76 .. code-block:: Python np.testing.assert_allclose(h31_10, h31_10_conv) .. GENERATED FROM PYTHON SOURCE LINES 77-79 Finally, it is also possible to approximate a sparse design by minimizing the L1-norm of the coefficients. This will avoid the potentially costly integer programming. .. GENERATED FROM PYTHON SOURCE LINES 79-90 .. code-block:: Python o = L1CoefficientsObjective() d = FIRDesigner(31, o, c) d.solve() h31_l1 = d.get_impulse_response() fig, ax = plt.subplots(2, 1, layout="constrained") freqz_fir(h31_l1, ax=ax[0], style="magnitude") ax[0].set_ylim(-60, 5) ax[1].stem(h31_l1) fig.suptitle("L1-norm minimized filter with at most $-40$ dB approximation error.") fig.show() print("Non-zero filter taps in h31_l1:", np.count_nonzero(h31_l1)) .. image-sg:: /examples/images/sphx_glr_sparsefilterdesign_004.png :alt: L1-norm minimized filter with at most $-40$ dB approximation error. :srcset: /examples/images/sphx_glr_sparsefilterdesign_004.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Non-zero filter taps in h31_l1: 28 .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 7.246 seconds) .. _sphx_glr_download_examples_sparsefilterdesign.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: sparsefilterdesign.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: sparsefilterdesign.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: sparsefilterdesign.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_