{ "metadata": { "name": "AnatomyOfMatplotlib-Part1-pyplot" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "code", "collapsed": false, "input": [ "# Turning on inline plots -- just for use in ipython notebooks.\n", "%pylab inline" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "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", "## 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 (more on that later).\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", "A newer 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)).\n", "\n", "## What is this \"backend\" thing I keep hearing about?\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. However, bugs do occur, and so two of the most important pieces of information you can provide in a bug report is which version of matplotlib, and which backend.\n", "\n" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import matplotlib\n", "print matplotlib.__version__\n", "print matplotlib.get_backend()" ], "language": "python", "metadata": {}, "outputs": [] }, { "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", "We start with the most important import statement you will ever need for matplotlib" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import matplotlib.pyplot as plt" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# pyplot\n", "The pyplot module is where everything in matplotlib comes together. It is the launching point for preparing your figures, making plots, and doing any modifications and decorations you want. It all starts here. Let us take a look at those three catagories of pyplot functions.\n", "\n", "## Plotting Preparation" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "================== ===========================================================================================\n", "Function Description \n", "================== ===========================================================================================\n", "`autoscale` Autoscale the axis view to the data (toggle).\n", "`axes` Add an axes to the figure. \n", "`axis` Convenience method to get or set axis properties.\n", "`cla` Clear the current axes. \n", "`clf` Clear the current figure. \n", "`clim` Set the color limits of the current image. \n", "`delaxes` Remove an axes from the current figure. \n", "`locator_params` Control behavior of tick locators. \n", "`margins` Set or retrieve autoscaling margins.\n", "`figure` Creates a new figure. \n", "`gca` Return the current axis instance. \n", "`gcf` Return a reference to the current figure. \n", "`gci` Get the current colorable artist. \n", "`hold` Set the hold state. \n", "`ioff` Turn interactive mode off. \n", "`ion` Turn interactive mode on. \n", "`ishold` Return the hold status of the current axes. \n", "`isinteractive` Return status of interactive mode. \n", "`rc` Set the current rc params. \n", "`rc_context` Return a context manager for managing rc settings. \n", "`rcdefaults` Restore the default rc params. \n", "`savefig` Save the current figure. \n", "`sca` Set the current Axes instance to *ax*. \n", "`sci` Set the current image. \n", "`set_cmap` Set the default colormap. \n", "`setp` Set a property on an artist object. \n", "`show` Display a figure. \n", "`subplot` Return a subplot axes positioned by the given grid definition. \n", "`subplot2grid` Create a subplot in a grid. \n", "`subplot_tool` Launch a subplot tool window for a figure. \n", "`subplots` Create a figure with a set of subplots already made. \n", "`subplots_adjust` Tune the subplot layout. \n", "`switch_backend` Switch the default backend. \n", "`tick_params` Change the appearance of ticks and tick labels. \n", "`ticklabel_format` Change the `~matplotlib.ticker.ScalarFormatter` used by default for linear axes. \n", "`tight_layout` Automatically adjust subplot parameters to give specified padding. \n", "`xkcd` Turns on `xkcd `_ sketch-style drawing mode. \n", "`xlabel` Set the *x* axis label of the current axis. \n", "`xlim` Get or set the *x* limits of the current axes. \n", "`xscale` Set the scaling of the *x*-axis. \n", "`xticks` Get or set the *x*-limits of the current tick locations and labels. \n", "`ylabel` Set the *y* axis label of the current axis. \n", "`ylim` Get or set the *y*-limits of the current axes. \n", "`yscale` Set the scaling of the *y*-axis. \n", "`yticks` Get or set the *y*-limits of the current tick locations and labels. \n", "================== ===========================================================================================" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plotting Functions" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "================== ===========================================================================================\n", "Function Description \n", "================== ===========================================================================================\n", "`acorr` Plot the autocorrelation of *x*. \n", "`bar` Make a bar plot. \n", "`barbs` Plot a 2-D field of barbs. \n", "`barh` Make a horizontal bar plot. \n", "`boxplot` Make a box and whisker plot. \n", "`broken_barh` Plot horizontal bars.\n", "`cohere` Plot the coherence between *x* and *y*. \n", "`contour` Plot contours. \n", "`contourf` Plot filled contours. \n", "`csd` Plot cross-spectral density. \n", "`errorbar` Plot an errorbar graph. \n", "`eventplot` Plot identical parallel lines at specific positions. \n", "`fill` Plot filled polygons. \n", "`fill_between` Make filled polygons between two curves. \n", "`fill_betweenx` Make filled polygons between two horizontal curves. \n", "`hexbin` Make a hexagonal binning plot. \n", "`hist` Plot a histogram. \n", "`hist2d` Make a 2D histogram plot. \n", "`imshow` Display an image on the axes. \n", "`loglog` Make a plot with log scaling on both the *x* and *y* axis. \n", "`matshow` Display an array as a matrix in a new figure window. \n", "`pcolor` Create a pseudocolor plot of a 2-D array. \n", "`pcolormesh` Plot a quadrilateral mesh. \n", "`pie` Plot a pie chart. \n", "`plot` Plot lines and/or markers to the :class:`~matplotlib.axes.Axes`. \n", "`plot_date` Plot with data with dates. \n", "`polar` Make a polar plot. \n", "`psd` Plot the power spectral density. \n", "`quiver` Plot a 2-D field of arrows. \n", "`scatter` Make a scatter plot of x vs y, where x and y are sequence like objects of the same lengths.\n", "`semilogx` Make a plot with log scaling on the *x* axis. \n", "`semilogy` Make a plot with log scaling on the *y* axis. \n", "`specgram` Plot a spectrogram. \n", "`spy` Plot the sparsity pattern on a 2-D array. \n", "`stackplot` Draws a stacked area plot. \n", "`stem` Create a stem plot. \n", "`step` Make a step plot. \n", "`streamplot` Draws streamlines of a vector flow. \n", "`tricontour` Draw contours on an unstructured triangular grid. \n", "`tricontourf` Draw contours on an unstructured triangular grid. \n", "`tripcolor` Create a pseudocolor plot of an unstructured triangular grid. \n", "`triplot` Draw a unstructured triangular grid as lines and/or markers.\n", "`xcorr` Plot the cross-correlation between *x* and *y*." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plot modifiers" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "================== ===========================================================================================\n", "Function Description \n", "================== ===========================================================================================\n", "`annotate` Create an annotation: a piece of text referring to a data point. \n", "`arrow` Add an arrow to the axes. \n", "`axhline` Add a horizontal line across the axis. \n", "`axhspan` Add a horizontal span (rectangle) across the axis. \n", "`axvline` Add a vertical line across the axes. \n", "`axvspan` Add a vertical span (rectangle) across the axes. \n", "`box` Turn the axes box on or off. \n", "`clabel` Label a contour plot. \n", "`colorbar` Add a colorbar to a plot. \n", "`grid` Turn the axes grids on or off.\n", "`hlines` Plot horizontal lines.\n", "`legend` Place a legend on the current axes. \n", "`minorticks_off` Remove minor ticks from the current plot. \n", "`minorticks_on` Display minor ticks on the current plot. \n", "`quiverkey` Add a key to a quiver plot.\n", "`rgrids` Get or set the radial gridlines on a polar plot. \n", "`suptitle` Add a centered title to the figure. \n", "`table` Add a table to the current axes. \n", "`text` Add text to the axes. \n", "`title` Set a title of the current axes. \n", "`vlines` Plot vertical lines. \n", "`xlabel` Set the *x* axis label of the current axis. \n", "`ylabel` Set the *y* axis label of the current axis. \n", "================== ===========================================================================================" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Figure\n", "## Introduction\n", "All plotting is done through the *figure* object. You can create as many figures as you need. Figures can't do much by themselves, but no plotting can happen without them. They are, literally, the \"canvas\" of your plot." ] }, { "cell_type": "code", "collapsed": false, "input": [ "fig = plt.figure()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Awww, nothing happened! This is because by default mpl will not show anything until told to do so. In other words, the \"interactive mode\" is turned off. This is very useful for scripting where we would not ever want to see the intermediate results. For those who wishes to experiment and want to see their plot as they issue commands, there is the \"plt.ion()\" command they can issue before creating their first figure of their session. For the purpoase of this tutorial, we will leave interactivity off.\n", "\n", "## Figure properties\n", "* figsize : tuple of integers, width, height in inches.\n", " \n", "* dpi : integer, esolution of the figure in dots per inch." ] }, { "cell_type": "code", "collapsed": false, "input": [ "fig = plt.figure(figsize=(10, 4))\n", "fig.gca() # needed for the pylab-inline to display anything\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "fig = plt.figure(figsize=plt.figaspect(2.0)) # Twice as tall\n", "fig.gca()\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Breakdown of a figure\n", "Open the file \"plot_demo.svg\" included with this notebook in a new tab." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Axes\n", "All plotting is done with respect to an *Axes*. An *Axes* is made up of *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." ] }, { "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])\n", "ax.set_xlim(0.5, 4.5)\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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])\n", "plt.xlim(0.5, 4.5)\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "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 \"Explicit is better than implicit\". 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." ] }, { "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(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", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A 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 to 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": [] }, { "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": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise\n", "How would you make a plot with a y-axis such that it starts at 1000 at the bottom, and goes to 500 at the top?" ] }, { "cell_type": "code", "collapsed": false, "input": [ "fig, ax = plt.subplots(1, 1)\n", "ax.set_ylim( )\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Labels and Legends\n", "You can label just about anything in mpl. You can provide a label to your plot, which allows your legend to automatically build itself. The X and Y axis can also be labeled, as well as the subplot itself via the title." ] }, { "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], label='Philadelphia')\n", "ax.plot([1, 2, 3, 4], [30, 23, 13, 4], label='Boston')\n", "ax.set_ylabel('Temperature (deg C)')\n", "ax.set_xlabel('Time')\n", "ax.set_title(\"A tale of two cities\")\n", "ax.legend()\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Also, if you happen to be plotting something that you do not want to appear in the legend, just set the label to \"\\_nolegend\\_\"." ] }, { "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\")\n", "ax.plot([1, 2, 3, 4], [10, 20, 25, 30], label=\"_nolegend_\")\n", "ax.legend()\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ticks, Tick Lines, Tick Labels and Tickers\n", "This is a constant source of confusion:\n", "\n", "* A Tick defines 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 automatically determines the Ticks for an Axis." ] }, { "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])\n", "ax.xaxis.set_ticks(range(1, 5)) # Set ticks at 1, 2, 3, 4\n", "ax.xaxis.set_ticklabels([3, 100, -12, \"foo\"]) # Label ticks as \"3\", \"100\", \"-12\", and \"foo\"\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Subplots\n", "While an *Axes* object can only belong to one *Figure*, A *Figure* can have many *Axes* objects. These are typically called \"subaxes\" or \"subplots\". They act just like regular *Axes*." ] }, { "cell_type": "code", "collapsed": false, "input": [ "fig = plt.figure(figsize=(10, 5))\n", "ax = fig.add_subplot(121)\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_title('A tale of two cities')\n", "ax.legend()\n", "\n", "t = np.linspace(0, 7, 25)\n", "z = 2 * np.sin(t) + 5\n", "ax = fig.add_subplot(122)\n", "ax.scatter(t, z, label='Philadelphia')\n", "ax.set_title(\"Observed Tide\")\n", "ax.legend()\n", "\n", "fig.suptitle('A title for the whole figure')\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are many ways to add and modify subplots in a figure.\n", "\n", "* `plt.subplots()`\n", "* `plt.subplot()` and `fig.add_subplot()` Which should be familiar to all Matlab users\n", "* `plt.axes()`\n", "* `plt.subplot2grid()`\n", "* `plt.subplot_tool()` Interactive modification of subplot spacing.\n", "\n", "## Spacing\n", "The spacing between the subplots can be adjusted using `plt.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", "plt.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": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A common complaint with matplotlib users is that the labels do not fit with the subplots, or the label of one subplot spills onto another subplot's area. 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\" feature, when invoked, will attempt to resize margins, and subplots so that nothing overlaps." ] }, { "cell_type": "code", "collapsed": false, "input": [ "# Without \"tight_layout\"\n", "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", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "# With \"tight_layout\"\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", "plt.tight_layout()\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As a last bit of an FAQ, this \"tight_layout\" feature is unrelated to the so-called \"bbox_inches='tight'\" feature that will be discussed separately." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## GridSpec\n", "Under the hood, matplotlib utilizes GridSpec to layout 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": [ "## \"Twining\" axis\n", "There will be times when you want to have the x axis and/or the y axis of your subplots to be \"twined\" or \"shared\". Twining 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 twinned axis. 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 twinned axis 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": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Axis Spines" ] }, { "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])\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", "ax.spines['bottom'].set_position(('outward', 10))\n", "ax.spines['left'].set_position(('outward', 10))\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercise\n", "Modify the above example to have spines and tick labels on both sides, with tickmarks *through* the spines." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Colorbars\n", "While not required for plotting, colorbars are much like legends because they help to describe the data being displayed. While legends describe plots, i.e., plot(), scatter(), hist(), stem(), colorbars describe images. To be really specific and technical, they can be used for any \"ScalarMappable\", which will be discussed in the Artists section. Let us take a look at a very simple example of a colorbar for a simple 2D image." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy as np\n", "y, x = np.ogrid[-6:6:20j, -10:10:30j]\n", "z = np.hypot(x, y)\n", "plt.imshow(z)\n", "plt.colorbar()\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "plt.imshow(z)\n", "plt.colorbar(orientation='horizontal', shrink=0.75) # We can make colorbars do all sorts of things!\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "plt.imshow(z)\n", "cbar = plt.colorbar(extend='both', aspect=10)\n", "cbar.set_label('distance') # And we can even add a label to it\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Colorbars in matplotlib can be difficult at times, and the documentation can sometimes be a bit unhelpful (patches welcome!). One of the most common problems that come up is when mixing subplots with a single colorbar:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "fig, (ax1, ax2) = plt.subplots(1, 2)\n", "ax1.imshow(z)\n", "im = ax2.imshow(z) # Note, due to a bug, you will need to save the\n", " # returned image object when calling imshow() from an Axes\n", " # and pass that to plt.colorbar() so that it knows what\n", " # image to build a colorbar from. This will be fixed for v1.3.1.\n", "plt.colorbar(im)\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Looks terrible, right? What is happening is that a colorbar in matplotlib is just a very squashed subplot with an image of the colormap and axis ticks and labels. When told to create a colorbar for an image, matplotlib will simply \"steal\" space from that image's subplot and create a new subplot. There are a couple ways to deal with this issue. First, if you preallocate space for the colorbar (by creating your own Axes object to add to the Figure), you can pass that preallocated Axes to the \"cax\" argument of `plt.colorbar()`, and it won't have to steal any space. The easier option is to pass a list of all the axes objects to `plt.colorbar(..., ax)`, and it will steal space equally from them." ] }, { "cell_type": "code", "collapsed": false, "input": [ "fig, (ax1, ax2) = plt.subplots(1, 2)\n", "ax1.imshow(z)\n", "im = ax2.imshow(z)\n", "plt.colorbar(im, ax=[ax1, ax2], shrink=0.5)\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There is also a third, very powerful option, called `axes_grid1`, which we will discuss in the `mpl_toolkits` section." ] } ], "metadata": {} } ] }