【问题标题】:Matplotlib: how to get image color bar to show up when using plt.figure() and figure.addaxes()Matplotlib:如何在使用 plt.figure() 和 figure.addaxes() 时显示图像颜色条
【发布时间】:2016-04-16 03:27:03
【问题描述】:

我正在尝试制作一个包含六个独立地块的图形,以两排三个地块组织。每行图都应该有自己的颜色条,对应于水平组中三个图中显示的图像。从视觉上看,该图应如下所示:

image_type1 | image_type1 | image_type1 | colorbar_for_type1_images

image_type2 | image_type2 | image_type2 | colorbar_for_type2_images

上图中的竖线只是为了分隔图形的不同组成部分。我的图中实际上不需要垂直线。

下面显示了我正在尝试做的一个示例,以及我尝试使用每行中的第三个图像绘制颜色条的失败尝试。

过去,当我将自己的颜色图用于一系列绘制线时,我已经能够使用类似于下面显示的代码成功地做到这一点,而不是像我一样用于图像正在尝试在下面做。

import numpy as np
from matplotlib import pyplot as plt
from matplotlib.cbook import get_sample_data

#Make 6 plotting areas of the same dimensions
figuresizex = 9.0
figuresizey = 6.1
lowerx = .07
lowery = .09
upperx = .92
uppery = .97
xspace = .05
yspace = .11
xwidth = (upperx-lowerx-2*xspace)/3.
ywidth = (uppery-lowery-yspace)/2.

fig = plt.figure(figsize=(figuresizex,figuresizey))
ax1 = fig.add_axes([lowerx,lowery+ywidth+yspace,xwidth,ywidth])
ax2 = fig.add_axes([lowerx+xwidth+xspace,lowery+ywidth+yspace,xwidth,ywidth])
ax3 = fig.add_axes([lowerx+2*xwidth+2*xspace,lowery+ywidth+yspace,xwidth,ywidth])
ax4 = fig.add_axes([lowerx,lowery,xwidth,ywidth])
ax5 = fig.add_axes([lowerx+xwidth+xspace,lowery,xwidth,ywidth])
ax6 = fig.add_axes([lowerx+2*xwidth+2*xspace,lowery,xwidth,ywidth])
axlist = [ax1,ax2,ax3,ax4,ax5,ax6]

#Start plotting images
image = np.identity(5)

for i in range(0,3):
    vmin, vmax = image.min(),image.max()
    axuse = axlist[i]
    im = axuse.imshow(image, vmin=vmin, vmax=vmax)
    if i == 3:
        cbar = axuse.colorbar(im)
        cbar = plt.colorbar(im)

image_2 = np.arange(16).reshape((4,4))

for i in range(0,3):
    vmin, vmax = image_2.min(),image_2.max()
    axuse = axlist[i+3]
    axuse.imshow(image_2,vmin=vmin, vmax=vmax)
    if i == 3:
        cbar = axuse.colorbar()
        cbar = plt.colorbar()

plt.show()

【问题讨论】:

    标签: python matplotlib plot colorbar


    【解决方案1】:

    我建议采用this question 中概述的方法。

    除了使添加颜色条变得简单且不依赖于您的第三张图像(应该是 i==2)之外,ImageGrid 的使用消除了显式(痛苦地?)定义所有 6 个轴和如果您的图像数量发生变化,它会变得更加灵活。

    更新:我添加了第三行,以表明使用 vmin 和 vmax 参数可以将相同的比例应用于每行中的所有图像。

    import numpy as np
    from matplotlib import pyplot as plt
    from mpl_toolkits.axes_grid1 import ImageGrid
    
    figuresizex = 9.0
    figuresizey = 6.1
    
    # generate images
    image1 = np.identity(5)
    image2 = np.arange(16).reshape((4,4))
    
    
    
    fig = plt.figure(figsize=(figuresizex,figuresizey))
    
    # create your grid objects
    top_row = ImageGrid(fig, 311, nrows_ncols = (1,3), axes_pad = .25,
                        cbar_location = "right", cbar_mode="single")
    middle_row = ImageGrid(fig, 312, nrows_ncols = (1,3), axes_pad = .25,
                           cbar_location = "right", cbar_mode="single")
    bottom_row = ImageGrid(fig, 313, nrows_ncols = (1,3), axes_pad = .25,
                           cbar_location = "right", cbar_mode="single")
    
    # plot the images            
    for i in range(3):
        vmin, vmax = image1.min(),image1.max()
        ax = top_row[i]
        im1 = ax.imshow(image1, vmin=vmin, vmax=vmax)
    
    for i in range(3):
        vmin, vmax = image2.min(),image2.max()
        ax =middle_row[i]
        im2 = ax.imshow(image2, vmin=vmin, vmax=vmax)
    
    # Update showing how to use identical scale across all 3 images
    # make some slightly different images and get their bounds
    image2s = [image2,image2 + 5,image2 - 5]
    
    # inelegant way to get the absolute upper and lower bounds from the three images
    i_max, i_min = 0,0
    for im in image2s:
        if im.max() > i_max: 
            i_max= im.max()
        if im.min() < i_min: 
            i_min = im.min()
    # plot these as you would the others, but use identical vmin and vmax for all three plots
    for i,im in enumerate(image2s):
        ax = bottom_row[i]
        im2_scaled = ax.imshow(im, vmin = i_min, vmax = i_max)
    
    # add your colorbars
    cbar1 = top_row.cbar_axes[0].colorbar(im1)
    middle_row.cbar_axes[0].colorbar(im2)       
    bottom_row.cbar_axes[0].colorbar(im2_scaled)
    
    # example of titling colorbar1
    cbar1.set_label_text("label"))
    
    # readjust figure margins after adding colorbars, 
    # left and right are unequal because of how
    # colorbar labels don't appear to factor in to the adjustment
    plt.subplots_adjust(left=0.075, right=0.9)
    
    plt.show()
    

    【讨论】:

    • 绝妙的答案!这正是我想要的。感谢您指出我的i==2 错误,我最近一直在编辑一些 Fortran 代码并且搞混了。问题:如果对于给定行中的三个图像,数据的值范围不完全相同,为了确保所有三个图像的配色方案一致,我可以找到最小值.min() 和最大值.max()所有三个图像的值并在所有三个调用 ImageGrid() 函数中使用这些值?
    • 好问题。可以,只要确保将最小值和最大值传递给imshowvminvmax 参数即可。我已经用第三个 ImageGrid 行编辑了我的答案以反映这一点。
    • ImageGrid() 似乎使图中的轴居中。这意味着,当添加颜色条时,坐标区 + 颜色条组合不再在图窗内居中。有什么办法解决这个问题吗?将整个事情集中在中心会很好。另外,如何给颜色条标签?
    • 嗯,这很奇怪。有时 matplotlib 看起来像黑魔法。不知道“正确”的方法是什么,但你可以manually readjust the figure borders 使用plt.subplots_adjust 重新定位所有内容(我已经使用此编辑了答案)或plt.tight_layout 在我的答案中引发错误但仍然出现去工作 (?)。很高兴我对此进行了深入研究,我一直在批量生成的一些地图中遇到边距问题,这应该可以解决它。
    猜你喜欢
    • 2021-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-13
    • 2016-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多