Python matplotlib:由几个pyplot.figure-s组成的动画

时间:2014-08-26 09:51:10

标签: animation matplotlib-basemap colorbar shapely descartes

我创建了一个'plotter(x)'函数,它读取pd.DataFrame中的时间序列并返回由两个轴组成的图形(return fig)。一个是pyplot.figure.add_subplot(111),我在其中添加descartes.PolygonPatch(shapely.Polygon(y)) - es。第二个是pyplot.figure.add_axes,其中包含带有自定义色彩映射的颜色条。

我需要第二个功能来制作一部电影,以2 fps的速率显示时间序列中每个时间步的图。我这样做了:

import matplotlib.pyplot as plt
import matplotlib.animation as animation
def video_plotter(rain_series):
    fig = plt.figure()
    ims = []
    for i in (range(len(rain_series.columns)-1)):
        fig = plotter(rain_series[[rain_series.columns[i], rain_series.columns[-1]]])
        ims.append([fig])
    ani = animation.ArtistAnimation(fig, ims, interval=50, blit=True,repeat_delay=1000)
    writer = animation.MencoderFileWriter(fps=2)
    ani.save('demo.mp4',writer=writer,dpi=100)

问题1:我该怎么做才能使这项工作?

我知道一个选项是循环应用我已经拥有的函数创建一系列.png-s的时间序列,然后直接在unix终端中使用mencoder来创建.avi。然而,颜色条和被映射的形状多边形的大多数值不随时间变化,并且每次需要绘制时消耗大量计算。另外,我需要添加一个不会改变的mpl_toolkits.basemap.Basemap。这使得'.png-series'方法不方便。我也不能使用sys导入:我需要在Python中做所有事情。

我需要在matplotlib.animation中使用blit=True来避免重绘特征,如果它们在先前帧中是相同的。它是否也适用于底图?

问题2:如何在视频中集成静态底图?

1 个答案:

答案 0 :(得分:4)

您似乎必须以不同方式安排代码才能使其正常工作。动画代码的总体布局由两部分组成:

<强> 1。创建情节的静态内容

在此步骤中,您将创建图形,添加子图,绘制所有静态内容(例如底图),并且通常添加第一个数据集或一些兼容的虚拟数据。

<强> 2。更新每个框架

对于每个动画帧,您通常只需更新动态数据而无需创建任何新对象。如果您有图像,则可以使用imobj = ax.imshow(img)在步骤1中创建图像。在此更新步骤中,您不会创建新图像,只需按imobj.set_array(newdata)更新图像数据。 (这就是说,可以创建新对象,但您需要记住删除不需要的对象。)

当然,这不仅限于图像,yuo可能会改变绘制的线条,曲面,补丁等背后的数据。

Blitting与此没有任何关系,只是为了让事情更快(并且不适用于所有后端)。如果你不需要实时显示动画,那么关闭blitting可能会更安全。


我的建议是,在考虑上述情况后重写plotter

仅举例说明如何制作动画:

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

# update the data for each frame
def anim(n):
    global data

    # get some new data
    data += np.random.random((100,100)) - .5
    # update the data into the image
    imobj.set_array(data)

    # returns a list of drawables which have been changed (needed for blitting)
    return imobj,

# create the figure
fig = plt.figure()
ax = fig.add_subplot(111)

# plot a static image
x = np.linspace(0, 2*np.pi, 200)
ax.plot(x, np.sin(x), 'r', lw=2)

# some data
data = np.random.random((100,100)) - .5

# create the image on top
imobj = ax.imshow(data, extent=[0,2*np.pi, -1.2, 1.2], origin='lower', cmap=plt.cm.gray, vmin=-2, vmax=2, alpha=.7, zorder=10)

# create the animation
ani = matplotlib.animation.FuncAnimation(fig, anim, frames=100)
ani.save("/tmp/test.mp4", fps=10, codec="libx264", extra_args=['-pix_fmt', 'yuv420p'])

这会产生一个动画,其中前景中的半透明图像会发生变化,后面会出现静态图像。 (如果您在尝试时遇到问题,可以将codecextra_args关键字保留,因为他们需要您安装libx264。)

电影的最后一帧:

enter image description here