diff --git a/doc/api/animation_api.rst b/doc/api/animation_api.rst index c8f4e72126e7..8edb6345cd3c 100644 --- a/doc/api/animation_api.rst +++ b/doc/api/animation_api.rst @@ -1,6 +1,6 @@ -====================== - ``animation`` module -====================== +********* +animation +********* .. automodule:: matplotlib.animation :no-members: @@ -11,10 +11,6 @@ :local: :backlinks: entry - -Animation -========= - The easiest way to make a live animation in matplotlib is to use one of the `Animation` classes. @@ -37,7 +33,6 @@ To save an animation to disk use `Animation.save` or `Animation.to_html5_video` See :ref:`ani_writer_classes` below for details about what movie formats are supported. - ``FuncAnimation`` ----------------- @@ -48,7 +43,6 @@ The inner workings of `FuncAnimation` is more-or-less:: fig.canvas.draw_idle() fig.canvas.start_event_loop(interval) - with details to handle 'blitting' (to dramatically improve the live performance), to be non-blocking, not repeatedly start/stop the GUI event loop, handle repeats, multiple animated axes, and easily save @@ -122,54 +116,40 @@ artist at a global scope and let Python sort things out. For example :: init_func=init, blit=True) plt.show() - The second method is to us `functools.partial` to 'bind' artists to function. A third method is to use closures to build up the required artists and functions. A fourth method is to create a class. - - - Examples ~~~~~~~~ .. toctree:: :maxdepth: 1 - ../gallery/animation/animate_decay - ../gallery/animation/bayes_update_sgskip - ../gallery/animation/double_pendulum_animated_sgskip + ../gallery/animation/bayes_update + ../gallery/animation/double_pendulum_sgskip ../gallery/animation/dynamic_image ../gallery/animation/histogram ../gallery/animation/rain - ../gallery/animation/random_data - ../gallery/animation/simple_3danim + ../gallery/animation/random_walk ../gallery/animation/simple_anim - ../gallery/animation/strip_chart_demo + ../gallery/animation/strip_chart ../gallery/animation/unchained ``ArtistAnimation`` ------------------- - Examples ~~~~~~~~ .. toctree:: :maxdepth: 1 - ../gallery/animation/basic_example - ../gallery/animation/basic_example_writer_sgskip ../gallery/animation/dynamic_image2 - - - Writer Classes ============== - - The provided writers fall into two broad categories: pipe-based and file-based. The pipe-based writers stream the captured frames over a pipe to an external process. The pipe-based variants tend to be more @@ -179,7 +159,6 @@ performant, but may not work on all systems. :toctree: _as_gen :nosignatures: - FFMpegWriter ImageMagickFileWriter AVConvWriter @@ -196,7 +175,6 @@ slower, these writers can be easier to debug. ImageMagickWriter AVConvFileWriter - Fundamentally, a `MovieWriter` provides a way to grab sequential frames from the same underlying `~matplotlib.figure.Figure` object. The base class `MovieWriter` implements 3 methods and a context manager. The @@ -215,32 +193,32 @@ file to disk. For example :: moviewriter.grab_frame() moviewriter.finish() - -If using the writer classes directly (not through `Animation.save`), it is strongly encouraged -to use the `~MovieWriter.saving` context manager :: +If using the writer classes directly (not through `Animation.save`), it is +strongly encouraged to use the `~MovieWriter.saving` context manager :: with moviewriter.saving(fig, 'myfile.mp4', dpi=100): for j in range(n): update_figure(n) moviewriter.grab_frame() - to ensures that setup and cleanup are performed as necessary. +Examples +~~~~~~~~ -:ref:`sphx_glr_gallery_animation_moviewriter_sgskip.py` +.. toctree:: + :maxdepth: 1 + ../gallery/animation/frame_grabbing_sgskip .. _ani_writer_classes: Helper Classes ============== - Animation Base Classes ---------------------- - .. autosummary:: :toctree: _as_gen :nosignatures: @@ -248,12 +226,6 @@ Animation Base Classes Animation TimedAnimation - -Custom Animation classes ------------------------- - -:ref:`sphx_glr_gallery_animation_subplots.py` - Writer Registry --------------- @@ -280,7 +252,7 @@ To reduce code duplication base classes MovieWriter FileMovieWriter -and mixins are provided +and mixins .. autosummary:: :toctree: _as_gen @@ -290,9 +262,9 @@ and mixins are provided FFMpegBase ImageMagickBase -See the source code for how to easily implement new `MovieWriter` -classes. +are provided. +See the source code for how to easily implement new `MovieWriter` classes. Inheritance Diagrams ==================== diff --git a/examples/animation/animate_decay.py b/examples/animation/animate_decay.py deleted file mode 100644 index d0fce20b86b2..000000000000 --- a/examples/animation/animate_decay.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -===== -Decay -===== - -A sinusoidal decay animation. -""" - - -import numpy as np -import matplotlib.pyplot as plt -import matplotlib.animation as animation - - -def data_gen(t=0): - cnt = 0 - while cnt < 1000: - cnt += 1 - t += 0.1 - yield t, np.sin(2*np.pi*t) * np.exp(-t/10.) - - -def init(): - ax.set_ylim(-1.1, 1.1) - ax.set_xlim(0, 10) - del xdata[:] - del ydata[:] - line.set_data(xdata, ydata) - return line, - -fig, ax = plt.subplots() -line, = ax.plot([], [], lw=2) -ax.grid() -xdata, ydata = [], [] - - -def run(data): - # update the data - t, y = data - xdata.append(t) - ydata.append(y) - xmin, xmax = ax.get_xlim() - - if t >= xmax: - ax.set_xlim(xmin, 2*xmax) - ax.figure.canvas.draw() - line.set_data(xdata, ydata) - - return line, - -ani = animation.FuncAnimation(fig, run, data_gen, blit=False, interval=10, - repeat=False, init_func=init) -plt.show() diff --git a/examples/animation/basic_example.py b/examples/animation/basic_example.py deleted file mode 100644 index 9e7f4ae103eb..000000000000 --- a/examples/animation/basic_example.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -========================= -Simple animation examples -========================= - -Two animations where the first is a random walk plot and -the second is an image animation. -""" - -import numpy as np -import matplotlib.pyplot as plt -import matplotlib.animation as animation - - -def update_line(num, data, line): - line.set_data(data[..., :num]) - return line, - -############################################################################### - -fig1 = plt.figure() - -# Fixing random state for reproducibility -np.random.seed(19680801) - -data = np.random.rand(2, 25) -l, = plt.plot([], [], 'r-') -plt.xlim(0, 1) -plt.ylim(0, 1) -plt.xlabel('x') -plt.title('test') -line_ani = animation.FuncAnimation(fig1, update_line, 25, fargs=(data, l), - interval=50, blit=True) - -# To save the animation, use the command: line_ani.save('lines.mp4') - -############################################################################### - -fig2 = plt.figure() - -x = np.arange(-9, 10) -y = np.arange(-9, 10).reshape(-1, 1) -base = np.hypot(x, y) -ims = [] -for add in np.arange(15): - ims.append((plt.pcolor(x, y, base + add, norm=plt.Normalize(0, 30)),)) - -im_ani = animation.ArtistAnimation(fig2, ims, interval=50, repeat_delay=3000, - blit=True) -# To save this second animation with some metadata, use the following command: -# im_ani.save('im.mp4', metadata={'artist':'Guido'}) - -plt.show() diff --git a/examples/animation/basic_example_writer_sgskip.py b/examples/animation/basic_example_writer_sgskip.py deleted file mode 100644 index d223471d100f..000000000000 --- a/examples/animation/basic_example_writer_sgskip.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -=================== -Saving an animation -=================== - -This example showcases the same animations as `basic_example.py`, but instead -of displaying the animation to the user, it writes to files using a -MovieWriter instance. -""" - -import numpy as np -import matplotlib -matplotlib.use("Agg") -import matplotlib.pyplot as plt -import matplotlib.animation as animation - - -def update_line(num, data, line): - line.set_data(data[..., :num]) - return line, - -# Fixing random state for reproducibility -np.random.seed(19680801) - - -# Set up formatting for the movie files -Writer = animation.writers['ffmpeg'] -writer = Writer(fps=15, metadata=dict(artist='Me'), bitrate=1800) - - -fig1 = plt.figure() - -data = np.random.rand(2, 25) -l, = plt.plot([], [], 'r-') -plt.xlim(0, 1) -plt.ylim(0, 1) -plt.xlabel('x') -plt.title('test') -line_ani = animation.FuncAnimation(fig1, update_line, 25, fargs=(data, l), - interval=50, blit=True) -line_ani.save('lines.mp4', writer=writer) - -fig2 = plt.figure() - -x = np.arange(-9, 10) -y = np.arange(-9, 10).reshape(-1, 1) -base = np.hypot(x, y) -ims = [] -for add in np.arange(15): - ims.append((plt.pcolor(x, y, base + add, norm=plt.Normalize(0, 30)),)) - -im_ani = animation.ArtistAnimation(fig2, ims, interval=50, repeat_delay=3000, - blit=True) -im_ani.save('im.mp4', writer=writer) diff --git a/examples/animation/bayes_update_sgskip.py b/examples/animation/bayes_update.py similarity index 88% rename from examples/animation/bayes_update_sgskip.py rename to examples/animation/bayes_update.py index e819682ac089..242d19ebb3df 100644 --- a/examples/animation/bayes_update_sgskip.py +++ b/examples/animation/bayes_update.py @@ -9,13 +9,18 @@ distribution should converge. """ -# update a distribution based on new data. +import math + import numpy as np import matplotlib.pyplot as plt -import scipy.stats as ss from matplotlib.animation import FuncAnimation +def beta_pdf(x, a, b): + return (x**(a-1) * (1-x)**(b-1) * math.gamma(a + b) + / (math.gamma(a) * math.gamma(b))) + + class UpdateDist(object): def __init__(self, ax, prob=0.5): self.success = 0 @@ -47,7 +52,7 @@ def __call__(self, i): # Choose success based on exceed a threshold with a uniform pick if np.random.rand(1,) < self.prob: self.success += 1 - y = ss.beta.pdf(self.x, self.success + 1, (i - self.success) + 1) + y = beta_pdf(self.x, self.success + 1, (i - self.success) + 1) self.line.set_data(self.x, y) return self.line, diff --git a/examples/animation/double_pendulum_animated_sgskip.py b/examples/animation/double_pendulum_sgskip.py similarity index 98% rename from examples/animation/double_pendulum_animated_sgskip.py rename to examples/animation/double_pendulum_sgskip.py index 9e419f324c12..3d4bf0c618ca 100644 --- a/examples/animation/double_pendulum_animated_sgskip.py +++ b/examples/animation/double_pendulum_sgskip.py @@ -94,5 +94,4 @@ def animate(i): ani = animation.FuncAnimation(fig, animate, np.arange(1, len(y)), interval=25, blit=True, init_func=init) -# ani.save('double_pendulum.mp4', fps=15) plt.show() diff --git a/examples/animation/dynamic_image.py b/examples/animation/dynamic_image.py index 28db4bae5e0d..f2ed30ffc2e2 100644 --- a/examples/animation/dynamic_image.py +++ b/examples/animation/dynamic_image.py @@ -1,10 +1,10 @@ """ -================= -An animated image -================= +============== +Animated image +============== -Animation of an image. """ + import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation @@ -29,4 +29,15 @@ def updatefig(*args): return im, ani = animation.FuncAnimation(fig, updatefig, interval=50, blit=True) + +# To save the animation, use e.g. +# +# ani.save("movie.mp4") +# +# or +# +# from matplotlib.animation import FFMpegWriter +# writer = Writer(fps=15, metadata=dict(artist='Me'), bitrate=1800) +# ani.save("movie.mp4", writer=writer) + plt.show() diff --git a/examples/animation/dynamic_image2.py b/examples/animation/dynamic_image2.py index 7616e834d922..d01a66ff6869 100644 --- a/examples/animation/dynamic_image2.py +++ b/examples/animation/dynamic_image2.py @@ -1,10 +1,10 @@ """ -======================================== -An animated image using a list of images -======================================== +================================================= +Animated image using a precomputed list of images +================================================= -Animate an image from a list of images (or Artists). """ + import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation @@ -30,6 +30,14 @@ def f(x, y): ani = animation.ArtistAnimation(fig, ims, interval=50, blit=True, repeat_delay=1000) -# ani.save('dynamic_images.mp4') +# To save the animation, use e.g. +# +# ani.save("movie.mp4") +# +# or +# +# from matplotlib.animation import FFMpegWriter +# writer = Writer(fps=15, metadata=dict(artist='Me'), bitrate=1800) +# ani.save("movie.mp4", writer=writer) plt.show() diff --git a/examples/animation/moviewriter_sgskip.py b/examples/animation/frame_grabbing_sgskip.py similarity index 63% rename from examples/animation/moviewriter_sgskip.py rename to examples/animation/frame_grabbing_sgskip.py index 0d2122247f7a..e74576249aa0 100644 --- a/examples/animation/moviewriter_sgskip.py +++ b/examples/animation/frame_grabbing_sgskip.py @@ -1,26 +1,23 @@ """ -=========== -MovieWriter -=========== - -Use a MovieWriter directly to grab individual frames and write -them to a file. This avoids any event loop integration, but has the advantage -of working with even the Agg backend. This is not recommended for use in an -interactive setting. +============== +Frame grabbing +============== +Use a MovieWriter directly to grab individual frames and write them to a +file. This avoids any event loop integration, and thus works even with the Agg +backend. This is not recommended for use in an interactive setting. """ import numpy as np import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt -import matplotlib.animation as manimation +from matplotlib.animation import FFMpegWriter # Fixing random state for reproducibility np.random.seed(19680801) -FFMpegWriter = manimation.writers['ffmpeg'] metadata = dict(title='Movie Test', artist='Matplotlib', comment='Movie support!') writer = FFMpegWriter(fps=15, metadata=metadata) diff --git a/examples/animation/histogram.py b/examples/animation/histogram.py index 365157172ab2..2556708dd7e7 100644 --- a/examples/animation/histogram.py +++ b/examples/animation/histogram.py @@ -4,8 +4,8 @@ ================== Use a path patch to draw a bunch of rectangles for an animated histogram. - """ + import numpy as np import matplotlib.pyplot as plt diff --git a/examples/animation/rain.py b/examples/animation/rain.py index 3e96be613b6f..6fe60ff0520d 100644 --- a/examples/animation/rain.py +++ b/examples/animation/rain.py @@ -8,6 +8,7 @@ Author: Nicolas P. Rougier """ + import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation @@ -65,7 +66,6 @@ def update(frame_number): scat.set_offsets(rain_drops['position']) -# Construct the animation, using the update function as the animation -# director. +# Construct the animation, using the update function as the animation director. animation = FuncAnimation(fig, update, interval=10) plt.show() diff --git a/examples/animation/random_data.py b/examples/animation/random_data.py deleted file mode 100644 index 3c1d6f933087..000000000000 --- a/examples/animation/random_data.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -=========== -Random data -=========== - -An animation of random data. - -""" - -import numpy as np -import matplotlib.pyplot as plt -import matplotlib.animation as animation - -# Fixing random state for reproducibility -np.random.seed(19680801) - - -fig, ax = plt.subplots() -line, = ax.plot(np.random.rand(10)) -ax.set_ylim(0, 1) - - -def update(data): - line.set_ydata(data) - return line, - - -def data_gen(): - while True: - yield np.random.rand(10) - -ani = animation.FuncAnimation(fig, update, data_gen, interval=100) -plt.show() diff --git a/examples/animation/simple_3danim.py b/examples/animation/random_walk.py similarity index 96% rename from examples/animation/simple_3danim.py rename to examples/animation/random_walk.py index d248d61b4748..ae60ce7c09ec 100644 --- a/examples/animation/simple_3danim.py +++ b/examples/animation/random_walk.py @@ -1,10 +1,10 @@ """ -============ -3D animation -============ +======================= +Animated 3D random walk +======================= -An animated plot in 3D. """ + import numpy as np import matplotlib.pyplot as plt import mpl_toolkits.mplot3d.axes3d as p3 diff --git a/examples/animation/simple_anim.py b/examples/animation/simple_anim.py index 417aa5f36709..3fc1294d645a 100644 --- a/examples/animation/simple_anim.py +++ b/examples/animation/simple_anim.py @@ -1,10 +1,10 @@ """ -=========== -Simple Anim -=========== +================== +Animated line plot +================== -A simple example of an animated plot """ + import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation @@ -15,16 +15,27 @@ line, = ax.plot(x, np.sin(x)) -def animate(i): - line.set_ydata(np.sin(x + i/10.0)) # update the data +def init(): # only required for blitting to give a clean slate. + line.set_ydata(x) return line, -# Init only required for blitting to give a clean slate. -def init(): - line.set_ydata(np.ma.array(x, mask=True)) +def animate(i): + line.set_ydata(np.sin(x + i/10.0)) # update the data. return line, + ani = animation.FuncAnimation(fig, animate, np.arange(1, 200), init_func=init, interval=25, blit=True) + +# To save the animation, use e.g. +# +# ani.save("movie.mp4") +# +# or +# +# from matplotlib.animation import FFMpegWriter +# writer = Writer(fps=15, metadata=dict(artist='Me'), bitrate=1800) +# ani.save("movie.mp4", writer=writer) + plt.show() diff --git a/examples/animation/strip_chart_demo.py b/examples/animation/strip_chart.py similarity index 100% rename from examples/animation/strip_chart_demo.py rename to examples/animation/strip_chart.py index 60a5db6b13b4..8e9bf2dad659 100644 --- a/examples/animation/strip_chart_demo.py +++ b/examples/animation/strip_chart.py @@ -5,6 +5,7 @@ Emulates an oscilloscope. """ + import numpy as np from matplotlib.lines import Line2D import matplotlib.pyplot as plt @@ -58,5 +59,4 @@ def emitter(p=0.03): ani = animation.FuncAnimation(fig, scope.update, emitter, interval=10, blit=True) - plt.show() diff --git a/examples/animation/subplots.py b/examples/animation/subplots.py deleted file mode 100644 index 9af8296471a1..000000000000 --- a/examples/animation/subplots.py +++ /dev/null @@ -1,104 +0,0 @@ -""" -================= -Animated subplots -================= - -This example uses subclassing, but there is no reason that the proper function -couldn't be set up and then use FuncAnimation. The code is long, but not -really complex. The length is due solely to the fact that there are a total of -9 lines that need to be changed for the animation as well as 3 subplots that -need initial set up. - -""" - -import numpy as np -import matplotlib.pyplot as plt -from matplotlib.lines import Line2D -import matplotlib.animation as animation - - -class SubplotAnimation(animation.TimedAnimation): - def __init__(self): - fig = plt.figure() - ax1 = fig.add_subplot(1, 2, 1) - ax2 = fig.add_subplot(2, 2, 2) - ax3 = fig.add_subplot(2, 2, 4) - - self.t = np.linspace(0, 80, 400) - self.x = np.cos(2 * np.pi * self.t / 10.) - self.y = np.sin(2 * np.pi * self.t / 10.) - self.z = 10 * self.t - - ax1.set_xlabel('x') - ax1.set_ylabel('y') - self.line1 = Line2D([], [], color='black') - self.line1a = Line2D([], [], color='red', linewidth=2) - self.line1e = Line2D( - [], [], color='red', marker='o', markeredgecolor='r') - ax1.add_line(self.line1) - ax1.add_line(self.line1a) - ax1.add_line(self.line1e) - ax1.set_xlim(-1, 1) - ax1.set_ylim(-2, 2) - ax1.set_aspect('equal', 'datalim') - - ax2.set_xlabel('y') - ax2.set_ylabel('z') - self.line2 = Line2D([], [], color='black') - self.line2a = Line2D([], [], color='red', linewidth=2) - self.line2e = Line2D( - [], [], color='red', marker='o', markeredgecolor='r') - ax2.add_line(self.line2) - ax2.add_line(self.line2a) - ax2.add_line(self.line2e) - ax2.set_xlim(-1, 1) - ax2.set_ylim(0, 800) - - ax3.set_xlabel('x') - ax3.set_ylabel('z') - self.line3 = Line2D([], [], color='black') - self.line3a = Line2D([], [], color='red', linewidth=2) - self.line3e = Line2D( - [], [], color='red', marker='o', markeredgecolor='r') - ax3.add_line(self.line3) - ax3.add_line(self.line3a) - ax3.add_line(self.line3e) - ax3.set_xlim(-1, 1) - ax3.set_ylim(0, 800) - - animation.TimedAnimation.__init__(self, fig, interval=50, blit=True) - - def _draw_frame(self, framedata): - i = framedata - head = i - 1 - head_slice = (self.t > self.t[i] - 1.0) & (self.t < self.t[i]) - - self.line1.set_data(self.x[:i], self.y[:i]) - self.line1a.set_data(self.x[head_slice], self.y[head_slice]) - self.line1e.set_data(self.x[head], self.y[head]) - - self.line2.set_data(self.y[:i], self.z[:i]) - self.line2a.set_data(self.y[head_slice], self.z[head_slice]) - self.line2e.set_data(self.y[head], self.z[head]) - - self.line3.set_data(self.x[:i], self.z[:i]) - self.line3a.set_data(self.x[head_slice], self.z[head_slice]) - self.line3e.set_data(self.x[head], self.z[head]) - - self._drawn_artists = [self.line1, self.line1a, self.line1e, - self.line2, self.line2a, self.line2e, - self.line3, self.line3a, self.line3e] - - def new_frame_seq(self): - return iter(range(self.t.size)) - - def _init_draw(self): - lines = [self.line1, self.line1a, self.line1e, - self.line2, self.line2a, self.line2e, - self.line3, self.line3a, self.line3e] - for l in lines: - l.set_data([], []) - -ani = SubplotAnimation() -# ani.save('test_sub.mp4') -plt.show() diff --git a/examples/animation/unchained.py b/examples/animation/unchained.py index faa2cf0a29c1..fbcce8337ee9 100644 --- a/examples/animation/unchained.py +++ b/examples/animation/unchained.py @@ -3,11 +3,12 @@ MATPLOTLIB **UNCHAINED** ======================== -Comparative path demonstration of frequency from a fake signal of a pulsar. -(mostly known because of the cover for Joy Division's Unknown Pleasures) +Comparative path demonstration of frequency from a fake signal of a pulsar +(mostly known because of the cover for Joy Division's Unknown Pleasures). Author: Nicolas P. Rougier """ + import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation @@ -67,7 +68,6 @@ def update(*args): # Return modified artists return lines -# Construct the animation, using the update function as the animation -# director. +# Construct the animation, using the update function as the animation director. anim = animation.FuncAnimation(fig, update, interval=10) plt.show()