Skip to content

Commit 7f2e8da

Browse files
committed
modernize matplotlib sections of interact notebook
1 parent d528a20 commit 7f2e8da

File tree

4 files changed

+152
-28
lines changed

4 files changed

+152
-28
lines changed

notebooks/02.Interact/02.00-Using-Interact.ipynb

Lines changed: 137 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
{
2626
"cell_type": "code",
2727
"execution_count": null,
28-
"metadata": {},
28+
"metadata": {
29+
"tags": []
30+
},
2931
"outputs": [],
3032
"source": [
3133
"from ipywidgets import interact, interactive, fixed, interact_manual\n",
@@ -294,10 +296,12 @@
294296
{
295297
"cell_type": "code",
296298
"execution_count": null,
297-
"metadata": {},
299+
"metadata": {
300+
"tags": []
301+
},
298302
"outputs": [],
299303
"source": [
300-
"# %load solutions/reverse-text.py\n"
304+
"# %load solutions/reverse-text.py"
301305
]
302306
},
303307
{
@@ -351,47 +355,59 @@
351355
]
352356
},
353357
{
354-
"cell_type": "markdown",
358+
"cell_type": "code",
359+
"execution_count": null,
355360
"metadata": {},
361+
"outputs": [],
362+
"source": []
363+
},
364+
{
365+
"cell_type": "markdown",
366+
"metadata": {
367+
"tags": []
368+
},
356369
"source": [
357370
"## Basic interactive plot\n",
358371
"\n",
359-
"Though the examples so far in this notebook had very basic output, more interesting possibilities are straightforward. \n",
360372
"\n",
361-
"The function below plots a straight line whose slope and intercept are given by its arguments."
373+
"The function below plots a straight line whose slope and intercept are given by its arguments.\n",
374+
"\n",
375+
"The interactive below displays a line whose slope and intercept is set by the sliders. Note that if the variable containing the widget, `interactive_plot`, is the last thing in the cell it is displayed."
362376
]
363377
},
364378
{
365379
"cell_type": "code",
366380
"execution_count": null,
367-
"metadata": {},
381+
"metadata": {
382+
"tags": []
383+
},
368384
"outputs": [],
369385
"source": [
370-
"%matplotlib widget\n",
371386
"import matplotlib.pyplot as plt\n",
372387
"import numpy as np\n",
373-
"\n",
374388
"def f(m, b):\n",
375389
" plt.figure(2)\n",
376390
" plt.clf()\n",
377391
" plt.grid()\n",
378392
" x = np.linspace(-10, 10, num=1000)\n",
379393
" plt.plot(x, m * x + b)\n",
380394
" plt.ylim(-5, 5)\n",
381-
" plt.show()\n"
395+
" plt.show()"
382396
]
383397
},
384398
{
385399
"cell_type": "markdown",
386400
"metadata": {},
387401
"source": [
388-
"The interactive below displays a line whose slope and intercept is set by the sliders. Note that if the variable containing the widget, `interactive_plot`, is the last thing in the cell it is displayed."
402+
"The interactive below displays a line whose slope and intercept is set by the sliders."
389403
]
390404
},
391405
{
392406
"cell_type": "code",
393407
"execution_count": null,
394-
"metadata": {},
408+
"metadata": {
409+
"tags": []
410+
},
395411
"outputs": [],
396412
"source": [
397413
"interact(f, m=(-2.0, 2.0), b=(-3, 3, 0.5))"
@@ -401,41 +417,128 @@
401417
"cell_type": "markdown",
402418
"metadata": {},
403419
"source": [
404-
"### Exercise: Make a plot\n",
420+
"## Fully interactive plot\n",
421+
"\n",
422+
"While the above example works, it has some drawbacks:\n",
423+
"1. It is inefficient to re-run all the plotting code\n",
424+
"2. No zooming or panning\n",
425+
"3. Screen can jump when moving the sliders\n",
405426
"\n",
406-
"Here is a python function that, given $k$ and $p$, plots $f(x) = \\sin(k x - p)$.\n"
427+
"A better solution is to use the [ipympl](https://matplotlib.org/ipympl/) Matplotlib backend. You can activate this with the line magic: `%matplotlib ipympl`. Then in your interactive function you update the matplotlib artists."
407428
]
408429
},
409430
{
410431
"cell_type": "code",
411432
"execution_count": null,
433+
"metadata": {
434+
"tags": []
435+
},
436+
"outputs": [],
437+
"source": [
438+
"# activate the widget based backend.\n",
439+
"%matplotlib ipympl\n",
440+
"\n",
441+
"x = np.linspace(-10, 10, num=1000)\n",
442+
"m, b = 0, 0\n",
443+
"\n",
444+
"fig, ax = plt.subplots()\n",
445+
"ax.grid()\n",
446+
"ax.set_ylim(-5, 5)\n",
447+
"line = ax.plot(x, m * x + b)[0]\n",
448+
"\n",
449+
"\n",
450+
"@interact(m=(-2.0, 2.0), b=(-3, 3, 0.5))\n",
451+
"def update_line(m, b):\n",
452+
" # use matplotlib functions to update the canvas\n",
453+
" line.set_ydata(m * x + b)\n",
454+
" fig.canvas.draw_idle()\n"
455+
]
456+
},
457+
{
458+
"cell_type": "markdown",
412459
"metadata": {},
460+
"source": [
461+
"## mpl-interactions\n",
462+
"\n",
463+
"The [mpl-interactions](https://mpl-interactions.readthedocs.io/en/stable/) library can automate the updating of Matplotlib artists for you. non-matplotlib kwargs to functions like `plot` will be interpted to sliders and widget controls similarly to `interact` and automatically connected with the matplotlib artists."
464+
]
465+
},
466+
{
467+
"cell_type": "code",
468+
"execution_count": null,
469+
"metadata": {
470+
"tags": []
471+
},
413472
"outputs": [],
414473
"source": [
415-
"def plot_f(k, p):\n",
416-
" plt.figure(5)\n",
417-
" plt.clf()\n",
418-
" plt.grid()\n",
419-
" x = np.linspace(0, 4 * np.pi)\n",
420-
" y = np.sin(k*x - p)\n",
421-
" plt.plot(x, y)\n",
422-
" plt.show()"
474+
"from mpl_interactions import ipyplot as iplt\n",
475+
"\n",
476+
"fig, ax = plt.subplots()\n",
477+
"ax.grid()\n",
478+
"ax.set_ylim(-5,5)\n",
479+
"\n",
480+
"# define function in a way you can re-use in calculations\n",
481+
"def f(x, m, b):\n",
482+
" return m * x + b\n",
483+
" \n",
484+
"ctrls = iplt.plot(x, f, m = (-2,2), b=(-3, 3, 10))\n"
423485
]
424486
},
425487
{
426488
"cell_type": "markdown",
427489
"metadata": {},
428490
"source": [
429-
"Copy the above function definition and make it interactive using `interact`, so that there are sliders for the parameters $k$ and $p$, where $0.5\\leq k \\leq 2$ and $0 \\leq p \\leq 2\\pi$ (hint: use `np.pi` for $\\pi$)."
491+
"### Exercise: Make a plot\n",
492+
"\n",
493+
"Here is an example of making a plot of $f(x) = \\sin(k x - p)$.\n"
430494
]
431495
},
432496
{
433497
"cell_type": "code",
434498
"execution_count": null,
499+
"metadata": {
500+
"tags": []
501+
},
502+
"outputs": [],
503+
"source": [
504+
"x = np.linspace(0, 4 * np.pi, 100)\n",
505+
"k = 1\n",
506+
"p = np.pi\n",
507+
"\n",
508+
"def f(x, k, p):\n",
509+
" return np.sin(k*x -p)\n",
510+
"fig, ax = plt.subplots()\n",
511+
"ax.grid()\n",
512+
"ax.plot(x, f(x, k, p))\n"
513+
]
514+
},
515+
{
516+
"cell_type": "markdown",
435517
"metadata": {},
518+
"source": [
519+
"Copy the above function definition and make it interactive using `interact` or `mpl-interactions`, so that there are sliders for the parameters $k$ and $p$, where $0.5\\leq k \\leq 2$ and $0 \\leq p \\leq 2\\pi$ (hint: use `np.pi` for $\\pi$)."
520+
]
521+
},
522+
{
523+
"cell_type": "code",
524+
"execution_count": null,
525+
"metadata": {
526+
"tags": []
527+
},
528+
"outputs": [],
529+
"source": [
530+
"# %load solutions/plot-function-interact.py"
531+
]
532+
},
533+
{
534+
"cell_type": "code",
535+
"execution_count": null,
536+
"metadata": {
537+
"tags": []
538+
},
436539
"outputs": [],
437540
"source": [
438-
"# %load solutions/plot-function.py"
541+
"# %load solutions/plot-function-mpl-inter.py"
439542
]
440543
},
441544
{
@@ -460,9 +563,9 @@
460563
],
461564
"metadata": {
462565
"kernelspec": {
463-
"display_name": "widgets-tutorial",
566+
"display_name": "Python 3 (ipykernel)",
464567
"language": "python",
465-
"name": "widgets-tutorial"
568+
"name": "python3"
466569
},
467570
"language_info": {
468571
"codemirror_mode": {
@@ -474,7 +577,14 @@
474577
"name": "python",
475578
"nbconvert_exporter": "python",
476579
"pygments_lexer": "ipython3",
477-
"version": "3.8.10"
580+
"version": "3.9.13"
581+
},
582+
"widgets": {
583+
"application/vnd.jupyter.widget-state+json": {
584+
"state": {},
585+
"version_major": 2,
586+
"version_minor": 0
587+
}
478588
}
479589
},
480590
"nbformat": 4,
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# with interact
2+
3+
fig, ax = plt.subplots()
4+
ax.grid()
5+
line = ax.plot(x, f(x, k, p))[0]
6+
7+
def plot_f(k, p):
8+
line.set_ydata(f(x, k, p))
9+
fig.canvas.draw_idle()
10+
11+
12+
interact(plot_f, k=(0.5, 2), p=(0, 2 * np.pi))
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fig, ax = plt.subplots()
2+
ax.grid()
3+
ctrls = iplt.plot(x, f, k=(.5, 2), p=(0, 2*np.pi))

notebooks/02.Interact/solutions/plot-function.py

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)