在 matplotlib 中更改颜色条渐变

里海

我有一个权重网格 (Y) 随着时间 (X) 演变: 在此处输入图片说明

我无法正确区分权重的变化,因为正负权重之间的分布不对称;应该识别空权重,因为这意味着不使用给定的变量。

由于这些原因,我想更改颜色渐变以获得类似的效果(a 或 b): 在此处输入图片说明

关于如何解决这个问题的任何想法?

存在的重要性欧内斯特

A colorbar in matplotlib maps number between 0 and 1 to a color. In order to map other numbers to colors you need a normalization to the range [0,1] first. This is usually done automatically from the minimum and maximum data, or by using vmin and vmax arguments to the respective plotting function. Internally a normalization instance matplotlib.colors.Normalize is used to perform the normalization and by default a linear scale between vmin and vmax is assumed.

Here you want a nonlinear scale, which (a) shifts the middle point to some specified value, and (b) squeezes the colors around that value.

The idea can now be to subclass matplotlib.colors.Normalize and let it return a a mapping which fulfills the criteria (a) and (b).

An option might be the combination of two root functions as shown below.

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

class SqueezedNorm(matplotlib.colors.Normalize):
    def __init__(self, vmin=None, vmax=None, mid=0, s1=2, s2=2, clip=False):
        self.vmin = vmin # minimum value
        self.mid  = mid  # middle value
        self.vmax = vmax # maximum value
        self.s1=s1; self.s2=s2
        f = lambda x, zero,vmax,s: np.abs((x-zero)/(vmax-zero))**(1./s)*0.5
        self.g = lambda x, zero,vmin,vmax, s1,s2: f(x,zero,vmax,s1)*(x>=zero) - \
                                             f(x,zero,vmin,s2)*(x<zero)+0.5
        matplotlib.colors.Normalize.__init__(self, vmin, vmax, clip)

    def __call__(self, value, clip=None):
        r = self.g(value, self.mid,self.vmin,self.vmax, self.s1,self.s2)
        return np.ma.masked_array(r)


fig, (ax, ax2, ax3) = plt.subplots(nrows=3, 
                                   gridspec_kw={"height_ratios":[3,2,1], "hspace":0.25})

x = np.linspace(-13,4, 110)
norm=SqueezedNorm(vmin=-13, vmax=4, mid=0, s1=1.7, s2=4)

line, = ax.plot(x, norm(x))
ax.margins(0)
ax.set_ylim(0,1)

im = ax2.imshow(np.atleast_2d(x).T, cmap="Spectral_r", norm=norm, aspect="auto")
cbar = fig.colorbar(im ,cax=ax3,ax=ax2, orientation="horizontal")

在此处输入图片说明

选择该函数,使其独立于其参数将任何范围映射到范围上[0,1],以便可以使用颜色图。该参数mid确定应将哪个值映射到颜色图的中间。这将是0在这种情况下。参数s1s2确定颜色图在两个方向上的压缩程度。

设置mid = np.mean(vmin, vmax), s1=1, s2=1将恢复原始缩放。

在此处输入图片说明

为了选择好的参数,可以使用一些滑块来查看实时更新的图。

在此处输入图片说明

from matplotlib.widgets import Slider

midax = plt.axes([0.1, 0.04, 0.2, 0.03], facecolor="lightblue")
s1ax = plt.axes([0.4, 0.04, 0.2, 0.03], facecolor="lightblue")
s2ax = plt.axes([0.7, 0.04, 0.2, 0.03], facecolor="lightblue")

mid = Slider(midax, 'Midpoint', x[0], x[-1], valinit=0)
s1 = Slider(s1ax, 'S1', 0.5, 6, valinit=1.7)
s2 = Slider(s2ax, 'S2', 0.5, 6, valinit=4)


def update(val):
    norm=SqueezedNorm(vmin=-13, vmax=4, mid=mid.val, s1=s1.val, s2=s2.val)
    im.set_norm(norm)
    cbar.update_bruteforce(im) 
    line.set_ydata(norm(x))
    fig.canvas.draw_idle()

mid.on_changed(update)
s1.on_changed(update)
s2.on_changed(update)

fig.subplots_adjust(bottom=0.15)

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

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

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章