.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "gallery/0006.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_gallery_0006.py: .. _gallery:0006: Piecewise Cubic, Daubechies Basis, Gaussian Measurements ============================================================= .. contents:: :depth: 2 :local: In this example we have #. A signal :math:`\by` consisting of piecewise cubic polynomials with 5 pieces of total length of 2048 samples. #. A Daubechies-8 wavelet basis :math:`\Psi` of shape 2048x2048 with 5 levels of decomposition. #. The sparse representation :math:`\bx` of the signal :math:`\by` in the basis :math:`\Psi` consisting of exactly 63 nonzero entries (corresponding to the spikes and the amplitudes of the cosine waves). #. A Gaussian sensing matrix :math:`\Phi` of shape 600x2048 making 600 random measurements in a vector :math:`\bb`. The columns of the sensing matrix are unit normalized. #. We are given :math:`\bb` and :math:`\bA = \Phi \Psi` and have to reconstruct :math:`\bx` using it. #. Then we can use :math:`\Psi` to compute :math:`\by = \Psi \bx`. .. math:: \bb = \bA \bx = \Phi \Psi \bx = \Phi \by. See also: * :ref:`api:problems` * :ref:`api:lop` .. GENERATED FROM PYTHON SOURCE LINES 37-48 .. code-block:: default # Configure JAX to work with 64-bit floating point precision. from jax.config import config config.update("jax_enable_x64", True) import jax.numpy as jnp import cr.nimble as crn import cr.sparse as crs import cr.sparse.plots as crplot .. GENERATED FROM PYTHON SOURCE LINES 49-53 Setup ------------------------------ We shall construct our test signal and dictionary using our test problems module. .. GENERATED FROM PYTHON SOURCE LINES 53-59 .. code-block:: default from cr.sparse import problems prob = problems.generate('piecewise-cubic-poly:daubechies:gaussian') fig, ax = problems.plot(prob) .. image-sg:: /gallery/images/sphx_glr_0006_001.png :alt: Piecewise cubic polynomial, Wavelet coefficients, Measurements :srcset: /gallery/images/sphx_glr_0006_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 60-61 Let us access the relevant parts of our test problem .. GENERATED FROM PYTHON SOURCE LINES 61-71 .. code-block:: default # The combined linear operator (sensing matrix + dictionary) A = prob.A # The sparse representation of the signal in the dictionary x0 = prob.x # The Cosine+Spikes signal y0 = prob.y # The measurements b0 = prob.b .. GENERATED FROM PYTHON SOURCE LINES 72-74 Check how many coefficients in the sparse representation are sufficient to capture 99.9% of the energy of the signal .. GENERATED FROM PYTHON SOURCE LINES 74-76 .. code-block:: default print(crn.num_largest_coeffs_for_energy_percent(x0, 99.9)) .. rst-class:: sphx-glr-script-out .. code-block:: none 115 .. GENERATED FROM PYTHON SOURCE LINES 77-79 Check how many coefficients in the sparse representation are sufficient to capture 100% of the energy of the signal .. GENERATED FROM PYTHON SOURCE LINES 79-81 .. code-block:: default print(crn.num_largest_coeffs_for_energy_percent(x0, 100)) .. rst-class:: sphx-glr-script-out .. code-block:: none 278 .. GENERATED FROM PYTHON SOURCE LINES 82-87 This number gives us an idea about the required sparsity to be configured for greedy pursuit algorithms. Although the exact sparsity of this representation is 63 but several of the spikes are too small and could be ignored for a reasonably good approximation. .. GENERATED FROM PYTHON SOURCE LINES 89-92 Sparse Recovery using Subspace Pursuit ------------------------------------------- We shall use subspace pursuit to reconstruct the signal. .. GENERATED FROM PYTHON SOURCE LINES 92-96 .. code-block:: default import cr.sparse.pursuit.sp as sp # We will first try to estimate a 100-sparse representation sol = sp.solve(A, b0, 100) .. GENERATED FROM PYTHON SOURCE LINES 97-98 This utility function helps us quickly analyze the quality of reconstruction .. GENERATED FROM PYTHON SOURCE LINES 98-100 .. code-block:: default problems.analyze_solution(prob, sol, perc=100) .. rst-class:: sphx-glr-script-out .. code-block:: none m: 600, n: 2048 b_norm: original: 709.229 reconstruction: 708.631 SNR: 27.74 dB x_norm: original: 733.968 reconstruction: 732.596 SNR: 26.09 dB y_norm: original: 733.967 reconstruction: 732.596 SNR: 26.09 dB Sparsity: original: 278, reconstructed: 100, overlap: 100, ratio: 0.360 Iterations: 20 .. GENERATED FROM PYTHON SOURCE LINES 101-102 We will now try to estimate a 150-sparse representation .. GENERATED FROM PYTHON SOURCE LINES 102-103 .. code-block:: default sol = sp.solve(A, b0, 150) .. GENERATED FROM PYTHON SOURCE LINES 104-106 Let us check if we correctly decoded all the nonzero entries in the sparse representation x .. GENERATED FROM PYTHON SOURCE LINES 106-109 .. code-block:: default problems.analyze_solution(prob, sol, perc=100) .. rst-class:: sphx-glr-script-out .. code-block:: none m: 600, n: 2048 b_norm: original: 709.229 reconstruction: 709.194 SNR: 40.17 dB x_norm: original: 733.968 reconstruction: 733.994 SNR: 37.55 dB y_norm: original: 733.967 reconstruction: 733.994 SNR: 37.55 dB Sparsity: original: 278, reconstructed: 150, overlap: 150, ratio: 0.540 Iterations: 20 .. GENERATED FROM PYTHON SOURCE LINES 110-111 We will now try to estimate a 200-sparse representation .. GENERATED FROM PYTHON SOURCE LINES 111-112 .. code-block:: default sol = sp.solve(A, b0, 200) .. GENERATED FROM PYTHON SOURCE LINES 113-115 Let us check if we correctly decoded all the nonzero entries in the sparse representation x .. GENERATED FROM PYTHON SOURCE LINES 115-117 .. code-block:: default problems.analyze_solution(prob, sol, perc=100) .. rst-class:: sphx-glr-script-out .. code-block:: none m: 600, n: 2048 b_norm: original: 709.229 reconstruction: 709.228 SNR: 57.63 dB x_norm: original: 733.968 reconstruction: 734.022 SNR: 54.44 dB y_norm: original: 733.967 reconstruction: 734.022 SNR: 54.44 dB Sparsity: original: 278, reconstructed: 200, overlap: 200, ratio: 0.719 Iterations: 20 .. GENERATED FROM PYTHON SOURCE LINES 118-119 We will now try to estimate a 250-sparse representation .. GENERATED FROM PYTHON SOURCE LINES 119-122 .. code-block:: default tracker = crs.ProgressTracker(x0=x0) sol = sp.solve(A, b0, 250, tracker=tracker) .. rst-class:: sphx-glr-script-out .. code-block:: none [1] x_norm: 9.02e-01, r_norm: 2.17e-01, SNR: 0.01 dB [2] x_norm: 9.95e-01, r_norm: 6.92e-02, SNR: 0.01 dB [3] x_norm: 1.01e+00, r_norm: 4.00e-02, SNR: 0.01 dB [4] x_norm: 1.01e+00, r_norm: 3.15e-02, SNR: 0.01 dB [5] x_norm: 1.02e+00, r_norm: 2.22e-02, SNR: 0.01 dB [6] x_norm: 1.02e+00, r_norm: 1.81e-02, SNR: 0.01 dB [7] x_norm: 1.02e+00, r_norm: 1.69e-02, SNR: 0.01 dB [8] x_norm: 1.02e+00, r_norm: 1.56e-02, SNR: 0.01 dB [9] x_norm: 1.02e+00, r_norm: 1.53e-02, SNR: 0.01 dB [10] x_norm: 1.03e+00, r_norm: 1.51e-02, SNR: 0.01 dB [11] x_norm: 1.03e+00, r_norm: 1.48e-02, SNR: 0.01 dB [12] x_norm: 1.03e+00, r_norm: 1.37e-02, SNR: 0.01 dB [13] x_norm: 1.03e+00, r_norm: 1.09e-02, SNR: 0.01 dB [14] x_norm: 1.03e+00, r_norm: 6.98e-03, SNR: 0.01 dB [15] x_norm: 1.03e+00, r_norm: 3.38e-03, SNR: 0.01 dB [16] x_norm: 1.03e+00, r_norm: 1.18e-03, SNR: 0.01 dB [17] x_norm: 1.03e+00, r_norm: 5.14e-04, SNR: 0.01 dB [18] x_norm: 1.03e+00, r_norm: 1.14e-04, SNR: 0.01 dB [19] x_norm: 1.03e+00, r_norm: 3.93e-05, SNR: 0.01 dB Algorithm converged in 19 iterations. .. GENERATED FROM PYTHON SOURCE LINES 123-124 Let us plot the progress of subspace pursuit over different iterations .. GENERATED FROM PYTHON SOURCE LINES 124-127 .. code-block:: default ax = crplot.one_plot(height=6) tracker.plot_progress(ax) .. image-sg:: /gallery/images/sphx_glr_0006_002.png :alt: 0006 :srcset: /gallery/images/sphx_glr_0006_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 128-130 Let us check if we correctly decoded all the nonzero entries in the sparse representation x .. GENERATED FROM PYTHON SOURCE LINES 130-132 .. code-block:: default problems.analyze_solution(prob, sol, perc=100) .. rst-class:: sphx-glr-script-out .. code-block:: none m: 600, n: 2048 b_norm: original: 709.229 reconstruction: 709.229 SNR: 88.12 dB x_norm: original: 733.968 reconstruction: 733.968 SNR: 83.66 dB y_norm: original: 733.967 reconstruction: 733.968 SNR: 83.66 dB Sparsity: original: 278, reconstructed: 250, overlap: 250, ratio: 0.899 Iterations: 19 .. GENERATED FROM PYTHON SOURCE LINES 133-134 The estimated sparse representation .. GENERATED FROM PYTHON SOURCE LINES 134-135 .. code-block:: default x = sol.x .. GENERATED FROM PYTHON SOURCE LINES 136-137 Let us reconstruct the signal from this sparse representation .. GENERATED FROM PYTHON SOURCE LINES 137-138 .. code-block:: default y = prob.reconstruct(x) .. GENERATED FROM PYTHON SOURCE LINES 139-140 The estimated measurements .. GENERATED FROM PYTHON SOURCE LINES 140-142 .. code-block:: default b = A.times(x) .. GENERATED FROM PYTHON SOURCE LINES 143-144 Let us visualize the original and reconstructed representation .. GENERATED FROM PYTHON SOURCE LINES 144-153 .. code-block:: default def plot_representations(x0, x): ax = crplot.h_plots(2, height=2) ax[0].stem(x0, markerfmt='.') ax[0].set_title('Original representation') ax[1].stem(x, markerfmt='.') ax[1].set_title('Reconstructed representation') plot_representations(x0, x) .. image-sg:: /gallery/images/sphx_glr_0006_003.png :alt: Original representation, Reconstructed representation :srcset: /gallery/images/sphx_glr_0006_003.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 154-155 Let us visualize the original and reconstructed signal .. GENERATED FROM PYTHON SOURCE LINES 155-163 .. code-block:: default def plot_signals(y0, y): ax = crplot.h_plots(2, height=2) ax[0].plot(y0) ax[0].set_title('Original signal') ax[1].plot(y) ax[1].set_title('Reconstructed signal') plot_signals(y0, y) .. image-sg:: /gallery/images/sphx_glr_0006_004.png :alt: Original signal, Reconstructed signal :srcset: /gallery/images/sphx_glr_0006_004.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 164-165 Let us visualize the original and reconstructed measurements .. GENERATED FROM PYTHON SOURCE LINES 165-174 .. code-block:: default def plot_measurments(b0, b): ax = crplot.h_plots(2, height=2) ax[0].plot(b0) ax[0].set_title('Original measurements') ax[1].plot(b) ax[1].set_title('Reconstructed measurements') plot_measurments(b0, b) .. image-sg:: /gallery/images/sphx_glr_0006_005.png :alt: Original measurements, Reconstructed measurements :srcset: /gallery/images/sphx_glr_0006_005.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 175-176 We will now try to estimate a 278-sparse representation .. GENERATED FROM PYTHON SOURCE LINES 176-177 .. code-block:: default sol = sp.solve(A, b0, 278) .. GENERATED FROM PYTHON SOURCE LINES 178-180 Let us check if we correctly decoded all the nonzero entries in the sparse representation x .. GENERATED FROM PYTHON SOURCE LINES 180-184 .. code-block:: default problems.analyze_solution(prob, sol, perc=100) .. rst-class:: sphx-glr-script-out .. code-block:: none m: 600, n: 2048 b_norm: original: 709.229 reconstruction: 709.229 SNR: 83.64 dB x_norm: original: 733.968 reconstruction: 733.968 SNR: 76.35 dB y_norm: original: 733.967 reconstruction: 733.968 SNR: 76.35 dB Sparsity: original: 278, reconstructed: 277, overlap: 243, ratio: 0.874 Iterations: 18 .. GENERATED FROM PYTHON SOURCE LINES 185-187 Sparse Recovery using SPGL1 --------------------------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 187-193 .. code-block:: default import cr.sparse.cvx.spgl1 as crspgl1 sigma = 0.01 * jnp.linalg.norm(b0) options = crspgl1.SPGL1Options(max_iters=1000) tracker = crs.ProgressTracker(x0=x0, every=5) sol = crspgl1.solve_bpic_jit(A, b0, sigma, options=options, tracker=tracker) .. rst-class:: sphx-glr-script-out .. code-block:: none [5] x_norm: 4.51e+02, r_norm: 3.46e+02, SNR: 6.15 dB [10] x_norm: 5.92e+02, r_norm: 1.25e+02, SNR: 10.58 dB [15] x_norm: 6.67e+02, r_norm: 1.04e+02, SNR: 15.33 dB [20] x_norm: 6.72e+02, r_norm: 8.73e+01, SNR: 16.29 dB [25] x_norm: 6.92e+02, r_norm: 2.75e+01, SNR: 18.33 dB [30] x_norm: 7.00e+02, r_norm: 2.26e+01, SNR: 20.01 dB [35] x_norm: 7.08e+02, r_norm: 2.12e+01, SNR: 22.07 dB [40] x_norm: 7.12e+02, r_norm: 2.00e+01, SNR: 23.03 dB [45] x_norm: 7.14e+02, r_norm: 1.97e+01, SNR: 23.85 dB [50] x_norm: 7.14e+02, r_norm: 1.97e+01, SNR: 23.99 dB [55] x_norm: 7.17e+02, r_norm: 8.20e+00, SNR: 24.59 dB [60] x_norm: 7.18e+02, r_norm: 6.87e+00, SNR: 24.91 dB [65] x_norm: 7.19e+02, r_norm: 6.95e+00, SNR: 25.32 dB [70] x_norm: 7.19e+02, r_norm: 6.97e+00, SNR: 25.58 dB [75] x_norm: 7.20e+02, r_norm: 7.06e+00, SNR: 25.91 dB [80] x_norm: 7.20e+02, r_norm: 7.05e+00, SNR: 26.28 dB [85] x_norm: 7.21e+02, r_norm: 7.07e+00, SNR: 26.65 dB [90] x_norm: 7.21e+02, r_norm: 7.08e+00, SNR: 26.87 dB [95] x_norm: 7.22e+02, r_norm: 7.09e+00, SNR: 27.12 dB [100] x_norm: 7.22e+02, r_norm: 7.08e+00, SNR: 27.41 dB [105] x_norm: 7.22e+02, r_norm: 7.09e+00, SNR: 27.59 dB [109] x_norm: 7.22e+02, r_norm: 7.09e+00, SNR: 27.61 dB Algorithm converged in 109 iterations. .. GENERATED FROM PYTHON SOURCE LINES 194-195 Analyze the solution .. GENERATED FROM PYTHON SOURCE LINES 195-197 .. code-block:: default problems.analyze_solution(prob, sol, perc=100) .. rst-class:: sphx-glr-script-out .. code-block:: none m: 600, n: 2048 b_norm: original: 709.229 reconstruction: 706.592 SNR: 40.00 dB x_norm: original: 733.968 reconstruction: 722.265 SNR: 27.61 dB y_norm: original: 733.967 reconstruction: 722.265 SNR: 27.61 dB Sparsity: original: 278, reconstructed: 464, overlap: 182, ratio: 0.392 Iterations: 109 n_times: 169, n_trans: 126 .. GENERATED FROM PYTHON SOURCE LINES 198-199 Try with lower threshold on allowed noise .. GENERATED FROM PYTHON SOURCE LINES 199-205 .. code-block:: default sigma = 0.001 * jnp.linalg.norm(b0) options = crspgl1.SPGL1Options(max_iters=1000) tracker = crs.ProgressTracker(x0=x0, every=20) sol = crspgl1.solve_bpic_jit(A, b0, sigma, options=options, tracker=tracker) .. rst-class:: sphx-glr-script-out .. code-block:: none [20] x_norm: 6.75e+02, r_norm: 8.29e+01, SNR: 16.64 dB [40] x_norm: 7.12e+02, r_norm: 1.56e+01, SNR: 22.89 dB [60] x_norm: 7.17e+02, r_norm: 1.49e+01, SNR: 25.14 dB [80] x_norm: 7.21e+02, r_norm: 2.82e+00, SNR: 26.06 dB [100] x_norm: 7.21e+02, r_norm: 2.52e+00, SNR: 26.56 dB [120] x_norm: 7.23e+02, r_norm: 2.37e+00, SNR: 27.18 dB [140] x_norm: 7.23e+02, r_norm: 2.28e+00, SNR: 27.86 dB [160] x_norm: 7.24e+02, r_norm: 2.25e+00, SNR: 28.33 dB [180] x_norm: 7.25e+02, r_norm: 7.61e-01, SNR: 28.60 dB [200] x_norm: 7.25e+02, r_norm: 6.95e-01, SNR: 28.66 dB [220] x_norm: 7.25e+02, r_norm: 7.09e-01, SNR: 28.73 dB [240] x_norm: 7.25e+02, r_norm: 7.08e-01, SNR: 28.79 dB [260] x_norm: 7.25e+02, r_norm: 7.02e-01, SNR: 28.94 dB [280] x_norm: 7.25e+02, r_norm: 7.08e-01, SNR: 29.06 dB [300] x_norm: 7.26e+02, r_norm: 7.08e-01, SNR: 29.21 dB [320] x_norm: 7.26e+02, r_norm: 7.08e-01, SNR: 29.27 dB [340] x_norm: 7.26e+02, r_norm: 7.08e-01, SNR: 29.32 dB [360] x_norm: 7.26e+02, r_norm: 7.09e-01, SNR: 29.40 dB [380] x_norm: 7.26e+02, r_norm: 7.08e-01, SNR: 29.48 dB [400] x_norm: 7.26e+02, r_norm: 7.09e-01, SNR: 29.55 dB [420] x_norm: 7.26e+02, r_norm: 7.09e-01, SNR: 29.63 dB [423] x_norm: 7.26e+02, r_norm: 7.09e-01, SNR: 29.64 dB Algorithm converged in 423 iterations. .. GENERATED FROM PYTHON SOURCE LINES 206-207 Let us plot the progress of SPGL1 over different iterations .. GENERATED FROM PYTHON SOURCE LINES 207-211 .. code-block:: default ax = crplot.one_plot(height=6) tracker.plot_progress(ax) .. image-sg:: /gallery/images/sphx_glr_0006_006.png :alt: 0006 :srcset: /gallery/images/sphx_glr_0006_006.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 212-213 Analyze the solution .. GENERATED FROM PYTHON SOURCE LINES 213-215 .. code-block:: default problems.analyze_solution(prob, sol, perc=100) .. rst-class:: sphx-glr-script-out .. code-block:: none m: 600, n: 2048 b_norm: original: 709.229 reconstruction: 708.996 SNR: 60.00 dB x_norm: original: 733.968 reconstruction: 725.987 SNR: 29.64 dB y_norm: original: 733.967 reconstruction: 725.988 SNR: 29.64 dB Sparsity: original: 278, reconstructed: 612, overlap: 198, ratio: 0.324 Iterations: 423 n_times: 755, n_trans: 454 .. GENERATED FROM PYTHON SOURCE LINES 216-217 The estimated sparse representation .. GENERATED FROM PYTHON SOURCE LINES 217-218 .. code-block:: default x = sol.x .. GENERATED FROM PYTHON SOURCE LINES 219-220 Let us reconstruct the signal from this sparse representation .. GENERATED FROM PYTHON SOURCE LINES 220-221 .. code-block:: default y = prob.reconstruct(x) .. GENERATED FROM PYTHON SOURCE LINES 222-223 The estimated measurements .. GENERATED FROM PYTHON SOURCE LINES 223-226 .. code-block:: default b = A.times(x) .. GENERATED FROM PYTHON SOURCE LINES 227-228 Let us visualize the original and reconstructed representation .. GENERATED FROM PYTHON SOURCE LINES 228-231 .. code-block:: default plot_representations(x0, x) .. image-sg:: /gallery/images/sphx_glr_0006_007.png :alt: Original representation, Reconstructed representation :srcset: /gallery/images/sphx_glr_0006_007.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 232-233 Let us visualize the original and reconstructed signal .. GENERATED FROM PYTHON SOURCE LINES 233-235 .. code-block:: default plot_signals(y0, y) .. image-sg:: /gallery/images/sphx_glr_0006_008.png :alt: Original signal, Reconstructed signal :srcset: /gallery/images/sphx_glr_0006_008.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 236-237 Let us visualize the original and reconstructed measurements .. GENERATED FROM PYTHON SOURCE LINES 237-239 .. code-block:: default plot_measurments(b0, b) .. image-sg:: /gallery/images/sphx_glr_0006_009.png :alt: Original measurements, Reconstructed measurements :srcset: /gallery/images/sphx_glr_0006_009.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 240-276 Comments --------- * We need 115 coefficients in the representation in the Daubechies basis to cover 99.9% of the signal energy. There are a total of 278 nonzero coefficients. Subspace Pursuit * With K=100 (< 115), Subspace Pursuit recovery is not very good (low SNR). It converges in 20 iterations. * With K=150, SP is pretty good. All detected nonzero coefficients are part of the true support. * With K=200, the SNR further improves to 54 dB. * With K=250, the SNR further improves to 83 dB. All detected coefficients are correct so far. * Pushing the sparsity to K=278 stars causing problems however. We can see the SNR drop to 76 dB. We can notice that only 243 of the detected 277 coefficients are correct coefficients. SPGL1 * We use the basis pursuit with inequality constraints version of SPGL1 in this example. * The allowed sigma for the residual norm :math:`\| \bA \bx - \bb \|_2` is chosen as a fraction of the norm of the measurements :math:`\| \bb \|_2`. * At a fraction of 0.01, SPGL1 converges in 106 iterations giving an SNR of 27 dB. * At a fraction of 0.001, SPGL1 converges in 486 iterations with an improved SNR of 29 dB. * It is interesting to note that while the measurement SNR has improved remarkably from 40 dB to 60 dB (as the target residual norm has reduced by a factor of 10), the improvement in signal SNR is not that good. Having a tighter bound on residual norm doesn't lead significantly better reconstruction. .. rst-class:: sphx-glr-timing **Total running time of the script:** (1 minutes 6.000 seconds) .. _sphx_glr_download_gallery_0006.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 0006.py <0006.py>` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 0006.ipynb <0006.ipynb>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_