11"""
2- ===============
3- Multiple images
4- ===============
2+ =================================
3+ Multiple images with one colorbar
4+ =================================
55
6- Make a set of images with a single colormap, norm, and colorbar.
6+ Use a single colorbar for multiple images.
7+
8+ Currently, a colorbar can only be connected to one image. The connection
9+ guarantees that the data coloring is consistent with the colormap scale
10+ (i.e. the color of value *x* in the colormap is used for coloring a data
11+ value *x* in the image).
12+
13+ If we want one colorbar to be representative for multiple images, we have
14+ to explicitly ensure consistent data coloring by using the same data
15+ normalization for all the images. We ensure this by explicitly creating a
16+ ``norm`` object that we pass to all the image plotting methods.
717"""
818
919import matplotlib .pyplot as plt
1222from matplotlib import colors
1323
1424np .random .seed (19680801 )
15- Nr = 3
16- Nc = 2
1725
18- fig , axs = plt .subplots (Nr , Nc )
26+ datasets = [
27+ (i + 1 )/ 10 * np .random .rand (10 , 20 )
28+ for i in range (4 )
29+ ]
30+
31+ fig , axs = plt .subplots (2 , 2 )
1932fig .suptitle ('Multiple images' )
2033
21- images = []
22- for i in range (Nr ):
23- for j in range (Nc ):
24- # Generate data with a range that varies from one plot to the next.
25- data = ((1 + i + j ) / 10 ) * np .random .rand (10 , 20 )
26- images .append (axs [i , j ].imshow (data ))
27- axs [i , j ].label_outer ()
34+ # create a single norm to be shared across all images
35+ norm = colors .Normalize (vmin = np .min (datasets ), vmax = np .max (datasets ))
2836
29- # Find the min and max of all colors for use in setting the color scale.
30- vmin = min (image .get_array ().min () for image in images )
31- vmax = max (image .get_array ().max () for image in images )
32- norm = colors .Normalize (vmin = vmin , vmax = vmax )
33- for im in images :
34- im .set_norm (norm )
37+ images = []
38+ for ax , data in zip (axs .flat , datasets ):
39+ images .append (ax .imshow (data , norm = norm ))
3540
3641fig .colorbar (images [0 ], ax = axs , orientation = 'horizontal' , fraction = .1 )
3742
38-
39- # Make images respond to changes in the norm of other images (e.g. via the
40- # "edit axis, curves and images parameters" GUI on Qt), but be careful not to
41- # recurse infinitely!
42- def update (changed_image ):
43- for im in images :
44- if (changed_image .get_cmap () != im .get_cmap ()
45- or changed_image .get_clim () != im .get_clim ()):
46- im .set_cmap (changed_image .get_cmap ())
47- im .set_clim (changed_image .get_clim ())
48-
49-
50- for im in images :
51- im .callbacks .connect ('changed' , update )
52-
5343plt .show ()
5444
5545# %%
46+ # The colors are now kept consistent across all images when changing the
47+ # scaling, e.g. through zooming in the colorbar or via the "edit axis,
48+ # curves and images parameters" GUI of the Qt backend. This is sufficient
49+ # for most practical use cases.
50+ #
51+ # Advanced: Additionally sync the colormap
52+ # ----------------------------------------
53+ #
54+ # Sharing a common norm object guarantees synchronized scaling because scale
55+ # changes modify the norm object in-place and thus propagate to all images
56+ # that use this norm. This approach does not help with synchronizing colormaps
57+ # because changing the colormap of an image (e.g. through the "edit axis,
58+ # curves and images parameters" GUI of the Qt backend) results in the image
59+ # referencing the new colormap object. Thus, the other images are not updated.
60+ #
61+ # To update the other images, sync the
62+ # colormaps using the following code::
63+ #
64+ # def sync_cmaps(changed_image):
65+ # for im in images:
66+ # if changed_image.get_cmap() != im.get_cmap():
67+ # im.set_cmap(changed_image.get_cmap())
68+ #
69+ # for im in images:
70+ # im.callbacks.connect('changed', sync_cmaps)
71+ #
5672#
5773# .. admonition:: References
5874#
@@ -63,6 +79,4 @@ def update(changed_image):
6379# - `matplotlib.figure.Figure.colorbar` / `matplotlib.pyplot.colorbar`
6480# - `matplotlib.colors.Normalize`
6581# - `matplotlib.cm.ScalarMappable.set_cmap`
66- # - `matplotlib.cm.ScalarMappable.set_norm`
67- # - `matplotlib.cm.ScalarMappable.set_clim`
6882# - `matplotlib.cbook.CallbackRegistry.connect`
0 commit comments