caddforge-fep 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- caddforge_fep-0.7.0/.github/workflows/release.yml +95 -0
- caddforge_fep-0.7.0/.gitignore +25 -0
- caddforge_fep-0.7.0/LICENSE +21 -0
- caddforge_fep-0.7.0/PKG-INFO +455 -0
- caddforge_fep-0.7.0/README.md +438 -0
- caddforge_fep-0.7.0/pyproject.toml +43 -0
- caddforge_fep-0.7.0/scripts/check_release.py +98 -0
- caddforge_fep-0.7.0/scripts/ci_tests.json +8 -0
- caddforge_fep-0.7.0/scripts/run_ci_tests.py +84 -0
- caddforge_fep-0.7.0/src/cadd_fep/__init__.py +5 -0
- caddforge_fep-0.7.0/src/cadd_fep/gui_extension.py +1797 -0
- caddforge_fep-0.7.0/src/cadd_fep/gui_static/common.js +53 -0
- caddforge_fep-0.7.0/src/cadd_fep/gui_static/fep.js +12 -0
- caddforge_fep-0.7.0/src/cadd_fep/gui_static/openfe-abfe-panel.js +766 -0
- caddforge_fep-0.7.0/src/cadd_fep/gui_static/openfe-rbfe-septop-panel.js +595 -0
- caddforge_fep-0.7.0/src/cadd_fep/gui_static/rbfe-network.js +1265 -0
- caddforge_fep-0.7.0/src/cadd_fep/openfe_abfe/__init__.py +5 -0
- caddforge_fep-0.7.0/src/cadd_fep/openfe_abfe/defaults.py +118 -0
- caddforge_fep-0.7.0/src/cadd_fep/openfe_abfe/workflow.py +634 -0
- caddforge_fep-0.7.0/src/cadd_fep/openfe_rbfe_septop/__init__.py +5 -0
- caddforge_fep-0.7.0/src/cadd_fep/openfe_rbfe_septop/workflow.py +1672 -0
- caddforge_fep-0.7.0/src/cadd_fep/rbfe/__init__.py +29 -0
- caddforge_fep-0.7.0/src/cadd_fep/rbfe/bundle.py +200 -0
- caddforge_fep-0.7.0/src/cadd_fep/rbfe/network.py +875 -0
- caddforge_fep-0.7.0/src/cadd_fep/tool.py +68 -0
- caddforge_fep-0.7.0/tests/test_gui_extension.py +371 -0
- caddforge_fep-0.7.0/tests/test_openfe_abfe_defaults.py +230 -0
- caddforge_fep-0.7.0/tests/test_openfe_abfe_workflow.py +431 -0
- caddforge_fep-0.7.0/tests/test_openfe_rbfe_septop_workflow.py +806 -0
- caddforge_fep-0.7.0/tests/test_placeholder_fep.py +2 -0
- caddforge_fep-0.7.0/tests/test_rbfe_network_planner.py +217 -0
- caddforge_fep-0.7.0/tests/test_release_metadata.py +77 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
name: CI and PyPI release
|
|
2
|
+
'on':
|
|
3
|
+
push:
|
|
4
|
+
branches:
|
|
5
|
+
- '**'
|
|
6
|
+
tags:
|
|
7
|
+
- v*
|
|
8
|
+
pull_request: null
|
|
9
|
+
workflow_dispatch: null
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
jobs:
|
|
13
|
+
build:
|
|
14
|
+
name: Build and validate distributions
|
|
15
|
+
runs-on: ubuntu-24.04
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v7.0.1
|
|
18
|
+
with:
|
|
19
|
+
fetch-depth: 0
|
|
20
|
+
persist-credentials: false
|
|
21
|
+
- uses: actions/setup-python@v7.0.0
|
|
22
|
+
with:
|
|
23
|
+
python-version: '3.12'
|
|
24
|
+
- name: Install build tools
|
|
25
|
+
run: python -m pip --isolated install --index-url https://pypi.org/simple --upgrade build twine packaging
|
|
26
|
+
- name: Build wheel from source distribution
|
|
27
|
+
run: python -m build
|
|
28
|
+
- name: Validate package metadata
|
|
29
|
+
run: python -m twine check --strict dist/*
|
|
30
|
+
- name: Check distribution identity and release version
|
|
31
|
+
env:
|
|
32
|
+
IS_RELEASE: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
|
|
33
|
+
RELEASE_TAG: ${{ github.ref_name }}
|
|
34
|
+
run: python scripts/check_release.py .
|
|
35
|
+
- uses: actions/upload-artifact@v7.0.2
|
|
36
|
+
with:
|
|
37
|
+
name: distributions
|
|
38
|
+
path: dist/*
|
|
39
|
+
if-no-files-found: error
|
|
40
|
+
test:
|
|
41
|
+
name: Test wheel (Python ${{ matrix.python }})
|
|
42
|
+
needs: build
|
|
43
|
+
runs-on: ubuntu-24.04
|
|
44
|
+
strategy:
|
|
45
|
+
fail-fast: false
|
|
46
|
+
matrix:
|
|
47
|
+
python:
|
|
48
|
+
- '3.10'
|
|
49
|
+
- '3.12'
|
|
50
|
+
steps:
|
|
51
|
+
- uses: actions/checkout@v7.0.1
|
|
52
|
+
with:
|
|
53
|
+
persist-credentials: false
|
|
54
|
+
- uses: actions/setup-python@v7.0.0
|
|
55
|
+
with:
|
|
56
|
+
python-version: ${{ matrix.python }}
|
|
57
|
+
- uses: actions/download-artifact@v8.0.1
|
|
58
|
+
with:
|
|
59
|
+
name: distributions
|
|
60
|
+
path: dist
|
|
61
|
+
- name: Install built wheel and test dependencies
|
|
62
|
+
shell: bash
|
|
63
|
+
run: |-
|
|
64
|
+
wheels=(dist/*.whl)
|
|
65
|
+
python -m pip --isolated install --index-url https://pypi.org/simple "${wheels[0]}[gui]"
|
|
66
|
+
python -m pip --isolated install --index-url https://pypi.org/simple pytest packaging 'tomli; python_version < "3.11"' 'httpx'
|
|
67
|
+
- name: Test installed wheel outside the checkout
|
|
68
|
+
env:
|
|
69
|
+
MPLBACKEND: Agg
|
|
70
|
+
OMP_NUM_THREADS: '1'
|
|
71
|
+
OPENBLAS_NUM_THREADS: '1'
|
|
72
|
+
run: python scripts/run_ci_tests.py
|
|
73
|
+
- name: Check installed dependencies
|
|
74
|
+
run: python -m pip check
|
|
75
|
+
publish:
|
|
76
|
+
name: Publish to PyPI
|
|
77
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
78
|
+
needs:
|
|
79
|
+
- build
|
|
80
|
+
- test
|
|
81
|
+
runs-on: ubuntu-24.04
|
|
82
|
+
environment:
|
|
83
|
+
name: pypi
|
|
84
|
+
url: https://pypi.org/project/caddforge-fep/
|
|
85
|
+
permissions:
|
|
86
|
+
id-token: write
|
|
87
|
+
concurrency:
|
|
88
|
+
group: pypi-${{ github.ref }}
|
|
89
|
+
cancel-in-progress: false
|
|
90
|
+
steps:
|
|
91
|
+
- uses: actions/download-artifact@v8.0.1
|
|
92
|
+
with:
|
|
93
|
+
name: distributions
|
|
94
|
+
path: dist
|
|
95
|
+
- uses: pypa/gh-action-pypi-publish@v1.14.2
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Byte-compiled / cache
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.so
|
|
5
|
+
|
|
6
|
+
# Environments
|
|
7
|
+
.venv/
|
|
8
|
+
.env
|
|
9
|
+
|
|
10
|
+
# Packaging / build
|
|
11
|
+
build/
|
|
12
|
+
dist/
|
|
13
|
+
*.egg-info/
|
|
14
|
+
.hatch/
|
|
15
|
+
|
|
16
|
+
# Tooling caches
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.ruff_cache/
|
|
19
|
+
.mypy_cache/
|
|
20
|
+
.coverage
|
|
21
|
+
runs/
|
|
22
|
+
|
|
23
|
+
# IDE/editor
|
|
24
|
+
.idea/
|
|
25
|
+
.vscode/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 The CADDForge Authors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: caddforge-fep
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: Free energy perturbation workflows for the CADDForge toolbox.
|
|
5
|
+
Author-email: Manuel Sellner <manuel.sellner@idorsia.com>, Christoph Sager <christoph.sager@idorsia.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Requires-Dist: caddforge-core>=0.21.0
|
|
10
|
+
Requires-Dist: pdbfixer>=1.9
|
|
11
|
+
Requires-Dist: rdkit>=2024.03.1
|
|
12
|
+
Provides-Extra: gui
|
|
13
|
+
Requires-Dist: caddforge-gui>=0.2.0; extra == 'gui'
|
|
14
|
+
Requires-Dist: fastapi>=0.110; extra == 'gui'
|
|
15
|
+
Requires-Dist: python-multipart>=0.0.21; extra == 'gui'
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# CADDForge FEP Plugin
|
|
19
|
+
|
|
20
|
+
Install this plugin with `python -m pip install caddforge-fep`. It depends directly
|
|
21
|
+
on `caddforge-core>=0.21.0`; Python imports and CLI commands still use `caddforge`.
|
|
22
|
+
For the complete public toolbox, including user-facing extras, install
|
|
23
|
+
`python -m pip install caddforge`. When migrating an existing environment, uninstall
|
|
24
|
+
the former `caddforge` core distribution before installing renamed core and updated plugins.
|
|
25
|
+
|
|
26
|
+
`caddforge-fep` provides free energy perturbation workflows as plugins for the CADDForge framework.
|
|
27
|
+
|
|
28
|
+
## Optional GUI dependencies
|
|
29
|
+
The core FEP workflows can be installed without GUI dependencies.
|
|
30
|
+
|
|
31
|
+
If you want to use the FEP GUI extension, install the optional GUI extra:
|
|
32
|
+
```bash
|
|
33
|
+
pip install "caddforge-fep[gui]"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Installation notes
|
|
37
|
+
- It is recommended to install `openfe` and the rest of the scientific runtime stack with `conda`.
|
|
38
|
+
- To avoid environment conflicts, install all required `conda` packages first, and only then install CADDForge packages with `pip`.
|
|
39
|
+
|
|
40
|
+
Typical order:
|
|
41
|
+
```bash
|
|
42
|
+
conda create -n caddforge-fep python=3.10
|
|
43
|
+
conda activate caddforge-fep
|
|
44
|
+
conda install -c conda-forge openfe openff-toolkit rdkit pdbfixer
|
|
45
|
+
pip install caddforge-core caddforge-fep
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Notes:
|
|
49
|
+
- The current GUI extension covers both `openfe-abfe` and `openfe-rbfe-septop`.
|
|
50
|
+
- The `openfe-rbfe-septop` GUI includes an interactive ligand-network canvas with draggable nodes, manual edge creation/removal, edge rescoring, and network save/load support.
|
|
51
|
+
|
|
52
|
+
## Implemented Tools
|
|
53
|
+
- [`openfe-abfe`](#tool-openfe-abfe)
|
|
54
|
+
- [`openfe-rbfe-septop`](#tool-openfe-rbfe-septop)
|
|
55
|
+
|
|
56
|
+
## Tool: `openfe-abfe`
|
|
57
|
+
|
|
58
|
+
### What it does
|
|
59
|
+
The `openfe-abfe` tool prepares, and optionally runs, OpenFE absolute binding free energy calculations through the standard CADDForge workflow/job interface. It supports:
|
|
60
|
+
- ligand input from a multi-record SDF with ligand selection by index
|
|
61
|
+
- protein input from PDB
|
|
62
|
+
- optional protein cleanup with `pdbfixer`
|
|
63
|
+
- OpenFE settings overrides through dot-path config entries
|
|
64
|
+
- local execution or Slurm execution with scratch work under `SLURM_TMPDIR`
|
|
65
|
+
- standardized CADDForge outputs (`result_record.json`, transformation JSON, OpenFE logs)
|
|
66
|
+
|
|
67
|
+
### External dependencies
|
|
68
|
+
These tools and libraries are required at runtime and are not installed automatically by this Python package:
|
|
69
|
+
- `openfe`
|
|
70
|
+
- `openff`
|
|
71
|
+
- `rdkit`
|
|
72
|
+
- `pdbfixer`
|
|
73
|
+
|
|
74
|
+
Installation note:
|
|
75
|
+
- `openfe` is best installed with `conda`.
|
|
76
|
+
- Install the `conda` packages first, then install `caddforge-core` / `caddforge-fep` with `pip`.
|
|
77
|
+
|
|
78
|
+
### CLI usage
|
|
79
|
+
```bash
|
|
80
|
+
caddforge run fep openfe-abfe --config abfe.yaml
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Python API usage
|
|
84
|
+
```python
|
|
85
|
+
from caddforge.core.execution import load_result_for_job, submit_workflow
|
|
86
|
+
from caddforge.plugins import get_tool
|
|
87
|
+
|
|
88
|
+
spec = get_tool("fep", "openfe-abfe")
|
|
89
|
+
cfg = spec.config_cls(
|
|
90
|
+
ligand_sdf="ligand_neutral.sdf",
|
|
91
|
+
protein_pdb="protein_fixed.pdb",
|
|
92
|
+
ligand_index=0,
|
|
93
|
+
backend="local", # or "slurm"
|
|
94
|
+
run_quickrun=True,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
workflow = spec.workflow_cls(cfg)
|
|
98
|
+
job = submit_workflow(workflow, cfg, backend_name=cfg.backend)
|
|
99
|
+
result = load_result_for_job(job)
|
|
100
|
+
if result is not None:
|
|
101
|
+
print(result.status.value, result.metrics)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Example config
|
|
105
|
+
```yaml
|
|
106
|
+
ligand_sdf: ligand_neutral.sdf
|
|
107
|
+
protein_pdb: protein_fixed.pdb
|
|
108
|
+
ligand_index: 0
|
|
109
|
+
fix_protein_pdb: false
|
|
110
|
+
partial_charge_method: am1bcc
|
|
111
|
+
off_toolkit_backend: ambertools
|
|
112
|
+
host_min_distance_nm: 0.5
|
|
113
|
+
host_max_distance_nm: 1.5
|
|
114
|
+
protocol_repeats: 1
|
|
115
|
+
settings_overrides:
|
|
116
|
+
complex_simulation_settings.real_time_analysis_interval: 10 picosecond
|
|
117
|
+
complex_equil_simulation_settings.equilibration_length: 0.2 nanosecond
|
|
118
|
+
complex_equil_simulation_settings.production_length: 0.5 nanosecond
|
|
119
|
+
complex_equil_simulation_settings.equilibration_length_nvt: 0.10 nanosecond
|
|
120
|
+
complex_simulation_settings.equilibration_length: 0.2 nanosecond
|
|
121
|
+
complex_simulation_settings.production_length: 2.0 nanosecond
|
|
122
|
+
complex_simulation_settings.n_replicas: 68
|
|
123
|
+
solvent_equil_simulation_settings.equilibration_length: 0.1 nanosecond
|
|
124
|
+
solvent_equil_simulation_settings.production_length: 0.5 nanosecond
|
|
125
|
+
solvent_equil_simulation_settings.equilibration_length_nvt: 0.05 nanosecond
|
|
126
|
+
solvent_simulation_settings.equilibration_length: 0.1 nanosecond
|
|
127
|
+
solvent_simulation_settings.production_length: 1 nanosecond
|
|
128
|
+
solvent_simulation_settings.real_time_analysis_interval: 10 picosecond
|
|
129
|
+
solvent_simulation_settings.n_replicas: 60
|
|
130
|
+
engine_settings.compute_platform: CUDA
|
|
131
|
+
complex_lambda_settings.lambda_elec:
|
|
132
|
+
[0, 0.05, 0.1, 0.14, 0.19, 0.24, 0.29, 0.33, 0.38, 0.43, 0.48, 0.52, 0.57, 0.62, 0.67, 0.71,
|
|
133
|
+
0.76, 0.81, 0.86, 0.9, 0.95, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
134
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
|
135
|
+
complex_lambda_settings.lambda_vdw:
|
|
136
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.06, 0.12, 0.18, 0.24,
|
|
137
|
+
0.28, 0.32, 0.36, 0.4, 0.44, 0.48, 0.52, 0.56, 0.6, 0.62, 0.64, 0.66, 0.68, 0.69, 0.7, 0.71,
|
|
138
|
+
0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.8, 0.81, 0.82, 0.83, 0.83, 0.84, 0.85,
|
|
139
|
+
0.86, 0.87, 0.88, 0.89, 0.9, 0.91, 0.92, 0.94, 0.96, 0.98, 1]
|
|
140
|
+
complex_lambda_settings.lambda_restraints:
|
|
141
|
+
[0, 0, 0, 0.01, 0.01, 0.02, 0.03, 0.04, 0.06, 0.07, 0.09, 0.11, 0.13, 0.16, 0.18, 0.21, 0.24,
|
|
142
|
+
0.27, 0.3, 0.33, 0.37, 0.4, 0.44, 0.49, 0.53, 0.57, 0.62, 0.67, 0.72, 0.77, 0.83, 0.88,
|
|
143
|
+
0.94, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
144
|
+
1, 1, 1, 1, 1, 1, 1]
|
|
145
|
+
solvent_lambda_settings.lambda_elec:
|
|
146
|
+
[0, 0.01, 0.02, 0.03, 0.04, 0.07, 0.09, 0.11, 0.13, 0.15, 0.17, 0.22, 0.26, 0.3, 0.35, 0.39,
|
|
147
|
+
0.43, 0.48, 0.52, 0.57, 0.61, 0.65, 0.7, 0.74, 0.78, 0.83, 0.87, 0.91, 0.96, 1, 1, 1, 1,
|
|
148
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
|
149
|
+
solvent_lambda_settings.lambda_vdw:
|
|
150
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
151
|
+
0.1, 0.18, 0.26, 0.32, 0.38, 0.42, 0.46, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68, 0.71,
|
|
152
|
+
0.74, 0.76, 0.78, 0.8, 0.81, 0.83, 0.84, 0.86, 0.88, 0.9, 0.92, 0.94, 0.96, 0.98, 1]
|
|
153
|
+
solvent_lambda_settings.lambda_restraints:
|
|
154
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
155
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
156
|
+
run_quickrun: true
|
|
157
|
+
quickrun_extra_args: []
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Tool-specific config options
|
|
161
|
+
|
|
162
|
+
#### Required / primary inputs
|
|
163
|
+
- `ligand_sdf` (`Path`): SDF containing the ligand set.
|
|
164
|
+
- `protein_pdb` (`Path`): Protein receptor PDB.
|
|
165
|
+
- `ligand_index` (`int`, default `0`): SDF record index to use for the ABFE calculation.
|
|
166
|
+
|
|
167
|
+
#### Optional preparation options
|
|
168
|
+
- `fix_protein_pdb` (`bool`, default `false`): If `true`, run `pdbfixer` before OpenFE setup.
|
|
169
|
+
- `partial_charge_method` (`str`, default `"am1bcc"`): Partial charge method for OpenFF charge generation.
|
|
170
|
+
- `off_toolkit_backend` (`str`, default `"ambertools"`): OpenFF backend used for charge assignment.
|
|
171
|
+
- `charge_n_conformers` (`int`, default `1`): Number of conformers for charge generation.
|
|
172
|
+
- `charge_nagl_model` (`str | None`): Optional NAGL model name.
|
|
173
|
+
- `charge_processors` (`int`, default `1`): Number of processors for charge assignment.
|
|
174
|
+
- `overwrite_charges` (`bool`, default `false`): Overwrite existing molecule charges.
|
|
175
|
+
- `require_neutral_ligand` (`bool`, default `true`): Enforce the OpenFE ABFE neutral-ligand limitation.
|
|
176
|
+
|
|
177
|
+
#### Protocol options
|
|
178
|
+
- `host_min_distance_nm` (`float`, default `0.5`): Minimum Boresch restraint host distance in nm.
|
|
179
|
+
- `host_max_distance_nm` (`float`, default `1.5`): Maximum Boresch restraint host distance in nm.
|
|
180
|
+
- `protocol_repeats` (`int | None`, default `1`): Number of independent protocol repeats per leg. Explicit `null` retains OpenFE's repeat default.
|
|
181
|
+
- `settings_overrides` (`dict[str, Any]`): The ABFE defaults below, merged with explicit dot-path overrides. Omitted, empty, or partial dictionaries retain all unspecified defaults.
|
|
182
|
+
|
|
183
|
+
| Settings group | NVT equilibration | Equilibration | Production | Lambda replicas | Analysis interval |
|
|
184
|
+
| --- | --- | --- | --- | --- | --- |
|
|
185
|
+
| Complex pre-equilibration | 0.10 ns | 0.2 ns | 0.5 ns | — | — |
|
|
186
|
+
| Complex alchemical simulation | — | 0.2 ns | 2.0 ns | 68 | 10 ps |
|
|
187
|
+
| Solvent pre-equilibration | 0.05 ns | 0.1 ns | 0.5 ns | — | — |
|
|
188
|
+
| Solvent alchemical simulation | — | 0.1 ns | 1 ns | 60 | 10 ps |
|
|
189
|
+
|
|
190
|
+
The default compute platform is `CUDA`. Each complex lambda array has 68 entries;
|
|
191
|
+
each solvent lambda array has 60 entries, with solvent restraints zero throughout.
|
|
192
|
+
`n_replicas` counts lambda replicas within a leg; it is distinct from independent
|
|
193
|
+
`protocol_repeats`. Keep each leg's three lambda-array lengths consistent with its
|
|
194
|
+
replica count when overriding the schedules.
|
|
195
|
+
|
|
196
|
+
The CLI, Python API, and GUI use the same defaults. Explicit
|
|
197
|
+
`settings_overrides.protocol_repeats` takes precedence over the top-level
|
|
198
|
+
`protocol_repeats`. Generated examples specify repeats only at the top level.
|
|
199
|
+
|
|
200
|
+
`settings_overrides` accepts plain values or strings of the form `<number> <unit>`, for example:
|
|
201
|
+
- `5 nanosecond`
|
|
202
|
+
- `0.15 molar`
|
|
203
|
+
|
|
204
|
+
#### Execution / output options
|
|
205
|
+
- `transformation_dir_name` (`str`, default `"abfe_json"`): Directory name used for OpenFE transformation JSON files.
|
|
206
|
+
- `run_quickrun` (`bool`, default `true`): If `true`, execute `openfe quickrun`.
|
|
207
|
+
- `quickrun_workdir` (`Path | None`): Optional OpenFE working directory.
|
|
208
|
+
- `quickrun_output` (`Path | None`): Optional output JSON path for `openfe quickrun`.
|
|
209
|
+
- `quickrun_extra_args` (`list[str]`, default `[]`): Extra raw arguments appended to `openfe quickrun`.
|
|
210
|
+
|
|
211
|
+
### Outputs
|
|
212
|
+
For each run, artifacts are written under `runs/<date>/<job-id>/`:
|
|
213
|
+
- `<transformation_dir_name>/`: OpenFE transformation JSON
|
|
214
|
+
- `results/openfe_results.json`: OpenFE quickrun output JSON
|
|
215
|
+
- `results/openfe_stdout.log`: OpenFE stdout
|
|
216
|
+
- `results/openfe_stderr.log`: OpenFE stderr
|
|
217
|
+
- `results/result_record.json`: standardized CADDForge `Result`
|
|
218
|
+
- `openfe_run/`: OpenFE working directory
|
|
219
|
+
- `stdout.log` / `stderr.log`: CADDForge workflow logs
|
|
220
|
+
|
|
221
|
+
## Tool: `openfe-rbfe-septop`
|
|
222
|
+
|
|
223
|
+
### What it does
|
|
224
|
+
The `openfe-rbfe-septop` tool plans, prepares, and optionally runs separate-topology RBFE calculations with OpenFE SepTop. It supports:
|
|
225
|
+
- input as one shared protein plus many ligand poses, or as many aligned protein-plus-ligand input pairs
|
|
226
|
+
- explicit project-compound selection via config
|
|
227
|
+
- automatic ligand-network generation with:
|
|
228
|
+
- charge bucketing
|
|
229
|
+
- compatibility grouping based on similarity and protein-clash filtering
|
|
230
|
+
- project-centered radial maps
|
|
231
|
+
- local orphan-cluster hubs
|
|
232
|
+
- optional diagnostic cycle edges
|
|
233
|
+
- extension of an existing persisted ligand network without removing existing edges
|
|
234
|
+
- portable self-contained network bundles with bundled proteins plus reusable completed edge records
|
|
235
|
+
- bundle refresh mode to rebuild a fresh portable bundle from an existing finished campaign
|
|
236
|
+
- persisted ligand-network JSON plus GraphML export
|
|
237
|
+
- local sequential execution or Slurm fan-out submission with one child job per transformation edge
|
|
238
|
+
- an interactive GUI workflow with network visualization and manual editing
|
|
239
|
+
|
|
240
|
+
### External dependencies
|
|
241
|
+
These tools and libraries are required at runtime and are not installed automatically by this Python package:
|
|
242
|
+
- `openfe`
|
|
243
|
+
- `openff`
|
|
244
|
+
- `rdkit`
|
|
245
|
+
|
|
246
|
+
Notes:
|
|
247
|
+
- This workflow assumes ligand poses are already meaningful and aligned in the protein frame.
|
|
248
|
+
- For Slurm, the campaign job plans/prepares the network once and then submits one child job per transformation so edges can run independently in parallel.
|
|
249
|
+
- `openfe` is best installed with `conda`, and all `conda` dependencies should be installed before adding the CADDForge packages with `pip`.
|
|
250
|
+
|
|
251
|
+
### CLI usage
|
|
252
|
+
```bash
|
|
253
|
+
caddforge run fep openfe-rbfe-septop --config rbfe_septop.yaml
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Refresh a portable bundle from an existing finished campaign:
|
|
257
|
+
```bash
|
|
258
|
+
caddforge run fep openfe-rbfe-septop --config rbfe_refresh_bundle.yaml
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Python API usage
|
|
262
|
+
```python
|
|
263
|
+
from caddforge.core.execution import load_result_for_job, submit_workflow
|
|
264
|
+
from caddforge.plugins import get_tool
|
|
265
|
+
|
|
266
|
+
spec = get_tool("fep", "openfe-rbfe-septop")
|
|
267
|
+
cfg = spec.config_cls(
|
|
268
|
+
ligand_sdf="ligands.sdf",
|
|
269
|
+
ligand_sdfs=[],
|
|
270
|
+
protein_pdb="protein.pdb",
|
|
271
|
+
project_compound_ids=["proj_anchor_01", "proj_anchor_02"],
|
|
272
|
+
operation_mode="run",
|
|
273
|
+
backend="local", # or "slurm"
|
|
274
|
+
protocol_repeats=3,
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
workflow = spec.workflow_cls(cfg)
|
|
278
|
+
job = submit_workflow(workflow, cfg, backend_name=cfg.backend)
|
|
279
|
+
result = load_result_for_job(job)
|
|
280
|
+
if result is not None:
|
|
281
|
+
print(result.status.value, result.metrics)
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Example config
|
|
285
|
+
```yaml
|
|
286
|
+
operation_mode: run
|
|
287
|
+
ligand_sdf: ligands.sdf
|
|
288
|
+
ligand_sdfs: []
|
|
289
|
+
protein_pdb: protein.pdb
|
|
290
|
+
complexes: []
|
|
291
|
+
project_compound_ids:
|
|
292
|
+
- proj_anchor_01
|
|
293
|
+
- proj_anchor_02
|
|
294
|
+
bundle_refresh_source_path: null
|
|
295
|
+
existing_network_path: null
|
|
296
|
+
existing_network_bundle_path: null
|
|
297
|
+
existing_transformations_manifest_path: null
|
|
298
|
+
export_network_bundle: true
|
|
299
|
+
reuse_completed_edges: true
|
|
300
|
+
|
|
301
|
+
partial_charge_method: am1bcc
|
|
302
|
+
off_toolkit_backend: ambertools
|
|
303
|
+
protocol_repeats: 3
|
|
304
|
+
settings_overrides:
|
|
305
|
+
engine_settings.compute_platform: CUDA
|
|
306
|
+
|
|
307
|
+
compatibility_threshold: 0.45
|
|
308
|
+
project_assignment_threshold: 0.35
|
|
309
|
+
local_cluster_threshold: 0.55
|
|
310
|
+
max_clash_score: 0.35
|
|
311
|
+
diagnostic_cycle_edges_per_component: 1
|
|
312
|
+
|
|
313
|
+
run_quickrun: true
|
|
314
|
+
quickrun_extra_args: []
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Tool-specific config options
|
|
318
|
+
|
|
319
|
+
#### Required / primary inputs
|
|
320
|
+
Use either:
|
|
321
|
+
- `ligand_sdf` and/or `ligand_sdfs`, together with `protein_pdb`
|
|
322
|
+
|
|
323
|
+
Or:
|
|
324
|
+
- `complexes`
|
|
325
|
+
|
|
326
|
+
Primary fields:
|
|
327
|
+
- `operation_mode` (`"plan" | "extend" | "prepare" | "run" | "refresh_bundle"`, default `"run"`): Network-only planning, network extension, transformation preparation, full execution, or rebuilding a portable bundle from an existing finished campaign/source.
|
|
328
|
+
- `ligand_sdf` (`Path | None`): Optional SDF containing ligands already placed in the protein frame.
|
|
329
|
+
- `ligand_sdfs` (`list[Path]`, default `[]`): Optional list of SDF files used with the shared protein. Each file may contain one or many ligands.
|
|
330
|
+
- `protein_pdb` (`Path | None`): Shared aligned protein PDB used with `ligand_sdf` and/or `ligand_sdfs`.
|
|
331
|
+
- `complexes` (`list[SeptopComplexInput]`, default `[]`): Alternative aligned per-ligand input pairs, each containing a `protein_pdb` and a `ligand_sdf`.
|
|
332
|
+
- `project_compound_ids` (`list[str]`, default `[]`): Explicit ligand identifiers used as project anchors.
|
|
333
|
+
- `bundle_refresh_source_path` (`Path | None`): Required for `operation_mode: refresh_bundle`. Accepts a campaign directory, a `results/` directory, a `ligand_network.json`, or an existing bundle zip.
|
|
334
|
+
- `existing_network_path` (`Path | None`): Persisted network JSON used for `extend`, `prepare`, or `run` from an existing network.
|
|
335
|
+
- `existing_network_bundle_path` (`Path | None`): Portable self-contained RBFE bundle zip used for `extend`, `prepare`, or `run`.
|
|
336
|
+
- `existing_transformations_manifest_path` (`Path | None`): Existing `transformations_manifest.json` used to reuse already prepared transformation JSON files without regenerating them.
|
|
337
|
+
|
|
338
|
+
`SeptopComplexInput` fields:
|
|
339
|
+
- `ligand_sdf` (`Path`): Ligand SDF file.
|
|
340
|
+
- `protein_pdb` (`Path`): Protein PDB file for that ligand pose.
|
|
341
|
+
- `ligand_index` (`int`, default `0`): Ligand record to use from the SDF.
|
|
342
|
+
- `ligand_id` (`str | None`): Reserved identifier field; current implementation derives IDs from ligand names/properties.
|
|
343
|
+
|
|
344
|
+
Current limitation:
|
|
345
|
+
- A `complexes` entry is not a single combined protein-ligand complex PDB file. The current implementation expects `protein_pdb` plus `ligand_sdf` for each entry.
|
|
346
|
+
|
|
347
|
+
Example `complexes` config:
|
|
348
|
+
```yaml
|
|
349
|
+
complexes:
|
|
350
|
+
- protein_pdb: poses/lig1_protein.pdb
|
|
351
|
+
ligand_sdf: poses/lig1_ligand.sdf
|
|
352
|
+
ligand_index: 0
|
|
353
|
+
- protein_pdb: poses/lig2_protein.pdb
|
|
354
|
+
ligand_sdf: poses/lig2_ligand.sdf
|
|
355
|
+
ligand_index: 0
|
|
356
|
+
|
|
357
|
+
project_compound_ids:
|
|
358
|
+
- lig1_ref
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
#### Network planning options
|
|
362
|
+
- `compatibility_threshold` (`float`, default `0.45`): Minimum pair similarity for direct compatibility.
|
|
363
|
+
- `project_assignment_threshold` (`float`, default `0.35`): Minimum similarity required to attach a ligand directly to a project hub.
|
|
364
|
+
- `local_cluster_threshold` (`float`, default `0.55`): Minimum similarity used to identify local orphan clusters.
|
|
365
|
+
- `max_clash_score` (`float`, default `0.35`): Maximum tolerated per-ligand protein-clash score for compatibility.
|
|
366
|
+
- `diagnostic_cycle_edges_per_component` (`int`, default `1`): Number of optional extra diagnostic edges to add per connected component.
|
|
367
|
+
|
|
368
|
+
Planning behavior:
|
|
369
|
+
1. Split ligands by formal charge.
|
|
370
|
+
2. Build compatibility components using similarity and protein-clash filtering.
|
|
371
|
+
3. Use explicit `project_compound_ids` as preferred centers when available.
|
|
372
|
+
4. Build local subclusters for ligands that are similar to each other but not close to a project hub.
|
|
373
|
+
5. Preserve existing edges when `operation_mode: extend`.
|
|
374
|
+
|
|
375
|
+
Reuse behavior:
|
|
376
|
+
- Use `existing_network_path` when you want to regenerate transformations from a saved ligand network.
|
|
377
|
+
- Use `existing_network_bundle_path` when you want to load a self-contained prior network including bundled proteins and reusable completed edge records.
|
|
378
|
+
- Use `existing_transformations_manifest_path` when you already have prepared transformation JSON files and want to reuse them directly.
|
|
379
|
+
- In `run` mode, `existing_transformations_manifest_path` avoids regenerating the transformation JSON files.
|
|
380
|
+
- `reuse_completed_edges` (`bool`, default `true`) reuses previously completed edges when compatible edge records are found next to `existing_network_path` or inside `existing_network_bundle_path`.
|
|
381
|
+
- `refresh_bundle` is a lightweight local-only maintenance mode. It does not plan, prepare, or run simulations; it just rebuilds a fresh `ligand_network_bundle.zip` from an existing campaign/source plus its current `edge_records`.
|
|
382
|
+
- Use `bundle_refresh_source_path` with `operation_mode: refresh_bundle` when you want to rebuild a portable bundle after a finished Slurm campaign.
|
|
383
|
+
|
|
384
|
+
#### Charge / protocol options
|
|
385
|
+
- `partial_charge_method` (`str`, default `"am1bcc"`): Partial charge method for OpenFF charge generation.
|
|
386
|
+
- `off_toolkit_backend` (`str`, default `"ambertools"`): OpenFF backend used for charge assignment.
|
|
387
|
+
- `charge_n_conformers` (`int`, default `1`): Number of conformers for charge generation.
|
|
388
|
+
- `charge_nagl_model` (`str | None`): Optional NAGL model name.
|
|
389
|
+
- `charge_processors` (`int`, default `1`): Number of processors for charge assignment.
|
|
390
|
+
- `overwrite_charges` (`bool`, default `false`): Overwrite existing molecule charges.
|
|
391
|
+
- `protocol_repeats` (`int | None`): Optional override for SepTop protocol repeats.
|
|
392
|
+
- `settings_overrides` (`dict[str, Any]`, default `{}`): Dot-path overrides applied to `SepTopProtocol.default_settings()`.
|
|
393
|
+
|
|
394
|
+
#### Execution / output options
|
|
395
|
+
- `transformation_dir_name` (`str`, default `"transformations"`): Directory name used for transformation JSON files.
|
|
396
|
+
- `network_dir_name` (`str`, default `"network"`): Directory name used for persisted network artifacts.
|
|
397
|
+
- `run_quickrun` (`bool`, default `true`): If `true`, execute `openfe quickrun` in `run` mode.
|
|
398
|
+
- `quickrun_extra_args` (`list[str]`, default `[]`): Extra raw arguments appended to `openfe quickrun`.
|
|
399
|
+
- `export_network_bundle` (`bool`, default `true`): Write a portable `ligand_network_bundle.zip` into `results/`.
|
|
400
|
+
|
|
401
|
+
Backend behavior:
|
|
402
|
+
- Local backend: edges are executed sequentially.
|
|
403
|
+
- Slurm backend: the campaign prepares the network and transformation JSONs once, then submits one Slurm child job per edge.
|
|
404
|
+
- `refresh_bundle` must use the local backend.
|
|
405
|
+
|
|
406
|
+
### Outputs
|
|
407
|
+
For each campaign run, artifacts are written under `runs/<date>/<job-id>/`:
|
|
408
|
+
- `<network_dir_name>/ligand_network.json`: canonical persisted RBFE network
|
|
409
|
+
- `<network_dir_name>/ligand_network.graphml`: GraphML view of the network
|
|
410
|
+
- `results/ligand_network.json`: exportable copy of the persisted ligand network JSON
|
|
411
|
+
- `results/ligand_network.graphml`: exportable copy of the GraphML network view
|
|
412
|
+
- `results/ligand_network_bundle.zip`: portable self-contained network bundle with bundled proteins and reusable edge records
|
|
413
|
+
- `results/ligand_network_summary.txt`: human-readable network summary
|
|
414
|
+
- `results/transformations_manifest.json`: manifest of prepared transformations and edge run directories
|
|
415
|
+
- `results/edge_records/`: canonical per-edge reusable result cache used for extension / rerun reuse
|
|
416
|
+
- `transformations/`: one OpenFE transformation JSON per planned edge
|
|
417
|
+
- `edges/<edge-id>/`: per-edge run directories
|
|
418
|
+
|
|
419
|
+
For local `run` mode, each edge directory contains:
|
|
420
|
+
- `results/openfe_results.json`
|
|
421
|
+
- `results/openfe_stdout.log`
|
|
422
|
+
- `results/openfe_stderr.log`
|
|
423
|
+
- `openfe_run/`
|
|
424
|
+
|
|
425
|
+
Campaign-level artifacts:
|
|
426
|
+
- `results/result_record.json`: standardized CADDForge `Result`
|
|
427
|
+
- `stdout.log` / `stderr.log`: campaign workflow logs
|
|
428
|
+
|
|
429
|
+
Notes:
|
|
430
|
+
- In Slurm mode, edge execution status is tracked per child job.
|
|
431
|
+
- The parent campaign job records the planned network and submitted child jobs; child jobs own the actual per-edge simulation logs and status.
|
|
432
|
+
- Reuse of previously completed edges is driven by the edge cache under `results/edge_records/`. A portable bundle is sufficient for later extension if you want to move or archive a network as a single file.
|
|
433
|
+
## Compressed inputs
|
|
434
|
+
|
|
435
|
+
ABFE and RBFE ligand SDF and protein PDB inputs, including paths nested in RBFE `complexes`, may be
|
|
436
|
+
provided with a trailing `.gz`. CADDForge expands each wrapper in runtime scratch while preserving
|
|
437
|
+
the original compressed path in saved configuration and provenance. Gzipped existing-network JSON
|
|
438
|
+
and transformation manifests are read directly so relative references remain anchored to the
|
|
439
|
+
manifest directory; gzip-wrapped self-contained network bundles are staged as plain bundle files.
|
|
440
|
+
|
|
441
|
+
## Continuous integration and releases
|
|
442
|
+
|
|
443
|
+
`.github/workflows/release.yml` builds a wheel and source archive, validates
|
|
444
|
+
metadata, and tests the installed wheel on Linux with Python 3.10 and 3.12.
|
|
445
|
+
The lightweight test selection is recorded in `scripts/ci_tests.json`;
|
|
446
|
+
external scientific engines are validated separately. CI installs the same
|
|
447
|
+
wheel with its `[gui]` extra so GUI regression tests use the declared GUI
|
|
448
|
+
dependencies, including `caddforge-gui`.
|
|
449
|
+
|
|
450
|
+
Pushing a matching `v*` release tag publishes the tested artifacts to PyPI.
|
|
451
|
+
Branch pushes, pull requests and manual runs never publish. Configure a
|
|
452
|
+
PyPI Trusted Publisher for the `idorsia` repository, `release.yml` workflow
|
|
453
|
+
and `pypi` environment before pushing release tags. Runtime CADDForge
|
|
454
|
+
dependencies must already be available publicly; publish core and GUI before
|
|
455
|
+
FEP/docking, and publish docking/descriptors before MD.
|