Chapitre 8 : La visualisation de données avec Matplotlib

En ingénierie, obtenir un résultat numérique (comme "vitesse = 12.4 m/s") ne suffit rarement. Pour analyser le comportement d'un système (un planeur qui descend, un moteur qui chauffe), tu dois voir l'évolution des variables dans le temps.

C'est le rôle de la bibliothèque Matplotlib. C'est l'outil standard en Python pour transformer des listes de nombres en courbes lisibles et interprétables.

Dans ce chapitre, nous allons nous concentrer sur l'art de produire des graphiques scientifiquement valides (avec unités, légendes et échelles adaptées), une compétence indispensable pour tes rapports techniques.

Objectifs du chapitre

  • Comprendre la logique de tracé (Abscisse vs Ordonnée).
  • Respecter la norme ingénieur : Titre, Axes labellisés, Unités.
  • Savoir quand utiliser une ligne continue (modèle) ou des points (mesures).
  • Superposer plusieurs courbes pour comparer des résultats.
  • Créer des planches graphiques avec plusieurs fenêtres (Subplots).

1. Premier tracé : Le concept de base

Pour tracer une courbe, l'ordinateur a besoin de deux séries de nombres de même taille :

  1. Les valeurs pour l'axe horizontal (généralement le temps t ou la position x).
  2. Les valeurs pour l'axe vertical (la grandeur physique étudiée, ex: y).
Note sur les données
Pour les exemples ci-dessous, nous utilisons np.linspace juste pour générer rapidement des chiffres. Concentre-toi uniquement sur les commandes commençant par plt.
import matplotlib.pyplot as plt
import numpy as np

# ==========================================
# 1. GÉNÉRATION DES DONNÉES (L'ÉCHANTILLONNAGE)
# ==========================================
# Un ordinateur ne sait pas tracer une infinité de points.
# On doit "découper" l'axe X en morceaux.
# np.linspace(début, fin, nombre_de_points)
x = np.linspace(0, 10, 20)  # On demande 20 points précis entre 0 et 10

# ==========================================
# 2. CALCUL DU MODÈLE (VECTORISATION)
# ==========================================
# NumPy applique l'opération "au carré" sur les 20 points d'un seul coup.
y = x**2 

# ==========================================
# 3. VISUALISATION (LE TRACÉ)
# ==========================================
plt.figure(figsize=(8, 5))

# plt.plot(Axe_X, Axe_Y)
# L'argument '-o' est purement pédagogique ici : 
# '-'  : Relie les points par une ligne (ce qu'on veut habituellement)
# 'o'  : Affiche les points calculés (pour visualiser nos 20 points)
plt.plot(x, y, '-o', color='purple', label="Courbe y=x²")

# Même pour un exemple simple, on garde les bonnes habitudes :
plt.title("Visualisation de l'échantillonnage (20 points)")
plt.xlabel("Valeurs de x")
plt.ylabel("Valeurs de y")
plt.grid(True)
plt.legend()

plt.show()

2. L'Anatomie d'un graphique "Ingénieur"

Le graphique précédent est mathématiquement juste, mais techniquement inacceptable dans un rapport professionnel.

Pourquoi ? Parce qu'il est muet. En le regardant, personne ne peut dire si $x$ représente des secondes ou des kilomètres, ni si $y$ est une température ou une vitesse. Un chiffre sans unité n'a aucune valeur physique.

Pour qu'un graphique soit validé en sciences de l'ingénieur, il doit impérativement comporter ces 3 éléments :

  1. Des Labels d'axes (Grandeur + Unité) : C'est la règle absolue. Exemple : Temps (s) ou Vitesse (km/h).
  2. Un Titre explicite : On doit comprendre quel phénomène est simulé sans avoir besoin de lire le texte autour.
  3. Une Grille : Elle transforme un simple dessin en outil de mesure (pour lire la valeur précise à $t=3s$ par exemple).

Voici un exemple complet respectant ces règles, avec un modèle physique simple : la réponse indicielle d'un système du 1er ordre (ex: un moteur qui démarre).

import matplotlib.pyplot as plt
import numpy as np

# ==========================================
# 1. GÉNÉRATION DU MODÈLE PHYSIQUE
# ==========================================
# Simulation d'un système du 1er ordre (ex: moteur qui démarre)
t = np.linspace(0, 5, 50)       # 50 points de mesure sur 5 secondes
vitesse = 10 * (1 - np.exp(-t)) # Formule : Vmax * (1 - exp(-t))

# ==========================================
# 2. MISE EN PAGE "PROFESSIONNELLE"
# ==========================================
# On définit la taille de la figure (Largeur, Hauteur) en pouces.
# figsize=(10, 6) est un standard lisible pour un rapport A4.
plt.figure(figsize=(10, 6))

# Tracé de la courbe principale
# linewidth=2 : On épaissit le trait pour la lisibilité sur vidéoprojecteur
plt.plot(t, vitesse, color="red", linewidth=2, label="Réponse du système")

# (Bonus Pédagogique) : On trace l'asymptote pour montrer la cible
plt.axhline(10, color='grey', linestyle='--', label="Vitesse limite (10 m/s)")

# ==========================================
# 3. LES 3 COMMANDEMENTS DE L'INGÉNIEUR
# ==========================================
# Règle d'or : Un graphique doit être compréhensible SANS lire le texte autour.

# 1. LE TITRE : Doit décrire le phénomène physique
plt.title("Réponse indicielle : Vitesse du moteur en fonction du temps")

# 2. L'AXE X : Nom de la variable + (UNITÉ)
plt.xlabel("Temps (s)")

# 3. L'AXE Y : Nom de la variable + (UNITÉ)
plt.ylabel("Vitesse (m/s)")

# ==========================================
# 4. FINITIONS
# ==========================================
plt.grid(True) # Indispensable pour lire des valeurs précises (ex: à t=3s)
plt.legend()   # Affiche le nom des courbes (défini par label="...")

plt.show()

3. Modèle vs Mesures (Ligne ou Points ?)

Dans la vraie vie, on doit souvent comparer un modèle théorique à des données expérimentales. Par exemple, tu peux avoir un modèle mathématique prédisant l'allongement d'un ressort en fonction de la force appliquée, et des relevés de capteurs mesurant cet allongement dans la réalité.

Deux types de données coexistent alors :

Matplotlib permet de gérer cela via le paramètre de style (3ème argument de plot).

import matplotlib.pyplot as plt
import numpy as np

# ==========================================
# 1. SIMULATION DE L'EXPÉRIENCE (Loi de Hooke)
# ==========================================
# On imagine un ressort qu'on étire.
# x : La force qu'on applique (de 0 à 10 Newtons)
force_x = np.linspace(0, 10, 15)

# --- Le Monde Théorique (Maths parfaites) ---
# y = a*x + b
allongement_theorique = 2 * force_x + 1 

# --- Le Monde Réel (Expérience) ---
# En vrai, un capteur a toujours du bruit (erreurs de mesure).
# On ajoute un aléa (bruit gaussien) à notre théorie.
bruit = np.random.normal(0, 1, 15) 
allongement_mesure = allongement_theorique + bruit

# ==========================================
# 2. VISUALISATION : DISCRET vs CONTINU
# ==========================================
plt.figure(figsize=(8, 5))

# COURBE 1 : Les Mesures (La Réalité)
# Règle : On ne relie JAMAIS des points expérimentaux bruts par des lignes.
# On utilise un marqueur ('o') pour montrer que ce sont des relevés ponctuels.
plt.plot(force_x, allongement_mesure, 'o', color='black', label="Relevés capteurs (Points)")

# COURBE 2 : Le Modèle (La Théorie)
# Règle : Une loi physique est continue, elle existe partout.
# On utilise une ligne ('-') pour représenter la tendance parfaite.
plt.plot(force_x, allongement_theorique, '-', color='blue', linewidth=2, label="Modèle théorique (Ligne)")

# ==========================================
# 3. HABILLAGE DU RAPPORT
# ==========================================
plt.title("Comparaison Modèle vs Réalité (Essai de traction)")
plt.xlabel("Force appliquée (N)")
plt.ylabel("Allongement (mm)")
plt.grid(True)

# La légende est cruciale ici pour expliquer la différence Point/Ligne
plt.legend() 

plt.show()

4. Comparer plusieurs courbes (La Légende)

Si tu veux comparer la trajectoire de deux planeurs différents, tu dois tracer deux courbes sur le même graphique. L'astuce est d'appeler plt.plot deux fois avant de faire plt.show().

Pour que le lecteur s'y retrouve, tu dois ajouter l'argument label="Nom de la courbe" dans chaque plot, puis appeler plt.legend() à la fin.
import matplotlib.pyplot as plt
import numpy as np

# ==========================================
# 1. PRÉPARATION DES SCÉNARIOS (DONNÉES)
# ==========================================
# On veut comparer deux stratégies de tir différentes sur 20 mètres.
dist_sol = np.linspace(0, 20, 100) 

# Scénario 1 : Tir en cloche (Angle fort, monte haut)
alt_cloche = -0.05 * (dist_sol - 10)**2 + 5

# Scénario 2 : Tir tendu (Angle faible, rase le sol)
alt_tendu  = -0.02 * dist_sol**2 + 0.4 * dist_sol

# ==========================================
# 2. LA TECHNIQUE DE SUPERPOSITION
# ==========================================
plt.figure(figsize=(10, 6))

# Le principe : Tant qu'on ne fait pas plt.show(), Matplotlib dessine
# sur la même figure. On peut donc empiler les courbes.

# Courbe 1
plt.plot(dist_sol, alt_cloche, label="Tir A : En cloche (45°)", color='purple')

# Courbe 2
plt.plot(dist_sol, alt_tendu,  label="Tir B : Tendu (15°)",    color='orange')

# (Bonus) Ajout du sol pour le réalisme physique
plt.axhline(0, color='black', linewidth=2, label="Sol")

# ==========================================
# 3. L'IMPORTANCE DE LA LÉGENDE
# ==========================================
plt.title("Comparaison balistique : Influence de l'angle de tir")
plt.xlabel("Distance (m)")
plt.ylabel("Altitude (m)")
plt.grid(True)

# COMMANDE MAGIQUE :
# plt.legend() va scanner toutes les instructions 'plot' précédentes,
# récupérer les textes dans 'label="..."' et dessiner l'encadré explicatif.
plt.legend() 

# Astuce Pro : Force 1m en hauteur à être égal à 1m en largeur à l'écran.
# Sinon, Matplotlib déforme la courbe et la trajectoire semble fausse.
plt.axis('equal')

plt.show()

5. Les Subplots : Tableaux de bord

Parfois, les échelles sont trop différentes pour tout mettre sur le même graphique (exemple : comparer l'altitude en mètres et la vitesse en m/s). On utilise alors plt.subplots pour créer une grille de graphiques.

La syntaxe change légèrement : on ne travaille plus directement sur plt, mais sur des axes (ax) spécifiques.

import matplotlib.pyplot as plt
import numpy as np

# ==========================================
# 1. PRÉPARATION DES DONNÉES (Cinématique)
# ==========================================
t = np.linspace(0, 10, 100) # 10 secondes de mouvement

# Mouvement uniformément accéléré (ex: une voiture qui accélère)
position = t**2      # x(t) en mètres
vitesse  = 2*t       # v(t) en m/s

# ==========================================
# 2. CRÉATION DU TABLEAU DE BORD (Subplots)
# ==========================================
# Problème : On ne peut pas mélanger des mètres et des m/s sur le même axe Y.
# Solution : On découpe la feuille en 2 zones distinctes.

# fig : La feuille de papier entière.
# (ax_haut, ax_bas) : Les deux zones de dessin que l'on récupère.
# sharex=True : MAGIQUE ! Si on zoome sur le temps en haut, ça zoome aussi en bas.
fig, (ax_haut, ax_bas) = plt.subplots(2, 1, sharex=True, figsize=(8, 8))

# ==========================================
# 3. REMPLISSAGE DES ZONES
# ==========================================

# --- Zone 1 (Haut) : La Position ---
# Attention : Avec les subplots, la commande 'plt.title' devient 'ax.set_title'
ax_haut.plot(t, position, color='blue', linewidth=2)
ax_haut.set_title("Analyse Cinématique : Position et Vitesse") 
ax_haut.set_ylabel("Position (m)") # Unité Mètres
ax_haut.grid(True)

# --- Zone 2 (Bas) : La Vitesse ---
ax_bas.plot(t, vitesse, color='orange', linewidth=2)
ax_bas.set_ylabel("Vitesse (m/s)") # Unité Mètres/Seconde
ax_bas.grid(True)

# L'axe X (Temps) est commun, on ne l'affiche qu'en bas pour ne pas surcharger.
ax_bas.set_xlabel("Temps (s)")

# ==========================================
# 4. FINALISATION
# ==========================================
# Ajuste automatiquement les espaces pour que les titres ne se chevauchent pas
plt.tight_layout()

plt.show()

Synthèse

  • Initialisation : Toujours importer matplotlib.pyplot as plt.
  • Rigueur : Un graphique technique doit avoir un Titre, des Labels (avec unités) et une Grille.
  • Styles : Utilise des lignes ('-') pour les modèles et des marqueurs ('o') pour les points de mesure.
  • Légende : Utilise label="..." dans tes plots et finis par plt.legend().
  • Subplots : Utilise les sous-graphiques pour afficher des grandeurs d'unités différentes (position vs vitesse) sur une même page.