python --如何实现colorbar的不等间距显示

先展示一下结果: 实现上述colorbar,主要使用一个函数,如下:

matplotlib.colors.TwoSlopeNorm 函数说明:一般包含三个参数:matplotlib.colors.TwoSlopeNorm(vcenter, vmin=None, vmax=None)

vmin:最小范围vmax:最大范围vcenter:中间范围

功能说明:

使用一个固定中心的标准化数据。当在概念中心周围映射变化速率不等的数据时很有用,例如,数据范围从 -20到40,中点为0。

代码如下:

# -*- 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: 211311040008@hhu.edu.cn

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: 211311040008@hhu.edu.cn

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的区间。

boundaries:至少2个 bin 边的单调递增序列: 第 n 个 bin 中的数据将被映射到第 n 个颜色。ncolors:要使用的颜色图中的颜色数。clip:如果为 True,则超出范围的值如果低于边界[0]则映射为0,如果高于边界[ -1]则映射为 ncolor-1。如果为 False,超出范围的值如果低于边界[0]则映射为 -1,如果高于边界[ -1]则映射为 ncolor。然后,这些索引通过 Colormap 转换为有效的索引。

# -*- 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: 211311040008@hhu.edu.cn

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',

)

举例示范4:

这里所使用的是对数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:

这个只是记录如何将colorbar的标签放在每个色标的中间的另一种方法之前尝试过别的方法,具体教程在这里:点击这里

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-centerhttps://matplotlib.org/stable/api/_as_gen/matplotlib.colors.TwoSlopeNorm.htmlhttps://matplotlib.org/stable/api/_as_gen/matplotlib.colors.BoundaryNorm.htmlhttps://zhajiman.github.io/post/matplotlib_colormap/https://stackoverflow.com/questions/54513247/matplotilb-how-to-set-colorbar-for-line-plot-with-log-scalehttps://stackoverflow.com/questions/8342549/matplotlib-add-colorbar-to-a-sequence-of-line-plots/49374315#49374315

相关文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: