尽管使用 bbox_inches="tight",plt.savefig() 从颜色栏标签中部分裁剪下标字符
plt.savefig() partially crops subscript character from colorbar label, despite using bbox_inches="tight"
我有一个图形,其中在主图的 x 轴下方包含一个带标签的颜色条。当我尝试使用 plt.savefig() 保存它时,标签中下标字符的最底部被从保存的图像中裁剪掉,例如 this, despite using bbox_inches="tight". However, if I simply save the figure manually in the pop-up window, the subscript character is not cropped, like this.
虽然后一张图片可以手动裁剪,或者使用代码中的额外行裁剪,但如果您能提供有关如何解决此问题而不需要额外工作的任何建议,我将不胜感激。
我试过像这样在颜色栏标签中添加一个换行符:
label="$U/U_{"+(u"\u221e")+"}$\n"
但这只是在标签下方添加了白色space;下标字符的底部仍然被裁剪。
我也尝试添加以下行:
cb.set_label(label,labelpad=5)
但这只是将标签从颜色条的底部偏移了;标签下方没有额外填充以完整显示下标字符。
代码如下:
import numpy
import random
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.colors as mcolors
import matplotlib.colorbar as cbar
from matplotlib import cm
##########################################################
# Centre colourmap so 0=white
class MidpointNormalize(mpl.colors.Normalize):
def __init__(self,vmin=None,vmax=None,midpoint=None,clip=False):
self.midpoint=midpoint
mpl.colors.Normalize.__init__(self,vmin,vmax,clip)
def __call__(self,value,clip=None):
x,y=[self.vmin,self.midpoint,self.vmax],[0,0.5,1]
return numpy.ma.masked_array(numpy.interp(value,x,y),numpy.isnan(value))
##########################################################
# Set min and max values
xymin=0
xymax=10
valmin=-5
valmax=5
val=numpy.zeros((xymax,xymax),dtype=float)
# Configure plot
fig,ax=plt.subplots()
ax.set_xlim([xymin,xymax])
ax.set_ylim([xymin,xymax])
# Configure colour bar
colours=plt.cm.RdBu(numpy.linspace(0,1,256))
colourmap=mcolors.LinearSegmentedColormap.from_list('colourmap',colours)
normalisecolors=mpl.colors.Normalize(vmin=valmin,vmax=valmax)
scalecolors=cm.ScalarMappable(norm=normalisecolors,cmap=colourmap)
label="$U/U_{"+(u"\u221e")+"}$"
for ix in range(xymin,xymax):
for iy in range(xymin,xymax):
xlow=ix*+1 # Calculate vertices of patch
xhigh=(ix*1)+1
ylow=iy*1
yhigh=(iy*1)+1
val[ix][iy]=random.randint(valmin,valmax) # Patch value
rgbacolor=scalecolors.to_rgba(val[ix][iy]) # Calculate RGBA colour for value
ax.add_patch(patches.Polygon([(xlow,ylow),(xlow,yhigh),(xhigh,yhigh),(xhigh,ylow)],fill=True,facecolor=rgbacolor)) # Add value as polygon patch
cax,_=cbar.make_axes(ax,orientation="horizontal")
cb=cbar.ColorbarBase(cax,cmap=colourmap,norm=MidpointNormalize(midpoint=0,vmin=valmin,vmax=valmax),orientation="horizontal",label=label)
plt.savefig("C:/Users/Christopher/Desktop/test.png",dpi=1200,bbox_inches="tight")
plt.clf
plt.close()
恐怕我真的没有一个好的答案给你。这似乎与此错误有关 https://github.com/matplotlib/matplotlib/issues/15313
好消息是它正在处理中,坏消息是目前还没有修复。
无论如何要考虑两点(基于阅读 github 上的帖子):
- dpi越高越差。所以你可能想以较低的 dpi 保存(300 对我来说很好)
- 问题不存在于 pdf 后端,因此您可以将绘图保存为 pdf(如果需要,最终转换为 png)
顺便说一句(这与所讨论的错误无关):我对您代码的复杂性感到困惑。在我看来,以下代码产生相同的输出:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import TwoSlopeNorm
N=10
valmin=-5
valmax=5
valmid=0
val=np.random.randint(low=valmin, high=valmax, size=(N,N))
cmap = 'RdBu'
norm = TwoSlopeNorm(vcenter=valmid, vmin=valmin, vmax=valmax)
label="$U/U_{"+(u"\u221e")+"}$"
# Configure plot
fig, ax=plt.subplots()
im = ax.imshow(val, cmap=cmap, norm=norm, aspect='auto', origin='lower')
cbar = fig.colorbar(im, orientation='horizontal', label=label)
fig.savefig('./test-1200.png',dpi=1200,bbox_inches="tight") # subscript is cut
fig.savefig('./test-300.png',dpi=300,bbox_inches="tight") # subscript is not cut
fig.savefig('./test-pdf.pdf',dpi=1200,bbox_inches="tight") # subscript is not cut
1200 dpi:
300 dpi:
pdf:
我有一个图形,其中在主图的 x 轴下方包含一个带标签的颜色条。当我尝试使用 plt.savefig() 保存它时,标签中下标字符的最底部被从保存的图像中裁剪掉,例如 this, despite using bbox_inches="tight". However, if I simply save the figure manually in the pop-up window, the subscript character is not cropped, like this.
虽然后一张图片可以手动裁剪,或者使用代码中的额外行裁剪,但如果您能提供有关如何解决此问题而不需要额外工作的任何建议,我将不胜感激。
我试过像这样在颜色栏标签中添加一个换行符:
label="$U/U_{"+(u"\u221e")+"}$\n"
但这只是在标签下方添加了白色space;下标字符的底部仍然被裁剪。
我也尝试添加以下行:
cb.set_label(label,labelpad=5)
但这只是将标签从颜色条的底部偏移了;标签下方没有额外填充以完整显示下标字符。
代码如下:
import numpy
import random
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.colors as mcolors
import matplotlib.colorbar as cbar
from matplotlib import cm
##########################################################
# Centre colourmap so 0=white
class MidpointNormalize(mpl.colors.Normalize):
def __init__(self,vmin=None,vmax=None,midpoint=None,clip=False):
self.midpoint=midpoint
mpl.colors.Normalize.__init__(self,vmin,vmax,clip)
def __call__(self,value,clip=None):
x,y=[self.vmin,self.midpoint,self.vmax],[0,0.5,1]
return numpy.ma.masked_array(numpy.interp(value,x,y),numpy.isnan(value))
##########################################################
# Set min and max values
xymin=0
xymax=10
valmin=-5
valmax=5
val=numpy.zeros((xymax,xymax),dtype=float)
# Configure plot
fig,ax=plt.subplots()
ax.set_xlim([xymin,xymax])
ax.set_ylim([xymin,xymax])
# Configure colour bar
colours=plt.cm.RdBu(numpy.linspace(0,1,256))
colourmap=mcolors.LinearSegmentedColormap.from_list('colourmap',colours)
normalisecolors=mpl.colors.Normalize(vmin=valmin,vmax=valmax)
scalecolors=cm.ScalarMappable(norm=normalisecolors,cmap=colourmap)
label="$U/U_{"+(u"\u221e")+"}$"
for ix in range(xymin,xymax):
for iy in range(xymin,xymax):
xlow=ix*+1 # Calculate vertices of patch
xhigh=(ix*1)+1
ylow=iy*1
yhigh=(iy*1)+1
val[ix][iy]=random.randint(valmin,valmax) # Patch value
rgbacolor=scalecolors.to_rgba(val[ix][iy]) # Calculate RGBA colour for value
ax.add_patch(patches.Polygon([(xlow,ylow),(xlow,yhigh),(xhigh,yhigh),(xhigh,ylow)],fill=True,facecolor=rgbacolor)) # Add value as polygon patch
cax,_=cbar.make_axes(ax,orientation="horizontal")
cb=cbar.ColorbarBase(cax,cmap=colourmap,norm=MidpointNormalize(midpoint=0,vmin=valmin,vmax=valmax),orientation="horizontal",label=label)
plt.savefig("C:/Users/Christopher/Desktop/test.png",dpi=1200,bbox_inches="tight")
plt.clf
plt.close()
恐怕我真的没有一个好的答案给你。这似乎与此错误有关 https://github.com/matplotlib/matplotlib/issues/15313
好消息是它正在处理中,坏消息是目前还没有修复。
无论如何要考虑两点(基于阅读 github 上的帖子):
- dpi越高越差。所以你可能想以较低的 dpi 保存(300 对我来说很好)
- 问题不存在于 pdf 后端,因此您可以将绘图保存为 pdf(如果需要,最终转换为 png)
顺便说一句(这与所讨论的错误无关):我对您代码的复杂性感到困惑。在我看来,以下代码产生相同的输出:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import TwoSlopeNorm
N=10
valmin=-5
valmax=5
valmid=0
val=np.random.randint(low=valmin, high=valmax, size=(N,N))
cmap = 'RdBu'
norm = TwoSlopeNorm(vcenter=valmid, vmin=valmin, vmax=valmax)
label="$U/U_{"+(u"\u221e")+"}$"
# Configure plot
fig, ax=plt.subplots()
im = ax.imshow(val, cmap=cmap, norm=norm, aspect='auto', origin='lower')
cbar = fig.colorbar(im, orientation='horizontal', label=label)
fig.savefig('./test-1200.png',dpi=1200,bbox_inches="tight") # subscript is cut
fig.savefig('./test-300.png',dpi=300,bbox_inches="tight") # subscript is not cut
fig.savefig('./test-pdf.pdf',dpi=1200,bbox_inches="tight") # subscript is not cut
1200 dpi:
300 dpi:
pdf: