Salta el contingut

Part 3: Hello Workflow

Traducció assistida per IA - més informació i suggeriments

Consulteu la llista de reproducció completa al canal de YouTube de Nextflow.

📗 La transcripció del vídeo està disponible aquí.

La majoria de workflows del món real impliquen més d'un pas. En aquest mòdul de formació, aprendreu com connectar processos junts en un workflow de múltiples passos.

Això us ensenyarà la manera Nextflow d'aconseguir el següent:

  1. Fer que les dades flueixin d'un procés al següent
  2. Recollir sortides de múltiples crides de procés en una única crida de procés
  3. Passar paràmetres addicionals a un procés
  4. Gestionar múltiples sortides que surten d'un procés

Per demostrar-ho, continuarem construint sobre l'exemple Hello World independent del domini de les Parts 1 i 2. Aquesta vegada, farem els següents canvis al nostre workflow per reflectir millor com la gent construeix workflows reals:

  1. Afegir un segon pas que converteixi la salutació a majúscules.
  2. Afegir un tercer pas que reculli totes les salutacions transformades i les escrigui en un únic fitxer.
  3. Afegir un paràmetre per nomenar el fitxer de sortida final i passar-lo com a entrada secundària al pas de recollida.
  4. Fer que el pas de recollida també informi d'una estadística simple sobre el que s'ha processat.
Com començar des d'aquesta secció

Aquesta secció del curs assumeix que heu completat les Parts 1-2 del curs Hello Nextflow, però si us sentiu còmodes amb els conceptes bàsics coberts en aquestes seccions, podeu començar des d'aquí sense fer res especial.


0. Escalfament: Executeu hello-workflow.nf

Utilitzarem l'script de workflow hello-workflow.nf com a punt de partida. És equivalent a l'script produït en treballar la Part 2 d'aquest curs de formació, excepte que hem eliminat les instruccions view() i hem canviat la destinació de sortida:

hello-workflow.nf
output {
    first_output {
        path 'hello_workflow'
        mode 'copy'
    }
}

Aquest diagrama resumeix l'operació actual del workflow. Hauria de semblar familiar, excepte que ara estem mostrant explícitament que les sortides del procés s'empaqueten en un canal, igual que les entrades. Utilitzarem aquest canal de sortida en un moment.

sayHello('Hello')Hello-output.txtBonjour-output.txtHolà-output.txtprocess callssayHello('Bonjour')sayHello('Holà')HolàBonjourHelloinput channeloutput channelHello, English, 123 Bonjour, French, 456Holà, Spanish, 789greetings.csv.splitCsv().map { row -> row[0] }Channel.fromPath()HelloBonjourHolàHello-output.txtBonjour-output.txtHolà-output.txtpublished outputs

Només per assegurar-nos que tot funciona, executeu l'script una vegada abans de fer cap canvi:

nextflow run hello-workflow.nf
Sortida de la comanda
 N E X T F L O W   ~  version 25.10.2

Launching `hello-workflow.nf` [admiring_lamarr] DSL2 - revision: 4d4053520d

executor >  local (3)
[b1/5826b5] process > sayHello (2) [100%] 3 of 3 ✔

Com abans, trobareu els fitxers de sortida a la ubicació especificada al bloc output. Per a aquest capítol, és sota results/hello_workflow/.

Contingut del directori
results/hello_workflow
├── Bonjour-output.txt
├── Hello-output.txt
└── Holà-output.txt

Si això us ha funcionat, esteu preparats per aprendre com muntar un workflow de múltiples passos.


1. Afegiu un segon pas al workflow

Afegirem un pas per convertir cada salutació a majúscules.

sayHello*-output.txtconvertToUpperUPPER-*Hello, English, 123 Bonjour, French, 456Holà, Spanish, 789greetings.csvHELLOBONJOURHOLàUPPER-Hello-output.txtUPPER-Bonjour-output.txtUPPER-Holà-output.txt

Per fer-ho, necessitem fer tres coses:

  • Definir la comanda que utilitzarem per fer la conversió a majúscules.
  • Escriure un nou procés que encapsuli la comanda de conversió a majúscules.
  • Cridar el nou procés al bloc workflow i configurar-lo per prendre la sortida del procés sayHello() com a entrada.

1.1. Definiu la comanda de conversió a majúscules i proveu-la al terminal

Per fer la conversió de les salutacions a majúscules, utilitzarem una eina UNIX clàssica anomenada tr per 'text replacement', amb la següent sintaxi:

Syntax
tr '[a-z]' '[A-Z]'

Aquesta és una substitució de text molt naïf que no té en compte les lletres accentuades, així que per exemple 'Holà' es convertirà en 'HOLà', però farà una feina prou bona per demostrar els conceptes de Nextflow i això és el que importa.

Per provar-ho, podem executar la comanda echo 'Hello World' i canalitzar la seva sortida a la comanda tr:

echo 'Hello World' | tr '[a-z]' '[A-Z]' > UPPER-output.txt

La sortida és un fitxer de text anomenat UPPER-output.txt que conté la versió en majúscules de la cadena Hello World.

Contingut del fitxer
UPPER-output.txt
HELLO WORLD

Això és bàsicament el que intentarem fer amb el nostre workflow.

1.2. Escriviu el pas de conversió a majúscules com a procés Nextflow

Podem modelar el nostre nou procés sobre el primer, ja que volem utilitzar tots els mateixos components.

Afegiu la següent definició de procés a l'script de workflow, just sota el primer:

hello-workflow.nf
/*
 * Utilitza una eina de substitució de text per convertir la salutació a majúscules
 */
process convertToUpper {

    input:
    path input_file

    output:
    path "UPPER-${input_file}"

    script:
    """
    cat '${input_file}' | tr '[a-z]' '[A-Z]' > 'UPPER-${input_file}'
    """
}

En aquest, compondrem el segon nom de fitxer de sortida basat en el nom del fitxer d'entrada, de manera similar al que vam fer originalment per a la sortida del primer procés.

1.3. Afegiu una crida al nou procés al bloc workflow

Ara necessitem dir a Nextflow que realment cridi el procés que acabem de definir.

Al bloc workflow, feu el següent canvi de codi:

hello-workflow.nf
workflow {

    main:
    // crea un canal per a entrades des d'un fitxer CSV
    greeting_ch = channel.fromPath(params.input)
                        .splitCsv()
                        .map { line -> line[0] }
    // emet una salutació
    sayHello(greeting_ch)
    // converteix la salutació a majúscules
    convertToUpper()

    publish:
    first_output = sayHello.out
}
hello-workflow.nf
workflow {

    main:
    // crea un canal per a entrades des d'un fitxer CSV
    greeting_ch = channel.fromPath(params.input)
                        .splitCsv()
                        .map { line -> line[0] }
    // emet una salutació
    sayHello(greeting_ch)

    publish:
    first_output = sayHello.out
}

Això encara no és funcional perquè no hem especificat què hauria de ser l'entrada del procés convertToUpper().

1.4. Passeu la sortida del primer procés al segon procés

Ara necessitem fer que la sortida del procés sayHello() flueixi cap al procés convertToUpper().

Convenientment, Nextflow empaqueta automàticament la sortida d'un procés en un canal, com es mostra al diagrama de la secció d'escalfament. Podem referir-nos al canal de sortida d'un procés com <process>.out.

Així doncs, la sortida del procés sayHello és un canal anomenat sayHello.out, que podem connectar directament a la crida a convertToUpper().

Hello-output.txtBonjour-output.txtHolà-output.txtsayHelloHello, English, 123 Bonjour, French, 456Holà, Spanish, 789greetings.csvconvertToUpperUPPER-*sayHello.out

Al bloc workflow, feu el següent canvi de codi:

hello-workflow.nf
    // converteix la salutació a majúscules
    convertToUpper(sayHello.out)
hello-workflow.nf
    // converteix la salutació a majúscules
    convertToUpper()

Per a un cas simple com aquest (una sortida a una entrada), això és tot el que necessitem fer per connectar dos processos!

1.5. Configureu la publicació de sortida del workflow

Finalment, actualitzem les sortides del workflow per publicar també els resultats del segon procés.

1.5.1. Actualitzeu la secció publish: del bloc workflow

Al bloc workflow, feu el següent canvi de codi:

hello-workflow.nf
    publish:
    first_output = sayHello.out
    uppercased = convertToUpper.out
}
hello-workflow.nf
    publish:
    first_output = sayHello.out
}

La lògica és la mateixa que abans.

1.5.2. Actualitzeu el bloc output

Al bloc output, feu el següent canvi de codi:

hello-workflow.nf
output {
    first_output {
        path 'hello_workflow'
        mode 'copy'
    }
    uppercased {
        path 'hello_workflow'
        mode 'copy'
    }
}
hello-workflow.nf
output {
    first_output {
        path 'hello_workflow'
        mode 'copy'
    }
}

Una vegada més, la lògica és la mateixa que abans.

Això us mostra que podeu controlar la configuració de sortida a un nivell molt granular, per a cada sortida individual. Sentiu-vos lliures de provar canviar els camins o el mode de publicació per a un dels processos per veure què passa.

Per descomptat, això significa que estem repetint alguna informació aquí, que podria esdevenir inconvenient si volguéssim actualitzar la ubicació per a totes les sortides de la mateixa manera. Més endavant al curs, aprendreu com configurar aquests paràmetres per a múltiples sortides de manera estructurada.

1.6. Executeu el workflow amb -resume

Provem això utilitzant la bandera -resume, ja que ja hem executat el primer pas del workflow amb èxit.

nextflow run hello-workflow.nf -resume
Sortida de la comanda
 N E X T F L O W   ~  version 25.10.2

Launching `hello-workflow.nf` [high_cantor] DSL2 - revision: d746983511

executor >  local (3)
[ab/816321] process > sayHello (3)       [100%] 3 of 3, cached: 3 ✔
[e0/ecf81b] process > convertToUpper (3) [100%] 3 of 3 ✔

Ara hi ha una línia extra a la sortida de la consola que correspon al nou procés que acabem d'afegir.

Trobareu les sortides al directori results/hello_workflow tal com s'ha establert al bloc output.

Contingut del directori
results/hello_workflow/
├── Bonjour-output.txt
├── Hello-output.txt
├── Holà-output.txt
├── UPPER-Bonjour-output.txt
├── UPPER-Hello-output.txt
└── UPPER-Holà-output.txt

Això és convenient! Però encara val la pena donar una ullada dins del directori de treball d'una de les crides al segon procés.

Contingut del directori
work/e0/ecf81b4cacc648b9b994218d5b29d7/
├── Holà-output.txt -> /workspaces/training/hello-nextflow/work/ab/81632178cd37e9e815959278808819/Holà-output.txt
└── UPPER-Holà-output.txt

Observeu que hi ha dos fitxers *-output: la sortida del primer procés així com la sortida del segon.

La sortida del primer procés hi és perquè Nextflow la va preparar allà per tenir tot el necessari per a l'execució dins del mateix subdirectori.

No obstant això, en realitat és un enllaç simbòlic que apunta al fitxer original al subdirectori de la primera crida de procés. Per defecte, quan s'executa en una sola màquina com estem fent aquí, Nextflow utilitza enllaços simbòlics en lloc de còpies per preparar fitxers d'entrada i intermedis.

Ara, abans de continuar, penseu en com tot el que vam fer va ser connectar la sortida de sayHello a l'entrada de convertToUpper i els dos processos es van poder executar en sèrie. Nextflow va fer la feina dura de gestionar fitxers d'entrada i sortida individuals i passar-los entre les dues comandes per nosaltres.

Aquesta és una de les raons per les quals els canals de Nextflow són tan potents: s'encarreguen de la feina rutinària implicada en connectar passos de workflow junts.

Conclusió

Sabeu com encadenar processos junts proporcionant la sortida d'un pas com a entrada al següent pas.

Què segueix?

Apreneu com recollir sortides de crides de procés per lots i alimentar-les en un únic procés.


2. Afegiu un tercer pas per recollir totes les salutacions

Quan utilitzem un procés per aplicar una transformació a cadascun dels elements d'un canal, com estem fent aquí amb les múltiples salutacions, de vegades volem recollir elements del canal de sortida d'aquest procés i alimentar-los en un altre procés que realitza algun tipus d'anàlisi o sumatori.

Per demostrar-ho, afegirem un nou pas al nostre pipeline que reculli totes les salutacions en majúscules produïdes pel procés convertToUpper i les escrigui en un únic fitxer.

sayHello*-output.txtconvertToUpperUPPER-*collectGreetingsCOLLECTED-output.txtHELLOBONJOURHOLàHello, English, 123 Bonjour, French, 456Holà, Spanish, 789greetings.csvHELLOBONJOURHOLàUPPER-Hello-output.txtUPPER-Bonjour-output.txtUPPER-Holà-output.txt

Per no espatllar la sorpresa, però això implicarà un operador molt útil.

2.1. Definiu la comanda de recollida i proveu-la al terminal

El pas de recollida que volem afegir al nostre workflow utilitzarà la comanda cat per concatenar múltiples salutacions en majúscules en un únic fitxer.

Executem la comanda per si sola al terminal per verificar que funciona com s'espera, igual que hem fet abans.

Executeu el següent al vostre terminal:

echo 'Hello' | tr '[a-z]' '[A-Z]' > UPPER-Hello-output.txt
echo 'Bonjour' | tr '[a-z]' '[A-Z]' > UPPER-Bonjour-output.txt
echo 'Holà' | tr '[a-z]' '[A-Z]' > UPPER-Holà-output.txt
cat UPPER-Hello-output.txt UPPER-Bonjour-output.txt UPPER-Holà-output.txt > COLLECTED-output.txt

La sortida és un fitxer de text anomenat COLLECTED-output.txt que conté les versions en majúscules de les salutacions originals.

Contingut del fitxer
COLLECTED-output.txt
HELLO
BONJOUR
HOLà

Aquest és el resultat que volem aconseguir amb el nostre workflow.

2.2. Creeu un nou procés per fer el pas de recollida

Creem un nou procés i l'anomenem collectGreetings(). Podem començar a escriure'l basat en el que hem vist abans.

2.2.1. Escriviu les parts 'òbvies' del procés

Afegiu la següent definició de procés a l'script de workflow:

hello-workflow.nf
/*
 * Recull salutacions en majúscules en un únic fitxer de sortida
 */
process collectGreetings {

    input:
    ???

    output:
    path "COLLECTED-output.txt"

    script:
    """
    cat ??? > 'COLLECTED-output.txt'
    """
}

Això és el que podem escriure amb confiança basat en el que heu après fins ara. Però això no és funcional! Deixa de banda la(es) definició(ns) d'entrada i la primera meitat de la comanda script perquè necessitem esbrinar com escriure-ho.

2.2.2. Definiu les entrades a collectGreetings()

Necessitem recollir les salutacions de totes les crides al procés convertToUpper(). Què sabem que podem obtenir del pas anterior al workflow?

El canal de sortida de convertToUpper() contindrà els camins als fitxers individuals que contenen les salutacions en majúscules. Això equival a una ranura d'entrada; anomenem-la input_files per simplicitat.

Al bloc de procés, feu el següent canvi de codi:

hello-workflow.nf
      input:
      path input_files
hello-workflow.nf
      input:
      ???

Observeu que utilitzem el prefix path encara que esperem que això contingui múltiples fitxers.

2.2.3. Compondreu la comanda de concatenació

Aquí és on les coses podrien complicar-se una mica, perquè necessitem poder gestionar un nombre arbitrari de fitxers d'entrada. Específicament, no podem escriure la comanda per endavant, així que necessitem dir a Nextflow com compondre-la en temps d'execució basat en quines entrades flueixen cap al procés.

En altres paraules, si tenim un canal d'entrada que conté l'element [file1.txt, file2.txt, file3.txt], necessitem que Nextflow ho converteixi en cat file1.txt file2.txt file3.txt.

Afortunadament, Nextflow està molt content de fer-ho per nosaltres si simplement escrivim cat ${input_files} a la comanda script.

Al bloc de procés, feu el següent canvi de codi:

hello-workflow.nf
    script:
    """
    cat ${input_files} > 'COLLECTED-output.txt'
    """
hello-workflow.nf
    script:
    """
    cat ??? > 'COLLECTED-output.txt'
    """

En teoria això hauria de gestionar qualsevol nombre arbitrari de fitxers d'entrada.

Consell

Algunes eines de línia de comandes requereixen proporcionar un argument (com -input) per a cada fitxer d'entrada. En aquest cas, hauríem de fer una mica de feina extra per compondre la comanda. Podeu veure un exemple d'això al curs de formació Nextflow for Genomics.

2.3. Afegiu el pas de recollida al workflow

Ara només hauríem de necessitar cridar el procés de recollida sobre la sortida del pas de conversió a majúscules. Això també és un canal, anomenat convertToUpper.out.

convertToUpperUPPER-Hello-output.txtUPPER-Bonjour-output.txtUPPER-Holà-output.txtsayHelloHello, English, 123 Bonjour, French, 456Holà, Spanish, 789greetings.csvconvertToUpper.outHello-output.txtBonjour-output.txtHolà-output.txtsayHello.out

2.3.1. Connecteu les crides de procés

Al bloc workflow, feu el següent canvi de codi:

hello-workflow.nf
    // converteix la salutació a majúscules
    convertToUpper(sayHello.out)

    // recull totes les salutacions en un fitxer
    collectGreetings(convertToUpper.out)
}
hello-workflow.nf
    // converteix la salutació a majúscules
    convertToUpper(sayHello.out)
}

Això connecta la sortida de convertToUpper() a l'entrada de collectGreetings().

2.3.2. Executeu el workflow amb -resume

Provem-ho.

nextflow run hello-workflow.nf -resume
Sortida de la comanda
N E X T F L O W   ~  version 25.10.2

Launching `hello-workflow.nf` [mad_gilbert] DSL2 - revision: 6acfd5e28d

executor >  local (3)
[79/33b2f0] sayHello (2)         | 3 of 3, cached: 3 ✔
[99/79394f] convertToUpper (3)   | 3 of 3, cached: 3 ✔
[47/50fe4a] collectGreetings (1) | 3 of 3 ✔

S'executa amb èxit, incloent el tercer pas.

No obstant això, mireu el nombre de crides per a collectGreetings() a l'última línia. Només esperàvem una, però n'hi ha tres.

Ara doneu una ullada al contingut del fitxer de sortida final.

Contingut del fitxer
results/COLLECTED-output.txt
Holà

Oh no. El pas de recollida es va executar individualment en cada salutació, que NO és el que volíem.

WITHOUT ANY OPERATORcollectGreetings( ... )separate process callscollectGreetings( ... )collectGreetings( ... )UPPER-Hello-output.txtUPPER-Bonjour-output.txtUPPER-Holà-output.txtconvertToUpper.outCOLLECTED-output.txtCOLLECTED-output.txtCOLLECTED-output.txtHELLOBONJOURHOLàseparate outputs

Necessitem fer alguna cosa per dir a Nextflow explícitament que volem que aquest tercer pas s'executi sobre tots els elements del canal de sortida de convertToUpper().

2.4. Utilitzeu un operador per recollir les salutacions en una única entrada

Sí, una vegada més la resposta al nostre problema és un operador.

Específicament, utilitzarem l'operador amb el nom apropiat collect().

2.4.1. Afegiu l'operador collect()

Aquesta vegada semblarà una mica diferent perquè no estem afegint l'operador en el context d'una factoria de canals; l'estem afegint a un canal de sortida.

Prenem el convertToUpper.out i afegim l'operador collect(), que ens dóna convertToUpper.out.collect(). Podem connectar això directament a la crida del procés collectGreetings().

Al bloc workflow, feu el següent canvi de codi:

hello-workflow.nf
    // recull totes les salutacions en un fitxer
    collectGreetings(convertToUpper.out.collect())
}
hello-workflow.nf
    // recull totes les salutacions en un fitxer
    collectGreetings(convertToUpper.out)
}

2.4.2. Afegiu algunes instruccions view()

També inclourem un parell d'instruccions view() per visualitzar els estats abans i després del contingut del canal.

hello-workflow.nf
    // recull totes les salutacions en un fitxer
    collectGreetings(convertToUpper.out.collect())

    // instruccions view opcionals
    convertToUpper.out.view { contents -> "Before collect: $contents" }
    convertToUpper.out.collect().view { contents -> "After collect: $contents" }
}
hello-workflow.nf
    // recull totes les salutacions en un fitxer
    collectGreetings(convertToUpper.out.collect())
}

Les instruccions view() poden anar on vulgueu; les hem posat just després de la crida per llegibilitat.

2.4.3. Executeu el workflow de nou amb -resume

Provem-ho:

nextflow run hello-workflow.nf -resume
Sortida de la comanda
N E X T F L O W   ~  version 25.10.2

Launching `hello-workflow.nf` [soggy_franklin] DSL2 - revision: bc8e1b2726

[d6/cdf466] sayHello (1)       | 3 of 3, cached: 3 ✔
[99/79394f] convertToUpper (2) | 3 of 3, cached: 3 ✔
[1e/83586c] collectGreetings   | 1 of 1 ✔
Before collect: /workspaces/training/hello-nextflow/work/b3/d52708edba8b864024589285cb3445/UPPER-Bonjour-output.txt
Before collect: /workspaces/training/hello-nextflow/work/99/79394f549e3040dfc2440f69ede1fc/UPPER-Hello-output.txt
Before collect: /workspaces/training/hello-nextflow/work/aa/56bfe7cf00239dc5badc1d04b60ac4/UPPER-Holà-output.txt
After collect: [/workspaces/training/hello-nextflow/work/b3/d52708edba8b864024589285cb3445/UPPER-Bonjour-output.txt, /workspaces/training/hello-nextflow/work/99/79394f549e3040dfc2440f69ede1fc/UPPER-Hello-output.txt, /workspaces/training/hello-nextflow/work/aa/56bfe7cf00239dc5badc1d04b60ac4/UPPER-Holà-output.txt]

S'executa amb èxit, encara que la sortida del registre pot semblar una mica més desordenada que això (l'hem netejat per llegibilitat).

Aquesta vegada el tercer pas només es va cridar una vegada! Mirant la sortida de les instruccions view(), veiem el següent:

  • Tres instruccions Abans de collect:, una per a cada salutació: en aquest punt els camins de fitxer són elements individuals al canal.
  • Una única instrucció Després de collect:: els tres camins de fitxer ara estan empaquetats en un únic element.

Podem resumir això amb el següent diagrama:

WITH THE collect() OPERATORsingle process callcollectGreetings( ... )UPPER-Hello-output.txtUPPER-Bonjour-output.txtUPPER-Holà-output.txtconvertToUpper.outCOLLECTED-output.txtsingle output.collect()UPPER-Hello-output.txtUPPER-Bonjour-output.txtUPPER-Holà-output.txtHELLOBONJOURHOLà

Finalment, podeu donar una ullada al contingut del fitxer de sortida per satisfer-vos que tot ha funcionat correctament.

Contingut del fitxer
results/COLLECTED-output.txt
BONJOUR
HELLO
HOLà

Aquesta vegada tenim les tres salutacions al fitxer de sortida final. Èxit!

Nota

Si executeu això diverses vegades sense -resume, veureu que l'ordre de les salutacions canvia d'una execució a la següent. Això us mostra que l'ordre en què els elements flueixen a través de les crides de procés no està garantit que sigui consistent.

2.4.4. Elimineu les instruccions view() per llegibilitat

Abans de passar a la següent secció, us recomanem que elimineu les instruccions view() per evitar embolicar la sortida de la consola.

hello-workflow.nf
    // recull totes les salutacions en un fitxer
    collectGreetings(convertToUpper.out.collect())
hello-workflow.nf
    // recull totes les salutacions en un fitxer
    collectGreetings(convertToUpper.out.collect())

    // instruccions view opcionals
    convertToUpper.out.view { contents -> "Before collect: $contents" }
    convertToUpper.out.collect().view { contents -> "After collect: $contents" }

Això és bàsicament l'operació inversa del punt 2.4.2.

Conclusió

Sabeu com recollir sortides d'un lot de crides de procés i alimentar-les en un pas d'anàlisi o sumatori conjunt.

Per recapitular, això és el que heu construït fins ara:

sayHello*-output.txtconvertToUpperUPPER-*collectGreetingsCOLLECTED-output.txtHELLOBONJOURHOLàHello, English, 123 Bonjour, French, 456Holà, Spanish, 789greetings.csvHELLOBONJOURHOLàUPPER-Hello-output.txtUPPER-Bonjour-output.txtUPPER-Holà-output.txt

Què segueix?

Apreneu com passar més d'una entrada a un procés.


3. Passeu paràmetres addicionals a un procés

Volem poder nomenar el fitxer de sortida final alguna cosa específica per poder processar lots posteriors de salutacions sense sobreescriure els resultats finals.

Per fer-ho, farem els següents refinaments al workflow:

  • Modificar el procés col·lector per acceptar un nom definit per l'usuari per al fitxer de sortida (batch_name)
  • Afegir un paràmetre de línia de comandes al workflow (--batch) i passar-lo al procés col·lector
collectGreetingsCOLLECTED-${batch_name}-output.txtHELLOBONJOURHOLà--batchUPPER-Hello-output.txtUPPER-Bonjour-output.txtUPPER-Holà-output.txtconvertToUpper.out.collect()

3.1. Modifiqueu el procés col·lector

Necessitarem declarar l'entrada addicional i integrar-la al nom del fitxer de sortida.

3.1.1. Declareu l'entrada addicional

Bones notícies: podem declarar tantes variables d'entrada com vulguem a la definició del procés. Anomenem aquesta batch_name.

Al bloc de procés, feu el següent canvi de codi:

hello-workflow.nf
    input:
    path input_files
    val batch_name
hello-workflow.nf
    input:
    path input_files

Podeu configurar els vostres processos per esperar tantes entrades com vulgueu. Ara mateix, totes estan configurades per ser entrades requerides; heu de proporcionar un valor perquè el workflow funcioni.

Aprendreu com gestionar entrades requerides vs. opcionals més endavant al vostre viatge amb Nextflow.

3.1.2. Utilitzeu la variable batch_name al nom del fitxer de sortida

Podem inserir la variable al nom del fitxer de sortida de la mateixa manera que hem compost noms de fitxer dinàmics abans.

Al bloc de procés, feu el següent canvi de codi:

hello-workflow.nf
    output:
    path "COLLECTED-${batch_name}-output.txt"

    script:
    """
    cat ${input_files} > 'COLLECTED-${batch_name}-output.txt'
    """
hello-workflow.nf
    output:
    path "COLLECTED-output.txt"

    script:
    """
    cat ${input_files} > 'COLLECTED-output.txt'
    """

Això configura el procés per utilitzar el valor batch_name per generar un nom de fitxer específic per a la sortida final del workflow.

3.2. Afegiu un paràmetre de línia de comandes batch

Ara necessitem una manera de subministrar el valor per a batch_name i alimentar-lo a la crida del procés.

3.2.1. Utilitzeu params per configurar el paràmetre

Ja sabeu com utilitzar el sistema params per declarar paràmetres CLI. Utilitzem això per declarar un paràmetre batch (amb un valor per defecte perquè som mandrosos).

A la secció de paràmetres del pipeline, feu els següents canvis de codi:

hello-workflow.nf
/*
 * Paràmetres del pipeline
 */
params {
    input: Path = 'data/greetings.csv'
    batch: String = 'batch'
}
hello-workflow.nf
/*
 * Paràmetres del pipeline
 */
params {
    input: Path = 'data/greetings.csv'
}

Igual que vam demostrar per a --input, podeu sobreescriure aquest valor per defecte especificant un valor amb --batch a la línia de comandes.

3.2.2. Passeu el paràmetre batch al procés

Per proporcionar el valor del paràmetre al procés, necessitem afegir-lo a la crida del procés.

Al bloc workflow, feu el següent canvi de codi:

hello-workflow.nf
    // recull totes les salutacions en un fitxer
    collectGreetings(convertToUpper.out.collect(), params.batch)
hello-workflow.nf
    // recull totes les salutacions en un fitxer
    collectGreetings(convertToUpper.out.collect())

Veieu que per proporcionar múltiples entrades a un procés, simplement les llisteu als parèntesis de la crida, separades per comes.

Advertència

HEU de proporcionar les entrades al procés en el MATEIX ORDRE EXACTE en què estan llistades al bloc de definició d'entrada del procés.

3.3. Executeu el workflow

Provem d'executar això amb un nom de lot a la línia de comandes.

nextflow run hello-workflow.nf -resume --batch trio
Sortida de la comanda
N E X T F L O W   ~  version 25.10.2

Launching `hello-workflow.nf` [confident_rutherford] DSL2 - revision: bc58af409c

executor >  local (1)
[79/33b2f0] sayHello (2)       | 3 of 3, cached: 3 ✔
[99/79394f] convertToUpper (2) | 3 of 3, cached: 3 ✔
[b5/f19efe] collectGreetings   | 1 of 1 ✔

S'executa amb èxit i produeix la sortida desitjada:

Contingut del fitxer
results/COLLECTED-trio-output.txt
HELLO
BONJOUR
HOLà

Ara, sempre que especifiquem el paràmetre adequadament, execucions posteriors sobre altres lots d'entrades no sobreescriuran resultats anteriors.

Conclusió

Sabeu com passar més d'una entrada a un procés.

Què segueix?

Apreneu com emetre múltiples sortides i gestionar-les convenientment.


4. Afegiu una sortida al pas col·lector

Fins ara hem estat utilitzant processos que només produïen una sortida cadascun. Vam poder accedir a les seves respectives sortides molt convenientment utilitzant la sintaxi <process>.out, que vam utilitzar tant en el context de passar una sortida al següent procés (p. ex. convertToUpper(sayHello.out)) com en el context de la secció publish: (p. ex. first_output = sayHello.out).

Què passa quan un procés produeix més d'una? Com gestionem les múltiples sortides? Podem seleccionar i utilitzar una sortida específica?

Totes preguntes excel·lents, i la resposta curta és que sí que podem!

Les múltiples sortides s'empaquetaran en canals separats. Podem optar per donar noms a aquests canals de sortida, cosa que facilita referir-nos-hi individualment més endavant, o podem referir-nos-hi per índex.

Per propòsits de demostració, diguem que volem comptar el nombre de salutacions que s'estan recollint per a un lot donat d'entrades i informar-ho en un fitxer.

4.1. Modifiqueu el procés per comptar i emetre el nombre de salutacions

Això requerirà dos canvis clau a la definició del procés: necessitem una manera de comptar les salutacions i escriure un fitxer d'informe, després necessitem afegir aquest fitxer d'informe al bloc output del procés.

4.1.1. Compteu el nombre de salutacions recollides

Convenientment, Nextflow ens permet afegir codi arbitrari al bloc script: de la definició del procés, cosa que és molt útil per fer coses com aquesta.

Això significa que podem utilitzar la funció integrada de Nextflow size() per obtenir el nombre de fitxers a l'array input_files, i escriure el resultat a un fitxer amb una comanda echo.

Al bloc de procés collectGreetings, feu els següents canvis de codi:

hello-workflow.nf
    script:
    count_greetings = input_files.size()
    """
    cat ${input_files} > 'COLLECTED-${batch_name}-output.txt'
    echo 'There were ${count_greetings} greetings in this batch.' > '${batch_name}-report.txt'
    """
hello-workflow.nf
    script:
    """
    cat ${input_files} > 'COLLECTED-${batch_name}-output.txt'
    """

La variable count_greetings es calcularà en temps d'execució.

4.1.2. Emeteu el fitxer d'informe i anomeneu les sortides

En principi tot el que necessitem fer és afegir el fitxer d'informe al bloc output:.

No obstant això, mentre hi som, també afegirem algunes etiquetes emit: a les nostres declaracions de sortida. Aquestes ens permetran seleccionar les sortides per nom en lloc d'haver d'utilitzar índexs posicionals.

Al bloc de procés, feu el següent canvi de codi:

hello-workflow.nf
    output:
    path "COLLECTED-${batch_name}-output.txt", emit: outfile
    path "${batch_name}-report.txt", emit: report
hello-workflow.nf
    output:
    path "COLLECTED-${batch_name}-output.txt"

Les etiquetes emit: són opcionals, i podríem haver afegit una etiqueta només a una de les sortides. Però com diu el refrany, per què no ambdues?

Consell

Si no anomeneu les sortides d'un procés utilitzant emit:, encara podeu accedir-hi individualment utilitzant el seu respectiu índex (basat en zero). Per exemple, utilitzaríeu <process>.out[0] per obtenir la primera sortida, <process>.out[1] per obtenir la segona sortida, i així successivament.

Preferim anomenar les sortides perquè altrament, és massa fàcil agafar l'índex equivocat per error, especialment quan el procés produeix moltes sortides.

4.2. Actualitzeu les sortides del workflow

Ara que tenim dues sortides sortint del procés collectGreetings, la sortida collectGreetings.out conté dos canals:

  • collectGreetings.out.outfile conté el fitxer de sortida final
  • collectGreetings.out.report conté el fitxer d'informe
collectGreetingsHELLOBONJOURHOLà--batchUPPER-Hello-output.txtUPPER-Bonjour-output.txtUPPER-Holà-output.txtconvertToUpper.out.collect()COLLECTED-${batch_name}-output.txt${batch_name}-report.txtcollectGreetings.out.outfilecollectGreetings.out.reportThere were ${count_greetings}greetings in this batch.

Necessitem actualitzar les sortides del workflow en conseqüència.

4.2.1. Actualitzeu la secció publish:

Al bloc workflow, feu el següent canvi de codi:

hello-workflow.nf
    publish:
    first_output = sayHello.out
    uppercased = convertToUpper.out
    collected = collectGreetings.out.outfile
    batch_report = collectGreetings.out.report
hello-workflow.nf
    publish:
    first_output = sayHello.out
    uppercased = convertToUpper.out
    collected = collectGreetings.out

Com podeu veure, referir-se a sortides de procés específiques ara és trivial. Quan anem a afegir un pas més al nostre pipeline a la Part 5 (Contenidors), podrem referir-nos fàcilment a collectGreetings.out.outfile i passar-lo al nou procés (spoiler: el nou procés s'anomena cowpy).

Però per ara, acabem d'actualitzar les sortides a nivell de workflow.

4.2.2. Actualitzeu el bloc output

Al bloc output, feu el següent canvi de codi:

hello-workflow.nf
output {
    first_output {
        path 'hello_workflow'
        mode 'copy'
    }
    uppercased {
        path 'hello_workflow'
        mode 'copy'
    }
    collected {
        path 'hello_workflow'
        mode 'copy'
    }
    batch_report {
        path 'hello_workflow'
        mode 'copy'
    }
}
hello-workflow.nf
output {
    first_output {
        path 'hello_workflow'
        mode 'copy'
    }
    uppercased {
        path 'hello_workflow'
        mode 'copy'
    }
    collected {
        path 'hello_workflow'
        mode 'copy'
    }
}

No necessitem actualitzar la definició de sortida collected ja que aquest nom no ha canviat. Només necessitem afegir la nova sortida.

4.3. Executeu el workflow

Provem d'executar això amb el lot actual de salutacions.

nextflow run hello-workflow.nf -resume --batch trio
Sortida de la comanda
 N E X T F L O W   ~  version 25.10.2

Launching `hello-workflow.nf` [ecstatic_wilson] DSL2 - revision: c80285f8c8

executor >  local (1)
[c5/4c6ca9] sayHello (3)       [100%] 3 of 3, cached: 3 ✔
[0e/6cbc59] convertToUpper (3) [100%] 3 of 3, cached: 3 ✔
[02/61ead2] collectGreetings   [100%] 1 of 1 ✔

Si mireu al directori results/hello_workflow/, trobareu el nou fitxer d'informe, trio-report.txt. Obriu-lo per verificar que el workflow va informar correctament del recompte de salutacions que es van processar.

Contingut del fitxer
trio-report.txt
There were 3 greetings in this batch.
sayHello*-output.txtconvertToUpperUPPER-*collectGreetingsCOLLECTED-trio-output.txtHELLOBONJOURHOLàHello, English, 123 Bonjour, French, 456Holà, Spanish, 789greetings.csv--batch triotrio-report.txtThere were 3 greetingsin this batch.

Sentiu-vos lliures d'afegir més salutacions al CSV i provar què passa.

Conclusió

Sabeu com fer que un procés emeti múltiples sortides amb nom i com gestionar-les adequadament a nivell de workflow.

Més generalment, enteneu els principis clau implicats en connectar processos junts de maneres comunes.

Què segueix?

Preneu-vos un descans extra llarg, us l'heu guanyat.

Quan estigueu preparats, passeu a Part 4: Hello Modules per aprendre com modularitzar el vostre codi per a una millor mantenibilitat i eficiència del codi.


Qüestionari

#

Com accediu a la sortida d'un procés al bloc workflow?

#

Què determina l'ordre d'execució dels processos a Nextflow?

#

Quin operador hauria de substituir ??? per recollir totes les sortides en una única llista per al procés posterior?

workflow {
    greetings_ch = Channel.of('Hello', 'Bonjour', 'Hola')
    SAYHELLO(greetings_ch)
    GATHER_ALL(SAYHELLO.out.???)
}
#

Quan hauríeu d'utilitzar l'operador collect()?

#

Com accediu a una sortida amb nom d'un procés?

#

Quina és la sintaxi correcta per anomenar una sortida en un procés?

#

Quan proporcioneu múltiples entrades a un procés, què ha de ser cert?