Introduccion a Nextflow: Channels
Tags: groovy, nextflow
Published: 2022-09-26 17:49:17

---
title: Introduccion a Nextflow: Channels
published: true
date: 2022-09-12 00:00:00 UTC
tags: groovy,nextflow
canonical_url: https://jorge.aguilera.soy/blog/nextflow/channels.html
---

En el artículo [anterior](basic.html) vimos los conceptos básicos de Nextflow (process, channel y workflow). En este, vamos a profundizar un poco más en el concepto de canales (channel)

El Channel es el medio por el que "hacemos llegar" datos a los procesos.

Existen múltiples formas de crear un canal. Algunos ejemplos:

```
ch1 = Channel.create()
ch1 << 1
ch1 << 'hola'

ch2 = Channel.of( 1, 3, 5, 7 )

ch3 = Channel.fromPath( '/data/some/*.txt' )

ch4 = Channel.watchPath( '/path/*.fa' )
```

y el canal irá emitiendo los elementos disponibles según se vayan consumiendo (es decir, el canal es una cola no bloqueante que conecta consumidores)

<dl>
<dt>INFO</dt>
<dd>
<p>También existe el tipo de Channel <code>value</code> que emite siempre el mismo valor y que puede ser leído mútiples veces. Por ejemplo <code>chn = Channel.value('hi')</code>
crea un canal que siempre emitirá el string <code>hi</code> cuando se lea de él.</p>
</dd>
</dl>

## Operadores

Los canales disponen de un conjunto de operadores (extensibles, puedes añadir los tuyos mediante el mecanismo de plugins que hablaremos en otro post) que permiten modificar los valores emitidos por estos (por ejemplo, un canal emite todos los ficheros de un directorio pero queremos filtrar por un criterio diferente al nombre)

Algunos de los operadores disponibles:

- filter (filtra por una expresion regular o por una lógica tuya, por ejemplo `channel.of(1,2,3).filter{ it % 2 == 1 }.view()`

- unique

- first, last

- until

- map

- collect

- toSortedList

- …​ (la lista completa de los operadores por defecto está en [https://www.nextflow.io/docs/latest/operator.html#](https://www.nextflow.io/docs/latest/operator.html#))

## Ejemplo

Como caso "práctico" vamos a crear un pipeline que descargue un CSV del Ayuntamiento de Madrid, filtre algunos registros y los muestre

El csv en concreto es la relacion de accidentes de trafico ocurridos durante el último año, donde se especifican, entre otros, el distrito y si hubo rastros de alcohol (campos 6 y 17 respectivamente) y el tipo de accidente (campo 7)

[La página del catálogo de datos](https://datos.madrid.es/portal/site/egob/menuitem.c05c1f754a33a9fbe4b2e4b284f1a5a0/?vgnextoid=7c2843010d9c3610VgnVCM2000001f4a900aRCRD&vgnextchannel=374512b9ace9f310VgnVCM100000171f5a0aRCRD&vgnextfmt=default)

parsecsv.nf

```
workflow {

  Channel.fromPath( "https://datos.madrid.es/egob/catalogo/300228-24-accidentes-trafico-detalle.csv" )

    | splitCsv(sep:';')

    | filter{ row ->
        // distrito && alchohol
	    row[6] == 'MORATALAZ' && row[17] == 'S'
    }

    | map { row ->
        // tipo
	    row[7]
    }

    | view
}
```

Si ejecutas este pipeline obtendras algo como:

```
nextflow run ./parsecsv.nf
N E X T F L O W ~ version 22.04.5
Launching `./parsecsv.nf` [shrivelled_meninsky] DSL2 - revision: 93c84a05a0
Atropello a persona
Vuelco
Colisión múltiple
Colisión múltiple
Choque contra obstáculo fijo
Vuelco
Choque contra obstáculo fijo
Choque contra obstáculo fijo
Colisión fronto-lateral
Alcance
Choque contra obstáculo fijo
Vuelco
Colisión fronto-lateral
Alcance
Choque contra obstáculo fijo
Vuelco
Choque contra obstáculo fijo
Choque contra obstáculo fijo
Choque contra obstáculo fijo
```

<dl>
<dt>WARNING</dt>
<dd>
<p>la utilidad real de los canales, y en realidad de Nextflow, va mucho más allá de este ejemplo pero creo que estos pequeños
ejercicios nos sirven para ir aproximandonos al lenguaje e ir intuyendo su potencial</p>
</dd>
<dt>INFO</dt>
<dd>
<p>Como puedes observar el DSL permite concatenar operadores mediante el uso del pipe "|"</p>
<div>
<ul>
<li>
<p>Al ejecutar este pipeline, Nextflow creará un canal (anónimo) que emitirá un elemento <code>path</code> (Nextflow es capaz de manejar URLs como
si fueran ficheros locales, como en este caso)</p>
</li>
<li>
<p>Este <code>path</code> será consumido por el operador <code>splitCSV</code> el cual a su ve emitirá las líneas del CSV parseadas como una lista</p>
</li>
<li>
<p>Cada línea será filtrada por la ejecución de una closure que devolverá <code>true</code> o <code>false</code> para indicar si el elemento tiene que ser emitido o no</p>
</li>
<li>
<p>El operador <code>map</code> recibe una lista de elementos (por cada linea filtrada) y emite un sólo campo de esta lista</p>
</li>
<li>
<p>Por último usamos un operador <code>view</code> que simplemente muestra por consola lo que lee por su canal</p>
</li>
</ul>
</div>
</dd>
</dl>

## Conclusión

Como se puede intuir, los canales son una herramienta imprescindible para diseñar nuestros pipelines. Su naturaleza asíncrona y capacidad de paralelizar el envío de los mensajes nos ofrecen una potencia para realizar tareas complejas muy interesante.