Parte 3: Chamada conjunta de variantes em uma coorte¶
Na Parte 2, você construiu um pipeline de chamada de variantes por amostra que processou os dados de cada amostra independentemente. Agora vamos estendê-lo para implementar a chamada conjunta de variantes, conforme abordado na Parte 1.
Tarefa¶
Nesta parte do curso, vamos estender o fluxo de trabalho para fazer o seguinte:
- Gerar um arquivo de índice para cada arquivo BAM de entrada usando o Samtools
- Executar o GATK HaplotypeCaller em cada arquivo BAM de entrada para gerar um GVCF de chamadas de variantes genômicas por amostra
- Coletar todos os GVCFs e combiná-los em um armazenamento de dados GenomicsDB
- Executar a genotipagem conjunta no armazenamento de dados GVCF combinado para produzir um VCF em nível de coorte
Esta parte se baseia diretamente no fluxo de trabalho produzido pela Parte 2.
Como começar a partir desta seção
Esta seção do curso pressupõe que você completou a Parte 2: Chamada de variantes por amostra e tem um pipeline genomics.nf funcional.
Se você não completou a Parte 2 ou deseja começar do zero para esta parte, pode usar a solução da Parte 2 como ponto de partida.
Execute estes comandos dentro do diretório nf4-science/genomics/:
cp solutions/part2/genomics-2.nf genomics.nf
cp solutions/part2/nextflow.config .
cp solutions/part2/modules/* modules/
Isso lhe dá um fluxo de trabalho completo de chamada de variantes por amostra. Você pode testar se ele é executado com sucesso executando o seguinte comando:
Plano de aula¶
Dividimos isso em duas etapas:
- Modificar a etapa de chamada de variantes por amostra para produzir um GVCF. Isso abrange a atualização de comandos e saídas do processo.
- Adicionar uma etapa de genotipagem conjunta que combina e genotipa os GVCFs por amostra.
Isso introduz o operador
collect(), closures Groovy para construção de linha de comando e processos com múltiplos comandos.
Note
Certifique-se de estar no diretório de trabalho correto:
cd /workspaces/training/nf4-science/genomics
1. Modificar a etapa de chamada de variantes por amostra para produzir um GVCF¶
O pipeline da Parte 2 produz arquivos VCF, mas a chamada conjunta requer arquivos GVCF. Precisamos ativar o modo de chamada de variantes GVCF e atualizar a extensão do arquivo de saída.
Relembre o comando de chamada de variantes GVCF da 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 ao comando base do HaplotypeCaller que encapsulamos na Parte 2, as diferenças são o parâmetro -ERC GVCF e a extensão de saída .g.vcf.
1.1. Informar ao HaplotypeCaller para emitir um GVCF e atualizar a extensão de saída¶
Abra o arquivo de módulo modules/gatk_haplotypecaller.nf para fazer duas alterações:
- Adicionar o parâmetro
-ERC GVCFao comando GATK HaplotypeCaller; - Atualizar o caminho do arquivo de saída para usar a extensão
.g.vcfcorrespondente, conforme convenção do GATK.
Certifique-se de adicionar uma barra invertida (\) no final da linha anterior quando adicionar -ERC GVCF.
Também precisamos atualizar o bloco de saída para corresponder à nova extensão de arquivo.
Como mudamos a saída do comando de .vcf para .g.vcf, o bloco output: do processo deve refletir a mesma mudança.
1.2. Atualizar a extensão do arquivo de saída no bloco de saídas do processo¶
Também precisamos atualizar a configuração de publicação e saída do fluxo de trabalho para refletir as novas saídas GVCF.
1.3. Atualizar os alvos de publicação para as novas saídas GVCF¶
Como agora estamos produzindo GVCFs em vez de VCFs, devemos atualizar a seção publish: do fluxo de trabalho para usar nomes mais descritivos.
Também organizaremos os arquivos GVCF em seu próprio subdiretório para maior clareza.
Agora atualize o bloco de saída para corresponder.
1.4. Atualizar o bloco de saída para a nova estrutura de diretórios¶
Também precisamos atualizar o bloco output para colocar os arquivos GVCF em um subdiretório gvcf.
Com o módulo, os alvos de publicação e o bloco de saída todos atualizados, podemos testar as alterações.
1.5. Executar o pipeline¶
Execute o fluxo de trabalho para verificar se as alterações funcionam.
Saída do comando
A saída do Nextflow parece a mesma de antes, mas os arquivos .g.vcf e seus arquivos de índice agora estão organizados em subdiretórios.
Conteúdo do diretório (links simbólicos encurtados)
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
Se você abrir um dos arquivos GVCF e percorrê-lo, poderá verificar que o GATK HaplotypeCaller produziu arquivos GVCF conforme solicitado.
Conclusão¶
Quando você altera o nome do arquivo de saída de um comando de ferramenta, o bloco output: do processo e a configuração de publicação/saída devem ser atualizados para corresponder.
O que vem a seguir?¶
Aprenda a coletar o conteúdo de um canal e passá-lo para o próximo processo como uma única entrada.
2. Adicionar uma etapa de genotipagem conjunta¶
Agora precisamos coletar os GVCFs por amostra, combiná-los em um armazenamento de dados GenomicsDB e executar a genotipagem conjunta para produzir um VCF em nível de coorte.
Conforme abordado na Parte 1, esta é uma operação de duas ferramentas: GenomicsDBImport combina os GVCFs, depois GenotypeGVCFs produz as chamadas de variantes finais.
Vamos encapsular ambas as ferramentas em um único processo chamado GATK_JOINTGENOTYPING.
Relembre os dois comandos da 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
O primeiro comando recebe os GVCFs por amostra e um arquivo de intervalos, e produz um armazenamento de dados GenomicsDB.
O segundo recebe esse armazenamento de dados, um genoma de referência e produz o VCF final em nível de coorte.
O URI do contêiner é o mesmo do HaplotypeCaller: community.wave.seqera.io/library/gatk4:4.5.0.0--730ee8817e436867.
2.1. Configurar as entradas¶
O processo de genotipagem conjunta precisa de dois tipos de entradas que ainda não temos: um nome de coorte arbitrário e as saídas GVCF coletadas de todas as amostras agrupadas juntas.
2.1.1. Adicionar um parâmetro cohort_name¶
Precisamos fornecer um nome arbitrário para a coorte.
Mais adiante na série de treinamento, você aprenderá como usar metadados de amostras para esse tipo de coisa, mas por enquanto apenas declaramos um parâmetro CLI usando params e damos a ele um valor padrão por conveniência.
2.1.2. Coletar as saídas do HaplotypeCaller entre amostras¶
Se conectássemos o canal de saída de GATK_HAPLOTYPECALLER diretamente ao novo processo, o Nextflow chamaria o processo em cada GVCF de amostra separadamente.
Queremos agrupar todos os três GVCFs (e seus arquivos de índice) para que o Nextflow entregue todos eles juntos em uma única chamada de processo.
Podemos fazer isso usando o operador de canal collect().
Adicione as seguintes linhas ao corpo do workflow, logo após a chamada a GATK_HAPLOTYPECALLER:
Analisando isso:
- Pegamos o canal de saída de
GATK_HAPLOTYPECALLERusando a propriedade.out. - Como nomeamos as saídas usando
emit:na seção 1, podemos selecionar os GVCFs com.vcfe os arquivos de índice com.idx. Sem saídas nomeadas, teríamos que usar.out[0]e.out[1]. - O operador
collect()agrupa todos os arquivos em um único elemento, entãoall_gvcfs_chcontém todos os três GVCFs juntos, eall_idxs_chcontém todos os três arquivos de índice juntos.
Podemos coletar os GVCFs e seus arquivos de índice separadamente (em vez de mantê-los juntos em tuplas) porque o Nextflow colocará todos os arquivos de entrada juntos para execução, então os arquivos de índice estarão presentes junto aos GVCFs.
Tip
Você pode usar o operador view() para inspecionar o conteúdo dos canais antes e depois de aplicar operadores de canal.
2.2. Escrever o processo de genotipagem conjunta e chamá-lo no fluxo de trabalho¶
Seguindo o mesmo padrão que usamos na Parte 2, escreveremos a definição do processo em um arquivo de módulo, importaremos para o fluxo de trabalho e o chamaremos nas entradas que acabamos de preparar.
2.2.1. Construir uma string para dar a cada GVCF um argumento -V¶
Antes de começarmos a preencher a definição do processo, há uma coisa a resolver.
O comando GenomicsDBImport espera um argumento -V separado para cada arquivo GVCF, assim:
gatk GenomicsDBImport \
-V reads_mother.bam.g.vcf \
-V reads_father.bam.g.vcf \
-V reads_son.bam.g.vcf \
...
Se escrevêssemos -V ${all_gvcfs_ch}, o Nextflow simplesmente concatenaria os nomes de arquivo e essa parte do comando ficaria assim:
Mas precisamos que a string fique assim:
Importante, precisamos construir essa string dinamicamente a partir de quaisquer arquivos que estejam no canal coletado. O Nextflow (via Groovy) fornece uma maneira concisa de fazer isso:
Analisando isso:
all_gvcfs.collect { gvcf -> "-V ${gvcf}" }itera sobre cada caminho de arquivo e anexa-Va ele, produzindo["-V A.g.vcf", "-V B.g.vcf", "-V C.g.vcf"]..join(' ')os concatena com espaços:"-V A.g.vcf -V B.g.vcf -V C.g.vcf".- O resultado é atribuído a uma variável local
gvcfs_line(definida comdef), que podemos interpolar no template de comando.
Esta linha vai dentro do bloco script: do processo, antes do template de comando.
Você pode colocar código Groovy arbitrário entre script: e as """ de abertura do template de comando.
Então você poderá se referir a toda essa string como gvcfs_line no bloco script: do processo.
2.2.2. Preencher o módulo para o processo de genotipagem conjunta¶
Agora podemos começar a escrever o processo completo.
Abra modules/gatk_jointgenotyping.nf e examine o esboço da definição do processo.
Vá em frente e preencha a definição do processo usando as informações fornecidas acima, depois verifique seu trabalho contra a solução na aba "Depois" abaixo.
| modules/gatk_jointgenotyping.nf | |
|---|---|
Há várias coisas que vale a pena destacar aqui.
Como anteriormente, várias entradas são listadas mesmo que os comandos não as referenciem diretamente: all_idxs, ref_index e ref_dict.
Listá-las garante que o Nextflow coloque esses arquivos no diretório de trabalho junto aos arquivos que aparecem nos comandos, que o GATK espera encontrar com base em convenções de nomenclatura.
A variável gvcfs_line usa a closure Groovy descrita acima para construir os argumentos -V para GenomicsDBImport.
Este processo executa dois comandos em série, assim como você faria no terminal.
GenomicsDBImport combina os GVCFs por amostra em um armazenamento de dados, depois GenotypeGVCFs lê esse armazenamento de dados e produz o VCF final em nível de coorte.
O armazenamento de dados GenomicsDB (${cohort_name}_gdb) é um artefato intermediário usado apenas dentro do processo; ele não aparece no bloco de saída.
Uma vez que você tenha completado isso, o processo está pronto para uso. Para usá-lo no fluxo de trabalho, você precisará importar o módulo e adicionar uma chamada de processo.
2.2.3. Importar o módulo¶
Adicione a instrução de importação a genomics.nf, abaixo das instruções de importação existentes:
O processo agora está disponível no escopo do fluxo de trabalho.
2.2.4. Adicionar a chamada do processo¶
Adicione a chamada a GATK_JOINTGENOTYPING no corpo do fluxo de trabalho, após as linhas collect():
O processo agora está totalmente conectado. Em seguida, configuramos como as saídas são publicadas.
2.3. Configurar o tratamento de saída¶
Precisamos publicar as saídas VCF conjuntas. Adicione alvos de publicação e entradas de bloco de saída para os resultados de genotipagem conjunta.
2.3.1. Adicionar alvos de publicação para o VCF conjunto¶
Adicione o VCF conjunto e seu índice à seção publish: do fluxo de trabalho:
Agora atualize o bloco de saída para corresponder.
2.3.2. Adicionar entradas de bloco de saída para o VCF conjunto¶
Adicione entradas para os arquivos VCF conjuntos. Vamos colocá-los na raiz do diretório de resultados, pois esta é a saída final.
Com o processo, os alvos de publicação e o bloco de saída todos no lugar, podemos testar o fluxo de trabalho completo.
2.4. Executar o fluxo de trabalho¶
Execute o fluxo de trabalho para verificar se tudo funciona.
Saída do comando
As duas primeiras etapas estão em cache da execução anterior, e a nova etapa GATK_JOINTGENOTYPING é executada uma vez nas entradas coletadas de todas as três amostras.
O arquivo de saída final, family_trio.joint.vcf (e seu índice), estão no diretório de resultados.
Conteúdo do diretório (links simbólicos encurtados)
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
Se você abrir o arquivo VCF conjunto, poderá verificar que o fluxo de trabalho produziu as chamadas de variantes esperadas.
Agora você tem um fluxo de trabalho de chamada conjunta de variantes automatizado e totalmente reproduzível!
Note
Tenha em mente que os arquivos de dados que fornecemos cobrem apenas uma pequena porção do cromossomo 20. O tamanho real de um conjunto de chamadas de variantes seria contado em milhões de variantes. É por isso que usamos apenas pequenos subconjuntos de dados para fins de treinamento!
Conclusão¶
Você sabe como coletar saídas de um canal e agrupá-las como uma única entrada para outro processo. Você também sabe como construir uma linha de comando usando closures Groovy e como executar múltiplos comandos em um único processo.
O que vem a seguir?¶
Comemore seu sucesso e faça uma pausa bem merecida.
Na próxima parte deste curso, você aprenderá como executar um pipeline de chamada de variantes pronto para produção do nf-core e compará-lo ao pipeline que você construiu manualmente.