├── requirements.txt
├── images
├── usage.png
├── commits.png
├── matplotlib.png
├── contributions.png
└── figure_creation_methods.png
├── environment.yml
├── README.md
├── 06_Animations.ipynb
├── 01_Interfaces.ipynb
├── 03_adding_content.ipynb
├── 05_Libraries_using_Matplotlib.ipynb
├── 02_Figure.ipynb
└── 00_Getting_started.ipynb
/requirements.txt:
--------------------------------------------------------------------------------
1 | matplotlib
2 | ipympl
3 | pandas
4 | jupyterlab
5 |
--------------------------------------------------------------------------------
/images/usage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timhoffm/using-matplotlib/HEAD/images/usage.png
--------------------------------------------------------------------------------
/images/commits.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timhoffm/using-matplotlib/HEAD/images/commits.png
--------------------------------------------------------------------------------
/images/matplotlib.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timhoffm/using-matplotlib/HEAD/images/matplotlib.png
--------------------------------------------------------------------------------
/images/contributions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timhoffm/using-matplotlib/HEAD/images/contributions.png
--------------------------------------------------------------------------------
/images/figure_creation_methods.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timhoffm/using-matplotlib/HEAD/images/figure_creation_methods.png
--------------------------------------------------------------------------------
/environment.yml:
--------------------------------------------------------------------------------
1 | name: using-matplotlib23
2 | channels:
3 | - conda-forge
4 | dependencies:
5 | - python
6 | - matplotlib
7 | - ipympl
8 | - pandas
9 | - jupyterlab
10 |
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Effectively using Matplotlib
2 |
3 | This is a tutorial explaining the basic concepts of Matplotlib and aims at enabling you to use Matplotlib more effectively.
4 |
5 | It's designed as a fundamental introduction and should be helpful for beginners and existing users alike.
6 |
7 | Note: The notebooks were created for live tutorials and explantory text may be a bit terse.
8 |
9 |
10 | ## Environment
11 |
12 | To be able to run the notebooks yourself, you need
13 |
14 | - jupyterlab
15 | - matplotlib
16 | - pandas
17 | - ipympl (optional)
18 |
19 | Use one of the following to create an environment:
20 |
21 | ```
22 | pip install -r requirements.txt
23 | ```
24 |
25 | or
26 |
27 | ```
28 | conda env create -f environment.yml
29 | conda activate using-matplotlib
30 | ```
31 |
--------------------------------------------------------------------------------
/06_Animations.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Bonus Example: Animations in notebooks"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": null,
13 | "metadata": {},
14 | "outputs": [],
15 | "source": [
16 | "import matplotlib.pyplot as plt\n",
17 | "import matplotlib.animation\n",
18 | "from IPython.display import HTML\n",
19 | "import numpy as np"
20 | ]
21 | },
22 | {
23 | "cell_type": "markdown",
24 | "metadata": {},
25 | "source": [
26 | "Data:"
27 | ]
28 | },
29 | {
30 | "cell_type": "code",
31 | "execution_count": null,
32 | "metadata": {},
33 | "outputs": [],
34 | "source": [
35 | "FRAMES = 50\n",
36 | "\n",
37 | "x = np.linspace(0, 2*np.pi)\n",
38 | "\n",
39 | "def f(x, phi=0):\n",
40 | " return np.sin(x - phi)"
41 | ]
42 | },
43 | {
44 | "cell_type": "markdown",
45 | "metadata": {},
46 | "source": [
47 | "Animated figure:\n",
48 | "\n",
49 | "- `FuncAnimation` generates a sequence of images from a figure. \n",
50 | " Before each image the figure is updated using a callback function.\n",
51 | "- The animation can be rendered to HTML and then embedded in IPython."
52 | ]
53 | },
54 | {
55 | "cell_type": "code",
56 | "execution_count": null,
57 | "metadata": {},
58 | "outputs": [],
59 | "source": [
60 | "fig, ax = plt.subplots()\n",
61 | "line, = ax.plot(x, f(x))\n",
62 | "text = ax.set_title('Frame 0')\n",
63 | "\n",
64 | "def animate(i):\n",
65 | " phi = 2 * np.pi * i / FRAMES\n",
66 | " line.set_data(x, f(x, phi))\n",
67 | " text.set_text(F'Frame {i}')\n",
68 | "\n",
69 | "ani = matplotlib.animation.FuncAnimation(fig, animate, frames=FRAMES)\n",
70 | "plt.close(fig)\n",
71 | "HTML(ani.to_jshtml(fps=20))"
72 | ]
73 | },
74 | {
75 | "cell_type": "markdown",
76 | "metadata": {},
77 | "source": [
78 | "
\n",
79 | " Task: Add a title to the above animation, that displays the current phase phi.\n",
80 | "
"
81 | ]
82 | },
83 | {
84 | "cell_type": "code",
85 | "execution_count": null,
86 | "metadata": {},
87 | "outputs": [],
88 | "source": []
89 | }
90 | ],
91 | "metadata": {
92 | "kernelspec": {
93 | "display_name": "Python 3 (ipykernel)",
94 | "language": "python",
95 | "name": "python3"
96 | },
97 | "language_info": {
98 | "codemirror_mode": {
99 | "name": "ipython",
100 | "version": 3
101 | },
102 | "file_extension": ".py",
103 | "mimetype": "text/x-python",
104 | "name": "python",
105 | "nbconvert_exporter": "python",
106 | "pygments_lexer": "ipython3",
107 | "version": "3.11.4"
108 | }
109 | },
110 | "nbformat": 4,
111 | "nbformat_minor": 4
112 | }
113 |
--------------------------------------------------------------------------------
/01_Interfaces.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "%matplotlib inline\n",
10 | "import matplotlib.pyplot as plt\n",
11 | "import numpy as np"
12 | ]
13 | },
14 | {
15 | "cell_type": "markdown",
16 | "metadata": {},
17 | "source": [
18 | "# Interfaces / ways of working\n",
19 | "\n",
20 | "## `Axes` interface (object-based)\n",
21 | "\n",
22 | "We've already used this.\n",
23 | "\n",
24 | "1. Create a `Figure` and one or more `Axes`\n",
25 | " (typically using ``plt.subplots()``)\n",
26 | "2. Configure and add data through methods on these obejcts.\n",
27 | "\n",
28 | "When to use:\n",
29 | "- Simple and more complicated plots (e.g. multiple axes, etc.)\n",
30 | "- When plotting in a script or library.\n",
31 | "\n",
32 | "Example:"
33 | ]
34 | },
35 | {
36 | "cell_type": "code",
37 | "execution_count": null,
38 | "metadata": {},
39 | "outputs": [],
40 | "source": [
41 | "fig, ax = plt.subplots()\n",
42 | "ax.plot([7, 3, 2])\n",
43 | "ax.set_ylabel('Number of pintxos')\n",
44 | "ax.set_ylim(0, None)"
45 | ]
46 | },
47 | {
48 | "cell_type": "markdown",
49 | "metadata": {},
50 | "source": [
51 | "## `pyplot` interface (function based)\n",
52 | "\n",
53 | "Create and manipulate a plot through `pyplot` functions\n",
54 | "\n",
55 | "A state based interface. There are notions of a *current figure* and a *current axes*.\n",
56 | "\n",
57 | "All function calls apply to the *current* element; i.e. `plt.xlabel('text')` sets the label of the current axes. If you want to set the label of another axes from the `pyplot` interface, you would have to change the current axes first.\n",
58 | " \n",
59 | "When to use:\n",
60 | "- All `pyplot` functions: Simple plots in an interactive interpreter\n",
61 | "- Special case: `plt.subplots()` can be generally used to create a basic figure and axes.\n",
62 | "\n",
63 | "Example:"
64 | ]
65 | },
66 | {
67 | "cell_type": "code",
68 | "execution_count": null,
69 | "metadata": {},
70 | "outputs": [],
71 | "source": [
72 | "plt.plot([7, 3, 2])\n",
73 | "plt.ylabel('Number of pintxos')\n",
74 | "plt.ylim(0, None)"
75 | ]
76 | },
77 | {
78 | "cell_type": "markdown",
79 | "metadata": {},
80 | "source": [
81 | "## `pylab` interface\n",
82 | "\n",
83 | "\n",
84 | "Immediately forget about this - or better: Remember not to use it. \n",
85 | "
\n",
86 | "\n",
87 | "A convenience interface mimicing MATLABs global scope. \n",
88 | "\n",
89 | "Use is strongly discouraged due to namespace pollution! (Loads all of pyplot and numpy into the global name space).\n",
90 | "\n",
91 | "When to use:\n",
92 | "- *Never*\n",
93 | "\n",
94 | "This is only still available in Matplotlib for backward compatibility.\n",
95 | "\n",
96 | "Example (intentionally not executable):\n",
97 | "\n",
98 | "~~~\n",
99 | "from pylab import *\n",
100 | "plot([7, 3, 2])\n",
101 | "ylabel('Number of pintxos')\n",
102 | "ylim(0, None)\n",
103 | "~~~"
104 | ]
105 | },
106 | {
107 | "cell_type": "markdown",
108 | "metadata": {},
109 | "source": [
110 | "## Minimal and pragmatic approach\n",
111 | "\n",
112 | "Creating a figure using `plt.figure()` or a figure and axes using `plt.subplots()` is still used in the object-'based approach (but no other `pyplot` functions).\n",
113 | "\n",
114 | "\n",
115 | " Hint: If you just want to learn one interface, use `plt.subplots()` and the object-based approach on the returned figure and axes.\n",
116 | "
"
117 | ]
118 | },
119 | {
120 | "cell_type": "markdown",
121 | "metadata": {},
122 | "source": [
123 | "## Translating between pyplot and Axes methods \n",
124 | "\n",
125 | "- Plotting functions are named identical: \n",
126 | " `plt.plot(...)`, `ax.plot(...)`\n",
127 | "- Modifying parameters uses setters on the axes, but plain functions in pyplot \n",
128 | " `ax.set_xlim(a, b)` vs. `plt.xlim(a, b)`\n",
129 | "- Obtaining parameters uses getters on the axes, but plain functions without args (hello MATLAB) in pyplot \n",
130 | " `ax.get_xlim()` vs. `plt.xlim()`\n"
131 | ]
132 | },
133 | {
134 | "cell_type": "markdown",
135 | "metadata": {},
136 | "source": [
137 | "Simple plot as OOP:\n",
138 | "\n",
139 | "\n",
140 | " Task: Translate the following OOP example to pyplot.\n",
141 | "
"
142 | ]
143 | },
144 | {
145 | "cell_type": "code",
146 | "execution_count": null,
147 | "metadata": {},
148 | "outputs": [],
149 | "source": [
150 | "x = np.linspace(0, 2, 100)\n",
151 | "\n",
152 | "fig, ax = plt.subplots()\n",
153 | "ax.plot(x, x, label='linear')\n",
154 | "ax.plot(x, x**2, label='quadratic')\n",
155 | "ax.plot(x, x**3, label='cubic')\n",
156 | "ax.set_xlabel('x label')\n",
157 | "ax.set_ylabel('y label')\n",
158 | "ax.set_title(\"Simple Plot\")\n",
159 | "ax.legend()"
160 | ]
161 | },
162 | {
163 | "cell_type": "markdown",
164 | "metadata": {},
165 | "source": [
166 | "Multiple Axes in `pyplot`\n",
167 | "\n",
168 | "\n",
169 | " Task: Translate the following pyplot example to object-based interface.\n",
170 | "
"
171 | ]
172 | },
173 | {
174 | "cell_type": "code",
175 | "execution_count": null,
176 | "metadata": {},
177 | "outputs": [],
178 | "source": [
179 | "plt.subplot(121)\n",
180 | "plt.plot(x, x)\n",
181 | "plt.title('linear')\n",
182 | "\n",
183 | "plt.subplot(122)\n",
184 | "plt.plot(x, x**2)\n",
185 | "plt.title('quadratic')"
186 | ]
187 | },
188 | {
189 | "cell_type": "markdown",
190 | "metadata": {},
191 | "source": [
192 | "# Summary\n",
193 | "\n",
194 | "- Learn the object-based approach first.\n",
195 | "- `pyplot` can be a convenience for simple quick plots. \n",
196 | " But understand how it works and relates to the underlying objects. - Otherwise it will be confusing."
197 | ]
198 | }
199 | ],
200 | "metadata": {
201 | "kernelspec": {
202 | "display_name": "Python 3 (ipykernel)",
203 | "language": "python",
204 | "name": "python3"
205 | },
206 | "language_info": {
207 | "codemirror_mode": {
208 | "name": "ipython",
209 | "version": 3
210 | },
211 | "file_extension": ".py",
212 | "mimetype": "text/x-python",
213 | "name": "python",
214 | "nbconvert_exporter": "python",
215 | "pygments_lexer": "ipython3",
216 | "version": "3.11.4"
217 | }
218 | },
219 | "nbformat": 4,
220 | "nbformat_minor": 4
221 | }
222 |
--------------------------------------------------------------------------------
/03_adding_content.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Adding content"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": null,
13 | "metadata": {},
14 | "outputs": [],
15 | "source": [
16 | "%matplotlib inline\n",
17 | "import matplotlib.pyplot as plt\n",
18 | "import numpy as np"
19 | ]
20 | },
21 | {
22 | "cell_type": "markdown",
23 | "metadata": {},
24 | "source": [
25 | "For simplicity, this section mainly uses `pyplot` plotting functions. However, the same applies to the corresponding `Axes` methods."
26 | ]
27 | },
28 | {
29 | "cell_type": "code",
30 | "execution_count": null,
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "x = np.linspace(-10, 10, 201)\n",
35 | "y = np.sin(x)\n",
36 | "\n",
37 | "fig, ax = plt.subplots()\n",
38 | "ax.plot(x, y)"
39 | ]
40 | },
41 | {
42 | "cell_type": "markdown",
43 | "metadata": {},
44 | "source": [
45 | "## Explicit styling with color, marker and linestyle\n",
46 | "\n",
47 | "`plot()` draws lines and/or markers at the given points"
48 | ]
49 | },
50 | {
51 | "cell_type": "markdown",
52 | "metadata": {},
53 | "source": [
54 | "### Styling with format strings\n",
55 | "\n",
56 | "Inspired by MATLAB.\n",
57 | "\n",
58 | "A format string consists of a part for color, marker and line:\n",
59 | "\n",
60 | "~~~\n",
61 | "fmt = '[marker][line][color]'\n",
62 | "~~~\n",
63 | "\n",
64 | "https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.plot.html (scroll down)"
65 | ]
66 | },
67 | {
68 | "cell_type": "code",
69 | "execution_count": null,
70 | "metadata": {},
71 | "outputs": [],
72 | "source": [
73 | "x = np.linspace(0, 2*np.pi, 20)\n",
74 | "y = np.sin(x)\n",
75 | "fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(9, 3), sharey=True)\n",
76 | "ax1.plot(x, y, 'o-')\n",
77 | "ax2.plot(x, y, 'gx')\n",
78 | "ax3.plot(x, y, 'r--')"
79 | ]
80 | },
81 | {
82 | "cell_type": "markdown",
83 | "metadata": {},
84 | "source": [
85 | "### Task\n",
86 | "Create the same plot but using keyword arguments `marker`, `linestyle` and `color` instead of the format string."
87 | ]
88 | },
89 | {
90 | "cell_type": "code",
91 | "execution_count": null,
92 | "metadata": {},
93 | "outputs": [],
94 | "source": [
95 | "fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(9, 3), sharey=True)\n",
96 | "ax1.plot(x, y, marker='o')\n",
97 | "ax2.plot(x, y, marker='x', linestyle='none', color='green')\n",
98 | "ax3.plot(x, y, marker='', linestyle='--', color='red')"
99 | ]
100 | },
101 | {
102 | "cell_type": "markdown",
103 | "metadata": {},
104 | "source": [
105 | "### Notes\n",
106 | "\n",
107 | "- Format strings are a handy shortcut for customization\n",
108 | "- They offer only a subset of the styling capabilities of keyword arguments\n",
109 | "- Format strings define the style completely, keyword arguments only modify single aspects. \n",
110 | " Compare `plot(x, y, 'x')` vs `plot(x, y, marker='x')`."
111 | ]
112 | },
113 | {
114 | "cell_type": "markdown",
115 | "metadata": {},
116 | "source": [
117 | "### Default color cycle\n",
118 | "\n",
119 | "Matplotlib automatically changes the color if you plot multiple curves.\n",
120 | "\n",
121 | "More on that later..."
122 | ]
123 | },
124 | {
125 | "cell_type": "code",
126 | "execution_count": null,
127 | "metadata": {},
128 | "outputs": [],
129 | "source": [
130 | "x = np.linspace(-5, 5, 201)\n",
131 | "for dx in np.linspace(0, np.pi, 12):\n",
132 | " plt.plot(x, np.sin(x - dx) - 0.2 * dx)"
133 | ]
134 | },
135 | {
136 | "cell_type": "markdown",
137 | "metadata": {},
138 | "source": [
139 | "## Colors\n",
140 | "\n",
141 | "There are various ways to specify colors:\n",
142 | "\n",
143 | "https://matplotlib.org/stable/tutorials/colors/colors.html\n",
144 | "\n",
145 | "https://matplotlib.org/stable/gallery/color/named_colors.html"
146 | ]
147 | },
148 | {
149 | "cell_type": "code",
150 | "execution_count": null,
151 | "metadata": {},
152 | "outputs": [],
153 | "source": [
154 | "plt.plot(x, x, color='b')\n",
155 | "plt.plot(x + 1, x, color='green')\n",
156 | "plt.plot(x + 2, x, color='#ff00ff')\n",
157 | "plt.plot(x + 3, x, color=(1, 0, 0))\n",
158 | "plt.plot(x + 4, x, color='0.5')\n",
159 | "plt.plot(x + 5, x, color='mediumseagreen')\n",
160 | "plt.plot(x + 6, x, color='xkcd:steel blue')\n",
161 | "plt.plot(x + 7, x, color='C1')"
162 | ]
163 | },
164 | {
165 | "cell_type": "markdown",
166 | "metadata": {},
167 | "source": [
168 | "`CN` color notation is in particular useful for relating additional plot elements with the data."
169 | ]
170 | },
171 | {
172 | "cell_type": "code",
173 | "execution_count": null,
174 | "metadata": {},
175 | "outputs": [],
176 | "source": [
177 | "plt.plot(x, x)\n",
178 | "plt.plot(x+1, x)\n",
179 | "\n",
180 | "plt.text(-1, 0, 'first color', color='C0', fontsize=16, horizontalalignment='right')\n",
181 | "plt.text(2, 0, 'second color', color='C1', fontsize=16)"
182 | ]
183 | },
184 | {
185 | "cell_type": "markdown",
186 | "metadata": {},
187 | "source": [
188 | "## Return values\n",
189 | "\n",
190 | "Most of the plotting functions have a return value.\n",
191 | "\n",
192 | "Often you don't need it. But it's good to know, and sometimes handy.\n",
193 | "\n",
194 | "The returned objects are Artists that define elements in the plot such as lines, etc. See the [Returns section in the docs](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.plot.html) for details."
195 | ]
196 | },
197 | {
198 | "cell_type": "code",
199 | "execution_count": null,
200 | "metadata": {},
201 | "outputs": [],
202 | "source": [
203 | "lines = plt.plot(x, np.sin(x))\n",
204 | "print(lines)\n",
205 | "lines[0].set_color('0.7')"
206 | ]
207 | },
208 | {
209 | "cell_type": "markdown",
210 | "metadata": {},
211 | "source": [
212 | "**Note:** `plot()` returns a list of `Line2D` because it can be used in a MATLAB style (not quite recommended because it can get messy)\n",
213 | "\n",
214 | "**Hint:** If you have a one-element list, you can use tuple-unpacking to directly store the element in a variable."
215 | ]
216 | },
217 | {
218 | "cell_type": "code",
219 | "execution_count": null,
220 | "metadata": {},
221 | "outputs": [],
222 | "source": [
223 | "lines = plt.plot(x, np.sin(x), x, np.cos(x))\n",
224 | "print(lines)\n",
225 | "\n",
226 | "# 1-element tuple unpacking\n",
227 | "line, = plt.plot(x, -np.sin(x))"
228 | ]
229 | },
230 | {
231 | "cell_type": "markdown",
232 | "metadata": {},
233 | "source": [
234 | "## `data` parameter\n",
235 | "\n",
236 | "Alternative way for specifying the data for objects that support index-access by names (dicts, structured numpy arrays, pandas DataFrames, ...)"
237 | ]
238 | },
239 | {
240 | "cell_type": "code",
241 | "execution_count": null,
242 | "metadata": {},
243 | "outputs": [],
244 | "source": [
245 | "data = {'x': x, 'sine': np.sin(x), 'cosine': np.cos(x)}\n",
246 | "\n",
247 | "plt.plot(data['x'], data['sine'])\n",
248 | "plt.plot('x', 'cosine', data=data)"
249 | ]
250 | },
251 | {
252 | "cell_type": "markdown",
253 | "metadata": {},
254 | "source": [
255 | "## Legend\n",
256 | "\n",
257 | "- By default, only elements that have labels are added to the legend.\n",
258 | "- The legend is placed in a best position.\n",
259 | "- The defaults can be overwritten by providing additional parameters to `legend()`."
260 | ]
261 | },
262 | {
263 | "cell_type": "code",
264 | "execution_count": null,
265 | "metadata": {},
266 | "outputs": [],
267 | "source": [
268 | "x = np.linspace(-10, 4, 201)\n",
269 | "line, = plt.plot(x, 0.1*x)\n",
270 | "plt.plot(x, np.sin(x), label='sin(x)')\n",
271 | "plt.plot(x, 0.5*np.cos(x), label='cos(x)')\n",
272 | "#line.set_label('x')\n",
273 | "plt.legend()"
274 | ]
275 | },
276 | {
277 | "cell_type": "markdown",
278 | "metadata": {},
279 | "source": [
280 | "#### Explicitly defining legend content\n",
281 | "\n",
282 | "The automatic label-based content detection for a legend is usually sufficient. However, sometimes you might want to add artists to a legend, that are not part of the axes.\n",
283 | "\n",
284 | "In that case, you can explicitly pass lists of Artists and labels to `legend()`."
285 | ]
286 | },
287 | {
288 | "cell_type": "code",
289 | "execution_count": null,
290 | "metadata": {},
291 | "outputs": [],
292 | "source": [
293 | "fig, (ax1, ax2) = plt.subplots(1, 2, sharey=True)\n",
294 | "line1, = ax1.plot(x, np.sin(x))\n",
295 | "line2, = ax2.plot(x, 0.5 * np.cos(x), 'C1')\n",
296 | "\n",
297 | "ax2.legend([line1, line2], ['a', 'b'])"
298 | ]
299 | },
300 | {
301 | "cell_type": "markdown",
302 | "metadata": {},
303 | "source": [
304 | "## Bar plots"
305 | ]
306 | },
307 | {
308 | "cell_type": "code",
309 | "execution_count": null,
310 | "metadata": {},
311 | "outputs": [],
312 | "source": [
313 | "x = [0, 1, 2, 3]\n",
314 | "y = [1, 4, 9, 16]\n",
315 | "plt.bar(x, y)"
316 | ]
317 | },
318 | {
319 | "cell_type": "code",
320 | "execution_count": null,
321 | "metadata": {},
322 | "outputs": [],
323 | "source": [
324 | "labels = ['a', 'b', 'c', 'd']\n",
325 | "plt.bar(labels, y)\n",
326 | "#plt.plot(x, y, 'ro')"
327 | ]
328 | },
329 | {
330 | "cell_type": "markdown",
331 | "metadata": {},
332 | "source": [
333 | "## Other plotting functions\n",
334 | "\n",
335 | "The concept is always the same:\n",
336 | "\n",
337 | "- an Axes method creates the data Artists and adds them to the Axes\n",
338 | "- the first few arguments describe the data\n",
339 | "- there are many optional keworda arguments to customize style and behavior\n",
340 | "\n",
341 | "\n",
342 | "See\n",
343 | "\n",
344 | "- https://matplotlib.org/stable/plot_types/index.html\n",
345 | "- https://matplotlib.org/stable/api/axes_api.html\n",
346 | "\n"
347 | ]
348 | },
349 | {
350 | "cell_type": "code",
351 | "execution_count": null,
352 | "metadata": {},
353 | "outputs": [],
354 | "source": []
355 | },
356 | {
357 | "cell_type": "code",
358 | "execution_count": null,
359 | "metadata": {},
360 | "outputs": [],
361 | "source": []
362 | }
363 | ],
364 | "metadata": {
365 | "kernelspec": {
366 | "display_name": "Python 3 (ipykernel)",
367 | "language": "python",
368 | "name": "python3"
369 | },
370 | "language_info": {
371 | "codemirror_mode": {
372 | "name": "ipython",
373 | "version": 3
374 | },
375 | "file_extension": ".py",
376 | "mimetype": "text/x-python",
377 | "name": "python",
378 | "nbconvert_exporter": "python",
379 | "pygments_lexer": "ipython3",
380 | "version": "3.11.4"
381 | }
382 | },
383 | "nbformat": 4,
384 | "nbformat_minor": 4
385 | }
386 |
--------------------------------------------------------------------------------
/05_Libraries_using_Matplotlib.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "%matplotlib inline\n",
10 | "import matplotlib.pyplot as plt\n",
11 | "import numpy as np"
12 | ]
13 | },
14 | {
15 | "cell_type": "markdown",
16 | "metadata": {},
17 | "source": [
18 | "# Other libraries using Matplotlib\n",
19 | "\n",
20 | "- Matplotlib provides building blocks and configuration capabilities to adapt a plot completely to your needs.\n",
21 | "- That's usually a couple of lines of code.\n",
22 | "- Providing ready made domain-specific plots is beyond the scope.\n",
23 | "\n",
24 | "There are many libraries building on top of Matplotlib https://matplotlib.org/thirdpartypackages/index.html"
25 | ]
26 | },
27 | {
28 | "cell_type": "markdown",
29 | "metadata": {},
30 | "source": [
31 | "## Write your own wrapper function\n",
32 | "\n",
33 | "Generally, you have two types:\n",
34 | "\n",
35 | "- Functions that create a complete figure\n",
36 | "- Functions that plot data into an existing axes\n",
37 | "\n",
38 | "\n",
39 | "### Creating a whole figure"
40 | ]
41 | },
42 | {
43 | "cell_type": "code",
44 | "execution_count": null,
45 | "metadata": {},
46 | "outputs": [],
47 | "source": [
48 | "import pandas as pd\n",
49 | "\n",
50 | "df = pd.DataFrame.from_dict({\n",
51 | " 'Question 1': [10, 15, 17, 32, 26],\n",
52 | " 'Question 2': [26, 22, 29, 10, 13],\n",
53 | " 'Question 3': [35, 37, 7, 2, 19],\n",
54 | " 'Question 4': [32, 11, 9, 15, 33],\n",
55 | " 'Question 5': [21, 29, 5, 5, 40],\n",
56 | " 'Question 6': [8, 19, 5, 30, 38]\n",
57 | " },\n",
58 | " orient='index',\n",
59 | " columns=[\n",
60 | " 'Strongly disagree', 'Disagree', 'Neither agree nor disagree', 'Agree', 'Strongly agree']\n",
61 | ")\n",
62 | "df"
63 | ]
64 | },
65 | {
66 | "cell_type": "markdown",
67 | "metadata": {},
68 | "source": [
69 | "Recommendation:\n",
70 | "\n",
71 | "- **Inputs:** The data \n",
72 | " Optionally add config parameters to make the plot more customizable.\n",
73 | "- **Output:** The created `Figure` and `Axes` (or `Axes`es), often the same as the `subplots()` return value. \n",
74 | " This gives users access to the fundamental objects and allows further customization.\n",
75 | " \n",
76 | "\n",
77 | "Example: https://matplotlib.org/stable/gallery/lines_bars_and_markers/horizontal_barchart_distribution.html"
78 | ]
79 | },
80 | {
81 | "cell_type": "code",
82 | "execution_count": null,
83 | "metadata": {},
84 | "outputs": [],
85 | "source": [
86 | "def survey(df):\n",
87 | " \"\"\"\n",
88 | " Parameters\n",
89 | " ----------\n",
90 | " df : DataFrame\n",
91 | " A DataFrame with one row per questiong and the agreement categories\n",
92 | " in the columns.\n",
93 | " \"\"\"\n",
94 | " data = df.to_numpy()\n",
95 | " data_cum = data.cumsum(axis=1)\n",
96 | " category_colors = plt.colormaps['RdYlGn'](\n",
97 | " np.linspace(0.15, 0.85, data.shape[1]))\n",
98 | "\n",
99 | " fig, ax = plt.subplots(figsize=(9.2, 5))\n",
100 | " ax.invert_yaxis()\n",
101 | " ax.xaxis.set_visible(False)\n",
102 | " ax.set_xlim(0, np.sum(data, axis=1).max())\n",
103 | "\n",
104 | " for i, (colname, color) in enumerate(zip(df.columns, category_colors)):\n",
105 | " widths = data[:, i]\n",
106 | " starts = data_cum[:, i] - widths\n",
107 | " rects = ax.barh(df.index, widths, left=starts, height=0.5,\n",
108 | " label=colname, color=color)\n",
109 | "\n",
110 | " r, g, b, _ = color\n",
111 | " text_color = 'white' if r * g * b < 0.5 else 'darkgrey'\n",
112 | " ax.bar_label(rects, label_type='center', color=text_color)\n",
113 | " ax.legend(ncol=len(category_names), bbox_to_anchor=(0, 1),\n",
114 | " loc='lower left', fontsize='small')\n",
115 | "\n",
116 | " return fig, ax"
117 | ]
118 | },
119 | {
120 | "cell_type": "code",
121 | "execution_count": null,
122 | "metadata": {},
123 | "outputs": [],
124 | "source": [
125 | "fig, ax = survey(df)\n",
126 | "\n",
127 | "fig.suptitle('Test')"
128 | ]
129 | },
130 | {
131 | "cell_type": "markdown",
132 | "metadata": {},
133 | "source": [
134 | "### Helper function to plot data\n",
135 | "\n",
136 | "- **Inputs:**\n",
137 | " - The `Axes` to plot into.\n",
138 | " - The data.\n",
139 | " - Addtional configuration parameters. - It's often reasonable to pass through arbitrary parameters using `**kwargs`.\n",
140 | "- **Output:** Usually not needed, but it may be a good idea to return the created `Artist`s - like the builtin plot functions do.\n"
141 | ]
142 | },
143 | {
144 | "cell_type": "code",
145 | "execution_count": null,
146 | "metadata": {},
147 | "outputs": [],
148 | "source": [
149 | "def plot_errorband(ax, x, y, err, **kwargs):\n",
150 | " \"\"\"\n",
151 | " Plot a line (x, y) and the corresponding error band y +/- err into the given Axes *ax*.\n",
152 | " \"\"\"\n",
153 | " poly = ax.fill_between(x, y-err, y+err, alpha=0.5, **kwargs)\n",
154 | " line = ax.plot(x, y, **kwargs)\n",
155 | " return line, poly"
156 | ]
157 | },
158 | {
159 | "cell_type": "code",
160 | "execution_count": null,
161 | "metadata": {},
162 | "outputs": [],
163 | "source": [
164 | "# data\n",
165 | "np.random.seed(1)\n",
166 | "x = np.linspace(0, 8, 16)\n",
167 | "y = 3 + 4*x/8 + np.random.uniform(0.0, 0.5, len(x))\n",
168 | "err = 5 + np.random.normal(size=len(x))\n",
169 | "\n",
170 | "# plot\n",
171 | "fig, ax = plt.subplots()\n",
172 | "plot_errorband(ax, x, y, err)\n",
173 | "plot_errorband(ax, x, y+10, err, color='green') # color='green'"
174 | ]
175 | },
176 | {
177 | "cell_type": "markdown",
178 | "metadata": {},
179 | "source": [
180 | "#### Alternative: more `pyplot`-like interface\n",
181 | "\n",
182 | "Make the `Axes` *ax* an optional parameter and use `plt.gca()` if not provided."
183 | ]
184 | },
185 | {
186 | "cell_type": "code",
187 | "execution_count": null,
188 | "metadata": {},
189 | "outputs": [],
190 | "source": [
191 | "def plot_errorband(x, y, err, ax=None, **kwargs):\n",
192 | " if ax is None:\n",
193 | " ax = plt.gca()\n",
194 | " \n",
195 | " poly = ax.fill_between(x, y-err, y+err, alpha=0.5, **kwargs)\n",
196 | " line = ax.plot(x, y, **kwargs)\n",
197 | " return line, poly"
198 | ]
199 | },
200 | {
201 | "cell_type": "code",
202 | "execution_count": null,
203 | "metadata": {},
204 | "outputs": [],
205 | "source": [
206 | "plot_errorband(x, y, err)\n",
207 | "plot_errorband(x, y+10, err)"
208 | ]
209 | },
210 | {
211 | "cell_type": "markdown",
212 | "metadata": {},
213 | "source": [
214 | "# `pandas` and matplotlib\n",
215 | "\n",
216 | "`pandas.plot` provides a high-level plotting interface to draw content of DataFrames using Matplotllib."
217 | ]
218 | },
219 | {
220 | "cell_type": "code",
221 | "execution_count": null,
222 | "metadata": {},
223 | "outputs": [],
224 | "source": [
225 | "%matplotlib inline\n",
226 | "import matplotlib.pyplot as plt\n",
227 | "import pandas as pd\n",
228 | "#import seaborn as sns"
229 | ]
230 | },
231 | {
232 | "cell_type": "code",
233 | "execution_count": null,
234 | "metadata": {},
235 | "outputs": [],
236 | "source": [
237 | "df = pd.DataFrame({'A': [1, 2, 4, 8], 'B': [4, 6, 3, 5]})"
238 | ]
239 | },
240 | {
241 | "cell_type": "code",
242 | "execution_count": null,
243 | "metadata": {},
244 | "outputs": [],
245 | "source": [
246 | "df"
247 | ]
248 | },
249 | {
250 | "cell_type": "markdown",
251 | "metadata": {},
252 | "source": [
253 | "Pure Matplotlib:"
254 | ]
255 | },
256 | {
257 | "cell_type": "code",
258 | "execution_count": null,
259 | "metadata": {},
260 | "outputs": [],
261 | "source": [
262 | "plt.plot(df.index, df.A)"
263 | ]
264 | },
265 | {
266 | "cell_type": "markdown",
267 | "metadata": {},
268 | "source": [
269 | "Using `DataFrame.plot`."
270 | ]
271 | },
272 | {
273 | "cell_type": "code",
274 | "execution_count": null,
275 | "metadata": {},
276 | "outputs": [],
277 | "source": [
278 | "df.plot.line(y='A')"
279 | ]
280 | },
281 | {
282 | "cell_type": "markdown",
283 | "metadata": {},
284 | "source": [
285 | "*Note*: `DataFrame.plot` has originally been a single function. The kind of plot (line, bar, ...) could be chosen by the `kind` parameter. This is a bit too generic.\n",
286 | "\n",
287 | "Nowadays, `DataFrame.plot` can also be regarded as a namespace with sub-functions `DataFrame.plot.line()`, `DataFrame.plot.bar()`, ..."
288 | ]
289 | },
290 | {
291 | "cell_type": "markdown",
292 | "metadata": {},
293 | "source": [
294 | "### Which Axes do my data go to?\n",
295 | "\n",
296 | "Handling of Axes:\n",
297 | "\n",
298 | "- `matplotlib.pyplot`: Plot into current axes (create one if necessary)\n",
299 | "- `matplotlib` OOP: Explicitly create axes\n",
300 | "- `pandas.plot`: Creates a new axes and plots into that. Alternatively, pass an existing axes via the `ax` keyword argument.\n",
301 | "\n",
302 | "Return value:\n",
303 | "- `matplotlib` plotting functions return the created Artist.\n",
304 | "- `pandas.plot` plotting functions return the axes"
305 | ]
306 | },
307 | {
308 | "cell_type": "code",
309 | "execution_count": null,
310 | "metadata": {},
311 | "outputs": [],
312 | "source": [
313 | "fig, axs = plt.subplots(1, 2)\n",
314 | "df.plot.line(y='A')\n",
315 | "#df.plot.line(y='A', ax=axs[1])"
316 | ]
317 | },
318 | {
319 | "cell_type": "markdown",
320 | "metadata": {},
321 | "source": [
322 | "### Philosophies\n",
323 | "\n",
324 | "- Matplotlib: Every aspect of the plot is configured by a separate function.\n",
325 | "- `pandas.plot`: Convenience function to quickly draw data with some common settings."
326 | ]
327 | },
328 | {
329 | "cell_type": "code",
330 | "execution_count": null,
331 | "metadata": {},
332 | "outputs": [],
333 | "source": [
334 | "df.plot.line(ylim=(0, None), title='My data')"
335 | ]
336 | },
337 | {
338 | "cell_type": "code",
339 | "execution_count": null,
340 | "metadata": {},
341 | "outputs": [],
342 | "source": [
343 | "plt.plot(df.index, df.A, label='A')\n",
344 | "plt.plot(df.index, df.B, label='B')\n",
345 | "plt.ylim(0, None)\n",
346 | "plt.xlim(0, max(df.index))\n",
347 | "plt.legend()\n",
348 | "plt.title('My data')"
349 | ]
350 | },
351 | {
352 | "cell_type": "markdown",
353 | "metadata": {},
354 | "source": [
355 | "You combine both worlds:\n",
356 | "- Use conveninece functions to draw the main part of the figure.\n",
357 | "- Fine-tune further using Matplotlib functions."
358 | ]
359 | },
360 | {
361 | "cell_type": "code",
362 | "execution_count": null,
363 | "metadata": {},
364 | "outputs": [],
365 | "source": [
366 | "ax = df.plot.line(ylim=(0, None), marker='o', title='My data')\n",
367 | "ax.annotate('Look here', (1, 6), xytext=(1.3, 7.2), arrowprops={'arrowstyle': '->'})"
368 | ]
369 | },
370 | {
371 | "cell_type": "code",
372 | "execution_count": null,
373 | "metadata": {},
374 | "outputs": [],
375 | "source": [
376 | "df.index = [f'Row {i}' for i in df.index]"
377 | ]
378 | },
379 | {
380 | "cell_type": "code",
381 | "execution_count": null,
382 | "metadata": {},
383 | "outputs": [],
384 | "source": [
385 | "df.plot.bar(rot=45)"
386 | ]
387 | },
388 | {
389 | "cell_type": "markdown",
390 | "metadata": {},
391 | "source": []
392 | }
393 | ],
394 | "metadata": {
395 | "kernelspec": {
396 | "display_name": "Python 3 (ipykernel)",
397 | "language": "python",
398 | "name": "python3"
399 | },
400 | "language_info": {
401 | "codemirror_mode": {
402 | "name": "ipython",
403 | "version": 3
404 | },
405 | "file_extension": ".py",
406 | "mimetype": "text/x-python",
407 | "name": "python",
408 | "nbconvert_exporter": "python",
409 | "pygments_lexer": "ipython3",
410 | "version": "3.11.4"
411 | }
412 | },
413 | "nbformat": 4,
414 | "nbformat_minor": 4
415 | }
416 |
--------------------------------------------------------------------------------
/02_Figure.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Figure and Subplots"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": null,
13 | "metadata": {},
14 | "outputs": [],
15 | "source": [
16 | "%matplotlib inline\n",
17 | "import matplotlib.pyplot as plt\n",
18 | "import numpy as np"
19 | ]
20 | },
21 | {
22 | "cell_type": "markdown",
23 | "metadata": {},
24 | "source": [
25 | "We usually need a `Figure` with one or multiple `Axes` (subplots).\n",
26 | "\n",
27 | "There are convenience functions to create both with one call."
28 | ]
29 | },
30 | {
31 | "cell_type": "markdown",
32 | "metadata": {},
33 | "source": [
34 | "## One plot - ``plt.subplots()``"
35 | ]
36 | },
37 | {
38 | "cell_type": "code",
39 | "execution_count": null,
40 | "metadata": {},
41 | "outputs": [],
42 | "source": [
43 | "plt.subplots();"
44 | ]
45 | },
46 | {
47 | "cell_type": "markdown",
48 | "metadata": {},
49 | "source": [
50 | "Returns a figure and an axes:"
51 | ]
52 | },
53 | {
54 | "cell_type": "code",
55 | "execution_count": null,
56 | "metadata": {},
57 | "outputs": [],
58 | "source": [
59 | "fig, ax = plt.subplots()\n",
60 | "fig.set_facecolor('blue')\n",
61 | "ax.set_facecolor('seagreen')"
62 | ]
63 | },
64 | {
65 | "cell_type": "code",
66 | "execution_count": null,
67 | "metadata": {},
68 | "outputs": [],
69 | "source": [
70 | "print(type(fig))"
71 | ]
72 | },
73 | {
74 | "cell_type": "code",
75 | "execution_count": null,
76 | "metadata": {},
77 | "outputs": [],
78 | "source": [
79 | "print(type(ax))"
80 | ]
81 | },
82 | {
83 | "cell_type": "markdown",
84 | "metadata": {},
85 | "source": [
86 | "## A regular grid of plots - `plt.subplots(rows, columns)`"
87 | ]
88 | },
89 | {
90 | "cell_type": "code",
91 | "execution_count": null,
92 | "metadata": {},
93 | "outputs": [],
94 | "source": [
95 | "plt.subplots(1, 2);"
96 | ]
97 | },
98 | {
99 | "cell_type": "markdown",
100 | "metadata": {},
101 | "source": [
102 | "Returns a `Figure` and a numpy array of `Axes`.\n",
103 | "\n",
104 | "By default, this is squeezed, i.e. if *rows* or *columns* is 1, you get a 1D array."
105 | ]
106 | },
107 | {
108 | "cell_type": "code",
109 | "execution_count": null,
110 | "metadata": {},
111 | "outputs": [],
112 | "source": [
113 | "fig, axs = plt.subplots(1, 2)\n",
114 | "print(type(axs), axs.shape)\n",
115 | "axs[0].set_facecolor('lime')\n",
116 | "axs[1].set_facecolor('fuchsia')"
117 | ]
118 | },
119 | {
120 | "cell_type": "markdown",
121 | "metadata": {},
122 | "source": [
123 | "The return value of `plt.subplots` is a (squeezed) numpy array."
124 | ]
125 | },
126 | {
127 | "cell_type": "code",
128 | "execution_count": null,
129 | "metadata": {},
130 | "outputs": [],
131 | "source": [
132 | "fig, axs = plt.subplots(2, 2)\n",
133 | "print(type(axs), axs.shape)\n",
134 | "axs[0, 0].set_facecolor('0.2')\n",
135 | "axs[0, 1].set_facecolor('0.4')\n",
136 | "axs[1, 0].set_facecolor('0.6')\n",
137 | "axs[1, 1].set_facecolor('0.8')"
138 | ]
139 | },
140 | {
141 | "cell_type": "markdown",
142 | "metadata": {},
143 | "source": [
144 | "By default, size-1 dimensions of the axes array are squeezed out."
145 | ]
146 | },
147 | {
148 | "cell_type": "markdown",
149 | "metadata": {},
150 | "source": [
151 | "\n",
152 | " Tip: Tuple unpacking\n",
153 | "
\n",
154 | "\n",
155 | "Tuple unpacking can be used to assign the returned axes to single variables. Common patterns:"
156 | ]
157 | },
158 | {
159 | "cell_type": "code",
160 | "execution_count": null,
161 | "metadata": {},
162 | "outputs": [],
163 | "source": [
164 | "fig, ax = plt.subplots()"
165 | ]
166 | },
167 | {
168 | "cell_type": "code",
169 | "execution_count": null,
170 | "metadata": {},
171 | "outputs": [],
172 | "source": [
173 | "fig, (ax1, ax2) = plt.subplots(1, 2)"
174 | ]
175 | },
176 | {
177 | "cell_type": "code",
178 | "execution_count": null,
179 | "metadata": {},
180 | "outputs": [],
181 | "source": [
182 | "fig, ((ax11, ax12), (ax21, ax22)) = plt.subplots(2, 2)"
183 | ]
184 | },
185 | {
186 | "cell_type": "markdown",
187 | "metadata": {},
188 | "source": [
189 | "\n",
190 | " Tip: Use axs.flat to iterate over all Axes.\n",
191 | "
"
192 | ]
193 | },
194 | {
195 | "cell_type": "code",
196 | "execution_count": null,
197 | "metadata": {},
198 | "outputs": [],
199 | "source": [
200 | "fig, axs = plt.subplots(3, 3)\n",
201 | "for ax in axs.flat:\n",
202 | " ax.set_facecolor('lightsalmon')"
203 | ]
204 | },
205 | {
206 | "cell_type": "markdown",
207 | "metadata": {},
208 | "source": [
209 | "`plt.subplots(N, M)` suits your needs when all created axes are on a regular grid and should have the same size."
210 | ]
211 | },
212 | {
213 | "cell_type": "markdown",
214 | "metadata": {},
215 | "source": [
216 | "## An irregular grid of plots - `plt.subplot_mosaic(...)`\n",
217 | "\n",
218 | "Inspired by the [patchwork](https://patchwork.data-imaginist.com/) library in R:\n",
219 | "\n",
220 | "- Provide a regular grid of names\n",
221 | "- Cells with the same name are merged into one plot\n",
222 | "- Use `None` for empty cells\n",
223 | "- Returns a dict, in which the individual `Axes` can be selected by name\n",
224 | "\n",
225 | "See the [subplot_mosaic() tutorial](https://matplotlib.org/stable/tutorials/provisional/mosaic.html) for more information."
226 | ]
227 | },
228 | {
229 | "cell_type": "code",
230 | "execution_count": null,
231 | "metadata": {},
232 | "outputs": [],
233 | "source": [
234 | "plt.subplot_mosaic([\n",
235 | " ['left', 'right-top'],\n",
236 | " ['left', 'right-bottom'],\n",
237 | "]);"
238 | ]
239 | },
240 | {
241 | "cell_type": "code",
242 | "execution_count": null,
243 | "metadata": {},
244 | "outputs": [],
245 | "source": [
246 | "fig, axd = plt.subplot_mosaic([\n",
247 | " ['left', 'right-top'],\n",
248 | " ['left', 'right-bottom'],\n",
249 | "])\n",
250 | "axd['left'].plot([1, 3, 2])\n",
251 | "axd['right-top'].hist(np.random.normal(size=500))\n",
252 | "axd['right-bottom'].hist(np.random.poisson(3, size=500))"
253 | ]
254 | },
255 | {
256 | "cell_type": "markdown",
257 | "metadata": {},
258 | "source": [
259 | "Tip: As a shortcut you can use a simple string\n",
260 | "\n",
261 | "- Lines -> rows\n",
262 | "- Letters -> subplot labels"
263 | ]
264 | },
265 | {
266 | "cell_type": "code",
267 | "execution_count": null,
268 | "metadata": {},
269 | "outputs": [],
270 | "source": [
271 | "fig, axd = plt.subplot_mosaic(\"\"\"\n",
272 | " AAABB\n",
273 | " AAACC\n",
274 | " DD.CC\n",
275 | " \"\"\");"
276 | ]
277 | },
278 | {
279 | "cell_type": "code",
280 | "execution_count": null,
281 | "metadata": {},
282 | "outputs": [],
283 | "source": [
284 | "axd"
285 | ]
286 | },
287 | {
288 | "cell_type": "markdown",
289 | "metadata": {},
290 | "source": [
291 | "## More complex layouts\n",
292 | "\n",
293 | "The above are the most important methods, but there is more:\n",
294 | "\n",
295 | "\n",
296 | "\n"
297 | ]
298 | },
299 | {
300 | "cell_type": "markdown",
301 | "metadata": {},
302 | "source": [
303 | "# Figure size\n",
304 | "\n",
305 | "`figsize = (width, height)` determines the dimensions of the figure in inches."
306 | ]
307 | },
308 | {
309 | "cell_type": "code",
310 | "execution_count": null,
311 | "metadata": {},
312 | "outputs": [],
313 | "source": [
314 | "fig, ax = plt.subplots()\n",
315 | "print('Default size:', fig.get_size_inches())"
316 | ]
317 | },
318 | {
319 | "cell_type": "code",
320 | "execution_count": null,
321 | "metadata": {},
322 | "outputs": [],
323 | "source": [
324 | "fig, ax = plt.subplots(figsize=(12, 4))"
325 | ]
326 | },
327 | {
328 | "cell_type": "markdown",
329 | "metadata": {
330 | "tags": []
331 | },
332 | "source": [
333 | "### Excusion: Exact figure size\n",
334 | "\n",
335 | "For pixel-based backends `figsize * dpi` is the actual size in pixels.\n",
336 | "\n",
337 | "Let's make the figure the pysically correct size on the screen."
338 | ]
339 | },
340 | {
341 | "cell_type": "code",
342 | "execution_count": null,
343 | "metadata": {},
344 | "outputs": [],
345 | "source": [
346 | "resolution = 1920, 1080 # pixels\n",
347 | "diagonal = 13.3 # inches\n",
348 | "\n",
349 | "import numpy as np\n",
350 | "rx, ry = resolution\n",
351 | "dpi = np.sqrt(rx**2 + ry**2) / diagonal\n",
352 | "print(dpi)"
353 | ]
354 | },
355 | {
356 | "cell_type": "code",
357 | "execution_count": null,
358 | "metadata": {},
359 | "outputs": [],
360 | "source": [
361 | "fig, ax = plt.subplots(dpi=dpi, facecolor='royalblue')"
362 | ]
363 | },
364 | {
365 | "cell_type": "markdown",
366 | "metadata": {},
367 | "source": [
368 | "Still does not match for the inline backend. :(\n",
369 | "\n",
370 | "The inline backend is trying to be smart and cuts of unused space around the axes ('tight' layout). Let's deactivate that:"
371 | ]
372 | },
373 | {
374 | "cell_type": "code",
375 | "execution_count": null,
376 | "metadata": {},
377 | "outputs": [],
378 | "source": [
379 | "%config InlineBackend.print_figure_kwargs = {'bbox_inches': None}\n",
380 | "\n",
381 | "fig, ax = plt.subplots(dpi=dpi, facecolor='royalblue')"
382 | ]
383 | },
384 | {
385 | "cell_type": "code",
386 | "execution_count": null,
387 | "metadata": {},
388 | "outputs": [],
389 | "source": [
390 | "# reactivate the tight layouting\n",
391 | "%config InlineBackend.print_figure_kwargs = {'bbox_inches': 'tight'}"
392 | ]
393 | },
394 | {
395 | "cell_type": "markdown",
396 | "metadata": {},
397 | "source": [
398 | "### General recommendation on figure size:\n",
399 | "\n",
400 | "\n",
401 | " Tip: Use dpi=100, do not bother with actual figure size.\n",
402 | "
\n",
403 | "\n",
404 | "Usually it's not worth adjusting the `dpi` to get a physically correct size on the screen, because different screens have different `dpi` and you don't want your plot to be screen depended.\n",
405 | "\n",
406 | "When working with pixel based output (i.e. not svg or pdf), use a fixed `dpi=100` and scale `figsize` as needed. Rule:\n",
407 | "\n",
408 | " `figsize * dpi = pixels` i.e. `figsize = (6, 4) --> 600x400 pixels`"
409 | ]
410 | },
411 | {
412 | "cell_type": "markdown",
413 | "metadata": {},
414 | "source": [
415 | "*Note*: The default is `dpi=100` in matplotlib (since version 2.0). The inline backend still overrides this default with `dpi=72` so that figures in the notebook are smaller by default."
416 | ]
417 | },
418 | {
419 | "cell_type": "markdown",
420 | "metadata": {},
421 | "source": [
422 | "### `figsize` and fonts\n",
423 | "\n",
424 | "Font sizes are in points. They are not affected by `figsize`."
425 | ]
426 | },
427 | {
428 | "cell_type": "code",
429 | "execution_count": null,
430 | "metadata": {},
431 | "outputs": [],
432 | "source": [
433 | "fig, ax = plt.subplots(figsize=(8, 4))\n",
434 | "fig.text(0.2, 0.5, 'figsize=(8, 4)', fontsize=20)"
435 | ]
436 | },
437 | {
438 | "cell_type": "code",
439 | "execution_count": null,
440 | "metadata": {},
441 | "outputs": [],
442 | "source": [
443 | "fig, ax = plt.subplots(figsize=(4, 2))\n",
444 | "fig.text(0.2, 0.5, 'figsize=(8, 4)', fontsize=20)"
445 | ]
446 | },
447 | {
448 | "cell_type": "markdown",
449 | "metadata": {},
450 | "source": [
451 | "## Layouting: Constrained Layout\n"
452 | ]
453 | },
454 | {
455 | "cell_type": "code",
456 | "execution_count": null,
457 | "metadata": {},
458 | "outputs": [],
459 | "source": [
460 | "x = np.linspace(0, 2, 201)\n",
461 | "fig, (ax1, ax2) = plt.subplots(1, 2)\n",
462 | "ax1.plot(x, x)\n",
463 | "ax2.plot(x, 1000*x**2)\n",
464 | "ax1.set_title('Function: x')\n",
465 | "ax2.set_title('Function: $x^2$')\n",
466 | "ax1.set_ylabel('The y label')\n",
467 | "ax2.set_ylabel('The y label')"
468 | ]
469 | },
470 | {
471 | "cell_type": "markdown",
472 | "metadata": {},
473 | "source": [
474 | "Layouting a figure is hard: Need to size and position elements such that they don't overlap.\n",
475 | "\n",
476 | "Matplotlib used to have a simple layouter (`plt.tight_layout()` or `fig.tight_layout()`).\n",
477 | "\n",
478 | "### New since Matplotlib 3.0: Constrained Layout"
479 | ]
480 | },
481 | {
482 | "cell_type": "code",
483 | "execution_count": null,
484 | "metadata": {},
485 | "outputs": [],
486 | "source": [
487 | "fig, (ax1, ax2) = plt.subplots(1, 2, layout='constrained')\n",
488 | "ax1.plot(x, x)\n",
489 | "ax2.plot(x, 1000*x**2)\n",
490 | "ax1.set_title('Function: x')\n",
491 | "ax2.set_title('Function: $x^2$')\n",
492 | "ax1.set_ylabel('The y label')\n",
493 | "ax2.set_ylabel('The y label')"
494 | ]
495 | },
496 | {
497 | "cell_type": "code",
498 | "execution_count": null,
499 | "metadata": {},
500 | "outputs": [],
501 | "source": []
502 | }
503 | ],
504 | "metadata": {
505 | "kernelspec": {
506 | "display_name": "Python 3 (ipykernel)",
507 | "language": "python",
508 | "name": "python3"
509 | },
510 | "language_info": {
511 | "codemirror_mode": {
512 | "name": "ipython",
513 | "version": 3
514 | },
515 | "file_extension": ".py",
516 | "mimetype": "text/x-python",
517 | "name": "python",
518 | "nbconvert_exporter": "python",
519 | "pygments_lexer": "ipython3",
520 | "version": "3.11.4"
521 | }
522 | },
523 | "nbformat": 4,
524 | "nbformat_minor": 4
525 | }
526 |
--------------------------------------------------------------------------------
/00_Getting_started.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "slideshow": {
7 | "slide_type": "slide"
8 | }
9 | },
10 | "source": [
11 | "# Effectively using Matplotlib\n",
12 | "\n",
13 | "\n",
14 | "\n",
15 | "### Tim Hoffmann\n",
16 | "\n",
17 | "- Day Job: Simulation Architect at ZEISS Semiconductor Manufacturing Technologies\n",
18 | "- Hobby: Core Developer Matplotlib\n",
19 | "\n",
20 | "\n",
21 | " Hint: Python is an open Community - You can become an active contributor too.\n",
22 | "
\n",
23 | "\n",
24 | "\n",
25 | "\n"
26 | ]
27 | },
28 | {
29 | "cell_type": "markdown",
30 | "metadata": {
31 | "slideshow": {
32 | "slide_type": "slide"
33 | }
34 | },
35 | "source": [
36 | "# Goal of this tutorial\n",
37 | "\n",
38 | "Understand fundamental concepts of Matplotlib to be able to use it effectively."
39 | ]
40 | },
41 | {
42 | "cell_type": "markdown",
43 | "metadata": {
44 | "slideshow": {
45 | "slide_type": "slide"
46 | }
47 | },
48 | "source": [
49 | "# Prerequisites\n",
50 | "\n",
51 | "https://github.com/timhoffm/using-matplotlib\n",
52 | "\n",
53 | "### Environment\n",
54 | "\n",
55 | "Jupyter plus any recent (>=3.0) matplotlib version will do. \n",
56 | "\n",
57 | "`pip install -r requirements.txt`\n",
58 | "\n",
59 | "or \n",
60 | "\n",
61 | "`conda env create -f environment.yml`"
62 | ]
63 | },
64 | {
65 | "cell_type": "markdown",
66 | "metadata": {},
67 | "source": [
68 | "# (One of) the major visualization libraries in Python\n",
69 | "\n",
70 | "Matplotlib was the first major visualization library.\n",
71 | "\n",
72 | "Today there are other great tools as well (notably web-based libraries like `bokeh` and `plotly`).\n",
73 | "\n",
74 | "> No one tool fulfills all needs.\n",
75 | "\n",
76 | "## Key reasons for Matplotlib:\n",
77 | "\n",
78 | "\n",
79 | "- very flexible - you can plot almost anything\n",
80 | "\n",
81 | "- available everywhere\n",
82 | "\n",
83 | "- foundation for special-purpose libraries (seaborn, cartopy, ...)\n",
84 | "\n",
85 | "- various backends: \n",
86 | " PNG, PDF, SVG, embed in notebooks, embed in GUI applications, ...\n",
87 | "\n",
88 | "- plotting interface for pandas\n",
89 | "\n",
90 | "- there's a lot of Matplotlib code out there."
91 | ]
92 | },
93 | {
94 | "cell_type": "markdown",
95 | "metadata": {
96 | "slideshow": {
97 | "slide_type": "slide"
98 | }
99 | },
100 | "source": [
101 | "# A Bit of History\n",
102 | "\n",
103 | "https://matplotlib.org/stable/users/history.html\n",
104 | "\n",
105 | "John D. Hunter first released Matplotlib in 2003."
106 | ]
107 | },
108 | {
109 | "cell_type": "markdown",
110 | "metadata": {
111 | "slideshow": {
112 | "slide_type": "slide"
113 | }
114 | },
115 | "source": [
116 | "#### Original design goal:\n",
117 | "\n",
118 | "Emulate MATLAB's plotting capabilities"
119 | ]
120 | },
121 | {
122 | "cell_type": "markdown",
123 | "metadata": {
124 | "slideshow": {
125 | "slide_type": "slide"
126 | }
127 | },
128 | "source": [
129 | "# Getting started"
130 | ]
131 | },
132 | {
133 | "cell_type": "markdown",
134 | "metadata": {
135 | "slideshow": {
136 | "slide_type": "-"
137 | }
138 | },
139 | "source": [
140 | "In notebooks, use the `%matplotlib` IPython magic to display plots inline.\n",
141 | "\n",
142 | "*Note:* `%matplotlib inline` is for static graphics. Alternatives: `%matplotlib ipympl` (or equivalent `%matplotlib widget`) for interactive plots. More later..."
143 | ]
144 | },
145 | {
146 | "cell_type": "code",
147 | "execution_count": 1,
148 | "metadata": {
149 | "slideshow": {
150 | "slide_type": "-"
151 | }
152 | },
153 | "outputs": [],
154 | "source": [
155 | "%matplotlib inline"
156 | ]
157 | },
158 | {
159 | "cell_type": "markdown",
160 | "metadata": {
161 | "slideshow": {
162 | "slide_type": "-"
163 | }
164 | },
165 | "source": [
166 | "The canonical import for Matplotlib:"
167 | ]
168 | },
169 | {
170 | "cell_type": "code",
171 | "execution_count": 2,
172 | "metadata": {
173 | "slideshow": {
174 | "slide_type": "-"
175 | }
176 | },
177 | "outputs": [],
178 | "source": [
179 | "import matplotlib.pyplot as plt"
180 | ]
181 | },
182 | {
183 | "cell_type": "markdown",
184 | "metadata": {
185 | "slideshow": {
186 | "slide_type": "slide"
187 | }
188 | },
189 | "source": [
190 | "A simple plot:\n",
191 | "\n",
192 | "- Create a `Figure` and an `Axes`\n",
193 | "- Plot your data into the `Axes`"
194 | ]
195 | },
196 | {
197 | "cell_type": "code",
198 | "execution_count": 3,
199 | "metadata": {
200 | "slideshow": {
201 | "slide_type": "fragment"
202 | }
203 | },
204 | "outputs": [
205 | {
206 | "data": {
207 | "image/png": "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",
208 | "text/plain": [
209 | ""
210 | ]
211 | },
212 | "metadata": {},
213 | "output_type": "display_data"
214 | }
215 | ],
216 | "source": [
217 | "fig, ax = plt.subplots()\n",
218 | "ax.plot([1, 3, 2]);\n",
219 | "#ax.spines[:].set_visible(False)"
220 | ]
221 | },
222 | {
223 | "cell_type": "markdown",
224 | "metadata": {
225 | "slideshow": {
226 | "slide_type": "fragment"
227 | }
228 | },
229 | "source": [
230 | "\n",
231 | " Hint: Suppressing output\n",
232 | "
\n",
233 | "Many functions in Matplotlib return some data, which is not always needed.\n",
234 | "\n",
235 | "Jupyter outputs the result of the last expression. To prevent the output append a semicolon:\n",
236 | "\n",
237 | " `ax.plot([1, 3, 2]);`"
238 | ]
239 | },
240 | {
241 | "cell_type": "markdown",
242 | "metadata": {
243 | "slideshow": {
244 | "slide_type": "slide"
245 | }
246 | },
247 | "source": [
248 | "# Basic elements of a plot\n",
249 | "\n",
250 | "- **Figure**: \n",
251 | " The outermost container for a matplotlib graphic.\n",
252 | "- **Axes**: \n",
253 | " A container for as single plot (line or scatter plot (y vs. x), a pseudo-color plot, etc.)\n",
254 | "- **Axis**: \n",
255 | " Direction with a scale. \n",
256 | " *Note:* This is *not* the line.\n",
257 | "- **Spines**: \n",
258 | " Axis lines.\n",
259 | "- **Artist**: \n",
260 | " Visible elements on the canvas: Lines, Rectangles, Text, Ticks, Axes, ...\n",
261 | " \n",
262 | "Let's highlight the respective parts of the plot:"
263 | ]
264 | },
265 | {
266 | "cell_type": "code",
267 | "execution_count": 4,
268 | "metadata": {
269 | "slideshow": {
270 | "slide_type": "slide"
271 | }
272 | },
273 | "outputs": [
274 | {
275 | "data": {
276 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAi4AAAGiCAYAAADA0E3hAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAb4klEQVR4nO3de5yddWHn8e+ZeybJJDNJzB1UCAKBUCHihUsr6spKqe4qImWF2mpXlLZS26rd1Wzj1ta2bltctbS0RcXdUm27irFuLbzsxihWsdxClIBCyH1CJslcMvfZP1KjkwyUcya3X+b9fr344zzzPOf5TX5kzie/8zxnKi+/4YmxAAAUoOFYn/AT5/10Opo6j8m5dg/Oyw33f/GYnAsAOPqOebh0NHVmXvP2Y31aAOAkUHe8BwAA8GwJFwCgGMIFACiGcAEAiiFcAIBiCBcAoBjCBQAohnABAIpR9QfQ7dn6zWy675Z0dz6Ywb6dOefyP8285736GY/p2npPHl33wfR1bczg8uGkuebxAgBTWNUrLiNDfZkx56ycccnqZ7X//n2b8sCan8vshRdm5VVrUt84vepBAgAkNay4zDn15Zlz6suf9f5b138mLTMWZdnFq5Ik9Y2tSfZVe1oAgKP/u4r27vhOOpZeOqnnGBtLuvdXf1z34GiGB7sndW4AoDZjY2MZGepNU+v81NUdmctqj3q4DPZ1pnHa3Ek9R/f+ZNbbajlyZ5JzJnVuAGByXvrme9IyY+ERea5j8tuhK5XKpI6fOS3Z+2fVH9fT0JDPPX/5pM7NeI29rbn2NV/OZ750eYam9x3v4Uxp5uLEYS5OLObjxDHc2ZR3v+FbR/T61qMeLk2t8zLY1zmp56hUkrbW6o+ra6hk2oz6SZ2b8RrTkLa0Zdr0hjT4sz2uzMWJw1ycWMzHiWO490BmTHYB48cd9c9xmTX//OzevPZonwYAmAKqDpfhod5071qf7l3rkyT9+55M96716e/ekiR57J4P5+G7bjq4/6Ll16a/e0s2rlud3q6NGRmq4SpbAIDU8FZR984Hct8X3nTw8aNf/2CSZMEL3pCzLvtIBvt2ZqBn68GvT2s7JSuuuC2PrludLQ99OiMXjxyBYQMAU1HV4dK++KV5+Q1PPO3Xz7rsI4cfs+gledFVX0qSNLW+OMn2ak8LAOB3FQEA5RAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUIyGWg7a8tCnsum+WzLY15nW9mVZdtGqzF504dPuv/2Rv8um+27J/r0/yMDywaS55vECAFNY1SsuOx69MxvXrc6p59+YlVetyeyFF+aBNdenv3vLhPvv2fatbLj7V7PozKtz4dVfSWPz7MmOGQCYoqoOlyfvvzULz7w6i86+JtPbl2XZxavSPGNhtqy/fcL99+34TlpmLsmSFW/JtLZTUlffNOlBAwBTU1XhMjoymJ7OB9Ox9JJx2zuWXpq92++d8JhZCy7IQM/2PPXE3RkbG8vY2GjtowUAprSqrnEZ6u/K2NhImlrnjtveOG1uBvs6Jzxm1oKVOfuVf5T1X7kxoyMDGVw+nLTUPmAAYOqq6eLcpHLI47FUKoduO6B39yPZ+LX/lude8MvpOOUn09hyTZKu2k4LAExpVYVLY0t7KpX6w1ZXhvY/lcZpcyc85ol/+XhmLViZU1749iRJXb1bigCA2lR1jUtdfVNmzDs3uzevHbd99+a1mbXgggmPGR3an0rFx8UAAJNXdVEsPe+t2bbhjmzbcEd6uzZm47rVGejemsXLr02SPHbPh/PwXTcd3H/Oc1+Zzh98OVse+nT279uU0ZHBIzd6AGBKqfoal/mnX5nh/q48fu/NGejdmekdZ2TFFbelZeaSJMlg384M9Gw9uP/CM6/KyFBPNj/0yTz6jf+eoZcOJq1H7hsAAKaOmi7OXXzOdVl8znUTfu2syz5y2LYl574lS859S5KkufXFSbbXcloAYIpz8QkAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMVoqOWgLQ99KpvuuyWDfZ1pbV+WZRetyuxFFz7t/qMjA3n823+c7Y/8nwycvT1prnm8AMAUVvWKy45H78zGdatz6vk3ZuVVazJ74YV5YM316e/e8rTHrP+Hd6Zr89dz5st/L03T5k1qwADA1FV1uDx5/61ZeObVWXT2NZnevizLLl6V5hkLs2X97RPu/9Smr2bP1m9mxRW3pWPJxanU1U960ADA1FRVuIyODKan88F0LL1k3PaOpZdm7/Z7Jzxm1+Nfycx552bTfX+SdZ+6MIN9nbWPFgCY0qoKl6H+royNjaSpde647Y3T5j5tkPTvezJ7t387vbu/l3Nf/adpaG6rfbQAwJRW08W5SeWQx2OpVA7d9q9fGRtNkpz9ij9OQ3Nb6updmQsA1KaqFZfGlvZUKvWHra4M7X8qjdPmTnhMc+tz0jx9gZUWAGDSqgqXuvqmzJh3bnZvXjtu++7NazNrwQUTHjNr4coM9O3I8FBv7aMEAEgNdxUtPe+t2bbhjmzbcEd6uzZm47rVGejemsXLr02SPHbPh/PwXTcd3P85y16bxub2fPfuX0vv7kcyOjJ45EYPAEwpVV/jMv/0KzPc35XH7705A707M73jjKy44ra0zFySJBns25mBnq0/OkHj9Jx35e3Z+LVV+fbfXJmhSwaT1iP3DQAAU0dNF+cuPue6LD7nugm/dtZlHzls2/T20/MTV34mSdLc+uIk22s5LQAwxfldRQBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFKOhloO2PPSpbLrvlgz2daa1fVmWXbQqsxdd+G8et2fbtzLQuz1pruWsAMBUV/WKy45H78zGdatz6vk3ZuVVazJ74YV5YM316e/e8ozHDQ/sy4a7fzV19U01DxYAmNqqDpcn7781C8+8OovOvibT25dl2cWr0jxjYbasv/0Zj/ve//vNzF/22lTqhAsAUJuqwmV0ZDA9nQ+mY+kl47Z3LL00e7ff+7THbfvuX2f/3ify3JXvqmmQAABJlde4DPV3ZWxsJE2tc8dtb5w2N4N9nRMe07fnB3nsng/n/Nd9NnV1NV1SAwCQpOa7iiqHPB5LpXLotmRsdCQP/+Mv53kvuimts59f26kAAP5VVUsgjS3tqVTqD1tdGdr/VBqnzT1s/+GhnnR3PpCeXeuzce0HkiQjN49MYrgAwFRWVbjU1Tdlxrxzs3vz2sx7/uUHt+/evDZzn/vvDn/yppl50Rv/Ydy2+obXJemrabAAwNRW9UUnS897azbcdVPa5q1I24Lzs/Xh/52B7q1ZvPzaJMlj93w4A73bc/Yr/jCVSl1mzHnB+Ceo+Mw7AKA2VYfL/NOvzHB/Vx6/9+YM9O7M9I4zsuKK29Iyc0mSZLBvZwZ6th7xgQIA1HSbz+Jzrsvic66b8GtnXfaRZz5h04wkPbWcFgCY4rxvAwAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMRpqOWjLQ5/KpvtuyWBfZ1rbl2XZRasye9GFE+7b+f2/z5b1t6dn18MZHRnM4DkDSfOkxgwATFFVr7jsePTObFy3Oqeef2NWXrUmsxdemAfWXJ/+7i0T7r9n6z+nfcklWXHFbVn5hi+mrr5p0oMGAKamqldcnrz/1iw88+osOvuaJMmyi1dl95P/lC3rb89pL3nPYfsvu3jV+BM2zUzSW9toAYApraoVl9GRwfR0PpiOpZeM296x9NLs3X7vER0YAMChqgqXof6ujI2NpKl17rjtjdPmZrCv81k9x8iQ1RYAoDY13lVUOeTxWCqVQ7cdbsfGz2d4sLu2UwIAU15V4dLY0p5Kpf6w1ZWh/U+lcdrcpznqgB2P3pnvfvU30tjSXv0oAQBSZbjU1Tdlxrxzs3vz2nHbd29em1kLLnja43Zs/Hy+e/e7c/Yrb05dvXuhAYDaVP1W0dLz3pptG+7Itg13pLdrYzauW52B7q1ZvPzaJMlj93w4D99108H9d2z8fDbc/as5/WX/NW3zX5ixsdEjN3oAYEqp+nbo+adfmeH+rjx+780Z6N2Z6R1nZMUVt6Vl5pIkyWDfzgz0bD24/9aH/1fGRofzyNr355G178/gyiQtR2z8AMAUUtMn5y4+57osPue6Cb921mUfGff4ha+9Y9zj5ukvTrK9ltMCAFOc31UEABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxhAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABRDuAAAxRAuAEAxGmo5aMtDn8qm+27JYF9nWtuXZdlFqzJ70YVPu3/X1nvy6LoPpq9rYwaXDyfNNY8XAJjCql5x2fHondm4bnVOPf/GrLxqTWYvvDAPrLk+/d1bJtx//75NeWDNz2X2wguz8qo1qW+cPulBAwBTU9UrLk/ef2sWnnl1Fp19TZJk2cWrsvvJf8qW9bfntJe857D9t67/TFpmLMqyi1clSeobW5Psq+qcY2NJ9/5qR5r0NIxlf89I9QfytIZ7h7Mv+7K/dzhD8Wd7PJmLE4e5OLGYjxPHcN9wkmRsbOyIPWdV4TI6Mpiezgdz6gtvGLe9Y+ml2bv93gmP2bvjO+lYemntI8yBaJn1tlqOHE5y/6TOzeHekVnJa473KEjMxYnEXJxYzMeJpW6sN0nbEXmuqsJlqL8rY2MjaWqdO25747S5GezrnPCYwb7ONE6bO+HXnq2Z05K9f1b9cbsGn5Of+87dkzo3401rruSzv7MkV71vc/YPHLmCpnrm4sRhLk4s5uPE0dKU/MVvzsov/sFI+gePzHPWdHFuUjnk8VgqlUO3/djez/C1Z3W2StLWWv1xA/V1aWiaOalzM15jcyVtbW1pbJ6ZoSO49Ef1zMWJw1ycWMzHiaOppZIlS5akru7JJEdmLqq6OLexpT2VSv1hqytD+5962lWVptZ5T7saAwBQjarCpa6+KTPmnZvdm9eO275789rMWnDBhMfMmn/+YfsDANSi6tuhl5731mzbcEe2bbgjvV0bs3Hd6gx0b83i5dcmSR6758N5+K6bDu6/aPm16e/eko3rVqe3a2NGhmq4PYgTxtDwWD65Zm+Ghi2/Hm/m4sRhLk4s5uPEcTTmovLyG56o+tl++AF0A707M73jjCy76AOZvejFSZINd787/d2b88LX3nFw/wMfQLc6vbs35smbR7K4/djcntY5sCBXf+ubx+RcAMDRV1O4TMYdL3px5jVvPybnEi4AcHLxu4oAgGIIFwCgGMIFACiGcAEAilHjJ+dyMvuZS2fk6le2Zc6s+jy+bSgf+2xXHnxsYMJ9L/mJabnykhk5fUlTGhsqeXzbUD65Zm++vaH/GI/65FTNXPy45c9vyh/dND8/2DqUX/ydY3Mx/Mmu2rlobEje/JpZedWLpqe9rT679gzn9i/vy5e/0XsMR31yqnYuXvGi1rzpVW1Z/JyG9O4fy7ce3p8/+ds92dc7egxHffJZcXpzrn5VW5Ytbczc2Q15/y2dWXf/M3/kyYplzXnH69vz3IWN2bV3JHd8ZV/uXNtT1XmPebjsHpx32Lbmpkpmttalp280QyNjaWmqy7SmSnZ3j2R0gv+v6uqSjrb67B8YS//gaBrrK5nRWpd9vaMZHPrRTVITnYtn9lMXtOadb2jPH//V7jz0/YFcefGM/O475+UtH9yWnV2H38a+4vTm3Pvd/vz5F/amp280l790en77hnl55+9tz6Obh47Dd3DyqHYufmh6SyXvu35OvvO9/rTPrD+GIz551TIXH/iFuWlvq8/v3/5UtnQOp31mfepNx6RVOxfnnNac914/Jx//XFe+8eD+zJ3dkJuuac+vXduRD/zpruPwHZw8WpoqeWzzYL78jZ781i/+26+3C+bU53feMS9fWteTD922K+c8vzm/8qaO7Okeydr7nv1nvB3zcLnh/i8etu1jvz4/G58czB99pevgtr/8wMKsu78vt35+72H7v+11s/OyFdPyltXbDm571zXtOe28pvzSH+w4OgOfIq66bGb+/us9+dLXD/yr8GOf25OVZ0/Lz1w6Y8K5+Njn9ox7/Odf2JuLVkzLS8+dJlwmqdq5+KGbfrYjd32rL6NjyUUrph2r4Z7Uqp2LF53dkvOWteTaD2xNd9+Bf33t2H1sPr/qZFftXJz9vKbseGo4f/fVA/+q3/7USL74tZ5c/aoj85uKp7J/frg///zws19dv/KSmdnZNXLwdWPT9uGccWpT3vjKtqrC5bhf49JQn5xxStNhby18e0N/lj+/ecJjlj9vgv0f7s8LTm1K/XH/jspVy1wcqlJJprXUHfxhTW1qnYvLXzI9i+Y15JNfevqwoTq1zMXLVkzL9zYN5k2vmpm//tCifHLVwrz9P85OU+PkfuHsVFfLXKz//kDmzm7Ii5e3JEnaZ9bl0he25p6HfIr7sXakXruP+zUus2bUp76+kq7u8f8a6do3ko62lgmPaW+rT9e+8d98V/dIGuormTWjLrv3edGsRS1zcag3vmJmWpoq+eq9fUdjiFNGLXOxeF5D3vq62XnX/9gx4Vus1KaWuVg4pyHnntacwaGxfOCWXZk1oy6/8qaOzGyty+/fvvtYDPukVMtcrP/+YD502668/xfmpqmxkob6Stbd35eP3tE14f4cPUfqtfuEWZ849DePVyqHbxu3f5XbefaqnYsfumxla667YlY++Oe7sqfHK+eR8Gznoq6S/Jefn5NPrtmbzTuHj83gpphq/l7U1SVjY2P50F/uynefGMw31/fnE3/TlVe/ZLpVlyOgmrk4dUFDbryqPZ/+0t68/Xe35zc+ujML5jbkpp/tOPoD5TBH4rX7uK+47O0ZycjIWDraxl+1Nntm/WFV/UMH6nr8/u0z6zM8MpZ9XjBrVstc/NBPXdCaX/tPHfmtW3flO9/7t+964ZlVOxfTWio589TmLFvSlF9+Y3uSAz/M6+oq+cpHl+Y3Proz//KIealFLX8vnto7kl17RtLb/6Mfx09sH0pdXSXzZtdnS6e4rEUtc/Gzr56V9d8fzB3/2J0k+f6WofT/VVdufvf8/MUX9lihP4aO1Gv3cV9xGR5JHtk0mAvOGr/Md8GZLVn//Yl/0K7/wWAuOHP8/ivPasn3nhjMiP8Ha1bLXCQHVlre8+aO/PZfPpVvPuQ26COh2rno6x/Lz39wW972oe0H/7vzaz3ZtH0ob/vQ9mx4fPBYDf2kU8vfi4ceG8ic2fVpaf7R6sqS5zRmZHQsnXtcpFurWuaiuamS0UOWY0ZHDzyuVKx+HUtH6rX7uIdLknz27u685mUzcvlLp+eUBQ15x+tnZ357/cF7u9/62ll57/VzDu5/59ruzO+ozw2vn51TFjTk8pdOz79/2Yz89T/uO17fwkmj2rm4bGVr3nv9nHzib/fk4R8MpL2tLu1tdZne4gfCZFUzF2NjyePbhsb9t6f7wMcDPL5tKP2D3kSdjGr/Xtz17b7s6x3Ne948J6cuaMiK05vzn//D7Hz5673jPrKB6lU7F994cH8u+YnW/MwlM7JwTn2WP78pN76xPRt+MJCn9orIyWhpruS0JY05bUljkgPXdp22pDHPaT+wqnK0XruP+1tFSfLVe/vSNr0u171mVjraDnyg0Ps+3nnw9sGOtvqDfxDJgdvZ3vfxzrzz9e157aUz89TekfzPz3ZVdTsVE6t2Ln764hlpqK/kXW/qyLve9KP3jL/8jZ783qddhDgZ1c4FR0+1c9E/MJZfv3lnfumN7fnEexdkX+9ovnpvX/7iTnd7TVa1c/F/7+lNa0slr/vJGXn762enp280//LIQP7s7/Ycp+/g5PGCU5ryhzfNP/j4HW848Db1D3/+H63X7srLb3hC/gMARTgh3ioCAHg2hAsAUAzhAgAUQ7gAAMUQLgBAMYQLAFAM4QIAFEO4AADFEC4AQDGECwBQDOECABTj/wOdCjuINY6DpAAAAABJRU5ErkJggg==",
277 | "text/plain": [
278 | ""
279 | ]
280 | },
281 | "metadata": {},
282 | "output_type": "display_data"
283 | }
284 | ],
285 | "source": [
286 | "fig, ax = plt.subplots()\n",
287 | "fig.set_facecolor('royalblue')\n",
288 | "ax.set_facecolor('yellowgreen')\n",
289 | "ax.xaxis.set_tick_params(colors='white', gridOn=True, grid_color='fuchsia')\n",
290 | "ax.spines['left'].set_color('orange')\n",
291 | "ax.spines['left'].set_linewidth(20)"
292 | ]
293 | },
294 | {
295 | "cell_type": "markdown",
296 | "metadata": {
297 | "slideshow": {
298 | "slide_type": "slide"
299 | }
300 | },
301 | "source": [
302 | "## Basic usage pattern\n",
303 | "\n",
304 | "- Create a figure and one or more axes\n",
305 | "- draw the data into the axes\n",
306 | "- configure further plot properties"
307 | ]
308 | },
309 | {
310 | "cell_type": "code",
311 | "execution_count": 5,
312 | "metadata": {},
313 | "outputs": [],
314 | "source": [
315 | "import numpy as np\n",
316 | "\n",
317 | "# prepare some data\n",
318 | "N = 100\n",
319 | "t = np.linspace(0, 60, N)\n",
320 | "temperature = 0.008 *t + 0.1 * np.random.random(N) + 23"
321 | ]
322 | },
323 | {
324 | "cell_type": "code",
325 | "execution_count": 6,
326 | "metadata": {},
327 | "outputs": [
328 | {
329 | "data": {
330 | "text/plain": [
331 | "Text(0, 0.5, 'Temperature')"
332 | ]
333 | },
334 | "execution_count": 6,
335 | "metadata": {},
336 | "output_type": "execute_result"
337 | },
338 | {
339 | "data": {
340 | "image/png": "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82Zs374dubm5yuP8rLzFxMRg7NixmDVrFlatWoXp06fjhRde4OfUw8GDB1FXV4eLL74YGo0GGo0GO3fuxO9//3toNBrlM+Hn5Z/BYMDUqVNx4sQJ/rvVQ1ZWFiZNmuT12MSJE5XDP5H+vBgADYGYmBhcfPHF2Lp1q9fjW7duxaWXXhqhuxoeCgsLkZmZ6fXZ2Ww27Ny5c8R9dqIoYvny5di0aRO2bduGwsJCr+f5WQUniiKsVis/px6uuuoqlJaWori4WPmaNWsW7rnnHhQXF2P06NH8vIKwWq344osvkJWVxX+3erjssst8RnV8+eWXyM/PBxAFf2YNeps1iaIoim+99Zao1WrF9evXi8eOHRO/973viQaDQTxz5kykby3i2traxMOHD4uHDx8WAYjPPfecePjwYfHs2bOiKIris88+K5pMJnHTpk1iaWmpeNddd4lZWVlia2trhO98aH37298WTSaTuGPHDrGmpkb56uzsVF7Dz0qycuVKcdeuXeLp06fFkpIS8YknnhBVKpX44YcfiqLIz6k3nqfARJGfl6cf/OAH4o4dO8Ty8nJx79694g033CAajUblz3J+Vm779+8XNRqN+Mwzz4gnTpwQX3/9dTEuLk587bXXlNdE8vNiADSE/vjHP4r5+fliTEyMeNFFFynHl0e67du3iwB8vh544AFRFKWjkk8++aSYmZkp6nQ6ccGCBWJpaWlkbzoC/H1GAMQNGzYor+FnJXnooYeU/9bS0tLEq666Sgl+RJGfU296BkD8vNzuuOMOMSsrS9RqtWJ2drZ4yy23iJ9//rnyPD8rb++++644ZcoUUafTiRMmTBDXrl3r9XwkPy9BFEVx8PNMRERERNGDPUBEREQ04jAAIiIiohGHARARERGNOAyAiIiIaMRhAEREREQjDgMgIiIiGnEYABEREdGIwwCIiIiIRhwGQER0wXnqqacwY8aMSN8GEUUxToImomFFEISgzz/wwANYvXo1rFYrUlJShuiuiGi4YQBERMNKbW2t8s8bN27Ez372M6+N07GxsTCZTJG4NSIaRlgCI6JhJTMzU/kymUwQBMHnsZ4lsAcffBBLly7Fr371K2RkZCAxMRFPP/007HY7fvjDHyI5ORm5ubn485//7PWzqqurcccddyApKQkpKSm4+eabcebMmaH9hYloUDAAIqIRYdu2bTh37hx27dqF5557Dk899RRuuOEGJCUlYd++fXj00Ufx6KOPorKyEgDQ2dmJRYsWIT4+Hrt27cKePXsQHx+Pa6+9FjabLcK/DRH1FwMgIhoRkpOT8fvf/x7jx4/HQw89hPHjx6OzsxNPPPEExo0bh5UrVyImJgYff/wxAOCtt96CSqXCSy+9hKlTp2LixInYsGEDKioqsGPHjsj+MkTUb5pI3wAR0VCYPHkyVCr33/kyMjIwZcoU5Xu1Wo2UlBTU1dUBAA4ePIiTJ0/CaDR6XcdiseDUqVNDc9NENGgYABHRiKDVar2+FwTB72NOpxMA4HQ6cfHFF+P111/3uVZaWtrg3SgRDQkGQEREflx00UXYuHEj0tPTkZCQEOnbIaIBxh4gIiI/7rnnHqSmpuLmm2/G7t27cfr0aezcuROPP/44qqqqIn17RNRPDICIiPyIi4vDrl27MGrUKNxyyy2YOHEiHnroIXR1dTEjRHQB4CBEIiIiGnGYASIiIqIRhwEQERERjTgMgIiIiGjEYQBEREREIw4DICIiIhpxGAARERHRiMMAiIiIiEYcBkBEREQ04jAAIiIiohGHARARERGNOAyAiIiIaMT5/8+pSiKnIpoiAAAAAElFTkSuQmCC",
341 | "text/plain": [
342 | ""
343 | ]
344 | },
345 | "metadata": {},
346 | "output_type": "display_data"
347 | }
348 | ],
349 | "source": [
350 | "# create a figure and one or more axes\n",
351 | "fig, ax = plt.subplots()\n",
352 | "\n",
353 | "# draw the data into the axes\n",
354 | "ax.plot(t, temperature)\n",
355 | "\n",
356 | "# configure further plot properties\n",
357 | "ax.set_xlabel('Time')\n",
358 | "ax.set_ylabel('Temperature')"
359 | ]
360 | },
361 | {
362 | "cell_type": "markdown",
363 | "metadata": {},
364 | "source": [
365 | "Most of the plotting and configuration is performed using Axes methods.\n",
366 | "\n",
367 | "See https://matplotlib.org/stable/api/axes_api.html"
368 | ]
369 | },
370 | {
371 | "cell_type": "markdown",
372 | "metadata": {},
373 | "source": [
374 | "\n",
375 | " Task: Extend the above plot.\n",
376 | "
\n",
377 | "\n",
378 | "- Add a title \"It's getting warm\" (use `ax.set_title(name)`)\n",
379 | "- Set the y-limit to the range 22..24 (use `ax.set_ylim(min, max)`)"
380 | ]
381 | }
382 | ],
383 | "metadata": {
384 | "celltoolbar": "Slideshow",
385 | "kernelspec": {
386 | "display_name": "Python 3 (ipykernel)",
387 | "language": "python",
388 | "name": "python3"
389 | },
390 | "language_info": {
391 | "codemirror_mode": {
392 | "name": "ipython",
393 | "version": 3
394 | },
395 | "file_extension": ".py",
396 | "mimetype": "text/x-python",
397 | "name": "python",
398 | "nbconvert_exporter": "python",
399 | "pygments_lexer": "ipython3",
400 | "version": "3.11.4"
401 | }
402 | },
403 | "nbformat": 4,
404 | "nbformat_minor": 4
405 | }
406 |
--------------------------------------------------------------------------------