Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 19 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,26 +204,30 @@ Below are scripts for adding MMseqs2 MSAs and custom templates to AlphaFold3 inp

ABCFold also includes a Boltz2 utility for scoring existing complex coordinates
or fixed-receptor ligand poses without running Boltz diffusion sampling. See
[Boltz Existing-Structure Scoring](docs/boltz_existing_scoring.md) for
[Boltz Affinity Scoring](docs/boltz_affinity.md) for
confidence scoring, affinity scoring, and `--reuse_trunk` examples.

After installation, use `boltz-score-existing` directly:
This is the fast Boltz path for already-built poses: it loads Boltz2 and runs
the confidence and optional affinity heads on supplied coordinates, but skips
the expensive diffusion structure-generation loop.

After installation, use `boltz-affinity` directly:

```bash
boltz-score-existing poses.sdf --receptor receptor.pdb --affinity
boltz-affinity poses.sdf --receptor receptor.pdb --affinity
```

For a checkout managed with `uv`, either run through `uv`:

```bash
uv run boltz-score-existing poses.sdf --receptor receptor.pdb --affinity
uv run boltz-affinity poses.sdf --receptor receptor.pdb --affinity
```

or activate the project environment first:

```bash
source .venv/bin/activate
boltz-score-existing poses.sdf --receptor receptor.pdb --affinity
boltz-affinity poses.sdf --receptor receptor.pdb --affinity
```

The module form
Expand All @@ -235,26 +239,31 @@ checkouts.
ABCFold also includes a Boltz-native docking wrapper for the case where a
crystal receptor and pocket are known, but the ligand pose should be generated
from SMILES by Boltz. See
[Boltz Crystal-Pocket Docking](docs/boltz_crystal_docking.md) for crystal
[Boltz Dock](docs/boltz_dock.md) for crystal
template, pocket constraint, reference-ligand, and affinity examples.

After installation, use `boltz-dock-crystal` directly:
This mode is named `boltz-dock` because it generates a new ligand pose. It is
not as fast as `boltz-affinity`: Boltz diffusion still runs, but the receptor is
kept close to the provided crystal template and the ligand is steered into the
known pocket.

After installation, use `boltz-dock` directly:

```bash
boltz-dock-crystal receptor.pdb "CCO" --pocket_residue A:145 --affinity
boltz-dock receptor.pdb "CCO" --pocket_residue A:145 --affinity
```

For a checkout managed with `uv`, either run through `uv`:

```bash
uv run boltz-dock-crystal receptor.pdb "CCO" --pocket_residue A:145 --affinity
uv run boltz-dock receptor.pdb "CCO" --pocket_residue A:145 --affinity
```

or activate the project environment first:

```bash
source .venv/bin/activate
boltz-dock-crystal receptor.pdb "CCO" --pocket_residue A:145 --affinity
boltz-dock receptor.pdb "CCO" --pocket_residue A:145 --affinity
```

The module form
Expand Down
8 changes: 4 additions & 4 deletions abcfold/boltz/dock_crystal.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class DockingInput:

def _parse_args(argv: list[str] | None = None) -> argparse.Namespace:
parser = argparse.ArgumentParser(
prog="boltz-dock-crystal",
prog="boltz-dock",
description=(
"Dock a ligand SMILES with Boltz while constraining the protein to "
"a crystal receptor template and the ligand to a pocket."
Expand All @@ -53,7 +53,7 @@ def _parse_args(argv: list[str] | None = None) -> argparse.Namespace:
parser.add_argument(
"--out_dir",
type=Path,
default=Path("boltz_crystal_docking"),
default=Path("boltz_dock"),
help="Directory for the generated YAML and Boltz outputs.",
)
parser.add_argument(
Expand Down Expand Up @@ -530,7 +530,7 @@ def prepare_crystal_docking_input(args: argparse.Namespace) -> DockingInput:
"--reference_ligand_chain."
)

yaml_path = out_dir / "boltz_crystal_dock.yaml"
yaml_path = out_dir / "boltz_dock.yaml"
yaml_text = _render_yaml(
receptor,
protein_chains,
Expand All @@ -542,7 +542,7 @@ def prepare_crystal_docking_input(args: argparse.Namespace) -> DockingInput:
yaml_path.write_text(yaml_text)

command = generate_boltz_crystal_dock_command(yaml_path, out_dir, args)
(out_dir / "boltz_crystal_dock_command.json").write_text(
(out_dir / "boltz_dock_command.json").write_text(
json.dumps(command, indent=2) + "\n"
)
return DockingInput(yaml_path=yaml_path, command=command, contacts=contacts)
Expand Down
9 changes: 6 additions & 3 deletions abcfold/boltz/score_existing.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@ def _safe_id(path: Path) -> str:

def _parse_args(argv: list[str] | None = None) -> argparse.Namespace:
parser = argparse.ArgumentParser(
prog="boltz-score-existing",
description="Score existing PDB/mmCIF complexes with Boltz2 confidence.",
prog="boltz-affinity",
description=(
"Score existing PDB/mmCIF complexes or fixed ligand poses with "
"Boltz2 confidence and optional affinity heads."
),
)
parser.add_argument(
"structures",
Expand All @@ -80,7 +83,7 @@ def _parse_args(argv: list[str] | None = None) -> argparse.Namespace:
parser.add_argument(
"--out_dir",
type=Path,
default=Path("boltz_existing_scores"),
default=Path("boltz_affinity_scores"),
help="Directory for confidence JSON/NPZ outputs.",
)
parser.add_argument(
Expand Down
43 changes: 24 additions & 19 deletions docs/boltz_existing_scoring.md → docs/boltz_affinity.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Boltz Existing-Structure Scoring
# Boltz Affinity Scoring

`abcfold.boltz.score_existing` scores already-built complexes with Boltz2
without running Boltz diffusion sampling. Use it when protein or complex
coordinates already exist and you want Boltz2 confidence and, optionally,
Boltz2 affinity estimates for those coordinates.
`boltz-affinity` scores already-built complexes with Boltz2 without running
Boltz diffusion sampling. Use it when protein or complex coordinates already
exist and you want Boltz2 confidence and, optionally, Boltz2 affinity estimates
for those coordinates.

This is a scoring utility, not a structure-generation or local-minimization
tool. It does not move the protein or ligand.
Expand All @@ -13,20 +13,20 @@ tool. It does not move the protein or ligand.
Installed ABCFold environments expose this as:

```bash
boltz-score-existing --help
boltz-affinity --help
```

For a local checkout managed with `uv`, use either:

```bash
uv run boltz-score-existing --help
uv run boltz-affinity --help
```

or activate the environment before using the command directly:

```bash
source .venv/bin/activate
boltz-score-existing --help
boltz-affinity --help
```

The development-module equivalent is:
Expand Down Expand Up @@ -68,9 +68,9 @@ Use this mode when each input file already contains the protein and ligand
chains in one `.pdb`, `.cif`, or `.mmcif` file.

```bash
boltz-score-existing \
boltz-affinity \
complex_1.cif complex_2.cif \
--out_dir boltz_existing_scores \
--out_dir boltz_affinity_scores \
--cache ~/.boltz \
--device cuda \
--no_download
Expand All @@ -79,9 +79,9 @@ boltz-score-existing \
For affinity estimates on the same coordinates:

```bash
boltz-score-existing \
boltz-affinity \
complex_1.cif complex_2.cif \
--out_dir boltz_existing_scores_affinity \
--out_dir boltz_affinity_scores \
--cache ~/.boltz \
--device cuda \
--no_download \
Expand All @@ -98,7 +98,7 @@ poses are stored as SDF files. This is the format used by DEKOIS2/Matcha-style
and HEDGEHOG-style pose scoring.

```bash
boltz-score-existing \
boltz-affinity \
poses.sdf \
--receptor receptor.pdb \
--out_dir boltz_pose_scores \
Expand All @@ -110,7 +110,7 @@ boltz-score-existing \
For confidence plus affinity:

```bash
boltz-score-existing \
boltz-affinity \
poses.sdf \
--receptor receptor.pdb \
--out_dir boltz_pose_scores_affinity \
Expand All @@ -132,7 +132,7 @@ topology, for example multiple poses of the same ligand against the same
protein.

```bash
boltz-score-existing \
boltz-affinity \
same_ligand_poses.sdf \
--receptor receptor.pdb \
--out_dir boltz_pose_scores_reuse \
Expand Down Expand Up @@ -161,10 +161,15 @@ The output directory contains:

## Runtime Notes

The command avoids the expensive Boltz diffusion sampling path, so it is faster
than full Boltz structure prediction. It still loads the Boltz2 checkpoint and
runs the trunk, so the first score is not instantaneous. On GPU, scoring
additional poses in the same process is much cheaper than the cold start.
The command avoids the expensive Boltz diffusion sampling path, so it is much
faster than full Boltz structure prediction. It still loads the Boltz2
checkpoint and runs the trunk, so the first score is not instantaneous. On GPU,
scoring additional poses in the same process is much cheaper than the cold
start, especially with `--reuse_trunk` for same-topology pose batches.

In practice, this mode should be treated as Boltz scoring rather than Boltz
prediction: it can rank or annotate already generated poses, but it will not
repair geometry or move the ligand.

The utility currently sets protein MSAs to `empty`, so proteins are scored in
single-sequence mode. That is useful for fast pose screening, but confidence and
Expand Down
40 changes: 22 additions & 18 deletions docs/boltz_crystal_docking.md → docs/boltz_dock.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Boltz Crystal-Pocket Docking
# Boltz Dock

`abcfold.boltz.dock_crystal` runs Boltz structure generation with a fixed
crystal receptor as a template, a ligand SMILES, and pocket constraints. Use it
when you know the receptor structure and pocket, but want Boltz to generate the
ligand pose instead of only scoring an existing pose.
`boltz-dock` runs Boltz structure generation with a fixed crystal receptor as a
template, a ligand SMILES, and pocket constraints. Use it when you know the
receptor structure and pocket, but want Boltz to generate the ligand pose
instead of only scoring an existing pose.

This is a Boltz-native docking/co-folding mode. It is not a classical force
field minimizer: Boltz still runs diffusion sampling, but the protein is guided
Expand All @@ -14,20 +14,20 @@ toward the crystal template and the ligand is guided into the pocket.
Installed ABCFold environments expose this as:

```bash
boltz-dock-crystal --help
boltz-dock --help
```

For a local checkout managed with `uv`, use either:

```bash
uv run boltz-dock-crystal --help
uv run boltz-dock --help
```

or activate the environment before using the command directly:

```bash
source .venv/bin/activate
boltz-dock-crystal --help
boltz-dock --help
```

The development-module equivalent is:
Expand All @@ -39,14 +39,14 @@ python -m abcfold.boltz.dock_crystal --help
## Explicit Pocket Residues

```bash
boltz-dock-crystal \
boltz-dock \
crystal_receptor.pdb \
"CCOc1ccc(...)" \
--protein_chain A \
--pocket_residue A:145 \
--pocket_residue A:146 \
--pocket_residue A:189 \
--out_dir boltz_crystal_dock \
--out_dir boltz_dock \
--affinity
```

Expand All @@ -61,13 +61,13 @@ If the receptor PDB still contains a reference ligand chain, the wrapper can
infer pocket residues by distance:

```bash
boltz-dock-crystal \
boltz-dock \
crystal_complex.pdb \
"CCOc1ccc(...)" \
--protein_chain A \
--reference_ligand_chain L \
--pocket_cutoff 6.0 \
--out_dir boltz_crystal_dock \
--out_dir boltz_dock \
--affinity
```

Expand All @@ -88,7 +88,7 @@ These settings keep the protein close to the crystal receptor and steer the
ligand into the pocket. They can be relaxed:

```bash
boltz-dock-crystal \
boltz-dock \
crystal_receptor.pdb \
"CCOc1ccc(...)" \
--pocket_residue A:145 \
Expand All @@ -102,8 +102,12 @@ less constrained.
## Accuracy and Runtime

This mode runs Boltz diffusion, so it is much slower than
`abcfold.boltz.score_existing`, which only scores supplied coordinates. The
default docking settings use:
`boltz-affinity`, which only scores supplied coordinates. Compared with a fully
unconstrained Boltz run, `boltz-dock` saves setup work by reusing the provided
crystal receptor, writing `msa: empty` unless `--use_msa_server` is requested,
and constraining the search to the known pocket. It is still a generative Boltz
run, so runtime is controlled mainly by diffusion samples, recycling steps, and
sampling steps. The default docking settings use:

- `--diffusion_samples 25`
- `--recycling_steps 10`
Expand All @@ -113,7 +117,7 @@ default docking settings use:
For a quick dry run that only writes the Boltz YAML and command:

```bash
boltz-dock-crystal \
boltz-dock \
crystal_receptor.pdb \
"CCOc1ccc(...)" \
--pocket_residue A:145 \
Expand All @@ -122,8 +126,8 @@ boltz-dock-crystal \

The output directory contains:

- `boltz_crystal_dock.yaml`
- `boltz_crystal_dock_command.json`
- `boltz_dock.yaml`
- `boltz_dock_command.json`
- Boltz prediction outputs when `--dry_run` is not used

Use `--use_msa_server` to let Boltz fetch MSAs. Without it, the wrapper writes
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ abcfold = ["data/config.ini"]

[project.scripts]
abcfold = "abcfold.abcfold:main"
boltz-score-existing = "abcfold.boltz.score_existing:main"
boltz-dock-crystal = "abcfold.boltz.dock_crystal:main"
boltz-affinity = "abcfold.boltz.score_existing:main"
boltz-dock = "abcfold.boltz.dock_crystal:main"
mmseqs2msa = "abcfold.scripts.add_mmseqs_msa:main"
custom_templates = "abcfold.scripts.add_custom_template:main"
ipsae = "abcfold.scripts.ipsae:main"
Expand Down
4 changes: 2 additions & 2 deletions tests/test_boltz_entrypoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ def test_boltz_console_entrypoints_are_registered():
for entry_point in entry_points(group="console_scripts")
}

assert scripts["boltz-score-existing"] == "abcfold.boltz.score_existing:main"
assert scripts["boltz-dock-crystal"] == "abcfold.boltz.dock_crystal:main"
assert scripts["boltz-affinity"] == "abcfold.boltz.score_existing:main"
assert scripts["boltz-dock"] == "abcfold.boltz.dock_crystal:main"
Loading