Introduccion a Nextflow

Nextflow enables scalable and reproducible scientific workflows using software containers. It allows the adaptation of pipelines written in the most common scripting languages.
Its fluent DSL simplifies the implementation and the deployment of complex parallel and reactive workflows on clouds and clusters.

Nextflow es un proyecto OpenSource muy usado sobre todo por la comunidad bioinformática (debido a que sus creadores trabajaban en esta área,) pero que puede ser usado en otros ámbitos y que básicamente permite definir procesos que puedan ser ejecutados de forma paralela tanto en local como en cloud sin tener que cambiarlos.

Para ello se ha creado un DSL (un lenguaje específico) en donde defines los procesos, con sus entradas, salidas, etc, y el flujo de llamadas entre los mismos. Este "pipeline" es ejecutado por Nextflow en el entorno que le digas y él se encarga de aprovisionar los recursos necesarios para ejecutarlo y vigilar su ejecución.

El DSL es agnóstico a lo que tú quieras ejecutar. Es decir, puedes definir un proceso que recibe la ruta de un fichero como parámetro de entrada y tú decides qué hacer con él: que Python lo ejecute, volcarlo a la salida con un cat, ejecutar un programa de procesado de imágenes, …​ Lo único que "necesita" Nextflow es que el exitStatus del programa le diga si ha ido bien o no para poder continuar con el resto de tareas

Vamos a verlo con un hello-world

main.nf
process sayHello {
  input:
    val x
  output:
    stdout
  script:
    """
    echo '$x world!'
    """
}

workflow {
   sayHello('hola') | view
}

En este pipeline creamos un proceso sayHello que recibe un String, su retorno va a ser un volcado de la ejecución, y que lo que va a ejecutar es un comando de bash echo

Por otra parte, se define el workflow del proceso, el qué ejecutar y en qué orden. En este ejemplo simplemente vamos a ejecutar el proceso anterior y vamos a volcar su salida por pantalla

nextflow run ./hola.nf
N E X T F L O W  ~  version 22.04.5
Launching `./hola.nf` [jolly_shaw] DSL2 - revision: 3df369f295
executor >  local (1)
[9a/eed166] process > sayHello [100%] 1 of 1 ✔
hola world!

Podríamos ejecutar el mismo proceso vía Docker:

nextflow run ./hola.nf -with-docker -process.container=ubuntu
N E X T F L O W  ~  version 22.04.5
Launching `./hola.nf` [fervent_wescoff] DSL2 - revision: 3df369f295
executor >  local (1)
[bf/f66b2d] process > sayHello [100%] 1 of 1 ✔
hola world!

Obviamente al ser un simple echo no hay diferencia, pero la idea es que podrías ejecutar el comando usando la imagen que te venga bien sin tener que instalar nada en tu equipo (más que Docker)

Además de Docker, puedes ejecutar el proceso contra numerosos servicios de cloud como AWS, Google, Azure, Kubernetes , …​

Instalación

Nextflow requiere tener instalada una versión de Java moderna, aunque también corre con la versión 11.

Para instalarlo simplemente ejecutaremos:

curl -s https://get.nextflow.io | bash

(para más detalle consultar la página oficial https://www.nextflow.io/)

Si todo ha ido bien y creas el fichero anterior deberías poder ejecutar el comando tal como se muestra en el apartado anterior.

Canales

Hasta ahora solamente hemos visto cómo ejecutar un proceso, pero una de las capacidades de Nextflow es poder definir varios procesos y expresar cómo queremos que se ejecuten (paralelo, dependientes entre sí).

Para ello usa el concepto de Channel y operators. Un channel podemos verlo como el main de un flujo de procesos y donde "concatenamos" la ejecución de los mismos

Vamos a modificar el ejemplo anterior:

process sayHello {
  input:
    val x
  output:
    stdout
  script:
    """
    echo '$x world!'
    """
}

workflow {
  Channel.of('Bonjour', 'Ciao', 'Hello', 'Hola') | sayHello | view
}

Channel.of recibe una lista de objetos y por cada uno de ellos invoca al proceso sayHello mostrando la salida de cada uno

N E X T F L O W  ~  version 22.04.5
Launching `./hola.nf` [golden_panini] DSL2 - revision: 68e7da3913
executor >  local (4)
[ea/bb9b4b] process > sayHello (2) [100%] 4 of 4 ✔
Bonjour world!

Hola world!

Hello world!

Ciao world!

of es sólo uno de los muchos operadores que ofrece Channel (con el añadido de que puedes crear los tuyos si echas en falta alguno). Hay operadores para filtrar, transformar, combinar, paralelizar, etc

Channel
    .from( 'a', 'b', 'aa', 'bc', 3, 4.5 )
    .filter( Number )
    .view()

Channel
    .from( 1, 2, 3, 4, 5 )
    .filter { it % 2 == 1 }
    .view()

Channel
    .from(1,2,3,40,50)
    .branch {
        small: it < 10
        large: it > 10
    }
    .set { result }

Conclusion

En próximos post espero poder ir explicando más funcionalidades y casos de uso. Por ahora basta deecir que …​ está implementado en Groovy y que formo parte del equipo de desarrollo

Este texto ha sido escrito por un humano

This post was written by a human

2019 - 2024 | Mixed with Bootstrap | Baked with JBake v2.6.7