 Tout le monde, donc toujours Maxime Garciel, et donc aujourd'hui, pour la session du jour, on va revenir un peu sur l'Unexclo et on va regarder tout ce qui est dépendance des containers, channel process et opérateurs, une petite entreprise qui sont agrovis et finissent sur la mode d'hilarisation. Donc commençons par la première partie, gérer les dépendances des containers. Donc je suis revenu sur mon glipod, donc pour l'instant je vais sur le monde d'environnement glipod. Pour l'instant, ce que je vais faire, je vais juste cacher toute la fenêtre parce que j'ai besoin essentiellement juste du site web pour le début. Ça va être un peu moins d'Unexclo pour commencer, donc vous inquiétez pas, on va regarder ça tranquillement. Donc l'intérêt de pouvoir gérer toutes nos dépendances avec des containers, c'est que ça va être simple de transmettre toutes nos dépendances à quelqu'un d'autre qui veut utiliser le même pipeline que nous. Donc Docker est un outil pour ça, Singularity est un outil pour ça aussi, AppTainer c'est un foc de Singularity qui marche aussi et ça va être la même chose. Après on a aussi la possibilité d'utiliser Konda ou BioKonda qui sont des environnements virtuels. Bon, sensiblement au final ça va être quasiment la même chose. Pour vraiment vraiment pouvoir utiliser Docker, la commande c'est Docker run, et là on va faire toujours l'exemple classique et le world. Donc Docker va directement récupérer toutes les infos par lui tout seul et voilà, il fait le Hello from Docker, ça demande ou ça marche bien. On a fait tourner notre premier container, c'est relativement facile. Normalement vous devriez pouvoir faire ça si vous les installez sur votre machine à vous et ça va vraiment vous permettre de voir s'il y a des petits problèmes. Après pour récupérer un container au lieu de faire run on fait pool et ça va faire la même chose. Donc recopillons cet exemple là. Si je fais Docker pool avec une image, il va récupérer l'image et si je fais Docker image, ça me liste toutes les images que j'ai sur ma machine. Donc là je vois qu'on avait déjà l'image pour le pipeline nextware in a sec et là on voit qu'on a une image pour des biens, celle qu'on vient juste de pooler, et l'image pour Hello world, c'est-à-dire le premier exemple qu'on a fait tourner. On peut aussi utiliser un container de manière interactive avec un minus, avec un moins it. Donc voyons voir à quoi ça marche. Je suis de manière interactuement dans mon container. J'ai plus mes alias dans mon container que je suis dans le container, mais on voit que ce n'est pas du tout ce que j'avais hors de mon container. Donc si je quitte mon container, je reviens, j'ai remont ll qui marche et je ne suis plus du tout au même endroit parce que je suis reparti hors de mon container. C'est vraiment tout simple. Notre premier docker file, donc ça, ça va être tout simple. On va créer un nouveau fichier qu'on va appeler docker file. On va pouvoir mettre toutes les infos qu'on veut. Et ici, ce qu'on va faire, on va récupérer d'abord la première ligne qui va nous dire quelle va être l'image de base de notre container. Donc là, on veut que notre container contienne comme image de base des biens. Donc tout simple. On peut rajouter des labels pour vraiment donner des informations qui a créé l'image. Quelles sont les emails ? Quelles sont son emails au moins pour pouvoir contacter les personnes ? Ça peut être pratique. Moi, j'ai des tendances à rajouter toutes ces infos là quand je crée des images. Donc vous faites un peu comme vous voulez. Moi, je conseille de faire ça. C'est quand même pas mal. C'est une bonne pratique. Non. Je ne m'appelle pas chékerame. Voilà. Après, ici, ce qu'on va faire, on va utiliser cette commande là pour dire à docker de quand ce fichier docker file va être lu par docker quand on veut créer notre container. Et donc là, on demande à docker de renait appétit get update et après d'installer conseil et curve. Tout simplement. Et je vais rajouter un pass. Je vais rajouter ici dans mon rendement pass users.game. Tout simplement. Voilà. Donc là, j'ai créé mon fichier docker file. Si on peut vérifier en ligne de commande, mon fichier docker file est bien là. Je ne suis plus du tout dans le monde. Ah si. Voilà. Mon fichier docker file est bien là. Il n'y a pas de problème. Construire l'image. C'est très simple. Docker build, build, magnitude et je vais appeler ça en image et on peut mettre un point où docker va directement trouver que c'est ça. Voilà. Donc là, docker est en train de construire une image. Donc il n'a pas eu besoin de télécharger. Je vais juste remonter pour montrer. Donc il n'a pas eu besoin de télécharger cette image là parce qu'elle était déjà sur place. Après, il a juste fait cette petite opération. Ça a été rapide. Et ce qui va se passer, c'est que chaque petite étape va rajouter une couche comme un oignon dans notre container. Il y a au moins un docker, ce qu'on va pouvoir faire. Si je modifie une couche supérieure ou une couche inférieure, il va garder les couches les plus profondes et il va juste changer les couches après derrière. Donc c'est relativement tout simple. Voilà. Donc là, si je fais un docker image, on va pouvoir voir que oui, j'ai mon image. Je viens d'être créé. Tout simple. On peut renéer mon image. Donc docker run, c'est mon image. Cossay, hello docker, legacy va se passer. Qu'est-ce que j'ai tapé ? Je n'ai pas tapé un truc. Cossay. Cossay. Et voilà. Ça a marché. On a créé notre premier docker file, notre premier container et on a fait tourner. Donc c'est relativement simple, vraiment pour des outils tout simples. Après, si on veut rajouter d'autres outils, on peut le faire. Donc là, on va récupérer toutes les infos pour pouvoir installer Salmon. Donc on va rajouter ça dans notre container. Voilà. On va reconstruire notre image. Là, on voit qu'en reconstruis notre image, on ne refait pas les étapes précédentes. On va vraiment refaire que la dernière étape. Donc ça nous fait vraiment quelque chose de plus simple. Et là, maintenant, si je regarde mes images, mon image, la ID a changé. Parce qu'elle vient d'être recrée il y a 7 secondes. Ce qu'on aurait pu faire quand on a créé l'image, c'est lui donner un tag. Ici, par exemple, on peut lui donner un tag Salmon. Je vais utiliser mon docker file, je vais enlever ça. Et on va lui refaire un tag simple. Ici, je remets toutes mes infos. Voilà. On reconstruit sans rien. Donc là, maintenant, si je regarde toutes mes images sur docker, j'ai mon image avec Simple qui est vraiment, où il y avait vraiment juste installé Cossail Curl. Là, on voit que c'est un ID particulier. J'ai fait une image où j'ai installé Salmon en plus avec cet ID là. Et là, j'ai monté la test, les tests que je viens de recréer, qui est exactement le même tag. Ça permet vraiment de pouvoir versionner et de voir les différentes images qu'on a. Généralement, le tag Lightest, c'est le dernier que vous utilisez. Et après, vous pouvez créer tout le tag que vous voulez. Moi, j'aime bien quand je crée ce genre de tag, versionner avec un numéro de version d'un outil ou quelque chose. Donc voilà. Si on veut pouvoir faire tourner Salmon à l'intérieur de notre image, on va pouvoir faire ça. Ah oui, ce n'est pas mon image. Ce n'est pas mon image. Voilà. Docker on, mon image, et bien voilà. On voit bien que ça marche. Pareil, on peut le faire de manière interactive avec moins IT. Je n'ai pas besoin de vous montrer. Si on veut créer un index, un génome index en utilisant Salmon dans le container, on va avoir besoin de monter les fichiers à l'intérieur. Parce que si j'essaie de faire Docker Run My Image, Salmon InX, voilà. Si j'essaie de faire cette commande-là, ça ne va pas marcher parce que Docker ne va pas pouvoir récupérer. Oui, ce n'est pas My Image. C'est mon image. Si j'essaie de faire ça, ça ne va pas marcher parce que Salmon ne peut pas trouver... Voilà. The file n'existe pas. Alors on sait que le fichier existe, parce qu'il est là. Data, Jégale, transcriptum. Mais il appart ici parce qu'il ne sait pas où est l'image le container. Il y a vraiment un environnement séparé. Donc on a besoin de rajouter volume pour lui dire voilà c'est là que le fichier se trouve et tu vas monter ça dans mon histoire. Donc si vraiment on rajoute ça, on va recommencer la même chose. Docker Run et on va rajouter moins tirer et tirer volume. Coupi ici. Alors Docker Run. Je vous tape en tout. Docker Run, voilà. Le script c'est mon image. Et maintenant, retapons Salmon index. On lui dit indexer le fichier transcriptum.FA. Parce que là on a dit de monter tout ce dossier là en local sous le nom transcriptum.FA dans mon container. Donc on a besoin juste de dire voilà transcriptum.FA, c'est là où ça va aller. Et donc là si on fait marcher ça, on va voir que Salmon a réussi et m'a généré tout ça. Le seul problème maintenant c'est que si je regarde, il n'a créé aucune info. Parce que pareil qu'on a monté les e-boots, il faut qu'on monte aussi les out-boots de l'autre côté. Donc c'est ce qu'on va faire ici en rajoutant des infos supplémentaires. Donc on a toujours notre Docker Run. On a notre volume. Donc on va simplifier l'histoire de volume. On va faire juste, on va monter directement tout ce qui est en PWD dans PWD. Tout simplement, on va rajouter un Workdir qui va être aussi PWD, c'est-à-dire là où on est actuellement. Et voilà. Là pour notre image, on va reprendre le chemin complet. Voilà. Et donc si on fait tout ça, exactement ça marche. Et on a un nouveau dossier qui a été créé qui contient mon container. On peut le voir ici. Et voilà. Donc on peut voir que Docker l'a créé en tant que route. Voilà. Les permissions, ça a été créé avec route. Ça on va pouvoir changer ça vraiment si on veut. Il y a des options dans Docker pour changer ça. Mais bon là c'est vraiment juste pour montrer ce qui est possible de faire avec Docker. Moi personnellement, ça je ne fais plus ça du tout parce que maintenant je laisse NextLow gérer tout ça pour moi. Je n'ai pas à me préoccuper de tout ça. Je vais vous montrer ça plus en détail. Je crois que je vous l'ai montré avant hier déjà. Mais on va regarder ça plus en détail tout à l'heure. Donc après ce qu'on va pouvoir faire aussi avec Docker, on va pouvoir mettre nos images à disposition de tout le monde, et avoir tout ça sur Docker Hub. Donc bon, là dans notre cas, ça ne nous intéresse pas. Donc on ne va pas le faire. Et là, ce qu'on va pouvoir faire c'est qu'on va pouvoir juste réutiliser notre script qu'on avait le premier jour et on va lui dire de faire tourner ça avec notre image à nous au lieu d'utiliser l'image qu'on avait prévue à l'intérieur. Et donc là, on va pouvoir voir le script de tour et indexer bien avec mon image Salmon. Il n'y a aucun problème. Ça marche sans souci. Singularity, ça va être exactement la même chose. Donc Singularity ne va pas marcher avec Geek Code. Donc si vous voulez faire ça, regardez sur votre ordinateur local ou sur un classur de calcul. Mais la syntax est sensiblement similaire. Et ça va être à peu près pareil. Après, c'est exact au lieu de run, mais sinon ça va être exactement la même chose. Alors avec Singularity, ce qu'on va pouvoir faire en plus, on va pouvoir importer une image Docker directement. On fait singularity, pull, pull et docker avec vraiment l'adresse d'une image ici sur Docker Hub. Il n'y a aucun problème et ça marche. Pour faire après tourner un pipeline next-lo, ça va être la même chose. On utilise pull, pull, singularity et notre image singularity. Singularity, ils ont leur propre répertoire de container singularity et donc de la même manière qu'on peut déposer des images sur Docker Hub. On va pouvoir poser des idées container singularity sur container. Aucun problème à ce niveau-là. On va regarder maintenant comment faire ça dans conda. Dans conda ça va être à peu près pareil. Ce qu'on peut faire on va initier conda voilà ok conda limite, no change ok il n'y a pas de problème. Bache on va faire Bache ok conda init, je suis dans Bache donc j'ai un environnement de base conda donc aucun problème. On va regarder déjà ici dans notre dossier on a déjà un fichier n.yaml donc c'est notre environnement conda tout au format yaml donc il n'y a pas avec des infos avec tous les outils de base donc voilà c'est notre recette vraiment pour créer notre environnement conda c'est exactement la même manière qu'on avait un docker file pour créer notre fichier docker qu'on peut faire un fichier pour singularity c'est vraiment notre recette de construction qui va nous permettre de construire notre environnement israël ici dans conda on n'a pas à se préoccuper de comment on va installer les outils va contenir déjà toutes les recettes d'installation des outils et va gérer les différentes dépendances et les différents soucis à ce niveau-là donc ça va prendre du temps à se construire j'ai fait mon environnement ici conda récupère de tout seul tout ce dont il a besoin donc là on voit que conda il va me chercher d'enbaillot conda salmone en version 1.5.1 donc là je regarde moi sur baillot conda voilà salmone j'ai un paquet de salmone c'est exactement ce que j'ai et je vais dire tous les highlights parce que je n'aime pas les surlignages et là il m'installe une version on l'avait dit la 1.5.1 voilà qui est là-dedans sans aucun problème et donc ici ce que je voulais vous montrer c'est que si je regarde ici la recette j'ai un fichier metta.yaml qui va m'indiquer ce qu'il faut faire pour installer salmone et une commande simple qui montre que ça marche bien et il y a ici ceci existe pour toutes les recettes pour tous les outils baillot conda est une source vraiment de recettes il y a tout plein d'infos donc là on ne voit pas tout parce que il y a plus de 8000 dossiers ici mais voilà c'est vraiment pour montrer l'étendue de baillot conda et à ce niveau là aussi automatiquement dès qu'une recette est mise à jour sur baillot conda un container va être créé un container docker un docker va être créé qui va être téléchargé qui va être uploadé donc téléversé je sais plus comment on dit bon c'est pas bien grave il va se retrouver sur quidotaio et on va pouvoir le récupérer pour avoir les informations sur les tags ici ce que je fais je regarde ici je regarde ici dans salmone et ici je vois dans salmone avec tous les tags dont j'ai besoin donc voilà donc là mon environnement est toujours en cours donc j'ai regardé ça pour salmone je pourrais regarder aussi mais c'est la même chose et c'est très similaire donc baillot container c'est vraiment une ressource que j'adore utiliser parce que ça me permet de plus avoir à ce que je vous ai montré précédemment et à avoir à créer votre container de docker vous-même vous pouvez utiliser un container déjà créé automatiquement pour vous qui contient votre outil alors l'inconvénient à ce niveau-là c'est que le container va être un petit peu plus gros qu'un container de base mais c'est tellement plus simple d'avoir un container et de pas avoir à gérer l'installation que honnêtement j'accepte quelques petits désacréments pour me fasciniser la vie voilà on pourrait j'ai pas envie de faire ça parce que c'est en train de prendre du temps à se créer l'autre option aussi pour faire des environnements c'est de utiliser une micro-memba plutôt que voilà il est en train de s'installer tout s'installe on peut créer alors ça c'est ce qu'on fait ce qu'on fait automatiquement c'est grosso modo ce que va faire bio containers pour vous il va créer un environnement contenant juste votre outil et il va créer automatiquement votre environnement en condas dans votre container docker on pourrait faire ça pour montrer comment ça marche mais il n'y a pas trop d'intérêt il y a un intérêt mais ça va prendre du temps je pense que c'est plus intéressant de voir la suite donc bio containers ici je vais arrêter parce que ça va prendre vraiment beaucoup de temps voilà voilà c'est mieux je vais juste montrer que bio containers on va pouvoir récupérer juste toutes les infos tous les outils qu'on veut sans aucun problème et là par exemple je récupère fascusi la version 0.11.5 ici sur bio containers il faut spécifier une version quand on va la récupérer sinon ça ne marche pas bio containers ne va pas pouvoir récupérer quelque chose parce qu'il n'y a pas de lait est de lait est sur bio containers donc voilà donc là ce qu'on va pouvoir voir niveau exercice on reprend le script 2 le script 2 ok le script 2 qui utilise index et ce qu'on veut niveau index c'est lui faire utiliser comme container un container salmon donc on était sur quelle version on voulait quelle version salmon 1.7 ok salmon 1.7 containers ok ok containers containers là non c'était salmon voilà donc on ajoutait une directive container avec l'adresse du container qu'on veut utiliser et donc là maintenant je devrais pouvoir faire explo run tout.nf je devrais pouvoir se marcher sans aucun problème with docker comment nobform ah oui c'est mon nextloop.coffee alors ici je vais lui enlever je vais commenter on va effacer ceci et on va rajouter un docker enable il y a la trou ici je relance là c'est encore d'exécution et ça a marché ça a bien utilisé ici cette directive là maintenant je vais vous montrer plus en détail ce que je vous ai dit ce qu'on a vu tout au début de cette session sur comment utiliser docker et donc comment ça marche en vrai donc je vais regarder dans mon répertoire de travail donc je vais dans work je regarde fd voilà et ici ce qui m'intéresse ça va être de regarder le command.sh donc on voit comment on a vu toutes les sessions précédentes la ligne de commande utilisée c'est ce qu'on retrouve ici dans notre script avec les bonnes valeurs remplacées automatiquement et après ce qui m'intéresse ça va être la commande dans le fichier dot command dot run ce qui va m'intéresser à regarder c'est la fonction nextflow nxf launch qui va gérer pour moi tout ce qu'on a vu en début de session avec docker comment on va gérer notre workdir comment on va pouvoir gérer que l'utilisateur qui est créé les fichiers soit pas l'utilisateur root soit bien l'utilisateur l'appel au container et comment monter les bons fichiers aux bons endroits ce qu'on fait là ici donc nextflow va faire tout ça automatiquement pour nous donc on n'a vraiment pas s'occuper de tout ça c'est ce que j'aime bien, j'ai tendance à être un petit peu flemar et donc voilà donc ici on va voir ce qu'ils ont fait ah oui donc on peut le faire directement soit en lui spécifiant une image en ligne de commande soit comme j'ai fait en modifiant le script avec une directive container il n'y a pas de problème exercice bonus, regardez les directives process voilà et pas à peine utilisé automatiquement donc voilà ici c'est ce qu'on a fait enlever cette ligne process container sur le nextflow il n'y a pas de problème et ce qu'on pourrait faire dans le script 5 c'est exactement ce que j'ai fait dans le script 2 c'est-à-dire que j'ai ajouté cette directive là on va faire ça, on va voir dans le script 5 on va rajouter ici voilà on veut Samuel ici pour le process de quantification aussi ici on va valoir Fascusi donc ici Fascusi 2 points cherchons Fascusi Fascusi je veux les tags sur Bioconda 0.19 on se devrait aller voilà et là si on fait tourner le script 5 voilà Nextflow a automatiquement récupérer les containers qu'on lui a spécifiées sans aucun soucis et il utilise vraiment un container séparé par tâche et moi je trouve que cette approche là de faire une tâche un container va vraiment dans la logite Nextflow à fond parce qu'on va vraiment tout séparer on a chaque tâche qui va contenir tous les fixés dont il ont besoin parce qu'il aurait été symlinké et cette tâche va vraiment tout va tourner juste ici avec son propre container tout ce dont on a besoin voilà donc ici j'agitation exactement, on a changé ici et on a changé ici c'était pareil voilà après on va voir un peu plus en détail si il va se passer ici donc on va voir maintenant plus en détail les channels les channels c'est vraiment une structure centrale de Nextflow ce qui va nous permettre de connecter les process différentes tâches ensemble donc il y a différents types de channels les QChannel et les ValueChannel donc avec soit les channels soit les channels avec des valeurs donc une QChannelQ c'est asynchronous, unidirectionnel et FIFO ça veut dire que les opérations ne sont pas bloquantes ça va pas bloquer ça va rien bloquer unidirectionnel ça va d'un process à un autre ça connecte dans un sens et FIFO ça veut dire que le premier qui arrive ça va être le premier qui sort tout simplement une QChannelQ c'est vraiment ce qui va être créé de base avec les créateurs de channel que sont channel off ou channel from basse donc si on crée on va faire ce petit snippet il y a déjà été créé ici ça va être tout simple ici ce qu'on va faire on va créer ce petit snippet qui va contenir une nouvelle channel qui va construire des éléments 1, 2 et 3 on va essayer d'imprimer directement la channel comme ça et après on va voir le contenu de la channel donc qu'est-ce qui se passe si on fait ça snippet de tnf on voit ici que quand j'ai essayé d'imprimer ma channel j'avais un Dataflow broadcast ce qui ne donne pas ce qui ne donne pas vraiment d'informations mais c'est comme ça je sais que c'est un objet particulier dans Nexlo et voilà le contenu c'est vraiment ce qu'on va vouloir imprimer c'est pour ça qu'on utilise l'opérateur review plutôt voilà donc exercice, exécuter ce snippet c'est bon on l'a fait c'est facile les values channel ça va être une channel qui va contenir vraiment qui va être utilisé autant de fois qu'on veut et autant de fois qu'on a besoin ça va plus contenir des valeurs et ça va pas être elle va pas être consommée contrairement à une QChannel elle va être consommée dès qu'elle est utilisée donc si j'ai 3 éléments dans ma QChannel ils vont passer dans un process et ils vont être consommés le process ne va pas être retourné on ne va pas réutiliser les mêmes éléments une value channel est différente dans le sens que tant qu'on va matcher des QChannels en face de ces values channel pour un process particulier la value channel ne va pas être consommée et va attendre que toutes les QChannels soient consommées pour permettre l'exécution du process donc une value channel va pouvoir être créée en utilisant soit une méthode de création value soit en utilisant n'importe quel autre opérateur qui peuvent retourner une simple value là on va faire un autre exemple supplémentaire exemple.nf exemple.nf exemple.nf voilà on va lui coller ça dedans copier coller voilà c'est pour comprendre les différences entre les QChannels donc voilà on va faire un nextflow run exemple.nf notre script nf a une première channel qui va contenir des éléments 1, 2 et 3 une deuxième channel qui contient juste l'élément 1 et donc on a un process sum et ce qu'on s'attendrait c'est que sum me face la somme de 1 de 2 avec 1 puis de 3 avec 1 et là ce qu'on voit ici c'est que sum n'a marché qu'une seule fois on l'a vu hier quand j'ai créé un pipeline utilisant le sub workflow on avait besoin de rajouter un opérateur pour transformer cette QChannel en value channel donc c'est ce qu'on va faire ici en ajoutant l'opérateur first ici j'utilise l'opérateur first ici sur ma channel là qu'est ce qui se passe on voit qu'ici le process a été exécuté 3 fois et j'ai ici eu 2 plus 1 1 plus 1, 2 plus 1 3 plus 1 on aurait pu faire aussi au lieu de transformer first utiliser le channel factory value et on devrait avoir exactement le même bruit on va vérifier que ça marche bien comme on l'espère voilà donc ça c'est vraiment la différence entre une channel de Q qui est consommée et une channel de valeur qui n'est pas consommée on voit vraiment que il a été utilisé plusieurs fois ok, on va faire on va vraiment regarder dans notre script pour voir vraiment les différences ici au point de vue du channel 1 et channel 2 voilà, j'ai mon channel 1 qui est un Dataflow broadcast en datastream donc ça c'est une channel de Q et ici j'ai un Dataflow variable c'est une channel de value donc c'est pas très clair si vraiment vous voulez inspecter ça on est en train de réfléchir à rajouter ces informations-là dans le matériel de tutoriel donc voilà, pour l'instant on peut vraiment inspecter ça uniquement de cette façon-là ou faire bien attention que vous avez créé une channel de valeur ce qu'on peut faire aussi si on veut c'est regarder avec la syntaxe DSL1 s'il y a des infos supplémentaires je préfère pas repartir sur la syntaxe DSL1 de nextflow qui est légèrement différente et qui va nous permettre d'avoir des infos supplémentaires je préférerais vraiment éviter ça donc on va pas regarder ça et je vais souhaiter cette étape-là on a vu que ça marchait quand on voulait les outils qui vont nous permettre de créer des channels donc on a vu déjà l'outil value qui va nous permettre de créer des channels des channels de valeur tout simplement, on l'a fait précédemment on peut créer ici une channel vide parce qu'on a aucun info à l'intérieur ici on va avoir une chaîne de caractère et ici on a une liste mais la liste va être émise comme un seul élément channel of ici va nous permettre de créer des QChannel ici ma QChannel est constituée de ces 4 éléments-là qui vont être qui vont être qu'on va pouvoir voir ici si on copie ce code-là channel of voilà c'est ça on peut utiliser des petits raccourcis qui vont nous permettre ça je vais le montrer c'est toujours utile à voir revoyons notre exemple ici on voit que j'ai fait en fait je veux créer un nouveau channel avec des intervalles en particulier mais pour pas taper tous les intervalles j'ai dit un nextflow de 1 jusqu'à 23 puis après x et y et il me crée mon channel avec ici de 1 à 23 plus ça peut être des chromosomes par exemple c'est vraiment pour simplifier les intervalles si vous avez ce que vous voulez nextflow pour vous simplifier la place from list ça va être pareil c'est créer une channel à partir d'une liste je vous recommande vraiment de pouvoir regarder tous les exemples voir comment ça se passe on regarde ça aussi ah oui ça aurait été mieux si j'avais chiffré ça j'ai tout émissé en un seul truc et donc voilà nextflow me crée une channel en partant d'une liste ma liste contient deux éléments nextflow me crée une channel en partant de liste aucun problème ça se fait bien from pass ça va être exactement pareil il va nous permettre de créer une channel en partant d'une en partant d'un fichier si je reprends sur mon exemple ici voilà le opérateur pour montrer ce que ça fait et là on va voir que nextflow a regardé dans data il a regardé dans meta et il match tout ce qui correspond à ce paramètre de globula et il récupère les deux il m'inquiéture c'est de fichier là dans mon channel aucun on a des infos supplémentaires sur tout ce qu'on va pouvoir faire sur cette channel sur cet outil de création de channel donc les types on peut retourner déficier des répertoires l'un ou l'autre on peut utiliser glob pour interpréter en utilisant toutes les wildcards possibles sans aucun souci ils donnent pour pouvoir inclure les fichiers cachés quelle va être la profondeur maximale si on doit suivre des liens symboliques si on doit être si on doit récupérer des channels relatifs et check if existe qui nous permet de donner une exception quand ça ne marche pas donc voilà exercice, utiliser le channel from pass, secret channel meeting, all file with the suffix fsq in data ok alors tous les fichiers fsq ici on est dans data gga on avait dit tous les fichiers fsq et imprime le résultat on a tous les fichiers fsq qui sont dans data tuga si on utilisait il y avait une histoire d'utiliser les deux astérix le d'un seul je crois que ça permet vraiment d'être beaucoup plus large dans notre dans notre choix de fichier si il n'y a aucune différence ça ne change rien si je me fiche tout ça si je me fiche voilà c'est bien ça mettre deux astérix nous permet d'englober aussi les répertoires ok on veut récupérer toutes les on voulait récupérer uniquement dans le répertoir gga et aussi tous les sous répertoirs on a fait dans le répertoir data et on veut aussi voir si il y a des fichiers cachés supplémentaires donc on va rajouter une deux fichiers parce qu'on a une version de fichiers cachés quelque part je ne sais pas on va regardons la solution c'est un deux point j'utilise pas assez souvent donc je ne me souviens plus la syntaxe voilà donc si il n'y a pas de fichiers cachés dans quel été le résultat on avait quelque chose de relativement similaire ok from file pair c'est notre créateur de channel qui va fonctionner de manière très similaire mais qui en plus va pouvoir nous créer directement des pairs de fichiers donc c'est très pratique surtout quand on a des fastq ça nous permet directement de créer un channel pour notre pair de fastq voilà ici je le récupère si je recréer si je recréer si je recréer mon channel et que je regasque l'intérieur on va voir que tous mes fichiers ici ont été créés alors j'ai un premier élément qui va être vraiment mon identifiant c'est une clé qui va nous permettre d'identifier les différents éléments et après j'ai un second élément qui est une liste qui va me contenir donc voilà c'est parfait c'est exactement ce qu'on voulait ah aussi ici si on veut que la pair si on veut que la clé récupère un élément récupère quelque chose ici pour identifier ça doit contenir un étoile ici une étoile, un sx voilà donc là on a pareil toutes les informations plein d'options sur l'humidité en plus ça c'est ce qu'on a fait c'est ce qu'on a imprimé à utiliser l'option flat true pour voir qu'est ce que ça fait on voit la différence c'est la perte de facio au lieu d'être dans un seul élément chacun et un élément c'est pareil effectivement on voit qu'il y a plus les accolades une channel from SRA qui va pouvoir nous permettre de récupérer des infos supplémentaires qui va permettre de récupérer directement des infos du NCBI donc il nous faudrait une clé API qu'on peut avoir en nous logant sur un content NCBI j'ai vraiment pas envie de faire ça là donc je vais pas le faire mais vous pouvez tester vous de votre côté et vous devriez avoir les mêmes informations sans trop problème fichier texte là c'est pareil c'est un opérateur qui va nous permettre de couper un fichier d'entrée en plusieurs bouts donc ici ce qui se passe voilà donc j'avais mon fichier random qui contient un loremi Ipsum donc il me crée un chunk de deux lignes il arrête il arrête il arrête sauf qu'il n'y en a qu'une à ce niveau là du coup il m'en fait un seul et il arrête voilà ah oui on utilisait Subscribe pour pouvoir imprimer les infos à chaque fois qu'il y avait une nouvelle valeur dans le sujet source ça se fait sans soucis ce qu'on peut regarder en plus comme info supplémentaire c'est ce qu'on peut tester c'est au lieu de splitter juste pour deux lignes splitter en 10 lignes et essayer de compter toutes les infos alors qu'est ce que c'est on va récupérer celui-là voilà ici on a utilisé Hit tout au parquet tout est passé en majucule ici on va rajouter un petit compte donc on rajoute juste un petit compteur pour voir combien quel est le numéro de la ligne voilà c'est pour montrer qu'on peut utiliser cet opérateur speedtext pas seulement sur des channels mais aussi sur l'officier que nous avons hors de channel qui va vous permettre après derrière de gérer toutes vos opérations sans avoir besoin que ce soit des channels donc refaisons ça exactement ici ça n'est plus une channel là ici on n'a pas sauté de ligne alors qu'avant on n'a sauté pas mais ça nous donne exactement la même information soit ce qu'ici maintenant mon f c'est juste un fichier à l'intérieur la même chose ici on peut y expliquer csv à partir d'un fichier csv donc ça va être la même chose sauf qu'en plus on va pouvoir spécifier si il y a un header pour récupérer les informations supplémentaires au point de vue des différentes noms de colonne donc ce qui va pouvoir être relativement pratique pour récupérer toutes les métadonnées que vous pouvez avoir et on peut bien évidemment lire plusieurs fichiers csv en même temps en dehors d'un contexte de channel ok quels infos on a ici copy les toiles parce que je sais qu'on avait de fichiers ici il n'aime pas les globes l'exercice try inputting fast to read from earlier csv add csv text file ah oui on va recréer un fichier csv qui va contenir toutes les informations qu'on avait précédemment voilà c'était ça copy new file simplechip.csv voilà on a id fastq1 fast fastq2 on veut pas on veut pas l'espace tout ici voilà donc ici dans mon exemple ce qu'on veut faire on va recréer un channel ici pour lire toutes nos infos et on a id on a u1 tout ce qui se passe si vous avez regardé ça quoi tu l'as plus ici exemple voilà on a toutes les informations qu'on avait précédemment donc l'exemple qu'est ce qu'on voulait faire dans l'exercice try inputting ah oui on voulait rajouter ça dans notre pipeline rna sec donc ce qu'on avait juste c'était donner ça à rna ici et on fait ça maintenant ça on a fait alors on peut le remplacer dans le script 7 donc je récupère mon exemple je regarde mon script 7 voilà on va remplacer le parum-read c'est pour un input si on le spécifit c'est juste simple sheet csv ici ce qu'on va faire on va récupérer mon parums d'input et ça on va le mettre dans on va appeler channel vids voilà ça on peut l'enlever beaucoup plus logique de faire ça bien voilà et supprimer ce truc ici voilà supprimer ça oui on met le ch à la fin respectons les principes avec le ce qu'on veut c'est remplacer ça par ça donc là le problème qu'on va avoir c'est que maintenant read.ch va convenir d'autres informations notamment on a toujours notre simple ID on a toujours un vid parce qu'il se passe ici ici ce qu'il va se passer ça va pas marcher de manière très simple parce qu'on va pas lui donner le bon nombre d'éléments si je lance l'example c'est script les channels vont pas marcher parce qu'on a pas le élément en entrée qui correspond à ce qu'on a tant sorti voilà alors là ça n'a pas marché pour une raison complètement différente parce qu'il voulait utiliser plus de ah c'est pas lui où j'ai spécifié mes containers vous savez que j'ai spécifié mes containers je fais ça dans le script plus dans le script 7 alors un d'example je fais ceci je fais ceci sur le bon nombre alors ce qu'on va faire plutôt de faire tout ça on va rééquiper notre mixflow et je vais remettre le container de base que j'avais alors relançons tout ça là j'utilise juste le container parce que je sais que ce container contient tous les outils dont j'ai besoin pour mes process sinon je voudrais faire ça bien je définirai directement pour chaque process un container séparé mais là j'avoue j'ai un peu la flemme donc là il a quand même essayé des informations mais on voit que ça marche pas terrible on voit que ça marche pas terrible parce qu'il dit qu'attention les tumples en entrée ne matchent pas du tout ce qu'on a donné après derrière c'est normal parce qu'on lui donne un tupple de 3 éléments alors qu'il s'attendait à avoir un tupple de 2 éléments donc ce qu'on va faire on va corriger tout ça donc il y a plusieurs façons de corriger tout ça à plat soit on va corriger tout ça ici dans notre process en disant qu'au lieu d'en étendre un seul élément tu vas en étendre 2 soit ce qu'on va faire ici c'est qu'on va pouvoir utiliser map pour réorganiser nos fichiers de sortie si on fait cela relance avec nous qu'est-ce qu'il se passe de limites alcohols sur les implements qu'est-ce qu'il n'a pas ah oui d'accord ce qu'on va faire on va supprimer ça ici on recommence il n'aime pas du tout voilà ici il a vraiment des indications avec ah oui ce qu'on a des colonnes alors comment c'était exactement ce qu'on voulait faire oui split cv me donne juste une seule ligne et cette ligne je vais l'utiliser en colonne voilà on a notre première colonne gut qui va contenir notre première ligne avec l'ID gut qui va contenir un fichier de fichiers de fichiers en paire donc là on a juste remodifié notre channel pour correspondre nos process et ça marche sans aucun souci comme on peut le voir donc si je regarde la solution ici qu'est-ce qu'ils ont fait ici voilà alors ici ce qu'ils ont fait ils ont changé l'intérieur du process donc l'intérieur des deux process moi j'ai préféré changer la channel les deux options marchent de toute façon on fait de la programmation vous connaissez il n'y a pas une seule façon sur les choses mais il y a plein de façons type variety value ça va être la même chose que les csv le séparateur c'est un table au lieu d'être une vagule donc là c'est la même chose je vais pas faire l'exercice parce que c'est vraiment similaire on peut apprévrément si on veut passer aussi des fichiers json des fichiers yaml il n'y a aucun problème et on peut garder toutes ces informations là dans tous ces parsers directement dans des modules qu'on peut après inclure sans aucun soucis dans nos propres process je pense qu'on va pouvoir reprendre d'une petite pause et maintenant on va voir plus en détail les process donc le process vraiment d'un expo ça va être notre tâche de base qu'on va pouvoir exécuter plus plus complexe ici c'est vraiment un exemple tout simple ou le process contient uniquement une définition du script le nom du process par convention on le met en majuscule après vous avez le droit de faire ce que vous aimez par convention on le laisse en majuscule donc ici on a notre process notre déclaration notre déclaration pour le script ici le script à l'intérieur on peut avoir beaucoup plus de définitions donc on a des directives qui vont donner plus d'informations on a vu précédemment contailleurs et conduct qui nous permettaient d'avoir des infos supplémentaires sur comment exécuter le process il y a d'autres informations qu'on va pouvoir rajouter à ce niveau là dans les directives dans les input on va pouvoir détailler quelles sont les channels qu'on va avoir en input dans les output qu'elles sont les channels qu'on va pouvoir donner en sortie du process on peut rajouter WAN qui va nous autoriser à conditionner si on veut exécuter ou pas ce process et après vraiment script qui va pouvoir nous détailler tout ce qui se passe ici dans ce process donc là on peut appuyer sur plus pour voir les informations donc la directive on peut en avoir 0 ou plus comme on veut niveau des inputs, pareil 0 ou tant qu'on veut WAN c'est optionnel pas et après la commande a exécuté on a différentes solutions ici script, shell ou exec ce que je vais vous détailler par plus tard donc ici script ça va vraiment être un bloc qui peut être un script multiline qui va vraiment nous aider à faire des lignes de commande plutôt compliquées par défaut script c'est du bash mais on peut mettre à la place ici un shebang piton pour dire que le script ici est un script en piton, tout simplement niveau des paramètres tous les paramètres qu'on définit avant le script, dans le script sont utilisables avec dollar tout ça c'est de façon dynamique avec des valeurs voilà petit problème si on veut utiliser des variables internes à bash, il va falloir les échapper parce que sinon nextflow suppose que cette variable est une variable nextflow et pas une variable bash donc si vous l'utilisez des variables bash dans votre script il faut que vous les échappiez avec un antislash une autre solution aussi c'est d'utiliser des simples codes et dans ce cas là on n'a pas besoin de les échapper mais ça nous bloque l'utilisation des variables nextflow donc l'autre option ça va être d'utiliser shell au lieu de script qui va nous permettre d'utiliser directement avec un dollar, toutes les variables bash mais il va falloir qu'on utilise un point d'esclamation pour toutes les variables nextflow donc ça peut rajouter une complexité supplémentaire mais ça peut aussi vous aider à mieux voir les choses comment ça se passe moi j'ai tendance à utiliser juste script avec des triple codes au moins je m'embête pas et c'est beaucoup plus simple on peut rajouter des conditions sur notre script avec des blocs if qui va nous permettre de dire par exemple ici on a un parrain compresse qui va nous permettre de dire si c'est du jzip on va compresser en jzip si c'est du bzb2 on va compresser en bzb2 ou là attention il n'y a pas ce paramètre là voilà tout simplement niveau des input donc tous les process sont complètement isolés d'un d'un des autres la seule façon que les process ont de communiquer ensemble c'est d'utiliser des channels c'est ce qui se passe ici dans cet exemple on a un channel d'entrée qui va avoir plusieurs éléments c'est pour ça que ça va être paralysé ici dans notre process et nous donner un input par élément on peut spécifier différents qualificatifs pour notre input je crois qu'on a vu ça le premier jour donc on avait pass pour un fichier, on avait val pour une value on avait tupple pour un ensemble de différents éléments que ce soit différentes values, différents fichiers ou un ensemble de valeurs et fichiers il y a aussi un qualificatif each qui nous permet de pouvoir y terrer sur différents entrées voilà le qualificatif val nous permet d'avoir des valeurs en input donc l'exemple ici est très simple on a notre channel ici qui contient des valeurs et ici les valeurs vont être affichées ici voilà les fichiers avec un pass c'est vraiment pour pouvoir dire que le fichier ici c'est un fichier et on peut avec input spécifier quel va être le nom du fichier le nom du fichier ici simple.facu ne va pas correspondre à ce qu'on a ici dans notre channel vous pouvez décider de donner à votre nom d'input un nom déjà défini donc c'est pas quelque chose que j'utilise souvent moi personnellement parce que ça peut appréposer des problèmes derrière mais ça peut être pratique des fois il y a des cas où ça peut être très pratique et donc là ici dans ce cas là on a décidé de nommer notre input on peut le laisser comme on a déjà de base ici par exemple si on n'a rien défini le nom de notre échantillon est une variable internanexlose c'est pour ça qu'on a un dollar c'est pas une variable bashed non on réduit les faipers voilà et la même syntaxe nous permet d'avoir plusieurs fichiers d'input donc c'est pas un problème à ce niveau-là alors plus vite et gracis ok ok on va regarder directement la solution alors on a notre rig ok on récupère tout ça ah oui voilà on fait un process qui va concrétiner tout ça donc ici on a notre paramètre d'entrée qui va nous contenir nos fichiers Fasq on crée une channel à partir de ce créateur de de channel qui va nous créer à partir de ces fichiers ici et on crée tout ça on va mettre tout ça dans une channel qu'on appelle rig channel donc ici concatenate ce process-là va contenir tout tous les différents fichiers qu'on peut avoir là ici en input on va dire récupère-moi tout ici ce qu'on va faire on va concatener tout qu'on va passer qu'on va mettre directement dans un fichier qu'on appelle concatenate.ext et de ce fichier on va récupérer uniquement les 10 premières lits qu'on va récupérer ici en output donc voilà tout simple et là notre workflow va nous permettre de récupérer ici en sortie ce fichier là on peut aussi combiner les channels ensemble donc ça c'est quelque chose de très intéressant pour vous ça va être pouvoir vraiment de pouvoir combiner différents channels donc ici j'ai une première channel d'élément 1, 2 et 3 une seconde channel qui est constituée d'élément A, B et C et ici j'ai mon process qui va combiner 1, qui va combiner les différents channels ensemble par pair donc là si on récupère ceci dans mon exemple voilà on voit que workflow a péré tout ça sans aucun problème on a nos 3 valeurs ce qu'on va pouvoir regarder c'est qu'est-ce qui se passe si les infos n'ont pas du tout le même nombre d'éléments par exemple ici j'en ai que 2 et ici j'en ai 4 mais j'aime bien mettre des espaces un peu plus agul si je fais ça ici j'ai ma première channel qui contient un que 2 éléments qui va bloquer l'exécution de mon process parce qu'il n'y a que 2 éléments qui sont consommés et une fois que les 2 éléments sont consommés il n'y a plus rien du coup ici cet input ne va pas pouvoir être pris en compte il n'y a plus rien pour nourrir le process donc même s'il reste des éléments dans notre deuxième channel ils ne vont pas être lus donc le pipeline s'arrête à ce niveau-là on va pouvoir gérer ça dans des manières différentes en par exemple ici si j'avais qu'un seul élément ce qu'on pouvait faire c'est faire ça en value on a vu tout à l'heure la différence entre le QChannel et la UChannel et là c'est exactement ce qui se passe désolé encore mon chat donc là voilà ce qui va se passer on a notre première channel pour chacun des éléments derrière donc on a remplacé X par une channel value on a une inscrite donc ici écrivez un process qui va être exécuté pour chacun des reads et utiliser le seigne de l'humain alors on fait ça sur lequel ok donc par exemple de VID à plat commande VID transcriptum ok ok c'est quelque chose de très similaire qu'on a déjà fait dans notre script 7 où on a bien notre fichier trans ou on a bien notre index qui est ici et notre index va être utilisé autant de fois qu'on a besoin sur notre fichier de quantification et la raison pour laquelle ça se passe c'est ici en output on n'a qu'un seul output ce que je pouvais changer ici c'est rajouter on va faire un tupple on va rajouter une valeur non c'était pas du tout ici c'était mon index voilà ici je fais un tupple value value on va dire index voilà ici si j'utilise ici un tupple en sortie ce process là va créer non plus une value channel mais une Q channel donc là ce process là ça prend un tupple avec une value et un pass qui est une value je vais appeler ça voilà ici ça n'a rien changé à mon script 7 pour avoir ici c'est comme mon script de quantification il est exécuté 3 fois non j'ai pas ceci là qu'est ce qu'il m'a fait il m'a fait un tupple ce que j'ai rajouté un index ça va exécuter 3 fois ça ben si pourquoi j'ai dû quand même créer une value channel je suis pas sûr de la raison pour laquelle ça marche ici bon c'est pas très très grave donc ici la solution qu'il voulait faire c'était pour matcher chacun des fichiers d'entrée ici avec le fichier transcriptom donc on a notre param red qui va matcher tout ça notre param transcriptom file qui va matcher ça ici on fait un riz et un param transcriptom et ça marche bien parce qu'ici notre channel va matcher plusieurs fichiers ici notre channel va matcher qu'un seul fichier donc on a bien pas de problème ici à ce niveau là où on a des Q channel et de value channel qu'on va pouvoir regarder ici à la place c'est de regarder un qualificatif each qui va nous permettre de voilà ça on va essayer parce que c'est toujours joli à voir je vais reprendre ce qu'on a écrit ici on a nos séquences qui sont tous les fichiers tfa voilà ça on fait beaucoup tous les fichiers tfa qui sont dans propres on a différentes méthodes régulaires, espresso, psychofi et ici on a utilisé une directive debug pour pouvoir nous permettre d'avoir la sortie standard ici directement dans le terminal ici on a en input on a la séquence d'entrée qui correspond ici à cette channel ce qu'on a specifié ici et on a les méthodes qui correspondent ici à ces paramètres à cette liste là et on a dit que pour chaque élément ici ce premier channel de séquence va avoir un seul élément à la fois basé sur tous les fichiers tfa qu'on a à l'intérieur mais pour chacun des éléments qu'on va voir ici NextLow va combiner chacun des éléments de notre liste ici on retrouve bien ici pour chacun des éléments espresso, psychofi et régulare si je regarde tous les éléments je vais vraiment voir que j'ai tout tout ce qui se passe ici donc j'ai eu 18 process qui ont été exécutés au final parce que ici j'ai 3 méthodes différentes ici je regarde dans data niveau des protéines j'ai 1, 2, 3, 4, 5, 6 j'ai 6 fichiers tfa et 6 x 3 ça fait bien 18 donc on a bien toutes les possibilités qu'on a été faites à ce niveau-là moi c'est vrai que j'ai tendance à peu utiliser ses qualités j'ai tendance à plutôt créer ça moi-même en utilisant des opérateurs qui vont permettre de combiner les cannelles ensemble mais c'est toujours utile de voir ça donc niveau des output on va pouvoir faire la même chose on va pouvoir avoir en output des valeurs on va pouvoir avoir en output des fichiers on va pouvoir en output avoir des fichiers multiples si on utilise des globes on peut regarder ça c'est pas intéressant on peut avoir des non-fichiers dynamiques en sorties parce qu'on a utilisé une variable d'entrée ici donc on avait utilisé ici une variable donc ici notre sortie et le nom qu'on a trouvé ici qui va vraiment dépendre de notre entrée ça c'est très simple ça va nous permettre de faire des choses simples et de... Nexo a un peu d'intérêt sur la façon dont vous nommez vous-même vos fichiers et Nexo est juste intéressé par votre channel de la façon dont vous organisez votre channel donc après vous pouvez décider vous de nommer vos fichiers comment vous voulez et c'est ça que j'aime bien moi dans Nexo ici Composer alors avoir des input et output complètement composés donc ça c'est ce qu'on voit vraiment avec des tupples c'est quelque chose que j'aime beaucoup faire moi avoir des tupples ce qui me permet d'avoir d'un côté un simple ID et c'est quand même très pratique d'avoir un simple ID pour identifier chacun des échantillons dans lesquels on va faire des commandes et donc là ici on a ce process qui en entrée prend le simple ID qui est généré par from file pair et après on a un fichier on a un chemin un fichier avec un passe ici donc ici on a par exemple notre commande ça fait une commande juste d'exemple et on pourrait avoir une commande sur ces fichiers-là qui vont créer ces fichiers-là et après en sortie on récupère toujours notre simple ID et après notre fichier de sortie exercice donc modifier le script pour que vous avez le band file name il est given donc là ce qu'on va faire on voudrait récupérer simple ID pour le nom de fichier BAM et ce qu'on va faire c'est qu'on va utiliser la variable nextflow pour donner ce nom de sortie et donner effectivement le nom de sortie ici dans notre script utiliser when ça va être vraiment ça va nous permettre de bloquer ici d'autoriser l'exécution suivant plein de paramètres qu'on peut avoir que ce soit nos fichiers d'entrée ici par exemple on autorise l'exécution que si le nom du fichier FASTA correspond contient ce bout de chaines de caractère en utilisant ces trégecs et si la valeur type correspond à NR ce qui va nous permettre de faire un blast d'une certaine façon on va vraiment pouvoir utiliser when pour contrôler l'exécution d'un process directement dans le process sans s'occuper d'avoir des blocs if ou ce genre de jeu moi j'ai plutôt tendance à mettre des blocs if autour de mes process pour contrôler l'exécution mais c'est vrai que dans certains cas j'aime bien pouvoir contrôler ça avec des when when vraiment on va nous permettre cette possibilité et de nous permettre d'être encore plus flexible niveau des directives on va vraiment pouvoir donner toutes les informations supplémentaires sur notre process que ce soit les ressources CPU memory, time niveau des containers niveau des environnements condas tout ce qu'on veut est possible à ce niveau là il y a une liste complète ici qui va nous permettre et là on en a détaillé une petite partie moi ce que je concesse surtout c'est d'avoir un tag dans le process directement et généralement moi tout le reste j'ai tendance à avoir tout CPU, time et memory j'ai tendance à avoir ça plutôt dans mes fichiers de configuration ce qui va me permettre vraiment de découpler mon script en tant que tel de la configuration et être vraiment très portable on peut bien évidemment organiser tous nos fichiers sortis avec la directive publishdir ici on le voit publishdir publishdir va nous permettre de publier tout ce qu'on veut en partant ici d'un paramètre en particulier mais on peut choisir généralement c'est bien d'avoir un paramètre pour ça, ça va nous permettre directement de dire en entrée où c'est qu'on veut donner nos résultats donc voilà aussi avec publishdir on va pouvoir vraiment pouvoir si j'ai un fichier si j'ai un process qui va me récupérer plusieurs fichiers je vais pouvoir séparer tous ces fichiers dans différents dossiers en basant par exemple sur un pattern précis donc par exemple ici j'ai tous les fichiers fq qui vont être à la racine ici tous les fichiers count qui vont être dans un dossier count tous les fichiers outlook qui vont être dans un dossier outlook vous pouvez vraiment contrôler tout ce que vous voulez donc regardons maintenant les opérateurs donc les opérateurs vont être toutes les méthodes qui vont nous permettre de soit connecter qui vont être connectés à une channel et qui va nous permettre soit de transformer les valeurs ou d'appliquer des nouvelles règles sur cette channel qui va nous permettre peut-être de combiner deux channels ensemble il y a différentes sortes d'opérateurs il y a les opérateurs de fil qui vont nous permettre de filtrer les éléments d'un channel les opérateurs de transformation qui vont nous permettre de transformer les éléments à intérieur de la channel les opérateurs split qui vont vous permettre de séparer notre channel en différentes channels les opérateurs de combinaison qui vont nous permettre de combiner notre channel les opérateurs forts qui vont nous permettre encore de séparer notre channel mais différemment opérateurs mathématiques qui vont nous permettre de faire des opérations sur notre channel et d'autres opérateurs donc ici un exemple un exemple basique donc on a une première channel qui va appeler nums donc nombre qui va contenir quatre éléments et on crée une nouvelle channel square qui va contenir les éléments de la channel num qu'on va mapper donc map ça va vraiment nous permettre de récupérer des éléments d'entrée et de ressortir des éléments sortis et de transformer complètement la channel donc ici dans notre classe heat c'est-à-dire l'élément d'entrée implicite de la channel et on va redonner en sortie heat multiplié par lui-même donc bien évidemment on fait un carré donc ici ce qu'on va faire avec cette fonction map notre channel num va se transformer en channel square et 4 devient 16 3 devient 9, 2 devient 4, 1 reste 1 donc les opérateurs les plus courants vu qu'on a déjà vu qu'il va nous permettre de voir ce qu'il y a à l'intérieur d'une channel, on peut utiliser une closure spécifique qui va nous permettre de donner d'avoir d'avoir une sortie un peu plus jolie map convient de voir qu'il va nous permettre de complètement réorganiser ma channel et moi map c'est un des opérateurs que je dis le plus souvent et avec map on va vraiment pouvoir faire tout ce qu'on veut on va pouvoir enlever des éléments à notre channel, on va pouvoir en rajouter on va pouvoir réorganiser des éléments on va pouvoir donner des informations supplémentaires et il a fait ce qu'on peut faire donc ici utiliser frompass pour créer une channel émettant des fichiers fastq matchant ce pattern-là et réutiliser map pour faire une paire contenant le final et le chemin ça on l'a déjà fait précédemment voilà alors ici ah oui c'est frompass, on avait ça avec frompass ici ce qu'on va faire on va utiliser point name pour récupérer juste le nom du fichier et recréer ici donc pour chacun des éléments qui correspondent à ça on va recréer on va recréer un élément final qui va contenir le nom et le fichier et ici on va ficher ça mix va nous permettre de mixer des channels ensemble, ici je prends la channel 1 que je mixe la channel 2 je mixe la channel 3 et on voit j'ai mes éléments 1, 2, 3, A, B, Z qui vont se retrouver ici à notre route alors par contre il faut faire bien élément il faut faire bien attention ici le résultat final ici n'est pas forcément ne respecte pas forcément l'ordre original des éléments ici par exemple 1 on voit bien que la sortie on s'attendrait peut-être à avoir 1, 2, 3, A, B, Z mais on a 1, 2, A, 3, B, Z et ça va vraiment dépendre de comment l'ordinateur va traiter ça comment le processeur va traiter ça et donc à l'ordre ça lui arrive Flatten va nous permettre de transformer une liste en enfin d'appliquer complètement une liste et donc au lieu que notre liste contienne un élément on va avoir notre channel qui va avoir une instance un élément donc là c'est ce qu'on a ici on crée une channel basée de liste ici la liste 1, 2, 3 et ici la liste 4, 5, 6 que l'on a plattie ce qui nous permet de voir voilà c'est collect, c'est exactement l'étape inverte donc là ici on a une channel avec 4 éléments donc 4 éléments séparés donc 4 instances différentes et on va avoir à la fin une seule channel collect collect comme tous les opérateurs qui vont retourner une seule une seule donnée et est un opérateur qui va le permettre de créer des channels de value groupe topol est un opérateur que j'utilise très souvent qui va permettre de grouper ensemble ici j'ai une première channel qui va contenir plusieurs éléments donc plusieurs instances de plusieurs éléments donc ma première instance contient l'élément 1 et A deuxième instance l'élément 1 et B troisième instance 2C puis 3B puis 1C puis 2A puis 3D ce qu'on va faire avec un groupe topol groupe topol par défaut va grouper tous les éléments qui partagent le premier élément ici 1 on va récupérer les éléments A B et C pour 2 on va récupérer les éléments C et A et pour 3 on va récupérer les éléments B et D ici pour ça qu'on sortit on va avoir cette sortie donc c'est un opérateur très utile pour grouper ensemble des éléments qui partagent une clé commune voilà là on fait notre channel frompass qui contient tous les éléments de data meta on utilise map pour donner en sortie un topol tout d'abord un file.basename et après notre fichier qu'on va grouper tout sur le fichier et ici on va pouvoir voir volant notre nom du fichier et voilà notre fichier join va nous permettre de joindre ensemble 2 channels séparés voilà qui contiennent une clé qui contiennent une clé commune donc par défaut c'est le premier élément qu'est utilisé ici on a alors x qui va être ici donc on a x1,4 y qui va être ici donc 2 et 5 z qui va être ici donc 3 et 6 on a bien ici notre output on voit bien ici que P n'a rien matché donc c'est pour ça que P n'est pas dans notre output il y a des possibilités de récupérer donc c'est vraiment manquante aussi après join je vous conseille de regarder la documentation à ce niveau-là pour avoir tous les nouveaux supplémentaires branc va nous permettre de pouvoir séparer une channel en 2 channels suivant ce qu'il y a à l'intérieur de notre channel ici par exemple on a notre channel qui contient les éléments 1, 2, 3, 40 et 50 et on va détailler on va donner ici un branch on va lui dire de créer une nouvelle channel qui va s'appeler small et une nouvelle channel qui va s'appeler large qui va filtrer les éléments si ils sont inférieurs à 10 ils vont dans small si ils sont supérieurs à 10 ils vont dans large et tout ça va être dans la channel résulte et si on fait résulte point small on va avoir tous les éléments de mode première channel ici qui vont correspondre à cette définition et pareil pour résol point large ici donc branch va nous retourner un objet multi-channel c'est-à-dire une channel qui contient plusieurs channels donc les channels à plusieurs channels on les détaille avec un point ici pour récupérer la channel qui nous intéresse dans l'exemple ici il n'y a rien qui se passe si on a un élément qui est égal à 10 on n'a pas pris ça en compte donc on peut prendre ça en compte avec des infos supplémentaires on peut avoir aussi un autre élément qui va nous permettre de tout matcher on va vraiment pouvoir détailler ça de la façon dont on veut je conseille vraiment de regarder toutes les documentations sur les opérateurs c'est moi c'est ce que je fais tout le temps je vais regarder comment regarder tout ça comment améliorer comment réécrire des choses nous revoilà alors on va regarder maintenant un petit peu de groovy voir un peu comment ça se passe donc nextlaw c'est un langage qui est implémenté par-dessus groovy qui est lui-même un super set de Java donc ce qui veut dire qu'on peut utiliser du code groovy ou du code Java pour faire du nextlaw mais on vient de voir avant de la syntaxe maintenant on va regarder un peu de la syntaxe groovy donc println peut être très utile pour printer à l'écran des values donc la syntaxe et comme ceci avec ou sans parenthèse pour faire des commentaires soit double slash soit slash étoile pour ouvrir plusieurs lignes et on ferme par étoile slash pour définir une variable c'est très simple il suffit juste d'assigner une value à cette valeur et cela est fait on peut créer des variables locales avec dev et je vais conseiller généralement d'utiliser dev pour définir des variables locales quand on est dans une fonction ou une clausure les listes peuvent être définies et on peut attraper un élément d'une liste en spécifiant l'index l'index commence à zéro on peut utiliser la méthode size pour avoir la liste du la liste pour avoir la taille de la liste et cela marcher on peut utiliser le keyword assert pour vérifier si une valeur est bonne et si cela ne marche pas, on va avoir une erreur j'ai tendance à ne pas mettre de assert dans mon pipeline parce que je trouve cela pas très joli après c'est tout, on peut vraiment faire tout ce qu'on veut et là, c'est vraiment pour revoir toutes les possibilités qu'on peut avoir d'engrouvir sur les listes on peut utiliser tout ce que vous voulez à ce niveau-là on a déjà vu Flatten, un opérateur qu'on avait dans des clous, qu'on peut utiliser sur une liste pour vraiment aplatir toutes les listes reverse pour renverser on peut multiplier des listes on peut enlever des éléments sur des listes ou ajouter des éléments sur des listes on peut vraiment faire tout ce que l'on veut à ce niveau-là on peut compter le nombre de une liste compter combien il y a de valeur dans une liste quel est l'élément minimal faire la liste de tous les éléments trier une liste trouver dans une liste tous les le premier élément dont la division par 2 est nul ici ça va être 4 et tous les éléments dans la division par 2 est nul ici bien évidemment 4 et 2 une map ça va être quasiment comme une liste sauf que ça va être organisé c'est comme un dictionnaire avec un clé et une valeur donc ici nous avons créé un dictionnaire avec l'élément la clé 0 correspond à l'élément la clé A correspond à l'élément 0 et la clé C correspond à l'élément 2 ici on veut vérifier que la clé A correspond bien à l'élément 0 ici on vérifie que la clé B correspond à l'élément 1 et ici on vérifie que la clé C correspond bien à l'élément 2 ce sont 3 notifications pour définir exactement la même chose pour ajouter des données à un dictionnaire donc à une map soit déclarer un nouvel déclarer une nouvelle clé comme ceci ou soit rajouter un nouvel élément en utilisant les strings peuvent être on peut utiliser la méthode join pour récupérer toutes les couleurs toutes les lettres à l'intérieur de cette liste pour créer directement une couleur pour créer directement un mot ici à l'intérieur join va être utilisé pour dire on prend tous les éléments et on va les mettre les uns la suite des autres join va pouvoir prendre des paramètres supplémentaires qui vont permettre de dire je vais mettre un espace entre je vais mettre un caractère spécifique ça peut être très pratique et qu'on veut les séparer par un argument particulier je fais ça très souvent dans tant pas mal de quand je dis les outils d'utilité ou je paralyse beaucoup tous les inputs et je donne tous les inputs avec un tirer tirer i en entrée voilà ici donc on a bien utilisé tirer parce que c'est notre valeur ici foxtype tirer ici parce que c'est notre variable foxtype ici on ne veut pas le tirer on ne veut pas le dollar sur la variable foxtolor mais on veut le dollar sur tout sur l'opération join sur la variable foxtolor voilà et pour finir on peut utiliser on peut utiliser des des caractères pour délimiter des chaînes de caractère donc on peut utiliser le caractère le caractère c'est un slash donc le caractère slash pour désigner une chaîne de caractère donc ici mon x va contenir slash tick antislash tag antislash slash et quand on imprime ça nous imprime directement cette chaîne de caractère si on met tout ça entre guillemets antislash T on a déjà vu des strings multiline avec des triple cot on peut faire aussi des antislash on a vu dans le script dans les process précédemment pour les scripts qu'on peut utiliser des if on peut refaire ça ici dans notre script nextload moi je me sers beaucoup de if mais justement les process n'est pas utilisé de when parce que je trouve que le when va être un petit peu complexe sur la taille, la tâche et la lecture après vraiment c'est à vous de faire comme vous voulez le health est complètement optional on peut utiliser que le if on n'a pas forcément besoin non plus de mettre les acolades donc à vous vraiment de voir comment vous organisez comment vous écrivez votre texte moi j'essaye de faire en sorte que le code soit le plus facile à comprendre surtout quand on bosse en communauté dans des pipeline je suis malheureusement pas le seul à dire mon code et ça me permet d'avoir un code le plus j'espère simple possible et le plus compréhensible quelque chose qu'on va pouvoir faire aussi on va pouvoir remplacer un if par un if en terner donc ici on va alors ici ce qui se passe ça va être la même chose on veut on vérifie alors on veut printer la valeur liste si liste existe dans ce cas liste va contenir liste sinon si ça n'existe pas on va imprimer et liste en petit donc on peut aussi simplifier encore plus en supprimant liste ici ce qui va nous faire directement cette simple ligne là et c'est vraiment exactement la même chose que ceci ici c'est une autre façon de réécrire si on a simplifié comme ceci qu'on peut simplifier cela après c'est vraiment des types de langages qui vont venir au fur et à mesure donc je vous inquiétez pas trop au début si vous voyez ça moi généralement quand je fais ce genre de choses je mets toujours un commentaire pour détailler ce qui se passe pourquoi comment mais après du coup je vous conseille de faire pareil pareil on peut faire des des boucles forts j'ai tendance à pas trop faire le boucle en exclots parce que pour moi je vais gérer tout ce qui est parallelisation de manière avec des channels donc j'ai tendance à pas faire de forts mais si vous avez besoin de faire des boucles forts c'est possible de faire des boucles forts et on peut faire des fonctions dans des exclots je me sens assez souvent de faire des fonctions quand j'ai besoin de faire des petites manipulations en groovy sur des nombres ou peut-être sur des choses un peu plus compliquées sur des fichiers ou ce genre de choses vous avez besoin de créer des fonctions généralement je vais créer des fonctions toujours avec des fichiers pour dire je définis une fonction et ici on va définir ce que c'est la fonction est ce que la fonction retourne vous pouvez faire ça ça marche ici nous avons créé la fonction film qui va retourner un nombre qui va calculer le nombre de fibonacci et là on vérifie bien que pour 10 nous avons bien 89 voilà, là on a fait pareil pour déclarer le factorial donc on n'a pas forcément besoin de spécifier ce qu'on retourne spécifier ce qu'on retourne parce que c'est beaucoup beaucoup de choses sont faites de manière implicite l'éclosure on a vu ça précédemment mais très rapidement ça va être vraiment quelque chose de base dans les exclots donc c'est qu'on utilise très souvent enfin c'est dangereux mais c'est quelque chose qu'on utilise très souvent nous c'est un bloc de code qui va pouvoir être passé comme un argument à une fonction et ça peut être aussi utilisé pour définir une fonction anonyme ici par exemple on a défini une fonction square qui contient les éléments hit dans ce qui va nous faire une fonction carré et là on peut faire en fait square sur 5 va nous donner 25, square sur 9 va nous donner 81 et avec ces clujons là on va pouvoir vraiment contrôler et pousser les choses à tous les niveaux on peut faire par exemple utiliser cette méthode square sur un collecte ce qui va nous donner ici de tout ce que de tout notre de tout notre liste ici on va se retrouver avec ça donc par défaut les clujures prennent un seul élément hit c'est implicit mais on peut donner un autre nom à l'élément par défaut qui s'appelle l'homme si vous avez plusieurs éléments par défaut dans ce cas là hit sera une liste vous avez le premier élément qui sera hit 0 puis après hit 1, 2, 3 dans ce cas là je vais plutôt détailler tous mes éléments avec mon premier élément, mon deuxième, mon troisième et pouvoir après faire mes calculs ou mes organisations exactement comme ce que je vais faire ici dans une map ou ici là on veut imprimer et ici j'ai deux éléments A et B et on fait print $ avec value $B ce qu'on pourrait faire ici c'est avoir enlever ce A, B et flash et faire print $ $I crochet 0 $I crochet 1 voilà alors deux autres fonctionnalités importantes d'une clujure alors les clujures on peut accéder et modifier les variables dans le scope dans les cas de son défini je veux dire qu'on peut le faire ça de suite et deuxièmement ça peut être démini d'une manière totalement anonyme c'est-à-dire qu'on n'a même pas besoin de lui donner un nom et c'est défini juste à l'endroit où on le utilise donc ici tout est détaillé ici là nous allons définir la variable résultat A0, ici nous définissons une indexionnaire donc avec la clé chine que la valeur 1, 1 que la valeur 2, USA que la valeur 3 et ici hop la petite détaille on fait la méthode each pour chacun des éléments pour chacun des éléments et on va additionner dans result, chacune des valeurs de toutes les clés donc ici le résultat final devrait être 1, 2, 3 voilà pour plusieurs ressources je vais vous conseiller de regarder plutôt la due documentation si vous avez plus de questions là, elle est posée sur Slack voilà pour finir cette dernière partie de la session du jour donc partie sur modélisation donc on va voir ici qu'est-ce que c'est un module au sens de Nexlo donc on a vu hier un petit peu ce que c'était un module pour NFCore et donc vraiment ça va être sensiblement pareil désolé un module c'est quelque chose de nouveau dans Nexlo avec la version qui est celle-tout et ça va vraiment nous permettre de simplifier notre script principal en enlevant tous les process et en les mettant ailleurs donc et chaque module peut être un process ou une définition d'un workflow ce qui va vraiment nous permettre d'inclure tout ce qu'on veut donc on peut importer un statement include et c'est ce qu'on va faire de suite donc ici on a notre script de base qui est notre premier script qu'on avait vu le premier jour qui est le script hello.nf ce qu'on va faire, on va créer un nouveau vichier qu'on va appeler module.nf qui va contenir ces process j'ai un nouveau script ici module.hello.nf qui va contenir mes modules ici enfin mes process qui sont dans le module donc ici j'ai aussi d'inclure le process letter depuis le module depuis le vichier module.nf et ici j'ai aussi d'inclure le process convert to upper depuis le module.nf si j'essaie maintenant de faire nextflow run c'est module.hello.nf ça on va voir que ça va pas marcher du tout parce que mon process n'est pas appelé actuellement split letter convert to upper voilà et là on voit effectivement nextflow nous dit on n'a pas réussi à trouver un composant appelé comme ça tout simplement parce qu'ici dans module ils ont des majeurs celui donc on va arranger tout ça ici avec transform to uppercay ici transform to uppercay voilà tout simplement et là nous récupérons l'exécution du pipeline voilà donc on peut inclure sans souci quelque chose on a aussi d'autres possibilités où on peut choisir un module et de la liacé de lui donner un nom différent on va dire par ici je vais l'appeler juste split et ce qui va me permettre d'utiliser juste split au lieu de split letters on voit que ça va bien marcher et ce qui va nous permettre aussi de pouvoir réutiliser un module une seconde fois split je vais l'appeler split again donc là j'ai rajouté un nouveau process split again qui est la copie exacte du process split donc ça devrait rien changer vraiment à notre résultat parce qu'on a déjà utilisé le process split qui va splitter en 6 mais oh que s'est-il passé ici ah oui ça a fait complètement il y a une différence split nous donne un fichier text en sortie donc là j'ai split le nom du fichier text on retrouve ici la chunk je vais splitter en petit bout de chaines de caractère de 6 donc voilà j'ai été surpris au résultat mais c'est pour montrer que vraiment j'ai utilisé ça pour rajouter des infos supplémentaires donc je vais effacer cette bêtise et on va dire que nous n'avons rien vu voilà alors importer un module, ça s'est fait donc ici exercice créé, affichier, module.nf qui va contenir ce qu'on a avant donc on l'a créé, on l'a fait c'est exactement ce qu'on a fait des imports multiples oui on aurait pu inclus directement les deux avec une seule inclusion moi j'aime bien inclus un seul process par lit c'est plus clair pour moi mais c'est possible de faire ça et on peut faire un alias donc ce que je vous ai montré avant, sans soucis, on l'a fait ce qui va vraiment nous permettre de faire ça plusieurs fois et l'exercice la main c'est d'utiliser ça et d'essayer de deviner ce qui va se passer à l'écran on a un premier process split one convert to upper one split to convert to upper two moi je dirais ce qui va se passer tout simplement c'est qu'on va afficher deux fois hello world donc dans voilà c'était ça définition des output oui ça ça va être quelque chose de très intéressant pour nous on va pouvoir définir de manière explicite un output et donc nous même plus utiliser de channel donc ça va nous permettre de vraiment pas de s'implifier mais de d'aller beaucoup plus loin dans le code donc là je peux enlever le channel letter.ch et dire que c'est split point out je peux enlever le résule point ch et dire que c'est convert to upper point out et si j'essaye de relancer cela on va voir ce qui se passe voilà on a fait ça nous a redonné exactement la même chose parce qu'on a directement dit un Xflow d'utiliser d'utiliser toutes les infos tout seuls donc au moins un Xflow notre pipeline est très simplifié ah oui si on a plusieurs channels définis on peut utiliser les index 0 1 et etc pour avoir les différentes possibles ce qu'on peut faire qui va être mieux d'utiliser des index parce que ça c'est pas clair c'est d'utiliser emit quand on crée un process pour nommer notre output donc là on regarde ici on peut dire emit emit upper ce qui va nous permettre de faire ça alors on va récupérer ceci dans notre module voilà je veux que standard output passe dans un pas dans un output qui va s'appeler un output qui va émettre un output que je nomme upper et là ce que je vais pouvoir faire c'est dot.upper.ju converto.upper.out.upper.ju et ce qui va nous permettre de récupérer directement notre output qu'on va nommer voilà et ça ça va vraiment permettre quand on a plusieurs output de récupérer les outputs qu'on veut ou pas ah oui alors pipy les inputs moi c'est quelque chose que j'ai tendance de pas faire mais c'est quelque chose qu'on peut faire aussi ici par exemple on devrait pouvoir alors comment on a écrit ça ah oui d'accord donc ce qu'on fait on a notre cliquings ici qu'on a mis dans notre workflow ok donc ça c'est un channel ce qu'on va faire on va piper ça directement dans split on l'a pipé dans split qu'on va piper sur un flatten on va piper ça sur converto.upper et on va piper tout ça directement dans juin alors j'ai même pas besoin de mettre les parenthèses ici quand j'ai besoin de mettre les parenthèses là et si j'essaye ça on devrait avoir le même résultat vérification voilà exactement je pense qu'on peut même ici récupérer un name d'output juste pour vérifier je suis pas sûr mais là on va découvrir ensemble si ça marche non ah oui je vais juste tenter ça oui je pense que c'est ici ça devrait être ici qu'on devrait pouvoir le récupérer je sais pas si ça va marcher bon il doit y avoir moyen de récupérer un name output mais j'aime pas trop utiliser cette nousation là parce que bon oui c'est simple et tout mais c'est peut-être un peu trop simple et généralement ça plus que voir exactement tout ce qui se passe alors définition d'un workflow ça c'est ce qu'on a fait ici on a défini un workflow qui nous permet de définir un workflow comme on a dans nos modules ici on a un scope process c'est exactement la même chose et avec include on va pouvoir inclure que ce soit un workflow ou un process ça va être pour nextflow c'est la même chose voilà là on voit ça si je recopie ceci en workflow j'aime bien mettre des majuscules quand je fais des choses voilà et voilà et là on voit bien qu'on a appelé d'abord un premier workflow pipeline qui contient un module split et qui contient un module qu'on verte tout à peur et tout ça se fait sans aucun souci donc ici ceci peut être dans un fichier séparé tout peut être dans des fichiers séparés donc ça va permettre de vraiment pouvoir simplifier le code la logique va pouvoir être un petit peu plus compliquée et ça va vraiment pouvoir permettre de récupérer du code fait par d'autres personnes sans aucun souci c'est vraiment dans cette logique là où on est allé à fond dans cette logique là avec le répertoire sur github nfcore module où on a fait des petits encapsulateurs chacun des outils qu'on veut utiliser dans nfcore c'est un process qu'on est à fond là-dedans où on fait ça pour les modules et aussi pour les sous-bordes pour eux comme j'en ai parlé hier voilà alors ici voilà on va pouvoir spécifier pour un input dire qu'est-ce que cela doit prendre en entrée ici si on rajoute un input take ce qui se passe ça marche aussi bien ici on a défini notre workflow pipeline en lui disant qu'il doit prendre en entrée un paramètre greeting et après notre workflow en tant que tel commence ici après la section main il va commencer par créer une channel en se basant de ce qu'on a ici en entrée qu'on va après faire passer par split qu'on va après aplatir puis convertir en uppercase non en fait on convertit pas du tout en uppercase parce qu'on a pris la diéversion qu'on avait utilisé avant bon c'est pas grave et après on visualise et d'ici mon pipeline peut commencer directement juste sur le sur le paramètre que je donne en entrée donc quand on utilise take on a besoin de déclarer d'avoir utilisé main dans le reste du bloc et on peut directement aussi faire cela en pout oui c'est une bonne idée un channel off ça nous permet de s'implifier encore notre pipeline et là on voit notre pipeline commence avec greeting, split, flatten convert to uppercase donc convert to uppercase vu qu'il fait plus du tout du convert to uppercase je vais le renommer en reverse voilà notre pipeline split, reverse et il marche comme prévu on peut de la même façon qu'on a défini des inputs notre process on peut définir aussi des outputs donc emit va fonctionner de la même façon qu'on défine un emit pour un process notre pipeline je vais enlever le view du pipeline je vais rajouter emit c'est reverse et c'est plus uppercase c'est juste reverse revoyons mon module on appelle ça reverse on emit ça et ici je veux récupérer mon pipeline point out voilà on a encore la même chose voilà on peut utiliser la notation point out pour vraiment spécifier ce qu'on a ce qu'on aimait on peut aussi donner une clé ici pour savoir d'émettre si on est si on veut émettre plusieurs forties ça va pouvoir nous permettre de détailler ces différentes sorties par exemple ici j'ai envie d'émettre le reverse qui va être reverse point out et j'ai envie aussi de sortir le split qui va être donc ici si je fais pipeline out point reverse point view on va bien voir ce que je veux là si je vais en pipeline out en split point view on aurait voir les officiers sortis du process split et donc voilà c'est bien ça on a bien ici les officiers sortis du process split et on a bien ici les chaînes de caractère sortis du process reverse calling named workflow donc si on reprend euh ici ouais on pourrait refaire ce même chose là allez ah oui donc on peut décider de lancer notre pipeline workflow en utilisant point d'entrée uniquement un workflow avec un nom moi j'ai tendance à pas faire ça parce que ça peut compliquer des choses mais ça va permettre d'utiliser peut-être juste une partie du pipeline sans utiliser le pipeline tout entier donc c'est quelque chose de possible qui est important de savoir qu'on peut le faire alors ce qui est important de savoir c'est le scope des paramètres qu'est-ce qui est défini à quel niveau donc reprenons ici un script de module alors je vais tout effacer voilà notre script principal ilo.nf reprenons il est là ila workflow ilo.nf ça marche mais si je lui définis de nouveaux paramètres ou que va-t-il se passer si on fait ça il me renommait et le world qui est ce que nous avions ce que j'ai tapé moi en ligne de commande pas du tout ce qui était ici les paramètres ici ne sont pas pris en compte ici on a pris en compte les paramètres qui sont uniquement ici ce que nextflow a cette façon-là de voir les paramètres on va pas pouvoir réassigner des valeurs aux paramètres donc vraiment ces paramètres-là vont être pris en compte cela ne seront jamais pris en compte on peut utiliser add param pour étendre pour ajouter pour ajouter des paramètres ici donc si je vais ajouter add param avec hola à la place de hola il va m'afficher hola mon de hola j'ai isolé ma prononciation espagnole c'est passant donc voilà je vous conseillerai de dire vraiment si vous avez des questions sur comment passer d'un pipeline dsl1 en pipeline dsl2 ça peut être intéressant de voir ce qui va falloir changer à ce niveau-là on a un channel dédié à aider les gens pour passer d'un pipeline dsl1 un pipeline dsl2 donc si vous avez des questions à ce niveau-là n'hésitez pas de venir poser des questions j'espère que la session du jour vous a plu et on se revoit demain pour la dernière session merci de votre attention