caddforge-descriptors 0.11.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_descriptors-0.11.0/.github/workflows/release.yml +99 -0
- caddforge_descriptors-0.11.0/.gitignore +25 -0
- caddforge_descriptors-0.11.0/LICENSE +21 -0
- caddforge_descriptors-0.11.0/PKG-INFO +444 -0
- caddforge_descriptors-0.11.0/README.md +425 -0
- caddforge_descriptors-0.11.0/pyproject.toml +41 -0
- caddforge_descriptors-0.11.0/scripts/check_release.py +98 -0
- caddforge_descriptors-0.11.0/scripts/ci_tests.json +11 -0
- caddforge_descriptors-0.11.0/scripts/run_ci_tests.py +84 -0
- caddforge_descriptors-0.11.0/src/cadd_descriptors/__init__.py +48 -0
- caddforge_descriptors-0.11.0/src/cadd_descriptors/ani_conformers/__init__.py +11 -0
- caddforge_descriptors-0.11.0/src/cadd_descriptors/ani_conformers/pipeline.py +72 -0
- caddforge_descriptors-0.11.0/src/cadd_descriptors/ani_conformers/workflow.py +390 -0
- caddforge_descriptors-0.11.0/src/cadd_descriptors/ani_psa/__init__.py +32 -0
- caddforge_descriptors-0.11.0/src/cadd_descriptors/ani_psa/pipeline.py +173 -0
- caddforge_descriptors-0.11.0/src/cadd_descriptors/ani_psa/workflow.py +355 -0
- caddforge_descriptors-0.11.0/src/cadd_descriptors/ani_utils.py +225 -0
- caddforge_descriptors-0.11.0/src/cadd_descriptors/cluster_molecules/__init__.py +5 -0
- caddforge_descriptors-0.11.0/src/cadd_descriptors/cluster_molecules/workflow.py +843 -0
- caddforge_descriptors-0.11.0/src/cadd_descriptors/inputs.py +108 -0
- caddforge_descriptors-0.11.0/src/cadd_descriptors/phesa/__init__.py +5 -0
- caddforge_descriptors-0.11.0/src/cadd_descriptors/phesa/workflow.py +622 -0
- caddforge_descriptors-0.11.0/src/cadd_descriptors/tool.py +81 -0
- caddforge_descriptors-0.11.0/tests/conftest.py +19 -0
- caddforge_descriptors-0.11.0/tests/test_ani_conformers_smoke.py +60 -0
- caddforge_descriptors-0.11.0/tests/test_ani_psa_smoke.py +85 -0
- caddforge_descriptors-0.11.0/tests/test_cluster_molecules_workflow.py +142 -0
- caddforge_descriptors-0.11.0/tests/test_phesa_workflow.py +506 -0
- caddforge_descriptors-0.11.0/tests/test_placeholder_descriptors.py +12 -0
- caddforge_descriptors-0.11.0/tests/test_release_metadata.py +77 -0
|
@@ -0,0 +1,99 @@
|
|
|
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
|
+
- name: Set up Java for PyOCL
|
|
58
|
+
uses: actions/setup-java@v6.0.1
|
|
59
|
+
with:
|
|
60
|
+
distribution: temurin
|
|
61
|
+
java-version: '21'
|
|
62
|
+
- uses: actions/download-artifact@v8.0.1
|
|
63
|
+
with:
|
|
64
|
+
name: distributions
|
|
65
|
+
path: dist
|
|
66
|
+
- name: Install built wheel and test dependencies
|
|
67
|
+
shell: bash
|
|
68
|
+
run: |-
|
|
69
|
+
python -m pip --isolated install --index-url https://pypi.org/simple dist/*.whl
|
|
70
|
+
python -m pip --isolated install --index-url https://pypi.org/simple pytest packaging 'tomli; python_version < "3.11"'
|
|
71
|
+
- name: Test installed wheel outside the checkout
|
|
72
|
+
env:
|
|
73
|
+
MPLBACKEND: Agg
|
|
74
|
+
OMP_NUM_THREADS: '1'
|
|
75
|
+
OPENBLAS_NUM_THREADS: '1'
|
|
76
|
+
run: python scripts/run_ci_tests.py
|
|
77
|
+
- name: Check installed dependencies
|
|
78
|
+
run: python -m pip check
|
|
79
|
+
publish:
|
|
80
|
+
name: Publish to PyPI
|
|
81
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
82
|
+
needs:
|
|
83
|
+
- build
|
|
84
|
+
- test
|
|
85
|
+
runs-on: ubuntu-24.04
|
|
86
|
+
environment:
|
|
87
|
+
name: pypi
|
|
88
|
+
url: https://pypi.org/project/caddforge-descriptors/
|
|
89
|
+
permissions:
|
|
90
|
+
id-token: write
|
|
91
|
+
concurrency:
|
|
92
|
+
group: pypi-${{ github.ref }}
|
|
93
|
+
cancel-in-progress: false
|
|
94
|
+
steps:
|
|
95
|
+
- uses: actions/download-artifact@v8.0.1
|
|
96
|
+
with:
|
|
97
|
+
name: distributions
|
|
98
|
+
path: dist
|
|
99
|
+
- 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,444 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: caddforge-descriptors
|
|
3
|
+
Version: 0.11.0
|
|
4
|
+
Summary: Molecular descriptor 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: hdbscan>=0.8.33
|
|
11
|
+
Requires-Dist: numpy>=1.25
|
|
12
|
+
Requires-Dist: pandas>=2.1
|
|
13
|
+
Requires-Dist: pyocl-idor>=0.8.3
|
|
14
|
+
Requires-Dist: rdkit>=2022.9.5
|
|
15
|
+
Requires-Dist: scikit-learn-extra>=0.3
|
|
16
|
+
Requires-Dist: scikit-learn>=1.3
|
|
17
|
+
Requires-Dist: torchani>=2.7.9
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# CADDForge Descriptors Plugin
|
|
21
|
+
|
|
22
|
+
Install this plugin with `python -m pip install caddforge-descriptors`. It depends directly
|
|
23
|
+
on `caddforge-core>=0.21.0`; Python imports and CLI commands still use `caddforge`.
|
|
24
|
+
For the complete public toolbox, including user-facing extras, install
|
|
25
|
+
`python -m pip install caddforge`. When migrating an existing environment, uninstall
|
|
26
|
+
the former `caddforge` core distribution before installing renamed core and updated plugins.
|
|
27
|
+
|
|
28
|
+
`caddforge-descriptors` provides descriptor and clustering workflows as plugins for the CADDForge framework.
|
|
29
|
+
|
|
30
|
+
## Implemented Tools
|
|
31
|
+
- [`ani-psa`](#tool-ani-psa)
|
|
32
|
+
- [`ani-conformers`](#tool-ani-conformers)
|
|
33
|
+
- [`cluster-molecules`](#tool-cluster-molecules)
|
|
34
|
+
- [`phesa`](#tool-phesa)
|
|
35
|
+
|
|
36
|
+
## Tool: `ani-psa`
|
|
37
|
+
|
|
38
|
+
### What it does
|
|
39
|
+
The `ani-psa` tool computes ANI-weighted 3D polar surface area values from one molecule or a batch of molecules. The workflow:
|
|
40
|
+
- accepts one SMILES, an inline SMILES list, or a SMILES file
|
|
41
|
+
- generates conformers with RDKit, optimizes them with MMFF, clusters them, and re-ranks them with TorchANI
|
|
42
|
+
- computes 3D PSA on the selected conformers and reports the Boltzmann-weighted average
|
|
43
|
+
- writes standardized CADDForge outputs plus per-molecule JSON/CSV summaries
|
|
44
|
+
|
|
45
|
+
### External dependencies
|
|
46
|
+
No external command-line tools are required beyond the Python environment.
|
|
47
|
+
|
|
48
|
+
Runtime notes:
|
|
49
|
+
- TorchANI and PyTorch must be available in the environment.
|
|
50
|
+
- CUDA is optional; set `device: cuda` or `device: cuda:0` if you want GPU execution.
|
|
51
|
+
|
|
52
|
+
### CLI usage
|
|
53
|
+
```bash
|
|
54
|
+
caddforge run descriptors ani-psa --config ani_psa.yaml
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Python API usage
|
|
58
|
+
```python
|
|
59
|
+
from cadd_descriptors import AniPsaConfig, AniPsaWorkflow
|
|
60
|
+
|
|
61
|
+
cfg = AniPsaConfig(
|
|
62
|
+
smiles="CC(=O)Oc1ccccc1C(=O)O",
|
|
63
|
+
top_n=25,
|
|
64
|
+
backend="local",
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
workflow = AniPsaWorkflow(cfg)
|
|
68
|
+
job = workflow.prepare_job()
|
|
69
|
+
result = workflow.run(job)
|
|
70
|
+
print(result.status.value, result.metrics)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Example config
|
|
74
|
+
```yaml
|
|
75
|
+
smiles: "CCO"
|
|
76
|
+
num_confs: 100
|
|
77
|
+
top_n: 10
|
|
78
|
+
rmsd_cluster_thresh: 0.5
|
|
79
|
+
max_mmff_iters: 200
|
|
80
|
+
temperature: 298.15
|
|
81
|
+
model_name: ANI2x
|
|
82
|
+
device: cpu
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Tool-specific config options
|
|
86
|
+
Only one input source must be set:
|
|
87
|
+
- `smiles`
|
|
88
|
+
- `smiles_list`
|
|
89
|
+
- `smiles_file`
|
|
90
|
+
|
|
91
|
+
#### Input options
|
|
92
|
+
- `smiles` (`str | None`): Single SMILES string.
|
|
93
|
+
- `smiles_list` (`list[str] | None`): Inline batch of SMILES strings.
|
|
94
|
+
- `smiles_file` (`Path | None`): SMILES input file.
|
|
95
|
+
- `smiles_column` (`str`, default `smiles`): Column to read from CSV/TSV input.
|
|
96
|
+
|
|
97
|
+
#### Conformer and ANI options
|
|
98
|
+
- `num_confs` (`int`, default `500`): Number of conformers to generate.
|
|
99
|
+
- `rmsd_cluster_thresh` (`float`, default `0.5`): RMSD threshold for conformer clustering.
|
|
100
|
+
- `max_mmff_iters` (`int`, default `200`): MMFF optimization steps per conformer.
|
|
101
|
+
- `top_n` (`int`, default `50`): Number of ANI-ranked conformers kept for PSA averaging.
|
|
102
|
+
- `temperature` (`float`, default `298.15`): Boltzmann weighting temperature in Kelvin.
|
|
103
|
+
- `model_name` (`str`, default `ANI2x`): TorchANI model name.
|
|
104
|
+
- `device` (`str | None`, default `cpu`): Torch device string.
|
|
105
|
+
|
|
106
|
+
### Outputs
|
|
107
|
+
For each run, artifacts are written under `runs/<date>/<job-id>/`:
|
|
108
|
+
- `results/results.json`: per-molecule PSA summary payload
|
|
109
|
+
- `results/results.csv`: tabular per-molecule PSA summary
|
|
110
|
+
- `results/result_record.json`: standardized CADDForge `Result`
|
|
111
|
+
- `stdout.log`: workflow log
|
|
112
|
+
|
|
113
|
+
## Tool: `phesa`
|
|
114
|
+
|
|
115
|
+
### What it does
|
|
116
|
+
The `phesa` tool computes OpenChemLib PheSA shape/pharmacophore similarities between one reference
|
|
117
|
+
molecule and one or more candidates. It supports:
|
|
118
|
+
- a reference molecule from SMILES, SDF, or an encoded PheSA text file
|
|
119
|
+
- candidate molecules from either SMILES strings or single-/multi-compound SDF files
|
|
120
|
+
- configurable maximum conformer count and pharmacophore point weight
|
|
121
|
+
- aligned SDF outputs for the reference and candidates
|
|
122
|
+
- pipeline outputs for scores and aligned candidate collections
|
|
123
|
+
|
|
124
|
+
### External dependencies
|
|
125
|
+
PheSA imports `pyocl`, provided by the public `pyocl-idor>=0.8.3` distribution.
|
|
126
|
+
The OpenChemLib runtime requires Java 21 or newer with `JAVA_HOME` configured.
|
|
127
|
+
|
|
128
|
+
### CLI usage
|
|
129
|
+
```bash
|
|
130
|
+
caddforge run descriptors phesa --config phesa.yaml
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Python API usage
|
|
134
|
+
```python
|
|
135
|
+
from cadd_descriptors import PhesaConfig, PhesaWorkflow
|
|
136
|
+
|
|
137
|
+
cfg = PhesaConfig(
|
|
138
|
+
reference_smiles="CCO",
|
|
139
|
+
candidate_smiles=["CCCO", "CCCCO"],
|
|
140
|
+
max_confs=200,
|
|
141
|
+
pp_weight=0.5,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
workflow = PhesaWorkflow(cfg)
|
|
145
|
+
job = workflow.prepare_job()
|
|
146
|
+
result = workflow.run(job)
|
|
147
|
+
print(result.status.value, result.metrics)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Example configs
|
|
151
|
+
```yaml
|
|
152
|
+
reference_smiles: "CCO"
|
|
153
|
+
candidate_smiles:
|
|
154
|
+
- "CCCO"
|
|
155
|
+
- "CCCCO"
|
|
156
|
+
max_confs: 200
|
|
157
|
+
pp_weight: 0.5
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
```yaml
|
|
161
|
+
reference_sdf: reference.sdf
|
|
162
|
+
candidate_sdf_files:
|
|
163
|
+
- candidates.sdf
|
|
164
|
+
- extra_candidate.sdf
|
|
165
|
+
max_confs: 200
|
|
166
|
+
pp_weight: 0.5
|
|
167
|
+
write_merged_aligned_candidates_sdf: true
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
```yaml
|
|
171
|
+
reference_phesa_file: reference_phesa.txt
|
|
172
|
+
candidate_smiles:
|
|
173
|
+
- "CCCO"
|
|
174
|
+
- "CCCCO"
|
|
175
|
+
max_confs: 200
|
|
176
|
+
pp_weight: 0.5
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Tool-specific config options
|
|
180
|
+
Exactly one reference source must be set:
|
|
181
|
+
- `reference_smiles`
|
|
182
|
+
- `reference_sdf`
|
|
183
|
+
- `reference_phesa_file`
|
|
184
|
+
|
|
185
|
+
Exactly one candidate source must be set:
|
|
186
|
+
- `candidate_smiles`
|
|
187
|
+
- `candidate_sdf_files`
|
|
188
|
+
|
|
189
|
+
`candidate_sdf_files` may contain single- or multi-compound SDF files. Each valid SDF molecule
|
|
190
|
+
record is scored as one candidate; record names are used as candidate IDs when present, otherwise
|
|
191
|
+
IDs fall back to the source file stem plus the record index.
|
|
192
|
+
|
|
193
|
+
#### PheSA options
|
|
194
|
+
- `max_confs` (`int`, default `200`): Maximum number of conformers for generated PheSA descriptors.
|
|
195
|
+
- `pp_weight` (`float`, default `0.5`): Pharmacophore point weight.
|
|
196
|
+
- `scores_csv_name` (`str`, default `scores.csv`): Scores CSV filename under `results/`.
|
|
197
|
+
- `aligned_dir_name` (`str`, default `aligned`): Aligned SDF output directory under `results/`.
|
|
198
|
+
- `write_merged_aligned_candidates_sdf` (`bool`, default `false`): Write one SDF containing all
|
|
199
|
+
successfully aligned candidate molecules.
|
|
200
|
+
- `merged_aligned_candidates_sdf_name` (`str`, default `aligned_candidates.sdf`): Filename for the
|
|
201
|
+
merged aligned candidate SDF under the aligned output directory.
|
|
202
|
+
|
|
203
|
+
When `reference_smiles` is used, both the reference and candidates use OpenChemLib's generated-shape
|
|
204
|
+
handler with `max_confs` and `pp_weight`. When `reference_sdf` is used, the reference uses
|
|
205
|
+
OpenChemLib's one-conformation handler; candidates still use `max_confs` and `pp_weight`.
|
|
206
|
+
|
|
207
|
+
With `reference_phesa_file`, the entire UTF-8 text file must contain one encoded PheSA descriptor.
|
|
208
|
+
Surrounding whitespace is stripped before decoding with `DescriptorHandlerShape.decode()`.
|
|
209
|
+
The decoded reference is used directly, without generating reference conformers. Candidates still
|
|
210
|
+
use `max_confs` and `pp_weight`. Empty, unreadable, or invalid descriptor files fail the run.
|
|
211
|
+
|
|
212
|
+
**Reference coordinate frame:** With `reference_phesa_file`, the aligned reference and candidate
|
|
213
|
+
SDFs, including the optional merged candidate SDF, remain in the PheSA alignment coordinate frame.
|
|
214
|
+
They are not restored to the coordinates of the original molecule used to create the encoded
|
|
215
|
+
descriptor. If downstream calculations need alignment in an input reference SDF's coordinate frame,
|
|
216
|
+
use `reference_sdf`; coordinate restoration applies only to that reference mode.
|
|
217
|
+
|
|
218
|
+
### Outputs
|
|
219
|
+
For each run, artifacts are written under `runs/<date>/<job-id>/`:
|
|
220
|
+
- `results/results.json`: per-candidate PheSA similarity payload
|
|
221
|
+
- `results/scores.csv`: tabular candidate scores
|
|
222
|
+
- `results/aligned/reference.sdf`: aligned reference structure
|
|
223
|
+
- `results/aligned/candidates/*.sdf`: aligned candidate structures
|
|
224
|
+
- `results/aligned/aligned_candidates.sdf`: optional merged aligned candidate SDF
|
|
225
|
+
- `results/aligned/manifest.csv`: candidate scores and aligned SDF paths
|
|
226
|
+
- `results/result_record.json`: standardized CADDForge `Result`
|
|
227
|
+
|
|
228
|
+
### Pipeline artifacts
|
|
229
|
+
The plugin exposes:
|
|
230
|
+
- input `reference_sdf` mapped to config field `reference_sdf`
|
|
231
|
+
- input `reference_phesa_file` mapped to config field `reference_phesa_file`
|
|
232
|
+
- input `candidates` mapped to config field `candidate_sdf_files`
|
|
233
|
+
- output `scores` from `scores_csv`
|
|
234
|
+
- output `aligned_reference` from `aligned_reference_sdf`
|
|
235
|
+
- output `aligned_candidates` from `aligned_manifest_csv` using column `aligned_candidate_sdf`
|
|
236
|
+
- optional output `merged_aligned_candidates` from `merged_aligned_candidates_sdf`
|
|
237
|
+
|
|
238
|
+
## Tool: `ani-conformers`
|
|
239
|
+
|
|
240
|
+
### What it does
|
|
241
|
+
The `ani-conformers` tool generates ANI re-ranked conformers and writes the selected conformers to SDF. It supports:
|
|
242
|
+
- one SMILES, an inline SMILES list, a SMILES file, or an input SDF file
|
|
243
|
+
- RDKit conformer generation and MMFF optimization
|
|
244
|
+
- ANI re-ranking of clustered conformer representatives
|
|
245
|
+
- batch processing with per-molecule summaries and a combined ranked-conformer SDF
|
|
246
|
+
|
|
247
|
+
### External dependencies
|
|
248
|
+
No external command-line tools are required beyond the Python environment.
|
|
249
|
+
|
|
250
|
+
Runtime notes:
|
|
251
|
+
- TorchANI and PyTorch must be available in the environment.
|
|
252
|
+
- CUDA is optional.
|
|
253
|
+
|
|
254
|
+
### CLI usage
|
|
255
|
+
```bash
|
|
256
|
+
caddforge run descriptors ani-conformers --config ani_conformers.yaml
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Python API usage
|
|
260
|
+
```python
|
|
261
|
+
from cadd_descriptors import AniConformersConfig, AniConformersWorkflow
|
|
262
|
+
|
|
263
|
+
cfg = AniConformersConfig(
|
|
264
|
+
smiles="CCO",
|
|
265
|
+
top_n=10,
|
|
266
|
+
num_confs=50,
|
|
267
|
+
backend="local",
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
workflow = AniConformersWorkflow(cfg)
|
|
271
|
+
job = workflow.prepare_job()
|
|
272
|
+
result = workflow.run(job)
|
|
273
|
+
print(result.status.value, result.paths["ranked_conformers_sdf"])
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Example config
|
|
277
|
+
```yaml
|
|
278
|
+
smiles: "CCO"
|
|
279
|
+
num_confs: 100
|
|
280
|
+
top_n: 10
|
|
281
|
+
rmsd_cluster_thresh: 0.5
|
|
282
|
+
max_mmff_iters: 200
|
|
283
|
+
model_name: ANI2x
|
|
284
|
+
device: cpu
|
|
285
|
+
output_sdf_name: ranked_conformers.sdf
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Tool-specific config options
|
|
289
|
+
Only one input source must be set:
|
|
290
|
+
- `smiles`
|
|
291
|
+
- `smiles_list`
|
|
292
|
+
- `smiles_file`
|
|
293
|
+
- `structure_file`
|
|
294
|
+
|
|
295
|
+
#### Input options
|
|
296
|
+
- `smiles` (`str | None`): Single SMILES string.
|
|
297
|
+
- `smiles_list` (`list[str] | None`): Inline batch of SMILES strings.
|
|
298
|
+
- `smiles_file` (`Path | None`): SMILES input file.
|
|
299
|
+
- `structure_file` (`Path | None`): Input SDF file.
|
|
300
|
+
- `smiles_column` (`str`, default `smiles`): Column to read from CSV/TSV SMILES input.
|
|
301
|
+
|
|
302
|
+
#### Conformer and ANI options
|
|
303
|
+
- `num_confs` (`int`, default `500`): Number of conformers to generate.
|
|
304
|
+
- `rmsd_cluster_thresh` (`float`, default `0.5`): RMSD threshold for conformer clustering.
|
|
305
|
+
- `max_mmff_iters` (`int`, default `200`): MMFF optimization steps per conformer.
|
|
306
|
+
- `top_n` (`int`, default `50`): Number of ANI-ranked conformers to keep.
|
|
307
|
+
- `model_name` (`str`, default `ANI2x`): TorchANI model name.
|
|
308
|
+
- `device` (`str | None`, default `cpu`): Torch device string.
|
|
309
|
+
- `output_sdf_name` (`str`, default `ranked_conformers.sdf`): Output SDF filename under `results/`.
|
|
310
|
+
|
|
311
|
+
### Outputs
|
|
312
|
+
For each run, artifacts are written under `runs/<date>/<job-id>/`:
|
|
313
|
+
- `results/results.json`: per-molecule conformer summary payload
|
|
314
|
+
- `results/<output_sdf_name>`: ranked conformers SDF
|
|
315
|
+
- `results/result_record.json`: standardized CADDForge `Result`
|
|
316
|
+
- `stdout.log`: workflow log
|
|
317
|
+
|
|
318
|
+
## Tool: `cluster-molecules`
|
|
319
|
+
|
|
320
|
+
### What it does
|
|
321
|
+
The `cluster-molecules` tool clusters molecules from SMILES input using fingerprint-based and scaffold-based algorithms. It supports:
|
|
322
|
+
- SMILES input from `.smi`, `.smiles`, `.sdf`, `.csv`, or `.tsv`
|
|
323
|
+
- multiple clustering algorithms: Butina, agglomerative, DBSCAN, HDBSCAN, k-medoids, scaffold, and affinity propagation
|
|
324
|
+
- medoid/centroid reporting for each cluster
|
|
325
|
+
- automatic k-medoids planning that chooses exact in-memory, exact disk-backed, or approximate execution modes
|
|
326
|
+
|
|
327
|
+
### External dependencies
|
|
328
|
+
No external command-line tools are required beyond the Python environment.
|
|
329
|
+
|
|
330
|
+
Runtime notes:
|
|
331
|
+
- `hdbscan` is required only for `algorithm: hdbscan`.
|
|
332
|
+
- The approximate `kmedoids` fallback uses sparse `MiniBatchKMeans` and then snaps cluster centers back to actual medoids.
|
|
333
|
+
|
|
334
|
+
### CLI usage
|
|
335
|
+
```bash
|
|
336
|
+
caddforge run descriptors cluster-molecules --config cluster.yaml
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Python API usage
|
|
340
|
+
```python
|
|
341
|
+
from cadd_descriptors import ClusterMoleculesConfig, ClusterMoleculesWorkflow
|
|
342
|
+
|
|
343
|
+
cfg = ClusterMoleculesConfig(
|
|
344
|
+
input_path="molecules.csv",
|
|
345
|
+
smiles_column="smiles",
|
|
346
|
+
algorithm="kmedoids",
|
|
347
|
+
kmedoids_n_clusters=100,
|
|
348
|
+
kmedoids_mode="auto",
|
|
349
|
+
backend="local",
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
workflow = ClusterMoleculesWorkflow(cfg)
|
|
353
|
+
job = workflow.prepare_job()
|
|
354
|
+
result = workflow.run(job)
|
|
355
|
+
print(result.status.value, result.metrics)
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Example config
|
|
359
|
+
```yaml
|
|
360
|
+
input_path: molecules.csv
|
|
361
|
+
smiles_column: smiles
|
|
362
|
+
algorithm: kmedoids # butina|agglomerative|dbscan|hdbscan|kmedoids|scaffold|affinity_propagation
|
|
363
|
+
fingerprint_radius: 2
|
|
364
|
+
fingerprint_bits: 2048
|
|
365
|
+
kmedoids_n_clusters: 100
|
|
366
|
+
kmedoids_mode: auto # auto|exact_ram|exact_disk|approximate
|
|
367
|
+
kmedoids_memory_budget_gb: null
|
|
368
|
+
kmedoids_disk_budget_gb: null
|
|
369
|
+
kmedoids_max_exact_n: 5000
|
|
370
|
+
kmedoids_max_exact_pairs: 25000000
|
|
371
|
+
kmedoids_max_exact_disk_n: 20000
|
|
372
|
+
kmedoids_max_exact_disk_pairs: 100000000
|
|
373
|
+
kmedoids_batch_size: 1024
|
|
374
|
+
kmedoids_max_iter: 20
|
|
375
|
+
kmedoids_minibatch_size: 4096
|
|
376
|
+
kmedoids_local_refine_limit: 128
|
|
377
|
+
kmedoids_temp_dir: null
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### Tool-specific config options
|
|
381
|
+
#### Input options
|
|
382
|
+
- `input_path` (`Path`): Input file containing molecules.
|
|
383
|
+
- `smiles_column` (`str`, default `smiles`): SMILES column for CSV/TSV input.
|
|
384
|
+
- `id_column` (`str | None`): Optional identifier column copied into outputs.
|
|
385
|
+
|
|
386
|
+
#### Fingerprint options
|
|
387
|
+
- `fingerprint_radius` (`int`, default `2`): Morgan fingerprint radius.
|
|
388
|
+
- `fingerprint_bits` (`int`, default `2048`): Morgan fingerprint size.
|
|
389
|
+
|
|
390
|
+
#### Algorithm selection
|
|
391
|
+
- `algorithm` (`butina | agglomerative | dbscan | hdbscan | kmedoids | scaffold | affinity_propagation`): Clustering algorithm.
|
|
392
|
+
|
|
393
|
+
#### Algorithm-specific options
|
|
394
|
+
- `butina_cutoff` (`float`, default `0.6`): Butina Tanimoto similarity cutoff.
|
|
395
|
+
- `agglomerative_n_clusters` (`int | None`): Agglomerative cluster count.
|
|
396
|
+
- `agglomerative_distance_threshold` (`float | None`): Agglomerative distance threshold.
|
|
397
|
+
- `dbscan_eps` (`float`, default `0.4`): DBSCAN epsilon in distance space.
|
|
398
|
+
- `dbscan_min_samples` (`int`, default `3`): DBSCAN minimum samples.
|
|
399
|
+
- `hdbscan_min_cluster_size` (`int`, default `5`): HDBSCAN minimum cluster size.
|
|
400
|
+
- `affinity_preference` (`float | None`): Affinity propagation preference.
|
|
401
|
+
- `scaffold_use_generic` (`bool`, default `true`): Use generic Bemis-Murcko scaffolds.
|
|
402
|
+
|
|
403
|
+
#### K-medoids planning options
|
|
404
|
+
- `kmedoids_n_clusters` (`int`, default `5`): Target number of medoid clusters.
|
|
405
|
+
- `kmedoids_mode` (`auto | exact_ram | exact_disk | approximate`, default `auto`): Force or auto-select the execution strategy.
|
|
406
|
+
- `kmedoids_memory_budget_gb` (`float | None`): Optional RAM budget for planning.
|
|
407
|
+
- `kmedoids_disk_budget_gb` (`float | None`): Optional temp-disk budget for planning.
|
|
408
|
+
- `kmedoids_max_exact_n` (`int`, default `5000`): Max size for exact in-memory planning.
|
|
409
|
+
- `kmedoids_max_exact_pairs` (`int`, default `25000000`): Max pair count for exact in-memory planning.
|
|
410
|
+
- `kmedoids_max_exact_disk_n` (`int`, default `20000`): Max size for exact disk-backed planning.
|
|
411
|
+
- `kmedoids_max_exact_disk_pairs` (`int`, default `100000000`): Max pair count for exact disk-backed planning.
|
|
412
|
+
- `kmedoids_batch_size` (`int`, default `1024`): Batch size for exact assignment/cost evaluation.
|
|
413
|
+
- `kmedoids_max_iter` (`int`, default `20`): PAM swap-iteration limit.
|
|
414
|
+
- `kmedoids_minibatch_size` (`int`, default `4096`): Mini-batch size for approximate mode.
|
|
415
|
+
- `kmedoids_local_refine_limit` (`int`, default `128`): Max cluster size for exact local medoid refinement in approximate mode.
|
|
416
|
+
- `kmedoids_temp_dir` (`Path | None`): Optional temp directory for disk-backed exact mode.
|
|
417
|
+
|
|
418
|
+
### Outputs
|
|
419
|
+
For each run, artifacts are written under `runs/<date>/<job-id>/`:
|
|
420
|
+
- `results/assignments.csv`: molecule-to-cluster assignments
|
|
421
|
+
- `results/centroids.csv`: per-cluster medoid/centroid summary
|
|
422
|
+
- `results/summary.json`: clustering summary
|
|
423
|
+
- `results/planning.json`: k-medoids planning summary when `algorithm: kmedoids`
|
|
424
|
+
- `results/result_record.json`: standardized CADDForge `Result`
|
|
425
|
+
- `stdout.log`: workflow log
|
|
426
|
+
## Compressed inputs
|
|
427
|
+
|
|
428
|
+
File-based SMILES, SDF, CSV, and TSV inputs may be supplied with a trailing `.gz`. CADDForge
|
|
429
|
+
expands these wrappers in job-local runtime scratch before invoking the descriptor workflow. Plain
|
|
430
|
+
inputs and native tool formats retain their existing behavior.
|
|
431
|
+
|
|
432
|
+
## Continuous integration and releases
|
|
433
|
+
|
|
434
|
+
`.github/workflows/release.yml` builds a wheel and source archive, validates
|
|
435
|
+
metadata, and tests the installed wheel on Linux with Python 3.10 and 3.12.
|
|
436
|
+
The lightweight test selection is recorded in `scripts/ci_tests.json`;
|
|
437
|
+
external scientific engines are validated separately.
|
|
438
|
+
|
|
439
|
+
Pushing a matching `v*` release tag publishes the tested artifacts to PyPI.
|
|
440
|
+
Branch pushes, pull requests and manual runs never publish. Configure a
|
|
441
|
+
PyPI Trusted Publisher for the `idorsia` repository, `release.yml` workflow
|
|
442
|
+
and `pypi` environment before pushing release tags. Runtime CADDForge
|
|
443
|
+
dependencies must already be available publicly; publish core first,
|
|
444
|
+
and publish docking/descriptors before MD.
|