Skip to main content

Section 1.4 Matplotlib and 3D graphing

Now that we have some experience making 2D graphs, let’s learn how to make 3D graphs. Note that we can graph both curves and surfaces in 3D. If you have taken a multivariable class hopefully you remember that surfaces arise as solutions to equations of three variables, while points on a space curve are parametric equations or vector-valued functions. The code for the points on a space curve is a little more straightforward so we will start with those examples.

Subsection 3D axes

First, for 3D graphs we will need to add 3D plots to our figure using the keyword projection='3d'. Read through and run the code below to see the default 3D axes.

Subsection Parametric Curves in 3D

Matplotlib graphs 3D curves by plotting points and connecting the dots. The \(x\text{,}\) \(y\text{,}\) and \(z-\)coordinates are still given by numpy arrays and then plotted on the axes.
Run the code below to graph the equation of a line between the points \((1,1,1)\) and \((2,3,4)\text{.}\)

You Try 1.19.

Edit the above code to graph the equation of a line between the points \((1,2,3)\) and \((4,5,6)\text{.}\)

You Try 1.20.

Edit the above code to add a third number to each numpy array. What happens? Can you explain what plot() just graphed?
We can also graph curves by making coordinates dependent on another. For example, the curve below looks like a parabola in the \(z\)-direction above the shadow \(y=x\)
As before, we need enough input points to get a smooth curve.
Parametric curves in 3D are just like 2D (see (Section 1.3)) with an added \(z\)-coordinate. For example, we can graph a horizontal circle at \(z=1\) using
  • \(\displaystyle x=\cos(t)\)
  • \(\displaystyle y=\sin(t)\)
  • \(\displaystyle z=1\)

You Try 1.21.

Play with the above code for \(x\text{,}\) \(y\text{,}\) and \(z\) to see what other interesting curves you can create.
In 3-space can you graph
  • a line?
  • a spiral?
  • a different circle?

Subsection Surfaces and scatterplots in 3D

To graph a surface or 3D scatterplot, we will need two-dimensional numpy arrays for all of our inputs and outputs. As a shortcut we can create 1D arrays for the \(x\) and \(y\) inputs first, then use NumPy’s function meshgrid() to create a coordinate grid of inputs (two 2D arrays). Last we define our outputs on that coordinate grid.
The function scatter() will plot a scatterplot just like in 2D. The function plot_surface() plots the points and connect those dots with a surface. Just like we need enough points to get a curve that looks smooth, we will need enough points to get a surface that looks smooth.

You Try 1.22.

Run the code below trying both the command plot_surface() (current default) and scatter() to see the difference.

You Try 1.23.

For the surface, increase the step in each input and run the above code again. When does the surface start to look “polygonal” instead of smooth?

You Try 1.24.

Modify the above code to graph the surface \(z=sin(y)\text{.}\) Choose a reasonable range of inputs that shows the important features of the graph.

You Try 1.25.

Change the surface to \(z=sin(xy)\text{.}\) What step size is needed to make the input window [-2,2] and [-2,2] display a smooth surface?
As in the 2D case, the function scatter() plots the points without connecting the dots.

Subsection Axes and Labels

Adding titles or labels to our 3D axes uses the same commands as in 2D. the commands set_title("title_here"), set_xlabel("label_here"), set_ylabel("label_here").

You Try 1.26.

In the above code, use parallel syntax to add a label to the \(z\)-axis.
Note that the default viewing window makes the \(x\)-axis positive left to right and \(y\)-axis positive front to back. Something new in the 3D setting, however, is the ability to choose our viewing angle for the 3D axes using view_init(elev= , azim=, roll=).

You Try 1.27.

In the code below, play with the values for elev, azim and roll.
  • What does each change?
  • What custom viewing angle do you think showcases this particular surface the best?

Subsection Plotting Multiple Surfaces

Unfortunately Matplotlib does NOT actually graph in 3D, but paints each surface in a 2D projection, one on top of the other, which can cause the resulting graphs to look weird. Sometimes it is enough to change the viewing angle.

You Try 1.28.

In the above code add a second surface to your graph using Z2 for the new outputs and ax.plot_surface(X,Y,Z2).
  • Can you find a viewing angle where both surfaces look good?
  • Can you find a viewing angle where they don’t quite look right?
A possible workaround involves making the surfaces transparent and plotting their intersection as well. If you find another workaround that is fairly simple and doesn’t involve “dark magic and paying with programmer souls” as one stack overflow user suggested, let us know and we can include it in future iterations of this book.

You Try 1.29.

Run the code below to see a Matplotlib 3D fail.
You can make your graphs transparent using the argument alpha = inside plot_surface.

You Try 1.30.

In the code above add alpha=0.5 after each of Z1, Z2, and Z3 inside plot_surface to see a partial fix. Play with values of alpha to see which transparency setting you prefer.
You can also graph the lines of intersection for each plane, which we will do later in the term.

Subsection Customizing

Like in 2D, we can customize our plots: the style, colors, markers, meshes, contours, line width, etc. There are many features available that we didn’t cover here, but hopefully you have enough to get you started with 3D graphing using Matplotlib in Python.
So how do you learn more?
Look up Matplotlib’s documentation on the web and find their page of examples, 3D plotting. Pick a 3D graph you want to learn to code and use the cell below to try it out. How is what you found different than what you learned in this section? Experiment by adjusting Matplotlib’s example code to see what happens.
This section gave us just an introduction to 3D graphing possibilities using Matplotlib in Python. We will continue to learn more about graphing as we move into using Python for matrix algebra.

Summary.

  • We can add 3D graphs and axes using the argument projection='3d' inside pyplot’s axes command.
  • We can plot curves using plot() and three numpy arrays representing the \(x\text{,}\) \(y\text{,}\) and \(z\)-coordinates for points on our curve.
  • We can use numpy.meshgrid() to create input coordinates on a grid and then use plot_surface() or scatter() to plot a surface or scatter plot on 3D axes.
  • As before we need enough points for plot_surface() or plot() to make smooth graphs.

Exercises Exercises

1.

The function meshgrid() has other uses, so it is nice to familiarize yourself with what it actually does. First make two small Numpy arrays, say one, X, with three entries and the other, Y, with five entries. Next make a meshgrid() of those two arrays and print the result. What do you notice?
  1. Experiment with different sizes of arrays X and Y. Explain in your own words what meshgrid does with the two arrays. Demonstrate with some example code.
  2. What happens if you multiply the arrays that result from meshgrid together? Demonstrate with some example code.

2.

In one figure create a gallery of examples containing at least one of each:
  • A curve in 3D
  • A suface in 3D
  • A scatterplot in 3D
Make sure your graphs are appropriately labelled for your reader.

3.

Look up Matplotlib’s documentation on the web and find their page of examples, 3D plotting. Pick a 3D graph you want to learn to code and try it out. Experiment with the code to make it your own. How is what you found different than what you learned in this section? Explain.

4.

NumPy’s meshgrid() will be used later to create a grid of points that we transform. Use meshgrid() to create a \(5 \times 5\) grid of x and y-values.
  1. Print out the arrays from meshgrid(). How does one array encode the increasing vs constant x-values? How does the other array encode the increasing vs constant y-values?
  2. Make a 2D scatterplot using just your two arrays from meshgrid(). Explain how this graph relates to your answer in part (a).
  3. Plot a \(5\times 5\) grid of vertical and horizontal lines in \(\mathbb{R}^2\) by extracting the appropriate rows and columns from your meshgrid().
     3 
    We will use a related approach in Section 2.3 to visualize matrix transformations.