Metadata-Version: 2.4
Name: omnigrid
Version: 1.0.2
Summary: Just-In-Time AutoGrid4 parameterization for the full periodic table
Author-email: Cleiton Augusto Correa Bezerra <augusto.cleiton@gmail.com>, Fernando Berton Zanchi <fernando.zanchi@fiocruz.br>
License-Expression: MIT OR Apache-2.0
Project-URL: Homepage, https://github.com/cleitonaugusto/OmniGrid
Project-URL: Documentation, https://github.com/cleitonaugusto/OmniGrid/blob/main/docs/MANUAL.md
Project-URL: Repository, https://github.com/cleitonaugusto/OmniGrid
Project-URL: Issues, https://github.com/cleitonaugusto/OmniGrid/issues
Project-URL: Paper, https://github.com/cleitonaugusto/OmniGrid/tree/main/paper
Keywords: molecular-docking,autodock4,autogrid4,virtual-screening,drug-discovery,metal-complexes,uff,rdkit
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Classifier: Topic :: Scientific/Engineering :: Chemistry
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE-APACHE
License-File: LICENSE-MIT
Requires-Dist: rdkit>=2022.09.1
Requires-Dist: numpy>=1.21
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Dynamic: license-file

# OmniGrid

[![CI](https://github.com/cleitonaugusto/OmniGrid/actions/workflows/ci.yml/badge.svg)](https://github.com/cleitonaugusto/OmniGrid/actions/workflows/ci.yml)
[![PyPI version](https://img.shields.io/pypi/v/omnigrid)](https://pypi.org/project/omnigrid/)
[![Python versions](https://img.shields.io/pypi/pyversions/omnigrid)](https://pypi.org/project/omnigrid/)
[![License: MIT OR Apache-2.0](https://img.shields.io/badge/License-MIT%20OR%20Apache--2.0-blue)](LICENSE-MIT)
[![ORCID](https://img.shields.io/badge/ORCID-0009--0003--5543--8026-brightgreen?logo=orcid)](https://orcid.org/0009-0003-5543-8026)

**Pipeline de Triagem Virtual de Alta Escala com Parametrização Just-In-Time para 61 Elementos via UFF**

OmniGrid estende o AutoGrid4/AutoDock-GPU para qualquer elemento químico, resolvendo o problema clássico de *buffer-overflow* ao calcular parâmetros UFF *sob demanda* — apenas para os átomos presentes em cada ligante — em vez de carregar a tabela periódica inteira de uma só vez.

---

## Funcionalidades

| Capacidade | Detalhe |
|---|---|
| Qualquer elemento | B, Si, Pt, Ru, Ir, Au, Re, Os, lantanídeos … via Universal Force Field (Rappé 1992) — **61 elementos** |
| Parâmetros JIT | `AD4_parameters_temp.dat` reconstruído por ligante; **~50% menor** que tabela completa |
| Detecção de cargas | Preserva cargas QM/RESP pré-existentes em PDBQT; **GFN2-xTB (xtb)** como método primário para ligantes com átomos exóticos; Gasteiger via RDKit para orgânicos puros; fallback gradual (formal → lookup → zero) |
| Cargas quânticas | **GFN2-xTB (xtb)** integrado — calcula cargas parciais de nível quântico para **qualquer elemento** (Pt, Ru, Fe, ...); auto-instalado via `omnigrid setup` (~61 MB) |
| Grid automático | Centro e dimensões calculados pelo bounding-box do ligante + padding de 5 Å |
| Log de auditoria | Registra exatamente quais parâmetros UFF foram injetados, por átomo, por corrida |
| Batch completo | Varre uma pasta; processa `.sdf / .mol2 / .pdb / .pdbqt` |
| Processamento paralelo | `process_batch_parallel()` distribui ligantes em múltiplos núcleos de CPU |
| Download automático | `fetcher.py` baixa estruturas do PubChem (CID) e RCSB PDB em paralelo |
| Modo dry-run | Gera arquivos sem executar o AutoGrid4 |
| Standalone | **Zero dependências externas** — RDKit substitui MGLTools, OpenBabel e AutoDock Tools |
| Instalável | `pip install .` → CLI `omnigrid` disponível no PATH |
| Benchmarks | Cobertura vs MGLTools/Meeko, speed, throughput, fidelidade UFF, eficiência de memória |

---

## Instalação

> 💡 **Primeiro, veja se você tem o Conda instalado.**  
> Abra o terminal e digite `conda --version`.  
> Se aparecer `command not found`:
> - **Linux:** `wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh && bash Miniconda3-latest-Linux-x86_64.sh -b -u`
> - **Windows:** https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe
> - **macOS:** `wget https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh && bash Miniconda3-latest-MacOSX-arm64.sh -b -u`

### Via Conda (recomendado)

```bash
# 1. Cria o ambiente (uma "caixa" chamada omnigrid)
conda create -n omnigrid python=3.10 -y
# 2. Ativa o ambiente (entra na caixa)
conda activate omnigrid
# 3. Instala o RDKit (manipulação de moléculas)
conda install -c conda-forge rdkit -y
# 4. Instala o OmniGrid
pip install git+https://github.com/cleitonaugusto/OmniGrid.git
# 5. Verifica
omnigrid --help
```

### Via clone (desenvolvimento)

```bash
conda create -n omnigrid python=3.10 -y
conda activate omnigrid
conda install -c conda-forge rdkit -y
git clone https://github.com/cleitonaugusto/OmniGrid.git
cd OmniGrid
pip install -e ".[dev]"
pytest tests/ -v
```

### Quando terminar

```bash
conda deactivate
```

> 📘 Guia rápido para iniciantes: [`docs/GUIA_RAPIDO.md`](docs/GUIA_RAPIDO.md)  
> Documentação completa: [`docs/MANUAL.md`](docs/MANUAL.md)

---

## Uso Rápido

### Via CLI (instalado)

```bash
omnigrid --receptor receptors/3UDX.pdbqt --ligands ligands/ --output results/
```

### Via módulo Python

```bash
python -m omnigrid --receptor receptors/3UDX.pdbqt --ligands ligands/ --output results/
```

### Via script legado

```bash
python run_omnigrid.py --receptor receptors/3UDX.pdbqt --ligands ligands/ --output results/
```

### Exemplos prontos

```bash
cd examples/
python3 01_prepare_receptor.py    # Baixar + preparar receptor
python3 02_generate_ligands.py    # Gerar ligantes de teste
python3 03_run_omnigrid.py        # Rodar pipeline (dry-run)
python3 04_multimetal_example.py  # Complexo heterobimetálico Pt+Ir
python3 05_screening_example.py   # Screening paralelo com 5 metais
```

---

## Preparação do Receptor (RDKit — sem dependências externas)

O OmniGrid usa **RDKit** para preparar receptores, substituindo MGLTools e OpenBabel:

```python
from pathlib import Path
from omnigrid.receptor_preparer import prepare_receptor

prepare_receptor(Path("receptors/3UDX.pdb"), Path("receptors/3UDX.pdbqt"))
```

Isso adiciona hidrogênios, atribui cargas de Gasteiger pré-computadas para resíduos padrão e gera PDBQT completo.

> **Nota sobre cargas:** Resíduos padrão (ALA–VAL, HIS, etc.) usam **cargas pré-computadas** validadas, evitando o problema de NaN que ocorre quando RDKit parseia PDB sem ordem de ligação. HETATM/cofatores usam Gasteiger como fallback com WARNING explícito.

---

## Uso Detalhado

### Execução mínima (grid automático por bounding-box)

```bash
omnigrid --receptor receptors/3UDX.pdbqt --ligands ligands/ --output results/
```

### Grid com centro e dimensões explícitas

```bash
omnigrid \
    --receptor  receptors/3UDX.pdbqt \
    --ligands   ligands/ \
    --output    results/ \
    --center    12.5 -3.2 8.7 \
    --npts      60 60 60 \
    --spacing   0.375
```

### Processamento paralelo

```bash
omnigrid --receptor receptors/3UDX.pdbqt --ligands ligands/ --output results/ --workers 8
```

### Dry-run

```bash
omnigrid --dry-run --receptor receptors/3UDX.pdbqt --ligands ligands/ --output results/
```

### Todos os parâmetros CLI

```
omnigrid --help
```

| Flag | Padrão | Descrição |
|---|---|---|
| `--receptor` | — | Arquivo PDBQT do receptor (obrigatório) |
| `--ligands` | — | Pasta com arquivos de ligantes (obrigatório) |
| `--output` | — | Pasta de saída (criada se ausente) |
| `--base-dat` | embutido | `AD4_parameters.dat` base |
| `--center X Y Z` | auto | Centro do grid em Å |
| `--npts NX NY NZ` | 40 40 40 | Pontos do grid por eixo |
| `--spacing` | 0.375 | Espaçamento do grid em Å |
| `--smooth` | 0.5 | Suavização do potencial |
| `--dielectric` | -0.1465 | Dielétrico dependente da distância |
| `--charge-scheme` | auto | Esquema de cargas: auto, gasteiger, xtb |
| `--padding` | 5.0 | Margem do bounding-box em Å (modo auto) |
| `--workers` | 1 | Núcleos de CPU para processamento paralelo |
| `--audit-log` | `results/uff_audit.log` | Caminho do log de auditoria UFF |
| `--autogrid` | `autogrid4` | Executável do AutoGrid4 |
| `--timeout` | 3600 | Timeout por ligante (segundos) |
| `--dry-run` | False | Gera arquivos sem executar AutoGrid4 |
| `--stop-on-error` | False | Aborta o batch no primeiro erro |
| `--log-level` | INFO | Verbosidade: DEBUG/INFO/WARNING/ERROR |

---

## Arquitetura

```
OmniGrid/
├── omnigrid/
│   ├── __init__.py         # Metadados + cite()
│   ├── __main__.py         # python -m omnigrid
│   ├── cli.py              # CLI entry point (omnigrid)
│   ├── atom_params.py      # Tabela UFF, dataclass AtomParams, fórmulas vol/solpar
│   ├── receptor_preparer.py # PDB → PDBQT via RDKit (H + cargas pré-computadas)
│   ├── ligand_reader.py    # Extração de tipos AD4 + detecção de cargas
│   ├── pdbqt_writer.py     # PDBQT para ligantes exóticos (torção-tree completa)
│   ├── params_writer.py    # Gera AD4_parameters_temp.dat + UFFAuditLog
│   ├── gpf_generator.py    # Gera .gpf com ligand_types, map lines e auto_grid_box
│   ├── runner.py           # Wrapper subprocess do AutoGrid4
│   ├── pipeline.py         # Orquestração sequencial e paralela
│   └── fetcher.py          # Download PubChem + RCSB PDB
├── examples/
│   ├── 01_prepare_receptor.py
│   ├── 02_generate_ligands.py
│   ├── 03_run_omnigrid.py
│   ├── 04_multimetal_example.py
│   ├── 05_screening_example.py
│   └── README.md
├── tests/
│   ├── test_validation.py      # Validação UFF, .dat, .gpf, auto_grid_box, cargas
│   ├── test_integration.py     # Pipeline end-to-end (dry-run + autogrid4)
│   ├── test_integration_real.py# Receptores reais (3UDX, 3ZNT, 8FQM)
│   ├── test_heavy_elements.py  # 49 elementos + complexos de coordenação
│   ├── test_benchmarks.py      # Speed, coverage, throughput, memória, fidelidade
│   └── test_pdbqt_writer.py    # PDBQT formatting + torsion tree
├── docs/
│   ├── MANUAL.md               # Documentação completa
│   └── GUIA_RAPIDO.md          # Guia rápido em 5 passos
├── paper/
│   ├── paper.md                # JOSS paper (English)
│   └── paper_pt.md             # Versão em Português
├── pyproject.toml              # pip install, CLI entry point, metadata
├── run_omnigrid.py             # CLI legado (compatibilidade)
├── CITATION.cff                # Metadados de citação
├── LICENSE-MIT                 # MIT License
└── LICENSE-APACHE              # Apache-2.0 License
```

---

## API Python

### Preparação de receptor

```python
from pathlib import Path
from omnigrid.receptor_preparer import prepare_receptor

prepare_receptor(Path("receptors/3UDX.pdb"), Path("receptors/3UDX.pdbqt"))
```

### Processamento sequencial

```python
from pathlib import Path
from omnigrid.pipeline import PipelineConfig, process_batch

cfg = PipelineConfig(
    receptor_pdbqt = Path("receptors/3UDX.pdbqt"),
    ligands_dir    = Path("ligands/"),
    output_dir     = Path("results/"),
)
results = process_batch(cfg)

for r in results:
    status = "OK" if r.success else f"FALHOU: {r.error}"
    print(f"{r.ligand.name}  {status}  exóticos={r.exotic_types}")
```

### Processamento paralelo

```python
from omnigrid.pipeline import process_batch_parallel

results = process_batch_parallel(cfg, n_workers=8)
```

### Download automático de estruturas

```python
from pathlib import Path
from omnigrid.fetcher import fetch_pubchem_structures, fetch_pdb_structures

baixados = fetch_pubchem_structures(
    cids=[2519, 5090, 702],
    output_dir=Path("ligands/"),
    n_workers=4,
)

estruturas = fetch_pdb_structures(
    pdb_ids=["1HVR", "4DKL", "3UDX"],
    output_dir=Path("receptors/"),
    n_workers=4,
)
```

### Detecção de cargas parciais

```python
from omnigrid.ligand_reader import extract_charges

info = extract_charges(Path("ligando_qm.pdbqt"))
# info.source    → 'pdbqt_preexisting' (QM/RESP) | 'gasteiger' | 'none'
# info.preserved → True se cargas foram preservadas do arquivo de entrada
# info.charges   → {serial_atômico: carga_parcial}
```

### Citando o projeto

```python
import omnigrid
omnigrid.cite()
```

---

## Base Física

### Volume de solvatação

```
vol = (4/3) × π × (Rii/2)³
```

Validado contra o arquivo AD4 padrão:  
C (Rii = 4,00 Å) → 33,51 Å³ ✓  
N (Rii = 3,50 Å) → 22,45 Å³ ✓

### Parâmetro de solvatação (modelo Stouten)

```
solpar = S_classe / vol
```

| Classe | Elementos | S calibrado |
|---|---|---|---|
| Não-polar | B, Si, Ge, Al, Sn, Pb, Ga, In, Tl, As, Sb, Bi | −4,792 × 10⁻² |
| Polar | Se, Te | −3,637 × 10⁻² |
| Metais de transição | Pt, Ru, Ir, Au, Cu, Zn, … | −2,860 × 10⁻³ |
| Lantanídeos | La, Ce, Pr, Nd, Sm, Eu, Gd, Tb, Dy, Ho, Er, Yb, Lu | −6,000 × 10⁻³ |

### Parâmetros UFF

Fonte: Rappé, A. K. et al. *J. Am. Chem. Soc.* **1992**, *114*(25), 10024–10035. DOI: [10.1021/ja00051a040](https://doi.org/10.1021/ja00051a040)

| Campo AD4 | Campo UFF | Descrição |
|---|---|---|
| `Rii` | `x1` | Parâmetro de distância vdW (Å) |
| `epsii` | `D1` | Profundidade do poço (kcal/mol) |
| `r_cov` | `r_1` | Raio covalente de ligação simples (Å) |

### Cálculo automático do grid (auto_grid_box)

O centro é o ponto médio do bounding-box (não o centróide):

```
centro_eixo = (coord_max + coord_min) / 2
npts_eixo   = ⌈(coord_max − coord_min + 2 × padding) / spacing⌉  (arredondado para par)
```

---

## Auditoria de Parâmetros UFF

Cada corrida com tipos exóticos gera entradas em `uff_audit.log`:

```
# OmniGrid — UFF Parameter Injection Audit Log
# timestamp            ligand                  type    Rii      epsii    vol        solpar     r_cov   hbond  source
2026-05-06T14:23:04  cisplatina_qm             Pt      2.4530   0.0800   7.7284    -0.000370  1.3640  0      UFF_Rappe1992
2026-05-06T14:23:11  boronic_acid_frag         B       3.6370   0.0950   25.1900   -0.001902  0.8040  0      UFF_Rappe1992
```

Cargas Gasteiger NaN/Inf disparam o fallback **GFN2-xTB (xtb)** automaticamente:

```
INFO: Gasteiger failed for 12 atoms — running GFN2-xTB for quantum-level charges...
INFO: xtb charge: Pt@idx1 = +0.432  Ir@idx15 = -0.218
```

Estratégia completa de cargas: GFN2-xTB (para exóticos) → Gasteiger → GFN2-xTB (fallback) → carga formal → lookup table → zero.

Para controle total, forneça PDBQT com cargas QM/RESP pré-existentes (o pipeline as preserva).

---

## Estrutura de Saída

```
results/
├── uff_audit.log                    # Log de auditoria UFF (toda a campanha)
└── <nome_ligante>/
    ├── AD4_parameters_temp.dat      # Parâmetros JIT (base + exóticos do ligante)
    ├── <nome_ligante>.pdbqt         # Ligante convertido para PDBQT
    ├── <nome_ligante>.gpf           # Arquivo de parâmetros de grid (AutoGrid4)
    ├── <nome_ligante>.glg           # Log do AutoGrid4
    ├── <receptor>.maps.fld          # Descritor do campo de grid
    ├── <receptor>.C.map             # Mapa de afinidade — carbono
    ├── <receptor>.Pt.map            # Mapa de afinidade — platina (tipo exótico)
    ├── <receptor>.e.map             # Mapa eletrostático
    └── <receptor>.d.map             # Mapa de dessolvatação
```

---

## Benchmarks

OmniGrid foi validado e benchmarkado contra abordagens tradicionais. Para gerar os gráficos:

```bash
python3 docs/benchmarks/generate_charts.py
```

### Cobertura de elementos

![Cobertura de elementos](docs/benchmarks/01_element_coverage.png)

Benchmark experimental com **63 ligantes** representando todas as categorias da tabela UFF:

| Categoria | Total | OmniGrid | MGLTools | Meeko |
|---|---|---|---|---|---|
| Orgânicos (C,H,N,O,S,P,F,Cl,Br,I) | 7 | **7/7** | 7/7 | 7/7 |
| Semimetais (B, Si, Ge, As, Se) | 6 | **6/6** | 6/6¹ | 3/6² |
| Metais de transição (Ti, V, Cr, Mn, Fe, Co, Ni, Cu, Zn, Zr, Nb, Mo, Tc, Ru, Rh, Pd, Ag, Cd, Hf, Ta, W, Re, Os, Ir, Pt, Au, Hg, Sc, Y, La, …) | 28 | **28/28** | 22/28³ | 1/28⁴ |
| Metais do bloco p (Al, Ga, In, Tl, Sn, Pb, Bi, Sb) | 8 | **8/8** | 8/8¹ | 0/8 |
| Alcalinos (Li, Na, K) | 3 | **3/3** | 3/3¹ | 0/3 |
| Lantanídeos (Ce, Pr, Nd, Sm, Eu, Gd, Ho, Er, Yb, Lu) | 11 | **11/11** | 11/11¹ | 0/11 |
| **Total** | **63** | **63/63 (100%)** | **57/63 (90%)** | **11/63 (17%)** |

> ⚠️ **63/63 = ligantes processados** — os 7 orgânicos usam apenas tipos AD4 padrão (C, H, N, O…). Os 56 restantes contêm elementos exóticos cobertos pelo UFF.  
> **61 elementos = parâmetros UFF disponíveis** via JIT (átomos exóticos que OmniGrid parametriza para o AutoGrid4).

¹ MGLTools gera PDBQT com tipos exóticos (Pt, Ru, Au, Ge, lantanídeos…), mas o **AutoGrid4 não tem parâmetros** para esses tipos — o crash persiste.  
² Meeko processa B e Si, mas falha em Ge, As, Se ("None type").  
³ MGLTools trava (timeout 30s) em Mn, Co, Ni, Cu, Pd, Cd — loop infinito no cálculo de cargas Gasteiger.  
⁴ Meeko processa MnCl₂, mas falha em todos os outros metais (None type + NaN charges).

OmniGrid suporta **61 elementos exóticos** (via UFF) + tipos AD4 padrão — cobertura completa da tabela periódica parametrizável — vs 15 do MGLTools e ~12 do Meeko (apenas C, H, O, N, S, P, F, Cl, Br, I, B, Si, Mn).

> 📖 **Tabela completa elemento-por-elemento** com tempos, modos de falha e análise de qualidade em [`docs/benchmarks/benchmark_results.md`](docs/benchmarks/benchmark_results.md).

### Velocidade JIT

![Velocidade JIT](docs/benchmarks/02_jit_speed.png)

Geração do `AD4_parameters_temp.dat` é **sub-100ms** mesmo para todos os 61 elementos.

### Eficiência de memória

![Eficiência de memória](docs/benchmarks/03_memory_efficiency.png)

Arquivo JIT para 2 elementos usa **~60% menos memória** que a tabela periódica completa.

### Fidelidade UFF vs Rappé 1992

![Fidelidade UFF](docs/benchmarks/04_uff_fidelity.png)

Todos os 17 metais testados conferem com Rappé 1992 dentro de tolerância de arredondamento (RMSD < 1e-10).

### Throughput do pipeline

![Throughput](docs/benchmarks/05_throughput.png)

Processamento paralelo escala linearmente, atingindo **≥5 ligantes/segundo** com 8 workers (dry-run).

> **Caveat:** O throughput de **≥5 ligantes/s** reflete apenas o *dry-run* (geração de arquivos sem execução do AutoGrid4). Em modo real, o throughput é limitado pelo tempo de execução do AutoGrid4 (tipicamente 1-10 s por ligante), resultando em **~0,1-1 ligante/s** dependendo do tamanho do receptor e da complexidade do grid.

---

## Resumo numérico

| Métrica | MGLTools | Meeko | OmniGrid |
|---|---|---|---|---|
| Preparação de ligante (PDBQT)¹ | **57/63 (90%)** | 11/63 (17%) | **63/63 (100%)** |
| Parâmetros AutoGrid4 para exóticos | ❌ (só 15 tipos) | ❌ | **✅ (61 via JIT)** |
| Solução completa (PDBQT + parâmetros) | ❌ | ❌ | **✅** |
| Semimetais (Ge, As, Se, …) | ✅ (6/6)² | ❌ (3/6) | **✅ (6/6)** |
| Metais de transição | ✅ (22/28)³ | ❌ (1/28) | **✅ (28/28)** |
| Lantanídeos | ✅ (11/11)² | ❌ (0/11) | **✅ (11/11)** |
| Bloco p (Al, Sn, Pb, …) | ✅ (8/8)² | ❌ (0/8) | **✅ (8/8)** |
| Alcalinos (Li, Na, K) | ✅ (3/3)² | ❌ (0/3) | **✅ (3/3)** |
| Preparação receptor | 5-30s | N/A | **<10s** |
| Geração parâmetros (JIT) | N/A | N/A | **<100ms** |
| Throughput (dry-run) | N/A | N/A | **≥2 lig/s** |
| Memória (2 elementos) | N/A | N/A | **~50% menor** que full table |
| Fidelidade UFF vs Rappé 1992 | N/A | N/A | **exata** |

¹ MGLTools gera PDBQT com tipos exóticos corretos (Pt, Ru, Au, Ge, …), mas o **AutoGrid4 não tem parâmetros** para esses tipos — o crash no grid persiste. OmniGrid é o único que fornece ambos: PDBQT + parâmetros JIT.  
² MGLTools falha em preparar Co, Ni, Cu, Pd, Cd (trava em loop infinito no Gasteiger).  
³ As 6 falhas do MGLTools (Mn, Co, Ni, Cu, Pd, Cd) são todas por timeout (30s) — o Gasteiger charge assignment entra em loop infinito.

> **Conclusão:** OmniGrid é a **única ferramenta que oferece solução completa** — preparação de ligante (PDBQT) + parâmetros AutoGrid4 (JIT) — para todos os 61 elementos da tabela UFF. MGLTools prepara o PDBQT mas não resolve o crash do AutoGrid4. Meeko falha em ambos.

---

## Adicionando um Novo Elemento Exótico

Edite `omnigrid/atom_params.py` e adicione ao dicionário `_UFF_RAW`:

```python
'Xe': (4.404, 0.332, 1.300),  # (x1 em Å,  D1 em kcal/mol,  r_cov em Å)
```

Nenhuma outra alteração é necessária — o pipeline detecta e parametriza o novo elemento automaticamente.

---

## Testes

```bash
# Suite completa
pytest tests/ -v

# Por categoria
pytest tests/test_validation.py -v       # Validação UFF
pytest tests/test_heavy_elements.py -v   # 61 elementos + complexos
pytest tests/test_benchmarks.py -v       # Speed, coverage, memória
pytest tests/test_integration_real.py -v # Receptores reais
```

**300 testes passando** (339 total, 39 lentos opcionais) cobrindo:
- Valores UFF de 61 elementos contra Rappé 1992
- Fidelidade case-sensitive dos símbolos no `.dat`
- Alinhamento exato entre `ligand_types` e linhas `map` no `.gpf`
- Aritmética do `auto_grid_box` (centro por bounding-box, npts pares)
- Detecção de cargas pré-existentes vs zero em PDBQT
- Complexos de coordenação: W, Au, Hg, Ir, Re, Pd, Ru, etc.
- Complexos heterobimetálicos (Pt-W, Au-Hg, Ir-Re-W)
- Benchmark de velocidade, cobertura, throughput e memória

---

## Como Citar

> O OmniGrid é dual-licensed sob **MIT OR Apache-2.0** — você escolhe qual licença seguir. Isso maximiza a compatibilidade: MIT para projetos GPLv2, Apache 2.0 para proteção de patentes. Em troca, pedimos que resultados publicados com o OmniGrid incluam a citação do projeto.

```python
import omnigrid
omnigrid.cite()
```

### Formato ABNT (padrão brasileiro)

```
BEZERRA, Cleiton Augusto Correa. OmniGrid: pipeline de triagem virtual de
alta escala com parametrização just-in-time para 61 elementos via UFF.
Versão 1.0.1. 2026. Disponível em: https://github.com/cleitonaugusto/OmniGrid.
Acesso em: [data de acesso].
```

### Formato BibTeX (LaTeX / Overleaf)

```bibtex
@software{bezerra2026omnigrid,
  author    = {Bezerra, Cleiton Augusto Correa},
  title     = {{OmniGrid}: Pipeline de Triagem Virtual de Alta Escala
               com Parametrização {Just-In-Time} para 61 Elementos via {UFF}},
  year      = {2026},
  version   = {1.0.1},
  url       = {https://github.com/cleitonaugusto/OmniGrid},
  orcid     = {https://orcid.org/0009-0003-5543-8026},
  license   = {MIT},
}
```

### Formato APA 7ª edição

```
Bezerra, C. A. C. (2026). OmniGrid: Pipeline de triagem virtual de alta
escala com parametrização just-in-time para 61 elementos via UFF
(Versão 1.0.1) [Software]. GitHub. https://github.com/cleitonaugusto/OmniGrid
```

### Referências científicas complementares

Se você usar tipos atômicos exóticos, **cite também**:

> Rappé, A. K. et al. UFF, a full periodic table force field.
> *J. Am. Chem. Soc.* **1992**, *114*(25), 10024–10035.
> DOI: [10.1021/ja00051a040](https://doi.org/10.1021/ja00051a040)

---

## Autor

[![ORCID](https://img.shields.io/badge/ORCID-0009--0003--5543--8026-brightgreen?logo=orcid)](https://orcid.org/0009-0003-5543-8026)
[![License: MIT OR Apache-2.0](https://img.shields.io/badge/License-MIT%20OR%20Apache--2.0-blue)](LICENSE-MIT)

**Cleiton Augusto Correa Bezerra**  
[https://orcid.org/0009-0003-5543-8026](https://orcid.org/0009-0003-5543-8026)

---

## Licença

Dual-licensed sob **MIT OR Apache-2.0** (você escolhe).  
Consulte [LICENSE-MIT](LICENSE-MIT) e [LICENSE-APACHE](LICENSE-APACHE) para os termos completos.

Copyright © 2026 Cleiton Augusto Correa Bezerra
