已定义色标
Matplotlib有很多自带的色标,但感觉都比较丑, 作为用惯ncl的人,还是觉得ncl的色标比较舒适,因此网上有大神写了一个ncl色标的python库cmaps。
from matplotlib import cm
import cmaps
ncmap = cm.viridis # <matplotlib.colors.ListedColormap object at 0x2b6b1578b550>
ncmap = cm.get_cmap('viridis',17) # 从viridis中取出17个颜色,此时ncmap.N是17
ncolor = cm.viridis.N #会现实该色标的颜色数量,256
ncmap = cmaps.precip3_16lev # <cmaps.colormap.Colormap object at 0x2b6b0abdceb0>,
# 也可以用ncmap.N统计其颜色数量,该色标有17个颜色
# cmaps.BlueDarkRed18.N的颜色有18个颜色
#可以通过以下方法获得colormap的RGBA值,一个Nx4的array数组,N是该colormap的颜色数量,4代表各个颜色的RGBA值
data = ncmap.colors
data = ncmap(range(8)) #取前8个颜色
data = ncmap(np.linspace(0, 1, 8)) #显示线性插值的8个颜色
自定义色标
from matplotlib.colors import ListedColormap
ncmap = ListedColormap(["blue","green","red"])
# 合并两个色标
newcolors = np.vstack((cm.Oranges_r(np.linspace(0, 1, 128)),
cm.Blues(np.linspace(0, 1, 128))))
newcmp = ListedColormap(newcolors, name='OrangeBlue')
# 将已定义的色标转置
ncmap = ListedColormap(cmaps.precip3_16lev(range(0,17,1))[::-1])
# 获得较为稀疏的已定义坐标
ncmap = cm.get_cmap('viridis',17) # matplotlib自带的colormap可以这样操作
ncmap = ListedColormap(cmaps.GMT_globe(range(0,209,3)))
# 替换已定义色标中的某一颜色
newcolors = cm.viridis(np.linspace(0, 1, 256))
pink = np.array([248/256, 24/256, 148/256, 1])
newcolors[:25, :] = pink
newcmp = ListedColormap(newcolors)
Colormap Normalization
# 将值线性分布到colormap上
pcm = ax.pcolormesh(x, y, Z, vmin=-1., vmax=1., cmap='RdBu_r')
# 将值对数分布到colormap上
pcm = ax[0].pcolor(X, Y, Z,
norm=colors.LogNorm(vmin=Z.min(), vmax=Z.max()),
cmap=cmaps.BlueDarkRed18, shading='auto')
# 将值线性分布到colormap上,同时vcenter的值将位于colormap中间
pc = ax2.pcolormesh(Z, norm=colors.CenteredNorm(vcenter=0), cmap=cm.coolwarm)
# 定义离散的colormap值
# 一般我会将ncolors设为len(bounds)+1,但看这个例子好像ncolors只要大于len(bounds)就可以
import matplotlib.colors as colors
bounds = np.array([-0.2, -0.1, 0, 0.5, 1])
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=cm.viridis.N, extend='both')
pcm = ax[2].pcolormesh(X, Y, Z, norm=norm, cmap=cm.viridis)
# 使值在colormap中间两侧的值的变化率不同
# make a colormap that has land and ocean clearly delineated and of the
# same length (256 + 256)
colors_undersea = plt.cm.terrain(np.linspace(0, 0.17, 256))
colors_land = plt.cm.terrain(np.linspace(0.25, 1, 256))
all_colors = np.vstack((colors_undersea, colors_land))
terrain_map = colors.LinearSegmentedColormap.from_list(
'terrain_map', all_colors)
# make the norm: Note the center is offset so that the land has more
# dynamic range:
divnorm = colors.TwoSlopeNorm(vmin=-500., vcenter=0, vmax=4000)
pcm = ax.pcolormesh(longitude, latitude, topo, rasterized=True, norm=divnorm,
cmap=terrain_map, shading='auto')
cb = fig.colorbar(pcm, shrink=0.6)
cb.set_ticks([-500, 0, 1000, 2000, 3000, 4000])
参考:
- https://matplotlib.org/stable/tutorials/colors/colormaps.html#overview
- https://matplotlib.org/stable/tutorials/colors/colormap-manipulation.html#sphx-glr-tutorials-colors-colormap-manipulation-py
- https://matplotlib.org/stable/tutorials/colors/colormapnorms.html
- https://matplotlib.org/stable/tutorials/colors/colorbar_only.html