Découverte :
Introduction aux pipelines

Il vous est peut-être arrivé d'attendre qu'un logiciel A ait fini son travail pour pouvoir lancer un logiciel B, qui lui utilise la sortie du logiciel A. Si l'exécution de A ne prend que quelques secondes cela n'est pas trop grave. Par contre, si elle prend des heures et que vous devez vérifier régulièrement s’il a fini, cela peut très vite devenir fatigant. Une bonne solution serait de faire que le logiciel B s'exécute automatiquement quand A a fini et c'est cela que l'on appelle un pipeline. Aujourd'hui je vais éclaircir pour vous ce terme et donner quelque exemples, très simples, de pipelines sous GNU/Linux.

C'est quoi un pipeline?

Il s'agit d'un terme anglais, en informatique il désigne un groupe de logiciels exécutés en série de telle façon que la sortie d'un logiciel sert d'entrée pour le suivant. Il y a différents intérêts à la construction d'un pipeline. On peut par exemple chercher à exécuter à la chaîne une série de logiciels pouvant écrire sur la sortie standard et ainsi éviter de créer des fichiers intermédiaires. On peut également chercher à ce que toute une série de tâches s'exécutent les unes après les autres, sans intervention de l'utilisateur.

Dans sa forme la plus simple, le pipeline n'est qu'une chaîne où chaque logiciel attend la sortie du précédent, mais on peut construire des pipelines où plusieurs logiciels dépendent de la sortie d'un autre et vice-versa (cf. Shéma). Certains pipelines contiennent même des boucles pour vérifier si la commande précédente s'est bien exécutée, et si se n'est pas le cas, la relancer au lieu de lancer le logiciel suivant. La complexité augmente, bien sûr, avec le nombre d'étapes dans le pipeline et le nombre de connexions entre elles.

Pour illustrer la notion de pipeline, je vais vous présenter quelque exemples qui pourront vous servir pour des petites tâches de la vie de tous les jours (enfin, celle des bio-informaticiens).

 

Les logiciels 2 et 3 attendent le résultat du logiciel 1. Le logiciel 4 lui ,utilise les sorties des logiciels 2 et 3.

Premier pipeline sur sortie standard

Sous GNU/Linux il existe une façon très simple de faire un pipeline, en ligne de commande, avec le symbole pipe '|'.

Voici un petit exemple : dans un terminal, on peut rechercher une commande que l'on a tapée précédemment avec à la commande 'history', mais elle résume parfois des milliers de commandes et si celle que vous cherchez est la millième cela peut être difficile de la trouver. Du coup il serait bien de pouvoir chercher notre commande grâce à un mot qu'elle contient. On peut le faire avec la commande 'grep', qui permet de chercher un terme spécifique dans un texte et d'afficher la ou les lignes qui le contiennent. Un moyen simple de connecter ces deux commandes est d'utiliser le pipe et de construire notre premier pipeline.

Dans cet exemple, je recherche les commandes que j'ai utilisées avec le logiciel 'samtools':

 

Comme vous pouvez le voir, le chiffre en début de ligne indique la position où se trouvait chaque commande, je n'avais pas utilisé samtools depuis un petit moment et j'aurais eu de la peine à retrouver ma commande sans ce petit pipeline.

Une autre façon d'utiliser la sortie standard est de faire appel à la commande 'xargs'. Imaginons cette fois que je cherche un fichier et dont je veux afficher le début. Je peux utiliser la fonction 'find' pour trouver mon fichier et 'head' pour en afficher le début.

Essayons avec le pipe :

Et mince, 'head' imprime ici le début du résultat de notre commande 'find' et non pas le début du fichier. Il faut donc une méthode pour faire comprendre à 'head' que les information qu'on lui envoie doivent être utilisées comme argument et non pas comme simple texte. Utilisons xargs pour résoudre ce problème.

Et voilà problème résolu, la commande 'find' trouve mon fichier et la commande 'head' affiche les premières lignes. Si il y avait eu plusieurs fichiers, chacun d'entre eux aurait été envoyé à la commande 'head' et leurs débuts auraient été imprimés les uns à la suite des autres.

(Pour les plus curieux, on peut le faire aussi avec l'option '-exec' de la commande find, mais dans ce cas pas besoin de pipeline)

 

Pipeline avec fichiers intermédiaires

Les deux exemples précédents utilisaient la sortie standard comment entrée pour la commande suivante. Je vais maintenant vous montrer comment enchaîner deux commandes et utiliser un fichier créé par la première.

Dans votre terminal c'est en fait très simple, il suffit d'écrire les deux commandes sur une seule ligne, mais en les séparent avec un point-virgule.

Voici un petit exemple avec les commandes samtools que j'ai cherchées dans le premier exemple :

La première commande crée le fichier 'test_all.VIR.bam' et la deuxième le trie. Pour mettre un petit contrôle on peut par exemple écrire dans un fichier que la commande est terminée. Ici ce n'est pas bien important, mais imaginez-vous aligner six ou sept commandes pour comprendre l'importance de ce rapport d'exécution. En effet si une commande rencontre une erreur, alors toutes les suivantes ne seront pas exécutées.

Et voilà, les commandes vont s'exécuter les unes après les autres et si quelque chose se passe mal, je saurai à quel niveau, grâce à mon fichier de contrôle.


Les méthodes présentées dans cet article ne vous serviront pas pour construire un pipeline robuste, qui exécute à la suite toute l'analyse de vos données de séquençage. Vous pouvez utiliser pour cela des logiciels tel que Galaxy, déjà présenté sur le blog (Galaxy ). Mais il existe de nombreuses méthodes et je présenterai dans un prochain article comment utiliser le système de queue d'un cluster pour construire un pipeline plus complexe.

En attendant n'hésitez pas à faire part des méthodes que vous utilisez dans les commentaires et si l'envie vous en prend, faites un article et proposez-le aux admins, nous sommes toujours contents d'avoir de nouvelles méthodes à partager/publier.

Je tiens à remercier Yoann, Nolwenn et Nelly pour leur relecture.

  • À propos de
  • Après un stage à l'EMBL Heidelberg en 2010, où j'ai découvert le traitement des données de séquençage (NGS), j'ai travaillé 3 ans à Genève entre deux laboratoires du SIB. J'y ai principalement géré une grande quantité de données RNA-seq et mis en place plusieurs pipelines pour le traitement automatique de ces données. Depuis décembre 2013 je travaille à l'IGH Montpellier, notre groupe étudie les problèmes liés à la réplication dans les cellules tumorales.

6 commentaires sur “Introduction aux pipelines

  1. Les pipelines sont des éléments essentiels dans notre travail de tous les jours. Très bonne astuce pour conserver une trace des commandes exécutées.

    Merci

  2. J'ajouterais deux choses à cette articles si vous me le permettez :
    - l'utilisation de && en lieu et place des ; dans votre exemple permettrons de contrôler la bonne exécution de la commande précédente ($? == 0). Du coup, je pipeline s'arrête quand il rencontre une erreur sans lancer la suite (qui souvent en dépende)
    - la commande tee permet quant à elle de rediriger la stout de la commande précédente dans un fichier et dans le stdin de la commande suivant. Cela permet de créer facilement des fichiers intermédiaires sans "casser" le pipeline.

    GLC

    • Merci se sont d'exellent conseils.

      En effet dans mon exemple avec samtools, si la première commande ne fonctionne pas, la suivante va être lancé mais ne trouvera pas le fichier .bam. Il faut donc remplacer les ';' par '&&'. De plus cela aurait écrit dans le rapport que les 1 et 2 étaient terminées, ce qui est faux dans ce cas.

      Pour 'tee', je ne l'avais jamais utilisé, mais c'est effectivement très sympa.

      Pour les lecteurs, disont que dans le premier exemple, en plus d'afficher les commandes qui contiennent le mot 'samtools' je veux sauver mon historique dans un fichier, le tout en un seul pipeline, je peux le faire grace à 'tee'.

      $history | tee mon_historique.txt | grep 'samtools'
      844 bsub -M6000000 'samtools view -Sb test_all.VIR.sam -o test_all.VIR.bam'
      870 bsub -M6000000 'samtools sort test_all.VIR.bam test_all.VIR_sorted'

      $head -3 mon_historique.txt #commande qui affiche le début du fichier
      26 mkdir bamToFastq_test
      27 cd bamToFastq_test/
      35 bsub 'gunzip *.gz'

      Voila, le résultat affiché est le même, mai sj'ai en plus une sauvegarde de mon historique. Je vous laisse imaginer toutes les applications possibles.

      Merci pour ses conseils, j'espère que d'autres lecteurs prendront le temps de nous donner ce genre d'informations.

      Ismael

  3. Très bon article qui montre l'un des aspect les plus intéressant du shell.
    Je ne connaissais pas la commande tee qui est plutôt intéressante, merci pour cette découverte.

    Par contre je préfère redirigé stderr dans un fichier de log avec '2>>fichier.log' plutôt que d'afficher un simple message de fin d'exécution.

    $samtools view -Sb test_all.VIR.sam -o test_all.VIR.bam 2>>rapport_execution.txt && samtools sort test_all.VIR.bam test_all.VIR_sorted 2>>rapport_execution.txt

    Ça permet d'avoir une trace complète des erreurs éventuelles.

  4. J'y connait pas grand chose, mais mettre le tout dans un fichier .sh et l’appeler avc bash permet aussi un pipeline efficace, avec en plus la gestion de variables. L'avantage c'est qu'on garde une trace, le désavantage c'est que ça peut faire beaucoup de fichier au finale.

  5. article interessant.... merci.
    La commande 'tee' est aussi vraiment sympa.

Laisser un commentaire