A bioinformática tem um problema de reprodutibilidade. Uma pesquisa de 2015 descobriu que mais de 70% dos pesquisadores tentaram e falharam em reproduzir a análise computacional de outro laboratório. As causas são bem compreendidas: versões de software não documentadas, caminhos de arquivo codificados, análises executadas interativamente sem registrar etapas, sementes aleatórias não fixadas e modificações de dados sem rastreamento de proveniência.
Isso importa cientificamente (resultados que não podem ser reproduzidos não podem ser construídos sobre) e praticamente (você não será capaz de reproduzir sua própria análise seis meses depois sem essas práticas). Este capítulo cobre as práticas que separam a análise que funciona uma vez da análise que funciona de forma confiável.
A Pilha de Reprodutibilidade
A reprodutibilidade total requer abordar múltiplas camadas:
Código (versão exata)
↓
Ambiente de software (versões exatas de ferramentas, dependências)
↓
Dados (entrada exata, com checksums)
↓
Ambiente de computação (OS, arquitetura de CPU)
↓
Aleatoriedade (sementes fixadas)
↓
Documentação (parâmetros, decisões tomadas)
A falha em qualquer camada quebra a reprodutibilidade. Cada camada tem sua solução.
Controle de Versão: Git para Análise
Código sem controle de versão é não científico. Todo script de análise, configuração de pipeline e etapa de processamento de dados deve estar no git.
O que commitar:
- Scripts de análise (Python, R, bash)
- Arquivos de configuração de pipeline (regras Snakemake/Nextflow)
- Arquivos de parâmetros (planilhas de amostras, configuração YAML)
- Funções utilitárias personalizadas
O que NÃO commitar:
- Dados brutos (muito grandes; use ferramentas de gerenciamento de dados)
- Arquivos intermediários (muito grandes; regenere do pipeline)
- Credenciais ou chaves de API
- Arquivos binários grandes (use Git LFS se necessário)
Granularidade do commit: commit por etapa lógica ("adicionar etapa de trimming de leitura ao pipeline"), não por tecla e não por semana. O histórico de commits deve contar a história da análise.
Estratégia de branch para análises: use feature branches para mudanças experimentais; mescle ao main quando validado. Tags de releases que correspondem a submissões de artigos — você precisa ser capaz de verificar exatamente o código que gerou as figuras.
main: código de análise estável e revisado
├── feature/add-deseq2-analysis
├── feature/try-alternative-normalization
└── tags: submission-v1, revision-v1
Gerenciamento de Ambiente
O Problema de Dependências
As ferramentas de bioinformática são notoriamente conhecidas por cadeias de dependências complexas e sensibilidade à versão. Uma análise executada com DESeq2 versão 1.28 pode fornecer resultados diferentes da mesma análise com a versão 1.36 (devido a atualizações de algoritmo). As ferramentas podem conflitar com as dependências umas das outras.
Conda e Mamba
Conda cria ambientes isolados com versões de pacotes reproduzíveis:
# Create environment from specification file
conda env create -f environment.yml
# environment.yml
name: rnaseq-analysis
channels:
- bioconda
- conda-forge
dependencies:
- python=3.10
- snakemake=7.32
- fastqc=0.12
- star=2.7.10
- samtools=1.17
- r-base=4.3
- bioconductor-deseq2=1.40
Sempre fixe versões exatas no environment.yml. python>=3.8 não é reproduzível; python=3.10.6 é.
Mamba: substituto drop-in para conda com resolução de dependências mais rápida (solucionador C++ vs. Python). Use mamba onde você usaria conda.
Containers: Docker e Singularity
Conda captura pacotes Python/R, mas não o OS subjacente, bibliotecas do sistema ou binários compilados. Os containers capturam tudo:
Docker: empacota todo o ambiente de tempo de execução (OS, bibliotecas do sistema, ferramentas) em uma imagem portátil. A mesma imagem Docker é executada identicamente em qualquer máquina Linux.
FROM continuumio/miniconda3:23.3.1-0
COPY environment.yml .
RUN conda env create -f environment.yml
Singularity/Apptainer: alternativa ao Docker projetada para ambientes HPC onde o Docker requer acesso root. Converte imagens Docker; executa sem root. Padrão na maioria dos clusters de computação de pesquisa.
Melhores práticas: defina seu ambiente como um Dockerfile ou arquivo de ambiente Conda, construa o container e registre o hash da imagem na configuração do seu pipeline. O hash da imagem (SHA256) é uma impressão digital exata do ambiente de software.
A maioria dos clusters HPC não permite Docker (requer root), mas suporta Singularity/Apptainer. Nextflow e Snakemake suportam Singularity nativamente: especifique uma imagem de container por regra/processo, e o gerenciador de fluxo de trabalho puxa e executa o container automaticamente. Esta é a abordagem recomendada para portabilidade do pipeline em sistemas HPC.
Gerenciadores de Fluxo de Trabalho
Scripts bash ad hoc para análises de várias etapas têm modos de falha previsíveis:
- Nenhuma maneira de retomar da falha
- Re-executa toda a análise quando você muda uma etapa
- Sem gerenciamento de paralelização
- Sem especificação de recursos
Os gerenciadores de fluxo de trabalho resolvem todos esses problemas.
Snakemake
Snakemake usa um sistema baseado em regras: define regras que especificam entradas, saídas e o comando shell. O Snakemake constrói um DAG de dependência a partir dos arquivos de saída alvo e executa apenas o que é necessário.
# Snakefile
rule trim_reads:
input:
r1 = "data/raw/{sample}_R1.fastq.gz",
r2 = "data/raw/{sample}_R2.fastq.gz"
output:
r1 = "results/trimmed/{sample}_R1.fastq.gz",
r2 = "results/trimmed/{sample}_R2.fastq.gz"
threads: 4
resources:
mem_mb = 8000
shell:
"trimmomatic PE -threads {threads} {input.r1} {input.r2} "
"{output.r1} /dev/null {output.r2} /dev/null ..."
rule star_align:
input:
r1 = "results/trimmed/{sample}_R1.fastq.gz",
r2 = "results/trimmed/{sample}_R2.fastq.gz",
index = "data/reference/star_index"
output:
bam = "results/aligned/{sample}.bam"
...
Recursos-chave do Snakemake:
- Wildcards (
{sample}): escala automaticamente para todas as amostras - Checkpointing: se uma etapa falha, a re-execução retoma daquela etapa, não do início
- Integração com HPC: envia cada regra como um job de cluster separado automaticamente
- Suporte a container: diretiva
conda:ousingularity:por regra - Geração de relatório: relatório HTML com estatísticas de tempo de execução e proveniência de arquivos de saída
Nextflow
Nextflow usa um paradigma de dataflow: os processos comunicam via canais (filas de dados). Mais poderoso para fluxos de trabalho de ramificação complexos e computação em nuvem.
process TRIM_READS {
input:
tuple val(sample), path(reads)
output:
tuple val(sample), path("*.trimmed.fastq.gz")
script:
"""
trimmomatic PE ${reads[0]} ${reads[1]} ...
"""
}
workflow {
reads = Channel.fromFilePairs("data/raw/*_{R1,R2}.fastq.gz")
trimmed = TRIM_READS(reads)
ALIGN(trimmed)
}
nf-core: uma coleção comunitária de pipelines Nextflow para tarefas comuns de bioinformática (RNA-seq, ChIP-seq, chamada de variantes, etc.) seguindo boas práticas. Para análises padrão, usar um pipeline nf-core é frequentemente melhor do que escrever o seu próprio — os pipelines são extensivamente testados, documentados e mantidos.
Quando Usar Qual
| Caso de Uso | Ferramenta |
|---|---|
| Pipeline de análise personalizado | Snakemake (nativo Python, fácil de aprender) |
| Pipeline de produção, nuvem | Nextflow (melhor suporte à nuvem) |
| RNA-seq/ATAC-seq padrão | Pipeline nf-core |
| Scripts únicos, Jupyter | Ambiente conda + git |
Gerenciamento de Dados
Dados Brutos Imutáveis
Os dados brutos nunca devem ser modificados. Trate-os como somente leitura:
- Defina permissões de diretório para somente leitura após o download inicial
- Verifique checksums (MD5/SHA256) após o download e periodicamente
- Mantenha dados brutos separados de dados processados
Nunca modifique no lugar: se uma etapa de processamento requer conversão de formato, escreva em um novo arquivo. A cadeia de bruto → processado deve ser totalmente rastreável.
Versionamento de Dados com DVC
DVC (Data Version Control): extensão do Git para versionar arquivos de dados grandes. Armazena dados em S3/GCS/armazenamento local; commita apenas ponteiros (checksums) para o git.
dvc add data/raw/rnaseq_counts.tsv # track file in DVC
git add data/raw/rnaseq_counts.tsv.dvc # commit pointer
dvc push # push data to remote storage
Isso fornece o mesmo fluxo de trabalho que o git para dados: dvc pull para baixar a versão exata dos dados correspondente a um commit.
Planilhas de Amostras e Metadados
Toda análise deve ter uma planilha de amostras estruturada que mapeia IDs de amostras para:
- Caminhos de arquivos (dados brutos)
- Metadados biológicos (condição, genótipo, tecido, ponto de tempo)
- Metadados técnicos (lote, data de sequenciamento, preparação de biblioteca)
- Métricas de QC (se disponíveis)
Mantenha planilhas de amostras no git (são pequenas). Nunca codifique informações de amostra em nomes de arquivos como única fonte de verdade — os nomes de arquivos são alterados, copiados incorretamente ou truncados.
Notebooks Computacionais: Melhores Práticas do Jupyter
Os notebooks Jupyter são excelentes para análise exploratória e relatórios, mas problemáticos para reprodutibilidade quando usados ingenuamente:
- A ordem de execução de células não é registrada — os notebooks podem estar em um estado que não pode ser reproduzido executando de cima para baixo
- O estado oculto se acumula ao re-executar células em ordem arbitrária
- Notebooks grandes são difíceis de revisar e testar
Melhores práticas:
- Reiniciar e executar tudo antes de commitar — garantir que o notebook é executado de forma limpa de cima para baixo
- Notebooks parametrizados: use Papermill para executar notebooks com diferentes parâmetros — cada execução produz um notebook de saída separado, criando um registro
- Extrair código reutilizável para módulos
.py; notebooks devem chamar funções, não defini-las - Limpar saídas antes de commitar (ou use o hook git
nbstripout) — dados de saída em notebooks tornam os diffs ilegíveis e inflam o tamanho do repositório - Fixar o ambiente do kernel nos metadados do notebook ou em um
requirements.txtcomplementar
Aleatoriedade e Sementes
Qualquer análise usando aleatorização deve fixar a semente aleatória:
- Agrupamento (inicialização k-means)
- Redução de dimensionalidade (t-SNE, UMAP)
- Divisões treinamento/teste em ML
- Bootstrap e testes de permutação
- Gradiente descendente estocástico (redes neurais)
import numpy as np
import random
import torch
SEED = 42
np.random.seed(SEED)
random.seed(SEED)
torch.manual_seed(SEED)
# For CUDA:
torch.cuda.manual_seed_all(SEED)
Relate a semente nos métodos. Se a análise for sensível à escolha da semente, execute com múltiplas sementes e relate a distribuição dos resultados.
Qualidade do Código na Análise
O código de análise na academia frequentemente tem padrões de qualidade mais baixos do que o software de produção — mas isso custa reprodutibilidade:
Parâmetros configuráveis: nunca codifique caminhos de arquivo, limiares ou parâmetros em scripts. Use um arquivo de configuração (YAML/TOML) ou argumentos de linha de comando. Isso torna trivial a re-execução com diferentes parâmetros e documenta quais parâmetros foram usados.
# config.yaml
input:
counts: data/counts_matrix.tsv
metadata: data/sample_metadata.csv
deseq2:
fdr_threshold: 0.05
lfc_threshold: 1.0
reference_level: "control"
output:
dir: results/deseq2/
Logging sobre instruções print: use o módulo logging do Python ou futile.logger do R. Os logs devem incluir timestamps, valores de parâmetros e métricas-chave (tamanho da entrada, tamanho da saída, tempo de execução). Um arquivo de log é um registro do que realmente aconteceu durante uma execução.
Saídas intermediárias: grave resultados intermediários em etapas-chave. Se uma etapa downstream falha, você pode retomar sem re-executar etapas upstream caras (mesmo sem um gerenciador de fluxo de trabalho).
Relatórios e Documentação
Clareza da seção de métodos: a seção de métodos de um artigo de bioinformática deve ser reproduzível. Inclua nomes exatos de ferramentas, versões, parâmetros de linha de comando e versões de genoma de referência/anotação usados.
Métodos ruins: "Realizamos análise de expressão diferencial usando DESeq2 com parâmetros padrão."
Métodos bons: "A análise de expressão diferencial foi realizada com DESeq2 v1.40.0 (Love et al. 2014), usando GLM binomial negativo com teste de Wald. A fórmula de design era ~batch + condition, onde batch corrigiu para as duas execuções de sequenciamento. Os genes foram filtrados para aqueles com contagens normalizadas médias > 10 em todas as amostras. Os p-valores foram ajustados com FDR Benjamini-Hochberg; genes com padj < 0,05 e |log2FC| > 1 foram chamados de diferencialmente expressos."
Tabelas suplementares: forneça todos os resultados processados (tabelas completas de expressão diferencial, não apenas os principais hits) como arquivos para download. Revisores e futuros pesquisadores precisam dos resultados completos para validar descobertas ou usar como informação prévia.
A Lista de Verificação de Reprodutibilidade
Antes de submeter um artigo ou compartilhar uma análise:
- Todo o código em um repositório git com um README
- Ambiente de software especificado (conda
environment.ymlou Dockerfile) - Dados brutos arquivados com checksums
- O pipeline de análise é executado de ponta a ponta de dados brutos a figuras
- Todas as sementes aleatórias fixadas e documentadas
- Parâmetros de análise em arquivos de configuração, não codificados
- A seção de métodos inclui versões exatas de ferramentas e parâmetros
- Tabelas de resultados completas em dados suplementares (não apenas destaques filtrados)
- Repositório marcado na versão de submissão
Um autoteste comum para reprodutibilidade: "Alguém sem conhecimento deste projeto pode reproduzir as figuras-chave em seis meses usando apenas o repositório e a seção de métodos do artigo?" Se a resposta for não, a análise não é verdadeiramente reproduzível. O "alguém" pode ser você — os membros do laboratório partem, a memória desvanece e você precisará revisitar esta análise.
Resumo de Ferramentas
| Categoria | Ferramenta | Finalidade |
|---|---|---|
| Controle de versão | Git + GitHub/GitLab | Versionamento e colaboração de código |
| Ambiente | Conda/Mamba | Gerenciamento de pacotes |
| Containers | Docker + Singularity | Reprodutibilidade completa do ambiente |
| Fluxo de trabalho | Snakemake | Gerenciamento de pipeline (nativo Python) |
| Fluxo de trabalho | Nextflow + nf-core | Gerenciamento de pipeline (nuvem/HPC) |
| Versionamento de dados | DVC | Versionamento de arquivos grandes |
| Notebooks | Papermill | Execução de notebook parametrizado |
| Aleatoriedade | Sementes fixadas | Reprodutibilidade estocástica |
A reprodutibilidade não é um requisito burocrático — é o padrão científico básico que permite que as descobertas sejam construídas sobre. Cada hora investida nessas práticas economiza muitas horas de confusão, re-análise e falha de replicação.