Skip to content

Commit 4177725

Browse files
authored
Merge pull request #7589 from tacaswell/doc_animation
Doc animation
2 parents 1a21bea + 4c4779b commit 4177725

File tree

2 files changed

+646
-130
lines changed

2 files changed

+646
-130
lines changed

doc/api/animation_api.rst

+329-9
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,332 @@
1-
*********
2-
animation
3-
*********
1+
======================
2+
``animation`` module
3+
======================
44

5+
.. automodule:: matplotlib.animation
56

6-
:mod:`matplotlib.animation`
7-
===========================
7+
.. contents:: Table of Contents
8+
:depth: 1
9+
:local:
10+
:backlinks: entry
811

9-
.. automodule:: matplotlib.animation
10-
:members:
11-
:undoc-members:
12-
:show-inheritance:
12+
13+
Animation
14+
=========
15+
16+
The easiest way to make a live animation in matplotlib is to use one of the
17+
`Animation` classes.
18+
19+
.. autosummary::
20+
:toctree: _as_gen
21+
:nosignatures:
22+
23+
FuncAnimation
24+
ArtistAnimation
25+
26+
In both cases it is critical to keep a reference to the instance
27+
object. The animation is advanced by a timer (typically from the host
28+
GUI framework) which the `Animation` object holds the only reference
29+
to. If you do not hold a reference to the `Animation` object, it (and
30+
hence the timers), will be garbage collected which will stop the
31+
animation.
32+
33+
To save an animation to disk use
34+
35+
.. autosummary::
36+
:toctree: _as_gen
37+
:nosignatures:
38+
39+
Animation.save
40+
Animation.to_html5_video
41+
42+
See :ref:`ani_writer_classes` below for details about what movie formats are supported.
43+
44+
45+
``FuncAnimation``
46+
-----------------
47+
48+
The inner workings of `FuncAnimation` is more-or-less::
49+
50+
for d in frames:
51+
artists = func(d, *fargs)
52+
fig.canvas.draw_idle()
53+
plt.pause(interval)
54+
55+
56+
with details to handle 'blitting' (to dramatically improve the live
57+
performance), to be non-blocking, handle repeats, multiple animated
58+
axes, and easily save the animation to a movie file.
59+
60+
'Blitting' is a `old technique
61+
<https://en.wikipedia.org/wiki/Bit_blit>`__ in computer graphics. The
62+
general gist is to take an existing bit map (in our case a mostly
63+
rasterized figure) and then 'blit' one more artist on top. Thus, by
64+
managing a saved 'clean' bitmap, we can only re-draw the few artists
65+
that are changing at each frame and possibly save significant amounts of
66+
time. When using blitting (by passing ``blit=True``) the core loop of
67+
`FuncAnimation` gets a bit more complicated ::
68+
69+
ax = fig.gca()
70+
71+
def update_blit(artists):
72+
fig.canvas.restore_region(bg_cache)
73+
for a in artists:
74+
a.axes.draw_artist(a)
75+
76+
ax.figure.canvas.blit(ax.bbox)
77+
78+
artists = init_func()
79+
80+
for a in artists:
81+
a.set_animated(True)
82+
83+
fig.canvas.draw()
84+
bg_cache = fig.canvas.copy_from_bbox(ax.bbox)
85+
86+
for f in frames:
87+
artists = func(f, *fargs)
88+
update_blit(artists)
89+
plt.pause(interval)
90+
91+
This is of course leaving out many details (such as updating the
92+
background when the figure is resized or fully re-drawn). However,
93+
this hopefully minimalist example gives a sense of how ``init_func``
94+
and ``func`` are used inside of `FuncAnimation` and the theory of how
95+
'blitting' works.
96+
97+
The expected signature on ``func`` and ``init_func`` is very simple to
98+
keep `FuncAnimation` out of your book keeping and plotting logic, but
99+
this means that the callable objects you pass in must know what
100+
artists they should be working on. There are several approaches to
101+
handling this, of varying complexity and encapsulation. The simplest
102+
approach, which works quite well in the case of a script, is to define the
103+
artist at a global scope and let Python sort things out. For example ::
104+
105+
import numpy as np
106+
import matplotlib.pyplot as plt
107+
from matplotlib.animation import FuncAnimation
108+
109+
fig, ax = plt.subplots()
110+
xdata, ydata = [], []
111+
ln, = plt.plot([], [], 'ro', animated=True)
112+
113+
def init():
114+
ax.set_xlim(0, 2*np.pi)
115+
ax.set_ylim(-1, 1)
116+
return ln,
117+
118+
def update(frame):
119+
xdata.append(frame)
120+
ydata.append(np.sin(frame))
121+
ln.set_data(xdata, ydata)
122+
return ln,
123+
124+
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
125+
init_func=init, blit=True)
126+
plt.show()
127+
128+
129+
The second method is to us `functools.partial` to 'bind' artists to
130+
function. A third method is to use closures to build up the required
131+
artists and functions. A fourth method is to create a class.
132+
133+
134+
135+
136+
Examples
137+
~~~~~~~~
138+
139+
.. toctree::
140+
:maxdepth: 1
141+
142+
../examples/animation/animate_decay
143+
../examples/animation/bayes_update
144+
../examples/animation/double_pendulum_animated
145+
../examples/animation/dynamic_image
146+
../examples/animation/histogram
147+
../examples/animation/rain
148+
../examples/animation/random_data
149+
../examples/animation/simple_3danim
150+
../examples/animation/simple_anim
151+
../examples/animation/strip_chart_demo
152+
../examples/animation/unchained
153+
154+
``ArtistAnimation``
155+
-------------------
156+
157+
158+
Examples
159+
~~~~~~~~
160+
161+
.. toctree::
162+
:maxdepth: 1
163+
164+
../examples/animation/basic_example
165+
../examples/animation/basic_example_writer
166+
../examples/animation/dynamic_image2
167+
168+
169+
170+
171+
Writer Classes
172+
==============
173+
174+
175+
176+
The provided writers fall into two broad categories: pipe-based and
177+
file-based. The pipe-based writers stream the captured frames over a
178+
pipe to an external process. The pipe-based variants tend to be more
179+
performant, but may not work on all systems.
180+
181+
.. autosummary::
182+
:toctree: _as_gen
183+
:nosignatures:
184+
185+
186+
FFMpegWriter
187+
ImageMagickFileWriter
188+
AVConvWriter
189+
190+
Alternatively the file-based writers save temporary files for each
191+
frame which are stitched into a single file at the end. Although
192+
slower, these writers can be easier to debug.
193+
194+
.. autosummary::
195+
:toctree: _as_gen
196+
:nosignatures:
197+
198+
FFMpegFileWriter
199+
ImageMagickWriter
200+
AVConvFileWriter
201+
202+
203+
Fundamentally, a `MovieWriter` provides a way to grab sequential frames
204+
from the same underlying `~matplotlib.figure.Figure` object. The base
205+
class `MovieWriter` implements 3 methods and a context manager. The
206+
only difference between the pipe-based and file-based writers is in the
207+
arguments to their respective ``setup`` methods.
208+
209+
210+
.. autosummary::
211+
:toctree: _as_gen
212+
:nosignatures:
213+
214+
MovieWriter.setup
215+
FileMovieWriter.setup
216+
MovieWriter.grab_frame
217+
MovieWriter.finish
218+
MovieWriter.saving
219+
220+
221+
The ``setup()`` method is used to prepare the writer (possibly opening
222+
a pipe), successive calls to ``grab_frame()`` capture a single frame
223+
at a time and ``finish()`` finalizes the movie and writes the output
224+
file to disk. For example ::
225+
226+
moviewriter = MovieWriter(...)
227+
moviewriter.setup(fig=fig, 'my_movie.ext', dpi=100)
228+
for j in range(n):
229+
update_figure(n)
230+
moviewriter.grab_frame()
231+
moviewriter.finish()
232+
233+
234+
If using the writer classes directly (not through `Animation.save`), it is strongly encouraged
235+
to use the `~MovieWriter.saving` context manager ::
236+
237+
with moviewriter.saving(fig, 'myfile.mp4', dpi=100):
238+
for j in range(n):
239+
update_figure(n)
240+
moviewriter.grab_frame()
241+
242+
243+
to ensures that setup and cleanup are performed as necessary.
244+
245+
246+
:ref:`animation-moviewriter`
247+
248+
249+
.. _ani_writer_classes:
250+
251+
Helper Classes
252+
==============
253+
254+
255+
Animation Base Classes
256+
----------------------
257+
258+
259+
.. autosummary::
260+
:toctree: _as_gen
261+
:nosignatures:
262+
263+
Animation
264+
TimedAnimation
265+
266+
267+
Custom Animation classes
268+
------------------------
269+
270+
:ref:`animation-subplots`
271+
272+
Writer Registry
273+
---------------
274+
275+
A module-level registry is provided to map between the name of the
276+
writer and the class to allow a string to be passed to
277+
`Animation.save` instead of a writer instance.
278+
279+
.. autosummary::
280+
:toctree: _as_gen
281+
:nosignatures:
282+
283+
MovieWriterRegistry
284+
285+
Writer Base Classes
286+
-------------------
287+
288+
To reduce code duplication base classes
289+
290+
.. autosummary::
291+
:toctree: _as_gen
292+
:nosignatures:
293+
294+
MovieWriter
295+
FileMovieWriter
296+
297+
and mixins are provided
298+
299+
.. autosummary::
300+
:toctree: _as_gen
301+
:nosignatures:
302+
303+
AVConvBase
304+
FFMpegBase
305+
ImageMagickBase
306+
307+
See the source code for how to easily implement new `MovieWriter`
308+
classes.
309+
310+
311+
Inheritance Diagrams
312+
====================
313+
314+
.. inheritance-diagram:: matplotlib.animation.FuncAnimation matplotlib.animation.ArtistAnimation
315+
:private-bases:
316+
317+
.. inheritance-diagram:: matplotlib.animation.AVConvFileWriter matplotlib.animation.AVConvWriter matplotlib.animation.FFMpegFileWriter matplotlib.animation.FFMpegWriter matplotlib.animation.ImageMagickFileWriter matplotlib.animation.ImageMagickWriter
318+
:private-bases:
319+
320+
321+
322+
Deprecated
323+
==========
324+
325+
326+
.. autosummary::
327+
:toctree: _as_gen
328+
:nosignatures:
329+
330+
MencoderBase
331+
MencoderFileWriter
332+
MencoderWriter

0 commit comments

Comments
 (0)