Édition interactive de la toile Matplotlib

PythonPythonBeginner
Pratiquer maintenant

This tutorial is from open-source community. Access the source code

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Ce laboratoire vous guidera à travers un exemple d'application trans-GUI utilisant la gestion d'événements Matplotlib pour interagir avec et modifier des objets sur le canevas. Vous allez apprendre à éditer un tracé sur un graphique, en traînant des marqueurs avec la souris et en basculant leur visibilité.

Conseils sur la VM

Une fois le démarrage de la VM terminé, cliquez dans le coin supérieur gauche pour basculer vers l'onglet Notebook pour accéder au Notebook Jupyter pour la pratique.

Parfois, vous devrez peut-être attendre quelques secondes pour que le Notebook Jupyter ait fini de charger. La validation des opérations ne peut pas être automatisée en raison des limitations du Notebook Jupyter.

Si vous rencontrez des problèmes pendant l'apprentissage, n'hésitez pas à demander à Labby. Donnez votre feedback après la session, et nous résoudrons rapidement le problème pour vous.

Importation des bibliothèques

Dans cette étape, nous importons les bibliothèques nécessaires au laboratoire. Nous utilisons Matplotlib pour créer le graphique et gérer les événements.

import matplotlib.pyplot as plt
import numpy as np

from matplotlib.backend_bases import MouseButton
from matplotlib.patches import PathPatch
from matplotlib.path import Path

Création du graphique

Dans cette étape, nous créons un graphique avec un tracé vert et des bords jaunes, en utilisant les données de tracé fournies. Nous ajoutons ensuite un objet PathPatch au graphique, qui représente le tracé.

fig, ax = plt.subplots()

pathdata = [
    (Path.MOVETO, (1.58, -2.57)),
    (Path.CURVE4, (0.35, -1.1)),
    (Path.CURVE4, (-1.75, 2.0)),
    (Path.CURVE4, (0.375, 2.0)),
    (Path.LINETO, (0.85, 1.15)),
    (Path.CURVE4, (2.2, 3.2)),
    (Path.CURVE4, (3, 0.05)),
    (Path.CURVE4, (2.0, -0.5)),
    (Path.CLOSEPOLY, (1.58, -2.57)),
]

codes, verts = zip(*pathdata)
path = Path(verts, codes)
patch = PathPatch(
    path, facecolor='green', edgecolor='yellow', alpha=0.5)
ax.add_patch(patch)

Création de la classe PathInteractor

Dans cette étape, nous créons la classe PathInteractor, qui gère les rappels d'événements pour l'objet de tracé. Cette classe nous permet d'éditer le tracé de manière interactive en traînant des marqueurs sur le graphique.

class PathInteractor:
    """
    Un éditeur de tracé.

    Appuyez sur 't' pour basculer les marqueurs de sommets sur et off. Lorsque les marqueurs de sommets sont activés,
    ils peuvent être traînés avec la souris.
    """

    showverts = True
    epsilon = 5  ## distance maximale en pixels pour considérer qu'un sommet est touché

    def __init__(self, pathpatch):

        self.ax = pathpatch.axes
        canvas = self.ax.figure.canvas
        self.pathpatch = pathpatch
        self.pathpatch.set_animated(True)

        x, y = zip(*self.pathpatch.get_path().vertices)

        self.line, = ax.plot(
            x, y, marker='o', markerfacecolor='r', animated=True)

        self._ind = None  ## le sommet actif

        canvas.mpl_connect('draw_event', self.on_draw)
        canvas.mpl_connect('button_press_event', self.on_button_press)
        canvas.mpl_connect('key_press_event', self.on_key_press)
        canvas.mpl_connect('button_release_event', self.on_button_release)
        canvas.mpl_connect('motion_notify_event', self.on_mouse_move)
        self.canvas = canvas

    def get_ind_under_point(self, event):
        """
        Retourne l'index du point le plus proche de la position de l'événement ou *None*
        si aucun point n'est à moins de ``self.epsilon`` de la position de l'événement.
        """
        xy = self.pathpatch.get_path().vertices
        xyt = self.pathpatch.get_transform().transform(xy)  ## en coordonnées d'affichage
        xt, yt = xyt[:, 0], xyt[:, 1]
        d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2)
        ind = d.argmin()
        return ind if d[ind] < self.epsilon else None

    def on_draw(self, event):
        """Rappel pour les dessins."""
        self.background = self.canvas.copy_from_bbox(self.ax.bbox)
        self.ax.draw_artist(self.pathpatch)
        self.ax.draw_artist(self.line)
        self.canvas.blit(self.ax.bbox)

    def on_button_press(self, event):
        """Rappel pour les pressions de bouton de souris."""
        if (event.inaxes is None
                or event.button!= MouseButton.LEFT
                or not self.showverts):
            return
        self._ind = self.get_ind_under_point(event)

    def on_button_release(self, event):
        """Rappel pour les relâches de bouton de souris."""
        if (event.button!= MouseButton.LEFT
                or not self.showverts):
            return
        self._ind = None

    def on_key_press(self, event):
        """Rappel pour les pressions de touches."""
        if not event.inaxes:
            return
        if event.key == 't':
            self.showverts = not self.showverts
            self.line.set_visible(self.showverts)
            if not self.showverts:
                self._ind = None
        self.canvas.draw()

    def on_mouse_move(self, event):
        """Rappel pour les déplacements de souris."""
        if (self._ind is None
                or event.inaxes is None
                or event.button!= MouseButton.LEFT
                or not self.showverts):
            return

        vertices = self.pathpatch.get_path().vertices

        vertices[self._ind] = event.xdata, event.ydata
        self.line.set_data(zip(*vertices))

        self.canvas.restore_region(self.background)
        self.ax.draw_artist(self.pathpatch)
        self.ax.draw_artist(self.line)
        self.canvas.blit(self.ax.bbox)

Création de l'interacteur de tracé

Dans cette étape, nous créons une instance de la classe PathInteractor, en passant l'objet PathPatch que nous avons créé précédemment.

interactor = PathInteractor(patch)

Définir les propriétés du graphique

Dans cette étape, nous définissons le titre et les limites des axes pour le graphique.

ax.set_title('drag vertices to update path')
ax.set_xlim(-3, 4)
ax.set_ylim(-3, 4)

Afficher le graphique

Dans cette étape, nous affichons le graphique à l'écran.

plt.show()

Sommaire

Dans ce laboratoire, nous avons appris à créer un graphique interactif qui nous permet d'éditer un tracé en traînant des marqueurs sur le graphique. Nous avons utilisé la bibliothèque Matplotlib pour créer le graphique et gérer les événements, et avons créé une classe personnalisée pour gérer les rappels d'événements. En suivant ces étapes, vous pouvez créer vos propres graphiques interactifs avec Matplotlib.