我是一名气候学家,经常会出现异常现象。温度场使用“蓝色到白色到红色”的色彩图。为了使图表更具可读性,我使用我在互联网上“找到”的功能将颜色图在一定数量的级别(箱子)中离散化(但我真的不明白):
这样的事情:
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()
这导致
现在我想将两个最中间的片段(即那两个接近0的片段)设置为白色,因为我不想显示非常小的偏差。
我的目标是最终得到类似的东西:
我真的很难弄清楚如何相应地修改这些LinearSegmentedColormap。有人可以帮我这个吗?
答案 0 :(得分:5)
您找到的函数构建了一个数据结构(在cdict
中),用于定义具有不执行任何插值的段的LinearSegmentedColormap(即行{{1}中的y1
始终与行i
中的y0
相同,并且这给出了常量或离散的颜色“波段”)。
i+1
是一个奇怪的数据结构,一个包含密钥cdict
,'red'
和'green'
的字典。每个键的值是包含'blue'
形式的元组的列表结构。 (x, y0, y1)
是颜色贴图坐标,它是0到1之间的某个浮点数。x
是y0
“左侧”的颜色值,x
是y1
“右侧”的颜色值。在连续值x
之间的频带中线性插值颜色;如果第一个元组由x
给出而第二个元组由(0, A, B)
给出,则(X, C, D)
和t
之间的点0
的颜色将由X
。
出于您的目的,您的功能非常好,但需要将颜色贴图中间附近的“波段”替换为白色。您可以尝试以下内容:
(t - 0) / (X - 0) * (C - B) + B
答案 1 :(得分:3)
让我们首先浏览您的代码
# get some uniformly sampled data, padded out a bit
colors_i = np.concatenate((np.linspace(0, 1., N), (0.,0.,0.,0.)))
# sample the input colormap at our sample points
colors_rgba = cmap(colors_i)
# indices for color map
indices = np.linspace(0, 1., N+1)
# dict to pass to the LinearSegmentedColormap
cdict = {}
# loop over the colors
for ki,key in enumerate(('red','green','blue')):
# in each color assemble a list that looks like
#[...,
# (indices[2], colors_rgba[1,ki], colors_rgba[2,ki]),
# (indices[3], colors_rgba[2,ki], colors_rgba[3,ki]),
# ....]
cdict[key] = [ (indices[i], colors_rgba[i-1,ki], colors_rgba[i,ki]) for i in xrange(N+1) ]
# The color for a number between [indices[2], indices[3]] are interpolated
# between colors_rgba[2,ki] and colors_rgba[2,ki] which are the same
# which is what gives you the discrete blocks.
# Construct and return colormap object.
return cols.LinearSegmentedColormap(cmap.name + "_%d"%N, cdict, 1024)
所以现在的问题是如何在中间创建一个带有“加倍”白色条带的彩色地图。我会改变功能位,让它接收两个颜色图(顶部和底部)
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_double_discretize(cmap_bottom, cmap_top, N, split=.5):
"""
Generates a descritized color map using two existing color maps
Parameters
----------
cmap_bottom : cmap
The bottom cmap
cmap_top : cmap
The top cmap
N : int
The number of bins in each color map
split : float, optional
Where to join the maps, must be in [0, 1]
"""
# sanity check
assert split < 1 and split > 0
# set up the data structure
cdict = {lab: [] for lab in ('red','green','blue')}
# do this in a fancy loop to a) save typing, b) make it easy to
# retrofit to do arbitrary splits
for cmap, ends in zip((cmap_bottom, cmap_top), ((0, split), (split, 1))):
# run over the _whole_ range for each color map
colors_i = np.concatenate((np.linspace(0, 1., N), (0.,0.,0.,0.)))
# map the color
colors_rgba = cmap(colors_i)
# get the values
indices = np.linspace(ends[0], ends[1], N+1, endpoint=True)
for ki,key in enumerate(('red','green','blue')):
cdict[key].extend((indices[i], colors_rgba[i-1,ki], colors_rgba[i,ki]) for i in xrange(N+1))
# print cdict
# Return colormap object.
return cols.LinearSegmentedColormap(cmap.name + "_%d"%N, cdict, 1024)
red_cdict = {'red': [(0, 0, 1),
(1, 1, 0)],
'blue': [(0, 0, 0),
(1, 1, 0)],
'green': [(0, 0, 0),
(1, 1, 0)]}
blue_cdict = {'blue': [(0, 0, 1),
(1, 1, 0),],
'red': [(0, 0, 1),
(1, 0, 0)],
'green': [(0, 0, 1),
(1, 0, 0)]}
red_cmap = cols.LinearSegmentedColormap('red', red_cdict, 1024)
blue_cmap = cols.LinearSegmentedColormap('blue', blue_cdict, 1024)
test_cmap = cmap_double_discretize(red_cmap, blue_cmap, 6)
# these don't actually go to white!
# test_cmap = cmap_double_discretize(cm.get_cmap('Reds_r'), cm.get_cmap('Blues'), 6)
fig, ax = plt.subplots()
data = np.clip(randn(250, 250), -1, 1)
cax = ax.pcolor(data, cmap=test_cmap)
plt.colorbar(cax)
plt.show()
您可以轻松修改此选项以分割两个以上的彩色地图。