Friday, February 8, 2013

Changing the viewing angle of a Matplotlib plot from command line

One annoying feature/bug of working with IPython in the notebook environment is that, when it draws a graphic for you, it freezes the image so that it's no longer possible to interact with it. What to do if, for example, you're plotting a 3d surface, and the default viewing angle doesn't display what you think of as the interesting features of the surface?

Thanks to a nice question on stackexchange, I now know how to not settle for the defaults.

Let's use a specific example: here's the graph of a function which I want to plot:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
sigmoid = lambda x,y: 1/sqrt(1 + 2*exp(20.1-27*(x**2 + y**2)))
ts = arange(0,1.001,.01)
fig = plt.figure()
ax = fig.gca(projection='3d')
(XX,YY) = meshgrid(ts,ts)
ZZ = vectorize(sigmoid)(XX,YY)
ax.plot_surface(XX,YY,ZZ,rstride = 5, cstride = 5, cmap = cm.jet)

This produces the following graphic:
Now, this isn't awful, but it's not the angle that I really want to be looking at this function from. What I'd really like is to be looking approximately down the line \(y = x \) and not be nearly so far "above" the plot.

The way to change this is to change the azim(uth) and elev(ation) attributes of the axis (the object called ax in the code above). Elevation refers to the angle between the top plane of the axis (the red stuff in the image) and the viewer's eye; in the picture above, it's about 30 degrees. (Python uses degrees instead of radians for these parameters, btw.) Azimuth refers to the direction that the viewer is facing, but be careful! In the image above, we're looking along the line \(y = - \frac{1}{\sqrt{3}} x \), which is a 120-degree rotation from the \(x\)-axis; however, if you type in ax.azim you'll get -60 out, not 120. That's because ax.azim is the angular position of the viewer, and not of their gaze.

ax.plot_surface(XX,YY,ZZ,rstride = 3, cstride = 3, cmap = cm.jet)
ax.view_init(azim = 180+40,elev = 22) 



I've adjusted the rstride and cstride parameters also, which determines how densely spaced the grid lines on the surface are. Notice how in this image, our view goes out along the line with slope \( \tan 40^\circ \), corresponding to the azimuth entered above.

2 comments: