"First we need to import the `matplotlib` library."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import matplotlib"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Matplotlib can output graphs using various backend graphics libraries, such as Tk, wxPython, etc. When running python using the command line, the graphs are typically shown in a separate window. In a Jupyter notebook, we can simply output the graphs within the notebook itself by running the `%matplotlib inline` magic command."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"%matplotlib inline\n",
"# matplotlib.use(\"TKAgg\") # use this instead in your program if you want to use Tk as your graphics backend."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now let's plot our first graph! :)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"plt.plot([1, 2, 4, 9, 5, 3])\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Yep, it's as simple as calling the `plot` function with some data, and then calling the `show` function!\n",
"\n",
"If the `plot` function is given one array of data, it will use it as the coordinates on the vertical axis, and it will just use each data point's index in the array as the horizontal coordinate.\n",
"You can also provide two arrays: one for the horizontal axis `x`, and the second for the vertical axis `y`:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [],
"source": [
"plt.plot([-3, -2, 5, 0], [1, 6, 4, 3])\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The axes automatically match the extent of the data. We would like to give the graph a bit more room, so let's call the `axis` function to change the extent of each axis `[xmin, xmax, ymin, ymax]`."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"plt.plot([-3, -2, 5, 0], [1, 6, 4, 3])\n",
"plt.axis([-4, 6, 0, 7])\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, let's plot a mathematical function. We use numpy's `linspace` function to create an array `x` containing 500 floats ranging from -2 to 2, then we create a second array `y` computed as the square of `x`."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import numpy\n",
"x = numpy.linspace(-2, 2, 500)\n",
"y = x**2\n",
"\n",
"plt.plot(x, y)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"That's a bit dry, let's add a title, and x and y labels, and draw a grid."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"plt.plot(x, y)\n",
"plt.title(\"Square function\")\n",
"plt.xlabel(\"x\")\n",
"plt.ylabel(\"y = x**2\")\n",
"plt.grid(True)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Line style and color"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"By default, matplotlib draws a line between consecutive points."
"The plot function returns a list of `Line2D` objects (one for each line). You can set extra attributes on these lines, such as the line width, the dash style or the alpha level. See the full list of attributes in [the documentation](http://matplotlib.org/users/pyplot_tutorial.html#controlling-line-properties)."
"Saving a figure to disk is as simple as calling [`savefig`](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.savefig) with the name of the file (or a file object). The available image formats depend on the graphics backend you use."
"A matplotlib figure may contain multiple subplots. These subplots are organized in a grid. To create a subplot, just call the `subplot` function, and specify the number of rows and columns in the figure, and the index of the subplot you want to draw on (starting from 1, then left to right, and top to bottom). Note that pyplot keeps track of the currently active subplot (which you can get a reference to by calling `plt.gca()`), so when you call the `plot` function, it draws on the *active* subplot.\n"
"If you need more complex subplot positionning, you can use `subplot2grid` instead of `subplot`. You specify the number of rows and columns in the grid, then your subplot's position in that grid (top-left = (0,0)), and optionally how many rows and/or columns it spans. For example:"
"If you need even more flexibility in subplot positioning, check out the [GridSpec documentation](http://matplotlib.org/users/gridspec.html)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Multiple figures\n",
"It is also possible to draw multiple figures. Each figure may contain one or more subplots. By default, matplotlib creates `figure(1)` automatically. When you switch figure, pyplot keeps track of the currently active figure (which you can get a reference to by calling `plt.gcf()`), and the active subplot of that figure becomes the current subplot."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [],
"source": [
"x = numpy.linspace(-1.4, 1.4, 30)\n",
"\n",
"plt.figure(1)\n",
"plt.subplot(211)\n",
"plt.plot(x, x**2)\n",
"plt.title(\"Square and Cube\")\n",
"plt.subplot(212)\n",
"plt.plot(x, x**3)\n",
"\n",
"plt.figure(2, figsize=(10, 5))\n",
"plt.subplot(121)\n",
"plt.plot(x, x**4)\n",
"plt.title(\"y = x**4\")\n",
"plt.subplot(122)\n",
"plt.plot(x, x**5)\n",
"plt.title(\"y = x**5\")\n",
"\n",
"plt.figure(1) # back to figure 1, current subplot is 212 (bottom)\n",
"plt.plot(x, -x**3, \"r:\")\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Pyplot's state machine: implicit *vs* explicit\n",
"So far we have used Pyplot's state machine which keeps track of the currently active subplot. Every time you call the `plot` function, pyplot just draws on the currently active subplot. It also does some more magic, such as automatically creating a figure and a subplot when you call `plot`, if they don't exist yet. This magic is convenient in an interactive environment (such as Jupyter).\n",
"\n",
"But when you are writing a program, *explicit is better than implicit*. Explicit code is usually easier to debug and maintain, and if you don't believe me just read the 2nd rule in the Zen of Python:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import this"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Fortunately, Pyplot allows you to ignore the state machine entirely, so you can write beautifully explicit code. Simply call the `subplots` function and use the figure object and the list of axes objects that are returned. No more magic! For example:"
"For consistency, we will continue to use pyplot's state machine in the rest of this tutorial, but we recommend using the object-oriented interface in your programs.\n",
"\n",
"## Pylab *vs* Pyplot *vs* Matplotlib\n",
"\n",
"There is some confusion around the relationship between pylab, pyplot and matplotlib. It's simple: matplotlib is the full library, it contains everything including pylab and pyplot.\n",
"\n",
"Pyplot provides a number of tools to plot graphs, including the state-machine interface to the underlying object-oriented plotting library.\n",
"\n",
"Pylab is a convenience module that imports matplotlib.pyplot and numpy in a single name space. You will find many examples using pylab, but it is no longer recommended (because *explicit* imports are better than *implicit* ones)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Drawing text\n",
"You can call `text` to add text at any location in the graph. Just specify the horizontal and vertical coordinates and the text, and optionally some extra attributes. Any text in matplotlib may contain TeX equation expressions, see [the documentation](http://matplotlib.org/users/mathtext.html) for more details."
"* Note: `ha` is an alias for `horizontalalignment`\n",
"\n",
"For more text properties, visit [the documentation](http://matplotlib.org/users/text_props.html#text-properties).\n",
"\n",
"It is quite frequent to annotate elements of a graph, such as the beautiful point above. The `annotate` function makes this easy: just indicate the location of the point of interest, and the position of the text, plus optionally some extra attributes for the text and the arrow."
"Matplotlib supports non linear scales, such as logarithmic or logit scales."
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [],
"source": [
"x = numpy.linspace(0.1, 15, 500)\n",
"y = x**3/numpy.exp(2*x)\n",
"\n",
"plt.figure(1)\n",
"plt.plot(x, y)\n",
"plt.yscale('linear')\n",
"plt.title('linear')\n",
"plt.grid(True)\n",
"\n",
"plt.figure(2)\n",
"plt.plot(x, y)\n",
"plt.yscale('log')\n",
"plt.title('log')\n",
"plt.grid(True)\n",
"\n",
"plt.figure(3)\n",
"plt.plot(x, y)\n",
"plt.yscale('logit')\n",
"plt.title('logit')\n",
"plt.grid(True)\n",
"\n",
"plt.figure(4)\n",
"plt.plot(x, y - y.mean())\n",
"plt.yscale('symlog', linthreshy=0.05)\n",
"plt.title('symlog')\n",
"plt.grid(True)\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Ticks and tickers\n",
"The axes have little marks called \"ticks\". To be precise, \"ticks\" are the *locations* of the marks (eg. (-1, 0, 1)), \"tick lines\" are the small lines drawn at those locations, \"tick labels\" are the labels drawn next to the tick lines, and \"tickers\" are objects that are capable of deciding where to place ticks. The default tickers typically do a pretty good job at placing ~5 to 8 ticks at a reasonable distance from one another.\n",
"\n",
"But sometimes you need more control (eg. there are too many tick labels on the logit graph above). Fortunately, matplotlib gives you full control over ticks. You can even activate minor ticks.\n",
"Plotting 3D graphs is quite straightforward. You need to import `Axes3D`, which registers the `\"3d\"` projection. Then create a subplot setting the `projection` to `\"3d\"`. This returns an `Axes3DSubplot` object, which you can use to call `plot_surface`, giving x, y, and z coordinates, plus optional attributes."
"You can draw lines simply using the `plot` function, as we have done so far. However, it is often convenient to create a utility function that plots a (seemingly) infinite line across the graph, given a slope and an intercept. You can also use the `hlines` and `vlines` functions that plot horizontal and vertical line segments.\n",
"Reading, generating and plotting images in matplotlib is quite straightforward.\n",
"\n",
"To read an image, just import the `matplotlib.image` module, and call its `imread` function, passing it the file name (or file object). This returns the image data, as a NumPy array. Let's try this with the `my_square_function.png` image we saved earlier."
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import matplotlib.image as mpimg\n",
"\n",
"img = mpimg.imread('my_square_function.png')\n",
"print img.shape, img.dtype"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We have loaded a 288x432 image. Each pixel is represented by a 4-element array: red, green, blue, and alpha levels, stored as 32-bit floats between 0 and1. Now all we need to do is to call `imshow`:"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"plt.imshow(img)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Tadaaa! You may want to hide the axes when you are displaying an image:"
"As we did not provide RGB levels, the `imshow` function automatically maps values to a color gradient. By default, the color gradient goes from blue (for low values) to red (for high values), but you can select another color map. For example:"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"collapsed": false,
"scrolled": false
},
"outputs": [],
"source": [
"plt.imshow(img, cmap=\"hot\")\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can also generate an RGB image directly:"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [],
"source": [
"img = numpy.empty((20,30,3))\n",
"img[:, :10] = [0, 0, 0.6]\n",
"img[:, 10:20] = [1, 1, 1]\n",
"img[:, 20:] = [0.6, 0, 0]\n",
"plt.imshow(img)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Since the `img` array is just quite small (20x30), when the `imshow` function displays it, it grows the image to the figure's size. By default it uses [bilinear interpolation](https://en.wikipedia.org/wiki/Bilinear_interpolation) to fill the added pixels. This is why the edges look blurry.\n",
"You can select another interpolation algorithm, such as copying the color of the nearest pixel:"
"Although matplotlib is mostly used to generate images, it is also capable of displaying animations, depending on the Backend you use. In a Jupyter notebook, we need to use the `nbagg` backend to use interactive matplotlib features, including animations. We also need to import `matplotlib.animation`."
"In this example, we start by creating data points, then we create an empty plot, we define the update function that will be called at every iteration of the animation, and finally we add an animation to the plot by creating a `FuncAnimation` instance.\n",
"\n",
"The `FuncAnimation` constructor takes a figure, an update function and optional arguments. We specify that we want a 100-frame long animation, with 20ms between each frame. At each iteration, `FuncAnimation` calls our update function and passes it the frame number `num` (from 0 to 99 in our case) followed by the extra arguments that we specified with `fargs`.\n",
"\n",
"Our update function simply sets the line data to be the first `num` data points (so the data gets drawn gradually), and just for fun we also add a small random number to each data point so that the line appears to wiggle."
"Matplotlib relies on 3rd-party libraries to write videos such as [FFMPEG](https://www.ffmpeg.org/) or `mencoder`. In this example we will be using FFMPEG so be sure to install it first."
"Now you know all the basics of matplotlib, but there are many more options available. The best way to learn more, is to visit the [gallery](http://matplotlib.org/gallery.html), look at the images, choose a plot that you are interested in, then just copy the code in a Jupyter notebook and play around with it."