You are on page 1of 9

PythonicPerambulations

(https://jakevdp.github.io/)
Musingsandramblingsthroughtheworldof
Pythonandbeyond
Atom(/atom.xml)
Search
Navigate

Archives(/archives.html)
HomePage(http://www.astro.washington.edu/users/vanderplas)

AnimatingtheLorenzSystemin3D
Feb16,2013
OneofthethingsIreallyenjoyaboutPythonishoweasyitmakesittosolveinterestingproblemsandvisualize
thosesolutionsinacompellingway.I'vedoneseveralpostsoncreatinganimationsusingmatplotlib'srelatively
newanimationtoolkit(http://matplotlib.sourceforge.net/api/animation_api.html):(someexamplesareachaotic
doublependulum(/blog/2012/08/18/matplotlibanimationtutorial/),thecollisionsofparticlesinabox
(/blog/2012/08/18/matplotlibanimationtutorial/),thetimeevolutionofaquantummechanicalwavefunction
(/blog/2012/09/05/quantumpython/),andevenascenefromtheclassicvideogame,SuperMarioBros.
(/blog/2013/01/13/hackingsupermariobroswithpython/)).
Recently,areadercommented(/blog/2012/08/18/matplotlibanimationtutorial/#comment799781196)asking
whetherImightdoa3Danimationexample.Matplotlibhasadecent3Dtoolkitcalledmplot3D
(http://matplotlib.org/mpl_toolkits/mplot3d/index.html),andthoughIhaven'tpreviouslyseenitusedinconjunction
withtheanimationtools,there'snothingfundamentalthatpreventsit.
Atthecommenter'ssuggestion,Idecidedtotrythisoutwithasimpleexampleofachaoticsystem:theLorenz
equations.

SolvingtheLorenzSystem
TheLorenzEquations(http://en.wikipedia.org/wiki/Lorenz_system)areasystemofthreecoupled,firstorder,
nonlineardifferentialequationswhichdescribethetrajectoryofaparticlethroughtime.Thesystemwasoriginally
derivedbyLorenzasamodelofatmosphericconvection,butthedeceptivesimplicityoftheequationshavemade
themanoftenusedexampleinfieldsbeyondatmosphericphysics.
Theequationsdescribetheevolutionofthespatialvariablesx ,y ,andz,giventhegoverningparameters , ,
and ,throughthespecificationofthetimederivativesofthespatialvariables:
dx/dt = (y x)
dy/dt = x( z) y
dz/dt = xy z

Theresultingdynamicsareentirelydeterministicgivingastartingpoint(x0 , y0 , z0 ) andatimeintervalt .Though


itlooksstraightforward,forcertainchoicesoftheparameters(, , ) ,thetrajectoriesbecomechaotic,andthe
resultingtrajectoriesdisplaysomesurprisingproperties.

Thoughnogeneralanalyticsolutionexistsforthissystem,thesolutionscanbecomputednumerically.Python
makesthissortofproblemveryeasytosolve:onecansimplyuseScipy'sinterfacetoODEPACK
(https://computation.llnl.gov/casc/odepack/odepack_home.html),anoptimizedFortranpackageforsolving
ordinarydifferentialequations.Here'showtheproblemcanbesetup:
import numpy as np
from 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 vector
t = np.linspace(0, 3, 1000) # one thousand time steps
x_t = integrate.odeint(lorentz_deriv, x0, t)

That'sallthereistoit!

Visualizingtheresults
Nowthatwe'vecomputedtheseresults,wecanusematplotlib'sanimationand3Dplottingtoolkitstovisualizethe
trajectoriesofseveralparticles.BecauseI'vedescribedtheanimationtoolsindepthinapreviouspost
(/blog/2012/08/18/matplotlibanimationtutorial/),Iwillskipthatdiscussionhereandjumpstraightintothecode:
LorenzSystemlorentz_animation.pydownload(/downloads/code/lorentz_animation.py)
import numpy as np
from scipy import integrate
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.colors import cnames
from 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 15


np.random.seed(1)
x0 = -15 + 30 * np.random.random((N_trajectories, 3))
# Solve for the trajectories
t = 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 animation


fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1], projection='3d')
ax.axis('off')
# choose a different color for each trajectory
colors = plt.cm.jet(np.linspace(0, 1, N_trajectories))
# set up lines and points
lines = sum([ax.plot([], [], [], '-', c=c)
for c in colors], [])
pts = sum([ax.plot([], [], [], 'o', c=c)
for c in colors], [])
# prepare the axes limits
ax.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 frame
def 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 numbe
r
def 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', 'libx26
4'])
plt.show()

Theresultinganimationlookssomethinglikethis:

0:33
Noticethattherearetwolocationsinthespacethatseemtodrawinallpaths:thesearethesocalled"Lorenz
attractors",andhavesomeinterestingpropertieswhichyoucanreadaboutelsewhere.Thequalitative
characteristicsoftheseLorenzattractorsvaryinsomewhatsurprisingwaysastheparameters(, , ) are
changed.Ifyouaresoinclined,youmaywishtodownloadtheabovecodeandplaywiththesevaluestoseewhat
theresultslooklike.
IhopethatthisbriefexercisehasshownyouthepowerandflexibilityofPythonforunderstandingandvisualizing
alargearrayofproblems,andperhapsgivenyoutheinspirationtoexploresimilarproblems.
Happycoding!
PostedbyJakeVanderplasFeb16,2013
Tweet

21

Comments
21Comments
Recommend 2

PythonicPerambulations

Share

Login

SortbyBest

Jointhediscussion
tjc 2yearsago

Hi Jake,
I was a bit perplexed by the 'sum' on lines 35 and 37. Crashes as is, for me. Did you mean:

# set up lines and points


lines = [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 Share

PrahasDavidNafissian>tjc 3monthsago

Absolutely correct correction! And on the Mac, take out the blit=true near the
bottom!

Reply Share

uriel_sandoval>tjc 2yearsago

Probably you are using a notebook with pylab inline, and that calls you the np.sum
function instead of the buit-in python sum.

Reply Share

BenRoot 2yearsago

It is Lorenz, not lorentz


1

Reply Share

jakevdp

Mod >BenRoot

2yearsago

Thanks - fixed that in all but the URL

Reply Share

GaelVaroquaux 2yearsago

Hey Jake,
Have you ever played with the Mayavi interactive examples of the Lorentz system:
http://docs.enthought.com/maya...
and
http://docs.enthought.com/maya...
I my opinion, what's really real with the second one, which is slightly more complex, is that
you can change parameters interactively and watch the system evolve.
1

Reply Share

jakevdp

Mod >GaelVaroquaux

2yearsago

Hey Gael,
Thanks for the links! Mayavi seems to have some pretty slick 3D tools! Maybe I'll
spend a little more time playing around with that.

Reply Share

PrahasDavidNafissian 3monthsago

Hello -- is there a way to generate a log file with the x,y,z points generated by this algorithm?
Thanks!

Reply Share

PrahasDavidNafissian 3monthsago

IGNORE -- 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 Share

CescFangs 4monthsago

Hi Jake,
amazing tutorial!!
When i try to save the animation as mp4,i got "UserWarning: MovieWriter ffmpeg
unavailable", and im pretty sure the ffmpeg installation was successful, how can i deal with
it?

Reply Share

CescFangs>CescFangs 4monthsago

The thing is i can run it with ipy notebook, however when i use sublime text, the
error occurs, i think it's something like environment path problems

Reply Share

TimBurton ayearago

great animation...but when I tried to run it locally in IPython (with python 3.4) it erred out
on line 14 "invalid syntax" ???

Reply Share

eldada ayearago

This 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 is
both beautiful and fun as well as very useful!
Many thanx!
One suggestion for the code The lines:
# set up lines and points
lines = sum([ax.plot([], [], [], '-', c=c) for c in colors], [])
pts = sum([ax.plot([], [], [], 'o', c=c) for c in colors], [])

Assume the `sum` function is not overloaded, which is often not the case in scientific
programming 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 Share

jakevdp

Mod >eldada

ayearago

Thanks! The ``sum`` overloading is one of the many reasons that the IPython team
is deprecating %pylab in favor of %matplotlib, which doesn't do any silent
overwriting of built-in functions. I'd recommend using the latter in the future.

Reply Share

DavidP.Sanders 2yearsago

This is just amazingly beautiful! Probably the best animation out there of this stunning
object!
Let me comment on the mathematics:
You say that there are "two locations in the space that seem to draw in all paths". In your
animation it indeed seems that these two locations are in the center of some circle-like
regions.
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 time
near one of those points, it will be ejected in a perpendicular direction and wind around the
two "lobes".
To see this, it's probably easier to run a single trajectory for more time. To *prove* it, of
course, is a different story (and actually very difficult -- it was done in 2002 by Warwick
Tucker).
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 "stable
manifold") where the trajectory approaches the fixed point asymptotically in a spiral; this is
seemore

Reply Share

DavidP.Sanders>DavidP.Sanders 2yearsago

OK, I was wrong.


The two points at the centres of the "wings" (or "lobes", as I called them) in fact have
an *incoming* one-dimensional stable direction, and an *unstable* two-dimensional
subspace (for the linearised system) and hence a two-dimensional unstable
manifold. However, they are "only slightly unstable", which is why a trajectory
spends a long time winding around them before it escapes. Apologies for the
confusion!
I did the analytical stability calculations with sympy. When I finally get round to
learning to use some blogging software, I'll post it!

Reply Share


jakevdp

Mod >DavidP.Sanders

2yearsago

Thanks for the info! I must admit I haven't looked closely at the theory
behind this... it's good to have my claims double-checked :)

Reply Share

tjc 2yearsago

Whoops. Sorry. My bad. was running in a pylab context. 'sum' works.

Reply Share

CamDP 2yearsago

Very pretty. Thanks for sharing!

Reply Share

Lywx 2yearsago

That is a very high quality demostration of matplotlib in 3D.

Reply Share

Emi 2yearsago

Wonderful!!!! The students can now see the chaotic evolution of this system, and what
sensitive dependence on initial conditions means.

Reply Share

WHAT'STHIS?

ALSOONPYTHONICPERAMBULATIONS

IsSeattleReallySeeinganUptickIn
Cycling?

KernelDensityEstimationinPython

14commentsayearago

AvatarAshish Absolutely amazing write-up.


Helped a lot. Great summary and
comparison! Can you explain what

21comments2yearsago

AvatarJimBoyle I am really intrigued by your


casual comment to use random forests for
further analysis. I have

ASimpleAnimation:TheMagicTriangle

Numbavs.Cython:Take2

6comments2yearsago

52comments2yearsago

AvatarShaniHadiyantoPribadi "a slightly


puzzling rearrangement of shapes into two
different triangles." The trick is

AvatarSturlaMolden Some things to remember


when you use Fortran and f2py: 1. Always
pass a

Subscribe

AddDisqustoyoursite

Privacy

RecentPosts
FastLombScarglePeriodogramsinPython(https://jakevdp.github.io/blog/2015/06/13/lombscargleinpython/)
OptimizingPythonintheRealWorld:NumPy,Numba,andtheNUFFT
(https://jakevdp.github.io/blog/2015/02/24/optimizingpythonwithnumpyandnumba/)
TheHipsterEffect:AnIPythonInteractiveExploration(https://jakevdp.github.io/blog/2014/11/11/thehipster
effectinteractive/)
HowBadIsYourColormap?(https://jakevdp.github.io/blog/2014/10/16/howbadisyourcolormap/)
OnFrequentismandFriedChicken(https://jakevdp.github.io/blog/2014/09/02/onfrequentismandfriedchicken/)
Follow@jakevdp

5,389followers

Copyright20122015JakeVanderplasPoweredbyPelican(http://getpelican.com)

You might also like