2

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

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))应该修复它,因为它在每个时间步从整组数据中获取最小和最大节点值,但显然它并没有修复颜色条。有办法解决吗?

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

4

2 回答 2

2

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

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

于 2020-02-10T19:14:54.093 回答
0

@SKPS,我们开始吧。在下面的脚本中,我使用了假坐标函数,只是为了给你一些值,因为原始函数是基于 FEM 例程的,因此它非常庞大。通过提供的链接,您可以下载脚本中使用的网格文件。在下面的代码中,我尝试了两种方法:FuncAnimation, 用于animate_plot()and 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)
于 2020-02-10T10:22:49.577 回答