Parte 3: Llamado conjunto de variantes en una cohorte¶
En la Parte 2, construiste un pipeline de llamado de variantes por muestra que procesaba los datos de cada muestra de forma independiente. Ahora vamos a extenderlo para implementar el llamado conjunto de variantes, como se cubrió en la Parte 1.
Asignación¶
En esta parte del curso, vamos a extender el workflow para hacer lo siguiente:
- Generar un archivo índice para cada archivo BAM de entrada usando Samtools
- Ejecutar GATK HaplotypeCaller en cada archivo BAM de entrada para generar un GVCF de llamados de variantes genómicas por muestra
- Recolectar todos los GVCFs y combinarlos en un almacén de datos GenomicsDB
- Ejecutar genotipado conjunto en el almacén de datos GVCF combinado para producir un VCF a nivel de cohorte
Esta parte se construye directamente sobre el workflow producido por la Parte 2.
Cómo comenzar desde esta sección
Esta sección del curso asume que has completado la Parte 2: Llamado de variantes por muestra y tienes un pipeline genomics.nf funcional.
Si no completaste la Parte 2 o quieres comenzar de nuevo para esta parte, puedes usar la solución de la Parte 2 como punto de partida.
Ejecuta estos comandos desde dentro del directorio nf4-science/genomics/:
cp solutions/part2/genomics-2.nf genomics.nf
cp solutions/part2/nextflow.config .
cp solutions/part2/modules/* modules/
Esto te proporciona un workflow completo de llamado de variantes por muestra. Puedes verificar que se ejecuta correctamente ejecutando el siguiente comando:
Plan de la lección¶
Hemos dividido esto en dos pasos:
- Modificar el paso de llamado de variantes por muestra para producir un GVCF. Esto cubre la actualización de comandos y salidas del proceso.
- Agregar un paso de genotipado conjunto que combine y genotipe los GVCFs por muestra.
Esto introduce el operador
collect(), closures de Groovy para construcción de líneas de comando y procesos con múltiples comandos.
Note
Asegúrate de estar en el directorio de trabajo correcto:
cd /workspaces/training/nf4-science/genomics
1. Modificar el paso de llamado de variantes por muestra para producir un GVCF¶
El pipeline de la Parte 2 produce archivos VCF, pero el llamado conjunto requiere archivos GVCF. Necesitamos activar el modo de llamado de variantes GVCF y actualizar la extensión del archivo de salida.
Recuerda el comando de llamado de variantes GVCF de la Parte 1:
gatk HaplotypeCaller \
-R /data/ref/ref.fasta \
-I /data/bam/reads_mother.bam \
-O reads_mother.g.vcf \
-L /data/ref/intervals.bed \
-ERC GVCF
Comparado con el comando base de HaplotypeCaller que envolvimos en la Parte 2, las diferencias son el parámetro -ERC GVCF y la extensión de salida .g.vcf.
1.1. Indicar a HaplotypeCaller que emita un GVCF y actualizar la extensión de salida¶
Abre el archivo de módulo modules/gatk_haplotypecaller.nf para hacer dos cambios:
- Agregar el parámetro
-ERC GVCFal comando GATK HaplotypeCaller; - Actualizar la ruta del archivo de salida para usar la extensión correspondiente
.g.vcf, según la convención de GATK.
Asegúrate de agregar una barra invertida (\) al final de la línea anterior cuando agregues -ERC GVCF.
También necesitamos actualizar el bloque output para que coincida con la nueva extensión de archivo.
Dado que cambiamos la salida del comando de .vcf a .g.vcf, el bloque output: del proceso debe reflejar el mismo cambio.
1.2. Actualizar la extensión del archivo de salida en el bloque de salidas del proceso¶
También necesitamos actualizar la configuración de publicación y salida del workflow para reflejar las nuevas salidas GVCF.
1.3. Actualizar los destinos de publicación para las nuevas salidas GVCF¶
Dado que ahora estamos produciendo GVCFs en lugar de VCFs, deberíamos actualizar la sección publish: del workflow para usar nombres más descriptivos.
También organizaremos los archivos GVCF en su propio subdirectorio para mayor claridad.
Ahora actualiza el bloque output para que coincida.
1.4. Actualizar el bloque output para la nueva estructura de directorios¶
También necesitamos actualizar el bloque output para colocar los archivos GVCF en un subdirectorio gvcf.
Con el módulo, los destinos de publicación y el bloque output actualizados, podemos probar los cambios.
1.5. Ejecutar el pipeline¶
Ejecuta el workflow para verificar que los cambios funcionen.
Salida del comando
La salida de Nextflow se ve igual que antes, pero los archivos .g.vcf y sus archivos índice ahora están organizados en subdirectorios.
Contenido del directorio (enlaces simbólicos acortados)
results/
├── gvcf/
│ ├── reads_father.bam.g.vcf -> */27/0d7eb9*/reads_father.bam.g.vcf
│ ├── reads_father.bam.g.vcf.idx -> */27/0d7eb9*/reads_father.bam.g.vcf.idx
│ ├── reads_mother.bam.g.vcf -> */e4/4ed55e*/reads_mother.bam.g.vcf
│ ├── reads_mother.bam.g.vcf.idx -> */e4/4ed55e*/reads_mother.bam.g.vcf.idx
│ ├── reads_son.bam.g.vcf -> */08/e95962*/reads_son.bam.g.vcf
│ └── reads_son.bam.g.vcf.idx -> */08/e95962*/reads_son.bam.g.vcf.idx
└── indexed_bam/
├── reads_father.bam -> */9a/c7a873*/reads_father.bam
├── reads_father.bam.bai -> */9a/c7a873*/reads_father.bam.bai
├── reads_mother.bam -> */f1/8d8486*/reads_mother.bam
├── reads_mother.bam.bai -> */f1/8d8486*/reads_mother.bam.bai
├── reads_son.bam -> */cc/fbc705*/reads_son.bam
└── reads_son.bam.bai -> */cc/fbc705*/reads_son.bam.bai
Si abres uno de los archivos GVCF y lo revisas, puedes verificar que GATK HaplotypeCaller produjo archivos GVCF según lo solicitado.
Conclusión¶
Cuando cambias el nombre del archivo de salida de un comando de herramienta, el bloque output: del proceso y la configuración de publicación/salida deben actualizarse para coincidir.
¿Qué sigue?¶
Aprende a recolectar el contenido de un canal y pasarlo al siguiente proceso como una única entrada.
2. Agregar un paso de genotipado conjunto¶
Ahora necesitamos recolectar los GVCFs por muestra, combinarlos en un almacén de datos GenomicsDB y ejecutar el genotipado conjunto para producir un VCF a nivel de cohorte.
Como se cubrió en la Parte 1, esta es una operación de dos herramientas: GenomicsDBImport combina los GVCFs, luego GenotypeGVCFs produce los llamados de variantes finales.
Envolveremos ambas herramientas en un único proceso llamado GATK_JOINTGENOTYPING.
Recuerda los dos comandos de la Parte 1:
gatk GenomicsDBImport \
-V reads_mother.g.vcf \
-V reads_father.g.vcf \
-V reads_son.g.vcf \
-L /data/ref/intervals.bed \
--genomicsdb-workspace-path family_trio_gdb
El primer comando toma los GVCFs por muestra y un archivo de intervalos, y produce un almacén de datos GenomicsDB.
El segundo toma ese almacén de datos, un genoma de referencia, y produce el VCF final a nivel de cohorte.
La URI del contenedor es la misma que para HaplotypeCaller: community.wave.seqera.io/library/gatk4:4.5.0.0--730ee8817e436867.
2.1. Configurar las entradas¶
El proceso de genotipado conjunto necesita dos tipos de entradas que aún no tenemos: un nombre arbitrario de cohorte y las salidas GVCF recolectadas de todas las muestras agrupadas juntas.
2.1.1. Agregar un parámetro cohort_name¶
Necesitamos proporcionar un nombre arbitrario para la cohorte.
Más adelante en la serie de capacitación aprenderás cómo usar metadatos de muestras para este tipo de cosas, pero por ahora simplemente declaramos un parámetro CLI usando params y le damos un valor predeterminado por conveniencia.
2.1.2. Reunir las salidas de HaplotypeCaller entre muestras¶
Si conectáramos el canal de salida de GATK_HAPLOTYPECALLER directamente al nuevo proceso, Nextflow llamaría al proceso en cada GVCF de muestra por separado.
Queremos agrupar los tres GVCFs (y sus archivos índice) para que Nextflow los entregue todos juntos a una única llamada de proceso.
Podemos hacer eso usando el operador de canal collect().
Agrega las siguientes líneas al cuerpo del workflow, justo después de la llamada a GATK_HAPLOTYPECALLER:
Desglosando esto:
- Tomamos el canal de salida de
GATK_HAPLOTYPECALLERusando la propiedad.out. - Debido a que nombramos las salidas usando
emit:en la sección 1, podemos seleccionar los GVCFs con.vcfy los archivos índice con.idx. Sin salidas nombradas, tendríamos que usar.out[0]y.out[1]. - El operador
collect()agrupa todos los archivos en un único elemento, por lo queall_gvcfs_chcontiene los tres GVCFs juntos, yall_idxs_chcontiene los tres archivos índice juntos.
Podemos recolectar los GVCFs y sus archivos índice por separado (en lugar de mantenerlos juntos en tuplas) porque Nextflow preparará todos los archivos de entrada juntos para la ejecución, por lo que los archivos índice estarán presentes junto a los GVCFs.
Tip
Puedes usar el operador view() para inspeccionar el contenido de los canales antes y después de aplicar operadores de canal.
2.2. Escribir el proceso de genotipado conjunto y llamarlo en el workflow¶
Siguiendo el mismo patrón que usamos en la Parte 2, escribiremos la definición del proceso en un archivo de módulo, lo importaremos en el workflow y lo llamaremos sobre las entradas que acabamos de preparar.
2.2.1. Construir una cadena para dar a cada GVCF un argumento -V¶
Antes de comenzar a completar la definición del proceso, hay una cosa que resolver.
El comando GenomicsDBImport espera un argumento -V separado para cada archivo GVCF, así:
gatk GenomicsDBImport \
-V reads_mother.bam.g.vcf \
-V reads_father.bam.g.vcf \
-V reads_son.bam.g.vcf \
...
Si escribiéramos -V ${all_gvcfs_ch}, Nextflow simplemente concatenaría los nombres de archivo y esa parte del comando se vería así:
Pero necesitamos que la cadena se vea así:
Importante, necesitamos construir esta cadena dinámicamente a partir de los archivos que estén en el canal recolectado. Nextflow (vía Groovy) proporciona una forma concisa de hacer esto:
Desglosando esto:
all_gvcfs.collect { gvcf -> "-V ${gvcf}" }itera sobre cada ruta de archivo y antepone-V, produciendo["-V A.g.vcf", "-V B.g.vcf", "-V C.g.vcf"]..join(' ')los concatena con espacios:"-V A.g.vcf -V B.g.vcf -V C.g.vcf".- El resultado se asigna a una variable local
gvcfs_line(definida condef), que podemos interpolar en la plantilla de comando.
Esta línea va dentro del bloque script: del proceso, antes de la plantilla de comando.
Puedes colocar código Groovy arbitrario entre script: y el """ de apertura de la plantilla de comando.
Entonces podrás referirte a toda esa cadena como gvcfs_line en el bloque script: del proceso.
2.2.2. Completar el módulo para el proceso de genotipado conjunto¶
Ahora podemos abordar la escritura del proceso completo.
Abre modules/gatk_jointgenotyping.nf y examina el esquema de la definición del proceso.
Adelante, completa la definición del proceso usando la información proporcionada arriba, luego verifica tu trabajo contra la solución en la pestaña "Después" a continuación.
| modules/gatk_jointgenotyping.nf | |
|---|---|
Hay varias cosas que vale la pena destacar aquí.
Como antes, varias entradas están listadas aunque los comandos no las referencien directamente: all_idxs, ref_index y ref_dict.
Listarlas asegura que Nextflow prepare estos archivos en el directorio de trabajo junto con los archivos que sí aparecen en los comandos, que GATK espera encontrar según convenciones de nomenclatura.
La variable gvcfs_line usa el closure de Groovy descrito arriba para construir los argumentos -V para GenomicsDBImport.
Este proceso ejecuta dos comandos en serie, tal como lo harías en la terminal.
GenomicsDBImport combina los GVCFs por muestra en un almacén de datos, luego GenotypeGVCFs lee ese almacén de datos y produce el VCF final a nivel de cohorte.
El almacén de datos GenomicsDB (${cohort_name}_gdb) es un artefacto intermedio usado solo dentro del proceso; no aparece en el bloque output.
Una vez que hayas completado esto, el proceso está listo para usar. Para usarlo en el workflow, necesitarás importar el módulo y agregar una llamada al proceso.
2.2.3. Importar el módulo¶
Agrega la declaración de importación a genomics.nf, debajo de las declaraciones de importación existentes:
El proceso ahora está disponible en el ámbito del workflow.
2.2.4. Agregar la llamada al proceso¶
Agrega la llamada a GATK_JOINTGENOTYPING en el cuerpo del workflow, después de las líneas collect():
El proceso ahora está completamente conectado. A continuación, configuramos cómo se publican las salidas.
2.3. Configurar el manejo de salidas¶
Necesitamos publicar las salidas del VCF conjunto. Agrega destinos de publicación y entradas de bloque output para los resultados de genotipado conjunto.
2.3.1. Agregar destinos de publicación para el VCF conjunto¶
Agrega el VCF conjunto y su índice a la sección publish: del workflow:
Ahora actualiza el bloque output para que coincida.
2.3.2. Agregar entradas de bloque output para el VCF conjunto¶
Agrega entradas para los archivos VCF conjunto. Los colocaremos en la raíz del directorio de resultados ya que esta es la salida final.
Con el proceso, los destinos de publicación y el bloque output todos en su lugar, podemos probar el workflow completo.
2.4. Ejecutar el workflow¶
Ejecuta el workflow para verificar que todo funcione.
Salida del comando
Los primeros dos pasos están almacenados en caché de la ejecución anterior, y el nuevo paso GATK_JOINTGENOTYPING se ejecuta una vez sobre las entradas recolectadas de las tres muestras.
El archivo de salida final, family_trio.joint.vcf (y su índice), están en el directorio de resultados.
Contenido del directorio (enlaces simbólicos acortados)
results/
├── family_trio.joint.vcf -> */a6/7cc8ed*/family_trio.joint.vcf
├── family_trio.joint.vcf.idx -> */a6/7cc8ed*/family_trio.joint.vcf.idx
├── gvcf/
│ ├── reads_father.bam.g.vcf -> */27/0d7eb9*/reads_father.bam.g.vcf
│ ├── reads_father.bam.g.vcf.idx -> */27/0d7eb9*/reads_father.bam.g.vcf.idx
│ ├── reads_mother.bam.g.vcf -> */e4/4ed55e*/reads_mother.bam.g.vcf
│ ├── reads_mother.bam.g.vcf.idx -> */e4/4ed55e*/reads_mother.bam.g.vcf.idx
│ ├── reads_son.bam.g.vcf -> */08/e95962*/reads_son.bam.g.vcf
│ └── reads_son.bam.g.vcf.idx -> */08/e95962*/reads_son.bam.g.vcf.idx
└── indexed_bam/
├── reads_father.bam -> */9a/c7a873*/reads_father.bam
├── reads_father.bam.bai -> */9a/c7a873*/reads_father.bam.bai
├── reads_mother.bam -> */f1/8d8486*/reads_mother.bam
├── reads_mother.bam.bai -> */f1/8d8486*/reads_mother.bam.bai
├── reads_son.bam -> */cc/fbc705*/reads_son.bam
└── reads_son.bam.bai -> */cc/fbc705*/reads_son.bam.bai
Si abres el archivo VCF conjunto, puedes verificar que el workflow produjo los llamados de variantes esperados.
¡Ahora tienes un workflow de llamado conjunto de variantes automatizado y completamente reproducible!
Note
Ten en cuenta que los archivos de datos que te proporcionamos cubren solo una pequeña porción del cromosoma 20. El tamaño real de un conjunto de llamados de variantes se contaría en millones de variantes. ¡Por eso usamos solo pequeños subconjuntos de datos para fines de capacitación!
Conclusión¶
Sabes cómo recolectar salidas de un canal y agruparlas como una única entrada para otro proceso. También sabes cómo construir una línea de comando usando closures de Groovy, y cómo ejecutar múltiples comandos en un único proceso.
¿Qué sigue?¶
Celebra tu éxito y tómate un merecido descanso.
En la siguiente parte de este curso, aprenderás cómo ejecutar un pipeline de llamado de variantes listo para producción desde nf-core y compararlo con el pipeline que construiste manualmente.