我修改了 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()
代码不再正常工作。您可以看到 2D 颜色图具有不同的颜色图,但颜色条是相同的。 如何解决这个问题? matplotlib 有问题吗?
您忘记定义标准化类的
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()