================ by Jawad Haider
Chpt 4 - Visualization with Matplotlib¶
13 - Three-Dimensional Plotting in Matplotlib¶
- Three-Dimensional Plotting in Matplotlib
- Three-Dimensional Points and Lines
- Three-Dimensional Contour Plots
- Wireframes and Surface Plots
- Surface Triangulations
Three-Dimensional Plotting in Matplotlib¶
Matplotlib was initially designed with only two-dimensional plotting in mind. Around the time of the 1.0 release, some three-dimensional plotting utilities were built on top of Matplotlib’s two-dimensional display, and the result is a convenient (if somewhat limited) set of tools for three-dimensional data visualization. We enable three-dimensional plots by importing the mplot3d toolkit, included with the main Matplotlib installation
With this 3D axes enabled, we can now plot a variety of three-dimensional plot types. Three-dimensional plotting is one of the functionalities that benefits immensely from viewing figures interactively rather than statically in the notebook; recall that to use interactive figures, you can use %matplotlib notebook rather than %matplotlib inline when running this code.
Three-Dimensional Points and Lines¶
The most basic three-dimensional plot is a line or scatter plot created
from sets of (x,y, z) triples. In analogy with the more common
two-dimensional plots discussed earlier, we can create these using the
ax.plot3D
and ax.scatter3D
functions. The call signature for these
is nearly identical to that of their two-dimensional counterparts, so
you can refer to “Simple Line Plots” and “Simple Scatter Plots” for
more information on controlling the output.
ax =plt.axes(projection='3d')
# data for 3d line
zline=np.linspace(0,15,1000)
xline=np.sin(zline)
yline=np.cos(zline)
ax.plot3D(xline,yline,zline,'gray')
# data for 3d scatter points
zdata=15*np.random.random(100)
xdata=np.sin(zdata)+0.1*np.random.randn(100)
ydata=np.cos(zdata)+0.1*np.random.randn(100)
ax.scatter3D(xdata,ydata,zdata, c=zdata, cmap='Greens');
<IPython.core.display.Javascript object>
Three-Dimensional Contour Plots¶
Analogous to the contour plots we explored in “Density and Contour
Plots”, mplot3d contains tools to create three-dimensional relief plots
using the same inputs. Like two-dimensional ax.contour
plots,
ax.contour3D
requires all the input data to be in the form of
two-dimensional regular grids, with the Z data evaluated at each point.
Here we’ll show a three-dimensional contour diagram of a
three-dimensional sinusoidal function
def f(x,y):
return np.sin(np.sqrt(x**2+y**2))
x=np.linspace(-6,6,30)
y=np.linspace(-6,6,30)
X,Y=np.meshgrid(x,y)
Z=f(X,Y)
fig=plt.figure()
ax=plt.axes(projection='3d')
ax.contour3D(X,Y,Z, 50,cmap='binary')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z');
<IPython.core.display.Javascript object>
Sometimes the default viewing angle is not optimal, in which case we can use the view_init method to set the elevation and azimuthal angles. In this example (the result of which is shown below, we’ll use an elevation of 60 degrees (that is, 60 degrees above the x-y plane) and an azimuth of 35 degrees (that is, rotated 35 degrees counter-clockwise about the z-axis):
<IPython.core.display.Javascript object>
Wireframes and Surface Plots¶
Two other types of three-dimensional plots that work on gridded data are wireframes and surface plots. These take a grid of values and project it onto the specified three- dimensional surface, and can make the resulting three-dimensional forms quite easy to visualize. Here’s an example using a wireframe
fit = plt.figure()
ax=plt.axes(projection='3d')
ax.plot_wireframe(X,Y,Z, color='black')
ax.set_title('WireFrame');
<IPython.core.display.Javascript object>
A surface plot is like a wireframe plot, but each face of the wireframe is a filled poly‐ gon. Adding a colormap to the filled polygons can aid perception of the topology of the surface being visualized
fig= plt.figure()
ax=plt.axes(projection='3d')
ax.plot_surface(X,Y,Z, rstride=1, cstride=1,
cmap='viridis', edgecolor='none')
ax.set_title('Surface');
<IPython.core.display.Javascript object>
Note that though the grid of values for a surface plot needs to be two-dimensional, it need not be rectilinear. Here is an example of creating a partial polar grid, which when used with the surface3D plot can give us a slice into the function we’re visualiz‐ ing
fig = plt.figure()
r = np.linspace(0, 6, 20)
theta = np.linspace(-0.9 * np.pi, 0.8 * np.pi, 40)
r, theta = np.meshgrid(r, theta)
X = r * np.sin(theta)
Y = r * np.cos(theta)
Z = f(X, Y)
ax = plt.axes(projection='3d')
ax.plot_surface(X, Y, Z, rstride=1, cstride=1,
cmap='viridis', edgecolor='none');
<IPython.core.display.Javascript object>
Surface Triangulations¶
For some applications, the evenly sampled grids required by the preceding routines are overly restrictive and inconvenient. In these situations, the triangulation-based plots can be very useful. What if rather than an even draw from a Cartesian or a polar grid, we instead have a set of random draws?
theta= 2*np.pi*np.random.random(1000)
r=6*np.random.random(1000)
x=np.ravel(r*np.sin(theta))
y=np.ravel(r*np.cos(theta))
z=f(x,y)
<IPython.core.display.Javascript object>
<mpl_toolkits.mplot3d.art3d.Path3DCollection at 0x7f86f7843820>
This leaves a lot to be desired. The function that will help us in this case is ax.plot_trisurf, which creates a surface by first finding a set of triangles formed between adjacent points
fig=plt.figure()
ax=plt.axes(projection='3d')
ax.plot_trisurf(x,y,z, cmap='viridis',edgecolor='none')
<IPython.core.display.Javascript object>
<mpl_toolkits.mplot3d.art3d.Poly3DCollection at 0x7f86f7206460>
The result is certainly not as clean as when it is plotted with a grid, but the flexibility of such a triangulation allows for some really interesting three-dimensional plots. For example, it is actually possible to plot a three-dimensional Möbius strip using this, as we’ll see next.