Bash : Utiliser gnuplot pour automatiser le tracé de courbes

Partager cet article

Temps estimé pour la lecture de cet article : 31 min

Introduction

Salut tout le monde, me revoilà après une petite pause mais comme on dit mieux vaut tard que jamais :3 !

Gnuplot est un logiciel qui sert à produire des représentations graphiques en deux ou trois dimensions de fonctions numériques ou de données. Un exemple concret ça peut être tout simplement le nombre de visiteurs sur votre site sur un an. On pourrait obtenir alors quelque chose du genre :

gnuplot-example-curve

Vous me direz, quel est l’intérêt, quand on a excel pour faire ça ? Tout simplement, on peut imaginer utiliser ce genre d’outil lors de développements en faisant appel à un simple script !

Pré-requis bash

gnuplot-bash-minmax

Afin d’automatiser le script que l’on va vouloir exécuter, il va nous falloir utiliser un peu de bash. Pourquoi ? Tout simplement pour pouvoir lire le fichier contenant les données. On pourrait bien sur également lancer le script bash depuis un programme et fournir comme argument les données.

Ici on va partir du fichier de données ci-contre :

1 158    
2 257    
3 512		
4 854		
5 698	
6 956	
7 1102
8 1158
9 1459
10 1523
11 2875
12 2431

Pas grand-chose à expliquer, on fait concorder un mois (ici représenté par un numéro, du coup 12 ce n’est pas mal, sisi je vous assure :3) à un nombre de visites. Magnifique, n’est-ce pas ?

Récupération de l’intervalle

Afin de dessiner nos courbes, on a besoin de connaître la valeur minimale et maximale de chaque axe. Pour ce faire, nous allons combiner 3 fonctions de bash à savoir : sort, sed et cut.

Commençons par trier le fichier par colonne de manière numérique (le -g).pour se faire on exécute cette commande :

sort -g stats.dat

Ensuite, on va utiliser la commande grep afin de récupérer la première valeur et la dernière valeur de notre sortie, comme ici on a trié le tout grâce au sort, on récupère bien la valeur minimale et maximale. Ce qui nous donne :

sort -g stats.dat | sed -n '1p;$p' 

Enfin, pour conserver uniquement une colonne donnée, on va utiliser la commande cut et préciser comme délimiteur un espace. Faites bien attention, quand vous allez remplir votre fichier, s’il n’y a ne serait-ce qu’une différence, par exemple une tabulation au lieu d’un espace, cut ne s’appliquera plus ou mal. Une fois que c’est bon on récupère le tout dans une variable et on prêt à dessiner notre courbe.

vals=($(sort -g stats.dat | sed -n '1p;$p' | cut -d' ' -f1))

Personnellement, afin de faire en sorte que l’affichage soit meilleur, je soustrais une petite valeur à mes valeurs afin de ne pas faire coller la courbe au bord de l’image, en réalisant une simple soustraction. Par exemple, ici pour le ymax, j’ajoute 500, afin de permettre à la courbe de ne pas coller au maximum des ordonnées.

Attention, si vous avez des nombres flottants, bash à un peu de mal avec ces nombres. On peut alors utiliser le programme bc (calculatrice en ligne de commande) afin de faire le calcul pour nous :

vmax=`echo "${vals[1]} + 5" | bc -l`

Utilisation de gnuplot

Dessiner une courbe avec gnuplot

Pour dessiner une courbe avec gnuplot, il suffit d’exécuter la commande plot, on peut alors préciser différentes options pour donner l’allure de la courbe.

plot 'stats.dat' with linespoints ls 1

Ici je lie simplement les points avec des lignes mais on peut également préciser une courbure grâce à la commande : smooth [bezier, sbezier, csplines, acsplines].

  • L’option csplines permet de connecter tous les points entre eux et de lisser le résultat.
  • L’option acsplines permet de dessiner une approximation d’une courbe basée sur les données.
  • L’option bezier permet de dessiner une courbe qui ne sera pas interpolée mais par contre les données seront lissées. Les points ne sont pas apparents sur cette option.

Jouer avec les options de gnuplot

On peut par la suite préciser un titre et des légendes pour les ordonnées et les abscisses grâce aux options : xlabel et ylabel.

set title '$1'
set ylabel 'Nombre de visiteurs unique'
set xlabel 'Mois'

On peut bien sur préciser l’intervalle désiré entre les données (qu’on ne se soit pas embêté pour rien quand même :p), pour ce faire, on utilise les options xr et yr (le r signifiant range).

set xr [$xmin:$xmax]
set yr [$ymin:$ymax]

On peut également gérer la distance entre différents tics (les petits tirets visibles sur chaque axe) et on peut bien sûr les cacher si désirés :

set xtic auto
set ytic auto

Pour les cacher il suffit d’utiliser la commande : unset [xtics|ytics]. Par défaut gnuplot, affiche une légende pour chaque courbe, quand il y en a une seule je ne trouve pas cela pertinent pour cacher la dites légende, il faut faire :

set nokey

Enfin on précise qu’on veut que le fichier de sortie soit une image :

set output 'curve.png'

Avec ça, vous devriez avoir les bases pour gérer vos graphiques, pour plus de commandes je vous propose d’aller voir directement l’ami du développeur la documentation. Passons maintenant à la personnalisation des couleurs et des polices utilisées.

Personnaliser l’apparence d’une courbe

Il est également possible de gérer comme on le désire la couleur des courbes, du fond et même la couleur et la police que l’on désire utiliser. L’option terminal permet de changer justement l’apparence des courbes, il existe plusieurs types de terminaux : png, svg, postscript ou encore epslatex. Ici, comme je compte juste faire une rapide présentation, je vous laisse suivre ce tutoriel si vous voulez plus de détails.

Nous allons, nous intéresser au type png. On peut donc préciser la taille de l’image de sortie, grâce à l’option size. On peut préciser le fond de l’image, ici on peut le faire blanc, mais on pourrait également donner un fond dépendant d’une couleur rgb. Ce qui nous donne cette commande :

set terminal png size 800,500 enhanced background rgb 'white'

Comme je le disais on peut également changer la fonte de manière globale, en précisant l’option font [Verdana|…],[size]. Ce qui nous donne :

set terminal enhanced font 'Verdana,10'

Si on voulait juste appliquer la fonte, sur une commande donnée par exemple seulement pour le titre, l’on peut faire :

set title 'Test' font "Verdana,20"

Enfin, pour changer la couleur du tracé d’une courbe, on peut utiliser l’option set style line.

set style line 1 lt 1 lw 1.5 pt 3 linecolor rgb '#2b63ff'

On peut ainsi jouer sur :

  • Le type de ligne (line type : lt)
  • L’épaisseur de la ligne (line width : lw)
  • Le type de points (point type : pt)
  • La couleur de la ligne (linecolor)

Résultat final

Et si on remettait tout ça ensemble, voilà le script final. Comment ça fonctionne ? Afin d’automatiser le tout, le script va se charger de construire un fichier qui sera fourni à gnuplot, une fois l’image de sortie obtenue, on supprime le fichier obtenu. Pourquoi on fait comme ça ? Tout simplement pour éviter de devoir créer notre fichier, puis d’appeler gnuplot à chaque fois. Là le script se charge de tout 🙂 !

#!/bin/bash

a=($(sort -g stats.dat | sed -n '1p;$p' | cut -d' ' -f1))
xmin=$((${a[0]}))
xmax=$((${a[2]}))
  
b=($(sort -k2 -g stats.dat | sed -n '1p;$p' | cut -d' ' -f2))
ymin=0
ymax=`echo "${b[1]}+500" | bc -l`
    
echo "set terminal png size 800,500 enhanced background rgb 'white'" > gnuplot_script
echo "set style line 1 lt 1 lw 1.5 pt 3 linecolor rgb '#2b63ff'" >> gnuplot_script
echo "set output 'curve.png'" >> gnuplot_script
echo "set autoscale" >> gnuplot_script
echo "set xtic auto" >> gnuplot_script
echo "set ytic auto" >> gnuplot_script 
echo "set title '$1'" >> gnuplot_script
echo "set ylabel 'Nombre de visiteurs unique'" >> gnuplot_script
echo "set xlabel 'Mois'" >> gnuplot_script
echo "set xr [$xmin:$xmax]" >> gnuplot_script
echo "set yr [$ymin:$ymax]" >> gnuplot_script
echo "set nokey" >> gnuplot_script
echo "plot 'stats.dat' with linespoints ls 1" >> gnuplot_script
	 
gnuplot gnuplot_script 
rm gnuplot_script 

Et voilà !

1 comment

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.