Licence CC BY-NC-ND Thierry Parmentelat & Arnaud Legout

Notebooks interactifs

Complément - niveau basique

Pour conclure cette série sur les outils de visualisation, nous allons voir quelques fonctionnalités disponibles uniquement dans l’environnement des notebooks, et qui offrent des possibilités supplémentaires par rapport aux visualisations que l’on a vues jusqu’à maintenant.

installation

Pour exécuter ou créer un notebook depuis votre ordinateur, il vous faut installer Jupyter, ce que se fait bien sûr depuis le terminal :

pip install jupyter

En 2020 il existe deux versions de l’interface Jupyter dites classic et lab, la seconde étant plus puissante en termes d’UI; pour installer le tout, faire plutôt

pip install jupyterlab

Pour lancer un serveur jupyter, faire selon le mode choisi

jupyter notebook
# ou
jupyter lab

Contenus

Pour le contenu des notebooks :

  • une cellule est marquée comme étant soit du code, soit du texte(markdown);

  • pour les cellules de markdown, on peut très simplement :

    • insérer des formules mathématiques, en insérant un fragment de $\LaTeX$ entre deux simples $, comme $\forall x\in\mathbb{R}$, ou encore
      sur une ligne séparée en entourant entre deux doubles dollars $$, comme $$\forall \epsilon>0, \exists\alpha>0, \forall x, |x-x_0| < \epsilon \implies |f(x)-f(x_0|<\epsilon$$

    • et bien sûr toute la panoplie des effets markdown, quoi qu’il faut se méfier car tout cela n’est pas très bien standardisé actuellement.

  • un notebook choisit son kernel (en clair son langage); le mot Jupyter vient de Julia + Python + R, et aujourd’hui il y a moyen de faire tourner presque tous les langages, même bash et C++ (mais en mode interprété bien sûr)

Courbes

import numpy as np
import matplotlib.pyplot as plt

Comme on l’a déjà vu plein de fois, la bonne façon de créer un graphique matplotlib c’est avec la formule magique suivante :

# ça c'est pour choisir la sortie 'notebook' 
%matplotlib notebook

# et ça c'est pour dire 'interactive on'
# pour éviter de devoir plt.show() tout le temps
plt.ion()
<matplotlib.pyplot._IonContext at 0x7f8779de9910>

Avec ces réglages - enfin surtout le premier - il y a pas mal de possibilités qui sont très pratiques :

  • pour commencer on peut changer la taille de la courbe en cliquant sur le petit coin visible en bas à droite de la figure

  • les courbes apparaissent avec un barre d’outils en dessous; entraînez-vous à utiliser par exemple l’outil de zoom, pour agrandir et vous déplacer dans la courbe

À titre d’exercice, sur cette courbe le nombre d’or correspond à une des racines du polynôme, à vous de trouver sa valeur avec une précision de

plt.figure(figsize=(2, 2))
X = np.linspace(-2, 2)
ZERO = X * 0
def golden(x):
    return x**2 - x - 1
plt.plot(X, golden(X));
plt.plot(X, ZERO);

Voici à quoi je suis arrivé de mon côté (je ne dis pas que c’est forcément la méthode la plus rapide pour trouver le nombre d’or ;-):
Mais tous les outils de visualisation décents vons proposer des mécanismes analogues, soyez-y attentifs car ça fait parfois gagner beaucoup de temps.

media/matplotlib-zoomed.png

Exemple de notebook interactif

Je vous signale enfin un exemple de notebook publié par la célèbre revue Nature, qui pourra vous donner une idée de ce qu’il est possible de faire avec un notebook interactif. Interactif dans le sens où on peut faire varier les paramètres d’une expérience et voir l’impact du changement se refléter immédiatement sur la visualisation.

Comme il n’est malheureusement plus actif en ligne semble-t-il, je vous invite à le faire marcher localement à partir de la version sur github ici.

Complément - niveau intermédiaire

Une visualisation interactive simple : interact

Pour refaire de notre coté quelque chose d’analogue, nous allons commencer par animer la fonction sinus, avec un bouton pour régler la fréquence. Pour cela nous allons utiliser la fonction interact ; à nouveau c’est un utilitaire qui fait partie de l’écosystème des notebooks, et plus précisément du module ipywidgets :

# dans cette partie on a besoin de 
# revenir dans un mode plus usuel
%matplotlib inline
from ipywidgets import interact

Dans un premier temps, j’écris une fonction qui prend en paramètre la fréquence, et qui dessine la fonction sinus sur un intervalle fixe de 0. à $4\pi$ :

def sinus(freq):
    X = np.linspace(0., 4*np.pi, 200)
    Y = np.sin(freq*X)
    plt.plot(X, Y)
sinus(1)
_images/a-c3-notebooks-interactifs_25_0.png
sinus(0.5)
_images/a-c3-notebooks-interactifs_26_0.png

Maintenant, plutôt que de tracer individuellement les courbes une à une, j’utilise interact qui va m’afficher une réglette pour changer le paramètre freq. Ça se présente comme ceci :

# je change maintenant la taille des visualisations
plt.rcParams["figure.figsize"] = (12, 4)
interact(sinus, freq=(0.5, 10., 0.25));
_images/a-c3-notebooks-interactifs_29_1.png

Mécanisme d’interact

La fonction interact s’attend à recevoir :

  • en premier argument : une fonction f ;

  • et ensuite autant d’arguments nommés supplémentaires que de paramètres attendus par f.

Comme dans mon cas la fonction sinus attend un paramètre nommé freq, le deuxième argument de interact lui est passé aussi avec le nom freq.

Les objets Slider

Chacun des arguments à interact (en plus de la fonction) correspond à un objet de type Slider (dans la ménagerie de ipywidget). Ici en passant juste le tuple (0.5, 10., 0.25) j’utilise un raccourci pour dire que je veux pouvoir régler le paramètre freq sur une plage allant de 0.5 à 10 avec un pas de 0.25.

Mon premier exemple avec interact est en réalité équivalent à ceci :

from ipywidgets import FloatSlider
# exactement équivalent à la version ci-dessus
interact(sinus, freq=FloatSlider(min=0.5, max=10., step=0.25));
_images/a-c3-notebooks-interactifs_36_1.png

Mais en utilisant la forme bavarde, je peux choisir davantage d’options, comme notamment :

  • mettre continuous_update = False ; l’effet de ce réglage, c’est que l’on met à jour la figure seulement lorsque je lâche la réglette ; c’est utile lorsque les calculs sont un peu lents, comme ici avec l’infrastructure notebook qui est à distance ;

  • mettre value=1. pour choisir la valeur initiale :

# exactement équivalent à la version ci-dessus
# sauf qu'on ne redessine que lorsque la réglette
# est relâchée
interact(sinus, freq=FloatSlider(min=0.5, max=10., 
                                 step=0.25, value=1.,
                                 continuous_update=False));
_images/a-c3-notebooks-interactifs_38_1.png

Plusieurs paramètres

Voyons tout de suite un exemple avec deux paramètres, je vais écrire maintenant une fonction qui me permet de changer aussi la phase :

def sinus2(freq, phase):
    X = np.linspace(0., 4*np.pi, 200)
    Y = np.sin(freq*(X+phase))
    plt.plot(X, Y)

Et donc maintenant je passe à interact un troisième paramètre :

interact(sinus2,
         freq=FloatSlider(min=0.5, max=10., step=0.5,
                          continuous_update=False),
         phase=FloatSlider(min=0., max=2*np.pi, step=np.pi/6, 
                           continuous_update=False),
        );
_images/a-c3-notebooks-interactifs_43_1.png

Bouche-trou : fixed

Si j’ai une fonction qui prend plus de paramètres que je ne veux montrer de réglettes, je peux fixer un des paramètres par exemple comme ceci :

from ipywidgets import fixed
# avec une fonction à deux argument,
# je peux en fixer un, et n'avoir qu'une réglette
# pour fixer celui qui est libre
interact(sinus2, freq=fixed(1.),
         phase=FloatSlider(min=0., max=2*np.pi, step=np.pi/6),
        );
_images/a-c3-notebooks-interactifs_47_1.png

Widgets

Il existe toute une famille de widgets, dont FloatSlider est l’exemple le plus courant, mais vous pouvez aussi :

  • créer des radio bouton pour entrer un paramètre booléen ;

  • ou une saisie de texte pour entre un paramètre de type str ;

  • ou une liste à choix multiples…

Bref, vous pouvez créer une mini interface-utilisateur avec des objets graphiques simples choisis dans une palette assez complète pour ce type d’application.

Voyez les détails complets sur readthedocs.io

# de même qu'un tuple était ci-dessus un raccourci pour un FloatSlider
# une liste ou un dictionnaire est transformé(e) en un Dropdown
interact(sinus, freq={'rapide': 10., 'moyenne': 1., 'lente': 0.1});
_images/a-c3-notebooks-interactifs_50_1.png

Voyez la liste complète des widgets ici.

Dashboards

Lorsqu’on a besoin de faire une interface un peu plus soignée, on peut créer sa propre disposition de boutons et autres réglages.

Voici un exemple de dashboard, uniquement pour vous donner une meilleure idée, qui pour changer agit sur une visualisation réalisée avec plot.ly plutôt que matplotlib :

import plotly
plotly.__version__
'5.2.1'
# on importe la bibliothèque plot.ly
import chart_studio.plotly as py
import plotly.graph_objs as go
# il est impératif d'utiliser plot.ly en mode 'offline' 
# pour in mode interactif, 
# car sinon les affichages sont beaucoup trop lents
import plotly.offline as pyoff

pyoff.init_notebook_mode()
# les widgets pour construire le tableau de bord
from ipywidgets import (interactive_output,
                        IntSlider, Dropdown, Layout, HBox, VBox, Text)
from IPython.display import display
# une fonction sinus à 4 réglages
# qu'on réalise pour changer avec plot.ly
# et non pas avec matplotlib
def sinus4(freq, phase, amplitude, domain):

    X = np.linspace(0., domain*np.pi, 500)
    Y = amplitude * np.sin(freq*(X+phase))

    data = [ go.Scatter(x=X, y=Y, mode='lines', name='sinus') ]
    # je fixe l'amplitude à 10 pour que les animations
    # soient plus parlantes
    layout = go.Layout(
        yaxis = {'range' : [-10, 10]},
        title="Exemple de graphique interactif avec dashboard",
        height=500,
        width=500,
    )
    figure = go.Figure(data=data, layout=layout)
    pyoff.iplot(figure)
def my_dashboard():
    """
    create and display a dashboard
    return a dictionary name->widget suitable for interactive_output
    """
    # dashboard pieces as widgets
    l_75 = Layout(width='75%')
    l_50 = Layout(width='50%')
    l_25 = Layout(width='25%')

    w_freq = Dropdown(options=list(range(1, 10)),
                      value = 1,
                      description = "fréquence",
                      layout=l_50)
    w_phase = FloatSlider(min=0., max = 2*np.pi, step=np.pi/12,
                          description="phase",
                          value=0., layout=l_75)
    w_amplitude = Dropdown(options={"micro" : .1,
                                    "mini" : .5,
                                    "normal" : 1.,
                                    "grand" : 3.,
                                    "énorme" : 10.},
                           value = 3.,
                           description = "amplitude",
                           layout = l_25)
    w_domain = IntSlider(min=1, max=10, description="dom. n * π", layout=l_50)

    # make up a dashboard
    dashboard = VBox([HBox([w_amplitude, w_phase]),
                      HBox([w_domain, w_freq]),
                     ])
    display(dashboard)
    return dict(freq=w_freq, phase=w_phase,
                amplitude=w_amplitude, domain=w_domain)

Avec tout ceci en place on peut montrer un dialogue interactif pour changer tous les paramètres de sinus4.

# interactively call sinus4
# attention il reste un bug:
# au tout début rien ne s'affiche,
# il faut faire bouger au moins un réglage
interactive_output(sinus4, my_dashboard())
"}, "metadata": {}, "output_type": "display_data"}]}}, "996834bcf7254e30bf8c8f217760ac29": {"model_module": "@jupyter-widgets/controls", "model_module_version": "1.5.0", "model_name": "VBoxModel", "state": {"_dom_classes": ["widget-interact"], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "1.5.0", "_model_name": "VBoxModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "1.5.0", "_view_name": "VBoxView", "box_style": "", "children": ["IPY_MODEL_26f4f555d34a45709b48508a2be45056", "IPY_MODEL_f595ebc24dd54c3998fa70277e2d0e87"], "layout": "IPY_MODEL_85016afd3dc34c1d85c0b8e032d4abeb"}}, "9e55b6fa6e2f4e6d81667c37ed70882a": {"model_module": "@jupyter-widgets/controls", "model_module_version": "1.5.0", "model_name": "FloatSliderModel", "state": {"_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "1.5.0", "_model_name": "FloatSliderModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "1.5.0", "_view_name": "FloatSliderView", "continuous_update": true, "description": "freq", "description_tooltip": null, "disabled": false, "layout": "IPY_MODEL_4b24b44df27a4d98b056941bd14b31da", "max": 10.0, "min": 0.5, "orientation": "horizontal", "readout": true, "readout_format": ".2f", "step": 0.25, "style": "IPY_MODEL_bd2470a2f20148ce81cd41e8591314b6", "value": 0.5}}, "9fbff3e0d88b4de8aa3e9eb63cd1b164": {"model_module": "@jupyter-widgets/base", "model_module_version": "1.2.0", "model_name": "LayoutModel", "state": {"_model_module": "@jupyter-widgets/base", "_model_module_version": "1.2.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "overflow_x": null, "overflow_y": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null}}, "a49a86f25c6045ad9f5b2052fc799ac7": {"model_module": "@jupyter-widgets/base", "model_module_version": "1.2.0", "model_name": "LayoutModel", "state": {"_model_module": "@jupyter-widgets/base", "_model_module_version": "1.2.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "overflow_x": null, "overflow_y": null, "padding": null, "right": null, "top": null, "visibility": null, "width": "50%"}}, "a58de0275cf3430ba5cff8a9843752ff": {"model_module": "@jupyter-widgets/output", "model_module_version": "1.0.0", "model_name": "OutputModel", "state": {"_dom_classes": [], "_model_module": "@jupyter-widgets/output", "_model_module_version": "1.0.0", "_model_name": "OutputModel", "_view_count": null, "_view_module": "@jupyter-widgets/output", "_view_module_version": "1.0.0", "_view_name": "OutputView", "layout": "IPY_MODEL_e458818691734004b05223376accfe84", "msg_id": "", "outputs": []}}, "b1bcd5add2064a3db46d287446d124aa": {"model_module": "@jupyter-widgets/base", "model_module_version": "1.2.0", "model_name": "LayoutModel", "state": {"_model_module": "@jupyter-widgets/base", "_model_module_version": "1.2.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "overflow_x": null, "overflow_y": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null}}, "b231427f12904710bc7b889ccfdda522": {"model_module": "@jupyter-widgets/base", "model_module_version": "1.2.0", "model_name": "LayoutModel", "state": {"_model_module": "@jupyter-widgets/base", "_model_module_version": "1.2.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "overflow_x": null, "overflow_y": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null}}, "b4f3b6bb5cb14b81889e6c2c8f4a94ab": {"model_module": "@jupyter-widgets/output", "model_module_version": "1.0.0", "model_name": "OutputModel", "state": {"_dom_classes": [], "_model_module": "@jupyter-widgets/output", "_model_module_version": "1.0.0", "_model_name": "OutputModel", "_view_count": null, "_view_module": "@jupyter-widgets/output", "_view_module_version": "1.0.0", "_view_name": "OutputView", "layout": "IPY_MODEL_65b71788574f4825bfdc3e8c8247b65e", "msg_id": "", "outputs": []}}, "b810d011a9d54fdcbdd5f6f6b2895fb9": {"model_module": "@jupyter-widgets/controls", "model_module_version": "1.5.0", "model_name": "FloatSliderModel", "state": {"_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "1.5.0", "_model_name": "FloatSliderModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "1.5.0", "_view_name": "FloatSliderView", "continuous_update": true, "description": "phase", "description_tooltip": null, "disabled": false, "layout": "IPY_MODEL_09f01eec5c5c40a0b2812250dda9e4d3", "max": 6.283185307179586, "min": 0.0, "orientation": "horizontal", "readout": true, "readout_format": ".2f", "step": 0.2617993877991494, "style": "IPY_MODEL_c5afde3c1f0f4d3793db0949a6bf57a6", "value": 0.0}}, "bb22332dca3f48c1a83f40cd1df4aabb": {"model_module": "@jupyter-widgets/controls", "model_module_version": "1.5.0", "model_name": "DropdownModel", "state": {"_dom_classes": [], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "1.5.0", "_model_name": "DropdownModel", "_options_labels": ["micro", "mini", "normal", "grand", "\u00e9norme"], "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "1.5.0", "_view_name": "DropdownView", "description": "amplitude", "description_tooltip": null, "disabled": false, "index": 3, "layout": "IPY_MODEL_466c567b1982458da65023254585c156", "style": "IPY_MODEL_e4f938588f264bc79e4afadb4cb0aa03"}}, "bd2470a2f20148ce81cd41e8591314b6": {"model_module": "@jupyter-widgets/controls", "model_module_version": "1.5.0", "model_name": "SliderStyleModel", "state": {"_model_module": "@jupyter-widgets/controls", "_model_module_version": "1.5.0", "_model_name": "SliderStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "StyleView", "description_width": "", "handle_color": null}}, "bda59631277a4a7da5cdeb553577039e": {"model_module": "@jupyter-widgets/controls", "model_module_version": "1.5.0", "model_name": "SliderStyleModel", "state": {"_model_module": "@jupyter-widgets/controls", "_model_module_version": "1.5.0", "_model_name": "SliderStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "StyleView", "description_width": "", "handle_color": null}}, "be638157461f4dc89b0fb8ccb17edfdf": {"model_module": "@jupyter-widgets/base", "model_module_version": "1.2.0", "model_name": "LayoutModel", "state": {"_model_module": "@jupyter-widgets/base", "_model_module_version": "1.2.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "overflow_x": null, "overflow_y": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null}}, "c5afde3c1f0f4d3793db0949a6bf57a6": {"model_module": "@jupyter-widgets/controls", "model_module_version": "1.5.0", "model_name": "SliderStyleModel", "state": {"_model_module": "@jupyter-widgets/controls", "_model_module_version": "1.5.0", "_model_name": "SliderStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "StyleView", "description_width": "", "handle_color": null}}, "c90b8517aa3e45a182e41e8d260b6252": {"model_module": "@jupyter-widgets/output", "model_module_version": "1.0.0", "model_name": "OutputModel", "state": {"_dom_classes": [], "_model_module": "@jupyter-widgets/output", "_model_module_version": "1.0.0", "_model_name": "OutputModel", "_view_count": null, "_view_module": "@jupyter-widgets/output", "_view_module_version": "1.0.0", "_view_name": "OutputView", "layout": "IPY_MODEL_e16322a611ac408b8ba137d35417f983", "msg_id": "", "outputs": []}}, "db533a09aaad4461a21e238b1e2dd13e": {"model_module": "@jupyter-widgets/base", "model_module_version": "1.2.0", "model_name": "LayoutModel", "state": {"_model_module": "@jupyter-widgets/base", "_model_module_version": "1.2.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "overflow_x": null, "overflow_y": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null}}, "dd4c2531c8854657b05558c84431c79d": {"model_module": "@jupyter-widgets/controls", "model_module_version": "1.5.0", "model_name": "VBoxModel", "state": {"_dom_classes": ["widget-interact"], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "1.5.0", "_model_name": "VBoxModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "1.5.0", "_view_name": "VBoxView", "box_style": "", "children": ["IPY_MODEL_5a79f50a39144135bb1081ad72687fa9", "IPY_MODEL_a58de0275cf3430ba5cff8a9843752ff"], "layout": "IPY_MODEL_b231427f12904710bc7b889ccfdda522"}}, "e0bb4b9b86bc48749dab89647780faa9": {"model_module": "@jupyter-widgets/controls", "model_module_version": "1.5.0", "model_name": "VBoxModel", "state": {"_dom_classes": ["widget-interact"], "_model_module": "@jupyter-widgets/controls", "_model_module_version": "1.5.0", "_model_name": "VBoxModel", "_view_count": null, "_view_module": "@jupyter-widgets/controls", "_view_module_version": "1.5.0", "_view_name": "VBoxView", "box_style": "", "children": ["IPY_MODEL_315b2bad051a492cbf6c6ad532053325", "IPY_MODEL_73fad8f0194c4b41a20b6e8c5e557a59"], "layout": "IPY_MODEL_ee164b92b203424cbce71fe25a5d5c01"}}, "e16322a611ac408b8ba137d35417f983": {"model_module": "@jupyter-widgets/base", "model_module_version": "1.2.0", "model_name": "LayoutModel", "state": {"_model_module": "@jupyter-widgets/base", "_model_module_version": "1.2.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "overflow_x": null, "overflow_y": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null}}, "e458818691734004b05223376accfe84": {"model_module": "@jupyter-widgets/base", "model_module_version": "1.2.0", "model_name": "LayoutModel", "state": {"_model_module": "@jupyter-widgets/base", "_model_module_version": "1.2.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "overflow_x": null, "overflow_y": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null}}, "e4f938588f264bc79e4afadb4cb0aa03": {"model_module": "@jupyter-widgets/controls", "model_module_version": "1.5.0", "model_name": "DescriptionStyleModel", "state": {"_model_module": "@jupyter-widgets/controls", "_model_module_version": "1.5.0", "_model_name": "DescriptionStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "StyleView", "description_width": ""}}, "e836691d69434b0ca4a943b50d9341a6": {"model_module": "@jupyter-widgets/base", "model_module_version": "1.2.0", "model_name": "LayoutModel", "state": {"_model_module": "@jupyter-widgets/base", "_model_module_version": "1.2.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "overflow_x": null, "overflow_y": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null}}, "ee164b92b203424cbce71fe25a5d5c01": {"model_module": "@jupyter-widgets/base", "model_module_version": "1.2.0", "model_name": "LayoutModel", "state": {"_model_module": "@jupyter-widgets/base", "_model_module_version": "1.2.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "overflow_x": null, "overflow_y": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null}}, "f106a2fc53604564afb39cc7f0c86020": {"model_module": "@jupyter-widgets/controls", "model_module_version": "1.5.0", "model_name": "DescriptionStyleModel", "state": {"_model_module": "@jupyter-widgets/controls", "_model_module_version": "1.5.0", "_model_name": "DescriptionStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "StyleView", "description_width": ""}}, "f1bca31cffa6476f859d57834481a897": {"model_module": "@jupyter-widgets/controls", "model_module_version": "1.5.0", "model_name": "SliderStyleModel", "state": {"_model_module": "@jupyter-widgets/controls", "_model_module_version": "1.5.0", "_model_name": "SliderStyleModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "StyleView", "description_width": "", "handle_color": null}}, "f595ebc24dd54c3998fa70277e2d0e87": {"model_module": "@jupyter-widgets/output", "model_module_version": "1.0.0", "model_name": "OutputModel", "state": {"_dom_classes": [], "_model_module": "@jupyter-widgets/output", "_model_module_version": "1.0.0", "_model_name": "OutputModel", "_view_count": null, "_view_module": "@jupyter-widgets/output", "_view_module_version": "1.0.0", "_view_name": "OutputView", "layout": "IPY_MODEL_48f59d521b4d458d9522a77c3233288f", "msg_id": "", "outputs": []}}}, "version_major": 2, "version_minor": 0}