chemur 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.
- chemur-0.1.0/.gitignore +29 -0
- chemur-0.1.0/CMakeLists.txt +14 -0
- chemur-0.1.0/LICENSE +21 -0
- chemur-0.1.0/PKG-INFO +269 -0
- chemur-0.1.0/README.md +225 -0
- chemur-0.1.0/cpp/chemur_core.cpp +365 -0
- chemur-0.1.0/docs/chemistry.md +68 -0
- chemur-0.1.0/docs/cli.md +138 -0
- chemur-0.1.0/pyproject.toml +132 -0
- chemur-0.1.0/src/chemur/__init__.py +34 -0
- chemur-0.1.0/src/chemur/__main__.py +5 -0
- chemur-0.1.0/src/chemur/_fallback_core.py +235 -0
- chemur-0.1.0/src/chemur/api.py +359 -0
- chemur-0.1.0/src/chemur/assignment.py +76 -0
- chemur-0.1.0/src/chemur/ccd.py +150 -0
- chemur-0.1.0/src/chemur/chemistry.py +557 -0
- chemur-0.1.0/src/chemur/cli.py +603 -0
- chemur-0.1.0/src/chemur/core.py +49 -0
- chemur-0.1.0/src/chemur/cosplif.py +1827 -0
- chemur-0.1.0/src/chemur/errors.py +15 -0
- chemur-0.1.0/src/chemur/features.py +441 -0
- chemur-0.1.0/src/chemur/ifm_config.py +239 -0
- chemur-0.1.0/src/chemur/ifm_matcher.py +2399 -0
- chemur-0.1.0/src/chemur/ifm_models.py +124 -0
- chemur-0.1.0/src/chemur/ifm_reporting.py +46 -0
- chemur-0.1.0/src/chemur/ifm_scoring.py +159 -0
- chemur-0.1.0/src/chemur/interaction_types.py +243 -0
- chemur-0.1.0/src/chemur/interactions.py +1184 -0
- chemur-0.1.0/src/chemur/models.py +364 -0
- chemur-0.1.0/src/chemur/parser.py +436 -0
- chemur-0.1.0/src/chemur/profile.py +230 -0
- chemur-0.1.0/src/chemur/profiles/__init__.py +2 -0
- chemur-0.1.0/src/chemur/profiles/default.yaml +184 -0
- chemur-0.1.0/src/chemur/protonation.py +81 -0
- chemur-0.1.0/src/chemur/scoring.py +241 -0
- chemur-0.1.0/src/chemur/sdf.py +267 -0
- chemur-0.1.0/src/chemur/trajectory.py +569 -0
- chemur-0.1.0/tests/test_assignment.py +70 -0
- chemur-0.1.0/tests/test_candidate_generation.py +179 -0
- chemur-0.1.0/tests/test_ccd.py +22 -0
- chemur-0.1.0/tests/test_cli_cutoffs.py +14 -0
- chemur-0.1.0/tests/test_cli_split_defaults.py +77 -0
- chemur-0.1.0/tests/test_core_geometry.py +84 -0
- chemur-0.1.0/tests/test_ligand_smiles.py +192 -0
- chemur-0.1.0/tests/test_new_interactions.py +682 -0
- chemur-0.1.0/tests/test_profile_consistency.py +118 -0
- chemur-0.1.0/tests/test_protonation.py +39 -0
- chemur-0.1.0/tests/test_scoring.py +138 -0
- chemur-0.1.0/tests/test_sdf_ligands.py +57 -0
- chemur-0.1.0/tests/test_split_by_ligand.py +44 -0
- chemur-0.1.0/tests/test_trajectory.py +109 -0
chemur-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*.so
|
|
4
|
+
*.pyd
|
|
5
|
+
.pytest_cache/
|
|
6
|
+
.mypy_cache/
|
|
7
|
+
.ruff_cache/
|
|
8
|
+
build/
|
|
9
|
+
dist/
|
|
10
|
+
wheelhouse/
|
|
11
|
+
*.egg-info/
|
|
12
|
+
_skbuild/
|
|
13
|
+
test_data/
|
|
14
|
+
wheels/
|
|
15
|
+
*.whl
|
|
16
|
+
*.tar.gz
|
|
17
|
+
.venv/
|
|
18
|
+
venv/
|
|
19
|
+
.DS_Store
|
|
20
|
+
.idea/
|
|
21
|
+
.vscode/
|
|
22
|
+
.coverage
|
|
23
|
+
htmlcov/
|
|
24
|
+
|
|
25
|
+
# Manuscript material lives outside the repo (~/Documents/chemur_paper)
|
|
26
|
+
paper/
|
|
27
|
+
|
|
28
|
+
# Default --split-by-ligand-dir for `chemur analyze`; generated output, never source.
|
|
29
|
+
ligand_outputs/
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.18)
|
|
2
|
+
project(chemur_core LANGUAGES CXX)
|
|
3
|
+
|
|
4
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
5
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
6
|
+
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
7
|
+
|
|
8
|
+
find_package(pybind11 CONFIG REQUIRED)
|
|
9
|
+
|
|
10
|
+
pybind11_add_module(_chemur_core cpp/chemur_core.cpp)
|
|
11
|
+
target_compile_features(_chemur_core PRIVATE cxx_std_17)
|
|
12
|
+
|
|
13
|
+
install(TARGETS _chemur_core LIBRARY DESTINATION chemur)
|
|
14
|
+
|
chemur-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Aaron Sweeney
|
|
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.
|
chemur-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: chemur
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Detect non-covalent interactions between proteins, nucleic acids, ligands and metals in PDB/mmCIF structures, with a Python API, a CLI, and a C++ geometry core.
|
|
5
|
+
Keywords: structural-biology,molecular-interactions,protein-ligand,protein-protein,nucleic-acids,hydrogen-bond,cheminformatics,mmcif
|
|
6
|
+
Author-Email: Aaron Sweeney <ucbtasw@ucl.ac.uk>
|
|
7
|
+
Maintainer-Email: Aaron Sweeney <ucbtasw@ucl.ac.uk>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
14
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
+
Classifier: Programming Language :: C++
|
|
16
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
23
|
+
Project-URL: Homepage, https://github.com/SweeneyAaron/chemur
|
|
24
|
+
Project-URL: Source, https://github.com/SweeneyAaron/chemur
|
|
25
|
+
Project-URL: Issues, https://github.com/SweeneyAaron/chemur/issues
|
|
26
|
+
Project-URL: ChimeraX plugin, https://github.com/SweeneyAaron/chimerax-chemur
|
|
27
|
+
Requires-Python: >=3.10
|
|
28
|
+
Requires-Dist: dimorphite_dl>=2
|
|
29
|
+
Requires-Dist: gemmi>=0.6
|
|
30
|
+
Requires-Dist: numpy>=1.23
|
|
31
|
+
Requires-Dist: PyYAML>=6
|
|
32
|
+
Requires-Dist: rdkit>=2023.9
|
|
33
|
+
Provides-Extra: protonation
|
|
34
|
+
Provides-Extra: trajectory
|
|
35
|
+
Requires-Dist: MDAnalysis>=2.4; extra == "trajectory"
|
|
36
|
+
Provides-Extra: dataframe
|
|
37
|
+
Requires-Dist: pandas>=1.5; extra == "dataframe"
|
|
38
|
+
Provides-Extra: all
|
|
39
|
+
Requires-Dist: chemur[dataframe,protonation,trajectory]; extra == "all"
|
|
40
|
+
Provides-Extra: test
|
|
41
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
42
|
+
Requires-Dist: chemur[dataframe]; extra == "test"
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
|
|
45
|
+
# Chemur
|
|
46
|
+
|
|
47
|
+
[](https://pypi.org/project/chemur/)
|
|
48
|
+
[](https://pypi.org/project/chemur/)
|
|
49
|
+
[](LICENSE)
|
|
50
|
+
|
|
51
|
+
Find the non-covalent interactions in a PDB or mmCIF structure — between proteins,
|
|
52
|
+
nucleic acids, ligands, metals and solvent, in any combination.
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install chemur
|
|
56
|
+
chemur analyze structure.cif --out interactions.json
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- **22 interaction types, each with defined geometry**
|
|
60
|
+
- **Any pair of components.** Protein–ligand, protein–protein, protein–DNA/RNA,
|
|
61
|
+
nucleic acid–ligand, ligand–ligand. Nothing is hard-coded to expect a receptor and
|
|
62
|
+
a small molecule.
|
|
63
|
+
- **Chemistry from templates, geometry from coordinates.** Ligands are typed from
|
|
64
|
+
SMILES, an SDF, or an automatic Chemical Component Dictionary lookup.
|
|
65
|
+
- **MD trajectories** — per-frame analysis with occupancy and time series.
|
|
66
|
+
|
|
67
|
+
A [ChimeraX plugin](https://github.com/SweeneyAaron/chimerax-chemur) builds on this
|
|
68
|
+
library for interactive 3D visualisation.
|
|
69
|
+
|
|
70
|
+
## Install
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pip install chemur
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Wheels are published for CPython 3.10–3.13 on Linux x86_64, macOS (a single
|
|
77
|
+
universal2 build covering Intel and Apple Silicon) and Windows x86_64. Other
|
|
78
|
+
platforms build from the source distribution and need a C++17 compiler and CMake ≥ 3.18.
|
|
79
|
+
|
|
80
|
+
| Extra | Installs | Enables |
|
|
81
|
+
| --- | --- | --- |
|
|
82
|
+
| `trajectory` | `MDAnalysis` | reading trajectory files |
|
|
83
|
+
| `dataframe` | `pandas` | `AnalysisResult.to_dataframe()` |
|
|
84
|
+
| `all` | both | |
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
pip install "chemur[all]"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
pH-range ligand protonation (`--protonate`) needs no extra — `dimorphite_dl` is a hard
|
|
91
|
+
dependency. It requires `rdkit<2026`, so a Chemur install is capped there too.
|
|
92
|
+
|
|
93
|
+
> `MDAnalysis` is LGPL-3.0-or-later (it relicensed from GPL at 2.8.0; the `>=2.4` floor
|
|
94
|
+
> still permits older GPL-licensed releases if you pin one). Chemur itself is MIT and
|
|
95
|
+
> neither bundles nor links it, but installing the `trajectory` extra adds
|
|
96
|
+
> copyleft-licensed code to your environment.
|
|
97
|
+
|
|
98
|
+
To confirm you got the compiled core rather than the fallback:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
python -c "from chemur.core import USING_CPP_CORE; print('C++ core:', USING_CPP_CORE)"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`True` is expected. `False` means the pure-Python fallback loaded — correct results,
|
|
105
|
+
10–100× slower. From a wheel that should never happen; from a source build it means
|
|
106
|
+
CMake or the compiler failed. Set `CHEMUR_FORCE_PYTHON_CORE=1` to select it deliberately.
|
|
107
|
+
|
|
108
|
+
## Quick start
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
import chemur
|
|
112
|
+
|
|
113
|
+
result = chemur.analyze("structure.cif")
|
|
114
|
+
|
|
115
|
+
for interaction in result.interactions:
|
|
116
|
+
print(interaction.interaction_type, interaction.component_ids)
|
|
117
|
+
|
|
118
|
+
result.to_json("interactions.json")
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
chemur analyze structure.cif --out interactions.json --csv interactions.csv
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Any biomolecule, not just protein–ligand
|
|
126
|
+
|
|
127
|
+
`analyze` returns **every** interaction it finds in the structure. There is no receptor
|
|
128
|
+
or ligand role — you pick out the ones you want by component.
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
import chemur
|
|
132
|
+
from collections import Counter
|
|
133
|
+
|
|
134
|
+
result = chemur.analyze("complex.cif")
|
|
135
|
+
|
|
136
|
+
# What was found, and between what?
|
|
137
|
+
print(Counter(i.interaction_type for i in result.interactions))
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
A protein–DNA interface, a protein–protein interface and a ligand binding site are all
|
|
141
|
+
the same query — filter on the components involved:
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
def between(result, a, b):
|
|
145
|
+
"""Interactions with one atom in component `a` and the other in `b`."""
|
|
146
|
+
return [
|
|
147
|
+
i for i in result.interactions
|
|
148
|
+
if {a, b} <= set(i.component_ids)
|
|
149
|
+
]
|
|
150
|
+
|
|
151
|
+
interface = between(result, "A:ARG:145", "B:DG:12") # protein side chain to a base
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Components are identified by `component_id`; `result.components` lists them all with
|
|
155
|
+
their names, so you can select a chain, a residue range, or a single ligand. Nucleic
|
|
156
|
+
acid phosphate backbones are perceived as anions, protein Arg/Lys as cations and
|
|
157
|
+
Asp/Glu as carboxylate anions, so salt bridges and cation–π across a protein–nucleic
|
|
158
|
+
acid interface are detected the same way as in a binding site.
|
|
159
|
+
|
|
160
|
+
## What it detects
|
|
161
|
+
|
|
162
|
+
| Family | Types |
|
|
163
|
+
| --- | --- |
|
|
164
|
+
| Hydrogen bonding | `hbond`, `weak_hbond`, `hbond_pi`, `solvent_bridge`, `amide_bridge` |
|
|
165
|
+
| Electrostatic | `salt_bridge`, `metal_coordination`, `cation_pi`, `anion_pi`, `anion_aromatic_edge` |
|
|
166
|
+
| Stacking | `pipi_stack`, `aliphatic_pi_stack`, `aliphatic_stack`, `amide_pi`, `ch_pi` |
|
|
167
|
+
| σ-hole | `halogen_bond`, `chalcogen_bond`, `tetrel_bond`, `halogen_pi`, `chalcogen_pi` |
|
|
168
|
+
| Other | `n_pi_star`, `hydrophobic` |
|
|
169
|
+
|
|
170
|
+
`aliphatic_stack` (saturated–saturated ring stacking) ships disabled; enable it in the
|
|
171
|
+
profile. The σ-hole, stacking and n→π\* geometries follow
|
|
172
|
+
[Adhav & Saikrishnan, *ACS Omega* **2023**, 8, 22268](https://doi.org/10.1021/acsomega.3c00205).
|
|
173
|
+
|
|
174
|
+
Each type has its own geometric criteria, all adjustable — see
|
|
175
|
+
[docs/cli.md](docs/cli.md) for overriding cutoffs and [docs/chemistry.md](docs/chemistry.md)
|
|
176
|
+
for the chemical gates (such as why an ordinary Met sulfur cannot donate a chalcogen bond).
|
|
177
|
+
|
|
178
|
+
## Ligand chemistry
|
|
179
|
+
|
|
180
|
+
Ligands need a chemical template so protonation, charge, aromaticity and
|
|
181
|
+
donor/acceptor status are correct. Chemur takes one from, in order of precedence:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
chemur analyze structure.cif --ligand-smiles LIG='CC(=O)N' # explicit SMILES
|
|
185
|
+
chemur analyze receptor.pdb --ligand-sdf docked.sdf # an SDF (coordinates too)
|
|
186
|
+
chemur analyze structure.cif # automatic CCD lookup
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
The automatic lookup resolves each ligand by its component name against the RCSB
|
|
190
|
+
Chemical Component Dictionary. Add `--protonate` to set the protonation state for a pH
|
|
191
|
+
range with Dimorphite-DL, and `--debug` to print the SMILES actually used.
|
|
192
|
+
|
|
193
|
+
Full detail in [docs/cli.md](docs/cli.md).
|
|
194
|
+
|
|
195
|
+
## Multiple ligands and docking output
|
|
196
|
+
|
|
197
|
+
Pass several ligands at once, or point at a directory of sdf files.
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
chemur analyze receptor.pdb --ligand-sdf a.sdf --ligand-sdf b.sdf # repeatable
|
|
201
|
+
chemur analyze receptor.pdb --ligand-sdf-dir poses/ # a whole directory
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
By default all supplied ligands are added to the structure and analysed **together**, as
|
|
205
|
+
one system — right for a cofactor plus a substrate, or two ligands sharing a pocket.
|
|
206
|
+
|
|
207
|
+
Docked poses are the opposite case: each is an alternative for the *same* site, so
|
|
208
|
+
analysing them together would stack overlapping copies into one pocket. Use `--batch` to
|
|
209
|
+
analyse each ligand independently against the same receptor:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
chemur analyze receptor.pdb --ligand-sdf-dir poses/ --batch --out all_poses.json
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Either way you also get one filtered file per ligand under `ligand_outputs/` — in batch
|
|
216
|
+
mode under a subdirectory per pose — while `--out` / `--csv` write the aggregate.
|
|
217
|
+
|
|
218
|
+
SDF coordinates are used directly, and ligand residues already present in the structure
|
|
219
|
+
are skipped so the SDF stays authoritative.
|
|
220
|
+
|
|
221
|
+
## Trajectories
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
pip install "chemur[trajectory]"
|
|
225
|
+
chemur trajectory topology.pdb trajectory.xtc --out frames.json
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Analyses each frame and reports per-interaction occupancy and time series.
|
|
229
|
+
|
|
230
|
+
## Documentation
|
|
231
|
+
|
|
232
|
+
- [docs/cli.md](docs/cli.md) — full command-line reference
|
|
233
|
+
- [docs/chemistry.md](docs/chemistry.md) — templates, hydrogen policy, σ-hole activation, profiles
|
|
234
|
+
|
|
235
|
+
## Development
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
git clone https://github.com/SweeneyAaron/chemur
|
|
239
|
+
cd chemur
|
|
240
|
+
|
|
241
|
+
conda create -n chemur-dev -c conda-forge \
|
|
242
|
+
python=3.11 rdkit gemmi numpy pyyaml pandas pytest \
|
|
243
|
+
cmake ninja pybind11 scikit-build-core cxx-compiler
|
|
244
|
+
conda activate chemur-dev
|
|
245
|
+
|
|
246
|
+
pip install -e ".[test,all]" -v
|
|
247
|
+
pytest
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
On macOS you need the Apple command line tools (`xcode-select --install`). If the build
|
|
251
|
+
fails with `'cstddef' file not found` they are incomplete — repair with
|
|
252
|
+
`sudo rm -rf /Library/Developer/CommandLineTools && xcode-select --install`.
|
|
253
|
+
|
|
254
|
+
This project uses a `src/` layout and has no `conftest.py` on purpose, so `pytest` always
|
|
255
|
+
exercises the *installed* package rather than the source tree. That is what makes the
|
|
256
|
+
wheel-level checks in CI meaningful.
|
|
257
|
+
|
|
258
|
+
## License
|
|
259
|
+
|
|
260
|
+
MIT — see [LICENSE](LICENSE).
|
|
261
|
+
|
|
262
|
+
## Citation
|
|
263
|
+
|
|
264
|
+
A manuscript is in preparation. Until then, please cite the repository:
|
|
265
|
+
|
|
266
|
+
```
|
|
267
|
+
Sweeney, A, Genz, L, Topf, M. Chemur: biomolecular interaction detection.
|
|
268
|
+
https://github.com/SweeneyAaron/chemur
|
|
269
|
+
```
|
chemur-0.1.0/README.md
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# Chemur
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/chemur/)
|
|
4
|
+
[](https://pypi.org/project/chemur/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
Find the non-covalent interactions in a PDB or mmCIF structure — between proteins,
|
|
8
|
+
nucleic acids, ligands, metals and solvent, in any combination.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pip install chemur
|
|
12
|
+
chemur analyze structure.cif --out interactions.json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- **22 interaction types, each with defined geometry**
|
|
16
|
+
- **Any pair of components.** Protein–ligand, protein–protein, protein–DNA/RNA,
|
|
17
|
+
nucleic acid–ligand, ligand–ligand. Nothing is hard-coded to expect a receptor and
|
|
18
|
+
a small molecule.
|
|
19
|
+
- **Chemistry from templates, geometry from coordinates.** Ligands are typed from
|
|
20
|
+
SMILES, an SDF, or an automatic Chemical Component Dictionary lookup.
|
|
21
|
+
- **MD trajectories** — per-frame analysis with occupancy and time series.
|
|
22
|
+
|
|
23
|
+
A [ChimeraX plugin](https://github.com/SweeneyAaron/chimerax-chemur) builds on this
|
|
24
|
+
library for interactive 3D visualisation.
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install chemur
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Wheels are published for CPython 3.10–3.13 on Linux x86_64, macOS (a single
|
|
33
|
+
universal2 build covering Intel and Apple Silicon) and Windows x86_64. Other
|
|
34
|
+
platforms build from the source distribution and need a C++17 compiler and CMake ≥ 3.18.
|
|
35
|
+
|
|
36
|
+
| Extra | Installs | Enables |
|
|
37
|
+
| --- | --- | --- |
|
|
38
|
+
| `trajectory` | `MDAnalysis` | reading trajectory files |
|
|
39
|
+
| `dataframe` | `pandas` | `AnalysisResult.to_dataframe()` |
|
|
40
|
+
| `all` | both | |
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install "chemur[all]"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
pH-range ligand protonation (`--protonate`) needs no extra — `dimorphite_dl` is a hard
|
|
47
|
+
dependency. It requires `rdkit<2026`, so a Chemur install is capped there too.
|
|
48
|
+
|
|
49
|
+
> `MDAnalysis` is LGPL-3.0-or-later (it relicensed from GPL at 2.8.0; the `>=2.4` floor
|
|
50
|
+
> still permits older GPL-licensed releases if you pin one). Chemur itself is MIT and
|
|
51
|
+
> neither bundles nor links it, but installing the `trajectory` extra adds
|
|
52
|
+
> copyleft-licensed code to your environment.
|
|
53
|
+
|
|
54
|
+
To confirm you got the compiled core rather than the fallback:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
python -c "from chemur.core import USING_CPP_CORE; print('C++ core:', USING_CPP_CORE)"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`True` is expected. `False` means the pure-Python fallback loaded — correct results,
|
|
61
|
+
10–100× slower. From a wheel that should never happen; from a source build it means
|
|
62
|
+
CMake or the compiler failed. Set `CHEMUR_FORCE_PYTHON_CORE=1` to select it deliberately.
|
|
63
|
+
|
|
64
|
+
## Quick start
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
import chemur
|
|
68
|
+
|
|
69
|
+
result = chemur.analyze("structure.cif")
|
|
70
|
+
|
|
71
|
+
for interaction in result.interactions:
|
|
72
|
+
print(interaction.interaction_type, interaction.component_ids)
|
|
73
|
+
|
|
74
|
+
result.to_json("interactions.json")
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
chemur analyze structure.cif --out interactions.json --csv interactions.csv
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Any biomolecule, not just protein–ligand
|
|
82
|
+
|
|
83
|
+
`analyze` returns **every** interaction it finds in the structure. There is no receptor
|
|
84
|
+
or ligand role — you pick out the ones you want by component.
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
import chemur
|
|
88
|
+
from collections import Counter
|
|
89
|
+
|
|
90
|
+
result = chemur.analyze("complex.cif")
|
|
91
|
+
|
|
92
|
+
# What was found, and between what?
|
|
93
|
+
print(Counter(i.interaction_type for i in result.interactions))
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
A protein–DNA interface, a protein–protein interface and a ligand binding site are all
|
|
97
|
+
the same query — filter on the components involved:
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
def between(result, a, b):
|
|
101
|
+
"""Interactions with one atom in component `a` and the other in `b`."""
|
|
102
|
+
return [
|
|
103
|
+
i for i in result.interactions
|
|
104
|
+
if {a, b} <= set(i.component_ids)
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
interface = between(result, "A:ARG:145", "B:DG:12") # protein side chain to a base
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Components are identified by `component_id`; `result.components` lists them all with
|
|
111
|
+
their names, so you can select a chain, a residue range, or a single ligand. Nucleic
|
|
112
|
+
acid phosphate backbones are perceived as anions, protein Arg/Lys as cations and
|
|
113
|
+
Asp/Glu as carboxylate anions, so salt bridges and cation–π across a protein–nucleic
|
|
114
|
+
acid interface are detected the same way as in a binding site.
|
|
115
|
+
|
|
116
|
+
## What it detects
|
|
117
|
+
|
|
118
|
+
| Family | Types |
|
|
119
|
+
| --- | --- |
|
|
120
|
+
| Hydrogen bonding | `hbond`, `weak_hbond`, `hbond_pi`, `solvent_bridge`, `amide_bridge` |
|
|
121
|
+
| Electrostatic | `salt_bridge`, `metal_coordination`, `cation_pi`, `anion_pi`, `anion_aromatic_edge` |
|
|
122
|
+
| Stacking | `pipi_stack`, `aliphatic_pi_stack`, `aliphatic_stack`, `amide_pi`, `ch_pi` |
|
|
123
|
+
| σ-hole | `halogen_bond`, `chalcogen_bond`, `tetrel_bond`, `halogen_pi`, `chalcogen_pi` |
|
|
124
|
+
| Other | `n_pi_star`, `hydrophobic` |
|
|
125
|
+
|
|
126
|
+
`aliphatic_stack` (saturated–saturated ring stacking) ships disabled; enable it in the
|
|
127
|
+
profile. The σ-hole, stacking and n→π\* geometries follow
|
|
128
|
+
[Adhav & Saikrishnan, *ACS Omega* **2023**, 8, 22268](https://doi.org/10.1021/acsomega.3c00205).
|
|
129
|
+
|
|
130
|
+
Each type has its own geometric criteria, all adjustable — see
|
|
131
|
+
[docs/cli.md](docs/cli.md) for overriding cutoffs and [docs/chemistry.md](docs/chemistry.md)
|
|
132
|
+
for the chemical gates (such as why an ordinary Met sulfur cannot donate a chalcogen bond).
|
|
133
|
+
|
|
134
|
+
## Ligand chemistry
|
|
135
|
+
|
|
136
|
+
Ligands need a chemical template so protonation, charge, aromaticity and
|
|
137
|
+
donor/acceptor status are correct. Chemur takes one from, in order of precedence:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
chemur analyze structure.cif --ligand-smiles LIG='CC(=O)N' # explicit SMILES
|
|
141
|
+
chemur analyze receptor.pdb --ligand-sdf docked.sdf # an SDF (coordinates too)
|
|
142
|
+
chemur analyze structure.cif # automatic CCD lookup
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The automatic lookup resolves each ligand by its component name against the RCSB
|
|
146
|
+
Chemical Component Dictionary. Add `--protonate` to set the protonation state for a pH
|
|
147
|
+
range with Dimorphite-DL, and `--debug` to print the SMILES actually used.
|
|
148
|
+
|
|
149
|
+
Full detail in [docs/cli.md](docs/cli.md).
|
|
150
|
+
|
|
151
|
+
## Multiple ligands and docking output
|
|
152
|
+
|
|
153
|
+
Pass several ligands at once, or point at a directory of sdf files.
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
chemur analyze receptor.pdb --ligand-sdf a.sdf --ligand-sdf b.sdf # repeatable
|
|
157
|
+
chemur analyze receptor.pdb --ligand-sdf-dir poses/ # a whole directory
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
By default all supplied ligands are added to the structure and analysed **together**, as
|
|
161
|
+
one system — right for a cofactor plus a substrate, or two ligands sharing a pocket.
|
|
162
|
+
|
|
163
|
+
Docked poses are the opposite case: each is an alternative for the *same* site, so
|
|
164
|
+
analysing them together would stack overlapping copies into one pocket. Use `--batch` to
|
|
165
|
+
analyse each ligand independently against the same receptor:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
chemur analyze receptor.pdb --ligand-sdf-dir poses/ --batch --out all_poses.json
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Either way you also get one filtered file per ligand under `ligand_outputs/` — in batch
|
|
172
|
+
mode under a subdirectory per pose — while `--out` / `--csv` write the aggregate.
|
|
173
|
+
|
|
174
|
+
SDF coordinates are used directly, and ligand residues already present in the structure
|
|
175
|
+
are skipped so the SDF stays authoritative.
|
|
176
|
+
|
|
177
|
+
## Trajectories
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
pip install "chemur[trajectory]"
|
|
181
|
+
chemur trajectory topology.pdb trajectory.xtc --out frames.json
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Analyses each frame and reports per-interaction occupancy and time series.
|
|
185
|
+
|
|
186
|
+
## Documentation
|
|
187
|
+
|
|
188
|
+
- [docs/cli.md](docs/cli.md) — full command-line reference
|
|
189
|
+
- [docs/chemistry.md](docs/chemistry.md) — templates, hydrogen policy, σ-hole activation, profiles
|
|
190
|
+
|
|
191
|
+
## Development
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
git clone https://github.com/SweeneyAaron/chemur
|
|
195
|
+
cd chemur
|
|
196
|
+
|
|
197
|
+
conda create -n chemur-dev -c conda-forge \
|
|
198
|
+
python=3.11 rdkit gemmi numpy pyyaml pandas pytest \
|
|
199
|
+
cmake ninja pybind11 scikit-build-core cxx-compiler
|
|
200
|
+
conda activate chemur-dev
|
|
201
|
+
|
|
202
|
+
pip install -e ".[test,all]" -v
|
|
203
|
+
pytest
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
On macOS you need the Apple command line tools (`xcode-select --install`). If the build
|
|
207
|
+
fails with `'cstddef' file not found` they are incomplete — repair with
|
|
208
|
+
`sudo rm -rf /Library/Developer/CommandLineTools && xcode-select --install`.
|
|
209
|
+
|
|
210
|
+
This project uses a `src/` layout and has no `conftest.py` on purpose, so `pytest` always
|
|
211
|
+
exercises the *installed* package rather than the source tree. That is what makes the
|
|
212
|
+
wheel-level checks in CI meaningful.
|
|
213
|
+
|
|
214
|
+
## License
|
|
215
|
+
|
|
216
|
+
MIT — see [LICENSE](LICENSE).
|
|
217
|
+
|
|
218
|
+
## Citation
|
|
219
|
+
|
|
220
|
+
A manuscript is in preparation. Until then, please cite the repository:
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
Sweeney, A, Genz, L, Topf, M. Chemur: biomolecular interaction detection.
|
|
224
|
+
https://github.com/SweeneyAaron/chemur
|
|
225
|
+
```
|