tunnelprofile 0.1.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.
- tunnelprofile-0.1.0/LICENSE +21 -0
- tunnelprofile-0.1.0/MANIFEST.in +10 -0
- tunnelprofile-0.1.0/PKG-INFO +507 -0
- tunnelprofile-0.1.0/README.md +468 -0
- tunnelprofile-0.1.0/docs/cofactors.md +195 -0
- tunnelprofile-0.1.0/docs/dynamics.md +603 -0
- tunnelprofile-0.1.0/docs/inputs.md +324 -0
- tunnelprofile-0.1.0/docs/methods.md +404 -0
- tunnelprofile-0.1.0/docs/results.md +165 -0
- tunnelprofile-0.1.0/docs/running.md +135 -0
- tunnelprofile-0.1.0/docs/validation.md +390 -0
- tunnelprofile-0.1.0/environment.yml +38 -0
- tunnelprofile-0.1.0/pyproject.toml +93 -0
- tunnelprofile-0.1.0/setup.cfg +4 -0
- tunnelprofile-0.1.0/tests/data/LinB_WT.pdb +7756 -0
- tunnelprofile-0.1.0/tests/data/caverweb_tunnel.dsd +34 -0
- tunnelprofile-0.1.0/tests/data/mgltools_ligand_dbe.pdbqt +12 -0
- tunnelprofile-0.1.0/tests/data/mgltools_receptor_linb.pdbqt +3179 -0
- tunnelprofile-0.1.0/tests/test_batch.py +69 -0
- tunnelprofile-0.1.0/tests/test_cli.py +97 -0
- tunnelprofile-0.1.0/tests/test_dynamics.py +237 -0
- tunnelprofile-0.1.0/tests/test_ensemble.py +287 -0
- tunnelprofile-0.1.0/tests/test_ff_bounds.py +458 -0
- tunnelprofile-0.1.0/tests/test_geometry.py +92 -0
- tunnelprofile-0.1.0/tests/test_hetero.py +206 -0
- tunnelprofile-0.1.0/tests/test_inputs.py +166 -0
- tunnelprofile-0.1.0/tests/test_pipeline.py +110 -0
- tunnelprofile-0.1.0/tests/test_pipeline_api.py +157 -0
- tunnelprofile-0.1.0/tests/test_platform.py +106 -0
- tunnelprofile-0.1.0/tests/test_prepare.py +193 -0
- tunnelprofile-0.1.0/tests/test_real_systems.py +444 -0
- tunnelprofile-0.1.0/tests/test_reproducible.py +95 -0
- tunnelprofile-0.1.0/tests/test_scoring.py +253 -0
- tunnelprofile-0.1.0/tests/test_tunnel.py +159 -0
- tunnelprofile-0.1.0/tests/test_units.py +242 -0
- tunnelprofile-0.1.0/tests/test_viz.py +460 -0
- tunnelprofile-0.1.0/tunnelprofile/__init__.py +43 -0
- tunnelprofile-0.1.0/tunnelprofile/__main__.py +10 -0
- tunnelprofile-0.1.0/tunnelprofile/_rescore_worker.py +28 -0
- tunnelprofile-0.1.0/tunnelprofile/batch.py +363 -0
- tunnelprofile-0.1.0/tunnelprofile/cli.py +327 -0
- tunnelprofile-0.1.0/tunnelprofile/cofactor.py +545 -0
- tunnelprofile-0.1.0/tunnelprofile/dynamics.py +289 -0
- tunnelprofile-0.1.0/tunnelprofile/ensemble.py +506 -0
- tunnelprofile-0.1.0/tunnelprofile/geometry.py +254 -0
- tunnelprofile-0.1.0/tunnelprofile/lb.py +529 -0
- tunnelprofile-0.1.0/tunnelprofile/metad.py +486 -0
- tunnelprofile-0.1.0/tunnelprofile/omm.py +172 -0
- tunnelprofile-0.1.0/tunnelprofile/pipeline.py +566 -0
- tunnelprofile-0.1.0/tunnelprofile/prepare.py +1020 -0
- tunnelprofile-0.1.0/tunnelprofile/profile.py +135 -0
- tunnelprofile-0.1.0/tunnelprofile/py.typed +0 -0
- tunnelprofile-0.1.0/tunnelprofile/refine.py +1368 -0
- tunnelprofile-0.1.0/tunnelprofile/smd.py +602 -0
- tunnelprofile-0.1.0/tunnelprofile/tunnel.py +605 -0
- tunnelprofile-0.1.0/tunnelprofile/viz.py +1209 -0
- tunnelprofile-0.1.0/tunnelprofile.egg-info/PKG-INFO +507 -0
- tunnelprofile-0.1.0/tunnelprofile.egg-info/SOURCES.txt +60 -0
- tunnelprofile-0.1.0/tunnelprofile.egg-info/dependency_links.txt +1 -0
- tunnelprofile-0.1.0/tunnelprofile.egg-info/entry_points.txt +2 -0
- tunnelprofile-0.1.0/tunnelprofile.egg-info/requires.txt +17 -0
- tunnelprofile-0.1.0/tunnelprofile.egg-info/top_level.txt +2 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Miquel Estevez-Gay
|
|
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 all
|
|
13
|
+
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 THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
include LICENSE README.md environment.yml
|
|
2
|
+
recursive-include docs *.md
|
|
3
|
+
# The reference data the tests measure against: a CAVER tunnel and an MGLTools
|
|
4
|
+
# receptor cannot be regenerated without the tools this project exists to
|
|
5
|
+
# replace, so they travel with the sdist.
|
|
6
|
+
recursive-include tests/data *
|
|
7
|
+
# Benchmarks are large and reproducible from their own scripts.
|
|
8
|
+
prune benchmarks
|
|
9
|
+
prune validation
|
|
10
|
+
prune examples
|
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tunnelprofile
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Tunnel detection and ligand transport energy profiles for proteins, without license-encumbered dependencies
|
|
5
|
+
Author-email: Miquel Estevez-Gay <miquel.estevezgay@unibe.ch>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Buller-Lab/tunnelprofile
|
|
8
|
+
Project-URL: Documentation, https://github.com/Buller-Lab/tunnelprofile#documentation
|
|
9
|
+
Project-URL: Issues, https://github.com/Buller-Lab/tunnelprofile/issues
|
|
10
|
+
Keywords: protein tunnels,molecular docking,binding energy,caver,caverdock,openmm,autodock vina,computational enzymology
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Operating System :: MacOS
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: numpy>=1.24
|
|
25
|
+
Requires-Dist: scipy>=1.10
|
|
26
|
+
Provides-Extra: chem
|
|
27
|
+
Requires-Dist: rdkit>=2023.9; extra == "chem"
|
|
28
|
+
Requires-Dist: meeko>=0.6; extra == "chem"
|
|
29
|
+
Requires-Dist: vina>=1.2.5; extra == "chem"
|
|
30
|
+
Requires-Dist: gemmi>=0.6; extra == "chem"
|
|
31
|
+
Provides-Extra: plots
|
|
32
|
+
Requires-Dist: matplotlib>=3.7; extra == "plots"
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: pytest>=7.4; extra == "dev"
|
|
35
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
36
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
37
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# tunnelprofile
|
|
41
|
+
|
|
42
|
+
**Energy profiles for ligands moving through protein tunnels** — tunnel
|
|
43
|
+
detection, per-sphere docking, force-field refinement and steered MD, built
|
|
44
|
+
entirely from permissively licensed components.
|
|
45
|
+
|
|
46
|
+
It is a replacement for the CAVER / CaverDock toolchain, which is free for
|
|
47
|
+
academic use but not commercially. Everything here can be used commercially,
|
|
48
|
+
including the parts under GPL — see [Licensing](#licensing).
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from tunnelprofile import analyse
|
|
52
|
+
|
|
53
|
+
analyse("protein.pdb", ligand="BrCCBr", start=["A:108", "A:132", "A:272"],
|
|
54
|
+
methods=["tunnels", "lb", "ub"], out="results")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
One call gives you the routes, an energy profile along each, an interactive HTML
|
|
58
|
+
page and PyMOL sessions, zipped up to carry to a workstation.
|
|
59
|
+
|
|
60
|
+
## What it can do
|
|
61
|
+
|
|
62
|
+
**Find tunnels.** A clearance field, a cost-weighted shortest path, medial-axis
|
|
63
|
+
centring and spline smoothing — no CAVER installation. Validated sphere by
|
|
64
|
+
sphere against a CAVER reference on LinB, and against 10 reviewed tunnels across
|
|
65
|
+
three structures.
|
|
66
|
+
|
|
67
|
+
**Follow them through a trajectory.** A multi-model PDB is a trajectory: frames
|
|
68
|
+
are superposed on a common core, tunnels found in each, and the results
|
|
69
|
+
clustered into routes with an occupancy and one representative each. Clustering
|
|
70
|
+
is machinery, not a result — you are shown the route, not the twenty curves
|
|
71
|
+
behind it.
|
|
72
|
+
|
|
73
|
+
**Profile the cost of getting through.** Four curves, all in kcal/mol:
|
|
74
|
+
|
|
75
|
+
| | what it is |
|
|
76
|
+
|---|---|
|
|
77
|
+
| LB (Vina) | a rigid conformer ensemble docked into every sphere |
|
|
78
|
+
| LB (force field) | those poses relaxed with OpenMM, best per sphere |
|
|
79
|
+
| UB (force field) | the same, constrained to one continuous trajectory |
|
|
80
|
+
| UB (Vina rescored) | the relaxed poses put back on the docking scale |
|
|
81
|
+
|
|
82
|
+
**Check the barrier dynamically.** Steered MD (`methods=["smd"]`) pulled along
|
|
83
|
+
the tunnel, with an adaptive force that re-aims at the next sphere as the
|
|
84
|
+
ligand moves.
|
|
85
|
+
|
|
86
|
+
Well-tempered metadynamics is also implemented, on a path collective variable
|
|
87
|
+
that turns with the tunnel so the substrate stays free to rotate — but it is a
|
|
88
|
+
**library-level API, not a `methods=` option**, because a run is tens of
|
|
89
|
+
minutes and its output is a free-energy surface rather than a profile the HTML
|
|
90
|
+
page can show:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from tunnelprofile.metad import MetaDOptions, run_metadynamics
|
|
94
|
+
result = run_metadynamics(build, tunnel, start_pose_A, MetaDOptions())
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
See [Dynamics](docs/dynamics.md) for how to get `build` and `start_pose_A`, and
|
|
98
|
+
for what the numbers do and do not mean.
|
|
99
|
+
|
|
100
|
+
**Handle a real deposited structure.** Cofactors, metals, halides and disulfides
|
|
101
|
+
are kept and parameterised rather than deleted — see below.
|
|
102
|
+
|
|
103
|
+
**Screen.** Search once and reuse the routes for any number of ligands; build
|
|
104
|
+
point mutants and compare bottleneck against barrier; run a ligand library
|
|
105
|
+
across workers with the protein work done once.
|
|
106
|
+
|
|
107
|
+
**Show you the result.** One interactive HTML page per run — pick tunnel, frame,
|
|
108
|
+
ligand and method, normalise the energy axis, swap spheres for ångströms — plus
|
|
109
|
+
PyMOL sessions for the structures, the ligand poses and the steered-MD
|
|
110
|
+
trajectories, and one zip containing all of it.
|
|
111
|
+
|
|
112
|
+
### Cofactors, metals and disulfides
|
|
113
|
+
|
|
114
|
+
Deleting a cofactor opens the pocket it fills and drops the charges the
|
|
115
|
+
substrate feels going past, so nothing is deleted for want of a template.
|
|
116
|
+
Anything the protein force field cannot type is parameterised with **OpenFF
|
|
117
|
+
Sage and NAGL charges**, its chemistry taken from the PDB Chemical Component
|
|
118
|
+
Dictionary and matched to your structure by atom name. Ionisation is applied, not assumed —
|
|
119
|
+
2-oxoglutarate is deposited as the neutral diacid and used as the dianion that
|
|
120
|
+
actually chelates the iron.
|
|
121
|
+
|
|
122
|
+
A metal inside a cofactor is split out and treated non-bonded: the organic part
|
|
123
|
+
typed as though the metal were not there, the metal given the ion's own
|
|
124
|
+
Lennard-Jones parameters, and the coordination shell held by distance
|
|
125
|
+
restraints. On myoglobin that reproduces the six-coordinate iron — four pyrrole
|
|
126
|
+
nitrogens, the proximal histidine, the bound dioxygen.
|
|
127
|
+
|
|
128
|
+
Where the CCD leaves a charge blank, which it does for every metal, you have to
|
|
129
|
+
say what it is: `cofactor_charge={"HEM": -2}`. Reading a blank as neutral is how
|
|
130
|
+
a ferric heme quietly becomes something else.
|
|
131
|
+
|
|
132
|
+
Disulfides are detected and bonded; free cysteines keep their thiol hydrogen.
|
|
133
|
+
|
|
134
|
+
Details, and the two limitations that remain, in
|
|
135
|
+
[docs/cofactors.md](docs/cofactors.md).
|
|
136
|
+
|
|
137
|
+
## Install
|
|
138
|
+
|
|
139
|
+
The chemistry stack has no reliable wheels, so conda-forge is the supported way
|
|
140
|
+
in. Either solver works; `mamba` is much faster.
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
git clone https://github.com/Buller-Lab/tunnelprofile.git
|
|
144
|
+
cd tunnelprofile
|
|
145
|
+
|
|
146
|
+
mamba env create -f environment.yml # or: conda env create -f environment.yml
|
|
147
|
+
mamba activate tunnelprofile # or: conda activate tunnelprofile
|
|
148
|
+
|
|
149
|
+
pip install -e . # or: pip install tunnelprofile
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`environment.yml` pins nothing tighter than a lower bound and solves to about
|
|
153
|
+
270 packages. Check it worked:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
python -c "import tunnelprofile; print(tunnelprofile.__version__)"
|
|
157
|
+
tunnelprofile --help
|
|
158
|
+
python examples/01_tunnels_only.py
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
<details>
|
|
162
|
+
<summary>If charges warn about NAGL on Fedora or RHEL</summary>
|
|
163
|
+
|
|
164
|
+
NAGL gives AM1-BCC-quality charges and needs torch. Some conda-forge torch
|
|
165
|
+
builds ship a `libtorch_cpu.so` that asks for an executable stack, which a
|
|
166
|
+
hardened kernel refuses; openff-toolkit then reports only "NAGL is not
|
|
167
|
+
available". The run detects this and prints the fix, which is one command:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
pip install patchelf
|
|
171
|
+
patchelf --clear-execstack "$CONDA_PREFIX/lib/libtorch_cpu.so"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Without it, charges fall back to AM1-BCC (slower, needs ambertools) and then
|
|
175
|
+
to Gasteiger (a real drop in quality). The warning says which was used.
|
|
176
|
+
|
|
177
|
+
</details>
|
|
178
|
+
|
|
179
|
+
<details>
|
|
180
|
+
<summary>What the environment contains, and why each piece is there</summary>
|
|
181
|
+
|
|
182
|
+
| package | for |
|
|
183
|
+
|---|---|
|
|
184
|
+
| `numpy`, `scipy` | the tunnel search itself: clearance field, graph, clustering |
|
|
185
|
+
| `openmm`, `pdbfixer` | protein repair and protonation, the restrained minimisation, MD |
|
|
186
|
+
| `rdkit` | ligand chemistry, conformers, bond-order perception |
|
|
187
|
+
| `openff-toolkit`, `openmmforcefields` | ligand and cofactor templates |
|
|
188
|
+
| `openff-nagl` | AM1-BCC-quality charges without AmberTools |
|
|
189
|
+
| `vina`, `meeko` | docking, and the receptor/ligand PDBQT preparation |
|
|
190
|
+
| `gemmi` | mmCIF, and the Chemical Component Dictionary |
|
|
191
|
+
| `matplotlib` | the static PNG profile from the batch runner (optional) |
|
|
192
|
+
|
|
193
|
+
</details>
|
|
194
|
+
|
|
195
|
+
### No GPU?
|
|
196
|
+
|
|
197
|
+
The energy profiles run on the CPU, roughly 30x slower — the LinB example takes
|
|
198
|
+
9 minutes instead of 17 seconds. CPU is never chosen automatically, because a
|
|
199
|
+
silent drop to it is orders of magnitude slower with no visible cause. Ask for
|
|
200
|
+
it explicitly, once:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
export TUNNELPROFILE_PLATFORM=CPU
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
or per run: `--platform CPU`, or `analyse(..., platform="CPU")`. Tunnel
|
|
207
|
+
detection does not use OpenMM and is unaffected.
|
|
208
|
+
|
|
209
|
+
### Just the tunnels, without the chemistry
|
|
210
|
+
|
|
211
|
+
Tunnel detection, clustering, the HTML page and the PyMOL sessions need only
|
|
212
|
+
numpy and scipy, and nothing chemical is imported until a method asks for it:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
pip install tunnelprofile
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
That install runs [example 01](examples/01_tunnels_only.py) as-is. The energy
|
|
219
|
+
profiles need the conda environment above.
|
|
220
|
+
|
|
221
|
+
### PLUMED, for OPES only
|
|
222
|
+
|
|
223
|
+
Not needed for anything above, and note that the conda-forge package does
|
|
224
|
+
**not** currently ship the `opes` module — see [Dynamics](docs/dynamics.md):
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
mamba install -c conda-forge openmm-plumed
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Examples
|
|
231
|
+
|
|
232
|
+
Runnable, from the repository root. Full index and guidance in
|
|
233
|
+
[examples/README.md](examples/README.md).
|
|
234
|
+
|
|
235
|
+
| | | needs |
|
|
236
|
+
|---|---|---|
|
|
237
|
+
| [01_tunnels_only.py](examples/01_tunnels_only.py) | find and cluster tunnels, write the page and the PyMOL session | pip alone |
|
|
238
|
+
| [02_energy_profile.py](examples/02_energy_profile.py) | the full four-curve transport profile | full env |
|
|
239
|
+
| [03_trajectory.py](examples/03_trajectory.py) | an MD trajectory, clustered into routes with occupancies | full env |
|
|
240
|
+
| [04_reuse_tunnels.py](examples/04_reuse_tunnels.py) | search once, screen many ligands down the same route | full env |
|
|
241
|
+
| [05_cofactors_and_metals.py](examples/05_cofactors_and_metals.py) | a metalloenzyme, end to end, with nothing to configure | full env |
|
|
242
|
+
| [06_steered_md.py](examples/06_steered_md.py) | pull the ligand out and watch the protein respond | full env |
|
|
243
|
+
| [07_variant_screen.py](examples/07_variant_screen.py) | build point mutants, compare bottleneck against barrier | full env |
|
|
244
|
+
| [08_ligand_library.py](examples/08_ligand_library.py) | a ligand library across workers | full env |
|
|
245
|
+
|
|
246
|
+
Or from the command line:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
tunnelprofile analyse protein.pdb --ligand "BrCCBr" \
|
|
250
|
+
--start "A:108,A:132,A:272" --methods tunnels,lb,ub --out results
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
`analyse` and `batch` are the whole command set. `--methods` chooses what runs:
|
|
254
|
+
any of `tunnels`, `lb`, `ub`, `smd`.
|
|
255
|
+
|
|
256
|
+
## Reusing a previous run
|
|
257
|
+
|
|
258
|
+
Every run writes `tunnels.json` and keeps the prepared frames beside it, so a
|
|
259
|
+
different ligand, a different route or different settings cost only the
|
|
260
|
+
profiling:
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
tunnelprofile analyse protein.pdb --start "A:108,A:132" --methods tunnels --out run1
|
|
264
|
+
tunnelprofile analyse --tunnels run1/tunnels.json --ligand "CCBr" \
|
|
265
|
+
--methods lb,ub --tunnel 2 --out run2
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
The frames are copied into `run1/frames/` and the saved ensemble points there.
|
|
269
|
+
That is not tidiness: a tunnel is a set of coordinates, so it only means
|
|
270
|
+
anything alongside the structure it was found in. Saving the ensemble while its
|
|
271
|
+
frames sat in a scratch directory that then gets deleted produces a file that
|
|
272
|
+
loads fine and fails the moment anything touches a frame -- so the load checks,
|
|
273
|
+
and says which files are missing.
|
|
274
|
+
|
|
275
|
+
## Outputs
|
|
276
|
+
|
|
277
|
+
One directory, and one zip of it to carry to a workstation:
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
results/
|
|
281
|
+
profiles.html every profile, interactive: pick tunnel, frame, ligand, method
|
|
282
|
+
tunnels.json the routes, reusable with tunnels= (see below)
|
|
283
|
+
frames/ the prepared structures the tunnels belong to
|
|
284
|
+
structures/ always: protein, tunnel spheres, bottlenecks, view.pml
|
|
285
|
+
energies/ if lb or ub ran: the above plus the ligand pose per sphere
|
|
286
|
+
smd/ if smd ran: pulling trajectories, protein included
|
|
287
|
+
results.zip
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Each PyMOL directory has a `view.pml`; `pymol view.pml` loads that session with
|
|
291
|
+
the tunnels grouped and the representative shown. `profiles.html` is one page
|
|
292
|
+
for the whole run, not one per folder.
|
|
293
|
+
|
|
294
|
+
## Documentation
|
|
295
|
+
|
|
296
|
+
| | |
|
|
297
|
+
|---|---|
|
|
298
|
+
| [Examples](examples/README.md) | eight runnable scripts, and which to start from |
|
|
299
|
+
| [Inputs](docs/inputs.md) | structures, ligands, starting points, charges, tunnels as objects |
|
|
300
|
+
| [Cofactors, metals and disulfides](docs/cofactors.md) | Sage/NAGL parameters, the CCD, non-bonded metal centres |
|
|
301
|
+
| [How it works](docs/methods.md) | detection, the two stages, the force-field bounds, units |
|
|
302
|
+
| [Reading the results](docs/results.md) | the HTML page and the PyMOL sessions |
|
|
303
|
+
| [Dynamics](docs/dynamics.md) | steered MD, well-tempered metadynamics, the MD protocol |
|
|
304
|
+
| [Validation](docs/validation.md) | against CAVER, CaverDock, Vina and experiment |
|
|
305
|
+
| [Running it](docs/running.md) | timings, GPU, batch screening, the test suite |
|
|
306
|
+
|
|
307
|
+
## Why not CAVER / CaverDock / MGLTools
|
|
308
|
+
|
|
309
|
+
Those are free for academic use but not for commercial use. Everything here is
|
|
310
|
+
replaced with a permissive equivalent:
|
|
311
|
+
|
|
312
|
+
| role | replaced | used instead | license |
|
|
313
|
+
|---|---|---|---|
|
|
314
|
+
| tunnel detection | CAVER 3 | own implementation (`tunnel.py`) | this project |
|
|
315
|
+
| docking | — | AutoDock Vina 1.2 (Python API) | Apache-2.0 |
|
|
316
|
+
| PDBQT preparation | MGLTools / AutoDockTools | Meeko | LGPL-2.1 |
|
|
317
|
+
| protein repair, protonation | `pdb4amber` | PDBFixer + OpenMM | MIT |
|
|
318
|
+
| ligand chemistry, conformers | Open Babel | RDKit | BSD-3 |
|
|
319
|
+
| ligand and cofactor force field | GAFF via `antechamber` (GPL) | OpenFF Sage 2.2.1, typed from SMIRKS | MIT |
|
|
320
|
+
| geometry, graphs | — | numpy / scipy | BSD |
|
|
321
|
+
|
|
322
|
+
LGPL-2.1 (Meeko) and MPL-2.0 (gemmi, pulled in by Meeko) are library licenses
|
|
323
|
+
that do not impose obligations on your own code.
|
|
324
|
+
|
|
325
|
+
## Licensing
|
|
326
|
+
|
|
327
|
+
This project is MIT, **nothing in the stack restricts commercial use**, and the
|
|
328
|
+
defaults call no GPL code.
|
|
329
|
+
|
|
330
|
+
### The defaults are GPL-free, and that is tested
|
|
331
|
+
|
|
332
|
+
Ligands and cofactors are typed with **OpenFF Sage 2.2.1** from SMIRKS and
|
|
333
|
+
charged with **NAGL**, both MIT, neither needing an external program. The
|
|
334
|
+
protein is **ff14SBonlysc** (see [How it works](docs/methods.md)), which ships
|
|
335
|
+
with openmmforcefields (MIT). The suite builds WelO5 — metal, halide,
|
|
336
|
+
cosubstrate, the lot — with `antechamber` and `sqm` made unreachable, so this
|
|
337
|
+
is checked rather than claimed.
|
|
338
|
+
|
|
339
|
+
`ambertools` is **not** a dependency of this package. It will still be
|
|
340
|
+
installed in your conda environment, because `openmmforcefields` declares it,
|
|
341
|
+
and there is nothing we can do about that short of dropping openmmforcefields.
|
|
342
|
+
Installed is not invoked: the default path never runs it.
|
|
343
|
+
|
|
344
|
+
### And using it would be fine anyway
|
|
345
|
+
|
|
346
|
+
GPL restricts distribution, not use. The GPL-3 text shipped with AmberTools:
|
|
347
|
+
|
|
348
|
+
> This License explicitly affirms your **unlimited permission to run the
|
|
349
|
+
> unmodified Program**. The output from running a covered work is covered by
|
|
350
|
+
> this License only if the output, given its content, constitutes a covered
|
|
351
|
+
> work.
|
|
352
|
+
>
|
|
353
|
+
> You may make, run and propagate covered works that you do not convey,
|
|
354
|
+
> **without conditions**.
|
|
355
|
+
|
|
356
|
+
So running `antechamber` commercially carries no obligation, and charges it
|
|
357
|
+
computes are output, not a covered work. This is categorically different from
|
|
358
|
+
CAVER, CaverDock and MGLTools, which restrict *use itself* to academic
|
|
359
|
+
contexts — that restriction is what this project exists to escape, and GPL does
|
|
360
|
+
not impose it. Within AmberTools, note also that the GAFF2 parameters are
|
|
361
|
+
public domain (`dat/leap/parm/gaff2.dat`); only the programs are GPL.
|
|
362
|
+
|
|
363
|
+
The one case with an obligation is **redistribution**: put AmberTools inside a
|
|
364
|
+
container or installer you hand to someone else and you are conveying GPL-3
|
|
365
|
+
code, and must pass on its source and licence — which is public, so in practice
|
|
366
|
+
a pointer and a notice. It does not reach your own code.
|
|
367
|
+
|
|
368
|
+
### When you may still want GAFF2
|
|
369
|
+
|
|
370
|
+
Sage covers organic chemistry. It does not cover everything, and the gap is
|
|
371
|
+
easy to hit:
|
|
372
|
+
|
|
373
|
+
| | Sage 2.2.1 | GAFF2 |
|
|
374
|
+
|---|---|---|
|
|
375
|
+
| drug-like organics, cofactors, porphyrins | yes | yes |
|
|
376
|
+
| molecular oxygen (`O=O`) | **no** | yes |
|
|
377
|
+
|
|
378
|
+
On myoglobin that costs the bound dioxygen: the heme is typed and the iron
|
|
379
|
+
restrained to its four pyrrole nitrogens and the proximal histidine, but `OXY`
|
|
380
|
+
is dropped and the sixth coordination position with it. The run names the
|
|
381
|
+
component and the remedy rather than failing obscurely. To get it back:
|
|
382
|
+
|
|
383
|
+
```bash
|
|
384
|
+
mamba install -c conda-forge ambertools # already present as a transitive dep
|
|
385
|
+
```
|
|
386
|
+
```python
|
|
387
|
+
analyse(..., ligand_ff="gaff-2.11", cofactor_ff="gaff-2.11",
|
|
388
|
+
charge_method="am1bcc", cofactor_charge_method="am1bcc")
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
That is a deliberate opt-in to GPL tooling, for the reasons above.
|
|
392
|
+
|
|
393
|
+
None of this is legal advice; it is what the licence files say and how these
|
|
394
|
+
arrangements are generally understood. For a commercial deliverable, have your
|
|
395
|
+
own legal people read it.
|
|
396
|
+
|
|
397
|
+
## Known limitations
|
|
398
|
+
|
|
399
|
+
* GBn2 implicit solvent, not explicit water. Adequate for ranking; not a free
|
|
400
|
+
energy. No water-mediated hydrogen bonds, and no real viscosity, so egress
|
|
401
|
+
kinetics from the dynamics modules are not physical.
|
|
402
|
+
* The force-field barrier is **pose-sampling limited**: repeating the profile
|
|
403
|
+
with different docking seeds moves the upper bound by +/- 6 kcal/mol, and
|
|
404
|
+
raising the pose budget from `seeds=16, keep_top=1` to `seeds=32, keep_top=3`
|
|
405
|
+
does not fix it. Treat a single force-field barrier as an estimate, not a
|
|
406
|
+
measurement. This dominates every other uncertainty in stage 2, including the
|
|
407
|
+
GB cutoff, which was checked and cleared.
|
|
408
|
+
* Freezing protein atoms does not speed up MD — OpenMM still evaluates their
|
|
409
|
+
forces. `--mobile-radius` and `--rigid-protein` control accuracy and
|
|
410
|
+
stability, not cost.
|
|
411
|
+
* The metadynamics barrier on LinB (25.35 +/- 3.89 kcal/mol) **exceeds the
|
|
412
|
+
+16.4 kcal/mol ceiling that kcat allows**, and the PMF does not bind the
|
|
413
|
+
substrate at all. The restrained pocket cannot open its 1.33 A bottleneck for
|
|
414
|
+
a ligand needing 2.2-2.5 A. A larger mobile shell and softer backbone
|
|
415
|
+
restraints are the untested next step; until then read these barriers as a
|
|
416
|
+
property of the model.
|
|
417
|
+
* Metadynamics transitions are one-way here (0.6 +/- 0.5 recrossings per 10 ns
|
|
418
|
+
walker), so the reweighted free energy has no statistics at the barrier and
|
|
419
|
+
only the bias-inversion estimate is usable.
|
|
420
|
+
* SMD forward and reverse work distributions overlap poorly, so BAR carries a
|
|
421
|
+
large uncertainty that is not yet computed.
|
|
422
|
+
* Only one system, one ligand and one tunnel have been run this way.
|
|
423
|
+
* OPES is implemented but unusable: the installed PLUMED has no `opes` module.
|
|
424
|
+
* Tunnel detection is validated quantitatively against one CAVER reference
|
|
425
|
+
(LinB WT) plus a functional check on L177W. More reference tunnels would
|
|
426
|
+
strengthen this.
|
|
427
|
+
* Multiple-tunnel enumeration is now checked against 10 reviewed tunnels on
|
|
428
|
+
three LinB structures, but all three are the same fold; other folds are
|
|
429
|
+
untested.
|
|
430
|
+
* Auxiliary tunnels narrower than the probe are invisible by construction — see
|
|
431
|
+
the probe discussion above before trusting a tunnel count.
|
|
432
|
+
* In the whole-box search test the ensemble often finds a *different* pose at
|
|
433
|
+
similar energy (RMSD 1.3–3.7 Å) until the seed budget is large. Inside a
|
|
434
|
+
sphere this matters much less, but raise `--seeds` for unusually large or
|
|
435
|
+
flexible ligands.
|
|
436
|
+
* NAGL charges fall back to AM1-BCC via AmberTools when torch is unavailable;
|
|
437
|
+
`--charge-method gasteiger` is the fast, less accurate option.
|
|
438
|
+
* Stage 2 energies are interaction energies, not potentials of mean force. Use
|
|
439
|
+
them to compare positions along one tunnel, not to compare ligands.
|
|
440
|
+
* Meeko cannot build a receptor template for some cofactors -- a heme is one --
|
|
441
|
+
so those structures get no docking. The run falls back to force-field
|
|
442
|
+
profiles from geometric starting poses and says so; see
|
|
443
|
+
[Cofactors](docs/cofactors.md).
|
|
444
|
+
* A metal inside a cofactor is treated non-bonded: no charge transfer, no
|
|
445
|
+
covalency, and the coordination geometry is held where it was deposited
|
|
446
|
+
rather than derived.
|
|
447
|
+
|
|
448
|
+
## Continuous integration
|
|
449
|
+
|
|
450
|
+
Every push runs `lint` and `minimal-install` (3.10, 3.11, 3.12) — about a
|
|
451
|
+
minute, and the second one is the guard that matters most: it proves the
|
|
452
|
+
package still works from `pip` alone, which one stray top-level import would
|
|
453
|
+
break invisibly.
|
|
454
|
+
|
|
455
|
+
The chemistry suite runs **weekly and on demand**, not per push. GitHub's
|
|
456
|
+
runners have no GPU, the energy tests are roughly 30x slower on the CPU
|
|
457
|
+
platform, and even the subset marked "not slow" was still going after an hour.
|
|
458
|
+
Run it by hand from *Actions → tests → Run workflow* when a change touches the
|
|
459
|
+
chemistry, and locally with `pytest -q` before a release — which
|
|
460
|
+
`scripts/release.sh` does for you.
|
|
461
|
+
|
|
462
|
+
## Releasing
|
|
463
|
+
|
|
464
|
+
The version lives in one place, `tunnelprofile/__init__.py`; `pyproject.toml`
|
|
465
|
+
reads it. One command does the rest:
|
|
466
|
+
|
|
467
|
+
```bash
|
|
468
|
+
./scripts/release.sh 0.2.0 --dry # checks and builds, changes nothing
|
|
469
|
+
./scripts/release.sh 0.2.0 # bumps, tests, tags, pushes
|
|
470
|
+
gh release create v0.2.0 --generate-notes
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
Publishing the GitHub release triggers `.github/workflows/publish.yml`, which
|
|
474
|
+
uploads to PyPI over **Trusted Publishing** — no API token stored in the
|
|
475
|
+
repository or in Actions secrets. Configure that once at
|
|
476
|
+
<https://pypi.org/manage/account/publishing/>:
|
|
477
|
+
|
|
478
|
+
| field | value |
|
|
479
|
+
|---|---|
|
|
480
|
+
| PyPI project | `tunnelprofile` |
|
|
481
|
+
| Owner | `Buller-Lab` |
|
|
482
|
+
| Repository | `tunnelprofile` |
|
|
483
|
+
| Workflow | `publish.yml` |
|
|
484
|
+
| Environment | `pypi` |
|
|
485
|
+
|
|
486
|
+
To rehearse against TestPyPI first — worth doing, because **a version number on
|
|
487
|
+
PyPI can never be reused**:
|
|
488
|
+
|
|
489
|
+
```bash
|
|
490
|
+
export TWINE_PASSWORD='pypi-...' # a TestPyPI token
|
|
491
|
+
./scripts/release.sh 0.2.0 --test
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
The script refuses to run on a dirty tree, off `main`, with a version that is
|
|
495
|
+
already tagged, or with one already on PyPI.
|
|
496
|
+
|
|
497
|
+
## Citing and contributing
|
|
498
|
+
|
|
499
|
+
Issues and pull requests welcome at
|
|
500
|
+
<https://github.com/Buller-Lab/tunnelprofile>. If you use this in published work,
|
|
501
|
+
cite the repository and the tools it stands on: AutoDock Vina, OpenMM, RDKit,
|
|
502
|
+
Meeko, PDBFixer, OpenFF and AmberTools.
|
|
503
|
+
|
|
504
|
+
## License
|
|
505
|
+
|
|
506
|
+
MIT — see [LICENSE](LICENSE). Read [Licensing](#licensing) above for what the
|
|
507
|
+
dependencies imply.
|