matplotlib 问题 Func.Animation
Issues with matplotlib Func.Animation
我正在尝试使用 matplotlib 制作一些动画(具体来说是 Conways game of life),但 .FuncAnimation
有一些问题
我找出了部分有效(但不是我想要的方式)或导致不同错误的不同情况。我想了解错误并制定出正确的代码版本。感谢您的帮助!
通过 .FuncAnimation 调用的函数 gameoflife
使用变量 w, h, grid
来更新图像。
完整的注释代码见下文。
案例 1:全局变量
如果我使用全局变量一切正常。
在通过 anim = animation.FuncAnimation(fig, gameoflife)
调用 gameoflife(self)
之前,我定义了 w, h, grid
全局
在gameoflife(self)
中我也将w, h, grid
定义为全局变量
w, h, grid = "something"
def gameoflife(self):
global w
global h
global grid
.
.
.
img = ax.imshow(grid)
return img
fig, ax = plt.subplots()
plt.axis('off')
img = ax.imshow(grid)
anim = animation.FuncAnimation(fig, gameoflife)
plt.show()
如前所述,这会产生所需的动画效果。但我想摆脱全局变量,因此我尝试了其他方法:
案例 2:传递对象
我没有在 gameoflife
中将 w, h, grid
定义为全局变量,而是用 anim = animation.FuncAniation(fig, gameoflife(w,h,grid))
传递了它们。
(我知道 w, h, grid
在我的示例中仍然是全局的。我在另一个版本上工作,但由于错误是相同的,我认为这个简单版本应该这样做。)
这会导致以下错误:
TypeError: 'AxesImage' object is not callable
我不明白这个错误,因为我没有在代码更改时调用 ax。
w, h, grid = "something"
def gameoflife(w, h, grid):
.
.
.
img = ax.imshow(grid)
return img
fig, ax = plt.subplots()
plt.axis('off')
img = ax.imshow(grid)
anim = animation.FuncAnimation(fig, gameoflife(w,h,grid))
plt.show()
案例 3:使用 fargs
传递对象
在第三种情况下,我尝试使用 .FuncAnimation 的“frags”参数传递 w, h, grid
,从而只生成第一帧。 (或者前两个,看你怎么看。“第一个”框架是通过img = ax.imshow(grid)
准确绘制的)
w, h, grid = "something"
def gameoflife(self, w, h, grid):
.
.
.
img = ax.imshow(grid)
return img
fig, ax = plt.subplots()
plt.axis('off')
img = ax.imshow(grid)
anim = animation.FuncAnimation(fig, gameoflife, fargs=(w,h,grid))
plt.show()
完整代码
希望评论得当 ;)
有两个部分(开始和结束),您可以在其中 comment/uncomment 部分来生成相应的案例。默认情况下是案例 1。
import random
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
##defining grid size
w= 20
h = 20
##generating random grid
grid = np.array([[random.randint(0,1) for x in range(w)] for y in range(h)])
######
# Choose for diffrent cases
######
##Case 1: Global Variables
def gameoflife(self):
global w
global h
global grid
##Case 2: Passing Objects
#def gameoflife(w, h, grid):
##Case 3: Passing Objects with fargs
#def gameoflife(self, w, h, grid):
####### Choose part over
# wt, ht as test values for position
# x,y to set calculation position
wt = w-1
ht = h-1
x,y = -1,0 #results in 0,0 for the first postion
# defining grid for calculation (calgrid)
calgrid = np.array([[0 for x in range(w)] for y in range(h)])
# testing for last position
while y<ht or x<wt:
# moving position through the grid
if x == wt:
y +=1
x = 0
else:
x += 1
#sorrounding cells check value
scv = 0
#counting living cells around position x,y
#if-else for exeptions at last column and row
if y == ht:
if x == wt:
scv = grid[x-1][y-1] + grid[x][y-1] + grid[0][y-1] + grid[x-1][y] + grid[0][y] + grid[x-1][0] + grid[x][0] + grid[0][0]
else:
scv = grid[x-1][y-1] + grid[x][y-1] + grid[x+1][y-1] + grid[x-1][y] + grid[x+1][y] + grid[x-1][0] + grid[x][0] + grid[x+1][0]
else:
if x == wt:
scv = grid[x-1][y-1] + grid[x][y-1] + grid[0][y-1] + grid[x-1][y] + grid[0][y] + grid[x-1][y+1] + grid[x][y+1] + grid[0][y+1]
else:
scv = grid[x-1][y-1] + grid[x][y-1] + grid[x+1][y-1] + grid[x-1][y] + grid[x+1][y] + grid[x-1][y+1] + grid[x][y+1] + grid[x+1][y+1]
# test cell to condidions and write result in calgrid
if grid[x][y] == 0:
if scv == 3:
calgrid [x][y] = 1
else :
if 1<scv<4:
calgrid [x][y] = 1
# updating grid, generating img and return it
grid = calgrid
img = ax.imshow(grid)
return img
fig, ax = plt.subplots()
plt.axis('off')
img = ax.imshow(grid) #generates "first" Frame from seed
#####
# Choose vor Case
#####
## Case 1: Global Variables
anim = animation.FuncAnimation(fig, gameoflife)
## Case 2: Passing Variables
#anim = anim = animation.FuncAnimation(fig, gameoflife(w,h,grid))
## Case 3: Passing Variables with fargs
#anim = animation.FuncAnimation(fig, gameoflife, fargs=(w,h,grid))
####### Choose part over
plt.show()
坦克寻求帮助和一切
你好托拜厄斯
情况 2:调用函数并将结果传递给 FuncAnimation。
def gameoflife(w,h,grid):
# ...
return ax.imshow(grid)
anim = animation.FuncAnimation(fig, gameoflife(w,h,grid))
与
基本相同
anim = animation.FuncAnimation(fig, ax.imshow(grid))
这将不起作用,因为第二个参数应该是一个函数,而不是函数的 return(在本例中是图像)。
为了更好地解释这一点,考虑一个简单的测试用例。 g
是一个函数,需要一个函数作为输入。它将 return 在 4
计算的函数。如果你提供一个函数 f
,一切都按预期工作,但是如果你提供一个函数的 return,如果 return 本身不是一个函数,它就会失败,这可以被评估.
def f(x):
return 3*x
def g(func):
return func(4)
g(f) # works as expected
g(f(2)) # throws TypeError: 'int' object is not callable
情况 3:您使用相同的参数重复调用该函数
在
的情况下
anim = animation.FuncAnimation(fig, gameoflife, fargs=(w,h,grid))
您为动画中的每一帧使用相同的初始参数 w,h,grid
调用函数 gameoflife。因此你得到一个静态动画(情节是动画的,但每一帧都是相同的,因为使用了相同的参数)。
结论。继续案例 1
因为案例1很好用,不知道为什么不用。一种更优雅的方法是使用 class 并使用 class 变量,例如在 .
我正在尝试使用 matplotlib 制作一些动画(具体来说是 Conways game of life),但 .FuncAnimation
有一些问题我找出了部分有效(但不是我想要的方式)或导致不同错误的不同情况。我想了解错误并制定出正确的代码版本。感谢您的帮助!
通过 .FuncAnimation 调用的函数 gameoflife
使用变量 w, h, grid
来更新图像。
完整的注释代码见下文。
案例 1:全局变量
如果我使用全局变量一切正常。
在通过 anim = animation.FuncAnimation(fig, gameoflife)
gameoflife(self)
之前,我定义了 w, h, grid
全局
在gameoflife(self)
中我也将w, h, grid
定义为全局变量
w, h, grid = "something"
def gameoflife(self):
global w
global h
global grid
.
.
.
img = ax.imshow(grid)
return img
fig, ax = plt.subplots()
plt.axis('off')
img = ax.imshow(grid)
anim = animation.FuncAnimation(fig, gameoflife)
plt.show()
如前所述,这会产生所需的动画效果。但我想摆脱全局变量,因此我尝试了其他方法:
案例 2:传递对象
我没有在 gameoflife
中将 w, h, grid
定义为全局变量,而是用 anim = animation.FuncAniation(fig, gameoflife(w,h,grid))
传递了它们。
(我知道 w, h, grid
在我的示例中仍然是全局的。我在另一个版本上工作,但由于错误是相同的,我认为这个简单版本应该这样做。)
这会导致以下错误:
TypeError: 'AxesImage' object is not callable
我不明白这个错误,因为我没有在代码更改时调用 ax。
w, h, grid = "something"
def gameoflife(w, h, grid):
.
.
.
img = ax.imshow(grid)
return img
fig, ax = plt.subplots()
plt.axis('off')
img = ax.imshow(grid)
anim = animation.FuncAnimation(fig, gameoflife(w,h,grid))
plt.show()
案例 3:使用 fargs
传递对象
在第三种情况下,我尝试使用 .FuncAnimation 的“frags”参数传递 w, h, grid
,从而只生成第一帧。 (或者前两个,看你怎么看。“第一个”框架是通过img = ax.imshow(grid)
准确绘制的)
w, h, grid = "something"
def gameoflife(self, w, h, grid):
.
.
.
img = ax.imshow(grid)
return img
fig, ax = plt.subplots()
plt.axis('off')
img = ax.imshow(grid)
anim = animation.FuncAnimation(fig, gameoflife, fargs=(w,h,grid))
plt.show()
完整代码
希望评论得当 ;)
有两个部分(开始和结束),您可以在其中 comment/uncomment 部分来生成相应的案例。默认情况下是案例 1。
import random
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
##defining grid size
w= 20
h = 20
##generating random grid
grid = np.array([[random.randint(0,1) for x in range(w)] for y in range(h)])
######
# Choose for diffrent cases
######
##Case 1: Global Variables
def gameoflife(self):
global w
global h
global grid
##Case 2: Passing Objects
#def gameoflife(w, h, grid):
##Case 3: Passing Objects with fargs
#def gameoflife(self, w, h, grid):
####### Choose part over
# wt, ht as test values for position
# x,y to set calculation position
wt = w-1
ht = h-1
x,y = -1,0 #results in 0,0 for the first postion
# defining grid for calculation (calgrid)
calgrid = np.array([[0 for x in range(w)] for y in range(h)])
# testing for last position
while y<ht or x<wt:
# moving position through the grid
if x == wt:
y +=1
x = 0
else:
x += 1
#sorrounding cells check value
scv = 0
#counting living cells around position x,y
#if-else for exeptions at last column and row
if y == ht:
if x == wt:
scv = grid[x-1][y-1] + grid[x][y-1] + grid[0][y-1] + grid[x-1][y] + grid[0][y] + grid[x-1][0] + grid[x][0] + grid[0][0]
else:
scv = grid[x-1][y-1] + grid[x][y-1] + grid[x+1][y-1] + grid[x-1][y] + grid[x+1][y] + grid[x-1][0] + grid[x][0] + grid[x+1][0]
else:
if x == wt:
scv = grid[x-1][y-1] + grid[x][y-1] + grid[0][y-1] + grid[x-1][y] + grid[0][y] + grid[x-1][y+1] + grid[x][y+1] + grid[0][y+1]
else:
scv = grid[x-1][y-1] + grid[x][y-1] + grid[x+1][y-1] + grid[x-1][y] + grid[x+1][y] + grid[x-1][y+1] + grid[x][y+1] + grid[x+1][y+1]
# test cell to condidions and write result in calgrid
if grid[x][y] == 0:
if scv == 3:
calgrid [x][y] = 1
else :
if 1<scv<4:
calgrid [x][y] = 1
# updating grid, generating img and return it
grid = calgrid
img = ax.imshow(grid)
return img
fig, ax = plt.subplots()
plt.axis('off')
img = ax.imshow(grid) #generates "first" Frame from seed
#####
# Choose vor Case
#####
## Case 1: Global Variables
anim = animation.FuncAnimation(fig, gameoflife)
## Case 2: Passing Variables
#anim = anim = animation.FuncAnimation(fig, gameoflife(w,h,grid))
## Case 3: Passing Variables with fargs
#anim = animation.FuncAnimation(fig, gameoflife, fargs=(w,h,grid))
####### Choose part over
plt.show()
坦克寻求帮助和一切
你好托拜厄斯
情况 2:调用函数并将结果传递给 FuncAnimation。
def gameoflife(w,h,grid):
# ...
return ax.imshow(grid)
anim = animation.FuncAnimation(fig, gameoflife(w,h,grid))
与
基本相同anim = animation.FuncAnimation(fig, ax.imshow(grid))
这将不起作用,因为第二个参数应该是一个函数,而不是函数的 return(在本例中是图像)。
为了更好地解释这一点,考虑一个简单的测试用例。 g
是一个函数,需要一个函数作为输入。它将 return 在 4
计算的函数。如果你提供一个函数 f
,一切都按预期工作,但是如果你提供一个函数的 return,如果 return 本身不是一个函数,它就会失败,这可以被评估.
def f(x):
return 3*x
def g(func):
return func(4)
g(f) # works as expected
g(f(2)) # throws TypeError: 'int' object is not callable
情况 3:您使用相同的参数重复调用该函数
在
的情况下anim = animation.FuncAnimation(fig, gameoflife, fargs=(w,h,grid))
您为动画中的每一帧使用相同的初始参数 w,h,grid
调用函数 gameoflife。因此你得到一个静态动画(情节是动画的,但每一帧都是相同的,因为使用了相同的参数)。
结论。继续案例 1
因为案例1很好用,不知道为什么不用。一种更优雅的方法是使用 class 并使用 class 变量,例如在