matplotlib imshow,ArtistAnimation和class属性

时间:2014-03-22 23:59:31

标签: python animation matplotlib

我正在尝试使用Python编写Conway的生活游戏并展示其演变。我无法显示输出。我在下面粘贴了我的全部代码。

我使用此示例作为基础:from the matplotlib doc。我的动画是静态的,但如果我使用

ims.append([plt.imshow(world.state+0, cmap=plt.cm.binary, interpolation='nearest')])

它动画正确。我试着编写一个函数wolrd.get_state(),认为这是某种评估问题,无济于事。

这让我疯了,我在这里失踪了什么?

由于

    import numpy as np
    from scipy.signal import convolve2d

    import matplotlib.pyplot as plt
    import matplotlib.animation as animation


    class World():
       """world information"""

       def __init__(self, grid):
           # noinspection PyNoneFunctionAssignment
           self.state = np.empty(grid.shape)
           self.__x_size = len(grid[0, :])
           self.__y_size = len(grid[:, 0])
           self.__x = range(self.__x_size)
           self.__y = range(self.__y_size)
           for i in self.__x:
            for j in self.__y:
                self.state[i, j] = grid[i, j]

    def evolve(self):
        alive_neighbours = convolve2d(self.state, np.ones((3, 3)), mode='same', boundary='wrap') - self.state
        for i in self.__y:
            for j in self.__x:
                if alive_neighbours[i, j] < 2:
                    self.state[i, j] = 0
                elif alive_neighbours[i, j] == 3:
                    self.state[i, j] = 1
                elif alive_neighbours[i, j] > 3:
                    self.state[i, j] = 0
        # self.state = np.random.randint(2, size=(self.__x_size, self.__y_size ))


if __name__ == "__main__":
    nbx = 5
    nby = 5
    nb_gen = 5

    initial_seed = np.random.randint(2, size=(nbx, nby))
    world = World(initial_seed)

    ims = []
    fig = plt.figure()

    for i in range(nb_gen):
        ims.append([plt.imshow(world.state, cmap=plt.cm.binary, interpolation='nearest')])
        world.evolve()

    ani = animation.ArtistAnimation(fig, ims, interval=500, blit=True, repeat_delay=1000)

    plt.show()

注意: 我成功地使用了:

def animate(i):
    world.evolve()
    return (plt.imshow(world.state, cmap=plt.cm.binary, interpolation='nearest'),)

ani = animation.FuncAnimation(fig, animate, frames=nb_gen, interval=500, blit=True, repeat_delay=1000)

但这不是我想要的。

1 个答案:

答案 0 :(得分:4)

动画的每一帧都显示相同的世界状态。

由于世界类仅修改状态,因此对每个帧都会将对相同对象的引用传递给imshow()。动画的每个帧都引用相同的数组。

Matplotlib在调用plt.show()之前不会将动画绘制到屏幕上,因此只能看到传递给imshow()的数组的最终版本,这是World.state的最终版本

这与

相同
a = [1, 2, 3]
b = a
a.append(4)
print(b)

输出[1,2,3,4]。 b指向a,所以当更改时,b会发生变化。

复制要显示的图像可以解决问题。

ims.append([plt.imshow(world.state.copy(), cmap=plt.cm.binary, interpolation='nearest')])

这也是world.state + 0和np.random.randint(2,size =(self .__ x_size,self .__ y_size))工作的原因:它们都创建了新数组,并且不修改数组已经传入imshow()。