3
3
Animations using matplotlib
4
4
===========================
5
5
6
- Animations in matplotlib can be created using the `~matplotlib.Animation`
7
- module. This module provides 2 main animation classes -
8
- `~matplotlib.animation.FuncAnimation` and
9
- `~matplotlib.animation.ArtistAnimation`.
6
+ Based on its plotting functionality, matplotlib also provides an interface to
7
+ generate animations using the :class:`~matplotlib.animation` module. An
8
+ animation is a sequence of frames where each frame corresponds to a plot on a
9
+ :class:`~matplotlib.figure.Figure`. This tutorial covers a general guideline on
10
+ how to create such animations and the different options available.
10
11
"""
11
12
12
13
import matplotlib .pyplot as plt
13
14
import matplotlib .animation as animation
14
15
import numpy as np
15
16
16
17
###############################################################################
18
+ # Animation Classes
19
+ # =================
20
+ #
21
+ # The process of animation can be thought about in 2 different ways:
22
+ #
23
+ # 1. Generate data for first frame and then modify this data for each frame to
24
+ # create an animated plot.
25
+ # 2. Generate a list (iterable) of plots (/images) that will each be a frame in
26
+ # the animation.
27
+ #
28
+ # Both of these thought processes can be translated into matplotlib using the
29
+ # :class:`~matplotlib.animation`'s :class:`~matplotlib.animation.FuncAnimation`
30
+ # and :class:`~matplotlib.animation.ArtistAnimation` classes respectively.
31
+ #
17
32
# :class:`~matplotlib.animation.FuncAnimation`
18
33
# --------------------------------------------
34
+ #
35
+ # :class:`~matplotlib.animation.FuncAnimation` class allows us to create an
36
+ # animation by passing a function that iteratively modifies the data of a plot.
37
+ # This is achieved by using the *setter* methods on various
38
+ # :class:`~matplotlib.artist.Artist`
39
+ # (examples: :class:`~matplotlib.line.Line2D`,
40
+ # :class:`~matplotlib.collections.PathCollection`, etc.). A usual
41
+ # :class:`~matplotlib.animation.FuncAnimation` object takes a
42
+ # :class:`~matplotlib.figure.Figure` that we want to animate and a function
43
+ # *func* that modifies the data plotted on the figure. It uses the *frames*
44
+ # parameter to determine the length of the animation. The *interval* parameter
45
+ # is used to determine time in milliseconds between drawing of two frames.
46
+ # (This is different than *fps* in `.animation.save` that we will
47
+ # cover later). We will now look at some examples of using
48
+ # :class:`~matplotlib.animation.FuncAnimation` with different artists.
19
49
20
- # :class:`~matplotlib.animation.FuncAnimation` uses a user-provided function by
21
- # repeatedly calling the function with at a regular *interval*. This allows
22
- # dynamic generation of data by using generators.
23
-
24
-
25
- def init ():
26
- ax .set_ylim (- 1 , 1 )
27
- ax .set_xlim (0 , 10 )
28
- xdata .clear ()
29
- ydata .clear ()
30
- line .set_data (xdata , ydata )
31
- return line ,
50
+ ###############################################################################
51
+ # Animating :class:`~matplotlib.lines.Line2D`
52
+ # ---------------------------------------------------------
53
+ #
54
+ # `.pyplot.plot` returns a :class:`~matplotlib.lines.Line2D` collection. The
55
+ # data on this collection can be modified by using the
56
+ # `.lines.Line2D.set_data` function. Therefore we can use this to modify the
57
+ # plot using the function for every frame.
32
58
33
59
fig , ax = plt .subplots ()
34
- line , = ax . plot ([], [], lw = 2 )
35
- ax . grid ()
60
+ rng = np . random . default_rng ( )
61
+
36
62
xdata , ydata = [], []
63
+ line , = ax .plot (xdata , ydata , c = 'b' )
64
+ ax .grid ()
65
+ ax .set_ylim (- 1 , 1 )
37
66
38
67
39
68
def update (frame ):
@@ -45,17 +74,20 @@ def update(frame):
45
74
ax .set_xlim (xmin , 2 * xmax )
46
75
ax .figure .canvas .draw ()
47
76
line .set_data (xdata , ydata )
48
-
49
77
return line ,
50
78
51
79
ani = animation .FuncAnimation (
52
- fig = fig , func = update , frames = 240 , init_func = init , interval = 30
80
+ fig = fig , func = update , interval = 30
53
81
)
54
82
plt .show ()
55
83
56
84
###############################################################################
57
- # Animating :class:`~matplotlib.lines.PathCollection`
58
- # ---------------------------------------------------
85
+ # Animating :class:`~matplotlib.collections.PathCollection`
86
+ # ---------------------------------------------------------
87
+ #
88
+ # `.pyplot.scatter` returns a :class:`~matplotlib.collections.PathCollection`
89
+ # that can similarly be modified by using the
90
+ # `.collections.PathCollection.set_offsets` function.
59
91
60
92
fig , ax = plt .subplots ()
61
93
rng = np .random .default_rng ()
@@ -84,6 +116,10 @@ def update(frame):
84
116
###############################################################################
85
117
# Animating :class:`~matplotlib.image.AxesImage`
86
118
# ---------------------------------------------------
119
+ #
120
+ # When we plot an image using `.pyplot.imshow`, it returns an
121
+ # :class:`~matplotlib.image.AxesImage` object. The data in this object can also
122
+ # similarly be modified by using the `.image.AxesImage.set_data` method.
87
123
88
124
fig , ax = plt .subplots ()
89
125
rng = np .random .default_rng ()
@@ -97,16 +133,17 @@ def update(frame):
97
133
return aximg ,
98
134
99
135
ani = animation .FuncAnimation (
100
- fig = fig , func = update , frames = 240 , interval = 200
136
+ fig = fig , func = update , frames = None , interval = 200
101
137
)
102
138
plt .show ()
103
139
104
140
###############################################################################
105
141
# :class:`~matplotlib.animation.ArtistAnimation`
106
142
# ----------------------------------------------
107
143
#
108
- # :class:`~matplotlib.animation.ArtistAnimation` uses a list of artists to
109
- # iterate over and animate.
144
+ # On the other hand, :class:`~matplotlib.animation.ArtistAnimation` can be used
145
+ # to generate animations if we have data on various different artists. This
146
+ # list of artists is then converted frame by frame into an animation.
110
147
111
148
112
149
fig , ax = plt .subplots ()
@@ -125,9 +162,40 @@ def update(frame):
125
162
ani = animation .ArtistAnimation (fig = fig , artists = artists , repeat_delay = 1000 )
126
163
plt .show ()
127
164
165
+ ###############################################################################
166
+ # :class:`~matplotlib.animation.FuncAnimation` is more efficient in terms of
167
+ # speed and memory as it draws an artist once and then modifies it. On the
168
+ # other hand :class:`~matplotlib.animation.ArtistAnimation` is flexible as it
169
+ # allows any iterable of artists to be animated in a sequence.
170
+
128
171
###############################################################################
129
172
# Animation Writers
130
- # -------------------------------------------
173
+ # -----------------
174
+ #
175
+ # Animation objects can be saved to disk using various multimedia writers
176
+ # (ex: Pillow, *ffpmeg*, *imagemagick*). Not all video formats are supported
177
+ # by all writers. A list of supported formats for each writer can be found at
178
+ # the end of this tutorial. There are 4 major types of writers:
179
+ #
180
+ # 1. :class:`~matplotlib.animation.PillowWriter` - Uses the Pillow library to
181
+ # create the animation.
182
+ #
183
+ # 2. :class:`~matplotlib.animation.HTMLWriter` - Used to create JS-based
184
+ # animations.
185
+ #
186
+ # 3. Pipe-based writers - :class:`~matplotlib.animation.FFMpegWriter` and
187
+ # :class:`~matplotlib.animation.ImageMagickWriter` are pipe based writers.
188
+ # These writers pipe each frame to the utility (*ffmpeg* / *imagemagick*) which
189
+ # then stitches all of them together to create the animation.
190
+ #
191
+ # 4. File-based writers - :class:`~matplotlib.animation.FFMpegFileWriter` and
192
+ # :class:`~matplotlib.animation.ImageMagickFileWriter` are examples of
193
+ # file-based writers. These writers are slower than their standard writers but
194
+ # are more useful for debugging as they save each frame in a file before
195
+ # stitching them together into an animation.
196
+ #
197
+ # Below we see examples for how to use different writers with
198
+ # `.animation.Animation.save`
131
199
132
200
fig , ax = plt .subplots ()
133
201
ax .grid ()
@@ -153,8 +221,6 @@ def update(frame):
153
221
# ani.save(filename="/tmp/pillow_example.gif", writer="pillow")
154
222
# ani.save(filename="/tmp/pillow_example.apng", writer="pillow")
155
223
156
- # Why does HTMLWriter documentation have a variable named
157
- # supported_formats = ['png', 'jpeg', 'tiff', 'svg']
158
224
# ani.save(filename="/tmp/html_example.html", writer="html")
159
225
# ani.save(filename="/tmp/html_example.htm", writer="html")
160
226
# ani.save(filename="/tmp/html_example.png", writer="html")
@@ -167,3 +233,14 @@ def update(frame):
167
233
168
234
# Imagemagick
169
235
# ani.save(filename="/tmp/imagemagick_example.gif", writer="imagemagick")
236
+
237
+ ###############################################################################
238
+ #
239
+ # ================================================ =============================
240
+ # Writer Supported Formats
241
+ # ================================================ =============================
242
+ # :class:`~matplotlib.animation.PillowWriter` .gif, .apng
243
+ # :class:`~matplotlib.animation.HTMLWriter` .htm, .html, .png
244
+ # :class:`~matplotlib.animation.FFMpegWriter` All formats supported by *ffmpeg*
245
+ # :class:`~matplotlib.animation.ImageMagickWriter` .gif
246
+ # ================================================ =============================
0 commit comments