animating the lorenz system in 3d
DESCRIPTION
lorenzTRANSCRIPT
Pythonic Perambulations(https://jakevdp.github.io/)Musings and ramblings through the world ofPython and beyond
Atom (/atom.xml)
Search
Navigate…
Archives (/archives.html)Home Page (http://www.astro.washington.edu/users/vanderplas)
Animating the Lorenz System in 3DFeb 16, 2013
One of the things I really enjoy about Python is how easy it makes it to solve interesting problems and visualizethose solutions in a compelling way. I've done several posts on creating animations using matplotlib's relativelynew animation toolkit (http://matplotlib.sourceforge.net/api/animation_api.html): (some examples are a chaoticdouble pendulum (/blog/2012/08/18/matplotlibanimationtutorial/), the collisions of particles in a box(/blog/2012/08/18/matplotlibanimationtutorial/), the timeevolution of a quantummechanical wavefunction(/blog/2012/09/05/quantumpython/), and even a scene from the classic video game, Super Mario Bros.(/blog/2013/01/13/hackingsupermariobroswithpython/)).Recently, a reader commented (/blog/2012/08/18/matplotlibanimationtutorial/#comment799781196) askingwhether I might do a 3D animation example. Matplotlib has a decent 3D toolkit called mplot3D(http://matplotlib.org/mpl_toolkits/mplot3d/index.html), and though I haven't previously seen it used in conjunctionwith the animation tools, there's nothing fundamental that prevents it.At the commenter's suggestion, I decided to try this out with a simple example of a chaotic system: the Lorenzequations.
Solving the Lorenz SystemThe Lorenz Equations (http://en.wikipedia.org/wiki/Lorenz_system) are a system of three coupled, firstorder,nonlinear differential equations which describe the trajectory of a particle through time. The system was originallyderived by Lorenz as a model of atmospheric convection, but the deceptive simplicity of the equations have madethem an oftenused example in fields beyond atmospheric physics.The equations describe the evolution of the spatial variables , , and , given the governing parameters , ,and , through the specification of the timederivatives of the spatial variables:
The resulting dynamics are entirely deterministic giving a starting point and a time interval . Thoughit looks straightforward, for certain choices of the parameters , the trajectories become chaotic, and theresulting trajectories display some surprising properties.
x y z σ β
ρ
dx/dt = σ(y − x)dy/dt = x(ρ − z) − y
dz/dt = xy − βz
( , , )x0 y0 z0 t
(σ, ρ, β)
Though no general analytic solution exists for this system, the solutions can be computed numerically. Pythonmakes this sort of problem very easy to solve: one can simply use Scipy's interface to ODEPACK(https://computation.llnl.gov/casc/odepack/odepack_home.html), an optimized Fortran package for solvingordinary differential equations. Here's how the problem can be set up:
import numpy as npfrom scipy import integrate
# Note: t0 is required for the odeint function, though it's not used here.def lorentz_deriv((x, y, z), t0, sigma=10., beta=8./3, rho=28.0): """Compute the time-derivative of a Lorenz system.""" return [sigma * (y - x), x * (rho - z) - y, x * y - beta * z]
x0 = [1, 1, 1] # starting vectort = np.linspace(0, 3, 1000) # one thousand time stepsx_t = integrate.odeint(lorentz_deriv, x0, t)
That's all there is to it!
Visualizing the resultsNow that we've computed these results, we can use matplotlib's animation and 3D plotting toolkits to visualize thetrajectories of several particles. Because I've described the animation tools indepth in a previous post(/blog/2012/08/18/matplotlibanimationtutorial/), I will skip that discussion here and jump straight into the code:
Lorenz System lorentz_animation.py download (/downloads/code/lorentz_animation.py)
import numpy as npfrom scipy import integrate
from matplotlib import pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dfrom matplotlib.colors import cnamesfrom matplotlib import animation
N_trajectories = 20
def lorentz_deriv((x, y, z), t0, sigma=10., beta=8./3, rho=28.0): """Compute the time-derivative of a Lorentz system.""" return [sigma * (y - x), x * (rho - z) - y, x * y - beta * z]
# Choose random starting points, uniformly distributed from -15 to 15np.random.seed(1)x0 = -15 + 30 * np.random.random((N_trajectories, 3))
# Solve for the trajectoriest = np.linspace(0, 4, 1000)x_t = np.asarray([integrate.odeint(lorentz_deriv, x0i, t) for x0i in x0])
# Set up figure & 3D axis for animationfig = plt.figure()ax = fig.add_axes([0, 0, 1, 1], projection='3d')ax.axis('off')
# choose a different color for each trajectorycolors = plt.cm.jet(np.linspace(0, 1, N_trajectories))
# set up lines and pointslines = sum([ax.plot([], [], [], '-', c=c) for c in colors], [])pts = sum([ax.plot([], [], [], 'o', c=c) for c in colors], [])
# prepare the axes limitsax.set_xlim((-25, 25))ax.set_ylim((-35, 35))ax.set_zlim((5, 55))
# set point-of-view: specified by (altitude degrees, azimuth degrees)ax.view_init(30, 0)
# initialization function: plot the background of each framedef init(): for line, pt in zip(lines, pts): line.set_data([], []) line.set_3d_properties([])
pt.set_data([], []) pt.set_3d_properties([]) return lines + pts
# animation function. This will be called sequentially with the frame numberdef animate(i): # we'll step two time-steps per frame. This leads to nice results. i = (2 * i) % x_t.shape[1]
for line, pt, xi in zip(lines, pts, x_t): x, y, z = xi[:i].T line.set_data(x, y) line.set_3d_properties(z)
pt.set_data(x[-1:], y[-1:]) pt.set_3d_properties(z[-1:])
ax.view_init(30, 0.3 * i) fig.canvas.draw() return lines + pts
# instantiate the animator.anim = animation.FuncAnimation(fig, animate, init_func=init, frames=500, interval=30, blit=True)
# Save as mp4. This requires mplayer or ffmpeg to be installed#anim.save('lorentz_attractor.mp4', fps=15, extra_args=['-vcodec', 'libx264'])
plt.show()
The resulting animation looks something like this:
Notice that there are two locations in the space that seem to drawin all paths: these are the socalled "Lorenzattractors", and have some interesting properties which you can read about elsewhere. The qualitativecharacteristics of these Lorenz attractors vary in somewhat surprising ways as the parameters arechanged. If you are so inclined, you may wish to download the above code and play with these values to see whatthe results look like.I hope that this brief exercise has shown you the power and flexibility of Python for understanding and visualizinga large array of problems, and perhaps given you the inspiration to explore similar problems.Happy coding!
Posted by Jake Vanderplas Feb 16, 2013Tweet 6 21
Comments21 Comments Pythonic Perambulations Login1
Share⤤ Sort by Best
Join the discussion…
tjc • 2 years agoHi Jake,
I was a bit perplexed by the 'sum' on lines 35 and 37. Crashes as is, for me. Did you mean:
Recommend 2
0:33
(σ, ρ, β)
• Reply •
# set up lines and pointslines = [ax.plot([], [], [], '-', c=c)[0]for c in colors]pts = [ax.plot([], [], [], 'o', c=c)[0]for c in colors]
Thanks for your posts.
1△ ▽
• Reply •
Prahas David Nafissian • 3 months ago> tjc
Absolutely correct correction! And on the Mac, take out the blit=true near thebottom!
△ ▽
• Reply •
uriel_sandoval • 2 years ago> tjc
Probably you are using a notebook with pylab inline, and that calls you the np.sumfunction instead of the buit-in python sum.
△ ▽
• Reply •
Ben Root • 2 years agoIt is Lorenz, not lorentz
1△ ▽
• Reply •
jakevdp • 2 years agoMod > Ben Root
Thanks - fixed that in all but the URL
△ ▽
• Reply •
Gael Varoquaux • 2 years agoHey Jake,
Have you ever played with the Mayavi interactive examples of the Lorentz system:http://docs.enthought.com/maya...andhttp://docs.enthought.com/maya...
I my opinion, what's really real with the second one, which is slightly more complex, is thatyou can change parameters interactively and watch the system evolve.
1△ ▽
• Reply •
jakevdp • 2 years agoMod > Gael Varoquaux
Hey Gael,Thanks for the links! Mayavi seems to have some pretty slick 3D tools! Maybe I'llspend a little more time playing around with that.
△ ▽
Prahas David Nafissian • 3 months agoHello -- is there a way to generate a log file with the x,y,z points generated by this algorithm?Thanks!
Share ›
Share ›
Share ›
Share ›
Share ›
Share ›
Share ›
• Reply • △ ▽
• Reply •
Prahas David Nafissian • 3 months agoIGNORE -- fixed. :-)
Hi -- thanks so much for your work! When I try to run the code, I get an error as follows:
Traceback (most recent call last):
... line 20, in lorentz_deriv
def lorentz_deriv((x, y, z), t0, sigma=10., beta=8./3, rho=28.0):
ValueError: need more than 1 value to unpack
Any ideas?
Thanks!
△ ▽
• Reply •
Cesc Fangs • 4 months agoHi Jake,
amazing tutorial!!When i try to save the animation as mp4,i got "UserWarning: MovieWriter ffmpegunavailable", and i‘m pretty sure the ffmpeg installation was successful, how can i deal withit?
△ ▽
• Reply •
Cesc Fangs • 4 months ago> Cesc Fangs
The thing is i can run it with ipy notebook, however when i use sublime text, theerror occurs, i think it's something like environment path problems
△ ▽
• Reply •
Tim Burton • a year agogreat animation...but when I tried to run it locally in IPython (with python 3.4) it erred outon line 14 "invalid syntax" ???
△ ▽
eldada • a year agoThis is a fantastic tutorial (like many others I found in this blog)!I just merged this demo another one of yours (http://jakevdp.github.io/blog/... ) - this isboth beautiful and fun as well as very useful!Many thanx!
One suggestion for the code -
The lines:# set up lines and pointslines = sum([ax.plot([], [], [], '-', c=c) for c in colors], [])pts = sum([ax.plot([], [], [], 'o', c=c) for c in colors], [])
Share ›
Share ›
Share ›
Share ›
Share ›
• Reply •
Assume the `sum` function is not overloaded, which is often not the case in scientificprogramming with python (e.g. %pylab). An alternative code which does not rely on the`sum` function:lines = [l for c in colors for l in ax.plot([], [], [], '-', c=c)]pts = [pt for c in colors for pt in ax.plot([], [], [], 'o', c=c)]
△ ▽
• Reply •
jakevdp • a year agoMod > eldada
Thanks! The ``sum`` overloading is one of the many reasons that the IPython teamis deprecating %pylab in favor of %matplotlib, which doesn't do any silentoverwriting of built-in functions. I'd recommend using the latter in the future.
△ ▽
• Reply •
David P. Sanders • 2 years ago
see more
This is just amazingly beautiful! Probably the best animation out there of this stunningobject!
Let me comment on the mathematics:You say that there are "two locations in the space that seem to draw in all paths". In youranimation it indeed seems that these two locations are in the center of some circle-likeregions.
There are indeed two special points at the centers of those regions, but they are *unstable*fixed points, and hence are repellers, not attractors! Once a trajectory spends enough timenear one of those points, it will be ejected in a perpendicular direction and wind around thetwo "lobes".To see this, it's probably easier to run a single trajectory for more time. To *prove* it, ofcourse, is a different story (and actually very difficult -- it was done in 2002 by WarwickTucker).
In fact, each of those fixed points is (if I remember correctly) a so-called "saddle--focus"."Focus" means that there is a two-dimensional object like a plane (the so-called "stablemanifold") where the trajectory approaches the fixed point asymptotically in a spiral; this is
△ ▽
• Reply •
David P. Sanders • 2 years ago> David P. Sanders
OK, I was wrong. The two points at the centres of the "wings" (or "lobes", as I called them) in fact havean *incoming* one-dimensional stable direction, and an *unstable* two-dimensionalsubspace (for the linearised system) and hence a two-dimensional unstablemanifold. However, they are "only slightly unstable", which is why a trajectoryspends a long time winding around them before it escapes. Apologies for theconfusion!
I did the analytical stability calculations with sympy. When I finally get round tolearning to use some blogging software, I'll post it!
△ ▽
Share ›
Share ›
Share ›
Share ›
Is Seattle Really Seeing an Uptick InCycling?14 comments • a year ago
AvatarJim Boyle — I am really intrigued by yourcasual comment to use random forests forfurther analysis. I have …
Kernel Density Estimation in Python21 comments • 2 years ago
AvatarAshish — Absolutely amazing write-up.Helped a lot. Great summary andcomparison! Can you explain what …
A Simple Animation: The Magic Triangle6 comments • 2 years ago
AvatarShani Hadiyanto Pribadi — "a slightlypuzzling rearrangement of shapes into twodifferent triangles." The trick is …
Numba vs. Cython: Take 252 comments • 2 years ago
AvatarSturla Molden — Some things to rememberwhen you use Fortran and f2py: 1. Alwayspass a …
ALSO ON PYTHONIC PERAMBULATIONS
△ ▽
• Reply •
jakevdp • 2 years agoMod > David P. Sanders
Thanks for the info! I must admit I haven't looked closely at the theorybehind this... it's good to have my claims double-checked :)
△ ▽
• Reply •
tjc • 2 years agoWhoops. Sorry. My bad. was running in a pylab context. 'sum' works.
△ ▽
• Reply •
Cam DP • 2 years agoVery pretty. Thanks for sharing!
△ ▽
• Reply •
Lywx • 2 years agoThat is a very high quality demostration of matplotlib in 3D.
△ ▽
• Reply •
Emi • 2 years agoWonderful!!!! The students can now see the chaotic evolution of this system, and whatsensitive dependence on initial conditions means.
△ ▽
WHAT'S THIS?
Subscribe✉ Add Disqus to your sited Privacyὑ�
Share ›
Share ›
Share ›
Share ›
Share ›
Recent PostsFast LombScargle Periodograms in Python (https://jakevdp.github.io/blog/2015/06/13/lombscargleinpython/)Optimizing Python in the Real World: NumPy, Numba, and the NUFFT(https://jakevdp.github.io/blog/2015/02/24/optimizingpythonwithnumpyandnumba/)The Hipster Effect: An IPython Interactive Exploration (https://jakevdp.github.io/blog/2014/11/11/thehipstereffectinteractive/)How Bad Is Your Colormap? (https://jakevdp.github.io/blog/2014/10/16/howbadisyourcolormap/)On Frequentism and Fried Chicken (https://jakevdp.github.io/blog/2014/09/02/onfrequentismandfriedchicken/)
Follow @jakevdp 5,389 followers
Copyright © 20122015 Jake Vanderplas Powered by Pelican (http://getpelican.com)