如何使用现有的 3D 数组为 python pcolormesh 设置动画,其中第三轴是时间步长?

Posted

技术标签:

【中文标题】如何使用现有的 3D 数组为 python pcolormesh 设置动画,其中第三轴是时间步长?【英文标题】:How can I animate a python pcolormesh using an existing 3D array where the third axis is the time steps? 【发布时间】:2021-12-10 10:18:36 【问题描述】:

我为 2D 扩散方程创建了一个 pcolormesh,创建了一个由 x、y 和 t 组成的 3D 数组。特定 t 的静态 2D 图很简单。如何在所有时间步上为其设置动画?

我使用以下内容创建我的 3D 数组:

set array for x and y
grid_size = 100
t_iter = 1000

D = .01
length = 1.0
tmax = 1.0

dx = dy = length/grid_size
dt = tmax/t_iter

rho = np.zeros((grid_size, grid_size, t_iter))
#rho[:] = 1.2
rho[grid_size//2, grid_size//2, 0] = 1.2  # set the initial configuration

for n in range(t_iter-1):
    for j in range(grid_size-1):
        for i in range(grid_size-1):
            pxx = rho[i+1,j,n] + rho[i-1,j,n] - 2*rho[i,j,n]
            pyy = rho[i,j+1,n] + rho[i,j-1,n] - 2*rho[i,j,n]
            rho[i,j,n+1] = D*dt*(pxx/dx**2+pyy/dy**2)

我可以使用 pcolormesh(没有标签和东西)为特定的 t 值绘制数据:

plt.pcolormesh(rho[:,:,500])

我试过这个,但它没有“动画”任何东西。我错过了什么?

from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()

mesh = ax.pcolormesh(rho[:,:,0])

def animate(i):
    ax.pcolormesh(rho[:,:,i])
    
anim = FuncAnimation(fig, animate, interval=10, frames=t_iter-1, repeat=False)

plt.draw()
plt.show()

【问题讨论】:

【参考方案1】:

出了三件事:

animate() 中,应该更新网格。 mesh.set_array() 设置新值。由于内部数据结构需要一维数组,所以二维数组应该是“raveled”:mesh.set_array(rho[:, :, i].ravel())animate() 应返回已更改元素的列表。 return mesh, 中的尾随逗号是 Python 制作仅包含一个元素的“元组”的方式。 这里最棘手的问题是所有图像最好使用相同的颜色映射。 vmin 告诉哪个值映射到“最低”颜色(默认 viridis 映射中的深紫色),而 vmax 对应于“最高”颜色的值(viridis 中的黄色)。如果它们是明确设置的,matplotlib 会将它们计算为 first 图像的最小值和最大值,在这种情况下为 01.2。这些值不适用于其他图像。通常,整体最小值和最大值给出合适的值。但是,在这种情况下,图像的“有趣”部分的范围要窄得多。我尝试使用第 1 个和第 99 个百分位数,看起来效果不错,但您可能需要调整这些值。

更新后的代码:

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np

grid_size = 100
t_iter = 1000

D = .01
length = 1.0
tmax = 1.0

dx = dy = length / grid_size
dt = tmax / t_iter

rho = np.zeros((grid_size, grid_size, t_iter))
# rho[:] = 1.2
rho[grid_size // 2, grid_size // 2, 0] = 1.2  # set the initial configuration

for n in range(t_iter - 1):
    for j in range(grid_size - 1):
        for i in range(grid_size - 1):
            pxx = rho[i + 1, j, n] + rho[i - 1, j, n] - 2 * rho[i, j, n]
            pyy = rho[i, j + 1, n] + rho[i, j - 1, n] - 2 * rho[i, j, n]
            rho[i, j, n + 1] = D * dt * (pxx / dx ** 2 + pyy / dy ** 2)

fig, ax = plt.subplots()

mesh = ax.pcolormesh(rho[:, :, 0], vmin=np.percentile(rho.ravel(), 1), vmax=np.percentile(rho.ravel(), 99))

def animate(i):
    mesh.set_array(rho[:, :, i].ravel())
    return mesh,

anim = FuncAnimation(fig, animate, interval=10, frames=t_iter, repeat=False)
plt.show()

【讨论】:

感谢您帮助破译动画代码。尽管如此,没有什么是动画的。我得到的只是初始颜色网格的静态框架。 我在 PyCharm 环境中运行它,它确实会产生动画。如果您使用的是 Jupyter,您可能需要像 %matplotlib widget%matplotlib qt 这样的东西来拥有一个非静态的 matplotlib 窗口。 tutorial examples 在您的环境中工作吗? 我正在运行 Jupyter 笔记本环境。更新 conda 包后一切正常。谢谢你。我什至添加了一个颜色条供参考。

以上是关于如何使用现有的 3D 数组为 python pcolormesh 设置动画,其中第三轴是时间步长?的主要内容,如果未能解决你的问题,请参考以下文章

Unity 3D:在现有的Android游戏场景中显示AdMob的横幅

如何将多维数组添加到现有的 Spark DataFrame

在 Unity3d 中,如何将浮动窗口(例如光照贴图)添加到现有的一组选项卡(例如:Inspector)?

使用 Python 创建 3D 数组

如何将数组值插入现有的 JSON 文档?

如何添加AdMob广告到现有的Unity3D ios游戏