Commit 96f3b243 authored by Michiel Cottaar's avatar Michiel Cottaar Committed by Michiel Cottaar
Browse files

Explain plt.getp

parent e8296319
......@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
"id": "christian-smart",
"id": "5567ba9e",
"metadata": {},
"source": [
"# Matplotlib tutorial\n",
......@@ -48,7 +48,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "quick-postage",
"id": "3917392c",
"metadata": {},
"outputs": [],
"source": [
......@@ -58,7 +58,7 @@
},
{
"cell_type": "markdown",
"id": "prescribed-writing",
"id": "76688c00",
"metadata": {},
"source": [
"<a class=\"anchor\" id=\"line\"></a>\n",
......@@ -69,7 +69,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "turkish-marsh",
"id": "00d5ff18",
"metadata": {},
"outputs": [],
"source": [
......@@ -78,7 +78,7 @@
},
{
"cell_type": "markdown",
"id": "compact-modeling",
"id": "3d0472b7",
"metadata": {},
"source": [
"To adjust how the line is plotted, check the documentation:"
......@@ -87,7 +87,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "distinct-coordinate",
"id": "38d3f3ab",
"metadata": {},
"outputs": [],
"source": [
......@@ -96,7 +96,7 @@
},
{
"cell_type": "markdown",
"id": "green-dutch",
"id": "867ea1f5",
"metadata": {},
"source": [
"As you can see there are a lot of options.\n",
......@@ -109,7 +109,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "adjacent-satellite",
"id": "c705366a",
"metadata": {},
"outputs": [],
"source": [
......@@ -123,7 +123,7 @@
},
{
"cell_type": "markdown",
"id": "external-meaning",
"id": "f7e493a7",
"metadata": {},
"source": [
"Because these keywords are so common, you can actually set one or more of them by passing in a string as the third argument."
......@@ -132,7 +132,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "simple-korean",
"id": "c2b6c5c5",
"metadata": {},
"outputs": [],
"source": [
......@@ -145,7 +145,7 @@
},
{
"cell_type": "markdown",
"id": "pediatric-sullivan",
"id": "c7dd3aa9",
"metadata": {},
"source": [
"<a class=\"anchor\" id=\"scatter\"></a>\n",
......@@ -156,7 +156,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "bright-preparation",
"id": "33b81ef4",
"metadata": {},
"outputs": [],
"source": [
......@@ -168,7 +168,7 @@
},
{
"cell_type": "markdown",
"id": "asian-mailing",
"id": "22de1aac",
"metadata": {},
"source": [
"The third argument is the variable determining the size, while the fourth argument is the variable setting the color.\n",
......@@ -180,7 +180,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "massive-relative",
"id": "0c445269",
"metadata": {},
"outputs": [],
"source": [
......@@ -190,7 +190,7 @@
},
{
"cell_type": "markdown",
"id": "positive-insight",
"id": "41a54dd8",
"metadata": {},
"source": [
"where it also returns the number of elements in each bin, as `n`, and\n",
......@@ -207,7 +207,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "intensive-taste",
"id": "9d7c817d",
"metadata": {},
"outputs": [],
"source": [
......@@ -222,7 +222,7 @@
},
{
"cell_type": "markdown",
"id": "boolean-metropolitan",
"id": "eca1cea7",
"metadata": {},
"source": [
"> If you want more advanced distribution plots beyond a simple histogram, have a look at the seaborn [gallery](https://seaborn.pydata.org/examples/index.html) for (too?) many options.\n",
......@@ -236,7 +236,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "basic-cambridge",
"id": "939fcf82",
"metadata": {},
"outputs": [],
"source": [
......@@ -249,7 +249,7 @@
},
{
"cell_type": "markdown",
"id": "twelve-assist",
"id": "cb1a8d17",
"metadata": {},
"source": [
"<a class=\"anchor\" id=\"shade\"></a>\n",
......@@ -260,7 +260,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "stuck-teaching",
"id": "f7221bc3",
"metadata": {},
"outputs": [],
"source": [
......@@ -270,7 +270,7 @@
},
{
"cell_type": "markdown",
"id": "metric-chemical",
"id": "86d77cf6",
"metadata": {},
"source": [
"This can be nicely combined with a polar projection, to create 2D orientation distribution functions:"
......@@ -279,7 +279,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "democratic-israel",
"id": "b96cbc10",
"metadata": {},
"outputs": [],
"source": [
......@@ -290,7 +290,7 @@
},
{
"cell_type": "markdown",
"id": "connected-consideration",
"id": "5a0defe8",
"metadata": {},
"source": [
"The area between two lines can be shaded using `fill_between`:"
......@@ -299,7 +299,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "engaged-lottery",
"id": "3f11d97b",
"metadata": {},
"outputs": [],
"source": [
......@@ -313,7 +313,7 @@
},
{
"cell_type": "markdown",
"id": "paperback-stylus",
"id": "aa3fb87b",
"metadata": {},
"source": [
"<a class=\"anchor\" id=\"image\"></a>\n",
......@@ -324,7 +324,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "acoustic-kitchen",
"id": "63f18c75",
"metadata": {},
"outputs": [],
"source": [
......@@ -340,7 +340,7 @@
},
{
"cell_type": "markdown",
"id": "frank-master",
"id": "be2facc0",
"metadata": {},
"source": [
"Note that matplotlib will use the **voxel data orientation**, and that\n",
......@@ -352,7 +352,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "initial-passing",
"id": "1a960ddf",
"metadata": {},
"outputs": [],
"source": [
......@@ -365,7 +365,7 @@
},
{
"cell_type": "markdown",
"id": "specialized-maintenance",
"id": "070f5772",
"metadata": {},
"source": [
"> It is easier to produce informative brain images using nilearn or fsleyes\n",
......@@ -377,7 +377,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "weighted-publicity",
"id": "c7f6c0f6",
"metadata": {},
"outputs": [],
"source": [
......@@ -390,7 +390,7 @@
},
{
"cell_type": "markdown",
"id": "manual-bacon",
"id": "de291180",
"metadata": {},
"source": [
"By default the locations of the arrows and text will be in data coordinates (i.e., whatever is on the axes),\n",
......@@ -425,7 +425,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "earned-anaheim",
"id": "3d3482ef",
"metadata": {},
"outputs": [],
"source": [
......@@ -436,7 +436,7 @@
},
{
"cell_type": "markdown",
"id": "valued-hungary",
"id": "4923481d",
"metadata": {},
"source": [
"Note that here we explicitly create the figure and add a single sub-plot to the figure.\n",
......@@ -444,6 +444,48 @@
"The \"Axes\" object has all of the same plotting command as we used above,\n",
"although the commands to adjust the properties of things like the title, x-axis, and y-axis are slighly different.\n",
"\n",
"`plt.getp` gives a helpful summary of the properties of a matplotlib object (and what you might change):"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c0c64d42",
"metadata": {},
"outputs": [],
"source": [
"plt.getp(ax)"
]
},
{
"cell_type": "markdown",
"id": "76b789ab",
"metadata": {},
"source": [
"When going through this list carefully you might have spotted that the plotted line is stored in the `lines` property.\n",
"Let's have a look at this line in more detail"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "02f9cb81",
"metadata": {},
"outputs": [],
"source": [
"plt.getp(ax.lines[0])"
]
},
{
"cell_type": "markdown",
"id": "9a192752",
"metadata": {},
"source": [
"This shows us all the properties stored about this line,\n",
"including its coordinates in many different formats \n",
"(`data`, `path`, `xdata`, `ydata`, or `xydata`),\n",
"the line style and width (`linestyle`, `linewidth`), `color`, etc.\n",
"\n",
"<a class=\"anchor\" id=\"subplots\"></a>\n",
"## Multiple plots (i.e., subplots)\n",
"As stated one of the strengths of the object-oriented interface is that it is easier to work with multiple plots. \n",
......@@ -453,7 +495,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "intensive-bruce",
"id": "3cafa27a",
"metadata": {},
"outputs": [],
"source": [
......@@ -469,7 +511,7 @@
},
{
"cell_type": "markdown",
"id": "upset-stanley",
"id": "51141fee",
"metadata": {},
"source": [
"For such a simple example, this works fine. But for longer examples you would find yourself constantly looking back through the\n",
......@@ -481,7 +523,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "frank-treatment",
"id": "a7a6b2c7",
"metadata": {},
"outputs": [],
"source": [
......@@ -494,7 +536,7 @@
},
{
"cell_type": "markdown",
"id": "occupational-astronomy",
"id": "a1ec90e2",
"metadata": {},
"source": [
"Here we use `plt.subplots`, which creates both a new figure for us and a grid of sub-plots. \n",
......@@ -509,7 +551,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "joint-chick",
"id": "0a5f85cc",
"metadata": {},
"outputs": [],
"source": [
......@@ -523,7 +565,7 @@
},
{
"cell_type": "markdown",
"id": "illegal-spanish",
"id": "ab07e5ab",
"metadata": {},
"source": [
"Uncomment `fig.tight_layout` and see how it adjusts the spacings between the plots automatically to reduce the whitespace.\n",
......@@ -534,7 +576,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "accomplished-watershed",
"id": "8e420304",
"metadata": {},
"outputs": [],
"source": [
......@@ -549,7 +591,7 @@
},
{
"cell_type": "markdown",
"id": "standing-course",
"id": "260dc7eb",
"metadata": {},
"source": [
"<a class=\"anchor\" id=\"grid-spec\"></a>\n",
......@@ -561,7 +603,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "silent-voluntary",
"id": "f58613d6",
"metadata": {},
"outputs": [],
"source": [
......@@ -581,7 +623,7 @@
},
{
"cell_type": "markdown",
"id": "roman-discharge",
"id": "cf0ef5c8",
"metadata": {},
"source": [
"<a class=\"anchor\" id=\"styling\"></a>\n",
......@@ -595,7 +637,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "english-yahoo",
"id": "6f49e003",
"metadata": {},
"outputs": [],
"source": [
......@@ -608,7 +650,7 @@
},
{
"cell_type": "markdown",
"id": "constant-evolution",
"id": "d1c2e77c",
"metadata": {},
"source": [
"You can also set any of these properties by calling `Axes.set` directly:"
......@@ -617,7 +659,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "suspended-biography",
"id": "5d744cf1",
"metadata": {},
"outputs": [],
"source": [
......@@ -632,30 +674,31 @@
},
{
"cell_type": "markdown",
"id": "annual-hundred",
"id": "9e621844",
"metadata": {},
"source": [
"> To match the matlab API and save some typing the equivalent commands in the procedural interface do not have the `set_` preset. So, they are `plt.xlabel`, `plt.ylabel`, `plt.title`. This is also true for many of the `set_` commands we will see below.\n",
"\n",
"You can edit the font of the text when setting the label:"
"You can edit the font of the text when setting the label or after the fact using the object-oriented interface:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "trained-mouse",
"id": "389a85ff",
"metadata": {},
"outputs": [],
"source": [
"fig, axes = plt.subplots()\n",
"axes.plot([1, 2, 3], [2.3, 4.1, 0.8])\n",
"axes.set_xlabel(\"xlabel\", color='red')\n",
"axes.set_ylabel(\"ylabel\", fontsize='larger')"
"axes.set_ylabel(\"ylabel\")\n",
"axes.get_yaxis().get_label().set_fontsize('larger')"
]
},
{
"cell_type": "markdown",
"id": "elementary-mentor",
"id": "c7612d2c",
"metadata": {},
"source": [
"<a class=\"anchor\" id=\"axis\"></a>\n",
......@@ -674,7 +717,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "capital-surgeon",
"id": "0b91948e",
"metadata": {},
"outputs": [],
"source": [
......@@ -695,7 +738,25 @@
},
{
"cell_type": "markdown",
"id": "discrete-hartford",
"id": "3d5db817",
"metadata": {},
"source": [
"As illustrated earlier, we can get a more complete list of the things we could change about the x-axis by looking at its properties:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ca4c208f",
"metadata": {},
"outputs": [],
"source": [
"plt.getp(axes.get_xlabel())"
]
},
{
"cell_type": "markdown",
"id": "61b4f566",
"metadata": {},
"source": [
"<a class=\"anchor\" id=\"faq\"></a>\n",
......@@ -727,7 +788,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "fifty-relaxation",
"id": "33900afe",
"metadata": {},
"outputs": [],
"source": [
......@@ -736,7 +797,7 @@
},
{
"cell_type": "markdown",
"id": "fifty-sunglasses",
"id": "7273f530",
"metadata": {},
"source": [
"> If you are using Jupyterlab (new version of the jupyter notebook) the `nbagg` backend will not work. Instead you will have to install `ipympl` and then use the `widgets` backend to get an interactive backend (this also works in the old notebooks).\n",
......@@ -747,7 +808,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "underlying-dealer",
"id": "b50352a0",
"metadata": {},
"outputs": [],
"source": [
......@@ -757,7 +818,7 @@
},
{
"cell_type": "markdown",
"id": "general-subscriber",
"id": "2a436f07",
"metadata": {},
"source": [
"Usually, the default backend will be fine, so you will not have to set it. \n",
......@@ -765,25 +826,7 @@
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.1"
}
},
"metadata": {},
"nbformat": 4,
"nbformat_minor": 5
}
%% Cell type:markdown id:christian-smart tags:
%% Cell type:markdown id:5567ba9e tags:
# Matplotlib tutorial
The main plotting library in python is `matplotlib`.
It provides a simple interface to just explore the data,
while also having a lot of flexibility to create publication-worthy plots.
In fact, the vast majority of python-produced plots in papers will be either produced
directly using matplotlib or by one of the many plotting libraries built on top of
matplotlib (such as [seaborn](https://seaborn.pydata.org/) or [nilearn](https://nilearn.github.io/)).
Like everything in python, there is a lot of help available online (just google it or ask your local pythonista).
A particularly useful resource for matplotlib is the [gallery](https://matplotlib.org/gallery/index.html).
Here you can find a wide range of plots.
Just find one that looks like what you want to do and click on it to see (and copy) the code used to generate the plot.
## Contents
- [Basic plotting commands](#basic-plotting-commands)
- [Line plots](#line)
- [Scatter plots](#scatter)
- [Histograms and bar plots](#histograms)
- [Adding error bars](#error)
- [Shading regions](#shade)
- [Displaying images](#image)
- [Adding lines, arrows, text](#annotations)
- [Using the object-oriented interface](#OO)
- [Multiple plots (i.e., subplots)](#subplots)
- [Adjusting plot layouts](#layout)
- [Advanced grid configurations (GridSpec)](#grid-spec)
- [Styling your plot](#styling)
- [Setting title and labels](#labels)
- [Editing the x- and y-axis](#axis)
- [FAQ](#faq)
- [Why am I getting two images?](#double-image)
- [I produced a plot in my python script, but it does not show up](#show)
- [Changing where the image appears: backends](#backends)
<a class="anchor" id="basic-plotting-commands"></a>
## Basic plotting commands
Let's start with the basic imports:
%% Cell type:code id:quick-postage tags:
%% Cell type:code id:3917392c tags:
``` python
```
import matplotlib.pyplot as plt
import numpy as np
```
%% Cell type:markdown id:prescribed-writing tags:
%% Cell type:markdown id:76688c00 tags:
<a class="anchor" id="line"></a>
### Line plots
A basic lineplot can be made just by calling `plt.plot`:
%% Cell type:code id:turkish-marsh tags:
%% Cell type:code id:00d5ff18 tags:
``` python
```
plt.plot([1, 2, 3], [1.3, 4.2, 3.1])
```
%% Cell type:markdown id:compact-modeling tags:
%% Cell type:markdown id:3d0472b7 tags:
To adjust how the line is plotted, check the documentation:
%% Cell type:code id:distinct-coordinate tags:
%% Cell type:code id:38d3f3ab tags:
``` python
```
plt.plot?
```
%% Cell type:markdown id:green-dutch tags:
%% Cell type:markdown id:867ea1f5 tags:
As you can see there are a lot of options.
The ones you will probably use most often are:
- `linestyle`: how the line is plotted (set to '' to omit the line)
- `marker`: how the points are plotted (these are not plotted by default)
- `color`: what color to use (defaults to cycling through a set of 7 colors)
%% Cell type:code id:adjacent-satellite tags:
%% Cell type:code id:c705366a tags:
``` python
```
theta = np.linspace(0, 2 * np.pi, 101)
plt.plot(np.sin(theta), np.cos(theta))
plt.plot([-0.3, 0.3], [0.3, 0.3], marker='o', linestyle='', markersize=20)
plt.plot(0, -0.1, marker='s', color='black')
x = np.linspace(-0.5, 0.5, 5)
plt.plot(x, x ** 2 - 0.5, linestyle='--', marker='+', color='red')
```
%% Cell type:markdown id:external-meaning tags:
%% Cell type:markdown id:f7e493a7 tags:
Because these keywords are so common, you can actually set one or more of them by passing in a string as the third argument.
%% Cell type:code id:simple-korean tags:
%% Cell type:code id:c2b6c5c5 tags:
``` python
```
x = np.linspace(0, 1, 11)
plt.plot(x, x)
plt.plot(x, x ** 2, '--') # sets the linestyle to dashed
plt.plot(x, x ** 3, 's') # sets the marker to square (and turns off the line)
plt.plot(x, x ** 4, '^y:') # sets the marker to triangles (i.e., '^'), linestyle to dotted (i.e., ':'), and the color to yellow (i.e., 'y')
```
%% Cell type:markdown id:pediatric-sullivan tags:
%% Cell type:markdown id:c7dd3aa9 tags:
<a class="anchor" id="scatter"></a>
### Scatter plots
The main extra feature of `plt.scatter` over `plt.plot` is that you can vary the color and size of the points based on some other variable array:
%% Cell type:code id:bright-preparation tags:
%% Cell type:code id:33b81ef4 tags:
``` python
```
x = np.random.rand(30)
y = np.random.rand(30)
plt.scatter(x, y, x * 30, y)
plt.colorbar() # adds a colorbar
```
%% Cell type:markdown id:asian-mailing tags:
%% Cell type:markdown id:22de1aac tags:
The third argument is the variable determining the size, while the fourth argument is the variable setting the color.
<a class="anchor" id="histograms"></a>
### Histograms and bar plots
For a simple histogram you can do this:
%% Cell type:code id:massive-relative tags:
%% Cell type:code id:0c445269 tags:
``` python
```
r = np.random.rand(1000)
n,bins,_ = plt.hist((r-0.5)**2, bins=30)
```
%% Cell type:markdown id:positive-insight tags:
%% Cell type:markdown id:41a54dd8 tags:
where it also returns the number of elements in each bin, as `n`, and
the bin centres, as `bins`.
> The `_` in the third part on the left
> hand side is a shorthand for just throwing away the corresponding part
> of the return structure.
There is also a call for doing bar plots:
%% Cell type:code id:intensive-taste tags:
%% Cell type:code id:9d7c817d tags:
``` python
```
samp1 = r[0:10]
samp2 = r[10:20]
bwidth = 0.3
xcoord = np.arange(10)
plt.bar(xcoord-bwidth, samp1, width=bwidth, color='red', label='Sample 1')
plt.bar(xcoord, samp2, width=bwidth, color='blue', label='Sample 2')
plt.legend(loc='upper left')
```
%% Cell type:markdown id:boolean-metropolitan tags:
%% Cell type:markdown id:eca1cea7 tags:
> If you want more advanced distribution plots beyond a simple histogram, have a look at the seaborn [gallery](https://seaborn.pydata.org/examples/index.html) for (too?) many options.
<a class="anchor" id="error"></a>
### Adding error bars
If your data is not completely perfect and has for some obscure reason some uncertainty associated with it,
you can plot these using `plt.error`:
%% Cell type:code id:basic-cambridge tags:
%% Cell type:code id:939fcf82 tags:
``` python