Matplotlib imshow:更改颜色条的中心值时,NaN 的颜色会发生变化
Matplotlib imshow: Color of NaN changes when change the center value of colorbar
我用 np.NaN 绘制了一个数据。由于原始数据的分布,我还想更改颜色条的中心值。但是当我改变颜色条的Vmin、Vmax和vcenter值时,np.NaN值的颜色变成了白色以外的其他颜色。那么我该如何解决呢?以下是代码:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors_tmp
class MidpointNormalize(colors_tmp.Normalize):
def __init__(self, vmin=None, vmax=None, vcenter=None, clip=False):
self.vcenter = vcenter
colors_tmp.Normalize.__init__(self, vmin, vmax, clip)
def __call__(self, value, clip=None):
# I'm ignoring masked values and all kinds of edge cases to make a
# simple example...
x, y = [self.vmin, self.vcenter, self.vmax], [0, 0.5, 1]
return np.ma.masked_array(np.interp(value, x, y))
img = np.linspace(1,1000,1000).reshape((20,50))
img[(img>700)*(img<800)] = np.nan
fig, ax = plt.subplots(1,1)
sc = ax.imshow(img)
axpos = ax.get_position()
cbar_ax = fig.add_axes(
[axpos.x1, axpos.y0, 0.01, axpos.height]) # l, b, w, h
cbar = fig.colorbar(sc, cax=cbar_ax)
然后我像这样更改颜色条的 Vmin、Vmax 和 vcenter:
fig, ax = plt.subplots(1,1)
sc = ax.imshow(img)
axpos = ax.get_position()
cbar_ax = fig.add_axes(
[axpos.x1, axpos.y0, 0.01, axpos.height]) # l, b, w, h
cbar = fig.colorbar(sc, cax=cbar_ax)
midnorm = MidpointNormalize(vmin=0, vcenter=200, vmax=500)
cbar.mappable.set_norm(midnorm)
cbar.mappable.set_cmap('BrBG')
结果如下,可以看到np.NaN的颜色还是白色
但是当我将其更改为 vmin=0, vcenter=800, vmax=1000
时,事情变得很奇怪:
fig, ax = plt.subplots(1,1)
sc = ax.imshow(img)
axpos = ax.get_position()
cbar_ax = fig.add_axes(
[axpos.x1, axpos.y0, 0.01, axpos.height]) # l, b, w, h
cbar = fig.colorbar(sc, cax=cbar_ax)
midnorm = MidpointNormalize(vmin=0, vcenter=800, vmax=1000)
cbar.mappable.set_norm(midnorm)
cbar.mappable.set_cmap('BrBG')
那是为什么呢?我想将 np.NaN 值保持为白色,我尝试了 ax.set_patch
和 set_bad(color="white")
,它们都不起作用...所以有没有人可以帮助我?非常感谢!
使用最新的 matplotlib 版本 (3.4.2),代码似乎按预期工作。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors_tmp
class MidpointNormalize(Normalize):
def __init__(self, vmin=None, vmax=None, vcenter=None, clip=False):
self.vcenter = vcenter
colors_tmp.Normalize.__init__(self, vmin, vmax, clip)
def __call__(self, value, clip=None):
# I'm ignoring masked values and all kinds of edge cases to make a
# simple example...
x, y = [self.vmin, self.vcenter, self.vmax], [0, 0.5, 1]
return np.ma.masked_array(np.interp(value, x, y))
img = np.linspace(1, 1000, 1000).reshape((20, 50))
img[(img > 700) * (img < 800)] = np.nan
fig, ax = plt.subplots(1, 1)
sc = ax.imshow(img)
axpos = ax.get_position()
cbar_ax = fig.add_axes(
[axpos.x1 + 0.01, axpos.y0, 0.01, axpos.height]) # l, b, w, h
cbar = fig.colorbar(sc, cax=cbar_ax)
midnorm = MidpointNormalize(vmin=0, vcenter=800, vmax=1000)
cbar.mappable.set_norm(midnorm)
cbar.mappable.set_cmap('BrBG')
plt.show()
另外,你可以试试:
- 调用时直接设置范数和cmap
imshow
- 使用
TwoSlopeNorm
而不是自定义规范
- 明确设置“不良”颜色(
'none'
透明,显示背景,或 'white'
修复与背景无关的颜色)
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
img = np.linspace(1, 1000, 1000).reshape((20, 50))
img[(img > 700) & (img < 800)] = np.nan
fig, ax = plt.subplots(1, 1)
cmap = plt.get_cmap('BrBG')
cmap.set_bad('white')
midnorm = mcolors.TwoSlopeNorm(vmin=0, vcenter=800, vmax=1000)
sc = ax.imshow(img, norm=midnorm, cmap=cmap)
axpos = ax.get_position()
cbar_ax = fig.add_axes(
[axpos.x1 + 0.01, axpos.y0, 0.01, axpos.height]) # l, b, w, h
cbar = fig.colorbar(sc, cax=cbar_ax)
plt.show()
我用 np.NaN 绘制了一个数据。由于原始数据的分布,我还想更改颜色条的中心值。但是当我改变颜色条的Vmin、Vmax和vcenter值时,np.NaN值的颜色变成了白色以外的其他颜色。那么我该如何解决呢?以下是代码:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors_tmp
class MidpointNormalize(colors_tmp.Normalize):
def __init__(self, vmin=None, vmax=None, vcenter=None, clip=False):
self.vcenter = vcenter
colors_tmp.Normalize.__init__(self, vmin, vmax, clip)
def __call__(self, value, clip=None):
# I'm ignoring masked values and all kinds of edge cases to make a
# simple example...
x, y = [self.vmin, self.vcenter, self.vmax], [0, 0.5, 1]
return np.ma.masked_array(np.interp(value, x, y))
img = np.linspace(1,1000,1000).reshape((20,50))
img[(img>700)*(img<800)] = np.nan
fig, ax = plt.subplots(1,1)
sc = ax.imshow(img)
axpos = ax.get_position()
cbar_ax = fig.add_axes(
[axpos.x1, axpos.y0, 0.01, axpos.height]) # l, b, w, h
cbar = fig.colorbar(sc, cax=cbar_ax)
然后我像这样更改颜色条的 Vmin、Vmax 和 vcenter:
fig, ax = plt.subplots(1,1)
sc = ax.imshow(img)
axpos = ax.get_position()
cbar_ax = fig.add_axes(
[axpos.x1, axpos.y0, 0.01, axpos.height]) # l, b, w, h
cbar = fig.colorbar(sc, cax=cbar_ax)
midnorm = MidpointNormalize(vmin=0, vcenter=200, vmax=500)
cbar.mappable.set_norm(midnorm)
cbar.mappable.set_cmap('BrBG')
结果如下,可以看到np.NaN的颜色还是白色
但是当我将其更改为 vmin=0, vcenter=800, vmax=1000
时,事情变得很奇怪:
fig, ax = plt.subplots(1,1)
sc = ax.imshow(img)
axpos = ax.get_position()
cbar_ax = fig.add_axes(
[axpos.x1, axpos.y0, 0.01, axpos.height]) # l, b, w, h
cbar = fig.colorbar(sc, cax=cbar_ax)
midnorm = MidpointNormalize(vmin=0, vcenter=800, vmax=1000)
cbar.mappable.set_norm(midnorm)
cbar.mappable.set_cmap('BrBG')
那是为什么呢?我想将 np.NaN 值保持为白色,我尝试了 ax.set_patch
和 set_bad(color="white")
,它们都不起作用...所以有没有人可以帮助我?非常感谢!
使用最新的 matplotlib 版本 (3.4.2),代码似乎按预期工作。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors_tmp
class MidpointNormalize(Normalize):
def __init__(self, vmin=None, vmax=None, vcenter=None, clip=False):
self.vcenter = vcenter
colors_tmp.Normalize.__init__(self, vmin, vmax, clip)
def __call__(self, value, clip=None):
# I'm ignoring masked values and all kinds of edge cases to make a
# simple example...
x, y = [self.vmin, self.vcenter, self.vmax], [0, 0.5, 1]
return np.ma.masked_array(np.interp(value, x, y))
img = np.linspace(1, 1000, 1000).reshape((20, 50))
img[(img > 700) * (img < 800)] = np.nan
fig, ax = plt.subplots(1, 1)
sc = ax.imshow(img)
axpos = ax.get_position()
cbar_ax = fig.add_axes(
[axpos.x1 + 0.01, axpos.y0, 0.01, axpos.height]) # l, b, w, h
cbar = fig.colorbar(sc, cax=cbar_ax)
midnorm = MidpointNormalize(vmin=0, vcenter=800, vmax=1000)
cbar.mappable.set_norm(midnorm)
cbar.mappable.set_cmap('BrBG')
plt.show()
另外,你可以试试:
- 调用时直接设置范数和cmap
imshow
- 使用
TwoSlopeNorm
而不是自定义规范 - 明确设置“不良”颜色(
'none'
透明,显示背景,或'white'
修复与背景无关的颜色)
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
img = np.linspace(1, 1000, 1000).reshape((20, 50))
img[(img > 700) & (img < 800)] = np.nan
fig, ax = plt.subplots(1, 1)
cmap = plt.get_cmap('BrBG')
cmap.set_bad('white')
midnorm = mcolors.TwoSlopeNorm(vmin=0, vcenter=800, vmax=1000)
sc = ax.imshow(img, norm=midnorm, cmap=cmap)
axpos = ax.get_position()
cbar_ax = fig.add_axes(
[axpos.x1 + 0.01, axpos.y0, 0.01, axpos.height]) # l, b, w, h
cbar = fig.colorbar(sc, cax=cbar_ax)
plt.show()