这是一个可能的解决方案。您将从图形宽度开始(这在准备论文时是有意义的)并使用图形的各个方面计算您的方式,子图和边距之间的一些任意间距。这些公式类似于我在this answer 中使用的公式。不平等方面由GridSpec 的width_ratios 论点处理。
然后你最终得到一个图形高度,使得子图的高度相等。
所以你不能避免输入一些数字,但它们不是“魔法”。所有这些都与可访问量有关,例如图形大小的分数或平均子图大小的分数。由于系统是封闭的,改变任何数字只会产生不同的图形高度,但不会破坏布局。
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np; np.random.seed(42)
imgs = []
shapes = [(550,200), ( 550,205), (1100,274) ]
for shape in shapes:
imgs.append(np.random.random(shape))
# calculate inverse aspect(width/height) for all images
inva = np.array([ img.shape[1]/float(img.shape[0]) for img in imgs])
# set width of empty column used to stretch layout
emptycol = 0.02
r = np.array([inva[0],inva[1], emptycol, inva[2], 3*emptycol, emptycol])
# set a figure width in inch
figw = 8
# border, can be set independently of all other quantities
left = 0.1; right=1-left
bottom=0.1; top=1-bottom
# wspace (=average relative space between subplots)
wspace = 0.1
#calculate scale
s = figw*(right-left)/(len(r)+(len(r)-1)*wspace)
# mean aspect
masp = len(r)/np.sum(r)
#calculate figheight
figh = s*masp/float(top-bottom)
gs = gridspec.GridSpec(3,len(r), width_ratios=r)
fig = plt.figure(figsize=(figw,figh))
plt.subplots_adjust(left, bottom, right, top, wspace)
ax1 = plt.subplot(gs[:,0])
ax2 = plt.subplot(gs[:,1])
ax2.set_yticks([])
ax3 = plt.subplot(gs[:,3])
ax3.yaxis.tick_right()
ax3.yaxis.set_label_position("right")
cax1 = plt.subplot(gs[0,5])
cax2 = plt.subplot(gs[1,5])
cax3 = plt.subplot(gs[2,5])
im1 = ax1.imshow(imgs[0], cmap="viridis")
im2 = ax2.imshow(imgs[1], cmap="plasma")
im3 = ax3.imshow(imgs[2], cmap="RdBu")
fig.colorbar(im1, ax=ax1, cax=cax1)
fig.colorbar(im2, ax=ax2, cax=cax2)
fig.colorbar(im3, ax=ax3, cax=cax3)
ax1.set_title("image title")
ax1.set_xlabel("xlabel")
ax1.set_ylabel("ylabel")
plt.show()