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

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

先展示一下结果:
python -- 如何实现colorbar的不等间距显示_第1张图片
实现上述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: [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:

  • 有时我们希望在概念中心点的两侧有不同的颜色映射,我们希望这两种颜色映射具有不同的线性比例。例如,在地形图中,陆地和海洋的中心位于零,但陆地的海拔高度范围通常比水的深度范围大,而且它们通常由不同的颜色图表示。
    python -- 如何实现colorbar的不等间距显示_第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:
python -- 如何实现colorbar的不等间距显示_第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: [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',
   
)    



举例示范4:
python -- 如何实现colorbar的不等间距显示_第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的标签放在每个色标的中间的另一种方法
  • 之前尝试过别的方法,具体教程在这里:点击这里
    python -- 如何实现colorbar的不等间距显示_第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

你可能感兴趣的:(python,绘图,python,库学习,如何解决系列,python,matplotlib,开发语言)