修改离散的LinearSegmentedColormap

Rap*_*oth 2 python matplotlib

我是气候学家,经常使用"蓝色到白色到红色"的色彩图来绘制温度场的异常.为了使图表更具可读性,我使用我在互联网上"找到"的功能将颜色图在一定数量的级别(箱子)中离散化(但我真的不明白):

像这样的东西:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
import matplotlib.colors as cols
from numpy.random import randn

def cmap_discretize(cmap, N):
    colors_i = np.concatenate((np.linspace(0, 1., N), (0.,0.,0.,0.)))
    colors_rgba = cmap(colors_i)
    indices = np.linspace(0, 1., N+1)
    cdict = {}
    for ki,key in enumerate(('red','green','blue')):
        cdict[key] = [ (indices[i], colors_rgba[i-1,ki], colors_rgba[i,ki]) for i in xrange(N+1) ]
    # Return colormap object.
    return cols.LinearSegmentedColormap(cmap.name + "_%d"%N, cdict, 1024)



cmap_disc= cmap_discretize(cm.RdBu_r,12)


fig, ax = plt.subplots()
data = np.clip(randn(250, 250), -1, 1)

cax = ax.pcolor(data, cmap=cmap_disc)
plt.colorbar(cax)

plt.show()
Run Code Online (Sandbox Code Playgroud)

这导致了

在此输入图像描述

现在我想将两个最中间的段(即那两个接近0的段)设置为白色,因为我不想显示非常小的偏差.

我的目标是最终得到类似的东西:

在此输入图像描述

我真的很难弄清楚如何相应地修改这些LinearSegmentedColormap.有人可以帮我这个吗?

wil*_*elm 5

您找到的函数构建了一个数据结构(in cdict),用于定义一个LinearSegmentedColormap,其中包含不执行任何插值的段(即,y1行中的行i总是与y0行相同i+1,这会给出常量或离散的颜色"band" ).

cdict是一个奇怪的数据结构,一个包含键的字典'red','green''blue'.每个键的值是包含表单元组的列表结构(x, y0, y1). x是彩色地图坐标,其是在0和1之间的某个浮点数 y0是上的"左"侧的颜色值x,并且y1是上的"右"侧的颜色值x.颜色在连续值之间的带中线性插值x; 如果所述第一元组由下式给出(0, A, B),并通过所述第二元组(X, C, D),那么点的颜色t之间0并且X将由下式给出(t - 0) / (X - 0) * (C - B) + B.

为了您的目的,您的功能非常好,但需要将颜色映射中间附近的"波段"替换为白色.您可以尝试以下内容:

def cmap_discretize(cmap, N):
    colors_i = np.concatenate((np.linspace(0, 1., N), (0.,0.,0.,0.)))
    colors_rgba = cmap(colors_i)
    indices = np.linspace(0, 1., N+1)
    cdict = {}
    for ki,key in enumerate(('red','green','blue')):
        cdict[key] = [ (indices[i], colors_rgba[i-1,ki], colors_rgba[i,ki]) for i in xrange(N+1) ]
    # "white out" the bands closest to the middle
    num_middle_bands = 2 - (N % 2)
    middle_band_start_idx = (N - num_middle_bands) // 2
    for middle_band_idx in range(middle_band_start_idx,
                                 middle_band_start_idx + num_middle_bands):
        for key in cdict.keys():
            old = cdict[key][middle_band_idx]
            cdict[key][middle_band_idx] = old[:2] + (1.,)
            old = cdict[key][middle_band_idx + 1]
            cdict[key][middle_band_idx + 1] = old[:1] + (1.,) + old[2:]
    # Return colormap object.
    return cols.LinearSegmentedColormap(cmap.name + "_%d"%N, cdict, 1024)
Run Code Online (Sandbox Code Playgroud)