Matplotlib自定义色彩映射不尊重着色

时间:2017-03-02 20:29:30

标签: python matplotlib

问题的旧版本低于

我正在定义以下自定义色彩映射,我将白色(#ffffff)分配给浮点zero_pt

import matplotlib.colors as col
from matplotlib.colors import LinearSegmentedColormap

zero_pt = 0.98181818181818181

cmap = LinearSegmentedColormap.from_list(
    'mycmap', [(0, 'blue'), (zero_pt, 'white'), (1, 'red')])

但是当我尝试从相同的zero_pt值中检索十六进制颜色代码时,我没有像我期望的那样得到#ffffff(即:white):

rgb = cmap(zero_pt)[:3]
print(col.rgb2hex(rgb))
> u'#ffdcdc'

为什么会这样,我该如何解决这个问题?



这里的老问题

我需要定义一个自定义色图,其中负值以蓝色显示,零值以白色显示,正值以红色显示。代码如下,以及必要的数据文件(data.pkl)和此处(edges.pkl)。

import pickle
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap


with open('data.pkl', 'r') as f:
    H = pickle.load(f)
with open('edges.pkl', 'r') as f:
    edges = pickle.load(f)

# Define zero point for empty bins which should be colored in white.
zero_pt = 1. - H.max() / (H.max() - H.min())

print(H.min(), H.max(), zero_pt)

cmap = LinearSegmentedColormap.from_list(
    'mycmap', [(0, 'blue'), (zero_pt, 'white'), (1, 'red')])

Y, X = np.meshgrid(edges[0], edges[1])
plt.pcolormesh(X, Y, H, cmap=cmap, vmin=H.min(), vmax=H.max())

plt.show()

这导致

enter image description here

如果我们检查H数组,我们会发现有很多零值,应该以白色显示,而在上图中显示为粉红色。

这不会发生我使用的所有数据,它只是偶尔发生。我认为问题与舍入有关?有没有办法强制像这样的情况以白色显示零值?

1 个答案:

答案 0 :(得分:1)

正如评论中所说,如果1/N是色彩映射中的颜色数,则需要将零点值舍入为N的倍数。当然,色点图中零点值与任何其他颜色之间的差异必须大于1/N

所以这是一个解决方案

import matplotlib.colors as col
from matplotlib.colors import LinearSegmentedColormap
import numpy as np 

N=256
zero_pt0 = 0.98181818181818181
zero_pt_rounded = np.ceil(zero_pt0*(N-1))/float(N-1)
print (zero_pt_rounded)

cmap = LinearSegmentedColormap.from_list(
    'mycmap', [(0, 'blue'), (zero_pt_rounded, 'white'), (1, 'red')], N=N)

# verify if original point zero_pt0 gives white color
rgb = cmap(zero_pt0)[:3]
print(col.rgb2hex(rgb))

关于您的旧问题:目前尚不清楚zero_pt = 1. - H.max() / (H.max() - H.min())行应该做什么。 我猜你需要把

data_value_for_white color = ...
zero_pt = (data_value_for_white color - H.min()) / (H.max() - H.min())

此外,为了确保色彩图中的白色覆盖所需的值,我们需要使色彩图中的两个相邻颜色变为白色。

N = 256 # number of colors in the colormap
zero_pt0 = np.floor(zero_pt*(N-1))/float(N-1)
zero_pt1 = np.ceil(zero_pt*(N-1))/float(N-1)
cmap = LinearSegmentedColormap.from_list('mycmap',
         [(0, 'blue'), (zero_pt0, 'white'),(zero_pt1, 'white'), (1, 'red')], N=N)

因此,完整的解决方案如下:

import pickle
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap, rgb2hex


with open('data.pkl', 'r') as f:
    H = pickle.load(f)
with open('edges.pkl', 'r') as f:
    edges = pickle.load(f)

# Define zero point for empty bins which should be colored in white.
data_value_for_white_color = 0.
zero_pt = (data_value_for_white_color - H.min()) / float(H.max() - H.min())

N=256
zero_pt0 = np.floor(zero_pt*(N-1))/float(N-1)
zero_pt1 = np.ceil(zero_pt*(N-1))/float(N-1)

cmap = LinearSegmentedColormap.from_list('mycmap',
     [(0, 'blue'), (zero_pt0, 'white'),(zero_pt1, 'white'), (1, 'red')], N=N)

Y, X = np.meshgrid(edges[0], edges[1])
plt.pcolormesh(X, Y, H, cmap=cmap, vmin=H.min(), vmax=H.max())
plt.show()

enter image description here