Obsah
1. Interaktivní ovládací prvky v Jupyter Notebooku
2. Princip činnosti ovládacích prvků v Jupyter Notebooku
3. Instalace knihovny ipywidgets do standardního Jupyter Notebooku
4. Instalace ipywidgets do JupyterLite s využitím knihovny micropip
5. Inicializace knihovny ipywidgets v obou variantách Jupyter Notebooku
6. Jednoduchý a velmi často používaný ovládací prvek – posuvník
7. Důsledky použití modelu MVC – větší množství „stejných“ posuvníků v diáři
8. Modifikace hodnoty posuvníku
9. Změna dalších vlastností ovládacích prvků
10. Použití funkce interact společně s posuvníkem
11. Graf, jehož parametr je možné interaktivně měnit
12. Graf, jehož tři parametry je možné interaktivně měnit
13. Interaktivní změna pravdivostní hodnoty přímo z prostředí Jupyter Notebooku
14. Tlačítko, progress bar a ovládací prvek pro vstup číselných údajů
15. Výběr z většího množství možností
18. Repositář s demonstračními příklady
19. Odkazy na články o Jupyter Notebooku
1. Interaktivní ovládací prvky v Jupyter Notebooku
„With the success of the notebook file format as a medium for communicating scientific results, more than an interactive development environment, Jupyter is turning into an interactive scientific authoring environment.“
Wolf Vollprecht
V dnešním článku, který tematicky navazuje na předchozí články o projektu Jupyter a na něj navazujících projektech, se seznámíme se způsobem vkládání interaktivních ovládacích prvků (tlačítek, posuvníků, výběrových tlačítek atd.) do diářů vytvářených a prezentovaných v Jupyter Notebooku, Jupyter Labu i v JupyterLite. Tyto prvky umožňují interaktivní modifikaci parametrů výpočtů, grafů atd. a poměrně zásadním způsobem tak rozšiřují možnosti praktického nasazení těchto technologií (dokážou tak do značné míry nahradit například NetLogo a podobné projekty). Všechny dále popsané ovládací prvky jsou poskytovány knihovnou nazvanou ipywidgets, která závisí na knihovně widgetsnbextension. Implementace ovládacích prvků je provedena jak v rámci prohlížeče (HTML+CSS+JavaScript), tak i v rámci kernelu Pythonu, protože k hodnotám těchto prvků lze přistupovat přímo ze skriptů vytvořených v diářích.
Obrázek 1: Úvodní stránka s původním uživatelským rozhraním Jupyter Notebooku či IPython Notebooku. I toto prostředí bude možné použít v souvislosti s příklady uvedenými v dnešním článku.
Obrázek 2: Základní informace o projektu JupyterLite zobrazené přímo ve webovém prostředí. Dnes uvedené příklady by měly být funkční i v tomto prostředí, ovšem za podmínky použití modulu micropip.
2. Princip činnosti ovládacích prvků v Jupyter Notebooku
Ovládací prvky, například tlačítka, výběrové boxy, posuvníky atd. jsou zobrazeny přímo v prostředí Jupyter Notebooku. A to je zobrazeno v ploše webového prohlížeče. Celé prostředí diáře je tvořeno dynamicky generovanou a měněnou HTML stránkou a několika skripty vytvořenými v JavaScriptu, které mění DOM (Document Object Model) stránky a současně komunikují s kernelem (v našem případě konkrétně s Pythonovským kernelem), který běží na serveru, tedy obecně na jiném počítači, než na kterém je zobrazeno prostředí Jupyter Notebooku. Z tohoto důvodu je ovládací prvek, který se z pohledu uživatele tváří jako jediný objekt, ve skutečnosti rozdělen na trojici objektů. Prvním objektem je vlastní vizuální ovládací prvek realizovaný kombinací HTML+CSS+JS (takzvaný view). Druhý objekt je zkonstruován na straně kernelu Pythonu a je tedy alokován na serveru (k tomuto objektu má přístup programový kód vytvořený v diáři). A mezi těmito dvěma objekty zprostředkovává komunikaci objekt třetí, opět zkonstruovaný na straně klienta (webového prohlížeče). Toto řešení má určité zajímavé důsledky, které si ukážeme později.
Obrázek 3: Architektura ovládacích prvků zobrazených v ploše Jupyter Notebooku (webový klient), ovšem dostupných i ze skriptů zapsaných do diáře (server a kernel Pythonu).
I v prostředí JupyterLite popsaném minule lze ovládací prvky v diářích používat. V tomto případě se opět pro realizaci ovládacího prvku používá trojice objektů, ovšem nyní veškerá činnost a komunikace probíhá pouze v rámci webového prohlížeče. Z pohledu uživatele diáře je ovšem situace prakticky totožná – až na ten rozdíl, že nedochází k odpojení kernelu při problémech se sítí, protože veškerý obsah je uložen v cache webového prohlížeče.
Obrázek 4: Úvodní obrazovka projektu JupyterLite při přístupu ke statickému obsahu z jiného počítače.
3. Instalace knihovny ipywidgets do standardního Jupyter Notebooku
Nejprve si popišme, jakým způsobem je možné knihovnu ipywidgets nainstalovat do standardního Jupyter Notebooku či Jupyter Labu. V případě, že neprovozujete nějakou velmi starou verzi Jupyter Notebooku, je instalace snadná a přímočará, protože knihovna ipywidgets je dostupná na PyPi. Pokud používáte nástroj pip (Python Installer), může instalace vypadat následovně:
$ pip3 install --user ipywidgets Collecting ipywidgets Downloading ipywidgets-7.6.3-py2.py3-none-any.whl (121 kB) |████████████████████████████████| 121 kB 2.8 MB/s Collecting widgetsnbextension~=3.5.0 Downloading widgetsnbextension-3.5.1-py2.py3-none-any.whl (2.2 MB) |████████████████████████████████| 2.2 MB 2.3 MB/s Collecting ipython>=4.0.0; python_version >= "3.3" Downloading ipython-7.25.0-py3-none-any.whl (786 kB) |████████████████████████████████| 786 kB 1.7 MB/s Collecting jupyterlab-widgets>=1.0.0; python_version >= "3.6" Downloading jupyterlab_widgets-1.0.0-py3-none-any.whl (243 kB) |████████████████████████████████| 243 kB 1.9 MB/s Requirement already satisfied: nbformat>=4.2.0 in ./.local/lib/python3.9/site-packages (from ipywidgets) (5.1.3) Requirement already satisfied: traitlets>=4.3.1 in ./.local/lib/python3.9/site-packages (from ipywidgets) (5.0.5) Collecting ipykernel>=4.5.1 Downloading ipykernel-6.0.3-py3-none-any.whl (122 kB) |████████████████████████████████| 122 kB 2.1 MB/s Collecting notebook>=4.4.1 Downloading notebook-6.4.0-py3-none-any.whl (9.5 MB) |████████████████████████████████| 9.5 MB 1.0 MB/s Collecting matplotlib-inline Downloading matplotlib_inline-0.1.2-py3-none-any.whl (8.2 kB) Collecting backcall Downloading backcall-0.2.0-py2.py3-none-any.whl (11 kB) Requirement already satisfied: pygments in ./.local/lib/python3.9/site-packages (from ipython>=4.0.0; python_version >= "3.3"->ipywidgets) (2.9.0) Collecting pexpect>4.3; sys_platform != "win32" Downloading pexpect-4.8.0-py2.py3-none-any.whl (59 kB) |████████████████████████████████| 59 kB 1.9 MB/s Collecting prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 Downloading prompt_toolkit-3.0.19-py3-none-any.whl (368 kB) |████████████████████████████████| 368 kB 1.7 MB/s Requirement already satisfied: setuptools>=18.5 in /usr/lib/python3.9/site-packages (from ipython>=4.0.0; python_version >= "3.3"->ipywidgets) (49.1.3) Collecting pickleshare Downloading pickleshare-0.7.5-py2.py3-none-any.whl (6.9 kB) ... ... ... Successfully installed backcall-0.2.0 debugpy-1.4.0 ipykernel-6.0.3 ipython-7.25.0 ipywidgets-7.6.3 jedi-0.18.0 jupyterlab-widgets-1.0.0 matplotlib-inline-0.1.2 notebook-6.4.0 parso-0.8.2 pexpect-4.8.0 pickleshare-0.7.5 prompt-toolkit-3.0.19 wcwidth-0.2.5 widgetsnbextension-3.5.1
Nyní je již možné spustit Jupyter Notebook, a to zcela standardním způsobem:
$ jupyter notebook [I 08:52:28.641 NotebookApp] Serving notebooks from local directory: /tmp/ramdisk [I 08:52:28.641 NotebookApp] 0 active kernels [I 08:52:28.641 NotebookApp] The Jupyter Notebook is running at: [I 08:52:28.641 NotebookApp] http://localhost:8888/ [I 08:52:28.641 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
Do nového diáře by mělo být v tomto okamžiku možné zapsat příkaz pro import knihovny (balíčku) ipywidgets (a příkaz by měl proběhnout bez chyby):
import ipywidgets
Zobrazit si můžeme nápovědu k celému balíčku:
help(ipywidgets) Help on package ipywidgets: NAME ipywidgets - Interactive widgets for the Jupyter notebook. DESCRIPTION Provide simple interactive controls in the notebook. Each Widget corresponds to an object in Python and Javascript, with controls on the page. To put a Widget on the page, you can display it with IPython's display machinery:: from ipywidgets import IntSlider from IPython.display import display slider = IntSlider(min=1, max=10) display(slider) Moving the slider will change the value. Most Widgets have a current value, accessible as a `value` attribute.
Zobrazit si můžeme i objekty dostupné v knihovně ipywidgets:
from pprint import * pprint(ipywidgets.__dir__()) ['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__path__', '__file__', '__cached__', '__builtins__', 'os', 'get_ipython', '_version', 'version_info', '__version__', '__protocol_version__', '__jupyter_widgets_controls_version__', '__jupyter_widgets_base_version__', 'widgets', 'widget', 'Widget', 'CallbackDispatcher', 'register', 'widget_serialization', 'util', 'trait_types', 'widget_layout', 'widget_style', 'domwidget', 'DOMWidget', 'valuewidget', 'ValueWidget', 'Color', 'Datetime', 'NumberFormat', 'widget_core', 'CoreWidget', 'widget_description', 'widget_bool', 'Checkbox', 'ToggleButton', 'Valid', 'widget_button', 'Button', 'ButtonStyle', 'docutils', 'widget_box', 'Box', 'HBox', 'VBox', 'GridBox', 'widget_int', 'widget_float', 'FloatText', 'BoundedFloatText', 'FloatSlider', 'FloatProgress', 'FloatRangeSlider', 'FloatLogSlider', 'IntText', 'BoundedIntText', 'IntSlider', 'IntProgress', 'IntRangeSlider', 'Play', 'SliderStyle', 'widget_color', 'ColorPicker', 'widget_date', 'DatePicker', 'widget_output', 'Output', 'widget_selection', 'RadioButtons', 'ToggleButtons', 'ToggleButtonsStyle', 'Dropdown', 'Select', 'SelectionSlider', 'SelectMultiple', 'SelectionRangeSlider', 'widget_selectioncontainer', 'Tab', 'Accordion', 'widget_string', 'HTML', 'HTMLMath', 'Label', 'Text', 'Textarea', 'Password', 'Combobox', 'widget_controller', 'Controller', 'interaction', 'interact', 'interactive', 'fixed', 'interact_manual', 'interactive_output', 'widget_link', 'jslink', 'jsdlink', 'Layout', 'widget_media', 'Image', 'Video', 'Audio', 'Style', 'widget_templates', 'TwoByTwoLayout', 'AppLayout', 'GridspecLayout', 'widget_upload', 'FileUpload', 'link', 'dlink', 'load_ipython_extension', 'register_comm_target', 'handle_kernel', '_handle_ipython']
4. Instalace ipywidgets do JupyterLite s využitím knihovny micropip
V případě, že si chcete ovládací prvky vyzkoušet v nástroji JupyterLite, s nímž jsme se seznámili minule, bude instalace probíhat odlišným způsobem. Je to ostatně logické, protože si musíme uvědomit, že jak instalace modulů, tak i jejich překlad probíhá v rámci webového prohlížeče, tedy v relativně izolovaném prostředí (což je ostatně jen dobře). Z tohoto důvodu byl do projektu Pyodide přidán i balíček nazvaný micropip, který zajišťuje právě instalaci, překlad atd. modulů v rámci prohlížeče. Ostatně i k této knihovně existuje nápověda, kterou si můžeme přímo v prostředí diáře zobrazit:
import micropip help(micropip)
S výsledkem:
Help on module micropip: NAME micropip FUNCTIONS install(requirements: Union[str, List[str]]) Install the given package and all of its dependencies. See :ref:`loading packages <loading_packages>` for more information. This only works for packages that are either pure Python or for packages with C extensions that are built in Pyodide. If a pure Python package is not found in the Pyodide repository it will be loaded from PyPi. Parameters ---------- requirements : ``str | List[str]`` A requirement or list of requirements to install. Each requirement is a string, which should be either a package name or URL to a wheel: - If the requirement ends in ``.whl`` it will be interpreted as a URL. The file must be a wheel named in compliance with the `PEP 427 naming convention <https://www.python.org/dev/peps/pep-0427/#file-format>`_. - If the requirement does not end in ``.whl``, it will interpreted as the name of a package. A package by this name must either be present in the Pyodide repository at `indexURL <globalThis.loadPyodide>` or on PyPi Returns ------- ``Future`` A ``Future`` that resolves to ``None`` when all packages have been downloaded and installed. DATA __all__ = ['install'] FILE /lib/python3.8/site-packages/micropip.py
Ve výše zobrazené nápovědě je popsána funkce install, která ovšem vrací hodnotu typu future, protože instalace probíhá na pozadí. V případě, že budete chtít počkat na dokončení instalace, použijeme konstrukci await (popsanou například zde):
import micropip await micropip.install("ipywidgets")
5. Inicializace knihovny ipywidgets v obou variantách Jupyter Notebooku
Shrňme si nyní informace o tom, jak probíhá import a inicializace knihovny ipywidgets. V klasickém Jupyter Notebooku či Jupyter Labu je to snadné:
import ipywidgets
V JupyterLite je nutné použít trojici příkazů:
import micropip await micropip.install("ipywidgets") import ipywidgets
Obrázek 5: Inicializace knihovny ipywidgets v diáři spuštěném v rámci JupyterLite.
{ "metadata": { "language_info": { "codemirror_mode": { "name": "python", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8" }, "kernelspec": { "name": "python", "display_name": "Pyolite", "language": "python" } }, "nbformat_minor": 4, "nbformat": 4, "cells": [ { "cell_type": "code", "source": "# Inicializace knihovny `ipywidgets` v Jupyter Notebooku Lite", "metadata": { "trusted": true }, "execution_count": 4, "outputs": [] }, { "cell_type": "code", "source": "import micropip", "metadata": { "trusted": true }, "execution_count": 5, "outputs": [] }, { "cell_type": "code", "source": "await micropip.install('ipywidgets')", "metadata": { "trusted": true }, "execution_count": 6, "outputs": [] }, { "cell_type": "code", "source": "import ipywidgets", "metadata": { "trusted": true }, "execution_count": 8, "outputs": [] }, { "cell_type": "code", "source": "pprint.pprint(ipywidgets.__dir__())", "metadata": { "trusted": true }, "execution_count": 9, "outputs": [ { "name": "stdout", "text": "['__name__',\n '__doc__',\n '__package__',\n '__loader__',\n '__spec__',\n '__path__',\n '__file__',\n '__cached__',\n '__builtins__',\n 'os',\n 'get_ipython',\n '_version',\n 'version_info',\n '__version__',\n '__protocol_version__',\n '__jupyter_widgets_controls_version__',\n '__jupyter_widgets_base_version__',\n 'widgets',\n 'widget',\n 'Widget',\n 'CallbackDispatcher',\n 'register',\n 'widget_serialization',\n 'util',\n 'trait_types',\n 'widget_layout',\n 'widget_style',\n 'domwidget',\n 'DOMWidget',\n 'valuewidget',\n 'ValueWidget',\n 'Color',\n 'Datetime',\n 'NumberFormat',\n 'widget_core',\n 'CoreWidget',\n 'widget_description',\n 'widget_bool',\n 'Checkbox',\n 'ToggleButton',\n 'Valid',\n 'widget_button',\n 'Button',\n 'ButtonStyle',\n 'docutils',\n 'widget_box',\n 'Box',\n 'HBox',\n 'VBox',\n 'GridBox',\n 'widget_int',\n 'widget_float',\n 'FloatText',\n 'BoundedFloatText',\n 'FloatSlider',\n 'FloatProgress',\n 'FloatRangeSlider',\n 'FloatLogSlider',\n 'IntText',\n 'BoundedIntText',\n 'IntSlider',\n 'IntProgress',\n 'IntRangeSlider',\n 'Play',\n 'SliderStyle',\n 'widget_color',\n 'ColorPicker',\n 'widget_date',\n 'DatePicker',\n 'widget_output',\n 'Output',\n 'widget_selection',\n 'RadioButtons',\n 'ToggleButtons',\n 'ToggleButtonsStyle',\n 'Dropdown',\n 'Select',\n 'SelectionSlider',\n 'SelectMultiple',\n 'SelectionRangeSlider',\n 'widget_selectioncontainer',\n 'Tab',\n 'Accordion',\n 'widget_string',\n 'HTML',\n 'HTMLMath',\n 'Label',\n 'Text',\n 'Textarea',\n 'Password',\n 'Combobox',\n 'widget_controller',\n 'Controller',\n 'interaction',\n 'interact',\n 'interactive',\n 'fixed',\n 'interact_manual',\n 'interactive_output',\n 'widget_link',\n 'jslink',\n 'jsdlink',\n 'Layout',\n 'widget_media',\n 'Image',\n 'Video',\n 'Audio',\n 'Style',\n 'widget_templates',\n 'TwoByTwoLayout',\n 'AppLayout',\n 'GridspecLayout',\n 'widget_upload',\n 'FileUpload',\n 'link',\n 'dlink',\n 'load_ipython_extension',\n 'register_comm_target',\n 'handle_kernel',\n '_handle_ipython']\n", "output_type": "stream" } ] }, { "cell_type": "code", "source": "", "metadata": {}, "execution_count": null, "outputs": [] } ] }
6. Jednoduchý a velmi často používaný ovládací prvek – posuvník
Jedním z velmi často používaných ovládacích prvků v diářích je posuvník neboli slider. Tento prvek umožňuje interaktivně, typicky s využitím myši, měnit hodnotu numerické proměnné, a to buď proměnné celočíselné nebo proměnné s uloženou hodnotou reprezentovanou v systému plovoucí řádové tečky/čárky (floating point). Tento prvek se vytvoří konstruktorem IntSlider(), popř. FloatSlider():
ipywidgets.IntSlider()
V diáři se všechny výrazy ihned vyhodnocují a pokud je výsledkem výrazu hodnota typu „ovládací prvek“, je tento ihned zobrazen a lze ho interaktivně používat (ovšem s tím, že jeho hodnotu nelze jednoduše zjistit – ovládací prvek jsme neuložili do proměnné):
Obrázek 6: Zobrazení ovládacího prvku v diáři.
V případě, že je nutné hodnotu posuvníku přečíst a dále zpracovat, postupuje se nepatrně odlišně – reference na objekt se uloží do proměnné a ta se posléze používá a přistupuje se k atributům objektu.
Vytvoření posuvníku:
slider = ipywidgets.IntSlider()
Zobrazení posuvníku:
slider
Přečtení hodnoty posuvníku:
slider.value 42
Obrázek 7: Přečtení hodnoty posuvníku.
7. Důsledky použití modelu MVC – větší množství „stejných“ posuvníků v diáři
Na dalším diáři nejprve vytvoříme nový posuvník a necháme si ho zobrazit:
slider = ipywidgets.IntSlider() slider
Dále použijeme funkci display pro zobrazení objektu, jehož reference je uložena v proměnné slider:
display(slider) display(slider)
Nyní bude posuvník na ploše diáře zobrazen třikrát a – což je důležité – změna jednoho posuvníku se projeví i na dalších dvou posuvnících:
Obrázek 8: Posuvník reprezentovaný stejným modelem je nyní zobrazen třikrát.
To, že je možné stejný prvek zobrazit vícekrát, ovšem jeho hodnoty a další vlastnosti budou navzájem svázány, je důsledkem použití modelu MVC, o němž jsme se zmínili ve druhé kapitole. Nyní totiž namísto takto svázaných objektů:
Obrázek 9: MVC použitý v Jupyter Notebooku.
Nyní ovšem máme více pohledů na stejný objekt a celý systém se nepatrně změnil:
Obrázek 10: Větší množství pohledů na stejný objekt, resp. stejný model.
8. Modifikace hodnoty posuvníku
V případě, že programově změníme hodnotu posuvníku, resp. přesněji řečeno hodnotu uloženou do atributu value, bude tato změna (provedená v modelu) ihned zrcadlena i v uživatelském rozhraní diáře – posuvník se tedy vizuálně změní:
Obrázek 11: Změna hodnoty posuvníku.
9. Změna dalších vlastností ovládacích prvků
Měnit lze ovšem mnohem větší množství atributů. Všechny atributy, a to včetně atributů skrytých, lze vypsat následovně:
slider.keys ['_dom_classes', '_model_module', '_model_module_version', '_model_name', '_view_count', '_view_module', '_view_module_version', '_view_name', 'continuous_update', 'description', 'description_tooltip', 'disabled', 'layout', 'max', 'min', 'orientation', 'readout', 'readout_format', 'step', 'style', 'value']
Můžeme například přečíst hodnotu atributu orientation, který uvádí, zda je prvek orientován vodorovně nebo svisle:
slider.orientation 'horizontal'
Tuto hodnotu lze modifikovat, což se ihned projeví i vizuálně:
slider.orientation='vertical'
Obrázek 12: Změna vlastností ovládacího prvku se ihned projeví i vizuálně.
Změnit lze i popisek posuvníku:
slider.description="a slider"
Obrázek 13: Modifikace popisku posuvníku.
Většinu parametrů ovšem můžeme specifikovat již při konstrukci ovládacího prvku:
ipywidgets.IntSlider( value=7, min=-50, max=50, step=2, description='Second widget:', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='d' )
Totéž pochopitelně platí i pro druhý již zmíněný ovládací prvek – FloatSlider, který můžeme zkonstruovat následujícím způsobem:
float_slider = ipywidgets.FloatSlider(min=10.0, max=50.0, value=25.0, step=2.5, description="Float Slider")
A následně ho zobrazit na ploše diáře:
float_slider
10. Použití funkce interact společně s posuvníkem
Při změně hodnoty ovládacího prvku je možné, aby diář automaticky zavolal zvolenou callback funkci. Tuto variantu si ukážeme na dalším jednoduchém demonstračním příkladu, v němž je definována tato funkce akceptující parametr nazvaný x:
def callbackFunction(x): return 2*x
Callback funkci propojíme s automaticky vytvořeným posuvníkem následujícím příkazem:
ipywidgets.interact(callbackFunction, x=10)
Jupyter Notebook na základě výchozí hodnoty parametru x zjistí, že se má použít číselný posuvník, ovšem bylo by možné využít například i zatrhávací box atd.
Obrázek 14: Zavolání callback funkce s každou novou hodnotou vybranou uživatelem.
11. Graf, jehož parametr je možné interaktivně měnit
Možnosti poskytované knihovnou ipywidgets můžeme velmi snadno zkombinovat s možnostmi knihovny Matplotlib a vložit tak do diáře grafy, jejichž parametry se mohou měnit ovládacími prvky. Může se jednat o číselné parametry, pravdivostní hodnoty atd. Opět se podívejme na relativně jednoduchý demonstrační příklad, v němž je vykreslena sinusovka, jejíž fázi je možné interaktivně měnit:
import matplotlib.pyplot as plt import numpy as np def plot(phase): x = np.arange(0, 6.28, 0.1) y = np.sin(x+phase) plt.plot(x,y) plt.show()
Propojení funkce plot s ovládacím prvkem:
ipywidgets.interactive(plot, phase=(0, 10, 0.1))
Výsledky:
Obrázek 15: Výchozí tvar grafu se sinusovkou.
Obrázek 16: Změna fáze sinusovky.
12. Graf, jehož tři parametry je možné interaktivně měnit
Samozřejmě nám nic nebrání v tom, abychom v diáři vytvořili graf s více modifikovatelnými parametry. Opět se podívejme na příklad založený na vykreslení sinusovky, popř. dvou sinusovek, tentokrát s dvojicí proměnných parametrů:
def plot(amplitude, phase, phase2): x = np.arange(0, 6.28, 0.1) y1 = np.sin(amplitude*x+phase) plt.plot(x,y1) y2 = np.sin(amplitude*x+phase2) plt.plot(x,y2) plt.show()
Funkci pro vykreslení grafu opět propojíme s automaticky vytvořenými ovládacími prvky:
w = ipywidgets.interactive(plot, amplitude=(0.5, 2.0, 0.1), phase=(0, 10, 0.1), phase2=(0, 10, 0.1))
A vše, tedy jak graf, tak i ovládací prvky, zobrazíme:
display(w)
Obrázek 17: Výchozí tvar grafu se sinusovkou.
Obrázek 18: Změna amplitudy a fáze sinusovky.
13. Interaktivní změna pravdivostní hodnoty přímo z prostředí Jupyter Notebooku
V případě, že je nějaký parametr funkce předané do interactive nastaven na pravdivostní hodnotu, zobrazí se namísto posuvníku zatrhávací box (checkbox), kterým se volí pravdivostní hodnota. Použití může vypadat následovně – dovolíme uživateli, aby si sám zvolil, zda se má zobrazit druhý průběh sinusovky či nikoli:
def plot(amplitude, phase, phase2, showSecondFunction): x = np.arange(0, 6.28, 0.1) y1 = np.sin(amplitude*x+phase) plt.plot(x,y1) if showSecondFunction: y2 = np.sin(amplitude*x+phase2) plt.plot(x,y2) plt.show()
Graf i k němu příslušné ovládací prvky zobrazíme na ploše diáře:
w = ipywidgets.interactive(plot, amplitude=(0.5, 2.0, 0.1), phase=(0, 10, 0.1), phase2=(0, 10, 0.1), showSecondFunction=True) display(w)
S tímto výsledkem:
Obrázek 19: Změna amplitudy a fáze sinusovky, volba vykreslení druhé sinusovky.
Další použití ovládacích prvků, které zobrazují či umožňují změnit pravdivostní hodnotu:
Obrázek 20: Ovládací prvky pro nastavení či zobrazení pravdivostní hodnoty.
14. Tlačítko, progress bar a ovládací prvek pro vstup číselných údajů
Do diáře je možné vložit i tlačítko, které dokáže po stisku/výběru zavolat zvolenou callback funkci. Opět si ukažme jednoduchý příklad:
button = ipywidgets.Button(description="Click Me!") output = ipywidgets.Output() display(button, output) @output.capture() def on_button_clicked(b): print(type(b)) print("Button clicked.") b.icon="warning" button.on_click(on_button_clicked)
Obrázek 21: Po stisku tlačítka se změní nápis a současně i ikona na tlačítku.
Zejména při delších výpočtech je vhodné zobrazit „teploměr“ (který se typicky zastaví na hodnotě 99 a tam zůstane dalších 10 minut :-). Jedná se o ovládací prvek, který se mění jen programově:
Obrázek 22: Progress bar neboli „teploměr“.
Pro vstup číselných údajů z klávesnice či kolečkem myši slouží další jednoduchý ovládací prvek:
Obrázek 23: Ovládací prvek pro vstup číselných údajů.
15. Výběr z většího množství možností
Poměrně často se setkáme s nutností vytvořit panel či dialog umožňující výběr položky z většího množství možností, ať již známých dopředu nebo dopočítaných skriptem. Pro tento účel lze použít dva ovládací prvky RadioButtons a Select. Nejprve si ukažme způsob použití panelu s přepínacími tlačítky, tedy klasické RadioButtons:
ipywidgets.RadioButtons( options=['pepperoni', 'pineapple', 'anchovies'], description='Pizza topping:', disabled=False )
Obrázek 24: Panel s přepínači pro výběr jednoho prvku z nabídky.
Poněkud méně přehledný je ovládací prvek Select, jehož výhodou je, že na relativně malém místě umožňuje (díky skrolování) zobrazit i velký počet položek:
ipywidgets.Select( options=['Linux', 'Windows', 'OSX'], value='Linux', description='OS:', disabled=False )
Obrázek 25: Panel s nabídkou několika prvků, z nichž lze vybrat jeden prvek.
16. Výběr data
V některých typech „aplikací“ vytvořených v diáři je nutné vybrat datum, popř. nějaký rozsah dat. K tomuto účelu slouží ovládací prvek vytvářený konstruktorem DatePicker:
ipywidgets.DatePicker( description='Pick a Date', disabled=False )
V neaktivním stavu zobrazuje tento prvek vybrané datum, ovšem po jeho výběru se zobrazí kalendář s možností přepínání měsíců, let atd.
Obrázek 26: Ovládací prvek s jednoduchým kalendářem.
17. Výběr barvy
Posledním ovládacím prvkem, s nímž se dnes seznámíme, je prvek určený pro výběr barvy. Tento prvek se vytvoří a zobrazí konstruktorem ColorPicker. Volání tohoto konstruktoru může vypadat následovně:
ipywidgets.ColorPicker( description='Pick a color', disabled=False )
Ovládací prvek pro výběr barvy v neaktivním stavu vypadá následovně:
Obrázek 27: Ovládací prvek s výběrem barvy.
Jaký dialog pro výběr barvy se skutečně zobrazí, je do značné míry závislé na použitém operačním systému, jeho správci oken, GUI knihovnách atd. V mém případě tento dialog vypadá následovně:
Obrázek 28: Dialog pro výběr barvy.
Vybranou barvu lze přečíst z atributu tohoto prvku obvyklým způsobem.
18. Repositář s demonstračními příklady
Všechny demonstrační příklady (resp. přesněji řečeno diáře), s nimiž jsme se seznámili v předchozích kapitolách, byly uloženy do Git repositáře umístěného na GitHubu (https://github.com/tisnik/jupyter-notebook-examples/). Poslední verze souborů s diáři naleznete pod odkazy uvedenými v tabulce pod tímto odstavcem. Diář by se měl otevřít přímo v rámci stránky GitHubu:
Do tohoto repositáře jsou uloženy i diagramy použité v dnešním článku. Ty byly nakresleny přímo v rámci JupyterLite:
# | Diagram | Popis | Zdrojový kód |
---|---|---|---|
1 | mvc1.dio | architektura MVC použitá pro zobrazení ovládacích prvků v diářích | https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywidgets/mvc1.dio |
2 | mvc2.dio | dva vizuální ovládací prvky navázané na jeden model | https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywidgets/mvc2.dio |
19. Odkazy na články o Jupyter Notebooku
Se samotným nástrojem Jupyter Notebook jsme se již na stránkách Rootu setkali několikrát, a to konkrétně v následujících článcích (přidán je i prozatím poslední článek o projektu JupyterLite):
- Jupyter Notebook – nástroj pro programátory, výzkumníky i lektory
https://www.root.cz/clanky/jupyter-notebook-nastroj-pro-programatory-vyzkumniky-i-lektory/ - Tvorba grafů v Jupyter Notebooku s využitím knihovny Matplotlib
https://www.root.cz/clanky/tvorba-grafu-v-jupyter-notebooku-s-vyuzitim-knihovny-matplotlib/ - Tvorba grafů v Jupyter Notebooku s využitím knihovny Matplotlib (dokončení)
https://www.root.cz/clanky/tvorba-grafu-v-jupyter-notebooku-s-vyuzitim-knihovny-matplotlib-dokonceni/ - Jupyter Notebook – operace s rastrovými obrázky a UML diagramy, literate programming
https://www.root.cz/clanky/jupyter-notebook-operace-s-rastrovymi-obrazky-a-uml-diagramy-literate-programming/ - Interpret programovacího jazyka Clojure integrovaný do Jupyter Notebooku
https://www.root.cz/clanky/interpret-programovaciho-jazyka-clojure-integrovany-do-jupyter-notebooku/ - Calysto Hy: integrace programovacího jazyka Hy s Jupyter Notebookem
https://www.root.cz/clanky/calysto-hy-integrace-programovaciho-jazyka-hy-s-jupyter-notebookem/ - JupyterLite: nová alternativní architektura Jupyter Notebooku
https://www.root.cz/clanky/jupyterlite-nova-alternativni-architektura-jupyter-notebooku/
20. Odkazy na Internetu
- ipywidgets (dokumentace)
https://ipywidgets.readthedocs.io/en/latest/ - Interactive Widgets
https://github.com/jupyter-widgets/ipywidgets/blob/master/docs/source/examples/Index.ipynb - Notebook interface
https://en.wikipedia.org/wiki/Notebook_interface - Jypyter: open source, interactive data science and scientific computing across over 40 programming languages
https://jupyter.org/ - Matplotlib Home Page
http://matplotlib.org/ - Matplotlib (Wikipedia)
https://en.wikipedia.org/wiki/Matplotlib - Popis barvových map modulu matplotlib.cm
https://gist.github.com/endolith/2719900#id7 - Ukázky (palety) barvových map modulu matplotlib.cm
http://matplotlib.org/examples/color/colormaps_reference.html - Galerie grafů vytvořených v Matplotlibu
https://matplotlib.org/3.2.1/gallery/ - showcase example code: xkcd.py
https://matplotlib.org/xkcd/examples/showcase/xkcd.html - Customising contour plots in matplotlib
https://philbull.wordpress.com/2012/12/27/customising-contour-plots-in-matplotlib/ - Graphics with Matplotlib
http://kestrel.nmt.edu/~raymond/software/python_notes/paper004.html - The IPython Notebook
http://ipython.org/notebook.html - nbviewer: a simple way to share Jupyter Notebooks
https://nbviewer.jupyter.org/ - Back to the Future: Lisp as a Base for a Statistical Computing System
https://www.stat.auckland.ac.nz/~ihaka/downloads/Compstat-2008.pdf - gg4clj: a simple wrapper for using R's ggplot2 in Clojure and Gorilla REPL
https://github.com/JonyEpsilon/gg4clj - Analemma: a Clojure-based SVG DSL and charting library
http://liebke.github.io/analemma/ - Clojupyter: a Jupyter kernel for Clojure
https://github.com/roryk/clojupyter - Incanter is a Clojure-based, R-like platform for statistical computing and graphics.
http://incanter.org/ - Evolution of incanter (Gource Visualization)
https://www.youtube.com/watch?v=TVfL5nPELr4 - Questions tagged [incanter] (na Stack Overflow)
https://stackoverflow.com/questions/tagged/incanter?sort=active - Data Sorcery with Clojure
https://data-sorcery.org/contents/ - What is REPL?
https://pythonprogramminglanguage.com/repl/ - What is a REPL?
https://codewith.mu/en/tutorials/1.0/repl - Programming at the REPL: Introduction
https://clojure.org/guides/repl/introduction - What is REPL? (Quora)
https://www.quora.com/What-is-REPL - Gorilla REPL: interaktivní prostředí pro programovací jazyk Clojure
https://www.root.cz/clanky/gorilla-repl-interaktivni-prostredi-pro-programovaci-jazyk-clojure/ - R Markdown: The Definitive Guide
https://bookdown.org/yihui/rmarkdown/ - Single-page application
https://en.wikipedia.org/wiki/Single-page_application - Video streaming in the Jupyter Notebook
https://towardsdatascience.com/video-streaming-in-the-jupyter-notebook-635bc5809e85 - How IPython and Jupyter Notebook work
https://jupyter.readthedocs.io/en/latest/architecture/how_jupyter_ipython_work.html - Jupyter kernels
https://github.com/jupyter/jupyter/wiki/Jupyter-kernels - Keras: The Python Deep Learning library
https://keras.io/ - TensorFlow
https://www.tensorflow.org/ - PyTorch
https://pytorch.org/ - Seriál Torch: framework pro strojové učení
https://www.root.cz/serialy/torch-framework-pro-strojove-uceni/ - Scikit-learn
https://scikit-learn.org/stable/ - Java Interop (Clojure)
https://clojure.org/reference/java_interop - Obrazy s balíčky Jupyter Notebooku pro Docker
https://hub.docker.com/u/jupyter/#! - Správce balíčků Conda (dokumentace)
https://docs.conda.io/en/latest/ - Lorenzův atraktor
https://www.root.cz/clanky/fraktaly-v-pocitacove-grafice-vi/#k02 - Lorenzův atraktor
https://www.root.cz/clanky/fraktaly-v-pocitacove-grafice-iii/#k03 - Graphics with Matplotlib
http://kestrel.nmt.edu/~raymond/software/python_notes/paper004.html - Embedding Matplotlib Animations in Jupyter Notebooks
http://louistiao.me/posts/notebooks/embedding-matplotlib-animations-in-jupyter-notebooks/ - Literate programing, Kolokviální práce Pavla Starého
https://www.fi.muni.cz/usr/jkucera/pv109/starylp.htm - PlantUML (home page)
http://plantuml.sourceforge.net/ - PlantUML (download page)
http://sourceforge.net/projects/plantuml/files/plantuml.jar/download - PlantUML (Language Reference Guide)
http://plantuml.sourceforge.net/PlantUML_Language_Reference_Guide.pdf - Plain-text diagrams take shape in Asciidoctor!
http://asciidoctor.org/news/2014/02/18/plain-text-diagrams-in-asciidoctor/ - Graphviz – Graph Visualization Software
http://www.graphviz.org/ - graphviz (Manual Page)
http://www.root.cz/man/7/graphviz/ - PIL: The friendly PIL fork (home page)
https://python-pillow.org/ - Python Imaging Library (PIL), (home page)
http://www.pythonware.com/products/pil/ - PIL 1.1.6 na PyPi
https://pypi.org/project/PIL/ - Pillow 5.2.0 na PyPi
https://pypi.org/project/Pillow/ - Python Imaging Library na Wikipedii
https://en.wikipedia.org/wiki/Python_Imaging_Library - Pillow na GitHubu
https://github.com/python-pillow/Pillow - Pillow – dokumentace na readthedocs.io
http://pillow.readthedocs.io/en/5.2.x/ - How to use Pillow, a fork of PIL
https://www.pythonforbeginners.com/gui/how-to-use-pillow - await in Python
https://docs.python.org/3/reference/expressions.html#await