1
1
"""
2
- ===========
3
- Multi Image
4
- ===========
2
+ ==================================
3
+ Multiple images sharing a colorbar
4
+ ==================================
5
5
6
- Make a set of images with a single colormap, norm, and colorbar.
7
- """
6
+ A colorbar is always connected to a single image (more precisely, to a single
7
+ `.ScalarMappable`). If we want to use multiple images with a single colorbar,
8
+ we have to create a colorbar for one of the images and make sure that the
9
+ other images use the same color mapping, i.e. the same Colormap and the same
10
+ `.Normalize` instance.
8
11
12
+ """
9
13
from matplotlib import colors
10
14
import matplotlib .pyplot as plt
11
15
import numpy as np
12
16
13
17
np .random .seed (19680801 )
14
- Nr = 3
15
- Nc = 2
16
- cmap = "cool"
18
+ nrows = 3
19
+ ncols = 2
20
+ cmap = "plasma"
21
+
22
+ data = [((1 + i ) / 10 ) * np .random .rand (11 , 21 ) * 1e-6
23
+ for i in range (nrows * ncols )]
24
+
25
+ #############################################################################
26
+ #
27
+ # All data available beforehand
28
+ # -----------------------------
29
+ #
30
+ # In the most simple case, we have all the image data sets available, e.g.
31
+ # in a list, before we start to plot. In this case, we create a common
32
+ # `.Normalize` instance scaling to the global min and max by passing all data
33
+ # to the *data* argument of Normalize. We then use this and a common colormap
34
+ # when creating the images.
35
+
36
+ fig , axs = plt .subplots (nrows , ncols , sharex = True , sharey = True )
37
+ fig .suptitle ('Multiple images sharing a colorbar' )
38
+
39
+ norm = colors .Normalize (data = data )
40
+ images = [ax .imshow (data , cmap = cmap , norm = norm )
41
+ for data , ax in zip (data , axs .flat )]
42
+ fig .colorbar (images [0 ], ax = axs , orientation = 'horizontal' , fraction = .06 )
43
+ plt .show ()
44
+
45
+ #############################################################################
46
+ #
47
+ # Not all data available beforehand
48
+ # ---------------------------------
49
+ #
50
+ # Things get a bit more complicated, if we don't have all the data beforehand,
51
+ # e.g. when we generate or load the data just before each plot command. In
52
+ # this case, the common norm has to be created and set afterwards. We can use
53
+ # a small helper function for that.
54
+
55
+ def normalize_images (images ):
56
+ """Normalize the given images to their global min and max."""
57
+ vmin = min (image .get_array ().min () for image in images )
58
+ vmax = max (image .get_array ().max () for image in images )
59
+ norm = colors .Normalize (vmin = vmin , vmax = vmax )
60
+ for im in images :
61
+ im .set_norm (norm )
62
+
17
63
18
- fig , axs = plt .subplots (Nr , Nc )
19
- fig .suptitle ('Multiple images' )
64
+ fig , axs = plt .subplots (nrows , ncols , sharex = True , sharey = True )
65
+ fig .suptitle ('Multiple images sharing a colorbar ' )
20
66
21
67
images = []
22
- for i in range (Nr ):
23
- for j in range (Nc ):
68
+ for i in range (nrows ):
69
+ for j in range (ncols ):
24
70
# Generate data with a range that varies from one plot to the next.
25
- data = ((1 + i + j ) / 10 ) * np .random .rand (10 , 20 ) * 1e-6
71
+ data = ((1 + i + j ) / 10 ) * np .random .rand (11 , 21 ) * 1e-6
26
72
images .append (axs [i , j ].imshow (data , cmap = cmap ))
27
- axs [i , j ].label_outer ()
28
-
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 )
73
+ normalize_images (images )
74
+ fig .colorbar (images [0 ], ax = axs , orientation = 'horizontal' , fraction = .06 )
35
75
36
- fig .colorbar (images [0 ], ax = axs , orientation = 'horizontal' , fraction = .1 )
37
76
77
+ #############################################################################
78
+ #
79
+ # Dynamically adapting to changes of the norm and cmap
80
+ # ----------------------------------------------------
81
+ #
82
+ # If the images norm or cmap can change later on (e.g. via the
83
+ # "edit axis, curves and images parameters" GUI on Qt), one can propagate
84
+ # these changes to all images by connecting to the 'changed' callback.
85
+ #
86
+ # Note: It's important to have the ``if`` statement to check whether there
87
+ # are really changes to apply. Otherwise, you would run into an infinite
88
+ # recursion with all images notifying each other infinitely.
38
89
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
90
def update (changed_image ):
43
91
for im in images :
44
92
if (changed_image .get_cmap () != im .get_cmap ()
@@ -50,7 +98,6 @@ def update(changed_image):
50
98
for im in images :
51
99
im .callbacksSM .connect ('changed' , update )
52
100
53
- plt .show ()
54
101
55
102
#############################################################################
56
103
#
0 commit comments