.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "getting_started/examples/gallery/basic_usage.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_getting_started_examples_gallery_basic_usage.py: Basic usage =========== This example demonstrates the basic usage of combined TFRs and how to compute and plot them using the ctfr package. .. GENERATED FROM PYTHON SOURCE LINES 9-15 .. code-block:: Python import ctfr import numpy as np import matplotlib.pyplot as plt .. GENERATED FROM PYTHON SOURCE LINES 16-18 -------------- .. GENERATED FROM PYTHON SOURCE LINES 21-24 Loading the audio data ~~~~~~~~~~~~~~~~~~~~~~ .. GENERATED FROM PYTHON SOURCE LINES 27-36 Our synthetic example consists of :math:`1` s of audio data sampled at :math:`22050 Hz`. The signal is comprised of two superposed sinusoidal components with frequencies :math:`f_1 = 440` Hz and :math:`f_2 = 506` Hz, as well as a pulse component with a short duration around :math:`t = 0.5` s. We will see how the ctfr package can help us compute a combined TFR of STFTs with good resolution in both time and frequency domains, which is not possible with a traditional STFT. Let’s load the audio data and plot it. .. GENERATED FROM PYTHON SOURCE LINES 36-43 .. code-block:: Python # Load the audio signal. signal, sr = ctfr.load(ctfr.fetch_sample("synthetic"), sr=22050) # For a local file, use ctfr.load("path/to/file") print(f"Sample rate: {sr} Hz") plt.plot(signal); .. image-sg:: /getting_started/examples/gallery/images/sphx_glr_basic_usage_001.png :alt: basic usage :srcset: /getting_started/examples/gallery/images/sphx_glr_basic_usage_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Sample rate: 22050 Hz [] .. GENERATED FROM PYTHON SOURCE LINES 44-46 -------------- .. GENERATED FROM PYTHON SOURCE LINES 49-52 Computing STFT spectrograms with different resolutions. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. GENERATED FROM PYTHON SOURCE LINES 55-60 Now, let’s compute and plot an STFT spectrogram of the audio signal. We will use a window length of :math:`L = 512` samples (approximately :math:`23` ms), a hop length of :math:`512` samples, and a FFT size of :math:`2048` samples. .. GENERATED FROM PYTHON SOURCE LINES 60-70 .. code-block:: Python # Compute the spectrogram with L = 512. spec_512 = ctfr.stft_spec(signal, win_length=512, n_fft=2048, hop_length=256) # Plot the spectrogram. img = ctfr.specshow(ctfr.power_to_db(spec_512, ref=np.max), sr=sr, hop_length=256, x_axis="time", y_axis="linear", cmap="inferno") plt.ylim(0, 1000) plt.colorbar(img, format="%+2.0f dB"); .. image-sg:: /getting_started/examples/gallery/images/sphx_glr_basic_usage_002.png :alt: basic usage :srcset: /getting_started/examples/gallery/images/sphx_glr_basic_usage_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 71-79 We can see that the the pulse component’s onset and offset are well delineated, but the sinusoidal components are not well resolved in the frequency domain. This is due to the short window length, which provides good time resolution but poor frequency resolution. Now, let’s increase the window length to :math:`L = 1024` samples (~ :math:`46` ms) and plot the STFT spectrogram again. .. GENERATED FROM PYTHON SOURCE LINES 79-89 .. code-block:: Python # Compute the spectrogram with L = 1024. spec_1024 = ctfr.stft_spec(signal, win_length=1024, n_fft=2048, hop_length=256) # Plot the spectrogram. img = ctfr.specshow(ctfr.power_to_db(spec_1024, ref=np.max), sr=sr, hop_length=256, x_axis="time", y_axis="linear", cmap="inferno") plt.ylim(0, 1000) plt.colorbar(img, format="%+2.0f dB"); .. image-sg:: /getting_started/examples/gallery/images/sphx_glr_basic_usage_003.png :alt: basic usage :srcset: /getting_started/examples/gallery/images/sphx_glr_basic_usage_003.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 90-97 We can see that our frequency resolution is improved at the cost of poorer time resolution. Let’s go even further and increase our window length to :math:`L = 2048` samples (~ :math:`93` ms), compute the corresponding STFT and plot the resulting spectrogram. .. GENERATED FROM PYTHON SOURCE LINES 97-107 .. code-block:: Python # Compute the spectrogram with L = 2048. spec_2048 = ctfr.stft_spec(signal, win_length=2048, n_fft=2048, hop_length=256) # Plot the spectrogram. img = ctfr.specshow(ctfr.power_to_db(spec_2048, ref=np.max), sr=sr, hop_length=256, x_axis="time", y_axis="linear", cmap="inferno") plt.ylim(0, 1000) plt.colorbar(img, format="%+2.0f dB"); .. image-sg:: /getting_started/examples/gallery/images/sphx_glr_basic_usage_004.png :alt: basic usage :srcset: /getting_started/examples/gallery/images/sphx_glr_basic_usage_004.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 108-112 With this larger window length, our sinusoidal components are now well resolved in the frequency domain, but the pulse component’s onset and offset are not well delineated. .. GENERATED FROM PYTHON SOURCE LINES 115-117 -------------- .. GENERATED FROM PYTHON SOURCE LINES 120-123 Computing a combined TFR ~~~~~~~~~~~~~~~~~~~~~~~~ .. GENERATED FROM PYTHON SOURCE LINES 126-136 In summary, what we have seen is the time-frequency trade-off. Achieving better frequency resolution (by increasing the window length) comes at the cost of poorer time resolution, and vice versa. However, we can circumvent this problem by computing a combined TFR, which is an average (in a generalized sense) of multiple STFTs computed with different window lengths. This allows us to achieve good resolution in both time and frequency domains. Let’s see how we can do this using the package. .. GENERATED FROM PYTHON SOURCE LINES 139-142 Using ctfr.ctfr_from_specs ^^^^^^^^^^^^^^^^^^^^^^^^^^ .. GENERATED FROM PYTHON SOURCE LINES 145-151 Since we have already computed STFTs with different window lengths, we can use the ``ctfr_from_specs`` function to compute a combined TFR from these STFT spectrograms. This function requires an iterable of STFT spectrograms with the same time-frequency alignment. Since we used the same hop length and FFT size for all STFTs, they are already aligned. .. GENERATED FROM PYTHON SOURCE LINES 151-157 .. code-block:: Python print(spec_512.shape) print(spec_1024.shape) print(spec_2048.shape) .. rst-class:: sphx-glr-script-out .. code-block:: none (1025, 87) (1025, 87) (1025, 87) .. GENERATED FROM PYTHON SOURCE LINES 158-161 We also have to provide a combination method. Let’s list all available methods: .. GENERATED FROM PYTHON SOURCE LINES 161-165 .. code-block:: Python ctfr.show_methods() .. rst-class:: sphx-glr-script-out .. code-block:: none Available combination methods: - Binwise mean -- mean - Binwise harmonic mean -- hmean - Binwise geometric mean -- gmean - Binwise minimum -- min - Sample-weighted geometric mean (SWGM) -- swgm - Fast local sparsity (FLS) -- fls - Lukin-Todd (LT) -- lt - Hybrid smoothed local sparsity (SLS-H) -- sls_h - Smoothed local sparsity with interpolation (SLS-I) -- sls_i .. GENERATED FROM PYTHON SOURCE LINES 166-170 For this example, we’ll use the Sample-Weighted Geometric Mean (SWGM), which is a lightweight and effective binwise combination method. Let’s compute the combined TFR and plot it. .. GENERATED FROM PYTHON SOURCE LINES 170-180 .. code-block:: Python # Compute the combined spectrogram using ctfr.ctfr_from_specs and the SWGM method, swgm_spec = ctfr.ctfr_from_specs((spec_512, spec_1024, spec_2048), method="swgm") # Plot the combined spectrogram. img = ctfr.specshow(ctfr.power_to_db(swgm_spec, ref=np.max), sr=sr, hop_length=256, x_axis="time", y_axis="linear", cmap="inferno") plt.ylim(0, 1000) plt.colorbar(img, format="%+2.0f dB"); .. image-sg:: /getting_started/examples/gallery/images/sphx_glr_basic_usage_005.png :alt: basic usage :srcset: /getting_started/examples/gallery/images/sphx_glr_basic_usage_005.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 181-186 .. note:: You can also use ``ctfr.methods.swgm_from_specs(X, ...)``, which is an alias for ``ctfr.ctfr_from_specs(X, method="swgm", ...)``. .. GENERATED FROM PYTHON SOURCE LINES 189-193 As we can see, we have achieved good resolution in both time and frequency domains, with the sinusoidal components and the pulse component well resolved. .. GENERATED FROM PYTHON SOURCE LINES 196-198 -------------- .. GENERATED FROM PYTHON SOURCE LINES 201-204 Using ctfr.ctfr ^^^^^^^^^^^^^^^ .. GENERATED FROM PYTHON SOURCE LINES 207-215 Using ``ctfr_from_specs`` is useful when we already have the STFT spectrograms to combine, or when we want more control over how to generate them. When we just want to compute a combined TFR directly from an audio signal, we can use the ``ctfr`` function, which computes the STFT spectrograms with different window lengths and then combines them. Let’s do this for our signal, using the same parameters as before. .. GENERATED FROM PYTHON SOURCE LINES 215-225 .. code-block:: Python # Compute the combined spectrogram using ctfr.ctfr and the SWGM method, swgm_spec_2 = ctfr.ctfr(signal, sr = sr, method = "swgm", win_lengths=[512, 1024, 2048], hop_length=256, n_fft=2048) # Plot the combined spectrogram. img = ctfr.specshow(ctfr.power_to_db(swgm_spec_2, ref=np.max), sr=sr, hop_length=512, x_axis="time", y_axis="linear", cmap="inferno") plt.ylim(0, 1000) plt.colorbar(img, format="%+2.0f dB"); .. image-sg:: /getting_started/examples/gallery/images/sphx_glr_basic_usage_006.png :alt: basic usage :srcset: /getting_started/examples/gallery/images/sphx_glr_basic_usage_006.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 226-230 .. note:: You can also use ``ctfr.methods.swgm(X, sr, ...)``, which is an alias for ``ctfr.ctfr(X, sr, method="swgm", ...)``. .. GENERATED FROM PYTHON SOURCE LINES 233-237 We can see that the combined spectrogram looks the same as the one we computed in the previous section. Let’s confirm that they’re indeed the same: .. GENERATED FROM PYTHON SOURCE LINES 237-238 .. code-block:: Python np.array_equal(swgm_spec, swgm_spec_2) .. rst-class:: sphx-glr-script-out .. code-block:: none True .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 14.153 seconds) .. _sphx_glr_download_getting_started_examples_gallery_basic_usage.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: basic_usage.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: basic_usage.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: basic_usage.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_