gpt4 book ai didi

python - Matplotlib : How to save an animation after clicking on the button that launches the animation?

转载 作者:太空宇宙 更新时间:2023-11-03 14:59:04 33 4
gpt4 key购买 nike

我制作了一个小森林火灾动画。我的代码在问题的末尾。

代码forestfire.py包含将火蔓延到所有森林的函数。然后 forestfire_test.py import forestfire.py as ff 从那里我可以用我的鼠标单击 matplotlib 显示的数组。

在我提出问题之前,这里有一些信息:

  • 没有树:森林[i,j] = 0
  • 一棵树:森林[i,j] = 1
  • 一棵着火的树:forest[i,j] = 2
  • 哈希值:forest[i,j] = 3

基本上,forest 是由 1 到 0 之间的数字组成的大小为 n x m 的二维数组。函数 onclick 点燃了森林,而当森林仍然有树木着火时,函数spreadfire将火势蔓延。

使用函数onclick,我可以让森林着火(如果我点击数组,树木将变成红色),使用函数start,我可以执行代码感谢按钮开始

现在的问题是,我第一次执行代码时,它不知道 ani 是什么(NameError: global name 'ani' is not Defined) - 这是正常的,因为我调用动画在我调用函数 start 之前,ani(通过尝试保存它)。但是,如果我尝试在函数 start 中保存 ani ,我会得到一个空白图 - 这也是正常的。

总而言之,我需要在调用函数 start 后保存动画,但无法在函数 start 结束时保存它,否则我会得到一个空白的情节。有人可以告诉我我应该做什么吗?

PS:我使用 Spyder 和 IPython 控制台,如果我的解释不够清楚,请告诉我。

forestfire_test.py

import forestfire as ff
import numpy as np

import matplotlib.pylab as plt
import matplotlib.colors as mcolors
from matplotlib import cm

from matplotlib.widgets import Button, Cursor


global forest
forest = np.random.rand(100,100)


# Colormap
greens = cm.Greens(np.linspace(0,1, num=50))
greensfill = cm.Greens(np.ones(25))
red = [(1,0,0,1)]*len(greens)
gray = [(.5,.5,.5,1)]*len(greens)

colors = np.vstack((greens, greensfill, red, gray))
mycmap = mcolors.LinearSegmentedColormap.from_list('my_colormap', colors)

# Figure
fig, ax = plt.subplots(figsize=(10,5))
fig.subplots_adjust(right=1.3)
im = ax.imshow(forest, animated=True, cmap = mycmap, interpolation="none", origin='lower', vmin=0, vmax=3.5)


ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.tick_params(direction='out')


cursor = Cursor(ax, useblit=True, color='red', linewidth=1)
plt.show()


# Coordinates
def onclick(event):
x, y = int(event.xdata), int(event.ydata)
forest[y,x] = 2.
im.set_data(forest)
fig.canvas.draw_idle()


fig.canvas.mpl_connect('button_press_event', onclick)


# Start button
def start(event):
global ani
ani = ff.forestfire(forest)

button_ax = plt.axes([0.15, 0.45, 0.2, 0.1])
button = Button(button_ax, 'Start', color='lightgrey', hovercolor='grey')
button.on_clicked(start)


# Animation
ani.save("forestfire_test.mp4", writer = 'ffmpeg', fps=5, dpi=500)

forestfire.py

from random import random

import numpy as np
from numpy.random import choice

import matplotlib.pylab as plt
import matplotlib.colors as mcolors
from matplotlib import cm

import matplotlib.animation as animation



def hazard(p):
r=random()
assert p>=0 and p<=1
return r <= p


def chg(case):
if case > 1.:
return 1.
else:
return case


def spreadfire(forest):

n,m=forest.shape
c = np.copy(forest)

L = xrange(3)

for i in xrange(n):
for j in xrange(m):

if c[i,j] == 2.:

sautX, sautY = choice([0,1,40],p=[0.4999,0.4999,0.0002]), choice([0,1,40],p=[0.4999,0.4999,0.0002])
Y, X = xrange(max(0,i-1-sautY),min(n,i+2+sautY),sautY+1), xrange(max(0,j-1-sautX),min(m,j+2+sautX),sautX+1)

for y1,y2 in zip(Y,L):
for x1,x2 in zip(X,L):

if hazard(chg(c[y1,x1])):
forest[y1,x1] = 2.

return forest


def forestfire(forest):

fig, ax = plt.subplots()

movie, hashes = [], []

# Colormap
greens = cm.Greens(np.linspace(0,1, num=50))
greensfill = cm.Greens(np.ones(25))
red = [(1,0,0,1)]*len(greens)
gray = [(.5,.5,.5,1)]*len(greens)

colors = np.vstack((greens, greensfill, red, gray))
mycmap = mcolors.LinearSegmentedColormap.from_list('my_colormap', colors)

# Initialization
k = 0
firefront = 5


forest = spreadfire(forest)

c = np.copy(forest)
c[np.where(c==2.)] = 3.
hashes.append(c)

im = plt.imshow(forest, animated=True, cmap = mycmap, interpolation="none", origin='lower', vmin=0, vmax=3.5)
movie.append([im])

# Fire propagation
while np.count_nonzero(forest == 2.) != 0:
k += 1
print k

if k < firefront:

forest = spreadfire(forest)

c = np.copy(forest)
c[np.where(c==2.)] = 3.
hashes.append(c)

im = plt.imshow(forest, animated=True, cmap = mycmap, interpolation="none", origin='lower', vmin=0, vmax=3.5)
movie.append([im])

else:
forest = spreadfire(forest)

c = np.copy(forest)
c[np.where(c==2.)] = 3.
hashes.append(c)

forest[np.where(hashes[0]==3.)] = 3.
im = plt.imshow(forest, animated=True, cmap = mycmap, interpolation="none", origin='lower', vmin=0, vmax=3.5)
movie.append([im])
hashes.remove(hashes[0])

return animation.ArtistAnimation(fig, movie, blit=True, repeat_delay=100)

最佳答案

正如评论中提到的,这里有两个问题:

  1. 您需要将 ani.save 移至启动函数内。这是因为 ani 仅在按下开始按钮后才会定义。
  2. plt.show 只能在脚本末尾调用。

这对我来说工作得很好,作为脚本运行(在 python 2.7.10,matplotlib 2.0.2 上),因为单击开始按钮后,动画将作为 mp4 文件保存到当前目录。

除此之外,我需要将帧速率设置为 6 或以上,如 previous question 中所述。 .

关于python - Matplotlib : How to save an animation after clicking on the button that launches the animation?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45270207/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com