绘制颜色渐变分段线时,如何合理使用自定义colormap并固定映射规则?
固定Colormap范围,避免随线段坐标变化自动适配
你遇到的核心问题是颜色映射的数组和线段的实际坐标范围绑定了——当前代码里的res_ar是根据线段的x起点和终点生成的(np.linspace(x1, x2, len(x_coords))),所以当线段变短(比如x从0到0.5),颜色数组的范围也跟着变成0到0.5,Matplotlib会自动把这个范围拉伸到colormap的0-1区间,看起来就像是colormap适配了线段。
要解决这个问题,我们需要让颜色映射的逻辑和线段坐标彻底脱钩:让颜色数组始终保持0到1的固定范围,通过调整颜色归一化(Normalize)的参数来控制colormap的使用区间,而不是让线段坐标影响颜色范围。
修改后的代码示例
情况1:使用完整colormap(阈值>0.3)
import numpy as np import matplotlib.pyplot as plt from matplotlib.collections import LineCollection from matplotlib.colors import LinearSegmentedColormap # 任意修改线段坐标,颜色映射不受影响 x1 = 0 x2 = 0.5 # 线段变短了 y1 = 0 y2 = 0.5 # 创建线段坐标 x_coords = np.linspace(x1, x2, 100) y_coords = np.linspace(y1, y2, 100) # 关键修改:颜色映射数组固定为0到1,和线段坐标无关 res_ar = np.linspace(0, 1, len(x_coords)) # 生成线段结构(这部分不需要改) points = np.array([x_coords, y_coords]).T.reshape(-1, 1, 2) segments = np.concatenate([points[:-1], points[1:]], axis=1) fig, ax = plt.subplots() # 自定义蓝红colormap(这部分不需要改) cvals = [0., 1.] colors = ['blue', 'red'] # 归一化范围固定为0-1,对应完整colormap norm = plt.Normalize(0, 1) tuples = list(zip(map(norm, cvals), colors)) cmap = LinearSegmentedColormap.from_list('', tuples) # 绘制分段线 lc = LineCollection(segments, cmap=cmap, norm=norm) # 传入固定的norm lc.set_array(res_ar) # 用固定的0-1数组 ax.add_collection(lc) ax.set_xlim(x1-0.1, x2+0.1) ax.set_ylim(y1-0.1, y2+0.1) plt.colorbar(lc) # 显示颜色条,验证范围是0-1 plt.show()
情况2:使用colormap的前半部分(阈值=0.15)
只需要修改Normalize的范围,把vmax设为0.5,这样颜色数组的0-1会被映射到colormap的0-0.5区间(蓝色到紫色):
# ... 前面的线段坐标、颜色数组部分和上面一样 ... # 调整归一化范围,只使用colormap的前半部分 norm = plt.Normalize(0, 0.5) # vmax设为0.5,对应colormap的前半段 # 后续代码不变 tuples = list(zip(map(norm, cvals), colors)) cmap = LinearSegmentedColormap.from_list('', tuples) lc = LineCollection(segments, cmap=cmap, norm=norm) lc.set_array(res_ar) # ... 显示部分不变 ...
关键修改点说明
- 固定颜色映射数组:把
res_ar改成np.linspace(0, 1, len(x_coords)),这样不管线段多长,颜色数组始终是0到1的线性序列,和线段坐标无关。 - 控制colormap使用区间:通过修改
Normalize的vmin和vmax来决定使用colormap的哪一部分:- 用完整colormap时,vmin=0,vmax=1
- 用前半部分时,vmin=0,vmax=0.5
- 如果想用后半部分,就设vmin=0.5,vmax=1
- 显式传入norm:创建
LineCollection时把固定的norm传进去,确保Matplotlib不会自动调整颜色范围。
这样修改后,不管你怎么调整线段的坐标(变长、变短、改变起点终点),colormap的使用逻辑都不会变,完全由你设定的阈值和归一化范围控制。
内容的提问来源于stack exchange,提问作者Artur Müller Romanov
相关产品推荐
相关产品推荐

