{ "metadata": { "name": "AnatomyOfMatplotlib-Part4-mpl_toolkits" }, "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\n", "import numpy as np\n", "import matplotlib.pyplot as plt" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# mpl_toolkits" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In addition to the core library of matplotlib, there are a few additional utilities that are set apart from matplotlib proper for some reason or another, but are often shipped with matplotlib.\n", "\n", "* [Basemap](http://matplotlib.org/basemap/) - shipped separately from matplotlib due to size of mapping data that are included.\n", "* [mplot3d](http://matplotlib.org/mpl_toolkits/mplot3d/index.html#toolkit-mplot3d-index) - shipped with matplotlib to provide very simple, rudimentary 3D plots in the same style as matplotlib's 2D plots.\n", "* [axes_grid1](http://matplotlib.org/mpl_toolkits/axes_grid/users/overview.html) - An enhanced SubplotAxes. Very Enhanced..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# mplot3d\n", "By taking advantage of matplotlib's z-order layering engine, mplot3d emulates 3D plotting by projecting 3D data into 2D space, layer by layer. While it isn't going to replace any of the true 3D plotting libraries anytime soon, its goal is to allow for matplotlib users to produce 3D plots with the same amount of simplicity as 2D plots are." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from mpl_toolkits.mplot3d import Axes3D, axes3d\n", "\n", "fig, ax = plt.subplots(1, 1, subplot_kw={'projection': '3d'})\n", "X, Y, Z = axes3d.get_test_data(0.05)\n", "ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)\n", "\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# axes_grid1\n", "This module was originally intended as a collection of helper classes to ease the displaying of (possibly multiple) images with matplotlib. Some of the functionality has come to be useful for non-image plotting as well. Some classes deals with the sizing and possitioning of multiple Axes relative to each other (ImageGrid, RGB Axes, and AxesDivider). The ParasiteAxes allow for the plotting of multiple datasets in the same axes, but with each their own x or y scale. Also, there is the AnchoredArtist that can be used to anchor particular artist objects in place.\n", "\n", "One can get a sense of the neat things that can be done with this toolkit by browsing through its user guide linked above. There is one particular feature that is an absolute must-have for me -- automatic allocation of space for colorbars." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from mpl_toolkits.axes_grid1 import AxesGrid\n", "fig = plt.figure()\n", "grid = AxesGrid(fig, 111, # similar to subplot(111)\n", " nrows_ncols = (2, 2),\n", " axes_pad = 0.2,\n", " share_all=True,\n", " label_mode = \"L\", # similar to \"label_outer\"\n", " cbar_location = \"right\",\n", " cbar_mode=\"single\",\n", " )\n", "\n", "extent = (-3,4,-4,3)\n", "for i in range(4):\n", " im = grid[i].imshow(Z, extent=extent, interpolation=\"nearest\")\n", " \n", "grid.cbar_axes[0].colorbar(im)\n", "plt.show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This next feature is commonly requested on the mailing lists. The problem is that most people who request it don't quite know how to describe it. We call it \"Parasite Axes\"." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%load http://matplotlib.org/mpl_examples/axes_grid/demo_parasite_axes2.py" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "from mpl_toolkits.axes_grid1 import host_subplot\n", "import mpl_toolkits.axisartist as AA\n", "\n", "host = host_subplot(111, axes_class=AA.Axes)\n", "plt.subplots_adjust(right=0.75)\n", "\n", "par1 = host.twinx()\n", "par2 = host.twinx()\n", "\n", "offset = 60\n", "new_fixed_axis = par2.get_grid_helper().new_fixed_axis\n", "par2.axis[\"right\"] = new_fixed_axis(loc=\"right\",\n", " axes=par2,\n", " offset=(offset, 0))\n", " \n", "par2.axis[\"right\"].toggle(all=True)\n", "\n", "host.set_xlim(0, 2)\n", "host.set_ylim(0, 2)\n", "\n", "host.set_xlabel(\"Distance\")\n", "host.set_ylabel(\"Density\")\n", "par1.set_ylabel(\"Temperature\")\n", "par2.set_ylabel(\"Velocity\")\n", "\n", "p1, = host.plot([0, 1, 2], [0, 1, 2], label=\"Density\")\n", "p2, = par1.plot([0, 1, 2], [0, 3, 2], label=\"Temperature\")\n", "p3, = par2.plot([0, 1, 2], [50, 30, 15], label=\"Velocity\")\n", "\n", "par1.set_ylim(0, 4)\n", "par2.set_ylim(1, 65)\n", "\n", "host.legend()\n", "\n", "host.axis[\"left\"].label.set_color(p1.get_color())\n", "par1.axis[\"right\"].label.set_color(p2.get_color())\n", "par2.axis[\"right\"].label.set_color(p3.get_color())\n", "\n", "plt.show()\n" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And finally, as a nice, teaser of what else axes_grid1 can do..." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%load http://matplotlib.org/mpl_toolkits/axes_grid/examples/demo_floating_axes.py" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "from matplotlib.transforms import Affine2D\n", "\n", "import mpl_toolkits.axisartist.floating_axes as floating_axes\n", "\n", "import numpy as np\n", "import mpl_toolkits.axisartist.angle_helper as angle_helper\n", "from matplotlib.projections import PolarAxes\n", "from mpl_toolkits.axisartist.grid_finder import FixedLocator, MaxNLocator, \\\n", " DictFormatter\n", "\n", "def setup_axes1(fig, rect):\n", " \"\"\"\n", " A simple one.\n", " \"\"\"\n", " tr = Affine2D().scale(2, 1).rotate_deg(30)\n", "\n", " grid_helper = floating_axes.GridHelperCurveLinear(tr, extremes=(0, 4, 0, 4))\n", "\n", " ax1 = floating_axes.FloatingSubplot(fig, rect, grid_helper=grid_helper)\n", " fig.add_subplot(ax1)\n", "\n", " aux_ax = ax1.get_aux_axes(tr)\n", "\n", " grid_helper.grid_finder.grid_locator1._nbins = 4\n", " grid_helper.grid_finder.grid_locator2._nbins = 4\n", "\n", " return ax1, aux_ax\n", "\n", "\n", "def setup_axes2(fig, rect):\n", " \"\"\"\n", " With custom locator and formatter.\n", " Note that the extreme values are swapped.\n", " \"\"\"\n", "\n", " #tr_scale = Affine2D().scale(np.pi/180., 1.)\n", "\n", " tr = PolarAxes.PolarTransform()\n", "\n", " pi = np.pi\n", " angle_ticks = [(0, r\"$0$\"),\n", " (.25*pi, r\"$\\frac{1}{4}\\pi$\"),\n", " (.5*pi, r\"$\\frac{1}{2}\\pi$\")]\n", " grid_locator1 = FixedLocator([v for v, s in angle_ticks])\n", " tick_formatter1 = DictFormatter(dict(angle_ticks))\n", "\n", " grid_locator2 = MaxNLocator(2)\n", "\n", " grid_helper = floating_axes.GridHelperCurveLinear(tr,\n", " extremes=(.5*pi, 0, 2, 1),\n", " grid_locator1=grid_locator1,\n", " grid_locator2=grid_locator2,\n", " tick_formatter1=tick_formatter1,\n", " tick_formatter2=None,\n", " )\n", "\n", " ax1 = floating_axes.FloatingSubplot(fig, rect, grid_helper=grid_helper)\n", " fig.add_subplot(ax1)\n", "\n", " # create a parasite axes whose transData in RA, cz\n", " aux_ax = ax1.get_aux_axes(tr)\n", "\n", " aux_ax.patch = ax1.patch # for aux_ax to have a clip path as in ax\n", " ax1.patch.zorder=0.9 # but this has a side effect that the patch is\n", " # drawn twice, and possibly over some other\n", " # artists. So, we decrease the zorder a bit to\n", " # prevent this.\n", "\n", " return ax1, aux_ax\n", "\n", "\n", "def setup_axes3(fig, rect):\n", " \"\"\"\n", " Sometimes, things like axis_direction need to be adjusted.\n", " \"\"\"\n", "\n", " # rotate a bit for better orientation\n", " tr_rotate = Affine2D().translate(-95, 0)\n", "\n", " # scale degree to radians\n", " tr_scale = Affine2D().scale(np.pi/180., 1.)\n", "\n", " tr = tr_rotate + tr_scale + PolarAxes.PolarTransform()\n", "\n", " grid_locator1 = angle_helper.LocatorHMS(4)\n", " tick_formatter1 = angle_helper.FormatterHMS()\n", "\n", " grid_locator2 = MaxNLocator(3)\n", "\n", " ra0, ra1 = 8.*15, 14.*15\n", " cz0, cz1 = 0, 14000\n", " grid_helper = floating_axes.GridHelperCurveLinear(tr,\n", " extremes=(ra0, ra1, cz0, cz1),\n", " grid_locator1=grid_locator1,\n", " grid_locator2=grid_locator2,\n", " tick_formatter1=tick_formatter1,\n", " tick_formatter2=None,\n", " )\n", "\n", " ax1 = floating_axes.FloatingSubplot(fig, rect, grid_helper=grid_helper)\n", " fig.add_subplot(ax1)\n", "\n", " # adjust axis\n", " ax1.axis[\"left\"].set_axis_direction(\"bottom\")\n", " ax1.axis[\"right\"].set_axis_direction(\"top\")\n", "\n", " ax1.axis[\"bottom\"].set_visible(False)\n", " ax1.axis[\"top\"].set_axis_direction(\"bottom\")\n", " ax1.axis[\"top\"].toggle(ticklabels=True, label=True)\n", " ax1.axis[\"top\"].major_ticklabels.set_axis_direction(\"top\")\n", " ax1.axis[\"top\"].label.set_axis_direction(\"top\")\n", "\n", " ax1.axis[\"left\"].label.set_text(r\"cz [km$^{-1}$]\")\n", " ax1.axis[\"top\"].label.set_text(r\"$\\alpha_{1950}$\")\n", "\n", "\n", " # create a parasite axes whose transData in RA, cz\n", " aux_ax = ax1.get_aux_axes(tr)\n", "\n", " aux_ax.patch = ax1.patch # for aux_ax to have a clip path as in ax\n", " ax1.patch.zorder=0.9 # but this has a side effect that the patch is\n", " # drawn twice, and possibly over some other\n", " # artists. So, we decrease the zorder a bit to\n", " # prevent this.\n", "\n", " return ax1, aux_ax\n", "\n", "\n", "\n", "if 1:\n", " import matplotlib.pyplot as plt\n", " fig = plt.figure(1, figsize=(8, 4))\n", " fig.subplots_adjust(wspace=0.3, left=0.05, right=0.95)\n", "\n", " ax1, aux_ax2 = setup_axes1(fig, 131)\n", " aux_ax2.bar([0, 1, 2, 3], [3, 2, 1, 3])\n", " \n", " #theta = np.random.rand(10) #*.5*np.pi\n", " #radius = np.random.rand(10) #+1.\n", " #aux_ax1.scatter(theta, radius)\n", "\n", "\n", " ax2, aux_ax2 = setup_axes2(fig, 132)\n", "\n", " theta = np.random.rand(10)*.5*np.pi\n", " radius = np.random.rand(10)+1.\n", " aux_ax2.scatter(theta, radius)\n", "\n", "\n", " ax3, aux_ax3 = setup_axes3(fig, 133)\n", "\n", " theta = (8 + np.random.rand(10)*(14-8))*15. # in degrees\n", " radius = np.random.rand(10)*14000.\n", " aux_ax3.scatter(theta, radius)\n", "\n", " plt.show()\n", "\n" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] } ], "metadata": {} } ] }