先展示一下结果:
实现上述colorbar,主要使用一个函数,如下:
matplotlib.colors.TwoSlopeNorm(vcenter, vmin=None, vmax=None)
功能说明:
代码如下:
# -*- coding: utf-8 -*-
"""
Created on Wed Dec 7 10:12:20 2022
@author: jianpu
@blog : https://blog.csdn.net/weixin_44237337?spm=1000.2115.3001.5343
@email: [email protected]
introduction : keep learning althongh walk slowly
"""
import cmaps
from matplotlib.colors import ListedColormap
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.cm as cm
import matplotlib.colors as mcolors
newcmap=(plt.get_cmap('RdBu_r'))
bins = np.array( [-20,-10,0,10,20,30,40])
fig=plt.figure(figsize=(10,10),dpi=150)
norm = mcolors.TwoSlopeNorm(vmin=-20, vcenter=0,vmax=40)
ax=fig.add_axes([0,0,0.5,0.05])
fc1=fig.colorbar(
mpl.cm.ScalarMappable(norm=norm,cmap=newcmap,),
cax=ax,
ticks = bins,
orientation='horizontal',
)
##### 设置colorbar label的不同显示位置
ax2=fc1.ax
ax2.xaxis.set_ticks_position('top') #将数值刻度移动到上边
ax3=ax2.secondary_xaxis('bottom') #新建ax3,使ax3与ax2完全相同,但是是处于下部
ax3.set_xticks([-10,0,10,20,30])
# 这里的标签名称可以自定义修改成想要的
ax3.set_xticklabels(['a','b','c','d','e'],ha="center")
# f1.ax.set_xscale('linear')
举例示范2:
代码如下:
"""
Created on Wed Dec 7 10:12:20 2022
@author: jianpu
@blog : https://blog.csdn.net/weixin_44237337?spm=1000.2115.3001.5343
@email: [email protected]
introduction : keep learning althongh walk slowly
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import matplotlib.cbook as cbook
from matplotlib import cm
dem = cbook.get_sample_data('topobathy.npz', np_load=True)
topo = dem['topo']
longitude = dem['longitude']
latitude = dem['latitude']
fig, ax = plt.subplots(dpi=200)
# 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')
# Simple geographic plot, set aspect ratio because distance between lines of
# longitude depends on latitude.
ax.set_aspect(1 / np.cos(np.deg2rad(49)))
ax.set_title('TwoSlopeNorm(x)')
cb = fig.colorbar(pcm, shrink=0.9)
cb.set_ticks([-500, 0, 1000, 2000, 3000, 4000])
plt.show()
举例示范3:
这一种适用于通过不同的rgb色域,拼接得到的colormap,使用的主要函数为:
matplotlib.colors.BoundaryNorm(boundaries, ncolors, clip=False, *, extend='neither')
官网说明
主要用来生成基于离散区间的颜色图索引
与Normalize或LogNorm不同,BoundaryNorm将值映射为整数,而不是0-1的区间。
# -*- coding: utf-8 -*-
"""
Created on Wed Dec 7 10:12:20 2022
@author: jianpu
@blog : https://blog.csdn.net/weixin_44237337?spm=1000.2115.3001.5343
@email: [email protected]
introduction : keep learning althongh walk slowly
"""
import cmaps
from matplotlib.colors import ListedColormap
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.cm as cm
import matplotlib.colors as mcolors
rgb=(
[0,0,255],
[39,39,255],
[78,78,255],
[91,118,255],
[118,130,255],
[ 255,255,255],
[ 255,255,255],
[ 255,190,190],
[ 255,142,142],
[ 255,122,122],
[ 255,99,99],
[ 255,58,58],
[ 248,19,8],
[ 153,33,20],
)
rgb=np.array(rgb)/255.0
newcmap=ListedColormap(rgb)
bins = [-600,-500,-400,-300,-200,-100,0,100,200,300,400,500,600,800,1000]
nbin = len(bins) - 1
cmap = cm.get_cmap('bwr', nbin)
norm4 = mcolors.BoundaryNorm(bins, nbin)
im4 = cm.ScalarMappable(norm=norm4, cmap=newcmap)
fig=plt.figure(figsize=(10,10),dpi=150)
ax=fig.add_axes([0,0,0.5,0.05])
f1 = fig.colorbar(
im4, cax=ax, orientation='horizontal',
)
这里所使用的是对数colorbar显示,最重要的原则是保持线条图和 ScalarMapable 的颜色同步。这意味着,线条的颜色不应取自独立的颜色列表,而应取自相同的颜色图,并使用与要显示的颜色条相同的标准化。然后,一个主要问题是决定如何处理不能成为对数规范化的一部分的0。下面是使用 SymLogNorm 假设0到2之间的线性范围和上面的日志范围的解决方案。
代码如下:
# -*- coding: utf-8 -*-
"""
Created on Mon Feb 6 21:24:46 2023
@author: win10
"""
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
"""Creating the data"""
time_vector = [0, 1, 2, 4, 8, 16, 32, 64, 128, 256]
amplitudes = [t ** 2 * np.exp(-t * np.power(np.linspace(-0.5, 0.5, 100), 2)) for t in time_vector]
"""Getting the non-zero minimum of the data"""
data = np.concatenate(amplitudes).ravel()
data_min = np.min(data[np.nonzero(data)])
"""Creating K-space data"""
k_vector = np.linspace(0,1,100)
"""Plotting"""
cmap = plt.cm.get_cmap("jet")
norm = mpl.colors.SymLogNorm(2, vmin=time_vector[0], vmax=time_vector[-1])
sm = mpl.cm.ScalarMappable(norm=norm, cmap=cmap)
sm.set_array([])
fig =plt.figure(dpi=200)
for i in range(len(time_vector)):
plt.plot(k_vector, amplitudes[i], color=cmap(norm(time_vector[i])), label=time_vector[i])
#c = np.arange(1, number_of_plots + 1)
plt.xlabel('Frequency')
plt.ylabel('Amplitude')
plt.yscale('symlog')
plt.xscale('log')
plt.legend(loc=3)
cbar = plt.colorbar(sm, ticks=time_vector, format=mpl.ticker.ScalarFormatter(),
shrink=1.0, fraction=0.1, pad=0)
plt.show()
单独的一个记录5:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors
n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1., n_lines + 1)
cmap = plt.get_cmap("jet", len(c))
norm = matplotlib.colors.BoundaryNorm(np.arange(len(c)+1)+0.5,len(c))
sm = plt.cm.ScalarMappable(norm=norm, cmap=cmap)
sm.set_array([]) # this line may be ommitted for matplotlib >= 3.1
fig, ax = plt.subplots(dpi=200)
for i, yi in enumerate(y.T):
ax.plot(x, yi, c=cmap(i))
fig.colorbar(sm, ticks=c)
plt.show()
参考如下:
- https://matplotlib.org/stable/tutorials/colors/colormapnorms.html#twoslopenorm-different-mapping-on-either-side-of-a-center
- https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.TwoSlopeNorm.html
- https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.BoundaryNorm.html
- https://zhajiman.github.io/post/matplotlib_colormap/
- https://stackoverflow.com/questions/54513247/matplotilb-how-to-set-colorbar-for-line-plot-with-log-scale
- https://stackoverflow.com/questions/8342549/matplotlib-add-colorbar-to-a-sequence-of-line-plots/49374315#49374315