在matplotlib中为任何艺术家制作动画的一般方法?

时间:2019-11-14 17:59:42

标签: python matplotlib animation

我最近尝试在matplotlib中为两个不同的艺术家plt.quiver()plt.hist()设置动画,而两次我都遇到相同的问题。显然那些类(我希望我的OOP素养很高)都没有类似set_data的方法。好吧,从技术上讲plt.quiver()确实有set_UVC,但这不适用于Line3D实例,仅适用于Line2D。另外,有一个animating a histogram的示例,但对我来说似乎是种严重的偷工减料。我试图在update()函数中用新值简单地定义我的艺术家,然后返回新艺术家,而不是在update()之外定义艺术家 ,然后更新使用set_data()方法的艺术家。但这只会导致动画中所有帧都保留在图中并重叠。下面是直方图和颤动图的动画。

直方图:

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

"""
evolution of mean values produced by 1000 dice rolls with 
more and more dices, which lead to a narrowing variance
with a growing number of dices.
"""

fig, ax = plt.subplots()

def update(i):

    k = [np.mean(np.random.randint(0,7,i)) for j in range(1000)]
    lol = ax.hist(k,bins=20)

    return lol

ani = FuncAnimation(fig, update, frames=(1,2,10,100,1000))

plt.show()

颤抖:

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation

def rot_z(angle):

    o   = 2*np.pi*(angle/360)

    mat = np.array(((np.cos(o),-np.sin(o),0),
                    (np.sin(o), np.cos(o),0),
                    (    0    ,     0    ,0)))

    return mat

fig = plt.figure()
ax = fig.gca(projection='3d')

ax.set_xlim(-1.5,1.5)
ax.set_ylim(-1.5,1.5)
ax.set_zlim(-1.5,1.5)

def update(frame):

    x,y,z = rot_z(frame).dot(np.array((1,1,1)))

    quiv = ax.quiver(0,
              0, 
              0, 
              x, 
              y, 
              z, 
              length=1)

    return quiv

ani = FuncAnimation(fig, update, frames=np.linspace(0,360,100))
plt.show()

如果运行它们,则可以看到问题。所以我想知道:是不是有一种更简单,抽象的动画艺术家方式,还是我受制于可能不存在的传承人?我已经检查了两个dir(plt.quiver), dir(plt.hist),以查看是否只是在文档中忽略了这些方法,但是动画直方图的示例似乎证实了我的担心。

1 个答案:

答案 0 :(得分:0)

您可以尝试在每次更新时使用ax.clear()清除图像。如果您要扩展抛出的数组而不是在每一帧都从头开始,那么直方图动画也许会更加流畅?

编辑:下面的代码包含一个可重复使用相同样本的测试

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

fig, ax = plt.subplots()
randnums = [np.random.randint(0,7,1000) for j in range(1000)]

def update(i):

    k = [np.mean(randnums[j][:i]) for j in range(1000)]
    ax.clear()
    lol = ax.hist(k,bins=20)

    return lol

ani = FuncAnimation(fig, update, frames=[2**t for t in range(11)])

plt.show()