1
1
"""
2
- ===============
3
- Multiple images
4
- ===============
2
+ =================================
3
+ Multiple images with one colorbar
4
+ =================================
5
5
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.
7
17
"""
8
18
9
19
import matplotlib .pyplot as plt
12
22
from matplotlib import colors
13
23
14
24
np .random .seed (19680801 )
15
- Nr = 3
16
- Nc = 2
17
25
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 )
19
32
fig .suptitle ('Multiple images' )
20
33
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 ))
28
36
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 ))
35
40
36
41
fig .colorbar (images [0 ], ax = axs , orientation = 'horizontal' , fraction = .1 )
37
42
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
-
53
43
plt .show ()
54
44
55
45
# %%
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
+ #
56
72
#
57
73
# .. admonition:: References
58
74
#
@@ -63,6 +79,4 @@ def update(changed_image):
63
79
# - `matplotlib.figure.Figure.colorbar` / `matplotlib.pyplot.colorbar`
64
80
# - `matplotlib.colors.Normalize`
65
81
# - `matplotlib.cm.ScalarMappable.set_cmap`
66
- # - `matplotlib.cm.ScalarMappable.set_norm`
67
- # - `matplotlib.cm.ScalarMappable.set_clim`
68
82
# - `matplotlib.cbook.CallbackRegistry.connect`
0 commit comments