备注
前往结尾 以下载完整示例代码。
颜色映射归一化#
展示如何使用norm将颜色映射以非线性方式映射到数据上。
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.colors as colors
N = 100
LogNorm#
这个示例数据有一个低峰,中心有一个尖峰。如果使用线性颜色比例绘制,那么只能看到尖峰。要同时看到峰和尖峰,这需要在对数比例上的z/颜色轴。
可以使用 LogNorm 进行对数颜色映射,而不是使用 pcolor(log10(Z)) 转换数据。
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X * 10)**2 - (Y * 10)**2)
Z = Z1 + 50 * Z2
fig, ax = plt.subplots(2, 1)
pcm = ax[0].pcolor(X, Y, Z, cmap='PuBu_r', shading='nearest')
fig.colorbar(pcm, ax=ax[0], extend='max', label='linear scaling')
pcm = ax[1].pcolor(X, Y, Z, cmap='PuBu_r', shading='nearest',
norm=colors.LogNorm(vmin=Z.min(), vmax=Z.max()))
fig.colorbar(pcm, ax=ax[1], extend='max', label='LogNorm')

PowerNorm#
此示例数据在X中混合了幂律趋势,在Y中混合了整流正弦波。如果使用线性颜色比例绘制,那么X中的幂律趋势部分掩盖了Y中的正弦波。
可以使用 PowerNorm 移除幂律。
X, Y = np.mgrid[0:3:complex(0, N), 0:2:complex(0, N)]
Z = (1 + np.sin(Y * 10)) * X**2
fig, ax = plt.subplots(2, 1)
pcm = ax[0].pcolormesh(X, Y, Z, cmap='PuBu_r', shading='nearest')
fig.colorbar(pcm, ax=ax[0], extend='max', label='linear scaling')
pcm = ax[1].pcolormesh(X, Y, Z, cmap='PuBu_r', shading='nearest',
norm=colors.PowerNorm(gamma=0.5))
fig.colorbar(pcm, ax=ax[1], extend='max', label='PowerNorm')

SymLogNorm#
这个示例数据有两个峰值,一个是负的,一个是正的,正峰值的幅度是负峰值的5倍。如果用线性颜色标度绘制,那么负峰值的细节就会被掩盖。
这里我们分别对正负数据进行对数缩放,使用 SymLogNorm。
请注意,颜色条标签看起来不太好。
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
Z = (5 * Z1 - Z2) * 2
fig, ax = plt.subplots(2, 1)
pcm = ax[0].pcolormesh(X, Y, Z, cmap='RdBu_r', shading='nearest',
vmin=-np.max(Z))
fig.colorbar(pcm, ax=ax[0], extend='both', label='linear scaling')
pcm = ax[1].pcolormesh(X, Y, Z, cmap='RdBu_r', shading='nearest',
norm=colors.SymLogNorm(linthresh=0.015,
vmin=-10.0, vmax=10.0, base=10))
fig.colorbar(pcm, ax=ax[1], extend='both', label='SymLogNorm')

自定义范数#
或者,上述示例数据可以通过自定义的归一化进行缩放。这个归一化方法对负数据的处理与正数据不同。
# Example of making your own norm. Also see matplotlib.colors.
# From Joe Kington: This one gives two different linear ramps:
class MidpointNormalize(colors.Normalize):
def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
self.midpoint = midpoint
super().__init__(vmin, vmax, clip)
def __call__(self, value, clip=None):
# I'm ignoring masked values and all kinds of edge cases to make a
# simple example...
x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1]
return np.ma.masked_array(np.interp(value, x, y))
fig, ax = plt.subplots(2, 1)
pcm = ax[0].pcolormesh(X, Y, Z, cmap='RdBu_r', shading='nearest',
vmin=-np.max(Z))
fig.colorbar(pcm, ax=ax[0], extend='both', label='linear scaling')
pcm = ax[1].pcolormesh(X, Y, Z, cmap='RdBu_r', shading='nearest',
norm=MidpointNormalize(midpoint=0))
fig.colorbar(pcm, ax=ax[1], extend='both', label='Custom norm')

BoundaryNorm#
对于任意分割色阶,可以使用 BoundaryNorm;通过提供颜色的边界,此规范将第一种颜色放在第一对之间,第二种颜色放在第二对之间,依此类推。
fig, ax = plt.subplots(3, 1, layout='constrained')
pcm = ax[0].pcolormesh(X, Y, Z, cmap='RdBu_r', shading='nearest',
vmin=-np.max(Z))
fig.colorbar(pcm, ax=ax[0], extend='both', orientation='vertical',
label='linear scaling')
# Evenly-spaced bounds gives a contour-like effect.
bounds = np.linspace(-2, 2, 11)
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256)
pcm = ax[1].pcolormesh(X, Y, Z, cmap='RdBu_r', shading='nearest',
norm=norm)
fig.colorbar(pcm, ax=ax[1], extend='both', orientation='vertical',
label='BoundaryNorm\nlinspace(-2, 2, 11)')
# Unevenly-spaced bounds changes the colormapping.
bounds = np.array([-1, -0.5, 0, 2.5, 5])
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256)
pcm = ax[2].pcolormesh(X, Y, Z, cmap='RdBu_r', shading='nearest',
norm=norm)
fig.colorbar(pcm, ax=ax[2], extend='both', orientation='vertical',
label='BoundaryNorm\n[-1, -0.5, 0, 2.5, 5]')
plt.show()

脚本总运行时间: (0 分钟 1.145 秒)