动画在for循环中生成的多个图形



我有一个来自库的绘图函数,它接受一个数组并从中生成一个热图(我将使用plt。(为了MWE的缘故,这里不展示)。函数不返回任何东西:它只调用plt.show():

import matplotlib.pyplot as plt
import numpy as np
# Complicated function from a library which I technically could but should not modify
# simplified for MWE
def heatmap(arr):
fig, ax = plt.subplots()
_ = ax.imshow(arr)
fig.show()

如果我在循环中调用这个函数,那么我将得到多个数字。

for i in range(100):
arr = np.random.rand(10,10)
heatmap(arr)

我想把这些数字收集起来,最后做成动画,像:

plots = []
for i in range(100):
arr = np.random.rand(10,10)
heatmap(arr)
plots.append(plt.gca())  # what should this actually look like?
# wish this existed
plt.animate(plots) # ???

我确实可以访问heatmap的代码,因此我可以在技术上更改它以返回图形和轴,但我想找到一个简单的解决方案,即使我无法访问绘图代码也可以工作。

这是可能的matplotlib吗?我在文档中看到的所有示例都建议我必须更新数字,而不是收集许多不同的数字。

根据这些评论,我找到了一个有效的解决方案来收集在循环中生成的绘图,而无需访问绘图函数,并将它们保存到动画中。

我最初使用的循环如下:

for i in range(100):
arr = np.random.rand(10,10)
heatmap(arr)

我将首先给出解决方案,然后一步一步地解释逻辑。

最终解决方案
plots = []
for i in range(100):
arr = np.random.rand(10,10)
heatmap(arr)
if i==0:
fig, ax = plt.gcf(), plt.gca()
else:
dummy_fig, ax = plt.gcf(), plt.gca()
ax.set(animated=True)
ax.remove()
ax.figure = fig
fig.add_axes(ax)
plt.close(dummy_fig)

plots.append([ax])
ani = animation.ArtistAnimation(fig, plots, interval=50, repeat_delay=200)
ani.save("video.mp4")

逐步渐进的解释为了保存这些情节并为以后制作动画,我必须做以下修改:

  1. 获取在图形中生成的图形和轴的句柄:
for i in range(100):
arr = np.random.rand(10,10)
heatmap(arr)
fig, ax = plt.gcf(), plt.gca()  # add this
  1. 使用第一个图形作为所有未来轴的绘图画布:
for i in range(100):
arr = np.random.rand(10,10)
heatmap(arr)
if i==0:  # fig is the one we'll use for our animation canvas.
fig, ax = plt.gcf(), plt.gca()
else:
dummy_fig, ax = plt.gcf(), plt.gca()  # we will ignore dummy_fig
plt.close(dummy_fig)
  1. 在关闭其他图形之前,将它们的轴移动到我们的主画布
for i in range(100):
arr = np.random.rand(10,10)
heatmap(arr)
if i==0:
fig, ax = plt.gcf(), plt.gca()
else:
dummy_fig, ax = plt.gcf(), plt.gca()
ax.remove()  # remove ax from dummy_fig
ax.figure = fig  # now assign it to our canvas fig
fig.add_axes(ax)  # also patch the fig axes to know about it
plt.close(dummy_fig)
  1. 设置轴为动画(似乎不是严格必要的)
for i in range(100):
arr = np.random.rand(10,10)
heatmap(arr)
if i==0:
fig, ax = plt.gcf(), plt.gca()
else:
dummy_fig, ax = plt.gcf(), plt.gca()
ax.set(animated=True)  # from plt example, but doesn't seem needed
# we could however add info to each plot here, e.g.
# ax.set(xlabel=f"image {i}")  # this could be done in i ==0 cond. too.
ax.remove()
ax.figure = fig 
fig.add_axes(ax)
plt.close(dummy_fig)
  1. 现在简单地收集所有这些轴在一个列表中,并绘制它们。
plots = []
for i in range(100):
arr = np.random.rand(10,10)
heatmap(arr)
if i==0:
fig, ax = plt.gcf(), plt.gca()
else:
dummy_fig, ax = plt.gcf(), plt.gca()
ax.set(animated=True)
ax.remove()
ax.figure = fig
fig.add_axes(ax)
plt.close(dummy_fig)

plots.append([ax])
ani = animation.ArtistAnimation(fig, plots, interval=50, repeat_delay=200)
ani.save("video.mp4")

最新更新