如何解决无论图形大小如何,您能否在 matplotlib 中强制图形子图的 wspace 和 hspace 为固定值
我正在尝试构建一个函数,以在具有单个颜色条和直方图的网格中绘制多个图像。我希望所有图之间的间距是一个固定值,并且颜色条跨越所有图像的高度,直方图跨越图像/颜色条的宽度。我有一些有效的代码,但它需要将图形大小设置为特定的纵横比才能工作。这并不理想,因为我想将该函数用于具有不同纵横比的图像以及不同数量的图像 2x1、1x2、2x2 等。
此代码输出 3 个不同纵横比的数字。我想是否将任何多余的尺寸应用于边框间距而不是子图 wspace、hspace 间距。
无花果宽:https://i.stack.imgur.com/BB1Cz.png
无花果:https://i.stack.imgur.com/G5C34.png
无花果:https://i.stack.imgur.com/AVX6C.png
代码如下:
import math
import numpy as np
import matplotlib as mpl
from matplotlib import pyplot as plt
def compare_frames(frames,columns,bins=256,alpha=.5,vmin=None,vmax=None,fig=None):
if vmin is None:
vmin = min([f.min() for f in frames])
if vmax is None:
vmax = max([f.max() for f in frames])
if fig == None:
fig = plt.figure()
color_cycle = plt.get_cmap('tab10')
rows = math.ceil(len(frames)/columns)
width_ratios = [1 for col in range(columns)] + [.05]
gs = mpl.gridspec.GridSpec(rows + 1,columns + 1,figure=fig,width_ratios=width_ratios)
images = []
for row in range(rows):
for col in range(columns):
idx = row*columns + col
if idx < len(frames):
ax = fig.add_subplot(gs[row,col])
ax.get_xaxis().set_ticks([])
ax.get_yaxis().set_ticks([])
for spine in ['bottom','top','left','right']:
ax.spines[spine].set_color(color_cycle(idx))
ax.spines[spine].set_linewidth(3)
images.append(ax.imshow(frames[idx],vmin=vmin,vmax=vmax))
cax = fig.add_subplot(gs[0:-1,-1])
plt.colorbar(images[0],cax=cax)
hax = fig.add_subplot(gs[-1,:])
for i,frame in enumerate(frames):
hax.hist(frame.ravel(),range=(vmin,vmax),color=color_cycle(i),alpha=alpha)
fig.subplots_adjust(wspace=.05,hspace=.05)
if __name__ == '__main__':
x_size = 640
y_size = 512
frames = []
for i in range(4):
frames.append(np.random.normal(i + 1,np.sqrt(i + 1),size=(y_size,x_size)))
fig_wide = plt.figure(figsize=(12,8))
compare_frames(frames,2,fig=fig_wide)
fig_tall = plt.figure(figsize=(6,fig=fig_tall)
fig_nice = plt.figure(figsize=(6.9,fig=fig_nice)
plt.show()
解决方法
我认为我可能应该使用 mpl_toolkits 中的 matplotlib axes_grid1。他们有一个内置的 ImageGrid 类,它可以做很多我想做的事情(图像和颜色条的固定间距):
def compare_frames(frames,columns,bins=256,alpha=.5,vmin=None,vmax=None,fig=None):
if vmin is None:
vmin = min([f.min() for f in frames])
if vmax is None:
vmax = max([f.max() for f in frames])
if fig == None:
fig = plt.figure()
color_cycle = plt.get_cmap('tab10')
rows = math.ceil(len(frames)/columns)
im_grid = axes_grid1.ImageGrid(fig,111,nrows_ncols=(rows,columns),axes_pad=.1,cbar_mode='single',cbar_pad=.1,cbar_size=.3)
for i,ax in enumerate(im_grid):
im = ax.imshow(frames[i],vmin=vmin,vmax=vmax)
ax.get_xaxis().set_ticks([])
ax.get_yaxis().set_ticks([])
for spine in ['bottom','top','left','right']:
ax.spines[spine].set_color(color_cycle(i))
ax.spines[spine].set_linewidth(3)
cbar = fig.colorbar(im,cax=im_grid.cbar_axes[0])
这很棒,我很想找到一种方法来使用这个 ImageGrid 类来完成大部分工作,然后在直方图的底部添加另一个轴。但是,我无法破解如何执行此操作,因为我发现的所有示例都在 Divider 类上使用“append_axes()”。然而,ImageGrid 形成了一个 SubplotDivider,它没有 append_axes 函数。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。