├── template ├── .gitignore ├── frames │ └── README.txt ├── icons │ ├── first.png │ ├── last.png │ ├── next.png │ ├── pause.png │ ├── play.png │ ├── prev.png │ └── reverse.png ├── icons_large │ ├── last.png │ ├── next.png │ ├── play.png │ ├── prev.png │ ├── first.png │ ├── pause.png │ └── reverse.png ├── README.md ├── make_frames.py ├── make_lorenz_frames.py └── animation.html ├── JSAnimation ├── __init__.py ├── icons │ ├── last.png │ ├── next.png │ ├── play.png │ ├── prev.png │ ├── first.png │ ├── pause.png │ └── reverse.png ├── IPython_display.py ├── examples.py └── html_writer.py ├── .gitignore ├── make_animation.py ├── setup.py ├── run_examples.ipynb ├── LICENSE ├── README.md └── make_lorenz_animation.py /template/.gitignore: -------------------------------------------------------------------------------- 1 | frames/*.png 2 | frames/*.sgv -------------------------------------------------------------------------------- /JSAnimation/__init__.py: -------------------------------------------------------------------------------- 1 | from .html_writer import HTMLWriter 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.pyc 3 | *.html 4 | *_frames/*.png 5 | .ipynb_checkpoints -------------------------------------------------------------------------------- /template/frames/README.txt: -------------------------------------------------------------------------------- 1 | This is the directory where individual frames will be stored. 2 | -------------------------------------------------------------------------------- /template/icons/first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/template/icons/first.png -------------------------------------------------------------------------------- /template/icons/last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/template/icons/last.png -------------------------------------------------------------------------------- /template/icons/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/template/icons/next.png -------------------------------------------------------------------------------- /template/icons/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/template/icons/pause.png -------------------------------------------------------------------------------- /template/icons/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/template/icons/play.png -------------------------------------------------------------------------------- /template/icons/prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/template/icons/prev.png -------------------------------------------------------------------------------- /JSAnimation/icons/last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/JSAnimation/icons/last.png -------------------------------------------------------------------------------- /JSAnimation/icons/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/JSAnimation/icons/next.png -------------------------------------------------------------------------------- /JSAnimation/icons/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/JSAnimation/icons/play.png -------------------------------------------------------------------------------- /JSAnimation/icons/prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/JSAnimation/icons/prev.png -------------------------------------------------------------------------------- /template/icons/reverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/template/icons/reverse.png -------------------------------------------------------------------------------- /JSAnimation/icons/first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/JSAnimation/icons/first.png -------------------------------------------------------------------------------- /JSAnimation/icons/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/JSAnimation/icons/pause.png -------------------------------------------------------------------------------- /JSAnimation/icons/reverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/JSAnimation/icons/reverse.png -------------------------------------------------------------------------------- /template/icons_large/last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/template/icons_large/last.png -------------------------------------------------------------------------------- /template/icons_large/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/template/icons_large/next.png -------------------------------------------------------------------------------- /template/icons_large/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/template/icons_large/play.png -------------------------------------------------------------------------------- /template/icons_large/prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/template/icons_large/prev.png -------------------------------------------------------------------------------- /template/icons_large/first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/template/icons_large/first.png -------------------------------------------------------------------------------- /template/icons_large/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/template/icons_large/pause.png -------------------------------------------------------------------------------- /template/icons_large/reverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakevdp/JSAnimation/HEAD/template/icons_large/reverse.png -------------------------------------------------------------------------------- /template/README.md: -------------------------------------------------------------------------------- 1 | Animation Template 2 | ------------------ 3 | This is the template that was developed before the HTMLWriter was written. 4 | To view the animation, use 5 | 6 | python make_frames.py 7 | 8 | or 9 | 10 | python make_lorenz_frames.py 11 | 12 | and then open ``animation.html`` with your browser. 13 | 14 | -------------------------------------------------------------------------------- /template/make_frames.py: -------------------------------------------------------------------------------- 1 | """ 2 | Create some sample animation frames for testing 3 | """ 4 | import numpy as np 5 | import matplotlib.pyplot as plt 6 | 7 | x = np.linspace(0, 10, 1000) 8 | 9 | fig, ax = plt.subplots(figsize=(4, 3)) 10 | line, = plt.plot(x, np.sin(x), '-b', lw=2) 11 | ax.set_xlim(0, 10) 12 | ax.set_ylim(-2, 2) 13 | 14 | for i in range(100): 15 | line.set_data(x, np.cos(i * 0.02 * np.pi) * np.sin(x - i * 0.02 * np.pi)) 16 | fig.savefig('frames/frame%.03i.png' % (i + 1)) 17 | -------------------------------------------------------------------------------- /make_animation.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from matplotlib import pyplot as plt 3 | from matplotlib import animation 4 | from JSAnimation import HTMLWriter 5 | 6 | 7 | fig = plt.figure(figsize=(4, 3)) 8 | ax = plt.axes(xlim=(0, 10), ylim=(-2, 2)) 9 | line, = ax.plot([], [], lw=2) 10 | 11 | def init(): 12 | line.set_data([], []) 13 | return line, 14 | 15 | def animate(i): 16 | x = np.linspace(0, 10, 1000) 17 | y = np.cos(i * 0.02 * np.pi) * np.sin(x - i * 0.02 * np.pi) 18 | line.set_data(x, y) 19 | return line, 20 | 21 | anim = animation.FuncAnimation(fig, animate, init_func=init, 22 | frames=100, interval=20, blit=True) 23 | 24 | # set embed_frames=True to embed base64-encoded frames directly in the HTML 25 | anim.save('animation.html', writer=HTMLWriter(embed_frames=True)) 26 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | 3 | DESCRIPTION = "Javascript Animation exporter for matplotlib and IPython" 4 | LONG_DESCRIPTION = DESCRIPTION 5 | NAME = "JSAnimation" 6 | AUTHOR = "Jake VanderPlas" 7 | AUTHOR_EMAIL = "jakevdp@cs.washington.edu" 8 | MAINTAINER = "Jake VanderPlas" 9 | MAINTAINER_EMAIL = "jakevdp@cs.washington.edu" 10 | DOWNLOAD_URL = 'http://github.com/jakevdp/JSAnimation' 11 | LICENSE = 'BSD' 12 | 13 | VERSION = '0.1' 14 | 15 | setup(name=NAME, 16 | version=VERSION, 17 | description=DESCRIPTION, 18 | long_description=LONG_DESCRIPTION, 19 | author=AUTHOR, 20 | author_email=AUTHOR_EMAIL, 21 | maintainer=MAINTAINER, 22 | maintainer_email=MAINTAINER_EMAIL, 23 | url=DOWNLOAD_URL, 24 | download_url=DOWNLOAD_URL, 25 | license=LICENSE, 26 | packages=['JSAnimation'], 27 | package_data={'JSAnimation': ['icons/*.png']} 28 | ) 29 | -------------------------------------------------------------------------------- /run_examples.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "name": "test" 4 | }, 5 | "nbformat": 3, 6 | "nbformat_minor": 0, 7 | "worksheets": [ 8 | { 9 | "cells": [ 10 | { 11 | "cell_type": "code", 12 | "collapsed": false, 13 | "input": [ 14 | "%pylab inline" 15 | ], 16 | "language": "python", 17 | "metadata": {}, 18 | "outputs": [] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "collapsed": false, 23 | "input": [ 24 | "from JSAnimation import examples" 25 | ], 26 | "language": "python", 27 | "metadata": {}, 28 | "outputs": [] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "collapsed": false, 33 | "input": [ 34 | "examples.basic_animation(interval=200)" 35 | ], 36 | "language": "python", 37 | "metadata": {}, 38 | "outputs": [] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "collapsed": false, 43 | "input": [ 44 | "examples.lorenz_animation()" 45 | ], 46 | "language": "python", 47 | "metadata": {}, 48 | "outputs": [] 49 | } 50 | ], 51 | "metadata": {} 52 | } 53 | ] 54 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Jake Vanderplas 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | JSAnimation 2 | =========== 3 | 4 | **NOTE: this package is part of matplotlib as of version 2.1. The code here is maintained only for historical purposes.** 5 | 6 | *Copyright (c) 2013, Jake Vanderplas* 7 | 8 | *License: [BSD](http://opensource.org/licenses/BSD-2-Clause)* 9 | 10 | This package implements an HTML/Javascript writer for Matplotlib animations. 11 | The result can be embedded in a web page, or an IPython notebook. 12 | 13 | Example 14 | ------- 15 | See a [rendered example](http://nbviewer.ipython.org/urls/raw.github.com/jakevdp/JSAnimation/master/animation_example.ipynb): please note the browser 16 | requirements listedbelow. 17 | 18 | Testing it Out 19 | -------------- 20 | There are several scripts which demonstrate this. ``make_animation.py`` 21 | creates a basic animation, with the frame data embedded within the HTML 22 | document. Run this using 23 | 24 | python make_animation.py 25 | 26 | and then open the resulting file, ``animation.html`` using your web browser. 27 | This file is created using the option ``embed = True``, which means that the 28 | image data is embedded directly in the html file in base64-representation. 29 | This means that the animation is entirely self-contained in the file. 30 | 31 | A more sophisticated animation can be created using 32 | 33 | python make_lorenz_animation.py 34 | 35 | (adapted from [this blog post](http://jakevdp.github.io/blog/2013/02/16/animating-the-lorentz-system-in-3d/) 36 | The resulting file, ``lorenz_animation.html``, 37 | can be opened in your web browser. 38 | This animation is created using the option ``embed = False``, which means that 39 | the frames are individually stored in the directory ``lorenz_animation_frames``. 40 | This prevents the html file from being too large. 41 | 42 | If you have IPython notebook installed, you can open ``animation_example.ipynb`` 43 | to see the automatic animation representation within the notebook. Simply 44 | import the ``IPython_display`` submodule, create the animation, and the 45 | javascript widget will appear embedded in your notebook window. 46 | 47 | Browser Compatibility 48 | --------------------- 49 | Because the animation widget uses an HTML5 slider element, it does not work 50 | in some browsers. For a comprehensive list of supported browsers, see 51 | [this list](http://caniuse.com/input-range). 52 | -------------------------------------------------------------------------------- /template/make_lorenz_frames.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy import integrate 3 | 4 | from matplotlib import pyplot as plt 5 | from mpl_toolkits.mplot3d import Axes3D 6 | from matplotlib.colors import cnames 7 | from matplotlib import animation 8 | 9 | N_trajectories = 20 10 | 11 | 12 | def lorentz_deriv((x, y, z), t0, sigma=10., beta=8./3, rho=28.0): 13 | """Compute the time-derivative of a Lorentz system.""" 14 | return [sigma * (y - x), x * (rho - z) - y, x * y - beta * z] 15 | 16 | 17 | # Choose random starting points, uniformly distributed from -15 to 15 18 | np.random.seed(1) 19 | x0 = -15 + 30 * np.random.random((N_trajectories, 3)) 20 | 21 | # Solve for the trajectories 22 | t = np.linspace(0, 4, 1000) 23 | x_t = np.asarray([integrate.odeint(lorentz_deriv, x0i, t) 24 | for x0i in x0]) 25 | 26 | # Set up figure & 3D axis for animation 27 | fig = plt.figure() 28 | ax = fig.add_axes([0, 0, 1, 1], projection='3d') 29 | ax.axis('off') 30 | 31 | # choose a different color for each trajectory 32 | colors = plt.cm.jet(np.linspace(0, 1, N_trajectories)) 33 | 34 | # set up lines and points 35 | lines = sum([ax.plot([], [], [], '-', c=c) 36 | for c in colors], []) 37 | pts = sum([ax.plot([], [], [], 'o', c=c) 38 | for c in colors], []) 39 | 40 | # prepare the axes limits 41 | ax.set_xlim((-25, 25)) 42 | ax.set_ylim((-35, 35)) 43 | ax.set_zlim((5, 55)) 44 | 45 | # set point-of-view: specified by (altitude degrees, azimuth degrees) 46 | ax.view_init(30, 0) 47 | 48 | # initialization function: plot the background of each frame 49 | def init(): 50 | for line, pt in zip(lines, pts): 51 | line.set_data([], []) 52 | line.set_3d_properties([]) 53 | 54 | pt.set_data([], []) 55 | pt.set_3d_properties([]) 56 | return lines + pts 57 | 58 | # animation function. This will be called sequentially with the frame number 59 | def animate(i): 60 | # we'll step two time-steps per frame. This leads to nice results. 61 | i = (2 * i) % x_t.shape[1] 62 | 63 | for line, pt, xi in zip(lines, pts, x_t): 64 | x, y, z = xi[:i].T 65 | line.set_data(x, y) 66 | line.set_3d_properties(z) 67 | 68 | pt.set_data(x[-1:], y[-1:]) 69 | pt.set_3d_properties(z[-1:]) 70 | 71 | ax.view_init(30, 0.3 * i) 72 | fig.canvas.draw() 73 | return lines + pts 74 | 75 | # instantiate the animator. 76 | #anim = animation.FuncAnimation(fig, animate, init_func=init, 77 | # frames=500, interval=30, blit=True) 78 | 79 | # Save as mp4. This requires mplayer or ffmpeg to be installed 80 | #anim.save('lorentz_attractor.mp4', fps=15, extra_args=['-vcodec', 'libx264']) 81 | 82 | #plt.show() 83 | 84 | for i in range(100): 85 | animate(2 * i + 1) 86 | fig.savefig('frames/frame%.03i.png' % (i + 1), dpi=80) 87 | 88 | -------------------------------------------------------------------------------- /make_lorenz_animation.py: -------------------------------------------------------------------------------- 1 | """ 2 | Lorenz animation 3 | 4 | Adapted from http://jakevdp.github.io/blog/2013/02/16/animating-the-lorentz-system-in-3d/ 5 | """ 6 | 7 | import numpy as np 8 | from scipy import integrate 9 | 10 | from matplotlib import pyplot as plt 11 | from mpl_toolkits.mplot3d import Axes3D 12 | from matplotlib.colors import cnames 13 | from matplotlib import animation 14 | 15 | from JSAnimation import HTMLWriter 16 | 17 | N_trajectories = 20 18 | 19 | 20 | def lorentz_deriv((x, y, z), t0, sigma=10., beta=8./3, rho=28.0): 21 | """Compute the time-derivative of a Lorentz system.""" 22 | return [sigma * (y - x), x * (rho - z) - y, x * y - beta * z] 23 | 24 | 25 | # Choose random starting points, uniformly distributed from -15 to 15 26 | np.random.seed(1) 27 | x0 = -15 + 30 * np.random.random((N_trajectories, 3)) 28 | 29 | # Solve for the trajectories 30 | t = np.linspace(0, 2, 500) 31 | x_t = np.asarray([integrate.odeint(lorentz_deriv, x0i, t) 32 | for x0i in x0]) 33 | 34 | # Set up figure & 3D axis for animation 35 | fig = plt.figure(figsize=(4, 3)) 36 | ax = fig.add_axes([0, 0, 1, 1], projection='3d') 37 | ax.axis('off') 38 | 39 | # choose a different color for each trajectory 40 | colors = plt.cm.jet(np.linspace(0, 1, N_trajectories)) 41 | 42 | # set up lines and points 43 | lines = sum([ax.plot([], [], [], '-', c=c) 44 | for c in colors], []) 45 | pts = sum([ax.plot([], [], [], 'o', c=c, ms=4) 46 | for c in colors], []) 47 | 48 | # prepare the axes limits 49 | ax.set_xlim((-25, 25)) 50 | ax.set_ylim((-35, 35)) 51 | ax.set_zlim((5, 55)) 52 | 53 | # set point-of-view: specified by (altitude degrees, azimuth degrees) 54 | ax.view_init(30, 0) 55 | 56 | # initialization function: plot the background of each frame 57 | def init(): 58 | for line, pt in zip(lines, pts): 59 | line.set_data([], []) 60 | line.set_3d_properties([]) 61 | 62 | pt.set_data([], []) 63 | pt.set_3d_properties([]) 64 | return lines + pts 65 | 66 | # animation function. This will be called sequentially with the frame number 67 | def animate(i): 68 | # we'll step two time-steps per frame. This leads to nice results. 69 | i = (2 * i) % x_t.shape[1] 70 | 71 | for line, pt, xi in zip(lines, pts, x_t): 72 | x, y, z = xi[:i + 1].T 73 | line.set_data(x, y) 74 | line.set_3d_properties(z) 75 | 76 | pt.set_data(x[-1:], y[-1:]) 77 | pt.set_3d_properties(z[-1:]) 78 | 79 | ax.view_init(30, 0.3 * i) 80 | fig.canvas.draw() 81 | return lines + pts 82 | 83 | # instantiate the animator. 84 | anim = animation.FuncAnimation(fig, animate, init_func=init, 85 | frames=200, interval=30, blit=True) 86 | 87 | # set embed_frames=False so that frames will be stored individually 88 | anim.save('lorenz_animation.html', writer=HTMLWriter(embed_frames=False)) 89 | 90 | 91 | -------------------------------------------------------------------------------- /JSAnimation/IPython_display.py: -------------------------------------------------------------------------------- 1 | from .html_writer import HTMLWriter 2 | from matplotlib.animation import Animation 3 | import matplotlib.pyplot as plt 4 | import tempfile 5 | import random 6 | import os 7 | 8 | 9 | __all__ = ['anim_to_html', 'display_animation'] 10 | 11 | 12 | class _NameOnlyTemporaryFile(object): 13 | """A context-managed temporary file which is not opened. 14 | 15 | The file should be accessible by name on any system. 16 | 17 | Parameters 18 | ---------- 19 | suffix : string 20 | The suffix of the temporary file (default = '') 21 | prefix : string 22 | The prefix of the temporary file (default = '_tmp_') 23 | hash_length : string 24 | The length of the random hash. The size of the hash space will 25 | be 16 ** hash_length (default=8) 26 | seed : integer 27 | the seed for the random number generator. If not specified, the 28 | system time will be used as a seed. 29 | absolute : boolean 30 | If true, return an absolute path to a temporary file in the current 31 | working directory. 32 | 33 | Example 34 | ------- 35 | 36 | >>> with _NameOnlyTemporaryFile(seed=0, absolute=False) as f: 37 | ... print(f) 38 | ... 39 | _tmp_d82c07cd 40 | >>> os.path.exists('_tmp_d82c07cd') # file removed after context 41 | False 42 | 43 | """ 44 | def __init__(self, prefix='_tmp_', suffix='', hash_length=8, 45 | seed=None, absolute=True): 46 | rng = random.Random(seed) 47 | self.name = '%s%0*x%s' % (prefix, hash_length, 48 | rng.getrandbits(4 * hash_length), suffix) 49 | if absolute: 50 | self.name = os.path.abspath(self.name) 51 | 52 | def __enter__(self): 53 | return self 54 | 55 | def __exit__(self, *exc_info): 56 | if os.path.exists(self.name): 57 | os.remove(self.name) 58 | 59 | 60 | def anim_to_html(anim, fps=None, embed_frames=True, default_mode='loop'): 61 | """Generate HTML representation of the animation""" 62 | if fps is None and hasattr(anim, '_interval'): 63 | # Convert interval in ms to frames per second 64 | fps = 1000. / anim._interval 65 | 66 | plt.close(anim._fig) 67 | if hasattr(anim, "_html_representation"): 68 | return anim._html_representation 69 | else: 70 | # tempfile can't be used here: we need a filename, and this 71 | # fails on windows. Instead, we use a custom filename generator 72 | #with tempfile.NamedTemporaryFile(suffix='.html') as f: 73 | with _NameOnlyTemporaryFile(suffix='.html') as f: 74 | anim.save(f.name, writer=HTMLWriter(fps=fps, 75 | embed_frames=embed_frames, 76 | default_mode=default_mode)) 77 | html = open(f.name).read() 78 | 79 | anim._html_representation = html 80 | return html 81 | 82 | 83 | def display_animation(anim, **kwargs): 84 | """Display the animation with an IPython HTML object""" 85 | from IPython.display import HTML 86 | return HTML(anim_to_html(anim, **kwargs)) 87 | 88 | 89 | # This is the magic that makes animations display automatically in the 90 | # IPython notebook. The _repr_html_ method is a special method recognized 91 | # by IPython. 92 | Animation._repr_html_ = anim_to_html 93 | -------------------------------------------------------------------------------- /JSAnimation/examples.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from matplotlib import pyplot as plt 3 | from matplotlib import animation 4 | from JSAnimation import IPython_display 5 | 6 | def basic_animation(frames=100, interval=30): 7 | """Plot a basic sine wave with oscillating amplitude""" 8 | fig = plt.figure() 9 | ax = plt.axes(xlim=(0, 10), ylim=(-2, 2)) 10 | line, = ax.plot([], [], lw=2) 11 | 12 | x = np.linspace(0, 10, 1000) 13 | 14 | def init(): 15 | line.set_data([], []) 16 | return line, 17 | 18 | def animate(i): 19 | y = np.cos(i * 0.02 * np.pi) * np.sin(x - i * 0.02 * np.pi) 20 | line.set_data(x, y) 21 | return line, 22 | 23 | return animation.FuncAnimation(fig, animate, init_func=init, 24 | frames=frames, interval=interval) 25 | 26 | 27 | def lorenz_animation(N_trajectories=20, rseed=1, frames=200, interval=30): 28 | """Plot a 3D visualization of the dynamics of the Lorenz system""" 29 | from scipy import integrate 30 | from mpl_toolkits.mplot3d import Axes3D 31 | from matplotlib.colors import cnames 32 | 33 | def lorentz_deriv(coords, t0, sigma=10., beta=8./3, rho=28.0): 34 | """Compute the time-derivative of a Lorentz system.""" 35 | x, y, z = coords 36 | return [sigma * (y - x), x * (rho - z) - y, x * y - beta * z] 37 | 38 | # Choose random starting points, uniformly distributed from -15 to 15 39 | np.random.seed(rseed) 40 | x0 = -15 + 30 * np.random.random((N_trajectories, 3)) 41 | 42 | # Solve for the trajectories 43 | t = np.linspace(0, 2, 500) 44 | x_t = np.asarray([integrate.odeint(lorentz_deriv, x0i, t) 45 | for x0i in x0]) 46 | 47 | # Set up figure & 3D axis for animation 48 | fig = plt.figure() 49 | ax = fig.add_axes([0, 0, 1, 1], projection='3d') 50 | ax.axis('off') 51 | 52 | # choose a different color for each trajectory 53 | colors = plt.cm.jet(np.linspace(0, 1, N_trajectories)) 54 | 55 | # set up lines and points 56 | lines = sum([ax.plot([], [], [], '-', c=c) 57 | for c in colors], []) 58 | pts = sum([ax.plot([], [], [], 'o', c=c, ms=4) 59 | for c in colors], []) 60 | 61 | # prepare the axes limits 62 | ax.set_xlim((-25, 25)) 63 | ax.set_ylim((-35, 35)) 64 | ax.set_zlim((5, 55)) 65 | 66 | # set point-of-view: specified by (altitude degrees, azimuth degrees) 67 | ax.view_init(30, 0) 68 | 69 | # initialization function: plot the background of each frame 70 | def init(): 71 | for line, pt in zip(lines, pts): 72 | line.set_data([], []) 73 | line.set_3d_properties([]) 74 | 75 | pt.set_data([], []) 76 | pt.set_3d_properties([]) 77 | return lines + pts 78 | 79 | # animation function: called sequentially 80 | def animate(i): 81 | # we'll step two time-steps per frame. This leads to nice results. 82 | i = (2 * i) % x_t.shape[1] 83 | 84 | for line, pt, xi in zip(lines, pts, x_t): 85 | x, y, z = xi[:i + 1].T 86 | line.set_data(x, y) 87 | line.set_3d_properties(z) 88 | 89 | pt.set_data(x[-1:], y[-1:]) 90 | pt.set_3d_properties(z[-1:]) 91 | 92 | ax.view_init(30, 0.3 * i) 93 | fig.canvas.draw() 94 | return lines + pts 95 | 96 | return animation.FuncAnimation(fig, animate, init_func=init, 97 | frames=frames, interval=interval) 98 | -------------------------------------------------------------------------------- /template/animation.html: -------------------------------------------------------------------------------- 1 | 136 | 137 |