2  Figures et mise en page

Ce chapitre documente l’insertion de figures statiques, la génération de figures par code Python, la mise en page multi-colonnes, et le cas particulier des figures PDF-only (TikZ, PGFplots).

2.1 Image statique avec caption et cross-référence

La syntaxe de base pour insérer une image est :

![Légende de la figure.](../../../images/mon-image.png){#fig-label width=80%}

L’identifiant #fig-label permet de faire une cross-référence avec @fig-label. L’attribut width accepte des pourcentages ou des valeurs absolues (5cm, 0.5\linewidth).

Voici un exemple avec le logo du cnam :

![Le logo officiel du Cnam.](../../../images/Cnam.jpg){#fig-logo-cnam width=40%}
Figure 2.1: Le logo officiel du cnam.

La Figure 2.1 montre le logo officiel du cnam, chargé depuis le dossier images/ à la racine du projet.

AstuceFormats d’images recommandés
  • PDF : privilégier les formats vectoriels .pdf ou .eps pour les schémas et graphiques (net à toutes résolutions). Pour les photos, .png ou .jpg en 300 dpi minimum.
  • HTML : tous les formats web standards (.png, .jpg, .svg). Les .svg sont particulièrement adaptés pour les schémas.
  • Quarto gère automatiquement la conversion des formats selon la cible de rendu.
AvertissementChemins relatifs au fichier .qmd, pas à la racine

Les chemins d’images sont relatifs à l’emplacement du fichier .qmd. Depuis content_fr/chapitres/, le dossier images/ à la racine est à ../../images/monfichier.png. Ce comportement est identique en PDF et en HTML.

2.2 Figures générées par code Python

Quarto peut exécuter des cellules Python (via Jupyter) et inclure leur sortie graphique comme figures numérotées. La syntaxe du chunk utilise des options préfixées par #| :

```{python}
#| label: fig-sincos
#| fig-cap: "Courbes $\\sin(x)$ et $\\cos(x)$ sur $[0, 2\\pi]$."
#| echo: true
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2 * np.pi, 300)
fig, axes = plt.subplots(1, 2, figsize=(8, 3))
axes[0].plot(x, np.sin(x), color='#d20025')
axes[0].set_title(r'$\sin(x)$')
axes[1].plot(x, np.cos(x), color='#005EA5')
axes[1].set_title(r'$\cos(x)$')
for ax in axes:
    ax.set_xlabel('$x$')
    ax.grid(True, alpha=0.3)
plt.tight_layout()
```

Rendu :

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2 * np.pi, 300)
fig, axes = plt.subplots(1, 2, figsize=(8, 3))
axes[0].plot(x, np.sin(x), color='#d20025')
axes[0].set_title(r'$\sin(x)$')
axes[1].plot(x, np.cos(x), color='#005EA5')
axes[1].set_title(r'$\cos(x)$')
for ax in axes:
    ax.set_xlabel('$x$')
    ax.grid(True, alpha=0.3)
plt.tight_layout()
Figure 2.2: Courbes \sin(x) et \cos(x) sur [0, 2\pi].

La Figure 2.2 est générée à chaque compilation. Avec execute: freeze: auto dans _quarto.yml, Quarto met en cache les résultats dans _freeze/ et ne réexécute le code que si le chunk a changé — utile pour les figures longues à calculer.

Avertissementplt.tight_layout() est essentiel

Sans plt.tight_layout(), les étiquettes des axes se chevauchent fréquemment dans le PDF. Terminez toujours vos figures matplotlib par cette ligne.

Astuceecho: false pour le document final

Pendant la rédaction, echo: true affiche le code — pratique pour la relecture. Pour la version soumise à l’école doctorale, passez les chunks de figures en #| echo: false pour n’afficher que le graphique.

2.3 Mise en page multi-colonnes

La directive layout-ncol place plusieurs figures côte à côte. On l’applique à un div contenant des sous-figures :

::: {#fig-duo layout-ncol=2}

```{python}
#| label: fig-duo-a
#| fig-cap: "Fonction $x^2$"
import matplotlib.pyplot as plt, numpy as np
x = np.linspace(-2, 2, 200)
plt.plot(x, x**2, color='#d20025'); plt.grid(True, alpha=0.3); plt.tight_layout()
```

```{python}
#| label: fig-duo-b
#| fig-cap: "Fonction $\\sqrt{|x|}$"
import matplotlib.pyplot as plt, numpy as np
x = np.linspace(-2, 2, 200)
plt.plot(x, np.sqrt(np.abs(x)), color='#005EA5'); plt.grid(True, alpha=0.3); plt.tight_layout()
```

Deux fonctions élémentaires.
:::

Rendu :

import matplotlib.pyplot as plt, numpy as np
x = np.linspace(-2, 2, 200)
plt.plot(x, x**2, color='#d20025'); plt.grid(True, alpha=0.3); plt.tight_layout()
import matplotlib.pyplot as plt, numpy as np
x = np.linspace(-2, 2, 200)
plt.plot(x, np.sqrt(np.abs(x)), color='#005EA5'); plt.grid(True, alpha=0.3); plt.tight_layout()
(a) Fonction x^2
(b) Fonction \sqrt{|x|}
Figure 2.3: Deux fonctions élémentaires.

La Figure 2.3 regroupe les deux sous-figures Figure 2.3 (a) et Figure 2.3 (b). La dernière ligne de texte dans le div devient la légende globale.

2.4 Figures PDF-only (TikZ, PGFplots)

Certaines figures complexes ne peuvent être générées qu’en LaTeX (TikZ, PGFplots, circuitikz…). On les insère via un bloc {=latex} dans un div figure, accompagné d’un contenu de remplacement visible en HTML :

:::{#fig-tikz fig-pos='h'}
```{=latex}
\centering
\begin{tikzpicture}
  \draw[thick, ->] (0,0) -- (3,0) node[right] {$x$};
  \draw[thick, ->] (0,0) -- (0,2) node[above] {$y$};
  \draw[blue, thick] plot[domain=0:2.8, samples=50] (\x, {sin(\x r)});
\end{tikzpicture}
```

::: {.content-visible when-format="html"}
*(Figure TikZ — disponible dans la version PDF uniquement)*
:::

Exemple de figure TikZ insérée en LaTeX brut.
:::

Rendu :

(Figure TikZ — disponible dans la version PDF uniquement)

Figure 2.4: Exemple de figure TikZ insérée en LaTeX brut.
AstuceAlternative : compiler la figure TikZ en PDF séparé

Pour les figures TikZ complexes, une approche plus robuste consiste à les compiler en fichier .pdf standalone, puis à les inclure comme une image normale :

![Légende.](figures/mon-schema-tikz.pdf){#fig-tikz width=80%}

Cela évite les problèmes de packages en conflit et accélère la compilation.

2.5 Positionnement des flottants (PDF)

En LaTeX, les figures et les tables sont des flottants : LaTeX décide de leur position pour obtenir la meilleure mise en page possible. L’attribut fig-pos (figures) ou tbl-pos (tables) permet de lui donner des instructions.

![Légende.](../../../images/Cnam.jpg){#fig-ex fig-pos='tb'}

Les spécificateurs se combinent librement dans une chaîne :

Spécificateur Signification
h here — à l’endroit exact dans le texte (si la place le permet)
t top — en haut de la page courante ou suivante
b bottom — en bas de la page courante ou suivante
p page — sur une page dédiée aux flottants
! Ignore les contraintes internes de LaTeX (densité, nombre de flottants)
H Force le placement ici, sans aucun flottement (nécessite \usepackage{float})

La valeur par défaut de Quarto est tbp. Pour un chunk Python, le spécificateur se passe en option de cellule :

```{python}
#| label: fig-python
#| fig-cap: "Ma figure."
#| fig-pos: 'h'
```

Pour définir un spécificateur par défaut sur tout le document, ajouter dans _quarto.yml :

fig-pos: 'H'
Avertissementh n’est pas une garantie

Le spécificateur h demande à LaTeX de placer le flottant ici si possible, mais LaTeX peut l’ignorer si la place est insuffisante. La combinaison ht (ici, puis haut de page) est généralement plus robuste. H force le placement sans condition, mais peut créer des pages presque vides si la figure est grande — à réserver aux cas où la position est vraiment critique.

NoteLes flottants ne s’appliquent qu’au PDF

En HTML, fig-pos et tbl-pos sont ignorés : les figures et tableaux sont insérés dans le flux du document à leur point d’insertion, comme tout autre élément.