Graphiques PGFPlots : légendes cheatées et boucles for

Comme on l’a vu précédemment, l’utilisation de TikZ/PGFplots permets d’obtenir rapidement des graphiques élégants et parfaitement intégrés dans le document maître $latex \LaTeX$. La gestion des légendes est par défaut assez intuitive. Je vais vous montrer dans ce billet comment avoir un contrôle total sur le contenu de ces-dites légendes. De plus, ce billet me servira de prétexte à l’utilisation de boucles for.

 

Prendre le contrôle de la légende

Dans 99 % des cas

En temps normal, il existe deux façons de préciser les entrées de la légende d’un environnement axis. Soit à la définition même de l’environnement :

\begin{axis}[legend entries={Courbe 1, Courbe 2}]
  \addplot{}  % Courbe 1
  \addplot{}  % Courbe 2
\end[axis]

ou après l’exécution de chaque \addplot :

\begin{axis}
  \addplot{}
    \addlegendentry{Courbe 1}
  \addplot{}
    \addlegendentry{Courbe 2}
\end{axis}

Les 1 % batards

Prenons un exemple simple, comme illustré ci-après :

Ensemble de courbes avec une légende personnalisée
Ensemble de courbes avec une légende personnalisée

Je pense que la problématique est assez simple : comment ajouter à la légende des courbes qui n’existent pas (courbes noires ici). Voici donc la solution :

\documentclass{minimal}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
 
\begin{document}
	\begin{tikzpicture}
		\begin{axis}[	xlabel={$x$}, ylabel={$y=f(x)$},
				legend style={at={(1,0)},anchor=south east},
				legend entries={$\sqrt{x+a}$, $\ln(x+a)$,	% Légende pour les fonctions
						$a=0$, $a=0.3$, $a=0.6$}	% Légende pour les paramètres
				]
			\addlegendimage{no markers,black}					% Image de la légende pour la première fonction
			\addlegendimage{no markers,black,dashed}				% Image de la légende pour la deuxième fonction
			\addplot+[mark=none] expression[domain=0:3,samples=100]{sqrt(x)};
			\addplot+[mark=none] expression[domain=0:3,samples=100]{sqrt(x+0.3)};
			\addplot+[mark=none] expression[domain=0:3,samples=100]{sqrt(x+0.6)};
			\pgfplotsset{cycle list shift=-3}					% Décrémente le compteur pour reinitialiser les styles par défaut
			\addplot+[mark=none,dashed] expression[domain=0:3,samples=100]{ln(x)};
			\addplot+[mark=none,dashed] expression[domain=0:3,samples=100]{ln(x+0.3)};
			\addplot+[mark=none,dashed] expression[domain=0:3,samples=100]{ln(x+0.6)};
		\end{axis}
	\end{tikzpicture}
\end{document}

A sa première exécution, la commande \addlegendimage va écraser l’image de la première entrée, la seconde exécution écrasera la suivante et ainsi de suite. Les arguments sont logiquement le style de l’image à ajouter, avec la même syntaxe que lors de la définition d’un \addplot. Si l’envie vous prenait d’utiliser le style d’une courbe déjà existante, sachez que vous pouvez donner un label à cette dernière (mettons « plot :JolieCourbe »), puis utiliser ce label :

\addlegendimage{/pgfplots/refstyle=plot:JolieCourbe}

Dans mon exemple, vous aurez noté la présence de «+» après les \addplot. Ils servent à préciser que seules les options définies entre crochets sont écrasées, les autres (telles que la couleur) restent définies automatiquement par PGFPlots.

On met ici a profit la coloration automatique de PGFPlots : à chaque \addplot, un compteur est incrémenté, et à chaque incrément est attribué une couleur, ce qui nous permet d’obtenir directeement le faisceau de courbes colorés. Pour forcer PGFPlots à réinitialiser ce compteur, donc à réappliquer le cycle de coloration au deuxième faisceau de courbe, c’est la commande suivante qui nous sauve :

\pgfplotsset{cycle list shift=-3}

Utilisation d’une boucle for

Première approche

Si on regarde un peu le code que je propose ci-avant, on remarque que les commandes sont assez répétitives, donc on est bien tentés d’utiliser une boucle pour raccourcir le code. Ce qui nous donnera donc :

\foreach \off in {0,0.3,...,0.6}{	% Tracé de la première fonction
	\addplot+[mark=none] expression[domain=0:3,samples=100]{sqrt(x+\off)};
}
\pgfplotsset{cycle list shift=-3}
\foreach \off in {0,0.3,...,0.6}{	% Tracé de la deuxième fonction
	\addplot+[mark=none,dashed] expression[domain=0:3,samples=100]{ln(x+\off)};
}

Si vous avez programmé un jour dans votre vie, alors vous n’aurez pas de difficulté à comprendre ce code. Dans l’absolu, j’aurais probablement pu faire ça en une seule boucle, mais pour une raison que ma raison ignore, la commande  \pgfplotsset ne semble pas passer dans une boucle…

Mais on peut quand même faire mieux !

Dans mon exemple, si on veut changer l’offset des fonctions, il suffit de changer les bornes de la boucle for… et penser à modifier la légende ! Pour faire ça plus proprement, on peut donc naturellement inclure les nouvelles entrées dans la boucle. Voici donc un exemple (complet) de solution pour réaliser ce miracle :

\begin{axis}[	xlabel={$x$}, ylabel={$y=f(x)$},
		legend style={at={(1,0)},anchor=south east}]
	\addlegendimage{no markers,black}	% Image de la légende pour la première fonction
		\addlegendentry{$\sqrt{x+a}$}
	\addlegendimage{no markers,black,dashed}% Image de la légende pour la deuxième fonction
		\addlegendentry{$\ln(x+a)$}
	\foreach \off in {0,0.3,...,0.6}{	% Tracé de la première fonction
		\addplot+[mark=none] expression[domain=0:3,samples=100]{sqrt(x+\off)};
		\edef\VariableTempo{$a=$\off}
		\expandafter\addlegendentry\expandafter{\VariableTempo}
	}
	\pgfplotsset{cycle list shift=-3}	% Décrémente le compteur pour reinitialiser les styles par défaut
	\foreach \off in {0,0.3,...,0.6}{	% Tracé de la deuxième fonction
		\addplot+[mark=none,dashed] expression[domain=0:3,samples=100]{ln(x+\off)};
	}
\end{axis}

La variable temporaire \VariableTempo nous est nécessaire ici pour la bonne exécution du code. PGFPlots est conçu de façon a parser dans un premier temps l’ensemble des commandes du code avant de lancer la boucle for, ce qui le conduit à une erreur si on tente (toujours dans mon cas) de balancer un \addlegendentry{$a=$\off} car la commande \off n’est pas encore définie ($latex \LaTeX$ nous retourne un « undefined command »)

 

Pour aller plus loin

  • Une autre façon de faire pour paramétrer la légende est de la créer de toute pièce, comme je l’avais expliqué ici.
  • Vous pouvez consulter la documentation officielle de PGFPlots ici (à partir de la page 175 en ce qui concerne les légendes, page 417 pour les boucles ).

Bonne compilation !