Hlavní navigace

Interaktivní ovládací prvky v Jupyter Notebooku

27. 7. 2021
Doba čtení: 26 minut

Sdílet

 Autor: Depositphotos
Ukážeme si vkládání interaktivních ovládacích prvků (tlačítek, posuvníků 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.

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í

16. Výběr data

17. Výběr barvy

18. Repositář s demonstračními příklady

19. Odkazy na články o Jupyter Notebooku

20. Odkazy na Internetu

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.

Poznámka: všechny dále uvedené demonstrační příklady by měly být funkční jak v klasickém Jupyter Notebooku, tak i v jeho novější variantě nazvané Jupyter Lab. Kromě toho je bude možné po nepatrné změně použít i v rámci projektu JupyterLite, se kterým jsme se seznámili v článku JupyterLite: nová alternativní architektura Jupyter Notebooku. Tato změna spočívá v nutnosti instalace knihoven s využitím balíčku micropip, přičemž vlastní instalace je prováděna přímo v diáři.

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
Poznámka: důležité je, aby se nainstaloval i závislý balíček widgetsnbextension, který jednotlivé ovládací prvky, s nimiž se setkáme v navazujících kapitolách, zpřístupňuje.

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.

Poznámka: takto vypadá diář určený pro import knihovny ipywidgets do prostředí projektu 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
)
Poznámka: tento příklad je převzat přímo z dokumentace ke knihovně ipywidgets.

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
)
Poznámka: i tento příklad je převzat z původní dokumentace, pouze byla změněna výchozí (vybraná) položka.

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:

CS24_early

# Příklad Popis Zdrojový kód
1 ipywidgets01.ipynb inicializace knihovny ipywidgets v JupyterLite https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywid­gets/ipywidgets01.ipynb
2 ipywidgets02.ipynb vytvoření interaktivně ovládaného posuvníku na ploše Jupyter Notebooku https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywid­gets/ipywidgets02.ipynb
3 ipywidgets03.ipynb přečtení hodnoty posuvníku, nastavení hodnoty, změna orientace https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywid­gets/ipywidgets03.ipynb
4 ipywidgets04.ipynb jeden objekt typu posuvník zobrazený několikrát na ploše Jupyter Notebooku https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywid­gets/ipywidgets04.ipynb
5 ipywidgets05.ipynb nastavení vlastností posuvníku při jeho konstrukci v Jupyter Notebooku https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywid­gets/ipywidgets05.ipynb
6 ipywidgets06.ipynb použití funkce interact společně s posuvníkem https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywid­gets/ipywidgets06.ipynb
7 ipywidgets07.ipynb graf, jehož parametr je možné interaktivně měnit https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywid­gets/ipywidgets07.ipynb
8 ipywidgets08.ipynb graf, jehož tři parametry je možné interaktivně měnit https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywid­gets/ipywidgets08.ipynb
9 ipywidgets09.ipynb interaktivní změna pravdivostní hodnoty přímo z prostředí Jupyter Notebooku https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywid­gets/ipywidgets09.ipynb
10 ipywidgets10.ipynb tlačítko na ploše Jupyter Notebooku https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywid­gets/ipywidgets10.ipynb
11 ipywidgets11.ipynb progress bar („teploměr“) https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywid­gets/ipywidgets11.ipynb
12 ipywidgets12.ipynb ovládací prvek pro vstup číselných údajů https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywid­gets/ipywidgets12.ipynb
13 ipywidgets13.ipynb ovládací prvky s pravdivostními hodnotami https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywid­gets/ipywidgets13.ipynb
14 ipywidgets14.ipynb ovládací prvky pro výběr z většího množství možností https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywid­gets/ipywidgets14.ipynb
15 ipywidgets15.ipynb ovládací prvky pro výběr data a barvy https://github.com/tisnik/jupyter-notebook-examples/blob/master/ipywid­gets/ipywidgets15.ipynb

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/ipywid­gets/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/ipywid­gets/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):

  1. 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/
  2. 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/
  3. 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/
  4. 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/
  5. Interpret programovacího jazyka Clojure integrovaný do Jupyter Notebooku
    https://www.root.cz/clanky/interpret-programovaciho-jazyka-clojure-integrovany-do-jupyter-notebooku/
  6. Calysto Hy: integrace programovacího jazyka Hy s Jupyter Notebookem
    https://www.root.cz/clanky/calysto-hy-integrace-programovaciho-jazyka-hy-s-jupyter-notebookem/
  7. JupyterLite: nová alternativní architektura Jupyter Notebooku
    https://www.root.cz/clanky/jupyterlite-nova-alternativni-architektura-jupyter-notebooku/

20. Odkazy na Internetu

  1. ipywidgets (dokumentace)
    https://ipywidgets.readthe­docs.io/en/latest/
  2. Interactive Widgets
    https://github.com/jupyter-widgets/ipywidgets/blob/mas­ter/docs/source/examples/In­dex.ipynb
  3. Notebook interface
    https://en.wikipedia.org/wi­ki/Notebook_interface
  4. Jypyter: open source, interactive data science and scientific computing across over 40 programming languages
    https://jupyter.org/
  5. Matplotlib Home Page
    http://matplotlib.org/
  6. Matplotlib (Wikipedia)
    https://en.wikipedia.org/wi­ki/Matplotlib
  7. Popis barvových map modulu matplotlib.cm
    https://gist.github.com/en­dolith/2719900#id7
  8. Ukázky (palety) barvových map modulu matplotlib.cm
    http://matplotlib.org/exam­ples/color/colormaps_refe­rence.html
  9. Galerie grafů vytvořených v Matplotlibu
    https://matplotlib.org/3.2.1/gallery/
  10. showcase example code: xkcd.py
    https://matplotlib.org/xkcd/e­xamples/showcase/xkcd.html
  11. Customising contour plots in matplotlib
    https://philbull.wordpres­s.com/2012/12/27/customising-contour-plots-in-matplotlib/
  12. Graphics with Matplotlib
    http://kestrel.nmt.edu/~ra­ymond/software/python_notes/pa­per004.html
  13. The IPython Notebook
    http://ipython.org/notebook.html
  14. nbviewer: a simple way to share Jupyter Notebooks
    https://nbviewer.jupyter.org/
  15. Back to the Future: Lisp as a Base for a Statistical Computing System
    https://www.stat.auckland­.ac.nz/~ihaka/downloads/Com­pstat-2008.pdf
  16. gg4clj: a simple wrapper for using R's ggplot2 in Clojure and Gorilla REPL
    https://github.com/JonyEpsilon/gg4clj
  17. Analemma: a Clojure-based SVG DSL and charting library
    http://liebke.github.io/analemma/
  18. Clojupyter: a Jupyter kernel for Clojure
    https://github.com/roryk/clojupyter
  19. Incanter is a Clojure-based, R-like platform for statistical computing and graphics.
    http://incanter.org/
  20. Evolution of incanter (Gource Visualization)
    https://www.youtube.com/wat­ch?v=TVfL5nPELr4
  21. Questions tagged [incanter] (na Stack Overflow)
    https://stackoverflow.com/qu­estions/tagged/incanter?sor­t=active
  22. Data Sorcery with Clojure
    https://data-sorcery.org/contents/
  23. What is REPL?
    https://pythonprogramminglan­guage.com/repl/
  24. What is a REPL?
    https://codewith.mu/en/tu­torials/1.0/repl
  25. Programming at the REPL: Introduction
    https://clojure.org/guides/re­pl/introduction
  26. What is REPL? (Quora)
    https://www.quora.com/What-is-REPL
  27. Gorilla REPL: interaktivní prostředí pro programovací jazyk Clojure
    https://www.root.cz/clanky/gorilla-repl-interaktivni-prostredi-pro-programovaci-jazyk-clojure/
  28. R Markdown: The Definitive Guide
    https://bookdown.org/yihui/rmarkdown/
  29. Single-page application
    https://en.wikipedia.org/wiki/Single-page_application
  30. Video streaming in the Jupyter Notebook
    https://towardsdatascience.com/video-streaming-in-the-jupyter-notebook-635bc5809e85
  31. How IPython and Jupyter Notebook work
    https://jupyter.readthedoc­s.io/en/latest/architectu­re/how_jupyter_ipython_wor­k.html
  32. Jupyter kernels
    https://github.com/jupyter/ju­pyter/wiki/Jupyter-kernels
  33. Keras: The Python Deep Learning library
    https://keras.io/
  34. TensorFlow
    https://www.tensorflow.org/
  35. PyTorch
    https://pytorch.org/
  36. Seriál Torch: framework pro strojové učení
    https://www.root.cz/serialy/torch-framework-pro-strojove-uceni/
  37. Scikit-learn
    https://scikit-learn.org/stable/
  38. Java Interop (Clojure)
    https://clojure.org/referen­ce/java_interop
  39. Obrazy s balíčky Jupyter Notebooku pro Docker
    https://hub.docker.com/u/jupyter/#!
  40. Správce balíčků Conda (dokumentace)
    https://docs.conda.io/en/latest/
  41. Lorenzův atraktor
    https://www.root.cz/clanky/fraktaly-v-pocitacove-grafice-vi/#k02
  42. Lorenzův atraktor
    https://www.root.cz/clanky/fraktaly-v-pocitacove-grafice-iii/#k03
  43. Graphics with Matplotlib
    http://kestrel.nmt.edu/~ra­ymond/software/python_notes/pa­per004.html
  44. Embedding Matplotlib Animations in Jupyter Notebooks
    http://louistiao.me/posts/no­tebooks/embedding-matplotlib-animations-in-jupyter-notebooks/
  45. Literate programing, Kolokviální práce Pavla Starého
    https://www.fi.muni.cz/us­r/jkucera/pv109/starylp.htm
  46. PlantUML (home page)
    http://plantuml.sourceforge.net/
  47. PlantUML (download page)
    http://sourceforge.net/pro­jects/plantuml/files/plan­tuml.jar/download
  48. PlantUML (Language Reference Guide)
    http://plantuml.sourcefor­ge.net/PlantUML_Language_Re­ference_Guide.pdf
  49. Plain-text diagrams take shape in Asciidoctor!
    http://asciidoctor.org/new­s/2014/02/18/plain-text-diagrams-in-asciidoctor/
  50. Graphviz – Graph Visualization Software
    http://www.graphviz.org/
  51. graphviz (Manual Page)
    http://www.root.cz/man/7/graphviz/
  52. PIL: The friendly PIL fork (home page)
    https://python-pillow.org/
  53. Python Imaging Library (PIL), (home page)
    http://www.pythonware.com/pro­ducts/pil/
  54. PIL 1.1.6 na PyPi
    https://pypi.org/project/PIL/
  55. Pillow 5.2.0 na PyPi
    https://pypi.org/project/Pillow/
  56. Python Imaging Library na Wikipedii
    https://en.wikipedia.org/wi­ki/Python_Imaging_Library
  57. Pillow na GitHubu
    https://github.com/python-pillow/Pillow
  58. Pillow – dokumentace na readthedocs.io
    http://pillow.readthedocs­.io/en/5.2.x/
  59. How to use Pillow, a fork of PIL
    https://www.pythonforbegin­ners.com/gui/how-to-use-pillow
  60. await in Python
    https://docs.python.org/3/re­ference/expressions.html#a­wait

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.