Aller au contenu

Matplotlib

Le thème propose des fonctionnalités pour faciliter l'intégration de graphiques réalisés avec matplotlib dans la documentation, créés à partir de données/codes dans pyodide.

Ces outils sont une évolution d'un travail proposé initialement par Nicolas Révéret.

Principe général#

L'idée générale pour que cela fonctionne est la suivante :

  1. Insérer dans le fichier markdown un élément html (une <div>) qui accueillera la figure une fois qu'elle sera créée.
  2. Importer matplotlib depuis pyodide.
  3. Configurer matplotlib pour interagir avec le DOM.
  4. Construire les données et afficher les courbes souhaitées dans la div créée au point 1.


  • L'étape 1 est facilitée par l'utilisation de la macro {{ figure(...) }}.
  • L'étape 2 est faite par l'utilisateur, normalement depuis la section env du fichier python associé à une macro IDE, terminal, py_btn ou run.
  • L'étape 3 est gérée automatiquement par le thème, lorsqu'un import de matplotlib est détecté (étape 2).
  • L'étape 4 est facilitée par l'utilisation d'objets de la classe PyodidePlot (déclarée automatiquement par le thème, lors de l'étape 2), qui permettent de tracer les figures directement au bon emplacement dans le DOM (la div du point 1, donc).

Exemples#

Exemple simple#

Concrètement, pour la situation la plus simple où une seule figure doit être affichée dans la page, il suffit d'insérer un appel de macro figure et l'élément comportant le code python (IDE, terminal, py_btn ou run).

Remarques :

  • Dans l'IDE ci-dessous, tous les codes sont groupés dans la section code, mais il est possible de mettre une partie de la logistique dans la section env, afin que l'utilisateur ne voit pas ce qui concerne les objets PyodidePlot.
  • L'installation de matplotlib peut être très longue...


{{ IDE('exemples/plot_1') }}

{{ figure() }}

Permet d'obtenir :

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier

Votre figure

Votre tracé sera ici

Plusieurs figures#

Pour tracer plusieurs figures dans la même page, il faut utiliser des id html différents pour les deux figures, et il faut ensuite cibler chaque figure avant d'y démarrer les tracés :


{{ IDE('exemples/plot_2') }}

!!! help ""
    {{ figure('cible_1') }}

    {{ figure('cible_2') }}

Permet d'obtenir :

###(Dés-)Active le code après la ligne # Tests (insensible à la casse)
(Ctrl+I)
Entrer ou sortir du mode "deux colonnes"
(Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran"
(Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier

Votre figure

Votre tracé sera ici

Votre figure

Votre tracé sera ici

La classe PyodidePlot#

Disponibilité de la classe PyodidePlot

La classe PyodidePlot n'est déclarée dans l'environnement pyodide qu'après que matplotlib ait été installé.
Cela signifie que la classe ne peut être utilisée dans une section que si matplotlib y est également importé, ou s'il a déjà été importé précédemment.


L'utilisation des objets PyodidePlot a été simplifiée

Les objets de la classe PyodidePlot permettent en fait de faire plus que simplement pointer vers la bonne balise/figure, mais ces fonctionnalités se sont révélées trop spécifiques et la méthode target permet normalement de couvrir tous les besoins en restant au plus proche d'une utilisation normale de matplotlib dans l'environnement du thème.

Les informations ci-dessous sont donc fournies à fins de complétude et restent d'actualité, même si elles ne sont à priori plus nécessaires.

Généralités#

Cette classe est déclarée automatiquement au premier import de matplotlib dans pyodide.

L'objet PyodidePlot ainsi créé peut ensuite être utilisé en remplacement de matplotlib.pyplot : il relaie automatiquement tous les appels de méthodes à la fonction correspondant du module pyplot. Deux exceptions à cela :

  • La méthode PyodidePlot.plot met en place le tracé de la figure dans la div voulue, avant de relayer l'appel à pyplot.plot. Il faut donc ne surtout pas utiliser pyplot.plot

  • La méthode PyodidePlot.plot_func n'existe pas dans le module pyplot. C'est un ajout du thème, qui permet d'obtenir en un seul appel le tracé d'une fonction sur un domaine donné, en prenant en charge la construction des ordonnées, le titre éventuel de la figure et l'appel final à pyplot.show().

Accéder au code de la classe

Il est possible d'utiliser l'un des scripts du thème pour voir le code complet de la classe :

python -m pyodide_mkdocs_theme --plot

La classe utilisée dans le thème est rigoureusement identique à celle présente dans ce fichier.
Certaines instructions au tout début du fichier ne correspondent par contre pas au code utilisé dans le thème, car le but de ce fichier est de pouvoir exécuter les fichiers pythons de la documentation utilisant matplotlib en local (voir l'admonition suivante).

Exécution locale de fichier python utilisant la classe PyodidePlot

Si vous souhaitez exécuter des fichiers python utilisant matplotlib en local, il faut "ruser" un peu, mais le thème fournit les outils nécessaires :

  1. Installer matplotlib sur la machine/dans l'environnement, si ce n'est pas déjà fait.

    Ne pas ajouter matplotlib au fichier requirements.txt

    La bibliothèque matplotlib est ici une dépendance de développement, et non une dépendance de la documentation.

  2. Utiliser la commande ci-dessous, pour récupérer le fichier pyodide_plot.py du thème et le placer à la racine du projet :

    python -m pyodide_mkdocs_theme --plot -F pyodide_plot.py
    
  3. Ajouter ceci au tout début du fichier python de la documentation que vous voulez exécuter en local :

    # --- PYODIDE:ignore --- #
    from pyodide_plot import PyodidePlot
    

    Ce code ne sera exécuté qu'en local, les sections ignore des fichiers n'étant pas récupérées pour le site construit avec mkdocs.

Documentation complète de la classe PyodidePlot

PyodidePlot(div_id: str = '') #

Helper class, to draw figures from pyodide runtime, into a specified html element. If no argument is provided, the default div_id is used (arguments configuration of the plugin).

import matplotlib.pyplot as plt
PyodidePlot().target()

plt.plot(xs, ys, ...)
plt.title("...")
plt.show()

In case you want to target more than one figure in the same page, pass the html id of the div tag to target to the PyodidePlot constructor:

fig1 = PyodidePlot("figure_id1")
fig2 = PyodidePlot("figure_id2")

fig1.target()       # Draw in "figure_id1"
plt.plot(...)

fig2.target()       # Draw in "figure_id2"
plt.plot(...)

target(keep_fig=False) #

Close any previously created figure, then setup the current run to draw in the div tag targeted by the current instance. If keep_fig is set to True, the automatic Figure N will be kept, above the drawn figure.

plot_func(func: Callable, rng: Sequence, fmt: str = None, title: str = None, *, show: bool = True, keep_figure_num: bool = False, **kw) #

Draw an automatic graph for the given function on the given range, then "show" automatically the resulting graph in the correct figure element in the page.

Parameters:

Name Type Description Default
func Callable

Callable, func(x) -> y

required
rng Sequence

Sequence of xs

required
fmt str

Curve formatting (just like pyplot.plot)

None
title str

If given, will be added as title of the graph.

None
show bool

Call pyplot.show() only if True. This allows to customize the graph before applying show manually.

True
keep_figure_num bool

if False (by default), the Figure N above the drawing is automatically removed.

False

plot(*args, keep_figure_num: bool = False, **kw) #

Generic interface, strictly equivalent to pyplot.plot, except the PyodidePlot instance will automatically apply the drawing to the desired html element it is related to.

Use specifically this method to "plot" ! You then can rely on pyplot to finalize the figure as you prefer.