Python pour le calcul scientifique/Graphiques
Rappel : les programmes commencent par :
#!/usr/bin/python3
import numpy as np
import matplotlib.pyplot as plt
Nous avons déjà vu un premier tracé élémentaire : Découverte de Python et de Jupyter > Premier tracé graphique ; nous en présentons un autre plus loin : Statistiques > Fréquence, histogramme.
Nous allons approfondir le sujet.
Concepts de base
modifierExemple
modifierConsidérons un tracé un peu plus avancé : il consiste en deux graphiques représentant les graphes des fonctions cosinus et sinus. Voici deux manières de le réaliser :
x = np.linspace(0, 2*np.pi, 50)
ycos = np.cos(x)
ysin = np.sin(x)
fig, liste_axes = plt.subplots(2, 1, constrained_layout=True)
fig.suptitle("Fonctions trigonométriques")
liste_axes[0].plot(x, ycos)
liste_axes[0].set_title("cosinus")
liste_axes[0].set_xlabel("x")
liste_axes[0].set_ylabel("y")
liste_axes[1].plot(x, ysin)
liste_axes[1].set_title("sinus", pad = 5)
liste_axes[1].set_xlabel("x")
liste_axes[1].set_ylabel("y")
plt.savefig("fonctions_trigo_pyplot.svg", format="svg")
Ou bien
x = np.linspace(0, 2*np.pi, 50)
ycos = np.cos(x)
ysin = np.sin(x)
plt.subplots(constrained_layout=True)
plt.suptitle("Fonctions trigonométriques")
plt.subplot(2, 1, 1)
plt.plot(x, ycos)
plt.title("cosinus")
plt.xlabel("x")
plt.ylabel("y")
plt.subplot(2, 1, 2)
plt.plot(x, ysin)
plt.title("sinus", pad = 5)
plt.xlabel("x")
plt.ylabel("y")
Analyse
modifierPremière manière
modifierLa création de deux graphiques se fait avec la commande plt.subplot()
à laquelle on indique le fait qu'il y a 2 lignes et 1 colonne ; le paramètre constrained_layout=True
permet d'avoir une meilleure mise en page. Cette commande retourne deux identifiants : fig
, l'identifiant de la figure, et liste_axes
, les identifiants des deux sous-figures.
La méthode .suptitle()
permet de créer un titre général. Pour chaque sous-figure (classe Axes
, que l'on pourrait traduire par « système d'axes »), on utilise les méthodes .plot()
pour tracer une courbe, .set_title()
pour lui donner un nom et les méthodes .set_xlabel()
et .set_ylabel()
pour les titres des axes.
La fonction plt.savefig()
permet d'enregistrer la figure dans un fichier, ici au format SVG.
Au lieu d'utiliser une matrice liste_axes
, on peut aussi utiliser un n-uplet :
fig, (axes0, axes1) = plt.subplots(2, 1, constrained_layout=True)
[…]
axes0.plot(x, ycos)
[…]
axes1.plot(x, ysin)
L'image est constituée de plusieurs objets. Il y en a de deux types :
- les contenants qui permettent la mise en page :
Figure
(la figure)[1] etAxes
(les systèmes d'axes)[2] ; - les primitives : ce sont les objets qui sont tracés à l'écran, essentiellement les
Line2D
(les courbes)[3].
La Figure
est un grand contenant, c'est lui qui contient tout le dessin ; on parle parfois de « toile » (canvas). Les Axes
sont les différentes sous-figures ; il y en a ici 2. Les axis
(« axe » en français) — à ne pas confondre avec le terme Axes
précédent — sont au nombre de deux par Axes
: l'axe de x (XAxis
) et l'axe des y (YAxis
).
Seconde manière
modifierChaque graphique est créé par la fonction plt.subplot(2, 1, 1)
. Les paramètres sont trois nombres : le nombre de lignes du tableau de figures, le nombre de colonnes de ce tableau, et le numéro de la cellule au sein du tableau en suivant le sens de lecture latin (de gauche à droite et de haut en bas). La création des graphiques est précédée de deux fonctions : plt.subplots(constrained_layout=True)
qui impose une répartition harmonieuse des graphiques, et plt.suptitle()
qui permet d'écrire un titre général.
Pour chaque graphique, on a les fonctions :
plt.plot()
qui tracent le graphique ;plt.title()
qui donnent un titre à chaque graphique ;plt.xlabel()
etplt.ylabel()
qui nomment les axes.
Styles de codage « pyplot » et « OO »
modifierOn voit qu'il y a aussi deux styles de codage, deux manières de rédiger. La première est la manière « pyplot » : la figure est décrite comme un automate fini (state machine), elle ne peut avoir qu'un nombre fini d'états et les fonctions font des transitions entre deux états. On utilise aussi l'expression « à la manière de Matlab ». On utilise des fonctions de l'espace de nom matplotlib.pylot (plt)
, ici : plt.subplots()
, plt.savefig()
et dans les exemples précédents, plt.plot()
, plt.hist()
, plt.xlabel()
, plt.ylabel()
, plt.title()
, plt.legend()
et plt.show()
.
La seconde manière est la manière « orientée objet » (OO) : comme nous avons défini des objets (la Figure
, les Axes
), nous pouvons utiliser des méthodes spécifiques à ces classes. C'est ainsi que nous avons les méthodes fig.suptitle()
, liste_axes[:].plot()
, .set_title()
, .set_xlabel()
et .set_ylabel()
.
Dans la manière OO, il faut donc connaître les identifiants des objets pour pouvoir utiliser leurs méthodes. La manière la plus simple est de créer explicitement les objets et d'assigner leur identifiant à des variables à cette occasion, par exemple :
fig, sysAxes = plt.subplots(1, 1)
courbe = sysAxes.plot(x, y)
ou bien
fig = plt.figure()
sysAxes = fig.add_subplot(1, 1, 1)
courbe = sysAxes.plot(x, y)
ou encore
fig = plt.figure()
sysAxes = plt.axes()
courbe = sysAxes.plot(x, y)
L'autre manière consiste à laisser pyplot tout créer tout seul, puis à récupérer les identifiants :
plt.plot(x, y)
fig = plt.gcf() # get current figure
sysAxes = plt.gca() # get current axes
courbe = sysAxes.lines[0]
ou bien
plt.plot(x, y)
fig = plt.gcf() # get current figure
sysAxes = fig.axes[0]
courbe = sysAxes.lines[0]
Mise en forme d'une courbe
modifierConsidérons une courbe unique. Nous pouvons changer l'apparence de la courbe en passant des paramètres lors de sa création. La première manière consiste à utiliser une chaîne de caractères comprenant :
- une lettre pour la couleur :
k
pour le noir (black),y
pour jaune (yellow)… - un ou deux caractères pour le type de trait :
-
pour un trait continu,--
pour un trait discontinu… - un caractère pour la forme des marqueurs :
o
pour des ronds, uns
pour un carré (square), und
pour un losange (diamond), unv
ou un^
pour un triangle pointe en bas ou en haut…
Par exemple :
plt.plot(x, y, "r--") # trait discontinu rouge
axes0 = plt.axes()
axes0.plot(x, y, "go") # cercles verts
Couleur | Marqueur | ||
---|---|---|---|
Caractère | Couleur | Caractère | Symbole |
b |
bleu | . |
point • |
g |
vert | , |
point d'un pixel ⋅ |
r |
rouge | o |
cercle ○ |
c |
cyan | v |
triangle pointe en bas ▽ |
m |
magenta | ^ |
triangle pointe en haut △ |
y |
jaune | < |
triangle pointe à gauche ◁ |
k |
noir | > |
triangle pointe à droite ▷ |
w |
blanc | s |
carré □ |
Style de ligne | p |
pentagone | |
Caractère | Style | 1 à 4 |
étoile à trois branches de différentes orientations |
- |
ligne continue | * |
étoile ✭ |
-- |
ligne discontinue | h , H |
hexagone sur la pointe ⬢ ou sur le plat ⬣ |
-. |
trait mixte | + |
croix droite + |
: |
trait pointillé | x |
croix de saint André × |
D , d |
losange carré ◇ ou étroit ◊ | ||
| |
trait vertical | | ||
_ |
trait horizontal — |
Notez la différence entre ".-"
qui affiche à la fois un marqueur point et un trait continu, et "-."
qui crée un trait mixte.
Méthodes avancées
Il est possible de passer les paramètres de manière plus explicite :
plt.plot(x, y, color="b", linestyle="dashed", marker="o")
L'attribut color
peut être spécifié de plusieurs manières :
- par une lettre, comme ci-dessus ;
- par un mot, le nom de la couleur ; il y a une cinquantaine de nom définis comme par exemple
blue
,lightblue
,darkblue
,grey
,chocolate
,fuschia
[4]… - avec le nom de la couleur dans la palette T10 ; les dix noms sont
tab:blue
,tab:orange
,tab:green
,tab:red
,tab:purple
,tab:brown
,tab:pink
,tab:gray
,tab:olive
ettab:cyan
; ce sont les couleurs utilisées par défaut ; - par un code RVB, les composante R, V et B étant indiquées en hexadécimal entre
00
etFF
:color = "#00FF00"
(bleu) ; on peut utiliser le canal alpha en quatrième composante (RVBA) :color = "#00FF0080"
; la composante A va de00
pour du parfaitement transparent àFF
pour du totalement opaque.
L'attribut linestyle
peut être indiqué par des caractères comme précédemment ; on peut également utiliser les noms : dashed
(discontinu), dashdot
(mixte), dotted
(pointillés), solid
(continu) ou bien None
ou une chaîne vide (pas de tracé).
On peut ajouter d'autres attributs, en particulier
linewidth
qui définit l'épaisseur du trait ;dashes
: permet de définir un trait discontinu avec un doublet (2-uplet) indiquant le nombre de point affichés et le nombre de points non-affichés, par exempledashes=(4, 2)
; on peut alterner plusieurs couple comme par exempledashes=(8, 2, 4, 2)
markeredgecolor
: couleur du trait du symbole marqueur ;markeredgewidth
: épaisseur du trait du symbole marqueur (en points) ;markerfacecolor
: couleur de remplissage du symbole marqueur ;fillstyle
: permet de ne remplir qu'une moitié du symbole marqueur ; prend les valeurstop
,right
,bottom
etleft
pour indiquer la moitié remplie ;markersize
: taille du symbole marqueur (en points).
Avec le style de codage orienté objet, cela donne :
courbe = plt.plot(x, y)
courbe[0].set_linestyle("--")
# ou bien
courbe, = plt.plot(x, y)
courbe.set_linestyle("--")
# ou encore
plt.plot(x, y)
axes = plt.gca()
courbe = axes.lines[0]
courbe.set_linestyle("--")
Les principales méthodes des objets Line2D sont : .set_color()
, .set_linestyle()
, .set_linewidth()
, .set_dashes()
, .set_marker()
et tous les .set_marker…()
(edgecolor
, edgewidth
facecolor
, size
).
- Ressources
- (en) « Pyplot tutorial », sur Matplotlib (consulté le 30 mars 2019)
- (en) « matplotlib.pyplot.plot », sur Matplotlib (consulté le 30 mars 2019)
- (en) « matplotlib.lines.Line2D.set_linestyle », sur Matplotlib (consulté le 30 mars 2019)
Annotations
modifierNous parlons ici le fait de placer des annotations sur une figure et non pas la notion d'annotation en programmation.
Il est possible de placer du texte avec la commande plt.text(x, y, chaine)
où (x, y) sont les coordonnées, dans le repère du tracé, où l'on veut placer le texte, et chaine est une chaîne de caractères. On peut modifier l'orientation de ce texte avec le paramètre rotation
exprimé en degrés, par exemple :
plt.text(0, 0, "origine", rotation=90)
Par ailleurs, la classe Axes
dispose d'une méthode .annotate()
. Dans sa forme la plus simple, on indique une chaîne correspondant à l'étiquette et un doublet (2-uplet) ou une liste indiquant les coordonnées où placer l'étiquette. Par exemple :
x = np.linspace(0, 2*np.pi, 50)
ycos = np.cos(x)
courbe = plt.plot(x, ycos)
fig = plt.gcf() # get current figure
sysAxes = plt.gca() # get current axes
ymin = ycos.min() # trouve la veleur minimale de ycos
imin = ycos.argmin() # trouve l'indice correspondant au minimum
xmin = x[imin]
sysAxes.annotate("min", (xmin, ymin))
Telle quelle, l'étiquette empiète sur la courbe. On peut placer l'étiquette à des coordonnées particulières avec l'attribut xytext
cet attribut reçoit un doublet ou une liste de coordonnées (x, y).
Par ailleurs, on peut relier l'étiquette au point visé avec l'attribut arrowsprop
(arrow's properties, propriétés de la flèche). Cet attribut reçoit un dictionnaire de propriétés, arrowsprop=dict(…)
ou bien arrowsprop={…}
. Par exemple, pour avoir simplement un trait, ce dictionnaire contient arrowstyle="-"
et pour une flèche, arrowstyle="->"
.
Par exemple, avec l'exemple précédent :
sysAxes.annotate("min", (xmin, ymin), xytext=(xmin+0.5, ymin+0.5), arrowprops=dict(arrowstyle="->"))
# ou bien
sysAxes.annotate("min", (xmin, ymin), xytext=(xmin+0.5, ymin+0.5), arrowprops={"arrowstyle":"-"})
- Ressource
- (en) « matplotlib.axes.Axes.annotate », sur Matplotlib (consulté le 7 avril 2019)
Autres exemples de tracés 2D
modifierPar exemple avec :
x = np.linspace(0, 2*np.pi, 20)
y = np.sin(x)
fig, listeAxes = plt.subplots(3, 1, constrained_layout=True)
# Tracé en escalier
listeAxes[0].step(x, y)
# tracé en bâtons
listeAxes[1].bar(x, y, width = 0.03)
# Tracé en flèches
listeAxes[2].quiver(x[:-1], y[:-1], np.diff(x), np.diff(y), scale_units="xy", scale=1, angles="xy", width=0.02)
Gestion des échelles
modifierPour fixer les valeurs extrêmes des axes, on utilise les commandes plt.xlim(min, max)
et plt.ylim(min, max)
.
Pour avoir une échelle logarithmique, respectivement en x et en y, on utilise les commandes plt.xscale("log")
et plt.yscale("log")
. Ces fonctions peuvent recevoir les paramètres suivants :
linear
: échelle linéaire (valeur par défaut) ;log
: échelle logarithmique ;symlog
: échelle logarithmique symétrique, c'est-à-dire avec la transformation avec C = 1/ln(10) ; nous avons ainsi des valeurs positives et négative sans avoir la singularité en 0 ;logit
: l'échelle est transformée par la fonction logit.
On peut superposer une grille avec la commande plt.grid(True)
.
S'il y a trop de graduations sur un axe, on peut réduire le nombre de graduations avec :
from matplotlib.ticker import NullFormatter
# […]
plt.gca().yaxis.set_minor_formatter(NullFormatter())
On peut imposer les valeurs graduées :
plt.gca().set_xticks([0, 1, 2, 3])
On peut imposer le fait d'avoir les mêmes échelles en x ou en y avec les mots-clefs sharex
et sharey
. Par exemple :
fig = plt.figure()
ax1 = fig.add_subplot(2, 1, 1)
ax2 = fig.add_subplot(2, 1, 2, sharex=ax1)
ou bien
fig, axs = plt.subplots(2,1, sharex=True)
Si l'on veut que l'échelle en x soit la même que l'échelle en y, on peut utiliser la méthode set_aspect()
[5] des objets axes
, par exemple
plt.gca().set_aspect("equal", adjustable="box")
Si l'on veut que le graphique soit carré, on utilise le mot-clef square
de l'objet axis
:
plt.axis("square")
Si l'on veut que les échelles sur les axes x et y soient de pas identiques, par exemple pour qu'un carré soit un carré et un demi-cercle ne soit pas une demie ellipse, on utilise :
plt.gca().set_aspect("equal", adjustable="box")
Plusieurs courbes sur un même système d'axes
modifierPour mettre plusieurs courbes sur un même système d'axes, on peut soit les créer les unes après les autres :
plt.plot(x1, y1)
plt.plot(x2, y2)
Soit les mettre dans la même commande :
plt.plot(x1, y1, x2, y2)
Matplotlib définit lui-même des couleurs différentes. On peut bien évidemment forcer le style des courbes. On peut également ajouter une étiquette (label) qui sera ensuite affichée dans la légende :
plt.plot(x1, y1, "k", label="courbe 1")
plt.plot(x2, y2, "b", label="courbe 1")
plt.legend()
# ou bien
courbes = plt.plot(x1, y1, "k", x2, y2, "b")
courbes[0].set_label("courbe 1")
courbes[1].set_label("courbe 2")
plt.legend()
# ou bien
courbes = plt.plot(x1, y1, x2, y2)
courbes[0].set(color="k", label="courbe 1")
courbes[1].set(color="b", label="courbe 2")
plt.legend()
On peut choisir l'emplacement de la légende avec le paramètre loc
qui peut prendre les valeurs "upper left"
, "upper center"
, "upper right"
, "center left"
… la valeur est composée de deux adjectifs :
- premier adjectif :
center
signifie au centre, au milieu,upper
signifie en haut,lower
signifie en bas ;
- second adjectif :
center
signifie au centre, au milieu,left
signifie à gauche,right
signifie à droite.
Par exemple :
plt.legend(loc="upper right")
Si l'on veut des courbes avec des échelles en y différentes, il faut créer un axe x « jumeau » (twin) avec la méthode .twinx()
. Par exemple :
fig, axe = plt.subplots(figsize=(5, 5))
plt.suptitle("Chargement")
axe2 = axe.twinx()
axe.plot(forces)
axe.set_xlabel("Étape")
axe.set_ylabel("F (N)")
axe2.plot(contraintes)
axe2.set_ylabel("σ (MPa)")
Tracé polaire
modifierUn tracé polaire s'obtient avec la commande plt.polar()
, par exemple :
theta = np.linspace(0, 2*np.pi, 20) # angle
r = 1 + 0.2*np.random.randn(20) # rayon
plt.polar(theta, r) # courbe polaire
Voici un exemple avec deux courbes superposées et une mise en forme des graduations et de la légende :
#!/usr/bin/python3
import numpy as np
import matplotlib.pyplot as plt
# **************
# * Constantes *
# **************
# positions angulaires
angles = 2*np.pi*np.linspace(0, 1, 9) # huitièmes de cercle
radDeg = 180/np.pi # conversion radians → degrés
etoile = np.array([1, 0.2, 1, 0.2, 1, 0.2, 1, 0.2, 1]) # Tracé de l'étoile
vents = np.array([2.85, 3.34, 5.2, 4.025, 4.9, 9.63, 7.5, 2.35, 2.85]) # Fréquence (unité arbitraire)
vents = vents/vents.max() # normalisation
# ***********
# * Traçage *
# ***********
courbes = plt.polar(angles, etoile, angles, vents) # tracé
# mise en forme
axes = plt.gca()
courbes[0].set(color="gray")
courbes[1].set(color="b", label="Fréquence des vents")
plt.legend(bbox_to_anchor=(1.45, 1.05), loc="upper right") # affichage à l'extérieur du tracé
axes.set_rticks([0.2, 0.4, 0.6, 0.8, 1]) # graduations radiales
axes.set_thetagrids(angles=radDeg*angles[0:-1], labels=("E", "NE", "N", "NO", "O", "SO", "S", "SE")) # graduations angulaires
plt.title("Rose des vents")
plt.savefig("rose_des_vents.svg", format="svg")
plt.show()
Cartes de valeurs et de vecteurs
modifierLorsque l'on a une surface dans un espace à trois dimensions, de type z = ƒ(x&htinsp;, y ), on peut afficher les données sur la forme d'une carte :
- lignes de niveau : on utilise la fonction
np.contour()
; - surfaces de niveau :
np.contourf()
; - carte de couleurs :
np.pcolormesh()
.
La fonction colorbar()
permet d'afficher l'échelle de couleurs.
Par exemple :
x = np.linspace(0, 2*np.pi, 20)
y = x.copy()
X, Y = np.meshgrid(x, y)
Z = np.sin(X)*np.sin(Y)
fig, liste_axes = plt.subplots(2, 2, constrained_layout=True)
im1 = liste_axes[0, 0].contour(X, Y, Z)
fig.colorbar(im1, ax=liste_axes[0, 0])
im2 = liste_axes[0, 1].contourf(X, Y, Z)
fig.colorbar(im2, ax=liste_axes[0, 1])
im3 = liste_axes[1, 0].pcolormesh(X, Y, Z)
fig.colorbar(im3, ax=liste_axes[1, 0])
On peut choisir d'autres échelles de couleur (color map) avec le paramètre cmpa
:
im3 = liste_axes[1, 0].pcolormesh(X, Y, Z, cmap="Greens")
Les échelles de couleur disponibles sont données à la page :
- (en) « Colors in matplotlib », sur matplotlib (consulté le 5 avril 2019).
On peut aussi faire une carte d'un champ de vecteurs avec la commande plt.quiver()
vue précédemment :
base = np.arange(10)
x, y = np.meshgrid(base, base)
ux = -0.1*y
uy = 0.1*x
plt.quiver(x, y, ux, uy, scale_units="xy", scale = 1, angles="xy")
Surfaces 3D
modifierIl est également possible de tracer des surfaces 3D. Il faut pour cela charger Axes3D
du module mpl_toolkits.mplot3d
; cela donne accès au paramètre projection="3d"
lorsque l'on définit le système d'axes. Par exemple :
from mpl_toolkits.mplot3d import Axes3D # permet d'utiliser l'attribut projection="3d"
x = np.linspace(0, 2*np.pi, 20)
y = x.copy()
X, Y = np.meshgrid(x, y)
Z = np.sin(X)*np.sin(Y)
plt.figure()
ax = plt.axes(projection="3d")
ax.contour(X, Y, Z, zdir="z", offset=-1) # projection sur le plan z = -1
ax.plot_surface(X, Y, Z, alpha=0.8)
On peut changer l'angle de vue du système d'axes avec les paramètres elev
(élévation) etazim
(azimut). Par exemple
ax = plt.axes(projection="3d", elev = 10, azim = 90)
Mise en forme de la figure
modifierLa figure dispose de paramètres de mise en forme :
figsize
: liste des dimensions (largeur, hauteur) en pouces (valeur par défaut[6.4, 4.8]
) ;dpi
: résolution en points par pouce (valeur par défaut100
) ;facecolor
: couleur de fond (valeur par défautwhite
) ;edgecolor
: couleur du filet de bordure (valeur par défautwhite
) ;layout
: définit le placement des objets pour éviter les effets indésirables (par exemple le recouvrement, valeur par défautnone
).
Par exemple :
M = np.random.randn(50)
fig = plt.figure(figsize = [10, 6])
plt.plot(M)
Mise en forme du texte
modifierSi l'on veut utiliser le style LaTeX, on utilise :
plt.rcParams["text.usetex"] = True
[…]
plt.xlabel("$x$")
Dessins
modifierLes dessins portent le nom de « pièces » (patch). Les fonctions pour les créer se trouvent dans le module matplotlib.patches
. Ces fonctions permettent de créer les pièces mais pour les dessiner (c'est-à-dire les mettre sur la « toile »), il faut utiliser la méthode .add_patch()
.
Par exemple :
from matplotlib.patches import Circle, Polygon
fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1]) # système d'axes occupant toute la figure
ax.set_xlim(0, 2) # axes gradués de 0 à 2
ax.set_ylim(0, 2)
# Création des pièces
cercle = Circle((0.25, 0.25), 0.1) # cercle de centre (0,25 ; 0,25) et de rayon 0,1
polygone = Polygon([[1.5, 1.5], [2, 1.5], [1.75, 2]]) # polygone à trois sommets (triangle)
# Dessin des pièces
ax.add_patch(cercle)
ax.add_patch(polygone)
Le dessin des pièces une par une est un processus assez long. Il est intéressant de créer une collection et de dessiner cette collection d'un seul tenant. On a pour cela recours au module matplotlib.collections
. Le code devient donc :
from matplotlib.patches import Circle, Polygon
from matplotlib.collections import PatchCollection
fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1])
ax.set_xlim(0, 2)
ax.set_ylim(0, 2)
cercle = Circle((0.25, 0.25), 0.1)
polygone = Polygon([[1.5, 1.5], [2, 1.5], [1.75, 2]])
coll = PatchCollection((cercle, polygone))
ax.add_collection(coll)
Il est possible de dessiner des chemins (path).
- Pour plus de détails voir : Découvrir le SVG/Chemins.
On a pour cela recours au module matplotlib.path
. Par exemple :
from matplotlib.patches import PathPatch
from matplotlib.path import Path
fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1])
ax.set_xlim(0, 2)
ax.set_ylim(0, 2)
# Création du chemin
chemin = Path([[0.25, 0.5], [0.25, 1.5], [0.75, 1.5]],
[Path.MOVETO, Path.CURVE3, Path.CURVE3])
# Création de la pièce à partir du chemin
pieceChemin = PathPatch(chemin)
# Dessin de la pièce
ax.add_patch(pieceChemin)
Ici, nous disons à la « plume » de se rendre (move to) au point de coordonnées (0,25 ; 0,25), puis de tracer une courbe de Bézier quadratique (curve 3) jusqu'au point (0,75 ; 1,5) avec comme point de contrôle intermédiaire (0,25 ; 1,5).
Transformation des objets graphiques
modifierIl est possible de faire subir des transformations linéaires aux objets graphiques[6]. On utilise pour cela le module matplotlib.transforms
(au pluriel) et l'attribut transform
(au singulier) des commandes pyplot.
Par exemple, pour tourner un objet de 90° :
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.transforms as transforms
donnees = np.random.randn(20) # points au hasard
base = plt.gca().transData # base de la transformation
rotation = transforms.Affine2D().rotate_deg(90) # rotation de 90°
plt.plot(donnees, transform = rotation + base)
La transformation transforms.Affine2D()
a normalement pour argument une matrice 3 × 3 classique en géométrie. Lorsque l'on est en deux dimensions, cette matrice a la forme
- Pour plus de détails voir : w:Matrice de transformation.
Les méthodes d'Affine2D()
permettent de générer automatiquement cette matrice. Par exemple, transforms.Affine2D().rotate(θ)
(angle θ en radians ; on utilise .rotate_deg()
pour des angles en degrés) crée la matrice de rotation
On peut donner directement la matrice M (de type np.array()
avec transforms.Affine2D().set_matrix(M)
. On peut indiquer les valeurs sous la forme d'une liste avec transforms.Affine2D().from_values(a, c, b, d, 0, 0)
(notez l'ordre des paramètres).
Créer un GIF animé
modifierIl existe plusieurs modules permettant de créer un GIF animé dans Python.
Avec le module PIL (Python imaging library)
modifierLa première étape consiste à créer un n-uplet contenant les noms de tous les fichiers image, dans l'ordre ; nous l'appelons imgs
. Puis, nous créons un n-uplet contenant les pointeurs vers les images, ouverte avec PIL.Images.open()
; nous l'appelons trames
. Nous créons le fichier GIF animé en utilisant la méthode .save()
du n-uplet trames
from PIL import Image
imgs=[] # initialisation du n-uplet
for i in range(10): # nom des images : "fichieri.png", i étant un entier ("fichier0.png", "fichier1.png" etc.)
imgs.append("fichier"+str(i)+".png")
trames = []
for i in imgs:
nouv_trame = Image.open(i)
trames.append(nouv_trame)
trames[0].save("animation.gif", format="GIF",
append_images=trames[1:],
save_all=True,
duration=300, # durée en milliseconde
loop=0) # pour boucler ;
- Ressources
Les couches de matplotlib
modifier
- (en) « Artist tutorial », sur Matplotlib (consulté le 29 mars 2019)
- (en) « Artist API », sur Matplotlib (consulté le 29 mars 2019)
Pour bien comprendre la documentation du module matplotlib
, il faut comprendre sa structure en couches. Cela n'est pas indispensable pour l'utilisation élémentaire du module, mais connaître ce vocabulaire devient important pour une utilisation avancée.
Le module matplotlib
est organisé en trois couches :
- la toile (
FigureCanvas
) : c'est l'espace sur lequel le tracé est fait ; - le restituteur (
Renderer
) : c'est l'objet chargé d'effectuer les tracés sur la toile ; - les artistes (
Artist
) : ce sont les classes des objets destinés à être tracés.
Il faut distinguer le tracé (plot), qui consiste à traduire les données en objets à tracer en utilisant les artistes, et la publication (show) qui consiste à afficher les tracés à l'écran ou à les écrire dans un fichier. La publication est le rôle de la « face cachée » (backend).
Cette structure en trois couches facilite la tâche de l'utilisateur : vous n'avez à vous concentrer qu'aux données et au type et style de tracé (en manipulant les artistes), la face cachée s'occupe de gérer la partie logicielle et matérielle (différence de système d'exploitation, de carte graphique, de format de fichier). La face cachée est donc une couche « abstraite », que l'utilisateur ne voit quasiment jamais.
Dans les cas les plus simples, l'utilisation d'un artiste provoque aussi sa publication : si l'on fait un .plot()
, la courbe s'affiche à l'écran. Mais dans certains cas, il faut indiquer à Python de publier le graphique ; par exemple, s'il y a des opérations de tracé longues à faire, on a intérêt à tout afficher à la fin, une fois toutes les opérations faites. C'est la raison d'être des fonctions et méthodes .show()
ou .draw()
.
On distingue ainsi deux types d'artistes : les contenants et les primitives. Nous avons ainsi l'organisation suivante :
- face cachée (
backend
)- toile (
FigureCanvas
) - restituteur (
Renderer
)
- toile (
- artistes (
Artist
)- conteneurs (
container
)- figure (
Figure
)- systèmes d'axes (
Axes
)- axes (
axis
)- graduations (
ticks
)
- graduations (
- légendes (
legend
)
- axes (
- …
- systèmes d'axes (
- figure (
- primitives (
primitive
)- courbes (
Line2D
) - textes (
Text
) - bords (
Spine
) - pièces (
Patch
) - …
- courbes (
- conteneurs (
Notes et références
modifier- ↑ « matplotlib.figure », sur Matplotlib.org (consulté le 3 mai 2022).
- ↑ « matplotlib.axes », sur Matplotlib.org (consulté le 3 mai 2022).
- ↑ « matplotlib.lines.Line2D », sur Matplotlib.org (consulté le 3 mai 2022).
- ↑ voir (en) « Specifying colors », sur Matplotlib (consulté le 30 mars 2019).
- ↑ « matplotlib.axes.Axes.set_aspect », sur Matplotlib.org (consulté le 3 mai 2022)
- ↑ « matplotlib.transforms », sur Matplotlib.org (consulté le 14 avril 2023).