【问题标题】:setting fixed color bar values设置固定颜色条值
【发布时间】:2020-02-09 22:55:28
【问题描述】:

我正在绘制一些按时间步长动画的节点数据,如下所示:

fig, ax = plt.subplots()
fig.tight_layout()
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)

def animate(i):
    ax.cla()
    plt.cla()
    ax.set_aspect('equal', 'box')
    c = ax.tricontourf(triang, z[:, i], 10, cmap='plasma')
    c.set_clim(np.min(z), np.max(z))
    plt.colorbar(c, cax=cax)

anim = FuncAnimation(fig, animate, interval=100, frames=nt)

其中 z - 是 nnodes x number_of_timesteps 节点值矩阵。但正如您在下图中看到的那样,颜色条的范围和值似乎并没有固定。我的意思是分配给特定颜色的值似乎是固定的,但颜色图例会及时变化。我认为c.set_clim(np.min(z), np.max(z)) 应该修复它,因为它在每个时间步从整组数据中获取最小和最大节点值,但显然它没有修复颜色条。有办法解决吗?

【问题讨论】:

  • 这可能适用于您的情况:ax.tricontourf(..., vmin=np.min(z), vmax=np.max(z)),省略对 set_clim 的调用。请注意,颜色是在tricontourf 内部分配的。颜色栏只是显示颜色分配方式的有用工具。
  • @JohanC,是的,我没有提到它,但我已经尝试过这种方式。结果是一样的......所以看起来当颜色从情节中消失时,颜色条被重新调整并且颜色也从中消失。但我认为有一种方法可以让它成为静态的......
  • 如果 z 和 np.min(z) 和 np.max(z) 以及 vmin 和 vmax 保持不变,相应的颜色条是否也应该保持不变?也许 np.min(z) 和 max 可以在 animate 函数中打印出来看看发生了什么?
  • @JohanC,检查了它们,它们确实在 animate 函数中的每次迭代都保持不变,这是预期的。
  • @arty:你能发布完整的代码和数据吗?我可以试试

标签: matplotlib colorbar clim


【解决方案1】:

您每次都会得到不同的颜色条,因为您没有指定轮廓的级别。试试:

c = ax.tricontourf(triang, z[:, i], 10, cmap='plasma', vmin=-1, vmax=1, levels=np.arange(-1, 1.02, 0.1))

【讨论】:

    【解决方案2】:

    @SKPS,我们开始吧。在下面的脚本中,我使用了假坐标函数,只是为了给你一些值,因为原始函数是基于 FEM 例程的,因此它非常庞大。通过提供的链接,您可以下载脚本中使用的网格文件。在下面的代码中,我尝试了两种方法:FuncAnimation,用于animate_plot()ArtistAnimation,用于animate_plot2()。您可以通过编辑代码的最后一行来在它们之间切换。看,FuncAnimation 的问题已经被描述过了。使用ArtistAnimation 时,颜色条看起来是静态的,但实际上它是最后一个时间步的颜色条。为了演示它,我更改了animate_plot2() 中的绘图函数,所以如果你运行它,你就会明白我的意思。同样在这种情况下,您会看到绘图的标题不再更新 - 它始终显示一个值。我尝试通过添加行 ax.cla()plt.cla() 来修复它,就像之前的情况一样,但它更糟了。

    亲切的问候。

    网格: https://www.dropbox.com/s/x4njq0t93636wfv/new_cave.msh?dl=0

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    import matplotlib.tri as mtri
    import meshio
    
    from matplotlib.animation import FuncAnimation
    from mpl_toolkits.axes_grid1 import make_axes_locatable
    from matplotlib.offsetbox import (AnchoredOffsetbox, DrawingArea, HPacker,
                                      TextArea)
    
    
    def load_mesh(mesh_filename):
        m = meshio.read(mesh_filename)
        p = m.points.transpose()
        p = np.delete(p, 2, axis=0)
        t = m.cells["triangle"]
        return p, t
    
    
    def animate_plot(nt, p, t):
        x = p[0, :]
        y = p[1, :]
        triang = mtri.Triangulation(x, y, t)
        nnodes = len(p[0])
        z = np.zeros((nnodes, nt))
        for j in range(nt):
            z[:, j] = j ** 2 * (np.sin(x * 10) + np.sin(y * 10))
    
        fig, ax = plt.subplots()
        divider = make_axes_locatable(ax)
        cax = divider.append_axes("right", size="5%", pad=0.05)
    
        def animate(i):
            ax.cla()
            plt.cla()
            ax.set_aspect('equal', 'box')
            ax.set(xlim=(min(x), max(x)), ylim=(min(y), max(y)))
            c = ax.tricontourf(triang, z[:, i], 10, cmap='plasma', vmin=-1, vmax=1)
            c.set_clim(np.min(z), np.max(z))
            ax.triplot(triang, color='white', lw=0.1)
            ax.set_title('test, ' + 'np.min(z)=' + str(np.min(z)) + ', np.max(z)=' + str(np.max(z)) + '.')
            cbar = plt.colorbar(c, cax=cax, format='%.0e')
            ax.set_xlabel('x [m]')
            ax.set_ylabel('y [m]')
    
        anim = FuncAnimation(
            fig, animate, interval=600, frames=nt)
        anim.save('test.gif', writer='imagemagick')
    
    
    def animate_plot2(nt, p, t):
        x = p[0, :]
        y = p[1, :]
        triang = mtri.Triangulation(x, y, t)
        nnodes = len(p[0])
        z = np.zeros((nnodes, nt))
        for j in range(nt):
            z[:, j] = 100 * (np.sin(x * 10) + np.sin(y * 10)) - j ** 2 * (np.sin(x * 10) + np.sin(y * 10))
    
        img = []
        fig, ax = plt.subplots()
        divider = make_axes_locatable(ax)
        cax = divider.append_axes("right", size="5%", pad=0.05)
    
        for i in range(nt):
            # ax.cla()
            # plt.cla()
            ax.set_aspect('equal', 'box')
            ax.set(xlim=(min(x), max(x)), ylim=(min(y), max(y)))
            fig.tight_layout()
            ax.set_title('time step = ' + str(i))
            c = ax.tricontourf(triang, z[:, i], 10, cmap='plasma')
            c.set_clim(np.min(z), np.max(z))
            ax.triplot(triang, color='white', lw=0.1)
            plt.colorbar(c, cax=cax)
            img.append(c.collections)
    
        name = 'test.gif'
        anim_img = animation.ArtistAnimation(fig, img, interval=300, blit=True)
        anim_img.save(name, writer='imagemagick', bitrate=300)
    
    
    mesh_filename = 'new_cave.msh'
    p, t = load_mesh(mesh_filename)
    
    nt = 10
    animate_plot2(nt, p, t)
    

    【讨论】:

    • 所以vmin, vmaxset_clim() 一样,它们只是将颜色分配给某个值,您可以更改它们,看看会发生什么。虽然我希望每一帧都有“静态”颜色条图例 - 即使它是所有值都为零的第一帧,我想要有颜色条来显示从 np.min(z)np.max(z) 的整个颜色和值范围.
    • 这应该作为对原始问题 not 的编辑发布作为答案。当有人提示您“发布完整代码”时,他们的意思是编辑问题 - 仅供将来参考
    猜你喜欢
    • 2011-03-03
    • 2021-12-18
    • 1970-01-01
    • 2012-05-13
    • 1970-01-01
    • 2015-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多