使用Matplotlib的Arbirtrary非线性颜色条

阿奇里·萨拉恩(AchilleSalaün)

我想使用Networkx和Matplotlib为网络的边缘着色,其中为每个边缘(i,j)赋予G[i][j]['label']0到1之间的值

但是,这些值通常非常接近于零,或者非常接近于1。由于所有内容都是非常红色或非常蓝色(使用色图),因此很难形象化颜色的变化coolwarm

然后,我的想法是应用filtR类似于以下过滤器之一的过滤器

在此处输入图片说明

它只是一个多项式函数,提供从[0,1]到[0,1]的双射,并在0或1周围扩展更多值。如果需要,则逆是易处理的。

现在,我只将其应用于边缘的值,以定义其颜色:

cm        = plt.get_cmap('coolwarm') 
cNorm     = colors.Normalize(vmin=0., vmax=1.)
scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=cm)
colorList = []

# The color is defined by filtR(G[i][j]['label'])
val_map   = {(i,j): filtR(G[i][j]['label']) for (i,j) in G.edges()}
values    = [scalarMap.to_rgba(val_map[e]) for e in G.edges()]
edges     = nx.draw_networkx_edges(G,edge_color=values,edge_cmap=plt.get_cmap('coolwarm'))


# Definition of the colorbar :-(
sm = cmx.ScalarMappable(cmap=cmx.coolwarm)
sm.set_array(values)
plt.colorbar(sm)

现在的问题是:我想定义相应的颜色条。

现在,它显示了通过filtR函数对边缘的评估,这是没有意义的:滤镜的唯一目的是修改[0,1]间隔上的颜色重新分配,以提高图形的可读性。

例如,我得到:

在此处输入图片说明

我对左边的部分感到满意​​,但对右边的部分却不满意,其中的颜色条应类似于:

在此处输入图片说明

在这里,过滤器功能显然不是最好的,但它应该为您提供更好的说明。

我试图values在定义colorbar之前重新定义:

# Definition of the colorbar :-(

new_val_map = {(i,j): filtR(G[i][j]['label']) for (i,j) in G.edges()}
new_values  = [scalarMap.to_rgba(val_map[e]) for e in G.edges()]

sm = cmx.ScalarMappable(cmap=cmx.coolwarm)
sm.set_array(new_values)
plt.colorbar(sm)

但是什么都没有改变。

我对Matplotlib的理解是有限的,给出的代码已经是堆栈溢出答案的拼凑而成。

认真的重要性

本质上,您根本不需要更改颜色图。想要创建自定义规范化。为此,您可以子类化matplotlib.colors.Normalize并让其返回自定义函数的值。该函数需要采用介于vmin之间的值vmax作为输入和返回值,范围为[0,1]。

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.colors as mcolors


class MyNormalize(mcolors.Normalize):
    def __call__(self, value, clip=None):
        # function to normalize any input between vmin and vmax linearly to [0,1]
        n = lambda x: (x-self.vmin)/(self.vmax-self.vmin)
        # nonlinear function between [0,1] and [0,1]
        f = lambda x,a: (2*x)**a*(2*x<1)/2. +(2-(2*(1-1*x))**a)*(2*x>=1)/2.
        return np.ma.masked_array(f(n(value),0.5))


fig, (ax,ax2) = plt.subplots(ncols=2)

x = np.linspace(-0.3,1.2, num=101)
X = (np.sort(np.random.rand(100))*1.5-0.3)

norm=  MyNormalize(vmin=-0.3, vmax=1.2)

ax.plot(x,norm(x))
im = ax2.imshow(X[::-1,np.newaxis], norm=norm, cmap="coolwarm", aspect="auto")
fig.colorbar(im)

plt.show()

在此处输入图片说明

所需色条的图像建议使用部分线性函数,例如使用以下蜜蜂。

class MyNormalize2(mcolors.Normalize):
    def __call__(self, value, clip=None):
        n = lambda x: self.vmin+(self.vmax-self.vmin)*x
        x, y = [self.vmin, n(0.2), n(0.8), self.vmax], [0, 0.48,0.52, 1]
        return np.ma.masked_array(np.interp(value, x, y))

在此处输入图片说明

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章