# Guia do Desenvolvedor Este guia fornece documentação detalhada para os scripts Python usados no pipeline do ViralQC. Destina-se a desenvolvedores que desejam entender a lógica interna, escolhas de implementação e o fluxo de execução da ferramenta. Os scripts estão localizados em `viralqc/scripts/python/` e são orquestrados por workflows do Snakemake. ## Gerenciamento de datasets (Datasets) Estes scripts são usados pelos comandos `get-nextclade-datasets` e `get-blast-database` para baixar e preparar dados de referência. ### get_github_dataset.py **Propósito**: Baixa diretórios específicos de datasets de um repositório GitHub sem usar a API do GitHub (para evitar limites de taxa). **Execução**: Chamado por `get_public_datasets.smk` ao processar vírus configurados como `github`. **Detalhes de Implementação**: - **Sem Uso de API**: Em vez de usar a API do GitHub, baixa o arquivo compactado do repositório via `https://codeload.github.com/.../zip/refs/heads/main`. - **Extração Seletiva**: Faz o stream do arquivo zip e extrai apenas os arquivos que correspondem ao `dataset-path` solicitado. - **Achatamento de Estrutura**: Lida com a remoção da pasta raiz (ex: `repo-main/`) para colocar os arquivos diretamente no diretório de destino. ### jsonl_to_gff.py **Propósito**: Converte relatórios de anotação JSONL do NCBI Datasets para o formato GFF3, garantindo compatibilidade com o Nextclade. **Execução**: Chamado por `get_blast_database.smk` após baixar dados do NCBI RefSeq. **Funções Principais**: - `clean_cds_name(cds_name)`: Sanitiza nomes de CDS removendo caracteres especiais, truncando para 20 caracteres e padronizando a formatação. Isso é crucial porque o Nextclade pode falhar com nomes de genes complexos, duplicados ou muito longos. - `jsonl_to_gff(...)`: - **Validação**: Verifica se os comprimentos das CDS são múltiplos de 3. Se não, o número de acesso é marcado como inválido e excluído. - **Agrupamento**: Agrupa entradas de CDS divididas (ex: genes unidos) por nome para criar características gênicas únicas. - **Gene vs CDS**: Se os dados de CDS estiverem ausentes, tenta criar uma característica de gene usando o comprimento total do genoma (se divisível por 3). ### get_minimizer_index.py **Propósito**: Gera um arquivo JSON de índice de minimizadores a partir de arquivos FASTA de referência, permitindo que o Nextclade mapeie sequências para datasets externos (hospedados no GitHub). **Execução**: Chamado por `get_public_datasets.smk` para datasets hospedados no GitHub. **Detalhes de Implementação**: - **Origem**: Esta é uma adaptação simplificada do script `minimizer.py` do projeto Nextclade. - **Personalização**: A função `fasta_read` foi modificada para incluir o nome do dataset nas anotações do registro de sequência. Isso garante que o índice gerado associe corretamente minimizadores de sequência com seus caminhos de datasets locais correspondentes. ## Pipeline de Análise Estes scripts são executados durante o fluxo de trabalho principal `vqc run` para processar sequências, identificar vírus e avaliar a qualidade. ### format_nextclade_sort.py **Propósito**: Processa a saída do `nextclade sort` para vincular datasets identificados com seus caminhos de arquivos locais e identificar sequências que não corresponderam a nenhum conjunto de dados. **Execução**: Executado imediatamente após `nextclade sort` em `run_analysis.smk`. **Funções Principais**: - `map_datasets_to_local_paths(...)`: Lê a configuração YAML para construir um mapeamento entre nomes de datasets remotos (ex: do Nextclade) e caminhos de armazenamento local. - `format_nextclade_output(...)`: Mescla resultados de classificação "local" e "externo". Adiciona uma coluna `localDataset` apontando para o diretório do vírus identificado. - `write_unmapped_sequences(...)`: Extrai sequências que não têm conjunto de dados atribuído (`localDataset` é NaN) e grava seus nomes em `unmapped_sequences.txt` para análise subsequente do BLAST. ### blast_wrapper.py **Propósito**: Um wrapper em torno do comando `blastn` para lidar com segurança com cabeçalhos FASTA contendo espaços. **Execução**: Executado pela regra `blast` em `run_analysis.smk` para sequências que não foram identificadas pelo Nextclade. **Detalhes de Implementação**: - **Sanitização**: O BLAST pode truncar cabeçalhos no primeiro espaço, levando a incompatibilidades de ID em etapas de pós processamento. Este script verifica espaços nos cabeçalhos. - **Fluxo de Renomeação**: 1. Se espaços forem encontrados, gera um FASTA temporário onde as sequências são renomeadas para índices simples (1, 2, 3...). 2. Salva um arquivo de mapeamento (`mapping.tsv`) vinculando índices aos cabeçalhos originais. 3. Executa o BLAST com o arquivo renomeado. 4. Restaura os cabeçalhos originais no TSV de saída do BLAST usando o arquivo de mapeamento. ### reorder_cds.py **Propósito**: Reordena a string `cdsCoverage` na saída TSV do Nextclade para corresponder à ordem dos genes definida no arquivo GFF. **Execução**: Executado após cada execução do `nextclade run`. **Lógica**: - O Nextclade emite genes em ordem alfabética e omite genes com zero de cobertura. - Este script lê o GFF para estabelecer a ordem canônica dos genes (posição de `start`). - Analisa o `cdsCoverage` existente (formato `Gene:Cov,...`), reordena-o e insere `Gene:0.0` para quaisquer genes ausentes. Isso garante ordenação consistente das colunas para processamento posterior. ### post_process_nextclade.py **Propósito**: O script central de agregação que combina resultados do Nextclade, BLAST e análises genéricas em um relatório final. Calcula métricas de qualidade categóricas (notas A-D) e produz a saída final (TSV, CSV ou JSON). **Execução**: O passo final da regra `post_process_nextclade`. **Gerenciamento de Memória e Geradores**: Este script é projetado para processar datasets massivos (ex: milhões de sequências) com uma pegada de memória constante para saídas CSV/TSV. 1. **Carregamento Preguiçoso (Lazy Loading) com Geradores**: A função `format_dfs` é implementada como um **Gerador** Python. Em vez de retornar uma lista de todos os DataFrames (o que carregaria todos os arquivos na RAM), ela `yields` (produz) um DataFrame processado por vez. * **Lógica**: Itera pela lista de arquivos de entrada. Para cada arquivo, lê os dados, enriquece com metadados, otimiza tipos, entrega ao consumidor e **imediatamente** deleta a referência e força a "coleta de lixo" (garbage collection). 2. **Escrita em Fluxo (Streamed Writing)**: A função `write_combined_df` (e sua auxiliar `_write_csv_tsv_output`) consome este gerador. Itera sobre o gerador, escrevendo cada pedaço produzido no disco imediatamente usando `mode='a'` (append/anexar). * **Resultado**: Em qualquer momento dado, apenas os dados de um único arquivo de entrada existem na memória. * **Limitação JSON**: Para saída JSON (`_write_json_output`), o script *deve* acumular todos os dados para formar um array JSON válido. No entanto, ainda emprega coleta de lixo para descartar artefatos de processamento intermediários assim que são anexados à lista principal. 3. **Coleta de Lixo Explícita**: A coleta de lixo automática do Python pode não ser acionada rápido o suficiente ao lidar com loops grandes e apertados de carregamento de dados. Chamadas explícitas de `del` combinadas com `gc.collect()` são colocadas estrategicamente para garantir que a memória seja liberada de volta para o SO antes de alocar o próximo pedaço. **Funções Principais**: * `format_dfs(files, config_file, blast_metadata_df)`: O gerador primário. Determina se um arquivo de resultado pertence a um vírus conhecido (com dataset configurado no YAML) ou é uma execução genérica (nextclade executado com referências informadas pela análise de BLAST). Chama a lógica de processamento apropriada (`_process_with_virus_info` ou `_process_generic_run`) e produz o resultado. * `load_blast_metadata(metadata_path)`: Carrega os metadados do banco de dados BLAST e normaliza nomes de colunas (ex: `accession` -> `virus`) para garantir consistência com as saídas do Nextclade. * `optimize_dataframe_memory(df)`: Analisa colunas do DataFrame. Se uma coluna de string (como `virus`, `clade`, `dataset`) tiver uma baixa cardinalidade (número de valores únicos < 50% do total de linhas), converte a coluna para o tipo `category`. Isso reduz drasticamente o uso de RAM. * `add_qualities(df, virus_info)`: Aplica a lógica de pontuação de qualidade linha por linha. Invoca o auxiliar `_compute_metrics_qualities` e então usa as funções `get_*_quality` para atribuir notas. * `add_coverages(df, virus_info)`: Analisa e formata a string `cdsCoverage`. Também calcula a cobertura para regiões alvo específicas e as adiciona como novas colunas (`targetRegionsCoverage`, `targetGeneCoverage`). * `format_sc2_clade(df, dataset_name)`: Contém lógica específica para SARS-CoV-2. Como o Nextclade emite linhagens Pango em uma coluna específica (`Nextclade_pango`), esta função mapeia para a coluna `clade` padrão para consistência. * `create_unmapped_df(unmapped_sequences, blast_results, blast_metadata_df)`: Lida com sequências que falharam tanto na identificação do Nextclade quanto no BLAST. Lê o arquivo bruto `unmapped_sequences.txt` e cria um DataFrame rotulado como "Unclassified". * `write_combined_df(df_iterator, output_file, output_format, ...)`: O despachante principal. Recebe o gerador `format_dfs` (iterador) e o direciona para o backend de escrita apropriado (CSV/TSV ou JSON). **Funções de Controle de Qualidade**: * `get_genome_quality(scores)`: Agrega pontuações de métricas individuais em uma Qualidade de Genoma final. Soma as pontuações (A=4, B=3, C=2, D=1) e normaliza para uma escala de 24 pontos para atribuir a nota final. * `get_target_regions_quality(...)`: Determina a qualidade de regiões alvo específicas. Lógica: Se o genoma inteiro for A/B, retorna vazio (implícito bom). Caso contrário, calcula a cobertura média das regiões alvo para atribuir uma nota. * `get_cds_cov_quality(...)`: Verifica cada CDS contra limites de cobertura para atribuir notas A/B/C/D por gene. * `get_missing_data_quality(coverage)`: Pontuado com base em limites (0.9, 0.75, 0.5). * `get_private_mutations_quality(total, threshold)`: Pontuado com base no desvio de um limite definido. * `get_qc_quality(total)`: Pontuação geral para métricas de contagem (0=A, 1=B, 2=C, >2=D). ### extract_target_regions.py **Propósito**: Extrai as coordenadas genômicas de regiões de "boa qualidade" para uso posterior (ex: geração de consenso ou design de primers). **Execução**: Executado pela regra `extract_target_regions` após o pós-processamento. **Lógica de Seleção**: A função `check_target_regions` determina a melhor região para extrair com base na qualidade: 1. **Genoma**: Se o `genomeQuality` geral for A ou B, o genoma inteiro é selecionado. 2. **Região Alvo**: Senão, se `targetRegionsQuality` for A ou B, as regiões alvo específicas são selecionadas. 3. **Gene Alvo**: Senão, se `targetGeneQuality` for A ou B, o gene alvo é selecionado. **Mapeamento de Coordenadas**: - Usa `get_regions` para consultar as coordenadas de início/fim da característica selecionada (gene ou genoma completo) no arquivo GFF. - Produz um arquivo BED compatível com `seqtk subseq`.