Partie 2 : Hello Channels¶
Traduction assistée par IA - en savoir plus et suggérer des améliorations
Dans la Partie 1 de ce cours (Hello World), nous vous avons montré comment fournir une entrée variable à un processus en fournissant l'entrée directement dans l'appel du processus : sayHello(params.input).
C'était une approche délibérément simplifiée.
En pratique, cette approche a des limitations majeures ; à savoir qu'elle ne fonctionne que pour des cas très simples où nous voulons seulement exécuter le processus une fois, sur une seule valeur.
Dans la plupart des cas d'utilisation de flux de travail réalistes, nous voulons traiter plusieurs valeurs (données expérimentales pour plusieurs échantillons, par exemple), nous avons donc besoin d'une façon plus sophistiquée de gérer les entrées.
C'est à cela que servent les canaux Nextflow. Les canaux sont des files d'attente conçues pour gérer les entrées efficacement et les faire passer d'une étape à l'autre dans des flux de travail à plusieurs étapes, tout en fournissant un parallélisme intégré et de nombreux autres avantages.
Dans cette partie du cours, vous apprendrez à utiliser un canal pour gérer plusieurs entrées provenant de diverses sources différentes. Vous apprendrez également à utiliser des opérateurs pour transformer le contenu des canaux selon les besoins.
Comment commencer à partir de cette section
Cette section du cours suppose que vous avez terminé la Partie 1 du cours Hello Nextflow, mais si vous êtes à l'aise avec les bases couvertes dans cette section, vous pouvez commencer ici sans rien faire de spécial.
0. Échauffement : Exécuter hello-channels.nf¶
Nous allons utiliser le script de flux de travail hello-channels.nf comme point de départ.
Il est équivalent au script produit en suivant la Partie 1 de ce cours de formation, sauf que nous avons changé la destination de sortie :
Juste pour s'assurer que tout fonctionne, exécutez le script une fois avant d'apporter des modifications :
Sortie de la commande
Comme précédemment, vous trouverez le fichier de sortie nommé output.txt dans le répertoire results/hello_channels (comme spécifié dans le bloc output du script de flux de travail, montré ci-dessus).
Contenu du répertoire
Si cela a fonctionné pour vous, vous êtes prêt·e à apprendre les canaux.
1. Fournir des entrées variables via un canal explicitement¶
Nous allons créer un canal pour passer l'entrée variable au processus sayHello() au lieu de compter sur la gestion implicite, qui a certaines limitations.
1.1. Créer un canal d'entrée¶
Il existe une variété de fabriques de canaux que nous pouvons utiliser pour configurer un canal.
Pour garder les choses simples pour l'instant, nous allons utiliser la fabrique de canaux la plus basique, appelée channel.of, qui créera un canal contenant une seule valeur.
Fonctionnellement, ce sera similaire à la configuration que nous avions avant, mais au lieu de laisser Nextflow créer un canal implicitement, nous le faisons explicitement maintenant.
Voici la ligne de code que nous allons utiliser :
Cela crée un canal appelé greeting_ch en utilisant la fabrique de canaux channel.of(), qui configure un simple canal de file d'attente, et charge la chaîne 'Hello Channels!' à utiliser comme valeur de salutation.
Note
Nous revenons temporairement aux chaînes codées en dur au lieu d'utiliser un paramètre CLI pour des raisons de lisibilité. Nous reviendrons à l'utilisation des paramètres CLI une fois que nous aurons couvert ce qui se passe au niveau du canal.
Dans le bloc workflow, ajoutez le code de la fabrique de canaux :
Ce n'est pas encore fonctionnel puisque nous n'avons pas encore changé l'entrée vers l'appel du processus.
1.2. Ajouter le canal comme entrée à l'appel du processus¶
Maintenant nous devons effectivement brancher notre canal nouvellement créé dans l'appel du processus sayHello(), remplaçant le paramètre CLI que nous fournissions directement avant.
Dans le bloc workflow, faites la modification de code suivante :
Cela indique à Nextflow d'exécuter le processus sayHello sur le contenu du canal greeting_ch.
Maintenant notre flux de travail est correctement fonctionnel ; c'est l'équivalent explicite d'écrire sayHello('Hello Channels!').
1.3. Exécuter le flux de travail¶
Exécutons-le !
Sortie de la commande
Si vous avez fait les deux modifications correctement, vous devriez obtenir une exécution réussie. Vous pouvez vérifier le répertoire des résultats pour vous assurer que le résultat est toujours le même qu'avant.
Nous avons donc augmenté la flexibilité de notre flux de travail tout en obtenant le même résultat final. Cela peut sembler que nous écrivons plus de code sans bénéfice tangible, mais la valeur deviendra claire dès que nous commencerons à gérer plus d'entrées.
En avant-première, regardons une chose de plus avant de passer à la suite : un petit avantage pratique de l'utilisation d'un canal explicite pour gérer l'entrée de données.
1.4. Utiliser view() pour inspecter le contenu du canal¶
Les canaux Nextflow sont construits d'une manière qui nous permet d'opérer sur leur contenu en utilisant des opérateurs, que nous couvrirons en détail plus tard dans ce chapitre.
Pour l'instant, nous allons juste vous montrer comment utiliser un opérateur super simple appelé view() pour inspecter le contenu d'un canal.
Vous pouvez considérer view() comme un outil de débogage, comme une instruction print() en Python, ou son équivalent dans d'autres langages.
Ajoutez cette petite ligne au bloc workflow :
La quantité exacte d'espaces n'a pas d'importance tant que c'est un multiple de 4 ; nous visons juste à aligner le début de l'instruction .view() avec la partie .of() de la construction du canal.
Maintenant exécutez à nouveau le flux de travail :
Sortie de la commande
Comme vous pouvez le voir, cela affiche le contenu du canal dans la console. Ici, nous n'avons qu'un élément, mais quand nous commencerons à charger plusieurs valeurs dans le canal dans la section suivante, vous verrez que cela est configuré pour afficher un élément par ligne.
À retenir¶
Vous savez comment utiliser une fabrique de canaux de base pour fournir une entrée à un processus.
Et ensuite ?¶
Apprendre à utiliser les canaux pour faire itérer le flux de travail sur plusieurs valeurs d'entrée.
2. Modifier le flux de travail pour s'exécuter sur plusieurs valeurs d'entrée¶
Les flux de travail s'exécutent généralement sur des lots d'entrées destinés à être traités en masse, nous voulons donc améliorer le flux de travail pour accepter plusieurs valeurs d'entrée.
2.1. Charger plusieurs salutations dans le canal d'entrée¶
De façon pratique, la fabrique de canaux channel.of() que nous utilisons est tout à fait capable d'accepter plus d'une valeur, donc nous n'avons pas besoin de la modifier du tout.
Nous pouvons simplement charger plusieurs valeurs dans le canal.
Mettons 'Hello', 'Bonjour' et 'Holà'.
Dans le diagramme, le canal est représenté en vert, et l'ordre des éléments est représenté comme des billes dans un tuyau : le premier chargé est à droite, puis le deuxième au milieu, puis le troisième est à gauche.
2.1.1. Ajouter plus de salutations¶
Avant le bloc workflow, faites la modification de code suivante :
La documentation nous dit que cela devrait fonctionner. Cela peut-il vraiment être aussi simple ?
2.1.2. Exécuter la commande et regarder la sortie du log¶
Essayons.
Sortie de la commande
Cela semble avoir bien fonctionné.
Le moniteur d'exécution montre que 3 of 3 appels ont été effectués pour le processus sayHello, et nous voyons les trois salutations énumérées par l'instruction view(), une par ligne comme promis.
Cependant, il n'y a toujours qu'une seule sortie dans le répertoire des résultats :
Contenu du répertoire
Vous devriez voir l'une des trois salutations dedans, mais celle que vous avez obtenue pourrait être différente de ce qui est montré ici. Pouvez-vous deviner pourquoi ?
En regardant le moniteur d'exécution, il nous a donné seulement un chemin de sous-répertoire (f4/c9962c).
Jetons un coup d'œil dedans.
Contenu du répertoire
Ce n'est même pas la même salutation que nous avons obtenue dans le répertoire des résultats ! Que se passe-t-il ?
À ce stade, nous devons vous dire que par défaut, le système de journalisation ANSI écrit les logs de plusieurs appels au même processus sur la même ligne. Donc le statut des trois appels au processus sayHello() atterrissent au même endroit.
Heureusement, nous pouvons désactiver ce comportement pour voir la liste complète des appels de processus.
2.1.3. Exécuter à nouveau la commande avec l'option -ansi-log false¶
Pour développer la journalisation afin d'afficher une ligne par appel de processus, ajoutez -ansi-log false à la commande.
Sortie de la commande
Cette fois nous voyons les trois exécutions de processus et leurs sous-répertoires de travail associés listés dans la sortie.
C'est beaucoup mieux, au moins pour un flux de travail simple.
Pour un flux de travail complexe, ou un grand nombre d'entrées, avoir la liste complète affichée dans le terminal deviendrait un peu accablant.
C'est pourquoi -ansi-log false n'est pas le comportement par défaut.
Astuce
La façon dont le statut est rapporté est un peu différente entre les deux modes de journalisation. Dans le mode condensé, Nextflow rapporte si les appels se sont terminés avec succès ou non. Dans ce mode étendu, il rapporte seulement qu'ils ont été soumis.
De toute façon, maintenant que nous avons les sous-répertoires de chaque appel de processus, nous pouvons chercher leurs logs et sorties.
Contenu du répertoire
work/23/871c7ec3642a898ecd5e6090d21300/
├── .command.begin
├── .command.err
├── .command.log
├── .command.out
├── .command.run
├── .command.sh
├── .exitcode
└── output.txt
Contenu des fichiers
Cela montre que les trois processus se sont exécutés avec succès (youpi).
Cela dit, nous avons toujours le problème qu'il n'y a qu'un seul fichier de sortie dans le répertoire des résultats.
Vous vous souvenez peut-être que nous avions codé en dur le nom du fichier de sortie pour le processus sayHello, donc les trois appels ont produit un fichier appelé output.txt.
Tant que les fichiers de sortie restent dans les sous-répertoires de travail, isolés des autres processus, c'est correct. Mais quand ils sont publiés dans le même répertoire de résultats, celui qui a été copié là en premier est écrasé par le suivant, et ainsi de suite.
2.2. S'assurer que les noms de fichiers de sortie seront uniques¶
Nous pouvons continuer à publier toutes les sorties dans le même répertoire de résultats, mais nous devons nous assurer qu'elles auront des noms uniques. Spécifiquement, nous devons modifier le premier processus pour générer un nom de fichier dynamiquement afin que les noms de fichiers finaux soient uniques.
Alors comment rendre les noms de fichiers uniques ? Une façon courante de le faire est d'utiliser une pièce unique de métadonnées des entrées (reçues du canal d'entrée) comme partie du nom du fichier de sortie. Ici, pour plus de commodité, nous utiliserons simplement la salutation elle-même puisque c'est juste une courte chaîne, et la préfixerons au nom de fichier de sortie de base.
2.2.1. Construire un nom de fichier de sortie dynamique¶
Dans le bloc process, faites les modifications de code suivantes :
Assurez-vous de remplacer output.txt à la fois dans la définition de sortie et dans le bloc de commande script:.
Astuce
Dans la définition de sortie, vous DEVEZ utiliser des guillemets doubles autour de l'expression du nom de fichier de sortie (PAS des guillemets simples), sinon cela échouera.
Cela devrait produire un nom de fichier de sortie unique chaque fois que le processus est appelé, afin qu'il puisse être distingué des sorties d'autres appels au même processus dans le répertoire de sortie.
2.2.2. Exécuter le flux de travail¶
Exécutons-le. Notez que nous revenons à l'exécution avec les paramètres de log ANSI par défaut.
Sortie de la commande
En revenant à la vue résumée, la sortie est à nouveau résumée sur une ligne.
Jetez un œil au répertoire results pour voir si toutes les salutations de sortie y sont.
Contenu du répertoire
Oui ! Et chacune a le contenu attendu.
Succès ! Maintenant nous pouvons ajouter autant de salutations que nous voulons sans nous soucier de l'écrasement des fichiers de sortie.
Astuce
En pratique, nommer les fichiers en fonction des données d'entrée elles-mêmes est presque toujours peu pratique. La meilleure façon de générer des noms de fichiers dynamiques est de passer des métadonnées à un processus avec les fichiers d'entrée. Les métadonnées sont généralement fournies via une « feuille d'échantillons » ou équivalents. Vous apprendrez comment faire cela plus tard dans votre formation Nextflow (voir la quête annexe sur les métadonnées).
À retenir¶
Vous savez comment alimenter plusieurs éléments d'entrée à travers un canal.
Et ensuite ?¶
Apprendre à utiliser un opérateur pour transformer le contenu d'un canal.
3. Fournir plusieurs entrées via un tableau¶
Nous venons de vous montrer comment gérer plusieurs éléments d'entrée qui étaient codés en dur directement dans la fabrique de canaux. Et si nous voulions fournir ces entrées multiples d'une manière différente ?
Par exemple, imaginez que nous configurions une variable d'entrée contenant un tableau d'éléments comme ceci :
greetings_array = ['Hello','Bonjour','Holà']
Pouvons-nous charger cela dans notre canal de sortie et nous attendre à ce que ça fonctionne ?
Découvrons-le.
3.1. Fournir un tableau de valeurs comme entrée au canal¶
Le bon sens suggère que nous devrions pouvoir simplement passer un tableau de valeurs au lieu d'une seule valeur. Essayons ; nous devrons configurer la variable d'entrée et la charger dans la fabrique de canaux.
3.1.1. Configurer la variable d'entrée¶
Prenons la variable greetings_array que nous venons d'imaginer et rendons-la réelle en l'ajoutant au bloc workflow :
| hello-channels.nf | |
|---|---|
Ce n'est pas encore fonctionnel, nous avons juste ajouté une déclaration pour le tableau.
3.1.2. Définir le tableau de salutations comme entrée de la fabrique de canaux¶
Maintenant nous allons remplacer les valeurs 'Hello','Bonjour','Holà' actuellement codées en dur dans la fabrique de canaux par le greetings_array que nous venons de créer.
Dans le bloc workflow, faites la modification suivante :
| hello-channels.nf | |
|---|---|
| hello-channels.nf | |
|---|---|
Cela devrait être fonctionnel maintenant.
3.1.3. Exécuter le flux de travail¶
Essayons de l'exécuter :
Sortie de la commande
N E X T F L O W ~ version 25.10.2
Launching `hello-channels.nf` [friendly_koch] DSL2 - revision: 97256837a7
executor > local (1)
[a8/1f6ead] sayHello (1) | 0 of 1
[Hello, Bonjour, Holà]
ERROR ~ Error executing process > 'sayHello (1)'
Caused by:
Missing output file(s) `[Hello, Bonjour, Holà]-output.txt` expected by process `sayHello (1)`
Command executed:
echo '[Hello, Bonjour, Holà]' > '[Hello, Bonjour, Holà]-output.txt'
Command exit status:
0
Command output:
(empty)
Work dir:
/workspaces/training/hello-nextflow/work/a8/1f6ead5f3fa30a3c508e2e7cf83ffb
Tip: you can replicate the issue by changing to the process work dir and entering the command `bash .command.run`
-- Check '.nextflow.log' file for details
Oh non ! Il y a une erreur !
Regardez la sortie de view() et les messages d'erreur.
On dirait que Nextflow a essayé d'exécuter un seul appel de processus, en utilisant [Hello, Bonjour, Holà] comme valeur de chaîne, au lieu d'utiliser les trois chaînes dans le tableau comme valeurs séparées.
Donc c'est l'« emballage » qui cause le problème. Comment faire pour que Nextflow déballe le tableau et charge les chaînes individuelles dans le canal ?
3.2. Utiliser un opérateur pour transformer le contenu du canal¶
C'est là que les opérateurs entrent en jeu.
Vous avez déjà utilisé l'opérateur .view(), qui regarde juste ce qu'il y a à l'intérieur.
Maintenant nous allons regarder les opérateurs qui nous permettent d'agir sur le contenu d'un canal.
Si vous parcourez la liste des opérateurs dans la documentation Nextflow, vous trouverez flatten(), qui fait exactement ce dont nous avons besoin : déballer le contenu d'un tableau et les émettre comme éléments individuels.
3.2.1. Ajouter l'opérateur flatten()¶
Pour appliquer l'opérateur flatten() à notre canal d'entrée, nous l'ajoutons à la déclaration de la fabrique de canaux.
Dans le bloc workflow, faites la modification de code suivante :
| hello-channels.nf | |
|---|---|
| hello-channels.nf | |
|---|---|
Ici nous avons ajouté l'opérateur sur la ligne suivante pour la lisibilité, mais vous pouvez ajouter des opérateurs sur la même ligne que la fabrique de canaux si vous préférez, comme ceci :
greeting_ch = channel.of(greetings_array).view().flatten()
3.2.2. Affiner les instructions view()¶
Nous pourrions exécuter cela tout de suite pour tester si ça fonctionne, mais pendant qu'on y est, nous allons affiner la façon dont nous inspectons le contenu du canal.
Nous voulons pouvoir contraster ce à quoi ressemble le contenu avant et après l'application de l'opérateur flatten(), donc nous allons en ajouter un second, ET nous allons ajouter un peu de code pour les étiqueter plus clairement dans la sortie.
Dans le bloc workflow, faites la modification de code suivante :
| hello-channels.nf | |
|---|---|
Vous voyez que nous avons ajouté une deuxième instruction .view, et pour chacune d'elles, nous avons remplacé les parenthèses vides (()) par des accolades contenant du code, tel que { greeting -> "Before flatten: $greeting" }.
Ce sont des closures. Le code qu'elles contiennent sera exécuté pour chaque élément dans le canal.
Nous définissons une variable temporaire pour la valeur interne, ici appelée greeting (mais ce pourrait être n'importe quel nom arbitraire), qui n'est utilisée que dans la portée de cette closure.
Dans cet exemple, $greeting représente chaque élément individuel chargé dans le canal.
Cela donnera une sortie console bien étiquetée.
Information
Dans certains pipelines, vous pourriez voir une variable spéciale appelée $it utilisée à l'intérieur des closures d'opérateurs.
C'est une variable implicite qui permet un accès raccourci à la variable interne,
sans avoir besoin de la définir avec un ->.
Nous préférons être explicites pour aider à la clarté du code, ainsi la syntaxe $it est découragée et sera progressivement supprimée du langage Nextflow.
3.2.3. Exécuter le flux de travail¶
Finalement, vous pouvez essayer d'exécuter à nouveau le flux de travail !
Sortie de la commande
Cette fois ça fonctionne ET nous donne l'aperçu supplémentaire de ce à quoi ressemble le contenu du canal avant et après l'exécution de l'opérateur flatten().
- Vous voyez que nous obtenons une seule instruction
Before flatten:parce qu'à ce moment le canal contient un élément, le tableau original. Ensuite nous obtenons trois instructionsAfter flatten:séparées, une pour chaque salutation, qui sont maintenant des éléments individuels dans le canal.
De manière importante, cela signifie que chaque élément peut maintenant être traité séparément par le flux de travail.
Astuce
Il est techniquement possible d'obtenir les mêmes résultats en utilisant une fabrique de canaux différente, channel.fromList, qui inclut une étape de mapping implicite dans son fonctionnement.
Ici nous avons choisi de ne pas l'utiliser afin de démontrer l'utilisation d'un opérateur sur un cas d'utilisation simple.
À retenir¶
Vous savez comment utiliser un opérateur comme flatten() pour transformer le contenu d'un canal, et comment utiliser l'opérateur view() pour inspecter le contenu du canal avant et après l'application d'un opérateur.
Et ensuite ?¶
Apprendre à faire prendre au flux de travail un fichier comme source de valeurs d'entrée.
4. Lire les valeurs d'entrée depuis un fichier CSV¶
De façon réaliste, nous allons rarement, voire jamais, commencer à partir d'un tableau de valeurs. Le plus probable est que nous aurons un ou plusieurs fichiers contenant les données qui doivent être traitées, dans un format structuré quelconque.
Nous avons préparé un fichier CSV appelé greetings.csv qui contient plusieurs salutations d'entrée, imitant le type de données tabulaires que vous pourriez vouloir traiter dans une analyse de données réelle, stocké sous data/.
(Les nombres ne sont pas significatifs, ils sont juste là à des fins d'illustration.)
Notre prochaine tâche est d'adapter notre flux de travail pour lire les valeurs de ce fichier.
Voyons comment nous pouvons faire cela.
4.1. Modifier le script pour attendre un fichier CSV comme source de salutations¶
Pour commencer, nous allons devoir faire deux changements clés au script :
- Changer le paramètre d'entrée pour pointer vers le fichier CSV
- Changer la fabrique de canaux pour une conçue pour gérer un fichier
4.1.1. Changer le paramètre d'entrée pour pointer vers le fichier CSV¶
Vous vous souvenez du paramètre params.input que nous avons configuré dans la Partie 1 ?
Nous allons le mettre à jour pour pointer vers le fichier CSV contenant nos salutations.
Faites la modification suivante à la déclaration du paramètre :
Cela suppose que le fichier est co-localisé avec le code du flux de travail. Vous apprendrez comment gérer d'autres emplacements de données plus tard dans votre parcours Nextflow.
4.1.2. Passer à une fabrique de canaux conçue pour gérer un fichier¶
Puisque nous voulons maintenant utiliser un fichier au lieu de simples chaînes comme entrée, nous ne pouvons pas utiliser la fabrique de canaux channel.of() d'avant.
Nous devons passer à l'utilisation d'une nouvelle fabrique de canaux, channel.fromPath(), qui a une fonctionnalité intégrée pour gérer les chemins de fichiers.
Dans le bloc workflow, faites la modification de code suivante :
Vous remarquerez que nous avons rechangé l'entrée du canal en param.input, et supprimé la déclaration greetings_array puisque nous n'en aurons plus besoin.
Nous avons également commenté le flatten() et la deuxième instruction view().
4.1.3. Exécuter le flux de travail¶
Essayons d'exécuter le flux de travail avec la nouvelle fabrique de canaux et le fichier d'entrée.
Sortie de la commande
N E X T F L O W ~ version 25.10.2
Launching `hello-channels.nf` [peaceful_poisson] DSL2 - revision: a286c08ad5
[- ] sayHello [ 0%] 0 of 1
Before flatten: /workspaces/training/hello-nextflow/data/greetings.csv
ERROR ~ Error executing process > 'sayHello (1)'
Caused by:
File `/workspaces/training/hello-nextflow/data/greetings.csv-output.txt` is outside the scope of the process work directory: /workspaces/training/hello-nextflow/work/30/e610cb4ea5ae8693f456ac3329c92f
Command executed:
echo '/workspaces/training/hello-nextflow/data/greetings.csv' > '/workspaces/training/hello-nextflow/data/greetings.csv-output.txt'
Command exit status:
-
Command output:
(empty)
Work dir:
/workspaces/training/hello-nextflow/work/30/e610cb4ea5ae8693f456ac3329c92f
Tip: when you have fixed the problem you can continue the execution adding the option `-resume` to the run command line
-- Check '.nextflow.log' file for details
Oh non, ça ne fonctionne pas. Regardez le début de la sortie console et le message d'erreur.
La partie Command executed: est particulièrement utile ici.
Cela peut sembler un peu familier. On dirait que Nextflow a essayé d'exécuter un seul appel de processus en utilisant le chemin du fichier lui-même comme valeur de chaîne. Donc il a résolu le chemin du fichier correctement, mais il n'a pas réellement analysé son contenu, ce qui est ce que nous voulions.
Comment faire pour que Nextflow ouvre le fichier et charge son contenu dans le canal ?
On dirait qu'on a besoin d'un autre opérateur !
4.2. Utiliser l'opérateur splitCsv() pour analyser le fichier¶
En parcourant à nouveau la liste des opérateurs, nous trouvons splitCsv(), qui est conçu pour analyser et diviser le texte au format CSV.
4.2.1. Appliquer splitCsv() au canal¶
Pour appliquer l'opérateur, nous l'ajoutons à la ligne de la fabrique de canaux comme précédemment.
Dans le bloc workflow, faites la modification de code suivante pour remplacer flatten() par splitcsv() (décommenté) :
| hello-channels.nf | |
|---|---|
Comme vous pouvez le voir, nous avons également mis à jour les instructions view() avant/après.
Techniquement nous aurions pu utiliser le même nom de variable (greeting) mais nous l'avons mis à jour en quelque chose de plus approprié (csv) pour rendre le code plus lisible par les autres.
4.2.2. Exécuter à nouveau le flux de travail¶
Essayons d'exécuter le flux de travail avec la logique d'analyse CSV ajoutée.
Sortie de la commande
N E X T F L O W ~ version 25.10.2
Launching `hello-channels.nf` [insane_fermat] DSL2 - revision: 8e62fcbeb1
executor > local (3)
[24/76da2f] sayHello (2) [ 0%] 0 of 3 ✘
Before splitCsv: /workspaces/training/hello-nextflow/data/greetings.csv
After splitCsv: [Hello, English, 123]
After splitCsv: [Bonjour, French, 456]
After splitCsv: [Holà, Spanish, 789]
ERROR ~ Error executing process > 'sayHello (2)'
Caused by:
Missing output file(s) `[Bonjour, French, 456]-output.txt` expected by process `sayHello (2)`
Command executed:
echo '[Bonjour, French, 456]' > '[Bonjour, French, 456]-output.txt'
Command exit status:
0
Command output:
(empty)
Work dir:
/workspaces/training/hello-nextflow/work/24/76da2fcc4876b61632749f99e26a50
Tip: you can try to figure out what's wrong by changing to the process work dir and showing the script file named `.command.sh`
-- Check '.nextflow.log' file for details
Intéressant, cela échoue aussi, mais avec une erreur différente. Cette fois Nextflow a analysé le contenu du fichier (youpi !) mais il a chargé chaque ligne comme un tableau, et chaque tableau est un élément dans le canal.
Nous devons lui dire de ne prendre que la première colonne de chaque ligne. Alors comment déballer cela ?
Nous avons précédemment utilisé flatten() pour déballer le contenu d'un canal, mais cela ne fonctionnerait pas ici parce que flatten déballe tout (n'hésitez pas à l'essayer si vous voulez voir par vous-même).
À la place, nous utiliserons un autre opérateur appelé map() qui est vraiment utile et apparaît beaucoup dans les pipelines Nextflow.
4.3. Utiliser l'opérateur map() pour extraire les salutations¶
L'opérateur map() est un petit outil très pratique qui nous permet de faire toutes sortes de mappings sur le contenu d'un canal.
Dans ce cas, nous allons l'utiliser pour extraire cet unique élément que nous voulons de chaque ligne dans notre fichier de données. Voici à quoi ressemble la syntaxe :
Cela signifie « pour chaque ligne dans le canal, prendre le 0ème (premier) élément qu'elle contient ».
Appliquons donc cela à notre analyse CSV.
4.3.1. Appliquer map() au canal¶
Dans le bloc workflow, faites la modification de code suivante :
| hello-channels.nf | |
|---|---|
Vous voyez que nous avons ajouté un autre appel view() pour confirmer que l'opérateur fait ce que nous attendons.
4.3.2. Exécuter le flux de travail¶
Exécutons cela une fois de plus :
Sortie de la commande
N E X T F L O W ~ version 25.10.2
Launching `hello-channels.nf` [focused_volhard] DSL2 - revision: de435e45be
executor > local (3)
[54/6eebe3] sayHello (3) [100%] 3 of 3 ✔
Before splitCsv: /workspaces/training/hello-nextflow/data/greetings.csv
After splitCsv: [Hello, English, 123]
After splitCsv: [Bonjour, French, 456]
After splitCsv: [Holà, Spanish, 789]
After map: Hello
After map: Bonjour
After map: Holà
Cette fois cela devrait s'exécuter sans erreur.
En regardant la sortie des instructions view(), vous voyez ce qui suit :
- Une seule instruction
Before splitCsv:: à ce moment le canal contient un élément, le chemin du fichier original. - Trois instructions
After splitCsv:séparées : une pour chaque salutation, mais chacune est contenue dans un tableau qui correspond à cette ligne dans le fichier. - Trois instructions
After map:séparées : une pour chaque salutation, qui sont maintenant des éléments individuels dans le canal.
Notez que les lignes peuvent apparaître dans un ordre différent dans votre sortie.
Vous pouvez également regarder les fichiers de sortie pour vérifier que chaque salutation a été correctement extraite et traitée à travers le flux de travail.
Nous avons obtenu le même résultat qu'avant, mais maintenant nous avons beaucoup plus de flexibilité pour ajouter plus d'éléments au canal de salutations que nous voulons traiter en modifiant un fichier d'entrée, sans modifier aucun code. Vous apprendrez des approches plus sophistiquées pour gérer des entrées complexes dans une formation ultérieure.
À retenir¶
Vous savez comment utiliser le constructeur de canal .fromPath() et les opérateurs splitCsv() et map() pour lire un fichier de valeurs d'entrée et les gérer de manière appropriée.
Plus généralement, vous avez une compréhension de base de la façon dont Nextflow utilise les canaux pour gérer les entrées vers les processus et les opérateurs pour transformer leur contenu.
Et ensuite ?¶
Prenez une grande pause, vous avez travaillé dur sur celui-ci !
Quand vous êtes prêt·e, passez à la Partie 3 : Hello Workflow pour apprendre comment ajouter plus d'étapes et les connecter ensemble dans un vrai flux de travail.
Quiz¶
Qu'est-ce qu'un canal dans Nextflow ?
Quand un canal contient plusieurs valeurs, comment Nextflow gère-t-il l'exécution du processus ?
Que fait l'opérateur flatten() ?
Quel est le but de l'opérateur view() ?
Que fait splitCsv() ?
Quel est le but de l'opérateur map() ?
Pourquoi est-il important d'utiliser des noms de fichiers de sortie dynamiques lors du traitement de plusieurs entrées ?