We'll start with a quick introduction to using matplotlib with the IPython notebook, and run through some examples of object oriented matplotlib.
The IPython notebook is designed to be used seamlessly with matplotlib.
When you start the notebook, you can type
[laptop]% ipython notebook --pylab
or
[laptop]% ipython notebook --pylab inline
The result of the first is to set up the notebook so that matplotlib figures can be used interactively within the notebook. The result of the second is that figures are embedded statically within the notebook page.
If you start the notebook without either of these annotations, you can enter the
pylab
or pylab inline
mode using one of IPython's magic functions. For
example, you can type in a notebook cell:
In [ ]: %pylab
or
In [ ]: %pylab inline
respectively, to get the same result as above.
Note that once you've activated one of these backends, you now (MPL: 1.3.0, IPython 1.1.0) can switch this mid-session by just using those commands, but at some point prior to these versions it wasn't possible. In
order to switch the backend in that case, you must restart the kernel, using either the option in the
Kernel
menu above, or the shortcut
Ctrl-m .
(for a list of available shortcuts, see the help menu: Ctrl-m h
)
Once you have restarted the kernel, you can change the pylab mode
and re-run your code.
Take a moment and see the effect of creating a simple plot using either pylab mode or pylab inline mode:
%pylab inline
from matplotlib import rcParams
print rcParams['backend']
x = np.linspace(0, 10, 1000)
plt.plot(x, np.sin(x))
If your plots show an ugly gray background, you can switch it off like so:
matplotlib.rcParams['figure.facecolor'] = 'w'
x = np.linspace(0, 10, 1000)
plt.plot(x, np.sin(x))
Matplotlib was originally designed to have an interface similar to that of matlab. For this reason, the library maintains pointers to the currently active figure and axes, and makes simple plots straightforward to create. For example:
import pylab # note that this import is automatic in `%pylab` or `%pylab inline` mode
pylab.figure() # this is optional: if you just call plot(), a figure will be created
pylab.plot(x, np.sin(x))
pylab.title('plot 1: sine')
pylab.figure()
pylab.plot(x, np.cos(x))
pylab.title('plot 2: cosine')
This is fine for simple plots, but when you start wanting to do more powerful things, it can get a little bit tricky. A better way to approach it might be like this:
import matplotlib.pyplot as plt # Again, in pylab mode this import happens automatically
fig1 = plt.figure()
ax1 = fig1.add_subplot(1, 1, 1)
ax1.plot(x, np.sin(x))
ax1.set_title('sine')
fig2 = plt.figure()
ax2 = fig2.add_subplot(1, 1, 1)
ax2.plot(x, np.cos(x))
ax2.set_title('cosine')
In this instance, all the typing might seem a bit gratuitous. But as our plot objects get more and more complicated, explicitly keeping track of the figures and axes will make our lives increasingly easier.
Also, because we don't care about which plot is active at any given time, it gives us the freedom to write code in any order. The following generates the same plot output as the previous snippet, but makes more clear the relationship between the two figures:
fig1 = plt.figure()
fig2 = plt.figure()
ax1 = fig1.add_subplot(1, 1, 1)
ax2 = fig2.add_subplot(1, 1, 1)
ax1.plot(x, np.sin(x))
ax2.plot(x, np.cos(x))
ax1.set_title('sine')
ax2.set_title('cosine')
One thing that will be important to recognize for this tutorial is that each and every
plot element in matplotlib has an associated object that can be passed around and
manipulated. To see this, we'll use the non-inline pylab mode, so you may have to
type Ctrl-m .
and restart the kernel:
%pylab
x = np.linspace(0, 10, 1000)
fig, ax = plt.subplots()
lines = ax.plot(x, np.sin(x))
print lines
Now that we've created the plot, we can adjust the attributes of the Line2D
instance. In general, any keyword in the plot
command has an associated
set_
command.
After setting the different parameters, we can call the draw()
method of
the figure canvas to make the plot reflect the changes.
lines[0].set_color('green')
fig.canvas.draw()
lines[0].set_linewidth(3)
fig.canvas.draw()
Other plot elements can be manipulated as well. For example, text:
txt = plt.text(4, 0.5, "Hello")
txt.set_size(20)
txt.set_color('blue')
fig.canvas.draw()
You can also dynamically change the location of the text:
txt.set_x(7)
txt.set_y(-0.5)
fig.canvas.draw()
Similarly, you can even dynamically change the locations of each point in the line! For example, changing the y data looks like this:
lines[0].set_ydata(np.sin(2 * x))
fig.canvas.draw()
This sort of operation can be used to create simple animations (this does not work for the QT backend on OSX) -- for example:
for i in range(100):
lines[0].set_ydata(np.sin(x + 0.1 * i))
fig.canvas.draw()
Please note that in general, this is not a stable way to create animations in
matplotlib. For this purpose, the animation
submodule should be used.
We'll talk about this a little bit later.
Different plot elements have different setter attributes. IPython can be a useful tool in figuring these things out: use the tab-completion to determine what can be set. Many of these values are internal parameters that you probably will not need, but some of them can give you interesting results:
txt.set_