RQL's Blog 菜鸟成长记

Matplotlib colormap

2022-06-23
renql

已定义色标

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

支持 支付宝鼓励 鸡腿鸡腿

喜欢此文!

下一篇 numpy用法

Content