Parte 3: Llamado de variantes conjunto en una cohorte¶
Traducción asistida por IA - más información y sugerencias
Anteriormente, 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 de variantes conjunto, como se describe en la Parte 1 (caso de uso multi-muestra).
Cómo comenzar desde esta sección
Esta sección del curso asume que has completado la Parte 1: Descripción del método, 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 da un workflow completo de llamado de variantes por muestra. Puedes probar que se ejecuta exitosamente ejecutando el siguiente comando:
Asignación¶
En esta parte del curso, vamos a extender el workflow para hacer lo siguiente:
- Generar un archivo de í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
Esto implementa el método descrito en la Parte 1: Descripción del método (segunda sección que cubre el caso de uso multi-muestra) y se construye directamente sobre el workflow producido en la Parte 2: Llamado de variantes por muestra.
Plan de la lección¶
Hemos dividido esto en dos etapas:
- 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ínea de comandos, y procesos con múltiples comandos.
Esto automatiza los pasos de la segunda sección de la Parte 1: Descripción del método, donde ejecutaste estos comandos manualmente en sus contenedores.
Consejo
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
.g.vcfcorrespondiente, 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 de salida 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 de salida para que coincida.
1.4. Actualizar el bloque de salida 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 de salida todos 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 de í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 como se solicitó.
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 sola 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 solo 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.
El URI del contenedor es el mismo 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 de cohorte arbitrario, 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.
Usaremos este parámetro para nombrar el archivo de salida final.
2.1.2. Agregar un valor predeterminado para cohort_name en el perfil de prueba¶
También agregamos un valor predeterminado para el parámetro cohort_name en el perfil de prueba:
| nextflow.config | |
|---|---|
A continuación, necesitaremos reunir las salidas por muestra para que puedan procesarse juntas.
2.1.3. Reunir las salidas de HaplotypeCaller a través de las 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 de índice) para que Nextflow los entregue todos juntos a una sola 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 de índice con.idx. Sin salidas nombradas, tendríamos que usar.out[0]y.out[1]. - El operador
collect()agrupa todos los archivos en un solo elemento, por lo queall_gvcfs_chcontiene los tres GVCFs juntos, yall_idxs_chcontiene los tres archivos de índice juntos.
Podemos recolectar los GVCFs y sus archivos de í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 de índice estarán presentes junto a los GVCFs.
Consejo
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 al workflow y lo llamaremos con 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 cualquier archivo que esté 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-Va ella, produciendo["-V A.g.vcf", "-V B.g.vcf", "-V C.g.vcf"]..join(' ')las 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 las """ de apertura de la plantilla de comando.
Luego 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¶
A continuación, 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 anteriormente, varias entradas están listadas aunque los comandos no las referencian directamente: all_idxs, ref_index y ref_dict.
Listarlas asegura que Nextflow prepare estos archivos en el directorio de trabajo junto a los archivos que sí aparecen en los comandos, que GATK espera encontrar basándose en 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 de salida.
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 de 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():
| genomics.nf | |
|---|---|
| genomics.nf | |
|---|---|
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 de salida para los resultados del 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 de salida para que coincida.
2.3.2. Agregar entradas de bloque de salida para el VCF conjunto¶
Agrega entradas para los archivos VCF conjuntos. 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 de salida 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 en caché de la ejecución anterior, y el nuevo paso GATK_JOINTGENOTYPING se ejecuta una vez en 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 de variantes conjunto automatizado y completamente reproducible!
Nota
Ten en cuenta que los archivos de datos que te dimos 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 subconjuntos pequeños de datos para propósitos de capacitación!
Conclusión¶
Sabes cómo recolectar salidas de un canal y agruparlas como una sola entrada a otro proceso. También sabes cómo construir una línea de comandos usando closures de Groovy, y cómo ejecutar múltiples comandos en un solo proceso.
¿Qué sigue?¶
¡Date una gran palmada en la espalda! Has completado el curso Nextflow para Genómica.
Dirígete al resumen del curso final para revisar lo que aprendiste y descubrir qué viene después.