Skip to content

Commit 85213e2

Browse files
authored
Merge pull request matplotlib#27729 from QuLogic/cmap-norm
DOC: Improve colormap normalization example
2 parents e470c70 + ffa4556 commit 85213e2

File tree

1 file changed

+81
-72
lines changed

1 file changed

+81
-72
lines changed

galleries/examples/images_contours_and_fields/colormap_normalizations.py

+81-72
Original file line numberDiff line numberDiff line change
@@ -13,85 +13,90 @@
1313

1414
import matplotlib.colors as colors
1515

16-
# %%
17-
# Lognorm: Instead of pcolor log10(Z1) you can have colorbars that have
18-
# the exponential labels using a norm.
19-
2016
N = 100
21-
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
2217

23-
# A low hump with a spike coming out of the top. Needs to have
24-
# z/colour axis on a log scale, so we see both hump and spike.
25-
# A linear scale only shows the spike.
18+
# %%
19+
# LogNorm
20+
# -------
21+
# This example data has a low hump with a spike coming out of its center. If plotted
22+
# using a linear colour scale, then only the spike will be visible. To see both hump and
23+
# spike, this requires the z/colour axis on a log scale.
24+
#
25+
# Instead of transforming the data with ``pcolor(log10(Z))``, the color mapping can be
26+
# made logarithmic using a `.LogNorm`.
2627

28+
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
2729
Z1 = np.exp(-X**2 - Y**2)
2830
Z2 = np.exp(-(X * 10)**2 - (Y * 10)**2)
2931
Z = Z1 + 50 * Z2
3032

3133
fig, ax = plt.subplots(2, 1)
3234

33-
pcm = ax[0].pcolor(X, Y, Z,
34-
norm=colors.LogNorm(vmin=Z.min(), vmax=Z.max()),
35-
cmap='PuBu_r', shading='nearest')
36-
fig.colorbar(pcm, ax=ax[0], extend='max')
37-
38-
pcm = ax[1].pcolor(X, Y, Z, cmap='PuBu_r', shading='nearest')
39-
fig.colorbar(pcm, ax=ax[1], extend='max')
35+
pcm = ax[0].pcolor(X, Y, Z, cmap='PuBu_r', shading='nearest')
36+
fig.colorbar(pcm, ax=ax[0], extend='max', label='linear scaling')
4037

38+
pcm = ax[1].pcolor(X, Y, Z, cmap='PuBu_r', shading='nearest',
39+
norm=colors.LogNorm(vmin=Z.min(), vmax=Z.max()))
40+
fig.colorbar(pcm, ax=ax[1], extend='max', label='LogNorm')
4141

4242
# %%
43-
# PowerNorm: Here a power-law trend in X partially obscures a rectified
44-
# sine wave in Y. We can remove the power law using a PowerNorm.
43+
# PowerNorm
44+
# ---------
45+
# This example data mixes a power-law trend in X with a rectified sine wave in Y. If
46+
# plotted using a linear colour scale, then the power-law trend in X partially obscures
47+
# the sine wave in Y.
48+
#
49+
# The power law can be removed using a `.PowerNorm`.
4550

4651
X, Y = np.mgrid[0:3:complex(0, N), 0:2:complex(0, N)]
47-
Z1 = (1 + np.sin(Y * 10.)) * X**2
52+
Z = (1 + np.sin(Y * 10)) * X**2
4853

4954
fig, ax = plt.subplots(2, 1)
5055

51-
pcm = ax[0].pcolormesh(X, Y, Z1, norm=colors.PowerNorm(gamma=1. / 2.),
52-
cmap='PuBu_r', shading='nearest')
53-
fig.colorbar(pcm, ax=ax[0], extend='max')
56+
pcm = ax[0].pcolormesh(X, Y, Z, cmap='PuBu_r', shading='nearest')
57+
fig.colorbar(pcm, ax=ax[0], extend='max', label='linear scaling')
5458

55-
pcm = ax[1].pcolormesh(X, Y, Z1, cmap='PuBu_r', shading='nearest')
56-
fig.colorbar(pcm, ax=ax[1], extend='max')
59+
pcm = ax[1].pcolormesh(X, Y, Z, cmap='PuBu_r', shading='nearest',
60+
norm=colors.PowerNorm(gamma=0.5))
61+
fig.colorbar(pcm, ax=ax[1], extend='max', label='PowerNorm')
5762

5863
# %%
59-
# SymLogNorm: two humps, one negative and one positive, The positive
60-
# with 5-times the amplitude. Linearly, you cannot see detail in the
61-
# negative hump. Here we logarithmically scale the positive and
62-
# negative data separately.
64+
# SymLogNorm
65+
# ----------
66+
# This example data has two humps, one negative and one positive, The positive hump has
67+
# 5 times the amplitude of the negative. If plotted with a linear colour scale, then
68+
# the detail in the negative hump is obscured.
69+
#
70+
# Here we logarithmically scale the positive and negative data separately with
71+
# `.SymLogNorm`.
6372
#
6473
# Note that colorbar labels do not come out looking very good.
6574

6675
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
67-
Z = 5 * np.exp(-X**2 - Y**2)
76+
Z1 = np.exp(-X**2 - Y**2)
77+
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
78+
Z = (5 * Z1 - Z2) * 2
6879

6980
fig, ax = plt.subplots(2, 1)
7081

71-
pcm = ax[0].pcolormesh(X, Y, Z,
72-
norm=colors.SymLogNorm(linthresh=0.03, linscale=0.03,
73-
vmin=-1.0, vmax=1.0, base=10),
74-
cmap='RdBu_r', shading='nearest')
75-
fig.colorbar(pcm, ax=ax[0], extend='both')
82+
pcm = ax[0].pcolormesh(X, Y, Z, cmap='RdBu_r', shading='nearest',
83+
vmin=-np.max(Z))
84+
fig.colorbar(pcm, ax=ax[0], extend='both', label='linear scaling')
7685

77-
pcm = ax[1].pcolormesh(X, Y, Z, cmap='RdBu_r', vmin=-np.max(Z),
78-
shading='nearest')
79-
fig.colorbar(pcm, ax=ax[1], extend='both')
86+
pcm = ax[1].pcolormesh(X, Y, Z, cmap='RdBu_r', shading='nearest',
87+
norm=colors.SymLogNorm(linthresh=0.015,
88+
vmin=-10.0, vmax=10.0, base=10))
89+
fig.colorbar(pcm, ax=ax[1], extend='both', label='SymLogNorm')
8090

8191
# %%
82-
# Custom Norm: An example with a customized normalization. This one
83-
# uses the example above, and normalizes the negative data differently
84-
# from the positive.
92+
# Custom Norm
93+
# -----------
94+
# Alternatively, the above example data can be scaled with a customized normalization.
95+
# This one normalizes the negative data differently from the positive.
8596

86-
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
87-
Z1 = np.exp(-X**2 - Y**2)
88-
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
89-
Z = (Z1 - Z2) * 2
9097

9198
# Example of making your own norm. Also see matplotlib.colors.
9299
# From Joe Kington: This one gives two different linear ramps:
93-
94-
95100
class MidpointNormalize(colors.Normalize):
96101
def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
97102
self.midpoint = midpoint
@@ -107,38 +112,42 @@ def __call__(self, value, clip=None):
107112
# %%
108113
fig, ax = plt.subplots(2, 1)
109114

110-
pcm = ax[0].pcolormesh(X, Y, Z,
111-
norm=MidpointNormalize(midpoint=0.),
112-
cmap='RdBu_r', shading='nearest')
113-
fig.colorbar(pcm, ax=ax[0], extend='both')
115+
pcm = ax[0].pcolormesh(X, Y, Z, cmap='RdBu_r', shading='nearest',
116+
vmin=-np.max(Z))
117+
fig.colorbar(pcm, ax=ax[0], extend='both', label='linear scaling')
114118

115-
pcm = ax[1].pcolormesh(X, Y, Z, cmap='RdBu_r', vmin=-np.max(Z),
116-
shading='nearest')
117-
fig.colorbar(pcm, ax=ax[1], extend='both')
119+
pcm = ax[1].pcolormesh(X, Y, Z, cmap='RdBu_r', shading='nearest',
120+
norm=MidpointNormalize(midpoint=0))
121+
fig.colorbar(pcm, ax=ax[1], extend='both', label='Custom norm')
118122

119123
# %%
120-
# BoundaryNorm: For this one you provide the boundaries for your colors,
121-
# and the Norm puts the first color in between the first pair, the
122-
# second color between the second pair, etc.
123-
124-
fig, ax = plt.subplots(3, 1, figsize=(8, 8))
125-
ax = ax.flatten()
126-
# even bounds gives a contour-like effect
127-
bounds = np.linspace(-1, 1, 10)
128-
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256)
129-
pcm = ax[0].pcolormesh(X, Y, Z,
130-
norm=norm,
131-
cmap='RdBu_r', shading='nearest')
132-
fig.colorbar(pcm, ax=ax[0], extend='both', orientation='vertical')
124+
# BoundaryNorm
125+
# ------------
126+
# For arbitrarily dividing the color scale, the `.BoundaryNorm` may be used; by
127+
# providing the boundaries for colors, this norm puts the first color in between the
128+
# first pair, the second color between the second pair, etc.
129+
130+
fig, ax = plt.subplots(3, 1, layout='constrained')
133131

134-
# uneven bounds changes the colormapping:
135-
bounds = np.array([-0.25, -0.125, 0, 0.5, 1])
132+
pcm = ax[0].pcolormesh(X, Y, Z, cmap='RdBu_r', shading='nearest',
133+
vmin=-np.max(Z))
134+
fig.colorbar(pcm, ax=ax[0], extend='both', orientation='vertical',
135+
label='linear scaling')
136+
137+
# Evenly-spaced bounds gives a contour-like effect.
138+
bounds = np.linspace(-2, 2, 11)
136139
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256)
137-
pcm = ax[1].pcolormesh(X, Y, Z, norm=norm, cmap='RdBu_r', shading='nearest')
138-
fig.colorbar(pcm, ax=ax[1], extend='both', orientation='vertical')
140+
pcm = ax[1].pcolormesh(X, Y, Z, cmap='RdBu_r', shading='nearest',
141+
norm=norm)
142+
fig.colorbar(pcm, ax=ax[1], extend='both', orientation='vertical',
143+
label='BoundaryNorm\nlinspace(-2, 2, 11)')
139144

140-
pcm = ax[2].pcolormesh(X, Y, Z, cmap='RdBu_r', vmin=-np.max(Z1),
141-
shading='nearest')
142-
fig.colorbar(pcm, ax=ax[2], extend='both', orientation='vertical')
145+
# Unevenly-spaced bounds changes the colormapping.
146+
bounds = np.array([-1, -0.5, 0, 2.5, 5])
147+
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256)
148+
pcm = ax[2].pcolormesh(X, Y, Z, cmap='RdBu_r', shading='nearest',
149+
norm=norm)
150+
fig.colorbar(pcm, ax=ax[2], extend='both', orientation='vertical',
151+
label='BoundaryNorm\n[-1, -0.5, 0, 2.5, 5]')
143152

144153
plt.show()

0 commit comments

Comments
 (0)