编程语言
首页 > 编程语言> > python – 使用Matplotlib的Arbirtrary非线性颜色条

python – 使用Matplotlib的Arbirtrary非线性颜色条

作者:互联网

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

然而,通常,这些值要么非常接近零,要么非常接近1.然后很难看到颜色的变化,因为一切都是非常红或非常蓝(使用冷色图).

然后,我的想法是应用像以下其中一个过滤器过滤器:

enter image description here

它只是一个多项式函数,它提供从[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]间隔上的颜色重新分区,以提高图形的可读性.

例如,我得到:

enter image description here

我很满意左边的部分,但不是正确的部分,颜色条应该是这样的:

enter image description here

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

我尝试在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的理解是有限的,所提出的代码已经是堆栈溢出答案的拼凑.

解决方法:

基本上你根本不想改变色彩图. Instaed您想要创建自定义规范化.为此,您可以将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()

enter image description here

所需颜色条的图像相当于建议使用部分线性函数,如下面所用的函数.

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))

enter image description here

标签:python,matplotlib,networkx,colorbar
来源: https://codeday.me/bug/20190608/1196171.html