Skip to main content

Rustina

Linux x86-64 molecular docking in Rust, with a command-line interface and Python bindings. Rustina combines a QuickVina2-style Monte Carlo search on Vinardo grids with native inference of GNINA's fast CNN, fused with the empirical energy to pick the final pose. It needs no GPU, no PyTorch and no network access at run time.

Component Default Alternatives
Search qvina2-active: staged QuickVina2 runs (16), no moves on torsions the scoring function cannot see qvina2-race, qvina2, vina (CPU), gpu (wgpu batched Monte Carlo)
Scoring vinardo vina, ad4 (charge-aware AutoDock 4.2)
Pose ranking GNINA fast CNN on the 8 best candidates, fused with the energy: logit(p) − 0.25 (E − median E) / max(IQR E, 1 kcal/mol) --skip-cnn (energy only)
Receptor waters kept as supplied --waters strip, --waters toggle
Affinity CNN pK of the returned pose optional ensemble of GNINA heads (--cnn-affinity-models)

Benchmarks

Pose prediction with the default setup: crystal-ligand box + 8 Å per axis (minimum 18 Å), receptors from rustina.prepare_receptor, ligands from the supplied start conformer via rustina.prepare_ligand(skip_gen3d=True), seed 1. Success is a top-1 pose within 2 Å RMSD of the crystal ligand, evaluated with PoseBusters 0.6.5 (redock, all crystal instances); "valid" also requires its physical checks. Failures, including preparation failures, count as misses. Published rows use the same inputs and the same RMSD criterion.

Set Rustina Rustina, valid GNINA 1.3 Glide SP GOLD AutoDock Vina DiffDock
Astex Diverse (85) 76.5% 74.1% 81.2%¹ 63.5%¹ 67.1%² 57.6%² 71.8%²
PoseBusters (428) 61.7% 60.3% — — 51.2%² 52.3%² 37.9%²
PoseX self-docking (718) 58.1% 56.5% 64.6%¹ 48.3%¹ — 40.0%¹ —
PoseX cross-docking (1,312 pairs) 47.6% 46.9% 53.1%¹ 37.5%¹ — 28.1%¹ —

¹ PoseX (ICLR 2026); cross-docking is the per-target average. ² PoseBusters paper data, no post-processing.

Median docking time is 2.1 s per complex on 4 CPU threads (Astex, Ryzen 5 5600X). GNINA's lead on the PoseX sets comes from its slower three-model CNN ensemble and from that benchmark's tighter box convention (crystal ligand + 4 Å per side, no minimum); Rustina's search already returns a near-native pose among its nine outputs for 79% of the PoseX self-docking cases (567/718). With a GPU, --search-mode gpu matches the CPU default's accuracy about 11× faster: median 0.17 s per complex on Astex (77.6%) and 0.18 s on PoseBusters (61.7%, as on CPU).

Virtual screening on LIT-PCBA, all 15 targets (1,096 actives, 14,993 sampled inactives): mean AUROC 0.597 with the CNN affinity and EF1% 3.4 with CNN affinity × pose probability (Vinardo: 0.548 / 1.3). Published results on the full sets are GNINA 0.609 / 4.6 and Glide SP 0.532 / 3.4 (DrugCLIP, Table 3). LIT-PCBA remains hard for every structure-based score; heavy-atom count alone gives an AUROC of 0.567.

Details, protocols and per-target results are in docs/benchmarks.md.

Build

cargo build --release --locked
python -m pip install maturin
maturin build --release --locked --out target/wheels
python -m pip install target/wheels/*.whl

The Python package supports Python 3.9+. Docking and scoring need no Python dependencies. Receptor and ligand preparation use pip install 'rustina[prep]' (RDKit, Meeko, molscrub, gemmi).

Command line

Inputs are receptor and ligand PDBQT files with polar hydrogens and partial charges.

target/release/rustina dock -r data/receptor.pdbqt -l data/ligand.pdbqt \
  --cx 0 --cy -5 --cz 0 --sx 12 --sy 16 --sz 12 --seed 42 \
  --num-modes 9 -o target/docked.pdbqt

target/release/rustina score -r data/receptor.pdbqt -l data/ligand.pdbqt \
  --scoring vinardo --cnn

--batch DIRECTORY docks a directory of ligands against one receptor prepared once and writes a summary.csv. --diagnostics-json FILE records resolved settings and every written pose's scores. dock --help and score --help list all options.

  • Reproducibility. A seed makes CPU output identical across thread counts. GPU reproducibility also depends on the adapter and driver.
  • Search budget. CPU budgets are fixed by the mode; qvina2-active and qvina2-race need at least 16 runs. --steps and --bfgs-iter apply to GPU search.
  • Waters. --waters fixed (default) keeps receptor waters, strip removes them, and toggle docks with and without them and keeps the result whose top pose has the higher CNN probability (single-ligand docking only, twice the cost). On PoseX cross-docking with ordered crystal waters the toggle gained 2.4 percentage points.
  • Inputs. Coordinates and charges must be finite, atom serials unique and branch bonds valid; multi-model PDBQT uses its first model. Ligands with pseudo-water W atoms are rejected.

Python

import rustina

receptor = rustina.prepare_receptor("protein.pdb", center=(0, -5, 0), size=(20, 20, 20))
ligand = rustina.prepare_ligand("CC(=O)Nc1ccc(O)cc1")[0]

poses = rustina.dock(
    receptor["pdbqt"], ligand["pdbqt"],
    cx=0, cy=-5, cz=0, sx=20, sy=20, sz=20, seed=42,
)
print(poses[0]["affinity"], poses[0]["cnn_score"], poses[0]["cnn_affinity"])

results = rustina.screen(receptor["pdbqt"], [ligand["pdbqt"]], cx=0, cy=-5, cz=0, sx=20, sy=20, sz=20)
  • dock returns ranked poses with the empirical affinity (kcal/mol), the CNN pose probability cnn_score and CNN affinity cnn_affinity (pK). screen shares the receptor grids across a batch and returns the top pose per ligand in input order; a failed ligand carries an error string. Paths and PDBQT text are both accepted.
  • prepare_receptor(protein, center, size) crops whole residues around the box, removes waters (keep_waters=True keeps them) and crystallisation additives, and runs Meeko. Cofactors and ions Meeko cannot template, and observed atoms Meeko deletes from incomplete residues, are kept as element-typed atoms instead of failing or silently changing the pocket; tied histidine states, unbuildable residues and untemplated modified residues (e.g. selenomethionine) are retried. The returned report records every such change.
  • prepare_ligand(smiles_or_file) enumerates protonation (pH 7.4) and tautomer states with molscrub and embeds them deterministically; skip_gen3d=True keeps supplied 3D coordinates and protonation.
  • score and score_cnn rescore an existing pose.

Optional affinity ensemble

Averaging the affinity heads of GNINA's default2018-architecture models gives small, consistent ranking gains over the fast model (congeneric series and LIT-PCBA; see the benchmarks). The models are not bundled; convert them from a GNINA checkout:

python scripts/convert_gnina_models.py /path/to/gnina/gninasrc/lib/models --affinity-pack models/
target/release/rustina dock ... --cnn-affinity-models models/

Python dock() and screen() accept cnn_affinity_models="models/". Results add cnn_affinity_ensemble and cnn_affinity_ensemble_std; pose ranking is unchanged. The cost is one fast-CNN evaluation per model and pose. See docs/models.md.

Seed poses from deep-learning docking

Poses from another docking program can join Rustina's ranking. Each seed is refined by Rustina's direct Vinardo minimisation, CNN-scored and ranked with the search's candidates by the CNN-energy fusion plus a fixed bonus for seeds (--seed-bonus, default 2 logit units); the search still runs, so a wrong seed can lose to a better Rustina pose.

target/release/rustina dock -r receptor.pdbqt -l ligand.pdbqt ... --seed-poses seeds.pdbqt

Python dock(..., seed_poses=[...], seed_bonus=2.0) accepts PDBQT texts or paths; poses refined from a seed carry seed_index. rustina.seed_pose_from_sdf(pose_sdf, ligand_pdbqt) converts any program's SDF pose of the ligand into a seed. scripts/unimol_seed_poses.py runs Uni-Mol Docking V2 (optional, not bundled; it needs its own PyTorch environment and checkpoint) and writes the seed. With Uni-Mol seeds (RMSD ≤ 2 Å, top pose):

Set Rustina Uni-Mol Rustina + Uni-Mol seed
PoseX self-docking (718; held-out test of the bonus) 57.1% 72.6% 76.2%
PoseX cross-docking (1,312 pairs) 45.1% 64.5% 65.2%
Family-disjoint cohort, 2021–2025 (132) 48.5% 53.0% 63.6%
Astex (85) 76.5% 95.3% 94.1%

The bonus was chosen on the last three sets and fixed before the PoseX self-docking outputs existed. Uni-Mol's own poses are often physically invalid (40% of its cross-docking poses pass PoseBusters); Rustina's refinement repairs them. Uni-Mol was trained on PDBbind, which contains the Astex complexes.

Models and licenses

The bundled fast CNN (GNINA 1.3.2 all_default_to_default_1_3_1, Apache-2.0) and its provenance are described in docs/models.md. Attribution is in THIRD_PARTY_NOTICES.md.

Development

screening.rs shares receptor preparation, docking, refinement and pose ranking between the CLI and Python bindings. Search lives in optimize.rs, qvina.rs and gpu/; empirical potentials in scoring.rs and ad4.rs; CNN inference in cnn.rs. AGENTS.md describes working in the repository, and docs/validation.md the protocol for evaluating changes. docs/benchmark.md documents the search and ranking diagnostics harness.

cargo fmt --all --check
cargo clippy --all-targets --locked -- -D warnings
cargo test --all-targets --locked

Install the release wheel, then run python -m unittest discover -s /absolute/path/to/rustina/python/tests -v from outside the checkout. GPU tests exercise the available adapter; an absent adapter prints a skip message but counts as passing, so hardware validation must confirm that they ran on a real GPU.

Tagged releases publish one Linux x86-64 Python wheel and a CLI archive, built in manylinux 2.28 and tested as installed packages before publishing.

Graphify is optional navigation tooling: scripts/setup_graphify.sh installs it and scripts/graphify update . --force rebuilds the code graph under scratch/graphify.

Metadata

Release files for rustina 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for rustina 0.8.0
File Interpreter ABI Platform
rustina-0.8.0-cp39-abi3-manylinux_2_28_x86_64.whl CPython 3.9 abi3 Linux glibc 2.28+ x86-64 Details

Release files / rustina-0.8.0-cp39-abi3-manylinux_2_28_x86_64.whl

Download URL rustina-0.8.0-cp39-abi3-manylinux_2_28_x86_64.whl
Size 3.4 MB
Tags CPython 3.9 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
fbd28cc4a71b6f7c1a66ae310c2e10698dde25cbe177925c255c350e10cba898
BLAKE2b-256 checksum
How to use checksums
9966b52713cc63760e45ab8ec47fea269e32f78dcfae418f2b477eb866ecdd5c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Security for rustina 0.8.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 1 file in this release has been uploaded with provenance metadata.

Attestation for rustina-0.8.0-cp39-abi3-manylinux_2_28_x86_64.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page