Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Update to docs with regards to colorbar and colorizer #30112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 15 additions & 33 deletions galleries/examples/images_contours_and_fields/multi_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@
value *x* in the image).

If we want one colorbar to be representative for multiple images, we have
to explicitly ensure consistent data coloring by using the same data
normalization for all the images. We ensure this by explicitly creating a
``norm`` object that we pass to all the image plotting methods.
to explicitly ensure consistent data coloring by using the same
data-to-color pipeline for all the images. We ensure this by explicitly
creating a `matplotlib.colorizer.Colorizer` object that we pass to all
the image plotting methods.
"""

import matplotlib.pyplot as plt
import numpy as np

from matplotlib import colors
import matplotlib.colorizer as mcolorizer
import matplotlib.colors as mcolors

np.random.seed(19680801)

Expand All @@ -31,12 +33,13 @@
fig, axs = plt.subplots(2, 2)
fig.suptitle('Multiple images')

# create a single norm to be shared across all images
norm = colors.Normalize(vmin=np.min(datasets), vmax=np.max(datasets))
# create a colorizer with a predefined norm to be shared across all images
norm = mcolors.Normalize(vmin=np.min(datasets), vmax=np.max(datasets))
colorizer = mcolorizer.Colorizer(norm=norm)

images = []
for ax, data in zip(axs.flat, datasets):
images.append(ax.imshow(data, norm=norm))
images.append(ax.imshow(data, colorizer=colorizer))

fig.colorbar(images[0], ax=axs, orientation='horizontal', fraction=.1)

Expand All @@ -45,30 +48,10 @@
# %%
# The colors are now kept consistent across all images when changing the
# scaling, e.g. through zooming in the colorbar or via the "edit axis,
# curves and images parameters" GUI of the Qt backend. This is sufficient
# for most practical use cases.
#
# Advanced: Additionally sync the colormap
# ----------------------------------------
#
# Sharing a common norm object guarantees synchronized scaling because scale
# changes modify the norm object in-place and thus propagate to all images
# that use this norm. This approach does not help with synchronizing colormaps
# because changing the colormap of an image (e.g. through the "edit axis,
# curves and images parameters" GUI of the Qt backend) results in the image
# referencing the new colormap object. Thus, the other images are not updated.
#
# To update the other images, sync the
# colormaps using the following code::
#
# def sync_cmaps(changed_image):
# for im in images:
# if changed_image.get_cmap() != im.get_cmap():
# im.set_cmap(changed_image.get_cmap())
#
# for im in images:
# im.callbacks.connect('changed', sync_cmaps)
#
# curves and images parameters" GUI of the Qt backend. Additionally,
# if the colormap of the colorizer is changed, (e.g. through the "edit
# axis, curves and images parameters" GUI of the Qt backend) this change
# propagates to the other plots and the colorbar.
#
# .. admonition:: References
#
Expand All @@ -77,6 +60,5 @@
#
# - `matplotlib.axes.Axes.imshow` / `matplotlib.pyplot.imshow`
# - `matplotlib.figure.Figure.colorbar` / `matplotlib.pyplot.colorbar`
# - `matplotlib.colorizer.Colorizer`
# - `matplotlib.colors.Normalize`
# - `matplotlib.cm.ScalarMappable.set_cmap`
# - `matplotlib.cbook.CallbackRegistry.connect`
38 changes: 26 additions & 12 deletions galleries/users_explain/colors/colorbar_only.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
This tutorial shows how to build and customize standalone colorbars, i.e.
without an attached plot.

A `~.Figure.colorbar` needs a "mappable" (`matplotlib.cm.ScalarMappable`)
object (typically, an image) which indicates the colormap and the norm to be
used. In order to create a colorbar without an attached image, one can instead
use a `.ScalarMappable` with no associated data.
A `~.Figure.colorbar` requires a `matplotlib.colorizer.ColorizingArtist` which
contains a `matplotlib.colorizer.Colorizer` that holds the data-to-color pipeline
(norm and colormap). To create a colorbar without an attached plot one can
directly instantiate the base class `.ColorizingArtist`, which has no associated
data.

"""

import matplotlib.pyplot as plt
Expand All @@ -23,17 +25,21 @@
# -------------------------
# Here, we create a basic continuous colorbar with ticks and labels.
#
# The arguments to the `~.Figure.colorbar` call are the `.ScalarMappable`
# (constructed using the *norm* and *cmap* arguments), the axes where the
# colorbar should be drawn, and the colorbar's orientation.
# The arguments to the `~.Figure.colorbar` call are a `.ColorizingArtist`,
# the axes where the colorbar should be drawn, and the colorbar's orientation.
# To crate a `.ColorizingArtist` one must first make `.Colorizer` that holds the
# desired *norm* and *cmap*.
#
#
# For more information see the `~matplotlib.colorbar` API.

fig, ax = plt.subplots(figsize=(6, 1), layout='constrained')

norm = mpl.colors.Normalize(vmin=5, vmax=10)

fig.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap="cool"),
colorizer = mpl.colorizer.Colorizer(norm=norm, cmap="cool")

fig.colorbar(mpl.colorizer.ColorizingArtist(colorizer),
cax=ax, orientation='horizontal', label='Some Units')

# %%
Expand All @@ -47,7 +53,9 @@

fig, ax = plt.subplots(layout='constrained')

fig.colorbar(mpl.cm.ScalarMappable(norm=mpl.colors.Normalize(0, 1), cmap='magma'),
colorizer = mpl.colorizer.Colorizer(norm=mpl.colors.Normalize(0, 1), cmap='magma')

fig.colorbar(mpl.colorizer.ColorizingArtist(colorizer),
ax=ax, orientation='vertical', label='a colorbar label')

# %%
Expand All @@ -65,7 +73,9 @@
bounds = [-1, 2, 5, 7, 12, 15]
norm = mpl.colors.BoundaryNorm(bounds, cmap.N, extend='both')

fig.colorbar(mpl.cm.ScalarMappable(norm=norm, cmap="viridis"),
colorizer = mpl.colorizer.Colorizer(norm=norm, cmap='viridis')

fig.colorbar(mpl.colorizer.ColorizingArtist(colorizer),
cax=ax, orientation='horizontal',
label="Discrete intervals with extend='both' keyword")

Expand Down Expand Up @@ -94,8 +104,10 @@
bounds = [1, 2, 4, 7, 8]
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)

colorizer = mpl.colorizer.Colorizer(norm=norm, cmap=cmap)

fig.colorbar(
mpl.cm.ScalarMappable(cmap=cmap, norm=norm),
mpl.colorizer.ColorizingArtist(colorizer),
cax=ax, orientation='horizontal',
extend='both',
spacing='proportional',
Expand All @@ -116,8 +128,10 @@
bounds = [-1.0, -0.5, 0.0, 0.5, 1.0]
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)

colorizer = mpl.colorizer.Colorizer(norm=norm, cmap=cmap)

fig.colorbar(
mpl.cm.ScalarMappable(cmap=cmap, norm=norm),
mpl.colorizer.ColorizingArtist(colorizer),
cax=ax, orientation='horizontal',
extend='both', extendfrac='auto',
spacing='uniform',
Expand Down
12 changes: 7 additions & 5 deletions lib/matplotlib/colorbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
import numpy as np

import matplotlib as mpl
from matplotlib import _api, cbook, collections, cm, colors, contour, ticker
from matplotlib import _api, cbook, collections, colors, contour, ticker
import matplotlib.artist as martist
import matplotlib.colorizer as mcolorizer
import matplotlib.patches as mpatches
import matplotlib.path as mpath
import matplotlib.spines as mspines
Expand Down Expand Up @@ -199,12 +200,12 @@ class Colorbar:
Draw a colorbar in an existing Axes.

Typically, colorbars are created using `.Figure.colorbar` or
`.pyplot.colorbar` and associated with `.ScalarMappable`\s (such as an
`.pyplot.colorbar` and associated with `.ColorizingArtist`\s (such as an
`.AxesImage` generated via `~.axes.Axes.imshow`).

In order to draw a colorbar not associated with other elements in the
figure, e.g. when showing a colormap by itself, one can create an empty
`.ScalarMappable`, or directly pass *cmap* and *norm* instead of *mappable*
`.ColorizingArtist`, or directly pass *cmap* and *norm* instead of *mappable*
to `Colorbar`.

Useful public methods are :meth:`set_label` and :meth:`add_lines`.
Expand Down Expand Up @@ -244,7 +245,7 @@ def __init__(
ax : `~matplotlib.axes.Axes`
The `~.axes.Axes` instance in which the colorbar is drawn.

mappable : `.ScalarMappable`
mappable : `.ColorizingArtist`
The mappable whose colormap and norm will be used.

To show the colors versus index instead of on a 0-1 scale, set the
Expand Down Expand Up @@ -288,7 +289,8 @@ def __init__(
colorbar and at the right for a vertical.
"""
if mappable is None:
mappable = cm.ScalarMappable(norm=norm, cmap=cmap)
colorizer = mcolorizer.Colorizer(norm=norm, cmap=cmap)
mappable = mcolorizer.ColorizingArtist(colorizer)

self.mappable = mappable
cmap = mappable.cmap
Expand Down
9 changes: 5 additions & 4 deletions lib/matplotlib/figure.py
Original file line number Diff line number Diff line change
Expand Up @@ -1200,17 +1200,18 @@ def colorbar(
Parameters
----------
mappable
The `matplotlib.cm.ScalarMappable` (i.e., `.AxesImage`,
The `matplotlib.colorizer.ColorizingArtist` (i.e., `.AxesImage`,
`.ContourSet`, etc.) described by this colorbar. This argument is
mandatory for the `.Figure.colorbar` method but optional for the
`.pyplot.colorbar` function, which sets the default to the current
image.

Note that one can create a `.ScalarMappable` "on-the-fly" to
generate colorbars not attached to a previously drawn artist, e.g.
Note that one can create a `.colorizer.ColorizingArtist` "on-the-fly"
to generate colorbars not attached to a previously drawn artist, e.g.
::

fig.colorbar(cm.ScalarMappable(norm=norm, cmap=cmap), ax=ax)
cr = colorizer.Colorizer(norm=norm, cmap=cmap)
fig.colorbar(colorizer.ColorizingArtist(cr), ax=ax)

cax : `~matplotlib.axes.Axes`, optional
Axes into which the colorbar will be drawn. If `None`, then a new
Expand Down
Loading