Josh Pinto
Josh Pinto

Reputation: 1573

How do I create a 3D line plot in matplotlib from the data in arrays?

I have numerically solved the Lorenz equations using SciPy with the script:

# Lorenz Equations SciPy solver
import numpy as np
from scipy import integrate
from math import cos
from matplotlib import pyplot as plt
a, b = 0, 100
sigma, rho, beta = 10, 28, 8/3
N = 1000000
h = (b-a) / float(N)

def solvr(Y, t):
    return [sigma*(Y[1]-Y[0]), Y[0]*(rho-Y[2])-Y[1], Y[0]*Y[1]-beta*Y[2]]

t    = np.arange(a, b, h)
asol = integrate.odeint(solvr, [0, 1, 1], t)
x    = asol[:,0]
y    = asol[:,1]
z    = asol[:,2]

Now what I would like to do is plot x, y and z (which are all Numpy ndarrays, if you are unsure) against each other in a 3D line (or wireframe) plot. I think this would have to be done using matplotlib, but I am not picky, so long as you give me a solution that will plot the data in 3D I do not care what modules I need to import.

Upvotes: 3

Views: 3579

Answers (2)

uhoh
uhoh

Reputation: 3745

Here is the Lorenz attractor both in 3D and animated. The script is in the following link (along with many goodies) in Jake VanderPlas' Pythonic Perambulations. You can learn a lot by going line-by-line through the script - it's an elegant use of matplotlib objects.

https://jakevdp.github.io/blog/2013/02/16/animating-the-lorentz-system-in-3d/

I added these two lines just before return in the animate function, and then used ImageJ to import the "image stack" and save the "animated GIF":

fname = "Astro_Jake_" + str(i+10000)[1:]
fig.savefig(fname)

Here is Jake's original with two small modifications https://pastebin.com/qWkLft0K (the blit=True used to be necessary for me on macOS but it doesn't seem to be any more)

  1. get rid of the explicit tuple inside lorenz_deriv() and unpack it in the lines below
  2. add a True/False toggle - either it makes a nice animation in real time, or it saves ~1000 small .png files for later building a GIF.

Astro Jake

Here is a minimal, simplified example of plotting lines in 3D based on the above:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from scipy.integrate import odeint as ODEint

def lorentz_deriv(xyz, t0, sigma=10., beta=8./3, rho=28.0):
    """Compute the time-derivative of a Lorentz system."""
    x, y, z = xyz # unpack here
    return [sigma * (y - x), x * (rho - z) - y, x * y - beta * z]

x = np.linspace(0, 20, 1000)
y, z = 10.*np.cos(x), 10.*np.sin(x) # something simple

fig = plt.figure()
ax = fig.add_subplot(1,2,1,projection='3d')
ax.plot(x, y, z)

# now Lorentz
times = np.linspace(0, 4, 1000) 

start_pts = 30. - 15.*np.random.random((20,3))  # 20 random xyz starting values

trajectories = []
for start_pt in start_pts:
    trajectory = ODEint(lorentz_deriv, start_pt, times)
    trajectories.append(trajectory)

ax = fig.add_subplot(1,2,2,projection='3d')
for trajectory in trajectories:
    x, y, z = trajectory.T  # transpose and unpack 
    # x, y, z = zip(*trajectory)  # this also works!
    ax.plot(x, y, z)

plt.show()

screen shot of simplified 3D Lorenz

Upvotes: 8

norlesh
norlesh

Reputation: 1841

There is a brief example / tutorial on how to do wireframe plots (as well as 3d scatter) at the matplotlib site http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html#wireframe-plots

Upvotes: 3

Related Questions