Matplotlib 颜色栏边框和颜色未对齐

Matplotlib 颜色栏边框和颜色未对齐,matplotlib,alignment,colorbar,Matplotlib,Alignment,Colorbar,我对色条有一个恼人的问题,即使经过了认真的研究,我也找不到这个问题,即使有人问我。我有一个绘图,其中我覆盖了一个轮廓和一个pcolormesh,我想要一个颜色条来指示值。除了一件事外,这一切都很好: 颜色条框架和实际的颜色条是偏移的,这样在框架的下方有一个白色位,而在顶部颜色是突出的。当框架根据需要与轴对齐时,颜色条会偏移 下面是一个工作示例,它模拟了我所处的情况,即带有插图的多个绘图 import matplotlib.gridspec as gridspec import numpy as

我对色条有一个恼人的问题,即使经过了认真的研究,我也找不到这个问题,即使有人问我。我有一个绘图,其中我覆盖了一个轮廓和一个pcolormesh,我想要一个颜色条来指示值。除了一件事外,这一切都很好:

颜色条框架和实际的颜色条是偏移的,这样在框架的下方有一个白色位,而在顶部颜色是突出的。当框架根据需要与轴对齐时,颜色条会偏移

下面是一个工作示例,它模拟了我所处的情况,即带有插图的多个绘图

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

figheight = 4.2 - (2.1 - 49.519 / 25.4)
matplotlib.rcParams['figure.figsize'] = (5.25, figheight)
matplotlib.rcParams['axes.linewidth'] = 0.5

fig = plt.figure()
grid = gridspec.GridSpec(2, 1, height_ratios=[49.519 / 25.4 / figheight, 2.1 / figheight])
ax0 = plt.subplot(grid[0, 0])
ax1 = plt.subplot(grid[1, 0])

plt.tight_layout()

###############################################################################################
#
#           Define position of inset
#
    ###############################################################################################

ax1.axis('off')
pos1 = ax1.get_position()
pos2 = matplotlib.transforms.Bbox([[pos1.x0, pos1.y0],
                                    [.8*pos1.x1,
                                     0.8*pos1.height + pos1.y0]])
left, bottom, width, height = [pos2.x0, pos2.y0, pos2.width, pos2.height]

ax2 = fig.add_axes([left, bottom, width, height])

###############################################################################################
#
#           ax2 (inset) plot
#
###############################################################################################

pos2 = ax2.get_position()
ax2.axis('on')

x = np.linspace(0,5)
z = (np.outer(np.sin(x), np.cos(x))+1)*0.5

im = ax2.pcolormesh(z)
c  = ax2.contour(z, linewidths=7)

ax2pos = ax2.get_position()

cbar_axis = fig.add_axes([ax2pos.x1+0.05,ax2pos.y0, .02, ax2pos.height])
colorbar = fig.colorbar(im, ax = ax2,
                    cax = cbar_axis, ticks = [0.1, .5, .9])
colorbar.outline.set_visible(True)

plot = 'Minimal.pdf'

fig.savefig(plot)

plt.close()
如果选择了“内联”图形后端,则内联显示和保存的.pdf文件中的问题仍然存在。使用紧密布局或不使用紧密布局会改变偏移的严重程度,这取决于条形图的大小-与使用PyQT5而不是内联图形后端相同。当我在不同的组合之间切换时,我以为它已经消失了,但我才意识到它仍然存在

如果您有任何意见,我将不胜感激



正如ImportanceOfBeingErnest所建议的,我已经尝试在figsize上使用np.round,但这并没有改变任何事情。虽然你可以随意调整大小使它看起来很好,但它总是在一边或另一边竖立着。当我将Spyder 3上的图形后端从“内联”更改为“QT5”时,无论是否舍入,问题都会变得不那么严重。这张图片是对这一点的总结。请注意,对于not rounded和PyQT5,问题仍然存在,但没有那么严重。

首先,覆盖轮廓和pcolormesh并创建颜色条的方法如下所示

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np

x = np.linspace(0,5)
z = (np.outer(np.sin(x), np.cos(x))+1)*0.5

fig = plt.figure(figsize=(4, 4))
ax = fig.add_subplot(111)
im = ax.pcolormesh(z)
c  = ax.contour(z, linewidths=7)

divider = make_axes_locatable(ax)
cax = divider.append_axes("right", "5%", pad="3%")
colorbar = fig.colorbar(im, cax=cax, ticks = [0.1, .5, .9])

plt.show()

现在从问题开始讨论问题。当然,可以创建轴来手动放置颜色条。用问题中的代码替换色条创建仍然可以生成一个漂亮的图像

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0,5)
z = (np.outer(np.sin(x), np.cos(x))+1)*0.5

fig = plt.figure(figsize=(4, 4))
ax = fig.add_subplot(111)
plt.subplots_adjust(right=0.8)
im = ax.pcolormesh(z)
c  = ax.contour(z, linewidths=7)

ax2pos = ax.get_position()

cbar_axis = fig.add_axes([ax2pos.x1+0.05,ax2pos.y0, .05, ax2pos.height])
colorbar = fig.colorbar(im, ax = ax,
                    cax = cbar_axis, ticks = [0.1, .5, .9])
colorbar.outline.set_visible(True)
plt.show()

到目前为止的结论是:这个问题是不可复制的,至少没有一个完整的研究


我不确定问题中示例中行为的原因。然而,似乎可以通过将数字大小四舍五入到3个有效数字来克服

matplotlib.rcParams['figure.figsize'] = (5.25, np.round(figheight,3))

在检查中,很明显,色条不仅在其轴的顶部溢出,而且还稍微向左定位。 因此,这里的问题似乎是当光栅化发生时,颜色条轴的位置和颜色条本身之间的冲突。你可以找到更多的细节,但我会总结一下这里发生的事情

在生成输出时,色条被光栅化,以避免渲染期间出现伪影问题。在光栅化过程中,颜色条的位置捕捉到最接近的整数像素,而轴保持在它应该位于的位置。然后,当产生输出时,颜色条落在图像的固定像素的边界内,尽管图像本身是矢量化的。因此,有两种策略可以用来避免这场灾难

使用更精细的DPI 从矢量化坐标到栅格化坐标的转换发生在假定图像上有给定DPI的情况下。默认情况下,该值设置为72。然而,通过使用更多DPI,光栅化过程引起的整体偏移将更小,因为颜色条捕捉到的最近像素将更近。在这里,我们将输出更改为具有
fig.savefig(plot,dpi=4000)
,问题就消失了: 但是,请注意,在我的机器上,由于这种变化,输出大小从62 KB更改为78 KB(尽管DPI调整也很极端)。如果您担心文件大小,则应选择较低的DPI来解决此问题

使用不同的颜色贴图 当颜色栏中的颜色超过50种时,就会发生光栅化。因此,我们可以做一个快速测试,通过via将颜色映射设置为
Pastel1
im=ax2.pcolormesh(z,cmap='Pastel1')
。这里,颜色条/轴不匹配得到缓解

作为一种退路,采用少于50种颜色的颜色条可以缓解此问题

光栅化轴 为了完整性,还有第三种选择。如果栅格化颜色条轴,则轴边界和颜色贴图都将栅格化,并且会丢失偏移。这也将栅格化标签,轴将作为一个轴移动,打破与附近轴的对齐。为此,您只需要包括
cbar\u axis.set\u光栅化(True)

尝试使用,至少可以简化颜色条的定位(请参阅)。我不知道偏移量,但你可以尝试用一个(我知道它不理想)来掩盖它。要获得进一步的帮助,你需要提供一个。这是仅在显示时发生,还是仅在保存时发生,或者在两种情况下都发生?我确实怀疑这是什么原因造成的,但由于我无法重现问题,我无法测试这种怀疑是否合理。因为在我获得更多声誉之前,我不能上传超过2个链接:[3]:[4]:我提供了上述示例并添加了更多细节。@Christian编辑了答案。你能证实吗?不,还是一样。你可能碰巧遇到一些颜色条大小的值,使它看起来不错,但是如果你改变它,我总能找到一些值,它位于条的一侧或另一侧,包括圆形的fig大小。你能举一个不起作用的值的例子吗?可能有第三个选项,使用
cbar\u pos=cbar\u axis.get\u position()
获取轴位置值,
new\u cbar\u bbox=matplotlib.transforms.bbox.from\u extends([new\u x0,new\u y0,new\u x1,new\u y1])
创建新的bbox和
cbar\u axis.set\u位置(new\u cbar\u bbox)
将颜色条轴Bbox重置为更适合整数捕捉的值,但我无法完全实现。