.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/plot_display.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_auto_examples_plot_display.py: ====================== Using display.specshow ====================== This notebook gives a more in-depth demonstration of all things that `specshow` can do to help generate beautiful visualizations of spectro-temporal data. .. GENERATED FROM PYTHON SOURCE LINES 11-16 .. code-block:: Python # Code source: Brian McFee # License: ISC # sphinx_gallery_thumbnail_number = 6 .. GENERATED FROM PYTHON SOURCE LINES 17-20 All of librosa's plotting functions rely on matplotlib. To demonstrate everything we can do, it will help to import matplotlib's pyplot API here. .. GENERATED FROM PYTHON SOURCE LINES 20-25 .. code-block:: Python import numpy as np import matplotlib.pyplot as plt import librosa .. GENERATED FROM PYTHON SOURCE LINES 26-27 First, we'll load in a demo track .. GENERATED FROM PYTHON SOURCE LINES 27-31 .. code-block:: Python y, sr = librosa.load(librosa.ex('trumpet')) .. GENERATED FROM PYTHON SOURCE LINES 32-38 The first thing we might want to do is display an ordinary (linear) spectrogram. We'll do this by first computing the short-time Fourier transform, and then mapping the magnitudes to a decibel scale. .. GENERATED FROM PYTHON SOURCE LINES 38-42 .. code-block:: Python D = librosa.stft(y) # STFT of y S_db = librosa.amplitude_to_db(np.abs(D), ref=np.max) .. GENERATED FROM PYTHON SOURCE LINES 43-49 If you're familiar with matplotlib already, you may know that there are two ways of using it: the `pyplot` interface and the object-oriented interface. Both are supported by librosa, as we'll show here. First, the pyplot interface: .. GENERATED FROM PYTHON SOURCE LINES 49-54 .. code-block:: Python plt.figure() librosa.display.specshow(S_db) plt.colorbar() .. image-sg:: /auto_examples/images/sphx_glr_plot_display_001.png :alt: plot display :srcset: /auto_examples/images/sphx_glr_plot_display_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 55-56 And now the object-oriented interface .. GENERATED FROM PYTHON SOURCE LINES 56-61 .. code-block:: Python fig, ax = plt.subplots() img = librosa.display.specshow(S_db, ax=ax) fig.colorbar(img, ax=ax) .. image-sg:: /auto_examples/images/sphx_glr_plot_display_002.png :alt: plot display :srcset: /auto_examples/images/sphx_glr_plot_display_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 62-69 Both figures are identical, but they use different programming interfaces to construct. Most people find the pyplot interface to be quicker to learn, but the object-oriented interface can be a little more flexible for complex figures. For the remainder of this example, we'll use the object-oriented interface. .. GENERATED FROM PYTHON SOURCE LINES 71-82 Decorating your plot -------------------- The figure above conveys the basic content of the spectrogram, but it's missing axis labels. Without that information, it's impossible for a reader to know how to interpret the visualization. specshow provides many helpers to automatically decorate the axes of your plot. For the plot above, our x-axis corresponds to time, and our y-axis corresponds to linearly spaced frequencies produced by the discrete Fourier transform. We can tell specshow to decorate the axes accordingly: .. GENERATED FROM PYTHON SOURCE LINES 82-88 .. code-block:: Python fig, ax = plt.subplots() img = librosa.display.specshow(S_db, x_axis='time', y_axis='linear', ax=ax) ax.set(title='Now with labeled axes!') fig.colorbar(img, ax=ax, format="%+2.f dB") .. image-sg:: /auto_examples/images/sphx_glr_plot_display_003.png :alt: Now with labeled axes! :srcset: /auto_examples/images/sphx_glr_plot_display_003.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 89-91 This is much better already! Note that we also added a format string to the colorbar, so readers know how to read the color scale. .. GENERATED FROM PYTHON SOURCE LINES 93-101 Changing axis scales -------------------- The linear frequency scale is sometimes helpful, but often it can difficult to read. Alternatively, it is common to use a logarithmic frequency axis. This has the benefit that every octave occupies a constant vertical extent. We can tell specshow to use log-scaled frequency axes just as above: .. GENERATED FROM PYTHON SOURCE LINES 101-107 .. code-block:: Python fig, ax = plt.subplots() img = librosa.display.specshow(S_db, x_axis='time', y_axis='log', ax=ax) ax.set(title='Using a logarithmic frequency axis') fig.colorbar(img, ax=ax, format="%+2.f dB") .. image-sg:: /auto_examples/images/sphx_glr_plot_display_004.png :alt: Using a logarithmic frequency axis :srcset: /auto_examples/images/sphx_glr_plot_display_004.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 108-115 Changing the analysis parameters -------------------------------- The default parameter settings used by librosa (e.g., `sr=22050`, `hop_length=512`, etc) may not be appropriate for every signal. If you change a parameter from its default value, e.g. when computing an STFT, you can pass that same parameter to `specshow`. This ensures that axis scales (e.g. time or frequency) are computed correctly. .. GENERATED FROM PYTHON SOURCE LINES 115-124 .. code-block:: Python fig, ax = plt.subplots() D_highres = librosa.stft(y, hop_length=256, n_fft=4096) S_db_hr = librosa.amplitude_to_db(np.abs(D_highres), ref=np.max) img = librosa.display.specshow(S_db_hr, hop_length=256, x_axis='time', y_axis='log', ax=ax) ax.set(title='Higher time and frequency resolution') fig.colorbar(img, ax=ax, format="%+2.f dB") .. image-sg:: /auto_examples/images/sphx_glr_plot_display_005.png :alt: Higher time and frequency resolution :srcset: /auto_examples/images/sphx_glr_plot_display_005.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 125-131 Note that only the parameters which are strictly necessary are supported by `specshow`. For example, without the `hop_length`, we wouldn't know how to translate frame indices to time indices. A full list of the supported parameters is provided in the `librosa.display.specshow` documentation. .. GENERATED FROM PYTHON SOURCE LINES 133-141 Other types of spectral data ---------------------------- The examples above illustrate how to plot linear spectrograms, but librosa provides many kinds of spectral representations: Mel-scaled, constant-Q, variable-Q, chromagrams, tempograms, etc. specshow can plot these just as well. For example, a Mel spectrogram can be displayed as follows: .. GENERATED FROM PYTHON SOURCE LINES 141-149 .. code-block:: Python fig, ax = plt.subplots() M = librosa.feature.melspectrogram(y=y, sr=sr) M_db = librosa.power_to_db(M, ref=np.max) img = librosa.display.specshow(M_db, y_axis='mel', x_axis='time', ax=ax) ax.set(title='Mel spectrogram display') fig.colorbar(img, ax=ax, format="%+2.f dB") .. image-sg:: /auto_examples/images/sphx_glr_plot_display_006.png :alt: Mel spectrogram display :srcset: /auto_examples/images/sphx_glr_plot_display_006.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 150-153 Constant-Q plots, and other logarithmically scaled frequency representations such as Variable-Q or `iirt` can be decorated using either the frequencies (Hz) or their note names in scientific pitch notation: .. GENERATED FROM PYTHON SOURCE LINES 153-165 .. code-block:: Python C = librosa.cqt(y=y, sr=sr) C_db = librosa.amplitude_to_db(np.abs(C), ref=np.max) fig, ax = plt.subplots() librosa.display.specshow(C_db, y_axis='cqt_hz', x_axis='time', ax=ax) ax.set(title='Frequency (Hz) axis decoration') fig, ax = plt.subplots() librosa.display.specshow(C_db, y_axis='cqt_note', x_axis='time', ax=ax) ax.set(title='Pitch axis decoration') .. rst-class:: sphx-glr-horizontal * .. image-sg:: /auto_examples/images/sphx_glr_plot_display_007.png :alt: Frequency (Hz) axis decoration :srcset: /auto_examples/images/sphx_glr_plot_display_007.png :class: sphx-glr-multi-img * .. image-sg:: /auto_examples/images/sphx_glr_plot_display_008.png :alt: Pitch axis decoration :srcset: /auto_examples/images/sphx_glr_plot_display_008.png :class: sphx-glr-multi-img .. GENERATED FROM PYTHON SOURCE LINES 166-168 In the latter case, the underlying data representation is still measured in Hz; only the tick labels are changed. .. GENERATED FROM PYTHON SOURCE LINES 170-173 Chroma representations don't have a fixed frequency axis, and instead aggregate information across all frequencies corresponding to a given pitch class. specshow can plot these too: .. GENERATED FROM PYTHON SOURCE LINES 173-180 .. code-block:: Python chroma = librosa.feature.chroma_cqt(y=y, sr=sr) fig, ax = plt.subplots() img = librosa.display.specshow(chroma, y_axis='chroma', x_axis='time', ax=ax) ax.set(title='Chromagram demonstration') fig.colorbar(img, ax=ax) .. image-sg:: /auto_examples/images/sphx_glr_plot_display_009.png :alt: Chromagram demonstration :srcset: /auto_examples/images/sphx_glr_plot_display_009.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 181-183 If you also happen to know the key of the piece being analyzed, you can pass this to specshow and it will spell the notes properly: .. GENERATED FROM PYTHON SOURCE LINES 183-189 .. code-block:: Python fig, ax = plt.subplots() img = librosa.display.specshow(chroma, y_axis='chroma', x_axis='time', key='Eb:maj', ax=ax) ax.set(title='Chromagram explicitly in Eb:maj') fig.colorbar(img, ax=ax) .. image-sg:: /auto_examples/images/sphx_glr_plot_display_010.png :alt: Chromagram explicitly in Eb:maj :srcset: /auto_examples/images/sphx_glr_plot_display_010.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 190-191 This will also work for 'cqt_note' mode. .. GENERATED FROM PYTHON SOURCE LINES 193-195 Indian notation systems ----------------------- .. GENERATED FROM PYTHON SOURCE LINES 195-204 .. code-block:: Python # The examples above use Western music notation to identify pitch classes, but we can # also decorate axes with either Hindustani or Carnatic svara classes. # # These are specified by using `y_axis='chroma_h'` or `'chroma_c'`, respectively. # # Just as with key identification in the chroma example above, you can specify the # thaat (Hindustani) or melakarta number or name (Carnatic) to notate the plot. .. GENERATED FROM PYTHON SOURCE LINES 205-207 For example, the example above is in Eb:maj (or, more accurately, F:dorian), which we can also represent in Hindustani notation as Sa=5 (F) and 'kafi' thaat: .. GENERATED FROM PYTHON SOURCE LINES 207-214 .. code-block:: Python fig, ax = plt.subplots() img = librosa.display.specshow(chroma, y_axis='chroma_h', x_axis='time', Sa=5, thaat='kafi', ax=ax) ax.set(title='Chromagram with Hindustani notation') fig.colorbar(img, ax=ax) .. image-sg:: /auto_examples/images/sphx_glr_plot_display_011.png :alt: Chromagram with Hindustani notation :srcset: /auto_examples/images/sphx_glr_plot_display_011.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 215-218 In Carnatic notation, we would use melakarta #22. Note: `thaat` is optional for Hindustani notation, but `mela` is required for Carnatic. .. GENERATED FROM PYTHON SOURCE LINES 218-225 .. code-block:: Python fig, ax = plt.subplots() img = librosa.display.specshow(chroma, y_axis='chroma_c', x_axis='time', Sa=5, mela=22, ax=ax) ax.set(title='Chromagram with Carnatic notation') fig.colorbar(img, ax=ax) .. image-sg:: /auto_examples/images/sphx_glr_plot_display_012.png :alt: Chromagram with Carnatic notation :srcset: /auto_examples/images/sphx_glr_plot_display_012.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 226-234 These notation schemes can also be used in cqt plots by specifying `y_axis='cqt_svara'`. In this mode, `Sa` must be specified in Hz. Carnatic notation is used if `mela` is provided, and Hindustani is used if not. Individual svara are only notated if the display range is sufficiently small, so we'll zoom into a single octave for this example. .. GENERATED FROM PYTHON SOURCE LINES 234-246 .. code-block:: Python Sa = librosa.note_to_hz('F4') fig, ax = plt.subplots() librosa.display.specshow(C_db, y_axis='cqt_svara', Sa=Sa, x_axis='time', ax=ax) ax.set(title='Hindustani decoration', ylim=[Sa, 2*Sa]) fig, ax = plt.subplots() librosa.display.specshow(C_db, y_axis='cqt_svara', Sa=Sa, mela=22, x_axis='time', ax=ax) ax.set(title='Carnatic decoration', ylim=[Sa, 2*Sa]) .. rst-class:: sphx-glr-horizontal * .. image-sg:: /auto_examples/images/sphx_glr_plot_display_013.png :alt: Hindustani decoration :srcset: /auto_examples/images/sphx_glr_plot_display_013.png :class: sphx-glr-multi-img * .. image-sg:: /auto_examples/images/sphx_glr_plot_display_014.png :alt: Carnatic decoration :srcset: /auto_examples/images/sphx_glr_plot_display_014.png :class: sphx-glr-multi-img .. GENERATED FROM PYTHON SOURCE LINES 247-252 Non-spectral data ----------------- specshow can also be used for data that isn't exactly spectro-temporal. One common application is recurrence (self-similarity) plots, which are time-by-time, as illustrated below. .. GENERATED FROM PYTHON SOURCE LINES 252-259 .. code-block:: Python R = librosa.segment.recurrence_matrix(chroma, mode='affinity') fig, ax = plt.subplots() img = librosa.display.specshow(R, y_axis='time', x_axis='time', ax=ax) ax.set(title='Recurrence / self-similarity') fig.colorbar(img, ax=ax) .. image-sg:: /auto_examples/images/sphx_glr_plot_display_015.png :alt: Recurrence / self-similarity :srcset: /auto_examples/images/sphx_glr_plot_display_015.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 260-264 In this example, notice that we used 'time' for both axis labels. In general, any of the supported modes can be used for either axis. For example, we could also plot the chroma covariance plot with chroma decorations on each axis: .. GENERATED FROM PYTHON SOURCE LINES 264-272 .. code-block:: Python ccov = np.cov(chroma) fig, ax = plt.subplots() img = librosa.display.specshow(ccov, y_axis='chroma', x_axis='chroma', key='Eb:maj', ax=ax) ax.set(title='Chroma covariance') fig.colorbar(img, ax=ax) .. image-sg:: /auto_examples/images/sphx_glr_plot_display_016.png :alt: Chroma covariance :srcset: /auto_examples/images/sphx_glr_plot_display_016.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 273-275 Certain plots (e.g. covariance, self-similarity) are automatically squared by `specshow`. To override that, pass `auto_scale=False`. .. GENERATED FROM PYTHON SOURCE LINES 277-294 Color maps ---------- You may have noticed that the color mappings for the images above were selected automatically by `specshow`. This is done by `librosa.display.cmap` according to the following heuristic: - If the data is boolean, use black-and-white - If the data is (mostly) positive or (mostly) negative, use a sequential colormap - If the data contains both positive and negative values, use a diverging colormap. The default sequential colormap is 'magma', which is perceptually uniform and converts gracefully to grayscale. You can always override this automatic colormap selection by setting an explicit `cmap`: .. GENERATED FROM PYTHON SOURCE LINES 294-300 .. code-block:: Python fig, ax = plt.subplots() img = librosa.display.specshow(S_db, cmap='gray_r', y_axis='log', x_axis='time', ax=ax) ax.set(title='Inverted grayscale') fig.colorbar(img, ax=ax, format="%+2.f dB") .. image-sg:: /auto_examples/images/sphx_glr_plot_display_017.png :alt: Inverted grayscale :srcset: /auto_examples/images/sphx_glr_plot_display_017.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 301-306 `specshow` uses `matplotlib.pyplot.pcolormesh` to generate the underlying image. Any parameters to `pcolormesh` can be passed through from `specshow`, for example, to set explicit bounds on the minimum and maximum ranges for colors. This can be helpful when centering divergent colormaps around 0 (or some other reference point). .. GENERATED FROM PYTHON SOURCE LINES 306-315 .. code-block:: Python max_var = np.max(np.abs(ccov)) fig, ax = plt.subplots() img = librosa.display.specshow(ccov, vmin=-max_var, vmax=max_var, y_axis='chroma', x_axis='chroma', key='Eb:maj', ax=ax) ax.set(title='Chroma covariance') fig.colorbar(img, ax=ax) .. image-sg:: /auto_examples/images/sphx_glr_plot_display_018.png :alt: Chroma covariance :srcset: /auto_examples/images/sphx_glr_plot_display_018.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 316-322 Multiple plots -------------- Often, we'll want to show multiple synchronized features simultaneously. This can be done using matplotlib's `subplot` mechanism and sharing axes. There are many examples of this throughout the librosa documentation, but here we'll go through it step by step. .. GENERATED FROM PYTHON SOURCE LINES 322-354 .. code-block:: Python # Construct a subplot grid with 3 rows and 1 column, sharing the x-axis) fig, ax = plt.subplots(nrows=3, ncols=1, sharex=True) # On the first subplot, show the original spectrogram img1 = librosa.display.specshow(S_db, x_axis='time', y_axis='log', ax=ax[0]) ax[0].set(title='STFT (log scale)') # On the second subplot, show the mel spectrogram img2 = librosa.display.specshow(M_db, x_axis='time', y_axis='mel', ax=ax[1]) ax[1].set(title='Mel') # On the third subplot, show the chroma features img3 = librosa.display.specshow(chroma, x_axis='time', y_axis='chroma', key='Eb:maj', ax=ax[2]) ax[2].set(title='Chroma') # To eliminate redundant axis labels, we'll use "label_outer" on all subplots: for ax_i in ax: ax_i.label_outer() # And we can share colorbars: fig.colorbar(img1, ax=[ax[0], ax[1]]) # Or have individual colorbars: fig.colorbar(img3, ax=[ax[2]]) # We can then even do fancy things like zoom into a particular time and frequency # region. Since the axes are shared, this will apply to all three subplots at once. ax[0].set(xlim=[1, 3]) # Zoom to seconds 1-3 .. image-sg:: /auto_examples/images/sphx_glr_plot_display_019.png :alt: STFT (log scale), Mel, Chroma :srcset: /auto_examples/images/sphx_glr_plot_display_019.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 355-368 Non-uniform axes ---------------- All of the examples so far have used either uniformly, linearly, or geometrically spaced axes. But sometimes, we have non-uniform sampling of data, and we'd like to plot it in natural coordinates. One example of this is when using beat-synchronous features in the common case where the tempo is not exactly fixed. To demonstrate this, we'll use a longer example clip. To specify non-uniform axis sampling, you will need to provide the `x_coords` (or `y_coords`) array indicating the position of each sample, as demonstrated below. .. GENERATED FROM PYTHON SOURCE LINES 368-401 .. code-block:: Python y, sr = librosa.load(librosa.ex('nutcracker')) chroma = librosa.feature.chroma_cqt(y=y, sr=sr) tempo, beats = librosa.beat.beat_track(y=y, sr=sr) # beats contains the frame indices of each detected beat # for synchronization and visualization, we'll need to expand this # to cover the limits of the data. This can be done as follows: beats = librosa.util.fix_frames(beats, x_min=0) # Now beat-synchronize the chroma features chroma_sync = librosa.util.sync(chroma, beats, aggregate=np.median) # For visualization, we can convert to time (in seconds) beat_times = librosa.frames_to_time(beats) # We'll plot the synchronized and unsynchronized features next # to each other fig, ax = plt.subplots(nrows=2, sharex=True) img = librosa.display.specshow(chroma, y_axis='chroma', x_axis='time', ax=ax[0], key='Eb:maj') ax[0].set(title='Uniform time sampling') ax[0].label_outer() librosa.display.specshow(chroma_sync, y_axis='chroma', x_axis='time', x_coords=beat_times, ax=ax[1], key='Eb:maj') ax[1].set(title='Beat-synchronous sampling') fig.colorbar(img, ax=ax) # For clarity, we'll zoom in on a 15-second patch ax[1].set(xlim=[10, 25]) .. image-sg:: /auto_examples/images/sphx_glr_plot_display_020.png :alt: Uniform time sampling, Beat-synchronous sampling :srcset: /auto_examples/images/sphx_glr_plot_display_020.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 402-410 Conclusion ---------- This series of examples demonstrates most of the functionality of `librosa.display.specshow`, but it does not exhaustively show every option, e.g., for axis decoration. Interested readers should look through the rest of the API documentation to see how these other options can be used effectively. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 9.729 seconds) .. _sphx_glr_download_auto_examples_plot_display.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_display.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_display.py ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_