{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Plotting with python\n", "\n", "The main plotting module in python is `matplotlib`. There is a lot\n", "that can be done with it - see the [webpage](https://matplotlib.org/gallery/index.html)\n", "\n", "\n", "## Contents\n", "\n", "* [Running inside a notebook](#inside-notebook)\n", " * [2D plots](#2D-plots)\n", " * [Histograms and Bar Plots](#histograms)\n", " * [Scatter plots](#scatter-plots)\n", " * [Subplots](#subplots)\n", " * [Displaying Images](#displaying-images)\n", " * [3D plots](#3D-plots)\n", "* [Running in a standalone script](#plotting-in-scripts)\n", "* [Exercise](#exercise)\n", "\n", "---\n", "\n", "\n", "<a class=\"anchor\" id=\"inside-notebook\"></a>\n", "## Inside a notebook\n", "\n", "Inside a jupyter notebook you get access to this in a slightly\n", "different way, compared to other modules:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This only needs to be done once in a notebook, like for standard imports.\n", "\n", "> There are also other alternatives, including interactive versions - see the practical on Jupyter notebooks for more information about this.\n", "\n", "\n", "The library works very similarly to plotting in matlab. Let's start\n", "with some simple examples.\n", "\n", "<a class=\"anchor\" id=\"2D-plots\"></a>\n", "### 2D plots" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "plt.style.use('bmh')\n", "\n", "x = np.linspace(-np.pi, np.pi, 256)\n", "cosx, sinx = np.cos(x), np.sin(x)\n", "\n", "plt.plot(x, cosx)\n", "plt.plot(x, sinx, color='red', linewidth=4, linestyle='-.')\n", "plt.plot(x, sinx**2)\n", "plt.xlim(-np.pi, np.pi)\n", "plt.title('Our first plots')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> Note that the `plt.style.use('bmh')` command is not necessary, but it\n", "> does make nicer looking plots in general. You can use `ggplot`\n", "> instead of `bmh` if you want something resembling plots made by R.\n", "> For a list of options run: `print(plt.style.available)`\n", "\n", "You can also save the objects and interrogate/set their properties, as\n", "well as those for the general axes:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "hdl = plt.plot(x, cosx)\n", "print(hdl[0].get_color())\n", "hdl[0].set_color('#707010')\n", "hdl[0].set_linewidth(0.5)\n", "plt.grid('off')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Use `dir()` or `help()` or the online docs to get more info on what\n", "you can do with these.\n", "\n", "<a class=\"anchor\" id=\"histograms\"></a>\n", "### Histograms and bar charts\n", "\n", "For a simple histogram you can do this:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "r = np.random.rand(1000)\n", "n,bins,_ = plt.hist((r-0.5)**2, bins=30)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "where it also returns the number of elements in each bin, as `n`, and\n", "the bin centres, as `bins`.\n", "\n", "> The `_` in the third part on the left\n", "> hand side is a shorthand for just throwing away the corresponding part\n", "> of the return structure.\n", "\n", "\n", "There is also a call for doing bar plots:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "samp1 = r[0:10]\n", "samp2 = r[10:20]\n", "bwidth = 0.3\n", "xcoord = np.arange(10)\n", "plt.bar(xcoord-bwidth, samp1, width=bwidth, color='red', label='Sample 1')\n", "plt.bar(xcoord, samp2, width=bwidth, color='blue', label='Sample 2')\n", "plt.legend(loc='upper left')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a class=\"anchor\" id=\"scatter-plots\"></a>\n", "### Scatter plots\n", "\n", "It would be possible to use `plot()` to create a scatter plot, but\n", "there is also an alternative: `scatter()`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "# setup some sizes for each point (arbitrarily example here)\n", "ssize = 100*abs(samp1-samp2) + 10\n", "ax.scatter(samp1, samp2, s=ssize, alpha=0.5)\n", "# now add the y=x line\n", "allsamps = np.hstack((samp1,samp2))\n", "ax.plot([min(allsamps),max(allsamps)],[min(allsamps),max(allsamps)], color='red', linestyle='--')\n", "plt.xlim(min(allsamps),max(allsamps))\n", "plt.ylim(min(allsamps),max(allsamps))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> Note that in this case we use the first line return to get a handle to\n", "> the axis, `ax`, and the figure ,`fig`. The axis can be used instead of\n", "> `plt` in most cases, although the `xlim()` and `ylim()` calls can only\n", "> be done through `plt`.\n", "\n", "> In general, figures and subplots can be created in matplotlib in a\n", "> similar fashion to matlab, but they do not have to be explicitly\n", "> invoked as you can see from the earlier examples.\n", "\n", "<a class=\"anchor\" id=\"subplots\"></a>\n", "### Subplots\n", "\n", "These are very similar to matlab:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.subplot(2, 1, 1)\n", "plt.plot(x,cosx, '.-')\n", "plt.xlim(-np.pi, np.pi)\n", "plt.ylabel('Full sampling')\n", "plt.subplot(2, 1, 2)\n", "plt.plot(x[::30], cosx[::30], '.-')\n", "plt.xlim(-np.pi, np.pi)\n", "plt.ylabel('Subsampled')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a class=\"anchor\" id=\"displaying-images\"></a>\n", "### Displaying images\n", "\n", "The main command for displaying images is `imshow()`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import nibabel as nib\n", "import os.path as op\n", "nim = nib.load(op.expandvars('${FSLDIR}/data/standard/MNI152_T1_1mm.nii.gz'), mmap=False)\n", "imdat = nim.get_data().astype(float)\n", "imslc = imdat[:,:,70]\n", "plt.imshow(imslc, cmap=plt.cm.gray)\n", "plt.colorbar()\n", "plt.grid('off')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that matplotlib will use the **voxel data orientation**, and that\n", "configuring the plot orientation is **your responsibility**. To rotate a\n", "slice, simply transpose the data (`.T`). To invert the data along along an\n", "axis, you don't need to modify the data - simply swap the axis limits around:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.imshow(imslc.T, cmap=plt.cm.gray)\n", "plt.xlim(reversed(plt.xlim()))\n", "plt.ylim(reversed(plt.ylim()))\n", "plt.colorbar()\n", "plt.grid('off')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a class=\"anchor\" id=\"3D-plots\"></a>\n", "### 3D plots" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Taken from https://matplotlib.org/gallery/mplot3d/wire3d.html#sphx-glr-gallery-mplot3d-wire3d-py\n", "\n", "from mpl_toolkits.mplot3d import axes3d\n", "\n", "fig = plt.figure()\n", "ax = fig.add_subplot(111, projection='3d')\n", "\n", "# Grab some test data.\n", "X, Y, Z = axes3d.get_test_data(0.05)\n", "\n", "# Plot a basic wireframe.\n", "ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Surface renderings are many other plots are possible - see 3D examples on\n", "the [matplotlib webpage](https://matplotlib.org/gallery/index.html#mplot3d-examples-index)\n", "\n", "---\n", "\n", "<a class=\"anchor\" id=\"plotting-in-scripts\"></a>\n", "## Plotting from standalone scripts\n", "\n", "When running from a standalone script, the same `matplotlib` import is required,\n", "but the line `%matplotlib <backend>` should *not* be used.\n", "\n", "In a script it is also necessary to _finish_ with `plt.show()` as\n", "otherwise nothing is actually displayed. For example, the above\n", "examples would setup a plot but the actual graphic would only appear\n", "after the `plt.show()` command was executed. Furthermore, control is\n", "not returned to the script immediately as the plot is interactive by default.\n", "\n", "---\n", "\n", "<a class=\"anchor\" id=\"exercise\"></a>\n", "## Exercise\n", "\n", "Find a different type of plot (e.g., boxplot, violin plot, quiver\n", "plot, pie chart, etc.), look up\n", "the documentation and then write _your own code that calls this_ to create a plot\n", "from some data that you create yourself (i.e., don't just blindly copy\n", "example code from the docs)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Make up some data and do the funky plot" ] } ], "metadata": {}, "nbformat": 4, "nbformat_minor": 2 }