Nous allons ici découvrir comment faire apparaitres de petits éléments interactifs qu'on nomme widgets, contraction de window et gadget. Cela pourra être un bouton, une barre de sélection...
Voici le visuel que nous allons parvenir à réaliser :
Les deux curseurs du bas sont des zones où on pourra interagir avec l'utilisateur et modifier l'allure des courbes en temps réel.
Remarque : si vous travaillez via un site vous permettant d'utiliser mapplotlib, il faudrait rajouter la ligne permettant de sauvegarder les courbes dans un fichier-image :
plt.savefig("essai.png")
Commençons par voir comment créer l'une de ces barres.
Commençons par reprendre le code final de l'activité précédente en replaçant les deux inputs par des valeurs fixes, par exemple 5 moles et 16 moles.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
# Déclaration des coefficients stochiométriques
cs_C4H10 = 2
cs_O2 = 13
cs_CO2 = 8
cs_H2O = 10
# Initialisation des quantités de matières initiales (en mol)
no_C4H10 = 5
no_O2 = 16
no_CO2 = 0
no_H2O = 0
# Calcul de l'avancement maximum
x_max_C4H10 = no_C4H10 / cs_C4H10
x_max_O2 = no_O2 / cs_O2
x_max = min(x_max_O2,x_max_C4H10)
# Création des listes
x = [ 0, x_max ]
n_C4H10 = [ (no_C4H10-cs_C4H10*valeur) for valeur in x]
n_O2 = [ (no_O2 - cs_O2*valeur) for valeur in x]
n_CO2 = [ (no_CO2 + cs_CO2*valeur) for valeur in x]
n_H2O = [ (no_H2O + cs_H2O*valeur) for valeur in x]
# Création des courbes
plt.plot(x, n_C4H10, label="C4H10", color='orange')
plt.plot(x, n_O2, label="O2", color='red')
plt.plot(x, n_CO2, label="CO2", color='black')
plt.plot(x, n_H2O, label="H2O", color='blue')
# Réglages axes et grille
liste_des_n_max = [ max(n_C4H10), max(n_O2), max(n_CO2), max(n_H2O) ]
n_max = max(liste_des_n_max)
plt.xlabel("Avancement (mol)")
plt.ylabel("Quantité de matière (mol)")
plt.title("Evolution de la réaction de combustion")
plt.legend(loc='upper center')
plt.axis([0,x_max,0,n_max])
plt.grid()
# Création des Widgets
# Création de l'image
nom_du_fichier = "courbes_avancement_"+str(no_C4H10)+str(no_O2)
plt.savefig(nom_du_fichier+".png")
# Affichage de l'interface
plt.show()
Dans les activités précédentes, nous avons vu que le nom des variables devaient normalement plutôt commencer par une minuscule. Nous avons néanmoins contourné cette norme puisque certaines notations de sciences physiques utilisent des majuscules. Voyons maintenant ce qu'indique une majuscule en informatique. Voici comment comment nous allons créer cette barre réglable à la souris :
w_reactif_1 = Slider(apparence_reactif_1, 'no(C4H10)', 0.1, 50.0, valinit=5, valstep=0.1, color='orange')
Nous voyons que :
apparence_reactif_1
va contenir les dimensions et la couleur de fond du rectangle'no(C4H10)'
correspond au texte qui sera affiché à gauche du Slider.0.1
correspond à la valeur minimale50
correspond à la valeur maximalevalinit=5
correspond à la valeur initialevalstep=0.1
correspond au cran d'avancement lorsqu'on déplace le curseur (mettre 1 pour obtenir des valeurs entières par exemple)color='orange'
correspond à la couleur de la partie de gauche du curseur.Rajoutons maintenant apparence_reactif_1 avant de créer le Slider :
01° Rajouter les lignes suivantes sous le commentaire Creation des Widgets.
apparence_reactif_1 = plt.axes([0.25, 0.0, 0.65, 0.03], facecolor='grey')
w_reactif_1 = Slider(apparence_reactif_1, 'no(C4H10)', 0.1, 50.0, valinit=5, valstep=0.1, color='orange')
Vous devriez avoir une erreur de ce type :
NameError: name 'Slider' is not defined
Pour créer nos wodgets, nous allons devoir importer leurs codes avec la ligne suivante qu'il faudra placer avec les autres importations.
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
Voici le code à tester en définitive :
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
# Déclaration des coefficients stochiométriques
cs_C4H10 = 2
cs_O2 = 13
cs_CO2 = 8
cs_H2O = 10
# Initialisation des quantités de matières initiales (en mol)
no_C4H10 = 5
no_O2 = 16
no_CO2 = 0
no_H2O = 0
# Calcul de l'avancement maximum
x_max_C4H10 = no_C4H10 / cs_C4H10
x_max_O2 = no_O2 / cs_O2
x_max = min(x_max_O2,x_max_C4H10)
# Création des listes
x = [ 0, x_max ]
n_C4H10 = [ (no_C4H10-cs_C4H10*valeur) for valeur in x]
n_O2 = [ (no_O2 - cs_O2*valeur) for valeur in x]
n_CO2 = [ (no_CO2 + cs_CO2*valeur) for valeur in x]
n_H2O = [ (no_H2O + cs_H2O*valeur) for valeur in x]
# Création des courbes
plt.plot(x, n_C4H10, label="C4H10", color='orange')
plt.plot(x, n_O2, label="O2", color='red')
plt.plot(x, n_CO2, label="CO2", color='black')
plt.plot(x, n_H2O, label="H2O", color='blue')
# Réglages axes et grille
liste_des_n_max = [ max(n_C4H10), max(n_O2), max(n_CO2), max(n_H2O) ]
n_max = max(liste_des_n_max)
plt.xlabel("Avancement (mol)")
plt.ylabel("Quantité de matière (mol)")
plt.title("Evolution de la réaction de combustion")
plt.legend(loc='upper center')
plt.axis([0,x_max,0,n_max])
plt.grid()
# Création des Widgets
apparence_reactif_1 = plt.axes([0.25, 0.0, 0.65, 0.03], facecolor='grey')
w_reactif_1 = Slider(apparence_reactif_1, 'no(C4H10)', 0.1, 50.0, valinit=5, valstep=0.1, color='orange')
# Création de l'image
nom_du_fichier = "courbes_avancement_"+str(no_C4H10)+str(no_O2)
plt.savefig(nom_du_fichier+".png")
# Affichage de l'interface
plt.show()
02° Lancer ce code dans IDLE :
Point positif : plus d'erreur. Point négatif : il est placé un peu n'importe où.
Si vous déplacer la valeur maximale de la zone orange, vous pourrez constater que la valeur à droite est modifiée, que le curseur devient plus grand ou plus petit et qu'une ligne rouge indique la position de la valeur initiale. Par contre, cela ne modifie en rien le graphique pour l'instant.
Pour améliorer le visuel, il va falloir aller chercher dans la documentation de matplotlib: Lien vers la documentation sur les axes
Pour rappel, notre code était :
apparence_reactif_1 = plt.axes([0.25, 0.0, 0.65, 0.03], facecolor='grey')
En allant lire la documentation, on peut voir que la liste permet de placer le rectangle symbolisant le Slider : [left, bottom, width, height]
03° Sachant que les dimensions sont fournies en pourcentage de la place disponible, vérifier si notre Slider est bien :
04° Modifier le code pour obtenir ceci :
...CORRECTION...
Puisqu'on doit fournir une liste contenant [left, bottom, width, height]
, le code a fournir est :
apparence_reactif_1 = plt.axes([0.25, 0.25, 0.5, 0.5], facecolor='grey')
Comme vous le voyez, on peut placer le Slider où on veut mais on ne peut pas agrandir la feuille avec cette méthode de placement. Nous allons donc devoir voir un peu plus en détail comme matplotlib place les différents éléments.
En réalité, nous avons laissé matplotlib placer tout ceci par défaut. Et cela ne donne donc pas grand chose.
Vous allez voir ici comment placer correctement et rigoureusement les éléments de votre fenêtre graphique.
Commençons par le cas le plus basique : on veut une zone graphique et placer les différents widgets autour.
Il existe une méthode qui permet de "pousser" le graphique et de limiter la place qu'il prend :
On peut pousser un peu plus et obtenir ceci :
La seule différence avec le code de la partie précédente tient en une ligne ici :
# Création des courbes
plt.subplots_adjust(left=0.75, bottom=0.50)
plt.plot(x, n_C4H10, label="C4H10", color='orange')
plt.plot(x, n_O2, label="O2", color='red')
plt.plot(x, n_CO2, label="CO2", color='black')
plt.plot(x, n_H2O, label="H2O", color='blue')
05° Identifier la ligne rajoutée. Comment se nommme la fonction utilisée ? A quoi correspondent 0.75 et 0.50 ?
...CORRECTION...
La fonction se nomme subplots_adjust.
Elle permet de décaler le côté gauche du graphe sélectionné de 75% de la largeur.
Elle permet de décaler le côté bas du graphe sélectionné de 50% de la hauteur.
06° Modifier le code pour obtenir ceci par exemple :
...CORRECTION...
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
# Déclaration des coefficients stochiométriques
cs_C4H10 = 2
cs_O2 = 13
cs_CO2 = 8
cs_H2O = 10
# Initialisation des quantités de matières initiales (en mol)
no_C4H10 = 5
no_O2 = 16
no_CO2 = 0
no_H2O = 0
# Calcul de l'avancement maximum
x_max_C4H10 = no_C4H10 / cs_C4H10
x_max_O2 = no_O2 / cs_O2
x_max = min(x_max_O2,x_max_C4H10)
# Création des listes
x = [ 0, x_max ]
n_C4H10 = [ (no_C4H10-cs_C4H10*valeur) for valeur in x]
n_O2 = [ (no_O2 - cs_O2*valeur) for valeur in x]
n_CO2 = [ (no_CO2 + cs_CO2*valeur) for valeur in x]
n_H2O = [ (no_H2O + cs_H2O*valeur) for valeur in x]
# Création des courbes
plt.subplots_adjust(left=0.25, bottom=0.25)
plt.plot(x, n_C4H10, label="C4H10", color='orange')
plt.plot(x, n_O2, label="O2", color='red')
plt.plot(x, n_CO2, label="CO2", color='black')
plt.plot(x, n_H2O, label="H2O", color='blue')
# Réglages axes et grille
liste_des_n_max = [ max(n_C4H10), max(n_O2), max(n_CO2), max(n_H2O) ]
n_max = max(liste_des_n_max)
plt.xlabel("Avancement (mol)")
plt.ylabel("Quantité de matière (mol)")
plt.title("Evolution de la réaction de combustion")
plt.legend(loc='upper center')
plt.axis([0,x_max,0,n_max])
plt.grid()
# Création des Widgets
apparence_reactif_1 = plt.axes([0.25, 0.05, 0.65, 0.03], facecolor='grey')
w_reactif_1 = Slider(apparence_reactif_1, 'no(C4H10)', 0.1, 50.0, valinit=5, valstep=0.1, color='orange')
# Création de l'image
nom_du_fichier = "courbes_avancement_"+str(no_C4H10)+str(no_O2)
plt.savefig(nom_du_fichier+".png")
# Affichage de l'interface
plt.show()
07° Rajouter un deuxième Slider pour règler la quantité de matière initiale de dioxygène :
...CORRECTION...
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
# Déclaration des coefficients stochiométriques
cs_C4H10 = 2
cs_O2 = 13
cs_CO2 = 8
cs_H2O = 10
# Initialisation des quantités de matières initiales (en mol)
no_C4H10 = 5
no_O2 = 16
no_CO2 = 0
no_H2O = 0
# Calcul de l'avancement maximum
x_max_C4H10 = no_C4H10 / cs_C4H10
x_max_O2 = no_O2 / cs_O2
x_max = min(x_max_O2,x_max_C4H10)
# Création des listes
x = [ 0, x_max ]
n_C4H10 = [ (no_C4H10-cs_C4H10*valeur) for valeur in x]
n_O2 = [ (no_O2 - cs_O2*valeur) for valeur in x]
n_CO2 = [ (no_CO2 + cs_CO2*valeur) for valeur in x]
n_H2O = [ (no_H2O + cs_H2O*valeur) for valeur in x]
# Création des courbes
plt.subplots_adjust(left=0.25, bottom=0.25)
plt.plot(x, n_C4H10, label="C4H10", color='orange')
plt.plot(x, n_O2, label="O2", color='red')
plt.plot(x, n_CO2, label="CO2", color='black')
plt.plot(x, n_H2O, label="H2O", color='blue')
# Réglages axes et grille
liste_des_n_max = [ max(n_C4H10), max(n_O2), max(n_CO2), max(n_H2O) ]
n_max = max(liste_des_n_max)
plt.xlabel("Avancement (mol)")
plt.ylabel("Quantité de matière (mol)")
plt.title("Evolution de la réaction de combustion")
plt.legend(loc='upper center')
plt.axis([0,x_max,0,n_max])
plt.grid()
# Création des Widgets
apparence_reactif_1 = plt.axes([0.25, 0.10, 0.65, 0.03], facecolor='grey')
w_reactif_1 = Slider(apparence_reactif_1, 'no(C4H10)', 0.1, 50.0, valinit=5, valstep=0.1, color='orange')
apparence_reactif_2 = plt.axes([0.25, 0.05, 0.65, 0.03], facecolor='grey')
w_reactif_2 = Slider(apparence_reactif_2, 'no(O2)', 0.1, 50.0, valinit=16, valstep=0.1, color='red')
# Création de l'image
nom_du_fichier = "courbes_avancement_"+str(no_C4H10)+str(no_O2)
plt.savefig(nom_du_fichier+".png")
# Affichage de l'interface
plt.show()
Cette partie n'a rien à voir avec Python mais avec le code couleur de ce site.
A partir de maintenant, nous allons utiliser la couleur ORANGE pour représenter les variables qui vont référence à un widget ou à les zones graphiques.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
# Déclaration des coefficients stochiométriques
cs_C4H10 = 2
cs_O2 = 13
cs_CO2 = 8
cs_H2O = 10
# Initialisation des quantités de matières initiales (en mol)
no_C4H10 = 5
no_O2 = 16
no_CO2 = 0
no_H2O = 0
# Calcul de l'avancement maximum
x_max_C4H10 = no_C4H10 / cs_C4H10
x_max_O2 = no_O2 / cs_O2
x_max = min(x_max_O2,x_max_C4H10)
# Création des listes
x = [ 0, x_max ]
n_C4H10 = [ (no_C4H10-cs_C4H10*valeur) for valeur in x]
n_O2 = [ (no_O2 - cs_O2*valeur) for valeur in x]
n_CO2 = [ (no_CO2 + cs_CO2*valeur) for valeur in x]
n_H2O = [ (no_H2O + cs_H2O*valeur) for valeur in x]
# Création des courbes
plt.subplots_adjust(left=0.25, bottom=0.25)
plt.plot(x, n_C4H10, label="C4H10", color='orange')
plt.plot(x, n_O2, label="O2", color='red')
plt.plot(x, n_CO2, label="CO2", color='black')
plt.plot(x, n_H2O, label="H2O", color='blue')
# Réglages axes et grille
liste_des_n_max = [ max(n_C4H10), max(n_O2), max(n_CO2), max(n_H2O) ]
n_max = max(liste_des_n_max)
plt.xlabel("Avancement (mol)")
plt.ylabel("Quantité de matière (mol)")
plt.title("Evolution de la réaction de combustion")
plt.legend(loc='upper center')
plt.axis([0,x_max,0,n_max])
plt.grid()
# Création des Widgets
apparence_reactif_1 = plt.axes([0.25, 0.10, 0.65, 0.03], facecolor='grey')
Slider(apparence_reactif_1, 'no(C4H10)', 0.1, 50.0, valinit=5, valstep=0.1, color='orange')
=apparence_reactif_2 = plt.axes([0.25, 0.05, 0.65, 0.03], facecolor='grey')
Slider(apparence_reactif_2, 'no(O2)', 0.1, 50.0, valinit=16, valstep=0.1, color='red')
=# Création de l'image
nom_du_fichier = "courbes_avancement_"+str(no_C4H10)+str(no_O2)
plt.savefig(nom_du_fichier+".png")
# Affichage de l'interface
plt.show()
Pour obtenir plus d'informations, il va falloir aller chercher dans la documentation de matplotlib: Lien vers la documentation sur les widgets
Et si vous voulez des exemples de code : Lien vers les exemples sur les widgets
Vous pourrez y trouver par exemple des boutons, des zones à cocher (checkbox) ou même des zones où les utilsateurs pourront taper du texte.
Dans la prochaine activité, nous verrons comment utiliser nos widgets pour agir sur les courbes. Cela va nécessiter de parler des fonctions.