Metadata-Version: 2.4
Name: omnigrid
Version: 1.0.0
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
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)
[![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)
[![Version](https://img.shields.io/github/v/tag/cleitonaugusto/OmniGrid?label=version)](https://github.com/cleitonaugusto/OmniGrid/releases/tag/v1.0.0)

**Pipeline de Triagem Virtual de Alta Escala com Parametrização Just-In-Time para a Tabela Periódica Completa**

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 … via Universal Force Field (Rappé 1992) — **49 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; Gasteiger via RDKit como fallback com **logging explícito** |
| 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 |
| `--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⁻³ |

### 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 são registradas com **WARNING explícito** no log:

```
WARNING: 12 atom(s) with NaN/Inf Gasteiger charges → 0.000: Pt@idx1, Ir@idx15, ...
Use DFT/RESP charges for production accuracy.
```

---

## 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)

OmniGrid suporta **49 elementos** (tabela periódica completa via UFF), vs 15 do MGLTools e 12 do Meeko.

### Velocidade JIT

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

Geração do `AD4_parameters_temp.dat` é **sub-100ms** mesmo para todos os 49 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).

---

## Resumo numérico

| Métrica | MGLTools | Meeko | OmniGrid |
|---|---|---|---|
| Elementos suportados | 15 | 12 | **49** |
| Metais de transição | ❌ | Parcial | ✅ Todos |
| Lantanídeos/Actinídeos | ❌ | ❌ | ✅ |
| 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** |

---

## 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   # 49 elementos + complexos
pytest tests/test_benchmarks.py -v       # Speed, coverage, memória
pytest tests/test_integration_real.py -v # Receptores reais
```

**279 testes passando** cobrindo:
- Valores UFF de 49 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 a tabela periódica completa.
Versão 1.0.0. 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 a Tabela Periódica Completa},
  year      = {2026},
  version   = {1.0.0},
  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 a tabela periódica completa
(Versão 1.0.0) [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
