|
**But de l'atelier** : manipuler les notions d' **événement** et de **fonction associée** pour rendre un graphique interactif.
|
|
**But de l'atelier** : manipuler les notions d' **événement** et de **fonction associée** pour rendre un graphique interactif.
|
|
|
|
|
|
**Autres notions manipulées au passage** :
|
|
**Autres notions manipulées au passage** :
|
|
- Python : **comprehension list** : création d'une nouvelle liste par une syntaxe plus performante qu'une boucle for classique (exemple de syntaxe : [x*x for x in liste_x] va créer une liste des carrés des éléments de liste_x) ; **zip** pour parcourir deux ou plusieurs conteneurs (liste, array...) simultanément, càd en prenant à l'itération i l'élément i de chaque conteneur, comme une fermeture éclair parcourt les dents situées de part et d'autre de la fermeture.
|
|
|
|
- spécifique mpl : modifier certaines caractéristiques d'une courbe existante avec **set_data()** ou **set_xdata() et set_ydata()** ; optionnel : le widget **"Textbox"**.
|
|
* Python : **comprehension list** : création d'une nouvelle liste par une syntaxe plus performante qu'une boucle for classique (exemple de syntaxe : \[x\*x for x in liste_x\] va créer une liste des carrés des éléments de liste_x) ; **zip** pour parcourir deux ou plusieurs conteneurs (liste, array...) simultanément, càd en prenant à l'itération i l'élément i de chaque conteneur, comme une fermeture éclair parcourt les dents situées de part et d'autre de la fermeture.
|
|
|
|
* spécifique mpl : modifier certaines caractéristiques d'une courbe existante avec **set_data()** ou **set_xdata() et set_ydata()** ; optionnel : le widget **"Textbox"**.
|
|
|
|
|
|
**Application** : sélectionner sur une courbe le point le plus proche d'un clic de souris
|
|
**Application** : sélectionner sur une courbe le point le plus proche d'un clic de souris
|
|
|
|
|
|
Il est possible de rendre certains objets d'une fenêtre matplotlib "réactifs" à un clic de souris. On va donc ici présenter la notion d'événement, associée à une fonction qu'il va déclencher.
|
|
Il est possible de rendre certains objets d'une fenêtre matplotlib "réactifs" à un clic de souris. On va donc ici présenter la notion d'événement, associée à une fonction qu'il va déclencher.
|
|
|
|
|
|
On propose de commencer par un événement simple, un clic de souris qui va juste renvoyer ses coordonnées, et déclencher la fonction avec laquelle il est associée, qui est définie par l'utilisateur. A la suite vous trouverez des fonctions plus utiles, comme ajouter un point ou sélectionner le point le plus proches du clic. Ensuite on a rédigé un paragraphe sur "Picker" (code test_picker, C. Poulard, S. Coulibaly). A priori, ses fonctionnalités permettent de sélectionner le point le plus proche de manière plus performante. Dans les faits, nous avons rencontré des problèmes de version (ça marche avec Matplotlib 3.4.2) et eu du mal à trouver des explications claires, d'où le besoin de faire des tests. On garde cependant une trace, en espérant que les prochaines versions soient plus pratiques à mettre en oeuvre. Les tests ont été l'occasion de découvrir un nouveau widget, **textbox**, une fenêtre de texte, qui est préférable au slider quand on veut rentrer des valeurs précises.
|
|
On propose de commencer par un événement simple, un clic de souris qui va juste renvoyer ses coordonnées, et déclencher la fonction avec laquelle il est associée, qui est définie par l'utilisateur. A la suite vous trouverez des fonctions plus utiles, comme ajouter un point ou sélectionner le point le plus proches du clic. Ensuite on a rédigé un paragraphe sur "Picker" (code test_picker, C. Poulard, S. Coulibaly). A priori, ses fonctionnalités permettent de sélectionner le point le plus proche de manière plus performante. Dans les faits, nous avons rencontré des problèmes de version (ça marche avec Matplotlib 3.4.2) et eu du mal à trouver des explications claires, d'où le besoin de faire des tests. On garde cependant une trace, en espérant que les prochaines versions soient plus pratiques à mettre en oeuvre. Les tests ont été l'occasion de découvrir un nouveau widget, **textbox**, une fenêtre de texte, qui est préférable au slider quand on veut rentrer des valeurs précises.
|
|
|
|
|
|
Exemple [d'événements ](https://matplotlib.org/stable/users/event_handling.html)à qui on peut associer une fonction :
|
|
Exemple [d'événements ](https://matplotlib.org/stable/users/event_handling.html)à qui on peut associer une fonction :
|
|
| nom de l'événement | type | description |
|
|
| nom de l'événement | type | description |
|
... | @@ -72,8 +73,7 @@ plt.show() |
... | @@ -72,8 +73,7 @@ plt.show() |
|
|
|
|
|
### le "clic" sélectionne le point le plus proche
|
|
### le "clic" sélectionne le point le plus proche
|
|
|
|
|
|
Cette fois, on va calculer la distance du point à chacun des points de la courbe, et on va retenir l'indice de la distance minimale, qui nous servira à aller chercher les bonnes coordonnées dans x et y. Attention, il s'agit ici de la distance "en unités de la courbe", on verra dans l'exemple du picker qu'il vaut mieux travailler en distances "écran", en pixels, pour que le point sélectionné corresponde à l'impression visuelle.
|
|
Cette fois, on va calculer la distance du point à chacun des points de la courbe, et on va retenir l'indice de la distance minimale, qui nous servira à aller chercher les bonnes coordonnées dans x et y. Attention, il s'agit ici de la distance "en unités de la courbe", on verra dans l'exemple du picker qu'il vaut mieux travailler en distances "écran", en pixels, pour que le point sélectionné corresponde à l'impression visuelle. Il restera à déplacer la courbe "sélection",réduite à un point, aux coordonnées de ce point.
|
|
Il restera à déplacer la courbe "sélection",réduite à un point, aux coordonnées de ce point.
|
|
|
|
|
|
|
|
```python
|
|
```python
|
|
def onclick_proche(event):
|
|
def onclick_proche(event):
|
... | @@ -90,20 +90,19 @@ def onclick_proche(event): |
... | @@ -90,20 +90,19 @@ def onclick_proche(event): |
|
fig.canvas.draw_idle()
|
|
fig.canvas.draw_idle()
|
|
|
|
|
|
fig,ax = plt.subplots()
|
|
fig,ax = plt.subplots()
|
|
|
|
ax.set_title("détermination du point de la courbe le plus proche")
|
|
donnees, = ax.plot(range(10), marker='o')
|
|
donnees, = ax.plot(range(10), marker='o')
|
|
selection, = ax.plot([0],[0], marker='*', c='red')
|
|
selection, = ax.plot([0],[0], marker='*', c='red', markersize=20)
|
|
|
|
|
|
fig.canvas.mpl_connect('button_press_event', onclick_proche)
|
|
fig.canvas.mpl_connect('button_press_event', onclick_proche)
|
|
plt.show()
|
|
plt.show()
|
|
```
|
|
```
|
|
|
|
|
|
<img src="uploads/d108c419b577d18f8c8296a4c6c7f6a7/Figure_selection_point_proche.png" width='240'>
|
|
![](uploads/d108c419b577d18f8c8296a4c6c7f6a7/Figure_selection_point_proche.png) _Figure avec sélection du point le plus proche\]_
|
|
<i>Figure avec sélection du point le plus proche]</i>
|
|
|
|
|
|
|
|
## Avec un "PickEvent" :
|
|
## Avec un "PickEvent" :
|
|
|
|
|
|
La méthode précédente fonctionne, mais elle a l'inconvénient de faire des calculs sur l'ensemble des points de la courbe.
|
|
La méthode précédente fonctionne, mais elle a l'inconvénient de faire des calculs sur l'ensemble des points de la courbe. On va utiliser la notion de _picker_, toujours sur une figure ne comportant qu'une seule courbe, afin de réaliser une **présélection**. Si on a plusieurs courbes, on peut ne lier le picker qu'à certaines d'entre elles. Si plusieurs sont réceptives au picker, la fonction liée sera déclenchée une fois pour chacune.
|
|
On va utiliser la notion de _picker_, toujours sur une figure ne comportant qu'une seule courbe, afin de réaliser une **présélection**. Si on a plusieurs courbes, on peut ne lier le picker qu'à certaines d'entre elles. Si plusieurs sont réceptives au picker, la fonction liée sera déclenchée une fois pour chacune.
|
|
|
|
|
|
|
|
![sélection picker](uploads/510c61180d0c1d51a059871fed23ab1c/selection_picker.png)
|
|
![sélection picker](uploads/510c61180d0c1d51a059871fed23ab1c/selection_picker.png)
|
|
|
|
|
... | @@ -218,3 +217,4 @@ nuage, = ax.plot(x, y, '*', c='blue', label="nuage", picker=init_radius, ls='Non |
... | @@ -218,3 +217,4 @@ nuage, = ax.plot(x, y, '*', c='blue', label="nuage", picker=init_radius, ls='Non |
|
textbox_radius.on_submit(submit_radius)
|
|
textbox_radius.on_submit(submit_radius)
|
|
```
|
|
```
|
|
|
|
|
|
|
|
![selection_point_mouseclick](uploads/467300d845b9a2e75b1b8ecca19328d8/selection_point_mouseclick.png) |
|
|
|
\ No newline at end of file |