diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8a85a0f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.pyc
+*.swp
+.ipynb_checkpoints
diff --git a/AnatomyOfMatplotlib-Part1-Figures_Subplots_and_layouts.ipynb b/AnatomyOfMatplotlib-Part1-Figures_Subplots_and_layouts.ipynb
index ed25e49..0c88701 100644
--- a/AnatomyOfMatplotlib-Part1-Figures_Subplots_and_layouts.ipynb
+++ b/AnatomyOfMatplotlib-Part1-Figures_Subplots_and_layouts.ipynb
@@ -1,960 +1,4 @@
{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {
- "collapsed": false,
- "slideshow": {
- "slide_type": "-"
- }
- },
- "outputs": [],
- "source": [
- "# Let printing work the same in Python 2 and 3\n",
- "from __future__ import print_function\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "slideshow": {
- "slide_type": "-"
- }
- },
- "source": [
- "# Matplotlib\n",
- "## Introduction\n",
- "Matplotlib is a library for producing publication-quality figures. mpl (for short) was designed from the bottom-up to serve dual-purposes. First, to allow for interactive, cross-platform control of figures and plots, and second, to make it very easy to produce static raster or vector graphics files without the need for any GUIs. Furthermore, mpl -- much like Python itself -- gives the developer complete control over the appearance of their plots, while still being very usable through a powerful defaults system.\n",
- "\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Online Documentation\n",
- "The [matplotlib.org](http://matplotlib.org) project website is the primary online resource for the library's documentation. It contains [examples](http://matplotlib.org/examples/index.html), [FAQs](http://matplotlib.org/faq/index.html), [API documentation](http://matplotlib.org/api/index.html), and, most importantly, the [gallery](http://matplotlib.org/gallery.html).\n",
- "\n",
- "## Gallery\n",
- "Many users of matplotlib are often faced with the question, \"I want to make a plot that has X with Y in the same figure, but it needs to look like Z\". Good luck getting an answer from a web search with that query. This is why the [gallery](http://matplotlib.org/gallery.html) is so useful, because it showcases the variety of ways one can make plots. Browse through the gallery, click on any figure that has pieces of what you want to see the code that generated it. Soon enough, you will be like a chef, mixing and matching components to produce your masterpiece!\n",
- "\n",
- "As always, if you have a new and interesting plot that demonstrates a feature of matplotlib, feel free to submit a well-commented version of the example code for inclusion.\n",
- "\n",
- "## Mailing Lists and StackOverflow\n",
- "When you are just simply stuck, and can not figure out how to get something to work, or just need some hints on how to get started, you will find much of the community at the matplotlib-users [mailing list](http://sourceforge.net/mail/?group_id=80706). This mailing list is an excellent resource of information with many friendly members who just love to help out newcomers. The number one rule to remember with this list is to be persistant. While many questions do get answered fairly quickly, some do fall through the cracks, or the one person who knows the answer isn't available. Therefore, try again with your questions rephrased, or with a plot showing your attempts so far. We love plots, so an image showing what is wrong often gets the quickest responses.\n",
- "\n",
- "Another community resource is [StackOverflow](http://stackoverflow.com/questions/tagged/matplotlib), so if you need to build up karma points, submit your questions here, and help others out too!\n",
- "\n",
- "## Github repository\n",
- "### Location\n",
- "[Matplotlib](https://github.com/matplotlib) is hosted by GitHub.\n",
- "\n",
- "### Bug Reports and feature requests\n",
- "So, you think you found a bug? Or maybe you think some feature is just too difficult to use? Or missing altogether? Submit your bug reports [here](https://github.com/matplotlib/matplotlib/issues) at matplotlib's issue tracker. We even have a process for submitting and discussing Matplotlib Enhancement Proposals ([MEPs](https://github.com/matplotlib/matplotlib/wiki))."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Quick note on \"backends\" and IPython notebooks\n",
- "Matplotlib has multiple backends. The backends allow mpl to be used on a variety of platforms with a variety of GUI toolkits (GTK, Qt, Wx, etc.), all of them written so that most of the time, you will not need to care which backend you are using. "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {
- "collapsed": false
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "1.4.3\n",
- "Qt4Agg\n"
- ]
- }
- ],
- "source": [
- "import matplotlib\n",
- "print(matplotlib.__version__)\n",
- "print(matplotlib.get_backend())"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Normally we wouldn't need to think about this too much, but IPython/Jupyter notebooks behave a touch differently than \"normal\" python.\n",
- "\n",
- "Inside of IPython, it's often easiest to use the IPython ``nbagg`` backend. This allows plots to be displayed and interacted with inline in the browser in an IPython notebook. Otherwise, figures will pop up in a separate gui window.\n",
- "\n",
- "We can do this in two ways:\n",
- "\n",
- "1. The IPython ``%matplotlib backend_name`` \"magic\" command (or ``plt.ion()``, which behaves similarly)\n",
- " - Figures will be shown automatically by IPython, even if you don't call ``plt.show()``.\n",
- " \n",
- "2. ``matplotlib.use(\"backend_name\")``\n",
- " - Figures will only be shown when you call ``plt.show()``.\n",
- "\n",
- "Here, we'll use the second method for one simple reason: it allows our code to behave the same way regardless of whether we run it inside of an IPython notebook or from the command line. Feel free to use the ``%matplotlib`` magic command if you'd prefer.\n",
- "\n",
- "One final note: You need to do this before you ``import matplotlib.pyplot``."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "matplotlib.use('nbagg')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# On with the show!\n",
- "Matplotlib is a large project and can seem daunting at first. However, by learning the components, it should begin to feel much smaller and more approachable.\n",
- "\n",
- "###Anatomy of a \"Plot\"\n",
- "\n",
- "People use \"plot\" to mean many different things. Here, we'll be using a consistent terminology (mirrored by the names of the underlying classes, etc):\n",
- "\n",
- "\n",
- "
\n",
- "\n",
- "The ``Figure`` is the top-level container in this hirearchy. It's the overall window/page that everything is drawn on. You can have multiple independent figures, but they can't contain another figure. However, ``Figure``s can contain multiple ``Axes``. \n",
- "\n",
- "Most plotting ocurs on an ``Axes``. The axes is effectively the area that we plot data on and any ticks/labels/etc associated with it. Usually we'll set up an axes with a call to ``subplot`` (which places axes on a regular grid), so in most cases we'll deal with here, ``Axes`` and ``Subplot`` are synonymous. We'll be heavily using ``Axes`` instances for plotting, etc, so you'll be seeing a lot of thse.\n",
- "\n",
- "Each ``Axes`` has an ``XAxis`` and a ``YAxis``. These contain the ticks, tick locations, labels, etc. In this tutorial, we'll mostly control ticks, tick labels, and data limits through other mechanisms, so we won't touch the individual ``Axis`` part of things much at all. However, it's worth mentioning here to explain where the term ``Axes`` comes from. Each ``Axes`` has two ``Axis`` instances.\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "###Getting Started\n",
- "\n",
- "In this tutorial, we'll use the following import statements. These abbreviations are semi-standardized, and most tutorials, other scientific python code, etc that you'll find elsewhere will use them as well."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import matplotlib.pyplot as plt"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Figures\n",
- "\n",
- "Now let's create a figure..."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "fig = plt.figure()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Awww, nothing happened! This is because by default mpl will not show anything until told to do so, as we mentioned earlier in the \"backend\" discussion.\n",
- "\n",
- "Instead, we'll need to call ``plt.show()``"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Great, a blank figure! Not terribly useful yet.\n",
- "\n",
- "However, while we're on the topic, you can control the size of the figure through the ``figsize`` argument, which expects a tuple of ``(width, height)`` in inches. \n",
- "\n",
- "A really useful utility function is [`figaspect`](http://matplotlib.org/api/figure_api.html?highlight=figaspect#matplotlib.figure.figaspect)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "# Twice as tall as it is wide:\n",
- "fig = plt.figure(figsize=plt.figaspect(2.0))\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Axes\n",
- "\n",
- "All plotting is done with respect to an [`Axes`](http://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes). An *Axes* is made up of [`Axis`](http://matplotlib.org/api/axis_api.html#matplotlib.axis.Axis) objects and many other things. An *Axes* object must belong to a *Figure* (and only one *Figure*). Most commands you will ever issue will be with respect to this *Axes* object.\n",
- "\n",
- "Typically, you'll set up a `Figure`, and then add an `Axes` to it. \n",
- "\n",
- "You can use `fig.add_axes`, but in most cases, you'll find that adding a subplot will fit your needs perfectly. (Again a \"subplot\" is just an axes on a grid system.) "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "fig = plt.figure()\n",
- "ax = fig.add_subplot(111) # We'll explain the \"111\" later. Basically, 1 row and 1 column.\n",
- "ax.set(xlim=[0.5, 4.5], ylim=[-2, 8], title='An Example Axes', ylabel='Y-Axis', xlabel='X-Axis')\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "\n",
- "Notice the call to ``set``. Matplotlib's objects typically have lots of \"explicit setters\" -- in other words, functions that start with ``set_`` and control a particular option. (This dates from a time before Python's ``property``.) \n",
- "\n",
- "To demonstrate this (and as an example of IPython's tab-completion), try typing `ax.set_` in a code cell, then hit the `` key. You'll see a long list of `Axes` methods that start with `set`.\n",
- "\n",
- "For example, we could have written the third line above as:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "ax.set_xlim([0.5, 4.5])\n",
- "ax.set_ylim([-2, 8])\n",
- "ax.set_title('An Example Axes')\n",
- "ax.set_ylabel('Y-Axis')\n",
- "ax.set_xlabel('X-Axis')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Clearly this can get repitive quickly. Therefore, Matplotlib's `set` method can be very handy. It takes each kwarg you pass it and tries to call the corresponding \"setter\". For example, `foo.set(bar='blah')` would call `foo.set_bar('blah')`.\n",
- "\n",
- "Note that the `set` method doesn't just apply to `Axes`; it applies to more-or-less all matplotlib objects.\n",
- "\n",
- "However, there are cases where you'll want to use things like `ax.set_xlabel('Some Label', size=25)` to control other options for a particular function."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "###Basic Plotting\n",
- "\n",
- "Most plotting happens on an `Axes`. Therefore, if you're plotting something on an axes, then you'll use one of its methods.\n",
- "\n",
- "We'll talk about different plotting methods in more depth in the next section. For now, let's focus on two methods: `plot` and `scatter`.\n",
- "\n",
- "`plot` draws points with lines connecting them. `scatter` draws unconnected points, optionally scaled or colored by additional variables.\n",
- "\n",
- "As a basic example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "fig = plt.figure()\n",
- "ax = fig.add_subplot(111)\n",
- "ax.plot([1, 2, 3, 4], [10, 20, 25, 30], color='lightblue', linewidth=3)\n",
- "ax.scatter([0.3, 3.8, 1.2, 2.5], [11, 25, 9, 26], marker='^', color='darkgreen')\n",
- "ax.set_xlim(0.5, 4.5)\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "###Axes methods vs. pyplot\n",
- "\n",
- "Interestingly, just about all methods of an *Axes* object exist as a function in the *pyplot* module (and vice-versa). For example, when calling `plt.xlim(1, 10)`, *pyplot* calls `ax.set_xlim(1, 10)` on whichever *Axes* is \"current\". Here is an equivalent version of the above example using just pyplot."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "plt.plot([1, 2, 3, 4], [10, 20, 25, 30], color='lightblue', linewidth=3)\n",
- "plt.scatter([0.3, 3.8, 1.2, 2.5], [11, 25, 9, 26], marker='^', color='darkgreen')\n",
- "plt.xlim(0.5, 4.5)\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Much cleaner, and much clearer! So, why will most of my examples not follow the pyplot approach? Because [PEP20](http://www.python.org/dev/peps/pep-0020/) \"The Zen of Python\" says:\n",
- "\n",
- "\"Explicit is better than implicit\"\n",
- "\n",
- "While very simple plots, with short scripts would benefit from the conciseness of the pyplot implicit approach, when doing more complicated plots, or working within larger scripts, you will want to explicitly pass around the *Axes* and/or *Figure* object to operate upon.\n",
- "\n",
- "The advantage of keeping which axes we're working with very clear in our code will become more obvious when we start to have multiple axes in one figure."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Multiple Axes\n",
- "\n",
- "We've mentioned before that a figure can have more than one `Axes` on it. If you want your axes to be on a regular grid system, then it's easiest to use `plt.subplots(...)` to create a figure and add the axes to it automatically.\n",
- "\n",
- "For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "fig, axes = plt.subplots(nrows=2, ncols=2)\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "`plt.subplots(...)` created a new figure and added 4 subplots to it. The `axes` object that was returned is a 2D numpy object array. Each item in the array is one of the subplots. They're laid out as you see them on the figure. \n",
- "\n",
- "Therefore, when we want to work with one of these axes, we can index the `axes` array and use that item's methods.\n",
- "\n",
- "For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "fig, axes = plt.subplots(nrows=2, ncols=2)\n",
- "axes[0,0].set(title='Upper Left')\n",
- "axes[0,1].set(title='Upper Right')\n",
- "axes[1,0].set(title='Lower Left')\n",
- "axes[1,1].set(title='Lower Right')\n",
- "\n",
- "# To iterate over all items in a multidimensional numpy array, use the `flat` attribute\n",
- "for ax in axes.flat:\n",
- " # Remove all xticks and yticks...\n",
- " ax.set(xticks=[], yticks=[])\n",
- " \n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "One really nice thing about `plt.subplots()` is that when it's called with no arguments, it creates a new figure with a single subplot. \n",
- "\n",
- "Any time you see something like\n",
- "\n",
- "```\n",
- "fig = plt.figure()\n",
- "ax = fig.add_subplot(111)\n",
- "```\n",
- "\n",
- "You can replace it with:\n",
- "\n",
- "```\n",
- "fig, ax = plt.subplots()\n",
- "```\n",
- "\n",
- "We'll be using that approach for the rest of the examples. It's much cleaner. \n",
- "\n",
- "However, keep in mind that we're still creating a figure and adding axes to it. We we start making plot layouts that can't be described by `subplots`, we'll go back to creating the figure first and then adding axes to it one-by-one."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Quick Exercise: Exercise 1.1\n",
- "--------------\n",
- "\n",
- "Let's use some of what we've been talking about. Can you reproduce this figure?\n",
- "\n",
- "
\n",
- "\n",
- "Here's the data and some code to get you started."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import matplotlib.pyplot as plt\n",
- "\n",
- "# Our data...\n",
- "x = np.linspace(0, 10, 100)\n",
- "y1, y2, y3 = np.cos(x), np.cos(x + 1), np.cos(x + 2)\n",
- "names = ['Signal 1', 'Signal 2', 'Signal 3']\n",
- "\n",
- "# Can you figure out what to do next to plot x vs y1, y2, and y3?"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Limits and autoscaling\n",
- "By default, matplotlib will attempt to determine limits for you that encompasses all the data you have plotted. This is the \"autoscale\" feature. For line and image plots, the limits are not padded, while plots such as scatter plots and bar plots are given some padding."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=plt.figaspect(0.5))\n",
- "\n",
- "ax1.plot([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
- "ax2.scatter([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
- "\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "###`ax.margins(...)`\n",
- "\n",
- "If you'd like to add a bit of \"padding\" to a plot, `ax.margins()` is a very handy way to do so. Instead of choosing \"even-ish\" numbers as min/max ranges for each axis, `margins` will make matplotlib calculate the min/max of each axis by taking the range of the data and adding on a fractional amount of padding.\n",
- "\n",
- "As an example: (Note that the ranges for the scatter example actually shrink slightly in this case)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=plt.figaspect(0.5))\n",
- "\n",
- "ax1.plot([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
- "ax2.scatter([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
- "\n",
- "ax1.margins(x=0.0, y=0.1) # 10% padding in the y-direction only\n",
- "ax2.margins(0.05) # 5% padding in all directions\n",
- "\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### `ax.axis(...)`\n",
- "\n",
- "The `ax.axis(...)` method is a convienent way of controlling the axes limits and enabling/disabling autoscaling.\n",
- "\n",
- "If you ever need to get all of the current plot limits, calling `ax.axis()` with no arguments will return the xmin/max/etc:\n",
- "\n",
- " xmin, xmax, ymin, ymax = ax.axis()\n",
- " \n",
- "If you'd like to manually set all of the x/y limits at once, you can use `ax.axis` for this, as well (note that we're calling it with a single argument that's a sequence, not 4 individual arguments):\n",
- "\n",
- " ax.axis([xmin, xmax, ymin, ymax])\n",
- " \n",
- "However, you'll probably use `axis` mostly with either the `\"tight\"` or `\"equal\"` options. There are other options as well; see the documentation for full details. In a nutshell, though:\n",
- "\n",
- " * *tight*: Set axes limits to the exact range of the data\n",
- " * *equal*: Set axes scales such that one cm/inch in the y-direction is the same as one cm/inch in the x-direction. (In matplotlib terms, this sets the aspect ratio of the plot to 1. That _doesn't_ mean that the axes \"box\" will be square, though!)\n",
- " \n",
- "And as an example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "fig, axes = plt.subplots(nrows=3)\n",
- "\n",
- "for ax in axes:\n",
- " ax.plot([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
- "\n",
- "axes[0].set_title('Normal Autoscaling', y=0.7, x=0.8)\n",
- "\n",
- "axes[1].set_title('ax.axis(\"tight\")', y=0.7, x=0.8)\n",
- "axes[1].axis('tight')\n",
- "\n",
- "axes[2].set_title('ax.axis(\"equal\")', y=0.7, x=0.8)\n",
- "axes[2].axis('equal')\n",
- "\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Manually setting only one limit\n",
- "\n",
- "Another trick with limits is to specify only half of a limit. When done **after** a plot is made, this has the effect of allowing the user to anchor a limit while letting matplotlib autoscale the rest of it."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "# Good -- setting limits after plotting is done\n",
- "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=plt.figaspect(0.5))\n",
- "ax1.plot([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
- "ax2.scatter([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
- "ax1.set_ylim(bottom=-10)\n",
- "ax2.set_xlim(right=25)\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "# Bad -- Setting limits before plotting is done\n",
- "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=plt.figaspect(0.5))\n",
- "ax1.set_ylim(bottom=-10)\n",
- "ax2.set_xlim(right=25)\n",
- "ax1.plot([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
- "ax2.scatter([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Legends\n",
- "\n",
- "As you've seen in some of the examples so far, the X and Y axis can also be labeled, as well as the subplot itself via the title. \n",
- "\n",
- "However, another thing you can label is the line/point/bar/etc that you plot. You can provide a label to your plot, which allows your legend to automatically build itself. "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "fig, ax = plt.subplots()\n",
- "ax.plot([1, 2, 3, 4], [10, 20, 25, 30], label='Philadelphia')\n",
- "ax.plot([1, 2, 3, 4], [30, 23, 13, 4], label='Boston')\n",
- "ax.set(ylabel='Temperature (deg C)', xlabel='Time', title='A tale of two cities')\n",
- "ax.legend()\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Legends will go in the upper right corner by default (you can control this with the `loc` kwarg), but if you'd prefer matplotlib to choose a location to avoid overlapping plot elements as much as possible, you can pass in:\n",
- "\n",
- " ax.legend(loc=\"best\")\n",
- " \n",
- "Also, if you happen to be plotting something that you do not want to appear in the legend, just set the label to \"\\_nolegend\\_\". \n",
- "\n",
- "On a side note, we're going to briefly introduce the `ax.bar` plotting method here. Unsurprisingly, it draws bars (vertical, by default)."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "fig, ax = plt.subplots(1, 1)\n",
- "ax.bar([1, 2, 3, 4], [10, 20, 25, 30], label=\"Foobar\", align='center', color='lightblue')\n",
- "ax.plot([1, 2, 3, 4], [10, 20, 25, 30], color='darkred', label=\"_nolegend_\", marker='o')\n",
- "ax.legend(loc='best')\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Exercise 1.2\n",
- "\n",
- "Once again, let's use a bit of what we've learned. Try to reproduce the following figure:\n",
- "\n",
- "
\n",
- "\n",
- "Hint: You'll need to combine `ax.axis(...)` and `ax.margins(...)`. Here's the data and some code to get you started:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "import matplotlib.pyplot as plt\n",
- "\n",
- "t = np.linspace(0, 2 * np.pi, 150)\n",
- "x1, y1 = np.cos(t), np.sin(t)\n",
- "x2, y2 = 2 * x1, 2 * y1\n",
- "\n",
- "colors = ['darkred', 'darkgreen']\n",
- "\n",
- "# Try to plot the two circles, scale the axes as shown and add a legend\n",
- "# Hint: it's easiest to combine `ax.axis(...)` and `ax.margins(...)` to scale the axes"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Dealing with the boundaries: Layout, ticks, spines, etc\n",
- "\n",
- "One key thing we haven't talked about yet is all of the annotation on the outside of the axes, the borders of the axes, and how to adjust the amount of space around the axes. We won't go over every detail, but this next section should give you a reasonable working knowledge of how to configure what happens around the edges of your axes.\n",
- "\n",
- "## Ticks, Tick Lines, Tick Labels and Tickers\n",
- "This is a constant source of confusion:\n",
- "\n",
- "* A Tick is the *location* of a Tick Label.\n",
- "* A Tick Line is the line that denotes the location of the tick.\n",
- "* A Tick Label is the text that is displayed at that tick.\n",
- "* A [`Ticker`](http://matplotlib.org/api/ticker_api.html#module-matplotlib.ticker) automatically determines the ticks for an Axis and formats the tick labels.\n",
- "\n",
- "[`tick_params()`](http://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes.tick_params) is often used to help configure your tickers."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "fig, ax = plt.subplots()\n",
- "ax.plot([1, 2, 3, 4], [10, 20, 25, 30])\n",
- "\n",
- "# Manually set ticks and tick labels *on the x-axis* (note ax.xaxis.set, not ax.set!)\n",
- "ax.xaxis.set(ticks=range(1, 5), ticklabels=[3, 100, -12, \"foo\"]) \n",
- "\n",
- "# Make the y-ticks a bit longer and go both in and out...\n",
- "ax.tick_params(axis='y', direction='inout', length=10)\n",
- "\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "A commonly-asked question is \"How do I plot non-numerical categories?\"\n",
- " \n",
- "The easiest way to do this is to \"fake\" the x-values and then change the tick labels to reflect the category.\n",
- "\n",
- "For example:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "data = [('apples', 2), ('oranges', 3), ('peaches', 1)]\n",
- "fruit, value = zip(*data)\n",
- "\n",
- "fig, ax = plt.subplots()\n",
- "x = np.arange(len(fruit))\n",
- "ax.bar(x, value, align='center', color='gray')\n",
- "ax.set(xticks=x, xticklabels=fruit)\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Subplot Spacing\n",
- "The spacing between the subplots can be adjusted using [`fig.subplots_adjust()`](http://matplotlib.org/api/pyplot_api.html?#matplotlib.pyplot.subplots_adjust). Play around with the example below to see how the different arguments affect the spacing."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "fig, axes = plt.subplots(2, 2, figsize=(9, 9))\n",
- "fig.subplots_adjust(wspace=0.5, hspace=0.3,\n",
- " left=0.125, right=0.9,\n",
- " top=0.9, bottom=0.1)\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "A common \"gotcha\" is that the labels are not automatically adjusted to avoid overlapping those of another subplot. Matplotlib does not currently have any sort of robust layout engine, as it is a design decision to minimize the amount of \"magic\" that matplotlib performs. We intend to let users have complete, 100% control over their plots. LaTeX users would be quite familiar with the amount of frustration that can occur with placement of figures in their documents.\n",
- "\n",
- "That said, there have been some efforts to develop tools that users can use to help address the most common compaints. The \"[Tight Layout](http://matplotlib.org/users/tight_layout_guide.html)\" feature, when invoked, will attempt to resize margins, and subplots so that nothing overlaps.\n",
- "\n",
- "If you have multiple subplots, and want to avoid overlapping titles/axis labels/etc, `fig.tight_layout` is a great way to do so:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "def example_plot(ax):\n",
- " ax.plot([1, 2])\n",
- " ax.set_xlabel('x-label', fontsize=16)\n",
- " ax.set_ylabel('y-label', fontsize=8)\n",
- " ax.set_title('Title', fontsize=24)\n",
- "\n",
- "fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2)\n",
- "example_plot(ax1)\n",
- "example_plot(ax2)\n",
- "example_plot(ax3)\n",
- "example_plot(ax4)\n",
- "\n",
- "# Try enabling fig.tight_layout to compare...\n",
- "#fig.tight_layout()\n",
- "\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## GridSpec\n",
- "Under the hood, matplotlib utilizes [`GridSpec`](http://matplotlib.org/api/gridspec_api.html) to lay out the subplots. While `plt.subplots()` is fine for simple cases, sometimes you will need more advanced subplot layouts. In such cases, you should use GridSpec directly. GridSpec is outside the scope of this tutorial, but it is handy to know that it exists. [Here](http://matplotlib.org/users/gridspec.html) is a guide on how to use it."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## Sharing axes\n",
- "There will be times when you want to have the x axis and/or the y axis of your subplots to be \"shared\". Sharing an axis means that the axis in one or more subplots will be tied together such that any change in one of the axis changes all of the other shared axes. This works very nicely with autoscaling arbitrary datasets that may have overlapping domains. Furthermore, when interacting with the plots (panning and zooming), all of the shared axes will pan and zoom automatically."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "fig, (ax1, ax2) = plt.subplots(1, 2, sharex=True, sharey=True)\n",
- "ax1.plot([1, 2, 3, 4], [1, 2, 3, 4])\n",
- "ax2.plot([3, 4, 5, 6], [6, 5, 4, 3])\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## \"Twinning\" axes\n",
- "Sometimes one may want to overlay two plots on the same axes, but the scales may be entirely different. You can simply treat them as separate plots, but then twin them."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "fig, ax1 = plt.subplots(1, 1)\n",
- "ax1.plot([1, 2, 3, 4], [1, 2, 3, 4])\n",
- "ax2 = ax1.twinx()\n",
- "ax2.scatter([1, 2, 3, 4], [60, 50, 40, 30])\n",
- "ax1.set_xlabel('X')\n",
- "ax1.set_ylabel('First scale')\n",
- "ax2.set_ylabel('Other scale')\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Axis Spines\n",
- "Spines are the axis lines for a plot. Each plot can have four spines: \"top\", \"bottom\", \"left\" and \"right\". By default, they are set so that they frame the plot, but they can be individually positioned and configured via the [`set_position()`](http://matplotlib.org/api/spines_api.html#matplotlib.spines.Spine.set_position) method of the spine. Here are some different configurations."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "fig, ax = plt.subplots()\n",
- "ax.plot([-2, 2, 3, 4], [-10, 20, 25, 5])\n",
- "ax.spines['top'].set_visible(False)\n",
- "ax.xaxis.set_ticks_position('bottom') # no ticklines at the top\n",
- "ax.spines['right'].set_visible(False)\n",
- "ax.yaxis.set_ticks_position('left') # no ticklines on the right\n",
- "\n",
- "# \"outward\"\n",
- "# Move the two remaining spines \"out\" away from the plot by 10 points\n",
- "ax.spines['bottom'].set_position(('outward', 10))\n",
- "ax.spines['left'].set_position(('outward', 10))\n",
- "\n",
- "# \"data\"\n",
- "# Have the spines stay intersected at (0,0)\n",
- "#ax.spines['bottom'].set_position(('data', 0))\n",
- "#ax.spines['left'].set_position(('data', 0))\n",
- "\n",
- "# \"axes\"\n",
- "# Have the two remaining spines placed at a fraction of the axes\n",
- "#ax.spines['bottom'].set_position(('axes', 0.75))\n",
- "#ax.spines['left'].set_position(('axes', 0.25))\n",
- "\n",
- "plt.show()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Exercise 1.3\n",
- "\n",
- "This one is a bit trickier. Once again, try to reproduce the figure below:\n",
- "\n",
- "
\n",
- "\n",
- "\n",
- "A few key hints: The two subplots have no vertical space between them (this means that the `hspace` is `0`). Note that the bottom spine is at 0 in data coordinates and the tick lines are missing from the left and top sides.\n",
- "\n",
- "Because you're going to be doing a lot of the same things to both subplots, to avoid repitive code you might consider writing a function that takes an `Axes` object and makes the spine changes, etc to it. \n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
- "source": [
- "%load exercises/1.2-spines.py"
- ]
- }
- ],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
@@ -972,8 +16,971 @@
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.10"
- }
+ },
+ "name": ""
},
- "nbformat": 4,
- "nbformat_minor": 0
-}
+ "nbformat": 3,
+ "nbformat_minor": 0,
+ "worksheets": [
+ {
+ "cells": [
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "# Let printing work the same in Python 2 and 3\n",
+ "from __future__ import print_function\n"
+ ],
+ "language": "python",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "-"
+ }
+ },
+ "outputs": [],
+ "prompt_number": 1
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "-"
+ }
+ },
+ "source": [
+ "# Matplotlib\n",
+ "## Introduction\n",
+ "Matplotlib is a library for producing publication-quality figures. mpl (for short) was designed from the bottom-up to serve dual-purposes. First, to allow for interactive, cross-platform control of figures and plots, and second, to make it very easy to produce static raster or vector graphics files without the need for any GUIs. Furthermore, mpl -- much like Python itself -- gives the developer complete control over the appearance of their plots, while still being very usable through a powerful defaults system.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Online Documentation\n",
+ "The [matplotlib.org](http://matplotlib.org) project website is the primary online resource for the library's documentation. It contains [examples](http://matplotlib.org/examples/index.html), [FAQs](http://matplotlib.org/faq/index.html), [API documentation](http://matplotlib.org/api/index.html), and, most importantly, the [gallery](http://matplotlib.org/gallery.html).\n",
+ "\n",
+ "## Gallery\n",
+ "Many users of matplotlib are often faced with the question, \"I want to make a plot that has X with Y in the same figure, but it needs to look like Z\". Good luck getting an answer from a web search with that query. This is why the [gallery](http://matplotlib.org/gallery.html) is so useful, because it showcases the variety of ways one can make plots. Browse through the gallery, click on any figure that has pieces of what you want to see the code that generated it. Soon enough, you will be like a chef, mixing and matching components to produce your masterpiece!\n",
+ "\n",
+ "As always, if you have a new and interesting plot that demonstrates a feature of matplotlib, feel free to submit a well-commented version of the example code for inclusion.\n",
+ "\n",
+ "## Mailing Lists and StackOverflow\n",
+ "When you are just simply stuck, and can not figure out how to get something to work, or just need some hints on how to get started, you will find much of the community at the matplotlib-users [mailing list](http://sourceforge.net/mail/?group_id=80706). This mailing list is an excellent resource of information with many friendly members who just love to help out newcomers. The number one rule to remember with this list is to be persistant. While many questions do get answered fairly quickly, some do fall through the cracks, or the one person who knows the answer isn't available. Therefore, try again with your questions rephrased, or with a plot showing your attempts so far. We love plots, so an image showing what is wrong often gets the quickest responses.\n",
+ "\n",
+ "Another community resource is [StackOverflow](http://stackoverflow.com/questions/tagged/matplotlib), so if you need to build up karma points, submit your questions here, and help others out too!\n",
+ "\n",
+ "## Github repository\n",
+ "### Location\n",
+ "[Matplotlib](https://github.com/matplotlib) is hosted by GitHub.\n",
+ "\n",
+ "### Bug Reports and feature requests\n",
+ "So, you think you found a bug? Or maybe you think some feature is just too difficult to use? Or missing altogether? Submit your bug reports [here](https://github.com/matplotlib/matplotlib/issues) at matplotlib's issue tracker. We even have a process for submitting and discussing Matplotlib Enhancement Proposals ([MEPs](https://github.com/matplotlib/matplotlib/wiki))."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Quick note on \"backends\" and IPython notebooks\n",
+ "Matplotlib has multiple backends. The backends allow mpl to be used on a variety of platforms with a variety of GUI toolkits (GTK, Qt, Wx, etc.), all of them written so that most of the time, you will not need to care which backend you are using. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "import matplotlib\n",
+ "print(matplotlib.__version__)\n",
+ "print(matplotlib.get_backend())"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [
+ {
+ "output_type": "stream",
+ "stream": "stdout",
+ "text": [
+ "1.4.3\n",
+ "Qt4Agg\n"
+ ]
+ }
+ ],
+ "prompt_number": 2
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Normally we wouldn't need to think about this too much, but IPython/Jupyter notebooks behave a touch differently than \"normal\" python.\n",
+ "\n",
+ "Inside of IPython, it's often easiest to use the IPython ``nbagg`` backend. This allows plots to be displayed and interacted with inline in the browser in an IPython notebook. Otherwise, figures will pop up in a separate gui window.\n",
+ "\n",
+ "We can do this in two ways:\n",
+ "\n",
+ "1. The IPython ``%matplotlib backend_name`` \"magic\" command (or ``plt.ion()``, which behaves similarly)\n",
+ " - Figures will be shown automatically by IPython, even if you don't call ``plt.show()``.\n",
+ " \n",
+ "2. ``matplotlib.use(\"backend_name\")``\n",
+ " - Figures will only be shown when you call ``plt.show()``.\n",
+ "\n",
+ "Here, we'll use the second method for one simple reason: it allows our code to behave the same way regardless of whether we run it inside of an IPython notebook or from the command line. Feel free to use the ``%matplotlib`` magic command if you'd prefer.\n",
+ "\n",
+ "One final note: You need to do this before you ``import matplotlib.pyplot``."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "matplotlib.use('nbagg')"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": 3
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# On with the show!\n",
+ "Matplotlib is a large project and can seem daunting at first. However, by learning the components, it should begin to feel much smaller and more approachable.\n",
+ "\n",
+ "###Anatomy of a \"Plot\"\n",
+ "\n",
+ "People use \"plot\" to mean many different things. Here, we'll be using a consistent terminology (mirrored by the names of the underlying classes, etc):\n",
+ "\n",
+ "\n",
+ "
\n",
+ "\n",
+ "The ``Figure`` is the top-level container in this hirearchy. It's the overall window/page that everything is drawn on. You can have multiple independent figures, but they can't contain another figure. However, ``Figure``s can contain multiple ``Axes``. \n",
+ "\n",
+ "Most plotting ocurs on an ``Axes``. The axes is effectively the area that we plot data on and any ticks/labels/etc associated with it. Usually we'll set up an axes with a call to ``subplot`` (which places axes on a regular grid), so in most cases we'll deal with here, ``Axes`` and ``Subplot`` are synonymous. We'll be heavily using ``Axes`` instances for plotting, etc, so you'll be seeing a lot of thse.\n",
+ "\n",
+ "Each ``Axes`` has an ``XAxis`` and a ``YAxis``. These contain the ticks, tick locations, labels, etc. In this tutorial, we'll mostly control ticks, tick labels, and data limits through other mechanisms, so we won't touch the individual ``Axis`` part of things much at all. However, it's worth mentioning here to explain where the term ``Axes`` comes from. Each ``Axes`` has two ``Axis`` instances.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "###Getting Started\n",
+ "\n",
+ "In this tutorial, we'll use the following import statements. These abbreviations are semi-standardized, and most tutorials, other scientific python code, etc that you'll find elsewhere will use them as well."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Figures\n",
+ "\n",
+ "Now let's create a figure..."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "fig = plt.figure()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Awww, nothing happened! This is because by default mpl will not show anything until told to do so, as we mentioned earlier in the \"backend\" discussion.\n",
+ "\n",
+ "Instead, we'll need to call ``plt.show()``"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Great, a blank figure! Not terribly useful yet.\n",
+ "\n",
+ "However, while we're on the topic, you can control the size of the figure through the ``figsize`` argument, which expects a tuple of ``(width, height)`` in inches. \n",
+ "\n",
+ "A really useful utility function is [`figaspect`](http://matplotlib.org/api/figure_api.html?highlight=figaspect#matplotlib.figure.figaspect)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "# Twice as tall as it is wide:\n",
+ "fig = plt.figure(figsize=plt.figaspect(2.0))\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Axes\n",
+ "\n",
+ "All plotting is done with respect to an [`Axes`](http://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes). An *Axes* is made up of [`Axis`](http://matplotlib.org/api/axis_api.html#matplotlib.axis.Axis) objects and many other things. An *Axes* object must belong to a *Figure* (and only one *Figure*). Most commands you will ever issue will be with respect to this *Axes* object.\n",
+ "\n",
+ "Typically, you'll set up a `Figure`, and then add an `Axes` to it. \n",
+ "\n",
+ "You can use `fig.add_axes`, but in most cases, you'll find that adding a subplot will fit your needs perfectly. (Again a \"subplot\" is just an axes on a grid system.) "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "fig = plt.figure()\n",
+ "ax = fig.add_subplot(111) # We'll explain the \"111\" later. Basically, 1 row and 1 column.\n",
+ "ax.set(xlim=[0.5, 4.5], ylim=[-2, 8], title='An Example Axes', ylabel='Y-Axis', xlabel='X-Axis')\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "Notice the call to ``set``. Matplotlib's objects typically have lots of \"explicit setters\" -- in other words, functions that start with ``set_`` and control a particular option. (This dates from a time before Python's ``property``.) \n",
+ "\n",
+ "To demonstrate this (and as an example of IPython's tab-completion), try typing `ax.set_` in a code cell, then hit the `` key. You'll see a long list of `Axes` methods that start with `set`.\n",
+ "\n",
+ "For example, we could have written the third line above as:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "ax.set_xlim([0.5, 4.5])\n",
+ "ax.set_ylim([-2, 8])\n",
+ "ax.set_title('An Example Axes')\n",
+ "ax.set_ylabel('Y-Axis')\n",
+ "ax.set_xlabel('X-Axis')"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Clearly this can get repitive quickly. Therefore, Matplotlib's `set` method can be very handy. It takes each kwarg you pass it and tries to call the corresponding \"setter\". For example, `foo.set(bar='blah')` would call `foo.set_bar('blah')`.\n",
+ "\n",
+ "Note that the `set` method doesn't just apply to `Axes`; it applies to more-or-less all matplotlib objects.\n",
+ "\n",
+ "However, there are cases where you'll want to use things like `ax.set_xlabel('Some Label', size=25)` to control other options for a particular function."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "###Basic Plotting\n",
+ "\n",
+ "Most plotting happens on an `Axes`. Therefore, if you're plotting something on an axes, then you'll use one of its methods.\n",
+ "\n",
+ "We'll talk about different plotting methods in more depth in the next section. For now, let's focus on two methods: `plot` and `scatter`.\n",
+ "\n",
+ "`plot` draws points with lines connecting them. `scatter` draws unconnected points, optionally scaled or colored by additional variables.\n",
+ "\n",
+ "As a basic example:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "fig = plt.figure()\n",
+ "ax = fig.add_subplot(111)\n",
+ "ax.plot([1, 2, 3, 4], [10, 20, 25, 30], color='lightblue', linewidth=3)\n",
+ "ax.scatter([0.3, 3.8, 1.2, 2.5], [11, 25, 9, 26], marker='^', color='darkgreen')\n",
+ "ax.set_xlim(0.5, 4.5)\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "###Axes methods vs. pyplot\n",
+ "\n",
+ "Interestingly, just about all methods of an *Axes* object exist as a function in the *pyplot* module (and vice-versa). For example, when calling `plt.xlim(1, 10)`, *pyplot* calls `ax.set_xlim(1, 10)` on whichever *Axes* is \"current\". Here is an equivalent version of the above example using just pyplot."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "plt.plot([1, 2, 3, 4], [10, 20, 25, 30], color='lightblue', linewidth=3)\n",
+ "plt.scatter([0.3, 3.8, 1.2, 2.5], [11, 25, 9, 26], marker='^', color='darkgreen')\n",
+ "plt.xlim(0.5, 4.5)\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Much cleaner, and much clearer! So, why will most of my examples not follow the pyplot approach? Because [PEP20](http://www.python.org/dev/peps/pep-0020/) \"The Zen of Python\" says:\n",
+ "\n",
+ "\"Explicit is better than implicit\"\n",
+ "\n",
+ "While very simple plots, with short scripts would benefit from the conciseness of the pyplot implicit approach, when doing more complicated plots, or working within larger scripts, you will want to explicitly pass around the *Axes* and/or *Figure* object to operate upon.\n",
+ "\n",
+ "The advantage of keeping which axes we're working with very clear in our code will become more obvious when we start to have multiple axes in one figure."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Multiple Axes\n",
+ "\n",
+ "We've mentioned before that a figure can have more than one `Axes` on it. If you want your axes to be on a regular grid system, then it's easiest to use `plt.subplots(...)` to create a figure and add the axes to it automatically.\n",
+ "\n",
+ "For example:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "fig, axes = plt.subplots(nrows=2, ncols=2)\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "`plt.subplots(...)` created a new figure and added 4 subplots to it. The `axes` object that was returned is a 2D numpy object array. Each item in the array is one of the subplots. They're laid out as you see them on the figure. \n",
+ "\n",
+ "Therefore, when we want to work with one of these axes, we can index the `axes` array and use that item's methods.\n",
+ "\n",
+ "For example:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "fig, axes = plt.subplots(nrows=2, ncols=2)\n",
+ "axes[0,0].set(title='Upper Left')\n",
+ "axes[0,1].set(title='Upper Right')\n",
+ "axes[1,0].set(title='Lower Left')\n",
+ "axes[1,1].set(title='Lower Right')\n",
+ "\n",
+ "# To iterate over all items in a multidimensional numpy array, use the `flat` attribute\n",
+ "for ax in axes.flat:\n",
+ " # Remove all xticks and yticks...\n",
+ " ax.set(xticks=[], yticks=[])\n",
+ " \n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "One really nice thing about `plt.subplots()` is that when it's called with no arguments, it creates a new figure with a single subplot. \n",
+ "\n",
+ "Any time you see something like\n",
+ "\n",
+ "```\n",
+ "fig = plt.figure()\n",
+ "ax = fig.add_subplot(111)\n",
+ "```\n",
+ "\n",
+ "You can replace it with:\n",
+ "\n",
+ "```\n",
+ "fig, ax = plt.subplots()\n",
+ "```\n",
+ "\n",
+ "We'll be using that approach for the rest of the examples. It's much cleaner. \n",
+ "\n",
+ "However, keep in mind that we're still creating a figure and adding axes to it. We we start making plot layouts that can't be described by `subplots`, we'll go back to creating the figure first and then adding axes to it one-by-one."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Quick Exercise: Exercise 1.1\n",
+ "--------------\n",
+ "\n",
+ "Let's use some of what we've been talking about. Can you reproduce this figure?\n",
+ "\n",
+ "
\n",
+ "\n",
+ "Here's the data and some code to get you started."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": true,
+ "input": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "\n",
+ "# Our data...\n",
+ "x = np.linspace(0, 10, 100)\n",
+ "y1, y2, y3 = np.cos(x), np.cos(x + 1), np.cos(x + 2)\n",
+ "names = ['Signal 1', 'Signal 2', 'Signal 3']\n",
+ "\n",
+ "# Can you figure out what to do next to plot x vs y1, y2, and y3?"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Limits and autoscaling\n",
+ "By default, matplotlib will attempt to determine limits for you that encompasses all the data you have plotted. This is the \"autoscale\" feature. For line and image plots, the limits are not padded, while plots such as scatter plots and bar plots are given some padding."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=plt.figaspect(0.5))\n",
+ "\n",
+ "ax1.plot([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
+ "ax2.scatter([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
+ "\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "###`ax.margins(...)`\n",
+ "\n",
+ "If you'd like to add a bit of \"padding\" to a plot, `ax.margins()` is a very handy way to do so. Instead of choosing \"even-ish\" numbers as min/max ranges for each axis, `margins` will make matplotlib calculate the min/max of each axis by taking the range of the data and adding on a fractional amount of padding.\n",
+ "\n",
+ "As an example: (Note that the ranges for the scatter example actually shrink slightly in this case)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=plt.figaspect(0.5))\n",
+ "\n",
+ "ax1.plot([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
+ "ax2.scatter([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
+ "\n",
+ "ax1.margins(x=0.0, y=0.1) # 10% padding in the y-direction only\n",
+ "ax2.margins(0.05) # 5% padding in all directions\n",
+ "\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### `ax.axis(...)`\n",
+ "\n",
+ "The `ax.axis(...)` method is a convienent way of controlling the axes limits and enabling/disabling autoscaling.\n",
+ "\n",
+ "If you ever need to get all of the current plot limits, calling `ax.axis()` with no arguments will return the xmin/max/etc:\n",
+ "\n",
+ " xmin, xmax, ymin, ymax = ax.axis()\n",
+ " \n",
+ "If you'd like to manually set all of the x/y limits at once, you can use `ax.axis` for this, as well (note that we're calling it with a single argument that's a sequence, not 4 individual arguments):\n",
+ "\n",
+ " ax.axis([xmin, xmax, ymin, ymax])\n",
+ " \n",
+ "However, you'll probably use `axis` mostly with either the `\"tight\"` or `\"equal\"` options. There are other options as well; see the documentation for full details. In a nutshell, though:\n",
+ "\n",
+ " * *tight*: Set axes limits to the exact range of the data\n",
+ " * *equal*: Set axes scales such that one cm/inch in the y-direction is the same as one cm/inch in the x-direction. (In matplotlib terms, this sets the aspect ratio of the plot to 1. That _doesn't_ mean that the axes \"box\" will be square, though!)\n",
+ " \n",
+ "And as an example:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "fig, axes = plt.subplots(nrows=3)\n",
+ "\n",
+ "for ax in axes:\n",
+ " ax.plot([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
+ "\n",
+ "axes[0].set_title('Normal Autoscaling', y=0.7, x=0.8)\n",
+ "\n",
+ "axes[1].set_title('ax.axis(\"tight\")', y=0.7, x=0.8)\n",
+ "axes[1].axis('tight')\n",
+ "\n",
+ "axes[2].set_title('ax.axis(\"equal\")', y=0.7, x=0.8)\n",
+ "axes[2].axis('equal')\n",
+ "\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Manually setting only one limit\n",
+ "\n",
+ "Another trick with limits is to specify only half of a limit. When done **after** a plot is made, this has the effect of allowing the user to anchor a limit while letting matplotlib autoscale the rest of it."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "# Good -- setting limits after plotting is done\n",
+ "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=plt.figaspect(0.5))\n",
+ "ax1.plot([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
+ "ax2.scatter([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
+ "ax1.set_ylim(bottom=-10)\n",
+ "ax2.set_xlim(right=25)\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "# Bad -- Setting limits before plotting is done\n",
+ "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=plt.figaspect(0.5))\n",
+ "ax1.set_ylim(bottom=-10)\n",
+ "ax2.set_xlim(right=25)\n",
+ "ax1.plot([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
+ "ax2.scatter([-10, -5, 0, 5, 10, 15], [-1.2, 2, 3.5, -0.3, -4, 1])\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Legends\n",
+ "\n",
+ "As you've seen in some of the examples so far, the X and Y axis can also be labeled, as well as the subplot itself via the title. \n",
+ "\n",
+ "However, another thing you can label is the line/point/bar/etc that you plot. You can provide a label to your plot, which allows your legend to automatically build itself. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "fig, ax = plt.subplots()\n",
+ "ax.plot([1, 2, 3, 4], [10, 20, 25, 30], label='Philadelphia')\n",
+ "ax.plot([1, 2, 3, 4], [30, 23, 13, 4], label='Boston')\n",
+ "ax.set(ylabel='Temperature (deg C)', xlabel='Time', title='A tale of two cities')\n",
+ "ax.legend()\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Legends will go in the upper right corner by default (you can control this with the `loc` kwarg), but if you'd prefer matplotlib to choose a location to avoid overlapping plot elements as much as possible, you can pass in:\n",
+ "\n",
+ " ax.legend(loc=\"best\")\n",
+ " \n",
+ "Also, if you happen to be plotting something that you do not want to appear in the legend, just set the label to \"\\_nolegend\\_\". \n",
+ "\n",
+ "On a side note, we're going to briefly introduce the `ax.bar` plotting method here. Unsurprisingly, it draws bars (vertical, by default)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "fig, ax = plt.subplots(1, 1)\n",
+ "ax.bar([1, 2, 3, 4], [10, 20, 25, 30], label=\"Foobar\", align='center', color='lightblue')\n",
+ "ax.plot([1, 2, 3, 4], [10, 20, 25, 30], color='darkred', label=\"_nolegend_\", marker='o')\n",
+ "ax.legend(loc='best')\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Exercise 1.2\n",
+ "\n",
+ "Once again, let's use a bit of what we've learned. Try to reproduce the following figure:\n",
+ "\n",
+ "
\n",
+ "\n",
+ "Hint: You'll need to combine `ax.axis(...)` and `ax.margins(...)`. Here's the data and some code to get you started:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": true,
+ "input": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "\n",
+ "t = np.linspace(0, 2 * np.pi, 150)\n",
+ "x1, y1 = np.cos(t), np.sin(t)\n",
+ "x2, y2 = 2 * x1, 2 * y1\n",
+ "\n",
+ "colors = ['darkred', 'darkgreen']\n",
+ "\n",
+ "# Try to plot the two circles, scale the axes as shown and add a legend\n",
+ "# Hint: it's easiest to combine `ax.axis(...)` and `ax.margins(...)` to scale the axes"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": 5
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Dealing with the boundaries: Layout, ticks, spines, etc\n",
+ "\n",
+ "One key thing we haven't talked about yet is all of the annotation on the outside of the axes, the borders of the axes, and how to adjust the amount of space around the axes. We won't go over every detail, but this next section should give you a reasonable working knowledge of how to configure what happens around the edges of your axes.\n",
+ "\n",
+ "## Ticks, Tick Lines, Tick Labels and Tickers\n",
+ "This is a constant source of confusion:\n",
+ "\n",
+ "* A Tick is the *location* of a Tick Label.\n",
+ "* A Tick Line is the line that denotes the location of the tick.\n",
+ "* A Tick Label is the text that is displayed at that tick.\n",
+ "* A [`Ticker`](http://matplotlib.org/api/ticker_api.html#module-matplotlib.ticker) automatically determines the ticks for an Axis and formats the tick labels.\n",
+ "\n",
+ "[`tick_params()`](http://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes.tick_params) is often used to help configure your tickers."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "fig, ax = plt.subplots()\n",
+ "ax.plot([1, 2, 3, 4], [10, 20, 25, 30])\n",
+ "\n",
+ "# Manually set ticks and tick labels *on the x-axis* (note ax.xaxis.set, not ax.set!)\n",
+ "ax.xaxis.set(ticks=range(1, 5), ticklabels=[3, 100, -12, \"foo\"]) \n",
+ "\n",
+ "# Make the y-ticks a bit longer and go both in and out...\n",
+ "ax.tick_params(axis='y', direction='inout', length=10)\n",
+ "\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "A commonly-asked question is \"How do I plot non-numerical categories?\"\n",
+ " \n",
+ "The easiest way to do this is to \"fake\" the x-values and then change the tick labels to reflect the category.\n",
+ "\n",
+ "For example:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "data = [('apples', 2), ('oranges', 3), ('peaches', 1)]\n",
+ "fruit, value = zip(*data)\n",
+ "\n",
+ "fig, ax = plt.subplots()\n",
+ "x = np.arange(len(fruit))\n",
+ "ax.bar(x, value, align='center', color='gray')\n",
+ "ax.set(xticks=x, xticklabels=fruit)\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Subplot Spacing\n",
+ "The spacing between the subplots can be adjusted using [`fig.subplots_adjust()`](http://matplotlib.org/api/pyplot_api.html?#matplotlib.pyplot.subplots_adjust). Play around with the example below to see how the different arguments affect the spacing."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "fig, axes = plt.subplots(2, 2, figsize=(9, 9))\n",
+ "fig.subplots_adjust(wspace=0.5, hspace=0.3,\n",
+ " left=0.125, right=0.9,\n",
+ " top=0.9, bottom=0.1)\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "A common \"gotcha\" is that the labels are not automatically adjusted to avoid overlapping those of another subplot. Matplotlib does not currently have any sort of robust layout engine, as it is a design decision to minimize the amount of \"magic\" that matplotlib performs. We intend to let users have complete, 100% control over their plots. LaTeX users would be quite familiar with the amount of frustration that can occur with placement of figures in their documents.\n",
+ "\n",
+ "That said, there have been some efforts to develop tools that users can use to help address the most common compaints. The \"[Tight Layout](http://matplotlib.org/users/tight_layout_guide.html)\" feature, when invoked, will attempt to resize margins, and subplots so that nothing overlaps.\n",
+ "\n",
+ "If you have multiple subplots, and want to avoid overlapping titles/axis labels/etc, `fig.tight_layout` is a great way to do so:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "def example_plot(ax):\n",
+ " ax.plot([1, 2])\n",
+ " ax.set_xlabel('x-label', fontsize=16)\n",
+ " ax.set_ylabel('y-label', fontsize=8)\n",
+ " ax.set_title('Title', fontsize=24)\n",
+ "\n",
+ "fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2)\n",
+ "example_plot(ax1)\n",
+ "example_plot(ax2)\n",
+ "example_plot(ax3)\n",
+ "example_plot(ax4)\n",
+ "\n",
+ "# Try enabling fig.tight_layout to compare...\n",
+ "#fig.tight_layout()\n",
+ "\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## GridSpec\n",
+ "Under the hood, matplotlib utilizes [`GridSpec`](http://matplotlib.org/api/gridspec_api.html) to lay out the subplots. While `plt.subplots()` is fine for simple cases, sometimes you will need more advanced subplot layouts. In such cases, you should use GridSpec directly. GridSpec is outside the scope of this tutorial, but it is handy to know that it exists. [Here](http://matplotlib.org/users/gridspec.html) is a guide on how to use it."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Sharing axes\n",
+ "There will be times when you want to have the x axis and/or the y axis of your subplots to be \"shared\". Sharing an axis means that the axis in one or more subplots will be tied together such that any change in one of the axis changes all of the other shared axes. This works very nicely with autoscaling arbitrary datasets that may have overlapping domains. Furthermore, when interacting with the plots (panning and zooming), all of the shared axes will pan and zoom automatically."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "fig, (ax1, ax2) = plt.subplots(1, 2, sharex=True, sharey=True)\n",
+ "ax1.plot([1, 2, 3, 4], [1, 2, 3, 4])\n",
+ "ax2.plot([3, 4, 5, 6], [6, 5, 4, 3])\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## \"Twinning\" axes\n",
+ "Sometimes one may want to overlay two plots on the same axes, but the scales may be entirely different. You can simply treat them as separate plots, but then twin them."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "fig, ax1 = plt.subplots(1, 1)\n",
+ "ax1.plot([1, 2, 3, 4], [1, 2, 3, 4])\n",
+ "ax2 = ax1.twinx()\n",
+ "ax2.scatter([1, 2, 3, 4], [60, 50, 40, 30])\n",
+ "ax1.set_xlabel('X')\n",
+ "ax1.set_ylabel('First scale')\n",
+ "ax2.set_ylabel('Other scale')\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Axis Spines\n",
+ "Spines are the axis lines for a plot. Each plot can have four spines: \"top\", \"bottom\", \"left\" and \"right\". By default, they are set so that they frame the plot, but they can be individually positioned and configured via the [`set_position()`](http://matplotlib.org/api/spines_api.html#matplotlib.spines.Spine.set_position) method of the spine. Here are some different configurations."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "fig, ax = plt.subplots()\n",
+ "ax.plot([-2, 2, 3, 4], [-10, 20, 25, 5])\n",
+ "ax.spines['top'].set_visible(False)\n",
+ "ax.xaxis.set_ticks_position('bottom') # no ticklines at the top\n",
+ "ax.spines['right'].set_visible(False)\n",
+ "ax.yaxis.set_ticks_position('left') # no ticklines on the right\n",
+ "\n",
+ "# \"outward\"\n",
+ "# Move the two remaining spines \"out\" away from the plot by 10 points\n",
+ "ax.spines['bottom'].set_position(('outward', 10))\n",
+ "ax.spines['left'].set_position(('outward', 10))\n",
+ "\n",
+ "# \"data\"\n",
+ "# Have the spines stay intersected at (0,0)\n",
+ "#ax.spines['bottom'].set_position(('data', 0))\n",
+ "#ax.spines['left'].set_position(('data', 0))\n",
+ "\n",
+ "# \"axes\"\n",
+ "# Have the two remaining spines placed at a fraction of the axes\n",
+ "#ax.spines['bottom'].set_position(('axes', 0.75))\n",
+ "#ax.spines['left'].set_position(('axes', 0.25))\n",
+ "\n",
+ "plt.show()"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Exercise 1.3\n",
+ "\n",
+ "This one is a bit trickier. Once again, try to reproduce the figure below:\n",
+ "\n",
+ "
\n",
+ "\n",
+ "\n",
+ "A few key hints: The two subplots have no vertical space between them (this means that the `hspace` is `0`). Note that the bottom spine is at 0 in data coordinates and the tick lines are missing from the left and top sides.\n",
+ "\n",
+ "Because you're going to be doing a lot of the same things to both subplots, to avoid repitive code you might consider writing a function that takes an `Axes` object and makes the spine changes, etc to it. \n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "collapsed": false,
+ "input": [
+ "%load exercises/1.2-spines.py"
+ ],
+ "language": "python",
+ "metadata": {},
+ "outputs": [],
+ "prompt_number": null
+ }
+ ],
+ "metadata": {}
+ }
+ ]
+}
\ No newline at end of file