带有自定义 LogNorm 的 Colorbar 无法正常工作

问题描述 投票:0回答:1

我修改了 matplotlib.colors 中的 LogNorm,以便可以手动设置对数刻度上的中点。 2D 颜色图随新的标准化颜色图相应变化,但颜色条与旧的未修改的颜色图保持不变。

已经有类似的代码: 移动对数颜色条,白色偏移到中心

使用以下代码:

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

x,y = np.meshgrid(np.linspace(-3,0,19), np.arange(10))
f = lambda x,y : 10**x*(1+y)
z = f(x,y)

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

im = ax.pcolormesh(x,y,z, cmap="RdBu_r", norm=LogNorm(vmin=z.min(), vmax=z.max()))
fig.colorbar(im, ax=ax)
ax.set_title("LogNorm")

class MidPointLogNorm(LogNorm):
    def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
        LogNorm.__init__(self,vmin=vmin, vmax=vmax, clip=clip)
        self.midpoint=midpoint
    def __call__(self, value, clip=None):
        # I'm ignoring masked values and all kinds of edge cases to make a
        # simple example...
        x, y = [np.log(self.vmin), np.log(self.midpoint), np.log(self.vmax)], [0, 0.5, 1]
        return np.ma.masked_array(np.interp(np.log(value), x, y))


im2 = ax2.pcolormesh(x,y,z, cmap="RdBu_r", 
                            norm=MidPointLogNorm(vmin=z.min(), vmax=z.max(), midpoint=1))
fig.colorbar(im2, ax=ax2)
ax2.set_title("MidPointLogNorm")
plt.show()

enter image description here

代码不再正常工作。您可以看到 2D 颜色图具有不同的颜色图,但颜色条是相同的。 如何解决这个问题? matplotlib 有问题吗?

python matplotlib colorbar
1个回答
0
投票

enter image description here

您忘记定义标准化类的

inverse
方法,从
inverse
调用
Colorbar
方法将标准化值映射到数据,在您的示例中,它使用基类的
inverse
方法,而不是知道你的中点...请参阅下面的代码了解
inverse
的定义。

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

class MidPointLogNorm(LogNorm):
    def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
        LogNorm.__init__(self,vmin=vmin, vmax=vmax, clip=clip)
        self.midpoint=midpoint
    def __call__(self, value, clip=None):
        # I'm ignoring masked values and all kinds of edge cases to make a
        # simple example...
        x, y = [np.log(self.vmin), np.log(self.midpoint), np.log(self.vmax)], [0, 0.5, 1]
        return np.ma.masked_array(np.interp(np.log(value), x, y))
    def inverse(self, value):
        # I'm ignoring masked values and all kinds of edge cases to make a simple example
        vmin, mid, vmax = self.vmin, self.midpoint, self.vmax
        a1, a2 = 2*np.log(mid/vmin), 2*np.log(vmax/mid)
        k1, k2 = vmin, mid*mid/vmax
        return np.where(value<0.5, k1*np.exp(a1*value), k2*np.exp(a2*value))

x,y = np.meshgrid(np.linspace(-3,0,19), np.arange(10))
z = 10**x*(1+y)

norm = MidPointLogNorm(vmin=0.001, vmax=10, midpoint=1)

fig, ax = plt.subplots()
im = ax.pcolormesh(x,y,z, cmap="RdBu_r", norm=norm)
cb = fig.colorbar(im, ax=ax)

plt.show()
© www.soinside.com 2019 - 2024. All rights reserved.