Dessiner avec Matplotlib

\(\newcommand{\ds}{\displaystyle}\) \(\newcommand{\Frac}{\ds\frac}\) \(\renewcommand{\r}{\mathbb{ R}}\) \(\newcommand{\C}{\mathbb{ C}}\) \(\newcommand{\n}{\mathbb{ N}}\) \(\newcommand{\z}{\mathbb{ Z}}\) \(\newcommand{\Q}{\mathbb{ Q}}\) \(\newcommand{\N}{\mathbb{ N}}\) \(\newcommand{\n}{\mathbb{ N}}\) \(\newcommand{\ol}{\overline}\) \(\newcommand{\abs}[1]{\left| \,{#1} \right|}\) \(\newcommand{\pv}{\;;\;}\) \(\newcommand{\ens}[1]{\left\{ {#1} \right\}}\) \(\newcommand{\mens}[1]{\setminus\left\{ {#1} \right\}}\) \(\newcommand{\Par}[1]{\left({#1}\right)}\) \(\newcommand{\pe}[1]{\left\lfloor {#1} \right\rfloor}\) \(\newcommand{\trans}[1]{\,^t\!{#1}}\)

Dessiner avec Matplotlib

Cours

Utilisation de Matplotlib dans ce cours

Matplotlib est une extension Python destinée à réaliser des visualisations de données statistiques. Toutefois, elle offre des primitives de dessin (lignes, ellipses, texte, etc) qui peuvent servir à illustrer des notions de programmation Python, pour générer des diagrammes, figures, motifs divers, typiquement ce genre de dessin :

../../../_images/matplotlib_triangles_emboites.png

La plupart des exercices de ce cours ne nécessitent que de savoir tracer des segments et des disques.

Environnements d’utilisation

Un environnement courant d’utilisation de Matplotlib est une feuille Jupyter Notebook :

../../../_images/matplotlib_jupyter_local.png

Ces feuilles peuvent s’utiliser :

  • soit en ligne, par exemple sur Google Colab ou Jupyter.org
  • soit en local (suite à une installation sur la machine que vous utilisez, soit réalisée par vous-même soit par un administrateur).

En local, on peut accéder à des feuilles Jupyter Notebook soit parce qu’on a installé directement l’environnement Jupyter ou encore on a installé la suite Anaconda.

Toujours en local, mais sans Jupyter Notebook, après installation de Matplotlib, on peut invoquer Matplotlib depuis un environnement classique d’utilisation de Python (comme Spyder, IDLE, VSCode, Pycharm, un éditeur de texte, etc). Les graphiques produits par Matplotlib sont alors visibles dans un logiciel de visualisation qui dépend du système utilisé, par exemple sous Windows, par défaut, c’est une fenêtre Tkinter :

../../../_images/matplotlib_idle_windows.png

Tout code de dessin dans ce cours importera Matplotlib sous la forme suivante :

import matplotlib.pyplot as plt

Installation de Matplotlib

Si on veut utiliser Matplotlib sur un site distant comme Google Colab alors Matplotlib est déjà installée.

Pour les 3 systèmes d’exploitation majoritaires, si vous avez déjà installé la suite Anaconda, alors le module Matplotlib est disponible et directement utilisable, dans leurs feuilles Jupyter Notebook ou dans la version de Spyder qu’Anaconda propose.

Pour installer sous Windows 10 :

  • taper cmd dans Cortana
  • ouvrir la ligne de commande proposée
  • y taper la commande suivante ci-dessous :
pip install matplotlib

Une fois la commande exécutée, l’installation de Matplotlib est effective (pas besoin de redémarrer). Vous pouvez la tester en exécutant le code suivant dans un éditeur de texte (par exemple, sous Windows, choisir, Démarrer > Python > IDLE) :

import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')
plt.show()

ce qui devrait afficher la figure suivante :

../../../_images/check_install.png

Sous Linux, c’est analogue, taper dans un terminal la commande suivante :

pip install matplotlib

ce qui installera Matplotlib sur votre système. Vous pouvez tester avec le même code que ci-dessus.

D’après la documentation de Matplotlib, sous Linux, il est possible d’installer Matplotlib via votre système de paquets (non testé).

Utilisation de Matplotlib sur Google Colab

Google Colab est un service gratuit mis à la disposition d’un utilisateur ayant un compte Google et permettant de programmer dans des feuilles Jupyter Notebook et exécutées sur l’infrastructure de Google.

Le module Matplotlib est immédiatement disponible sans même que vous ayiez besoin de l’installer. Voici un code simplissime de dessin, à exécuter dans une cellule :

import matplotlib.pyplot as plt

plt.plot([-3, 4], [3, -4],marker = 'o')

plt.axis('off')

Et voici une vue sur l’interface :

../../../_images/matplotlib_colab.png

On observera qu’avant de montrer le dessin, la sortie affiche 4 dimensions. Pour les cacher, il suffit de récrire le code comme suit :

import matplotlib.pyplot as plt

plt.plot([-3, 4], [3, -4],marker = 'o')

_ = plt.axis('off')

qui produit uniquement la figure :

../../../_images/matplotlib_colab_no_bb.png

Instruction de visualisation

Dans les feuilles Jupyter Notebook, et en particulier sur Google Colab, il n’est pas nécessaire de placer une instruction d’affichage pour que le résultat graphique soit visible.

Par exemple, le code suivant

import matplotlib.pyplot as plt

plt.plot([-3, 4], [3, -4],marker = 'o')

plt.axis('off')

affichera la figure demandée. Il n’est toutefois pas pénalisant d’écrire l’instruction d’affichage plt.show(), le programme réagira de la même façon que sans l’instruction. Sur ce point, l’éditeur Spyder a le même comportement.

En revanche, le même programme écrit dans d’autres interfaces (comme IDLE, VSCode, etc) ne montrera pas de sortie graphique. Pour l’obtenir, il faut écrire une instruction show, comme montré dans cet exemple, à la dernière ligne :

import matplotlib.pyplot as plt

plt.plot([-3, 4], [3, -4],marker = 'o')

plt.axis('off')
plt.show()

Système de repérage

Dans ce cours, Matplotlib est utilisé pour dessiner des motifs, figures géométriques, etc et qui, pour être compris, ne nécessitent pas la présence d’axes donnant les abscisses et ordonnées. Toutefois, pour construire ces objets, vous devrez utiliser le système d’axes rectangulaires fourni par Matplotlib. Dans la plupart des sorties graphiques de ce cours, le système de repérage sera rendu invisible grâce à la ligne de code :

plt.axis('off')

Vous pouvez rétablir ce système d’axes en désactivant avec un commentaire Python la ligne ci-dessus, ce qui donne :

# plt.axis('off')

ou encore en ne l’écrivant pas.

Voici un dessin rendu sans repère :

../../../_images/matplotlib_sans_repere.png

et le même mais avec repère activé :

../../../_images/matplotlib_avec_repere.png

Par ailleurs, le repère fourni par défaut par Matplotlib N’est PAS orthonomé (autrement dit, il n’a pas les mêmes unités sur les deux axes de coordonnées), ce qui peut entraîner, dans certains cas, des déformations perceptibles. Pour activer le repère orthonormé, on peut placer la ligne suivante dans le code :

plt.axis('equal')

Pour le dessin précédent, si cette ligne n’est pas présente, voilà le rendu que l’on obtient :

../../../_images/matplotlib_repere_non_ON.png

Pour information et test, voici le code utilisé pour générer les dessins ci-dessus :

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle

def disk(center, rad, **kwargs):
    circ=plt.Circle(center, rad, lw=0, **kwargs)
    plt.gca().add_patch(circ)

def line(A, B, **kwargs):
    plt.plot([A[0], B[0]],[A[1], B[1]], **kwargs)

def dot(A, **kwargs):
    plt.plot(*A, marker='o',**kwargs)

# --------- Code du dessin  --------------------------


disk((0,0), 2, color="black")
disk((8,0), 2, color= "black")
line((0,0), (8, 0), color="red")
dot((4,0), color="blue")

# -------- FIN du code du dessin --------------------

plt.axis('equal')
# plt.axis('off')
plt.savefig("fonctions_auxiliaires_matplotlib.png")
plt.show()

Tracé d’un segment, d’un point

Matplotlib ne dispose pas d’une simple fonction du genre line(A, B) qui construirait un segment d’extrémités A et B données. Pour tracer un segment, il faut utiliser la construction peu intuitive illustrée ci-dessous :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import matplotlib.pyplot as plt

# Le point A
xA, yA = (-5, 5)

# Le point B
xB, yB = (4, -4)

plt.plot([xA, xB], [yA, yB])

# plt.axis('equal')
# plt.axis('off')

plt.show()

et qui affiche le dessin suivant :

../../../_images/segment.png

On remarquera (ligne 9) que l’on donne à la fonction plot non pas les points A et B mais les abscisses puis les ordonnées de ces points.

Par ailleurs, je n’ai pas activé les lignes suivantes :

  • la ligne 11 : on se rend compte que le repère n’est pas orthonormé,
  • la ligne 12 : on peut lire les coordonnées des points A et B.

En utilisant des arguments nommés, on peut appliquer différentes options telles que :

  • la couleur avec color
  • l’épaisseur avec linewidth ou encore lw
  • le style de trait (pointillés variés) avec l’option linestyle ou encore ls
  • le canal de transparence avec alpha (un flottant entre 0 et 1)
  • les extrémités du segment sous forme de bulles avec marker='o', leur taille avec markersize, leur couleur mfc

Voci un exemple utilisant toutes ces options :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import matplotlib.pyplot as plt

# Le point A
xA, yA = (-5, 5)

# Le point B
xB, yB = (4, -4)

plt.plot([xA, xB], [yA, yB],
            color="orange", lw=10,
            alpha=0.5,
            marker="o", markersize=20, mfc="red", ls='dotted')

plt.axis('equal')
plt.axis('off')
plt.show()

et qui produit le dessin suivant :

../../../_images/options_segment.png
  • Lignes 10-12 : les options sont placées entre parenthèses sous forme d’arguments nommés. On peut en utiliser moins si on souhaite.

Le marqueur utilisé ci-dessus permet accessoirement de tracer une « bulle » en un point donné (c’est pratique pour se repérer dans un dessin). Exemple :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import matplotlib.pyplot as plt

plt.plot(0, 0, marker="o", color='red')
plt.plot(1, 0, marker="o", color='blue')
plt.plot(1, 1, marker="o", color='green')
plt.plot(0, 1, marker="o", color='yellow')

plt.axis('equal')
plt.axis('off')
plt.show()

qui produit le dessin suivant :

../../../_images/bulles_matplotlib.png

Noter (ligne 2 par exemple) la syntaxe plus simple qui n’utilise plus de listes de coordonnées mais directement la valeur de l’abscisse et de l’ordonnée.

Tracé d’un disque

Sous Matplotlib, on peut tracer assez naturellement un disque de centre et de rayon donnés :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot()

circ = plt.Circle((2,0), 4)
dot = plt.Circle((0,0), 0.2, color="red")

ax.add_patch(circ)
ax.add_patch(dot)

plt.axis('equal')
plt.axis('off')
plt.show()

qui affiche les deux disques ci-dessous

../../../_images/disque_matplotlib.png

Commentons le code :

  • ligne 3 : il faut créer une figure fig;
  • ligne 4 : dans fig, on crée un dessin ax ; ax est un nom de variable assez répandu pour désigner un dessin (subplot) et qui fait référence, dans le jargon de Matplotlib à axe (qui ne veut pas dire axe …) ;
  • ligne 6 : on crée un disque de centre le point (2, 0) et de rayon 4. Par défaut, le cercle est rempli, en la couleur par défaut, un bleu ;
  • ligne 7 : on crée un petit disque rouge (une « bulle » : le rayon de 0.2 est petit) centré en l’origine ;
  • lignes 9-10 : on insère les disques dans le dessin ax (sinon, ils resteraient invisibles) :
  • ligne 12 : les axes sont orthonormés, sans cela les disques auraient une forme « ovale ».

On peut, bien sûr, tracer sur le même dessin à la fois des disques et des segments, par exemple :

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot()

circ = plt.Circle((2,0), 4)
ax.add_patch(circ)

A=(-2,0)
B=(6, 0)

plt.plot([A[0], B[0]],[A[1], B[1]], color="yellow")

plt.axis('equal')
plt.axis('off')
plt.show()

qui produit le dessin suivant :

../../../_images/segment_disques_matplotlib.png

Tracé d’un rectangle

Pour tracer un rectangle, on utilise la classe Rectangle, cf. cet exemple

from matplotlib.patches import Rectangle
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot()

xy=(-2,3)
w=4
h=2

rect = Rectangle(xy, w, h, color="gray")

ax.add_patch(rect)

plt.axis('equal')
plt.axis('off')
plt.show()

et qui produit la sortie graphique suivante :

../../../_images/matplotlib_rect.png

Le principe est que l’on fournit à Rectangle :

  • le point xy du rectangle situé en bas à gauche,
  • la largeur du rectangle et qui est la dimension horizontale
  • la hauteur du rectangle et qui est la dimension verticale
  • d’éventuelles options.

On comprend mieux la génération du rectangle si les axes de coordonnées sont tracés :

from matplotlib.patches import Rectangle
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot()

xy=(-2,3)
w=4
h=2

rect = Rectangle(xy, w, h, color="gray")

ax.add_patch(rect)

plt.axis('equal')

plt.show()

et qui produit la sortie graphique suivante :

../../../_images/matplotlib_rect_axes.png

On notera que, par défaut, l’intérieur du rectangle est rempli. Si ce n’est pas souhaité, utiliser l’option fill=False.

Tracé d’un secteur circulaire

Pour tracer un secteur circulaire, on utilise la classe Wedge, cf. cet exemple :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import matplotlib.pyplot as plt
from matplotlib.patches import Wedge

fig = plt.figure(facecolor="black")
ax = fig.add_subplot()

centre=(2,0)
radius=2
start=25
end=360-start

pacman = Wedge(centre, radius, start, end, color="yellow")
ax.add_patch(pacman)

ax.set_facecolor("black")
plt.axis('off')
plt.axis('equal')
plt.savefig("pacman.png", facecolor="black")
plt.show()

et qui produit la sortie graphique suivante :

../../../_images/pacman.png

Dans le code ci-dessus, facecolor fait référence à la couleur de fond.

Tracer un polygone

On peut tracer un polygone avec le constructeur Polygon en donnant une liste de points en coordonnées :

from matplotlib.patches import Polygon
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot()

A=(0,0)
B=(0,5)
C=(1,5)
D=(1,1)
E=(3.5, 1)
F=(3.5,0)
polygon = Polygon([A, B, C, D, E, F], fill=False)
ax.add_patch(polygon)

A=(4,0)
B=(4,5)
C=(5,5)
D=(5,1)
E=(7.5, 1)
F=(7.5,0)
polygon = Polygon([A, B, C, D, E, F])
ax.add_patch(polygon)


plt.axis('equal')
plt.axis('off')
plt.show()
../../../_images/polygones.png

Par défaut, le polygone est rempli par la couleur par défaut. Pour ne pas remplir, placer l’option fill à False. Pour obtenir juste une ligne polygonale, utiliser l’argument nommé closed=False.

Tracer un arc de cercle ou d’ellipse

On peut tracer des arcs d’ellipse avec la classe Arc, en particulier des arcs de cercles. Exemple :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import matplotlib.pyplot as plt
from matplotlib.patches import Arc

fig = plt.figure(figsize=(10,5))
ax = fig.add_subplot()

A=(2,3)
R=5

arc = Arc(A, 2*R, 2*R,  theta1=30, theta2=180.0,lw=3)
ax.add_patch(arc)

arc = Arc(A, 2*R, R,  theta1=30, theta2=180.0,lw=3, edgecolor="blue")
ax.add_patch(arc)

plt.plot(*A, marker="o", color='black')
plt.axis('on')
plt.axis('equal')

plt.show()
../../../_images/arcs_cercle_ellipse.png

Le premier argument est le centre de l’ellipse ou du cercle. Les deux arguments suivants sont la longueur de l’axe horizontal et la longueur de l’axe vertical. Si ces longueurs sont égales, l’ellipse est un cercle et la longueur commune est son diamètre (et pas son rayon).

Ensuite, viennent des arguments nommés qui sont des angles par rapport au premier axe de coordonnées : le début de l’arc theta1 et la fin de l’arc theta2. Les angles sont donnés en degrés.

Tracer une ellipse

On peut tracer une ellipse avec la classe Ellipse. Les axes de l’ellipses sont parallèles aux axes de coordonnées. Exemple :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse

fig = plt.figure()
ax = fig.add_subplot()

shape = Ellipse((0,0), 10, 5)
ax.add_patch(shape)

plt.axis('equal')
plt.axis('on')
plt.show()
../../../_images/ellipse_mpl.png

Le premier argument est le centre de l’ellipse. Les deux arguments suivants sont la longueur de l’axe horizontal et la longueur de l’axe vertical. Si ces longueurs sont égales, l’ellipse est un cercle et la longueur commune est son diamètre (et pas son rayon).

Texte basique

Pour tracer un texte simple, utiliser la fonction text :

import matplotlib.pyplot as plt
plt.plot(0, 0, marker = 'o')
plt.text(0, 0, "Hello!", fontsize=12, weight="bold")

plt.show()

qui affiche

../../../_images/texte_matplotlib.png

On observera la position de la boîte de texte par rapport au point fourni à la fonction, dans l’exemple c’est le point (0, 0).

Utiliser des fonctions comme raccourci de code

Pour éviter la syntaxe peu naturelle de tracé de segment et d’écrire l’inclusion obligatoire de l’objet de type Circle dans le dessin courant, on peut créer ses propres fonctions.

Voici une possibilité :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle

plt.gcf().set_size_inches(12,12)

def disk(center, rad, **kwargs):
    circ=plt.Circle(center, rad, lw=0, **kwargs)
    plt.gca().add_patch(circ)

def line(A, B, **kwargs):
    plt.plot([A[0], B[0]],[A[1], B[1]], **kwargs)

def dot(A, **kwargs):
    plt.plot(*A, marker='o',**kwargs)

def rect(xy, w, h, **kwargs):
    my_rect = Rectangle(xy, w, h,**kwargs)
    plt.gca().add_patch(my_rect)

# --------- Code du dessin  --------------------------

rect((-2, -2),12, 4)
disk((0,0), 2, color="black")
disk((8,0), 2, color= "black")
line((0,0), (8, 0), color="red")
dot((4,0), color="blue")

# -------- FIN du code du dessin --------------------

plt.axis('equal')
plt.axis('off')
plt.show()

code qui produit le dessin suivant :

../../../_images/fonctions_auxiliaires_matplotlib.png

La ligne 4 permet de modifier la taille du dessin (ci-dessus 12 pouces x 12 pouces). Les lignes 1-20 et 28-32 peuvent être incluses dans tout fichier qui utilise Matplotlib pour faire du dessin. Il suffit d’écrire son code dans les lignes 21-27 et le code devient alors nettement plus simple à produire.

Les paramètres du type **kwargs permettent d’utiliser, si on en a besoin, les arguments nommés autorisés ( comme color) et vus précédemment.

Modifier la taille de la figure courante

Une figure Matplotlib a une taille par défaut (en pouces, 6,4 x 4,8). On peut modifier la taille de cette figure avec l’argument nommé figsize, par exemple :

import matplotlib.pyplot as plt

plt.plot([-3, 4], [3, -4],marker = 'o')
plt.show()

plt.figure(figsize=(8,6))
plt.plot([-3, 4], [3, -4],marker = 'o')
plt.show()

dont voici une vue dans une feuille Jupyter :

../../../_images/figsize.png

Le premier dessin a la taille par défaut.

Le second a pour taille (8, 6).

Les couleurs sous Matplotlib

Il existe de nombreuses façons de transmettre des couleurs à des options Matplotlib.

Les couleurs nommées

La façon la plus simple de transmettre les couleurs est d’utiliser une chaîne de caractères donnant le nom anglais d’une couleur (courante), typiquement yellow ou blue :

import matplotlib.pyplot as plt

plt.plot((-5, 5), (4, -4), color="red")

plt.show()
../../../_images/couleur_chaine.png

Le nom de couleur n’est pas sensible à la casse, autrement dit, il est indifférent d’écrire "YeLLow" ou "yellow".

Au-delà des couleurs courantes, on peut utiliser les noms de couleurs utilisées dans des feuilles de style CSS, par exemple, on peut utiliser la couleur "MediumTurquoise".

Les couleurs par défaut

Quand une couleur est prévue et qu’elle n’est pas communiquée, une couleur par défaut existe, le plus souvent un bleu proche du bleu acier, appelé parfois strong blue, utilisable dans du code Matplotlib par la chaîne littérale "tab:blue". Attention, parfois, les couleurs par défaut suivent un cycle :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import matplotlib.pyplot as plt

plt.figure(figsize=(15,5))

for i in range(20):
        plt.plot(i, 0, marker="o", markersize=30)

plt.axis('equal')
plt.axis('off')
plt.show()
../../../_images/alt_couleur.png

Les couleurs RGB

On peut aussi transmettre une couleur au format RGB, avec une syntaxe décimale ou hexadécimale, voici un exemple :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot()


circ1 = plt.Circle((4,0), 2, color="#D2691E")

r=210/255
g=105/255
b=30/255

circ2 = plt.Circle((0,0), 2, color=(r, g, b))

ax.add_patch(circ1)
ax.add_patch(circ2)


plt.axis('equal')
plt.axis('off')
plt.show()
../../../_images/rgb_mpl.png

Les nuances de gris

Un gris en RGB se code avec une seule couleur, entre le noir, codé par 0 et le blanc, codé par 1. Exemple avec deux disques gris :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot()


circ1 = plt.Circle((4,0), 2, color="0.25")
circ2 = plt.Circle((0,0), 2, color="0.55")

ax.add_patch(circ1)
ax.add_patch(circ2)


plt.axis('equal')
plt.axis('off')
plt.show()
../../../_images/gris_mpl.png

Pour les détails sur le passage des couleurs, on pourra consulter l”aide officielle.

Placer une couleur de fond

Il peut être souhaitable qu’une figure porte une couleur de fond, par exemple, pour qu’elle se distingue bien de son environnement d’affichage. Il existe une option pour cela :

import matplotlib.pyplot as plt

fig = plt.figure()
fig.patch.set_facecolor('lightyellow')

plt.plot((-5, 5), (4, -4))

plt.axis('off')
plt.show()
../../../_images/couleur_fond.png

Si les axes sont activés, cette couleur de fond ne s’applique qu’à l’extérieur du rectangle de repérage :

import matplotlib.pyplot as plt

fig = plt.figure()
fig.patch.set_facecolor('bisque')

plt.plot((-5, 5), (4, -4))

plt.axis('on')
plt.show()

ce qui est assez compréhensible.

../../../_images/couleur_fond_axes.png

Sauvegarder le dessin dans un fichier png

Il est possible de sauvegarder la production graphique dans un fichier png. Voici un exemple de code qui réalise cette tâche :

import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')

plt.savefig("exporter_code_matplotlib.png")

ce qui va créer dans le répertoire d’où a été lancé Python un fichier, nommé ici exporter_code_matplotlib.png. Il existe différentes options que l’on peut consulter ici. Par exemple, pour modifier la résolution, on utilisera l’option dpi :

import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')

plt.savefig("exporter_code_matplotlib.png", dpi=120)

Pour ajuster le contenu de l’image par rapport au bord, on pourra jouer sur l’option bbox_inches ; en particulier, l’option bbox_inches='tight' semble ajuster serré le contenu de l’image mais l’ajustement peut aussi nécessiter de jouer sur la taille de l’image via l’option (de figure) set_size_inches.

Fonctions prêtes à l’emploi

Voici quelques fonctions qui facilitent l’usage de certaines primitives données par Matplotlib et décrites ci-dessus.

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle, Arc, Polygon, Wedge, Ellipse

# Choisir la taille voulue
plt.gcf().set_size_inches(10,5)

def disk(center, rad, **kwargs):
    circ=plt.Circle(center, rad, lw=0, **kwargs)
    plt.gca().add_patch(circ)

def line(A, B, **kwargs):
    plt.plot([A[0], B[0]],[A[1], B[1]], **kwargs)

def dot(A, **kwargs):
    plt.plot(*A, marker='o',**kwargs)

def rect(xy, w, h, **kwargs):
    my_rect = Rectangle(xy, w, h,**kwargs)
    plt.gca().add_patch(my_rect)

def circle_arc(center, R,  theta1, theta2, **kwargs):
    arc = Arc(center, 2*R, 2*R,  theta1=theta1, theta2=theta2, **kwargs)
    plt.gca().add_patch(arc)

def polygon(L, **kwargs):
    my_polygon = Polygon(L, **kwargs)
    plt.gca().add_patch(my_polygon)

def wedge(centre, radius, start, end, **kwargs):
    my_wedge = Wedge(centre, radius, start, end, **kwargs)
    plt.gca().add_patch(my_wedge)

def ellipse(center, w, h, **kwargs):
    ell=Ellipse(center, w, h,  **kwargs)
    plt.gca().add_patch(ell)

# --------- Code du dessin  --------------------------




# -------- FIN du code du dessin --------------------

plt.axis('equal')
plt.axis('off')
plt.show()

Vous écrivez votre code entre les lignes pointillés. Si vous le souhaitez, vous pouver supprimer les fonctions au-dessus des pointillés et qui ne vous sont pas utiles.

Fonction addsubplot et version de Matplotlib

Sous certaines versions de Matplotlib, l’usage de add_subplot peut échouer comme dans l’exemple ci-dessous :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot()

circ = plt.Circle((2,0), 4)
dot = plt.Circle((0,0), 0.2, color="red")

ax.add_patch(circ)
ax.add_patch(dot)

plt.axis('equal')
plt.axis('off')
plt.show()
15
'NoneType' object has no attribute "add_patch"

car fig.add_subplot() ligne 4 renvoie None. Comme indiqué dans ce message, cela se produit pour des versions de Matplotlib strictement antérieure à 3.1 (2019). Pour y remédier, c’est très simple, il suffit de changer la ligne 4 par

ax = fig.add_subplot(1,1,1) voire ax = fig.add_subplot(111)

qui fonctionne aussi avec les versions plus récentes de Matplotlib.

Pour connaître votre version de Matplotlib, lancez le code suivant :

import matplotlib as mpl
print(mpl.__version__)
3.0.2

Exercices

Quelques marches

Imaginez une maison. Dessinez le sol avec un escalier à 5 marches suivi du sol de l’étage (ne pas dessiner la maison). Utiliser une variable pour désigner la hauteur et le profondeur de chaque marche. Vous pouvez aussi introduire des variables x et y pour désigner les coordonnées de la marche courante.

../../../_images/mpl_marches.png

Découper un carré

Dessiner un carré découpé en huit secteurs égaux.

../../../_images/mpl_carre_en_8.png

Cube

Dessiner un cube

../../../_images/cube.png

dont la représentation dépendra de deux variables c (le côté du carré de la face avant) et h la « hauteur » apparente la face supérieure. Si possible, faites en sorte que tous les angles aigus de la représentation soient à 45°.

Dessiner un signe plus

Dessiner une croix sous la forme d’un signe +. La zone centrale de la croix sera un carré de côte de côté \(c\), chaque branche de la croix aura une longueur et une largeur valant encore \(c\).

../../../_images/plus.png

Enveloppes

Dans cet exercice, on s’efforcera d’utiliser des variables représentant les dimensions utiles au dessin.

  1. Dessiner une enveloppe vue de dos (avec le rabat) :

    ../../../_images/enveloppe-rabat-mpl.png
  2. Dessiner une enveloppe timbrée :

    ../../../_images/enveloppe-timbre-mpl.png

Rose des vents

Dessiner une rose des vents. Nommer les points nécessaires avec des variables. Il n’y a aucun calcul à faire, simplement bien observer les alignements et procéder par masquage. Utiliser l’outil Polygon. Les couleurs sont orange et bleu.

../../../_images/rose-des-vents.png

Centre de gravité

Soient les points \(\mathtt{a=(50,50)}\), \(\mathtt{b=(-200,-100)}\) et \(\mathtt{c=(300,-300)}\). L’abscisse d’un point m vaut \(\mathtt{m[0]}\) et l’ordonnée \(\mathtt{m[1]}\), par exemple :

a=(50, 50)
print(a[0])
print(a[1])
  1. Construire le triangle \(\mathtt{abc}\).

  2. Rappelons qu’une médiane d’un triangle est une droite qui joint un sommet et le milieu du côté opposé. On sait que les trois médianes se coupent en le centre de gravité du triangle (\(\mathtt{g}\) ci-dessous).

    Construire les médianes du triangle \(\mathtt{abc}\). On utilisera que si on a deux points représentés respectivement par les couples \(\mathtt{x}\) et \(\mathtt{y}\) alors le milieu est représenté par le couple :

    m=((x[0]+y[0])/2,(x[1]+y[1])/2)

    ../../../_images/mpl_medianes_gravite.png

Dessiner un huit

Dessiner le chiffre 8 en plaçant deux ellipses noires ayant une intersection commune et en les creusant avec deux ellipses blanches.

../../../_images/huit_mpl.png

Cadrer carré

On donne deux points distincts A et B, par exemple

../../../_images/diago_carre.png

et on cherche à construire la carré de diagonale le segment AB, comme ci-dessous :

../../../_images/cadrer_carre.png

Si M est un point, on note xM et yM ses coordonnées. Les points A et B sont donnés par leurs coordonnées. On admet que l’autre diagonale CD du carré est telle que

\(\mathtt{C=(xM-v, yM+u)}\) et \(\mathtt{D=(xM+v, yM-u)}\)

\(\mathtt{M}\) est le milieu du segment AB et \(\mathtt{(u,v)=\Frac 12\overrightarrow{AB}}\).

Connaissant les point A et B, on demande de dessiner le carré comme illustré ci-dessus où on avait choisi A = (-4,1) et B = (-3,-1) comme on le voit ci-dessous :

../../../_images/cadrer_carre_repere.png

Logos succès-échec

Dessiner côte-à-côte les deux logos suivants :

../../../_images/success_failure.png

La croix et la coche ne sont pas dessinées comme des polygones mais comme des lignes épaisses (utiliser line et son option lw). Utiliser des variables. On pourra utiliser une petite distance pour décaler la coche par rapport au centre du disque.

Danger nucléaire

Dessiner le logo « danger nucléaire » :

../../../_images/danger_nucleaire.png

Les secteurs angulaires mesurent 60°. On aura besoin de Circle et de Wedge.

Logo de Tripadvisor

Dessiner le logo de Tripadvisor :

../../../_images/tripadvisor.png

C’est un logo assez difficile à dessiner. Quelques conseils :

  • faites un croquis à main levée,
  • donnez des noms aux points utiles,
  • définissez toutes les variables utiles, elles sont très nombreuses.

La couleur verte est un vert perse, poser vert = "#00AF87".

Suggestion de plan de dessin à suivre :

  • Tracer le disque de fond
  • Dessiner les pointes gauche et droite des yeux à l’aide d’un triangle noir pour chaque oeil (fonction polygon)
  • Dessiner le front noir et vert avec deux quarts de disque superposés (fonction wedge)
  • Dessiner la pointe du nez (fonction polygon)
  • Dessiner les yeux (chaque oeil nécessite trois disques) avec la fonction disk.

Voici un lien vers une description géométrique du logo