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.
Files changed (62) hide show
  1. tunnelprofile-0.1.0/LICENSE +21 -0
  2. tunnelprofile-0.1.0/MANIFEST.in +10 -0
  3. tunnelprofile-0.1.0/PKG-INFO +507 -0
  4. tunnelprofile-0.1.0/README.md +468 -0
  5. tunnelprofile-0.1.0/docs/cofactors.md +195 -0
  6. tunnelprofile-0.1.0/docs/dynamics.md +603 -0
  7. tunnelprofile-0.1.0/docs/inputs.md +324 -0
  8. tunnelprofile-0.1.0/docs/methods.md +404 -0
  9. tunnelprofile-0.1.0/docs/results.md +165 -0
  10. tunnelprofile-0.1.0/docs/running.md +135 -0
  11. tunnelprofile-0.1.0/docs/validation.md +390 -0
  12. tunnelprofile-0.1.0/environment.yml +38 -0
  13. tunnelprofile-0.1.0/pyproject.toml +93 -0
  14. tunnelprofile-0.1.0/setup.cfg +4 -0
  15. tunnelprofile-0.1.0/tests/data/LinB_WT.pdb +7756 -0
  16. tunnelprofile-0.1.0/tests/data/caverweb_tunnel.dsd +34 -0
  17. tunnelprofile-0.1.0/tests/data/mgltools_ligand_dbe.pdbqt +12 -0
  18. tunnelprofile-0.1.0/tests/data/mgltools_receptor_linb.pdbqt +3179 -0
  19. tunnelprofile-0.1.0/tests/test_batch.py +69 -0
  20. tunnelprofile-0.1.0/tests/test_cli.py +97 -0
  21. tunnelprofile-0.1.0/tests/test_dynamics.py +237 -0
  22. tunnelprofile-0.1.0/tests/test_ensemble.py +287 -0
  23. tunnelprofile-0.1.0/tests/test_ff_bounds.py +458 -0
  24. tunnelprofile-0.1.0/tests/test_geometry.py +92 -0
  25. tunnelprofile-0.1.0/tests/test_hetero.py +206 -0
  26. tunnelprofile-0.1.0/tests/test_inputs.py +166 -0
  27. tunnelprofile-0.1.0/tests/test_pipeline.py +110 -0
  28. tunnelprofile-0.1.0/tests/test_pipeline_api.py +157 -0
  29. tunnelprofile-0.1.0/tests/test_platform.py +106 -0
  30. tunnelprofile-0.1.0/tests/test_prepare.py +193 -0
  31. tunnelprofile-0.1.0/tests/test_real_systems.py +444 -0
  32. tunnelprofile-0.1.0/tests/test_reproducible.py +95 -0
  33. tunnelprofile-0.1.0/tests/test_scoring.py +253 -0
  34. tunnelprofile-0.1.0/tests/test_tunnel.py +159 -0
  35. tunnelprofile-0.1.0/tests/test_units.py +242 -0
  36. tunnelprofile-0.1.0/tests/test_viz.py +460 -0
  37. tunnelprofile-0.1.0/tunnelprofile/__init__.py +43 -0
  38. tunnelprofile-0.1.0/tunnelprofile/__main__.py +10 -0
  39. tunnelprofile-0.1.0/tunnelprofile/_rescore_worker.py +28 -0
  40. tunnelprofile-0.1.0/tunnelprofile/batch.py +363 -0
  41. tunnelprofile-0.1.0/tunnelprofile/cli.py +327 -0
  42. tunnelprofile-0.1.0/tunnelprofile/cofactor.py +545 -0
  43. tunnelprofile-0.1.0/tunnelprofile/dynamics.py +289 -0
  44. tunnelprofile-0.1.0/tunnelprofile/ensemble.py +506 -0
  45. tunnelprofile-0.1.0/tunnelprofile/geometry.py +254 -0
  46. tunnelprofile-0.1.0/tunnelprofile/lb.py +529 -0
  47. tunnelprofile-0.1.0/tunnelprofile/metad.py +486 -0
  48. tunnelprofile-0.1.0/tunnelprofile/omm.py +172 -0
  49. tunnelprofile-0.1.0/tunnelprofile/pipeline.py +566 -0
  50. tunnelprofile-0.1.0/tunnelprofile/prepare.py +1020 -0
  51. tunnelprofile-0.1.0/tunnelprofile/profile.py +135 -0
  52. tunnelprofile-0.1.0/tunnelprofile/py.typed +0 -0
  53. tunnelprofile-0.1.0/tunnelprofile/refine.py +1368 -0
  54. tunnelprofile-0.1.0/tunnelprofile/smd.py +602 -0
  55. tunnelprofile-0.1.0/tunnelprofile/tunnel.py +605 -0
  56. tunnelprofile-0.1.0/tunnelprofile/viz.py +1209 -0
  57. tunnelprofile-0.1.0/tunnelprofile.egg-info/PKG-INFO +507 -0
  58. tunnelprofile-0.1.0/tunnelprofile.egg-info/SOURCES.txt +60 -0
  59. tunnelprofile-0.1.0/tunnelprofile.egg-info/dependency_links.txt +1 -0
  60. tunnelprofile-0.1.0/tunnelprofile.egg-info/entry_points.txt +2 -0
  61. tunnelprofile-0.1.0/tunnelprofile.egg-info/requires.txt +17 -0
  62. 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.