prothon-ensembles 2.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.
- prothon_ensembles-2.1.0/.github/workflows/publish.yml +63 -0
- prothon_ensembles-2.1.0/.github/workflows/tests.yml +41 -0
- prothon_ensembles-2.1.0/.gitignore +22 -0
- prothon_ensembles-2.1.0/CHANGELOG.md +173 -0
- prothon_ensembles-2.1.0/CITATION.cff +38 -0
- prothon_ensembles-2.1.0/CONTRIBUTING.md +52 -0
- prothon_ensembles-2.1.0/LICENSE +21 -0
- prothon_ensembles-2.1.0/PKG-INFO +207 -0
- prothon_ensembles-2.1.0/README.md +168 -0
- prothon_ensembles-2.1.0/legacy/Prothon.py +579 -0
- prothon_ensembles-2.1.0/legacy/README.md +20 -0
- prothon_ensembles-2.1.0/legacy/prothon_example_script.py +17 -0
- prothon_ensembles-2.1.0/pyproject.toml +99 -0
- prothon_ensembles-2.1.0/pytest.ini +7 -0
- prothon_ensembles-2.1.0/setup.cfg +4 -0
- prothon_ensembles-2.1.0/src/Prothon.py +35 -0
- prothon_ensembles-2.1.0/src/prothon/__init__.py +57 -0
- prothon_ensembles-2.1.0/src/prothon/_version.py +24 -0
- prothon_ensembles-2.1.0/src/prothon/cli.py +177 -0
- prothon_ensembles-2.1.0/src/prothon/core/__init__.py +24 -0
- prothon_ensembles-2.1.0/src/prothon/core/dissimilarity.py +700 -0
- prothon_ensembles-2.1.0/src/prothon/core/plotting.py +426 -0
- prothon_ensembles-2.1.0/src/prothon/core/prothon_core.py +379 -0
- prothon_ensembles-2.1.0/src/prothon/core/representation.py +371 -0
- prothon_ensembles-2.1.0/src/prothon/utils.py +92 -0
- prothon_ensembles-2.1.0/src/prothon_ensembles.egg-info/PKG-INFO +207 -0
- prothon_ensembles-2.1.0/src/prothon_ensembles.egg-info/SOURCES.txt +35 -0
- prothon_ensembles-2.1.0/src/prothon_ensembles.egg-info/dependency_links.txt +1 -0
- prothon_ensembles-2.1.0/src/prothon_ensembles.egg-info/entry_points.txt +2 -0
- prothon_ensembles-2.1.0/src/prothon_ensembles.egg-info/requires.txt +10 -0
- prothon_ensembles-2.1.0/src/prothon_ensembles.egg-info/scm_file_list.json +30 -0
- prothon_ensembles-2.1.0/src/prothon_ensembles.egg-info/scm_version.json +8 -0
- prothon_ensembles-2.1.0/src/prothon_ensembles.egg-info/top_level.txt +2 -0
- prothon_ensembles-2.1.0/tests/conftest.py +104 -0
- prothon_ensembles-2.1.0/tests/test_core.py +267 -0
- prothon_ensembles-2.1.0/tests/test_dissimilarity.py +257 -0
- prothon_ensembles-2.1.0/tests/test_representation.py +149 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
name: Build distributions
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v5
|
|
14
|
+
with:
|
|
15
|
+
fetch-depth: 0 # setuptools-scm reads the tag
|
|
16
|
+
|
|
17
|
+
- name: Set up Python
|
|
18
|
+
uses: actions/setup-python@v6
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.11"
|
|
21
|
+
|
|
22
|
+
- name: Install build
|
|
23
|
+
run: python -m pip install --upgrade pip build
|
|
24
|
+
|
|
25
|
+
- name: Build
|
|
26
|
+
run: python -m build
|
|
27
|
+
|
|
28
|
+
- name: Verify the built version matches the release tag
|
|
29
|
+
run: |
|
|
30
|
+
TAG="${GITHUB_REF_NAME#v}"
|
|
31
|
+
VER=$(ls dist/*.tar.gz | sed -E 's/.*prothon_ensembles-(.*)\.tar\.gz/\1/')
|
|
32
|
+
echo "built: $VER tag: $TAG"
|
|
33
|
+
if [ "$TAG" != "$VER" ]; then
|
|
34
|
+
echo "::error::built version ($VER) does not match the tag ($TAG). A dirty tree or a missing tag will do this."
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
- name: Check the metadata PyPI will render
|
|
39
|
+
run: |
|
|
40
|
+
python -m pip install --upgrade twine
|
|
41
|
+
python -m twine check dist/*
|
|
42
|
+
|
|
43
|
+
- name: Upload artifacts
|
|
44
|
+
uses: actions/upload-artifact@v5
|
|
45
|
+
with:
|
|
46
|
+
name: dist
|
|
47
|
+
path: dist/
|
|
48
|
+
|
|
49
|
+
publish:
|
|
50
|
+
name: Publish to PyPI
|
|
51
|
+
needs: build
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
environment: pypi
|
|
54
|
+
permissions:
|
|
55
|
+
id-token: write # trusted publishing; no API token is stored
|
|
56
|
+
steps:
|
|
57
|
+
- uses: actions/download-artifact@v5
|
|
58
|
+
with:
|
|
59
|
+
name: dist
|
|
60
|
+
path: dist/
|
|
61
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
62
|
+
with:
|
|
63
|
+
skip-existing: true
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ${{ matrix.os }}
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
16
|
+
python-version: ["3.9", "3.11", "3.13"]
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
with:
|
|
20
|
+
fetch-depth: 0 # setuptools-scm needs the tags
|
|
21
|
+
|
|
22
|
+
- uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
|
|
26
|
+
- name: Install
|
|
27
|
+
run: |
|
|
28
|
+
python -m pip install --upgrade pip
|
|
29
|
+
python -m pip install -e ".[dev]"
|
|
30
|
+
|
|
31
|
+
- name: Lint
|
|
32
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
|
|
33
|
+
run: ruff check src tests
|
|
34
|
+
|
|
35
|
+
- name: Test
|
|
36
|
+
run: pytest --cov=prothon --cov-report=term-missing
|
|
37
|
+
|
|
38
|
+
- name: Smoke-test the CLI
|
|
39
|
+
run: |
|
|
40
|
+
prothon --version
|
|
41
|
+
prothon --info
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Build artifacts
|
|
2
|
+
build/
|
|
3
|
+
dist/
|
|
4
|
+
*.egg-info/
|
|
5
|
+
src/prothon/_version.py
|
|
6
|
+
|
|
7
|
+
# Python cache
|
|
8
|
+
__pycache__/
|
|
9
|
+
*.py[cod]
|
|
10
|
+
|
|
11
|
+
# Test and coverage
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
.coverage
|
|
14
|
+
htmlcov/
|
|
15
|
+
.ruff_cache/
|
|
16
|
+
|
|
17
|
+
# Prothon output
|
|
18
|
+
*_output/
|
|
19
|
+
|
|
20
|
+
# Environments
|
|
21
|
+
.venv/
|
|
22
|
+
venv/
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Prothon are recorded here. This project follows
|
|
4
|
+
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
5
|
+
|
|
6
|
+
## [2.1.0] — unreleased
|
|
7
|
+
|
|
8
|
+
A correctness and packaging release. The public API is unchanged: code written
|
|
9
|
+
against 2.0 runs without modification. **Numerical results will differ**, and
|
|
10
|
+
the reasons are set out below — the significance test in 2.0 was not sound.
|
|
11
|
+
|
|
12
|
+
### Fixed — the significance test
|
|
13
|
+
|
|
14
|
+
Version 2.0 built its null distribution by drawing two bootstrap resamples from
|
|
15
|
+
the *same* ensemble and measuring the Jensen–Shannon distance between them.
|
|
16
|
+
Two resamples of *n* frames drawn with replacement from the same *n* frames
|
|
17
|
+
share roughly 63% of their points, so they resemble each other far more closely
|
|
18
|
+
than two independent samples of the same size. The null was therefore too tight
|
|
19
|
+
by about a factor of two, and any honest between-ensemble distance cleared it.
|
|
20
|
+
|
|
21
|
+
Measured on a 400-frame Gaussian ensemble:
|
|
22
|
+
|
|
23
|
+
| quantity | value |
|
|
24
|
+
|---|---|
|
|
25
|
+
| bootstrap null used by 2.0 | 0.046 |
|
|
26
|
+
| two independent samples, same distribution | 0.097 |
|
|
27
|
+
| observed between-ensemble distance | 0.090 |
|
|
28
|
+
|
|
29
|
+
The consequence, over 40 null replicates in which both ensembles were drawn
|
|
30
|
+
from an identical distribution:
|
|
31
|
+
|
|
32
|
+
| | features called different | studies with ≥1 false positive |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| 2.0 bootstrap null | **100%** | **100%** |
|
|
35
|
+
| 2.1 permutation null | 1.2% | 7.5% |
|
|
36
|
+
|
|
37
|
+
Version 2.0 reported two independent samples of the same distribution as
|
|
38
|
+
differing significantly at every residue.
|
|
39
|
+
|
|
40
|
+
The replacement is a permutation test: the frames of both ensembles are pooled
|
|
41
|
+
and relabelled at random into two groups of the original sizes, which gives the
|
|
42
|
+
exact distribution of the statistic under the hypothesis that the ensembles are
|
|
43
|
+
the same. Per-feature values are standardised and pooled before correction, so
|
|
44
|
+
100 relabellings give p-value resolution fine enough to survive a
|
|
45
|
+
false-discovery-rate correction over several hundred residues.
|
|
46
|
+
|
|
47
|
+
`legacy=True` (CLI: `--legacy-statistics`) reproduces 2.0's behaviour exactly,
|
|
48
|
+
for regenerating published figures. It is documented as unsound.
|
|
49
|
+
|
|
50
|
+
### Fixed — everything else
|
|
51
|
+
|
|
52
|
+
- **Per-residue significance.** 2.0 computed one pooled p-value and wrote
|
|
53
|
+
`local_diss[p_value >= 0.05] = 0.0`. With a scalar `p_value`, NumPy reads
|
|
54
|
+
that as a mask over the whole array, so a single test decided the fate of
|
|
55
|
+
every residue at once. Each feature is now tested separately, and the
|
|
56
|
+
resulting p-values are Benjamini–Hochberg corrected — a 300-residue protein
|
|
57
|
+
tested at α = 0.05 yields fifteen false positives by construction.
|
|
58
|
+
- **Circular densities for torsions.** `cata` values wrap at ±π. 2.0 estimated
|
|
59
|
+
them with a Gaussian kernel on a linear grid, which splits a population
|
|
60
|
+
straddling the wraparound across both ends and puts a false trough between
|
|
61
|
+
them. Circular measures now use a von Mises kernel with Taylor's plug-in
|
|
62
|
+
bandwidth on a grid spanning a full turn. Each measure declares whether it is
|
|
63
|
+
circular, so the call site cannot forget.
|
|
64
|
+
- **`scikit-learn` is now declared as a dependency.** 2.0 imported it for PCA,
|
|
65
|
+
MDS and t-SNE without listing it, so a clean `pip install` failed on any run
|
|
66
|
+
that reached dimensionality reduction — which was the CLI default.
|
|
67
|
+
- **Constant features no longer crash the run.** A buried residue with zero
|
|
68
|
+
SASA in every frame gave `gaussian_kde` a singular covariance matrix and took
|
|
69
|
+
down the whole study. Such columns now get a degenerate density.
|
|
70
|
+
- **Float32 overflow in the contact sigmoid.** `mdtraj` returns float32
|
|
71
|
+
distances; `exp()` overflows above ~88 in float32 while the clip allowed 700.
|
|
72
|
+
The result was right by accident, via `1/(1+inf) → 0`, and noisy with
|
|
73
|
+
warnings. Distances are promoted to float64 first.
|
|
74
|
+
- **Replotting no longer overwrites saved figures**, and the documented
|
|
75
|
+
`xlabel`, `ylabel`, `title` and `color` arguments now take effect. In 2.0
|
|
76
|
+
`replot_global_dissimilarity` accepted them, discarded them, and re-saved
|
|
77
|
+
over the original file.
|
|
78
|
+
- **Reproducibility.** Resampling drew from the global NumPy state, so two runs
|
|
79
|
+
of one study gave different p-values with nothing recording why. `Prothon`
|
|
80
|
+
now takes `random_state`.
|
|
81
|
+
- **Empty atom selections are named.** A coarse-grained model with no C-beta
|
|
82
|
+
atoms produced an inscrutable NumPy error several frames down the stack.
|
|
83
|
+
|
|
84
|
+
### Added
|
|
85
|
+
|
|
86
|
+
- **Noise floor on every result.** The distance between two disjoint halves of
|
|
87
|
+
a single ensemble is the smallest difference the sampling can resolve. It is
|
|
88
|
+
reported alongside every comparison, drawn on every dissimilarity figure, and
|
|
89
|
+
`ComparisonResult.resolved` says plainly whether the measurement clears it.
|
|
90
|
+
- **`manifest.json` per measure**, recording inputs, parameters, seed, Prothon
|
|
91
|
+
version and full results — so a run can be reproduced and not merely admired.
|
|
92
|
+
- **`ComparisonResult`**, a typed result object that still supports dictionary
|
|
93
|
+
access (`result["global_dissimilarity"]`) so 2.0 code keeps working. Carries
|
|
94
|
+
the unmasked per-residue values, per-residue p-values, the significance mask
|
|
95
|
+
and the noise floor.
|
|
96
|
+
- **`Prothon.summary()`** and a readable default CLI output. `--json` restores
|
|
97
|
+
the 2.0 behaviour of dumping everything to stdout.
|
|
98
|
+
- `prothon --info`, listing measures and detected backends.
|
|
99
|
+
- Backward-compatibility shim: `from Prothon import Prothon` still works,
|
|
100
|
+
with a `DeprecationWarning`. Removed in 3.0. Shipped as a single module
|
|
101
|
+
`src/Prothon.py`, not a package — a directory named `Prothon` beside one
|
|
102
|
+
named `prothon` is a single path on macOS and Windows.
|
|
103
|
+
- 81 tests, a GitHub Actions matrix across operating systems and Python
|
|
104
|
+
versions, and `ruff` linting.
|
|
105
|
+
|
|
106
|
+
### Changed
|
|
107
|
+
|
|
108
|
+
- **Distribution name is `prothon-ensembles`; the import name and the command
|
|
109
|
+
are both `prothon`.** PyPI's `prothon` was registered in 2020 by an unrelated
|
|
110
|
+
protobuf generator and names there are permanent. conda-forge, where the name
|
|
111
|
+
is free, gets `prothon`. Version 2.0 was never published to either index, so
|
|
112
|
+
nothing that already works breaks.
|
|
113
|
+
- Releases publish to PyPI from a tag via trusted publishing (OpenID Connect),
|
|
114
|
+
so no long-lived API token exists to leak.
|
|
115
|
+
- **`src/` layout and `pyproject.toml`**, replacing `setup.py`. Versioning via
|
|
116
|
+
`setuptools-scm`.
|
|
117
|
+
- **Dimensionality reduction is off by default.** It defaulted to
|
|
118
|
+
`pca,mds,tsne`; MDS builds a dense frame-by-frame distance matrix, so on a
|
|
119
|
+
real trajectory the default turned a short comparison into an out-of-memory
|
|
120
|
+
failure. MDS is now refused above 5,000 frames with a message naming the
|
|
121
|
+
memory it would need, and a refusal no longer discards the comparison that
|
|
122
|
+
already succeeded.
|
|
123
|
+
- **Contact numbers are computed once rather than once per atom.** 2.0 rebuilt
|
|
124
|
+
the pair list in Python for every atom and recomputed the same distances.
|
|
125
|
+
Identical output to float32 precision:
|
|
126
|
+
|
|
127
|
+
| residues | 2.0 | 2.1 | speedup |
|
|
128
|
+
|---|---|---|---|
|
|
129
|
+
| 50 | 0.21 s | 0.05 s | 4× |
|
|
130
|
+
| 100 | 1.37 s | 0.48 s | 3× |
|
|
131
|
+
| 200 | 10.66 s | 1.10 s | 10× |
|
|
132
|
+
| 300 | 36.03 s | 2.22 s | 16× |
|
|
133
|
+
|
|
134
|
+
Pairs are processed in blocks, so a long trajectory of a large protein no
|
|
135
|
+
longer needs the whole distance matrix resident.
|
|
136
|
+
- Progress reporting moved from `print` to the `logging` module, so an
|
|
137
|
+
embedding program can silence or redirect it.
|
|
138
|
+
- Ensembles with fewer than 50 frames now emit a warning that the noise floor
|
|
139
|
+
understates the true uncertainty.
|
|
140
|
+
|
|
141
|
+
### Licence
|
|
142
|
+
|
|
143
|
+
Relicensed from GPL-3.0 to **MIT**, matching the rest of the AAI Research Lab
|
|
144
|
+
tooling and removing an adoption barrier: a number of industrial groups have
|
|
145
|
+
blanket policies against GPL dependencies, and they are a large part of the
|
|
146
|
+
audience for ensemble comparison.
|
|
147
|
+
|
|
148
|
+
The change is not retroactive. Versions up to and including 2.0.0 were
|
|
149
|
+
distributed under GPL-3.0 and copies obtained under it stay governed by it.
|
|
150
|
+
Nothing in the dependency stack required copyleft — MDTraj is LGPL, and NumPy,
|
|
151
|
+
SciPy, Matplotlib and scikit-learn are BSD.
|
|
152
|
+
|
|
153
|
+
### Known limitations
|
|
154
|
+
|
|
155
|
+
- The permutation null assumes frames are exchangeable. Frames from a single
|
|
156
|
+
continuous MD trajectory are correlated in time, so an ensemble holds fewer
|
|
157
|
+
independent conformations than it has frames and the p-values remain somewhat
|
|
158
|
+
optimistic. A block permutation over the correlation time is planned for 3.0.
|
|
159
|
+
The split-half noise floor is measured rather than assumed and is the more
|
|
160
|
+
trustworthy guide.
|
|
161
|
+
- Ensembles must share a topology. Comparison across differing sequences —
|
|
162
|
+
wild type against mutant, ortholog against ortholog — is planned for 3.0.
|
|
163
|
+
|
|
164
|
+
## [2.0.0] — 2025-04-23
|
|
165
|
+
|
|
166
|
+
- Restructured the single-module version 1 into a package.
|
|
167
|
+
- Added dimensionality reduction (PCA, MDS, t-SNE), matrix heatmaps, combined
|
|
168
|
+
local dissimilarity plots and a replotting API.
|
|
169
|
+
|
|
170
|
+
## [1.0.1] — 2023
|
|
171
|
+
|
|
172
|
+
- Original release accompanying Aina, Hsueh & Plotkin, *J. Chem. Inf. Model.*
|
|
173
|
+
**2023**, 63 (11), 3453–3461. Preserved under `legacy/`.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use Prothon, please cite the method paper below."
|
|
3
|
+
title: "Prothon: efficient comparison of protein conformational ensembles"
|
|
4
|
+
abstract: >-
|
|
5
|
+
Prothon represents a protein conformational ensemble as a vector of
|
|
6
|
+
probability distributions over local order parameters and quantifies the
|
|
7
|
+
dissimilarity between ensembles by the Jensen-Shannon distance between
|
|
8
|
+
corresponding distributions. The local representation requires no structural
|
|
9
|
+
superposition, so the cost is linear rather than quadratic in ensemble size.
|
|
10
|
+
type: software
|
|
11
|
+
license: MIT
|
|
12
|
+
repository-code: "https://github.com/aai-research-lab/Prothon"
|
|
13
|
+
authors:
|
|
14
|
+
- family-names: Aina
|
|
15
|
+
given-names: Adekunle
|
|
16
|
+
- family-names: Hsueh
|
|
17
|
+
given-names: Shawn C. C.
|
|
18
|
+
- family-names: Plotkin
|
|
19
|
+
given-names: Steven S.
|
|
20
|
+
preferred-citation:
|
|
21
|
+
type: article
|
|
22
|
+
title: >-
|
|
23
|
+
PROTHON: A Local Order Parameter-Based Method for Efficient Comparison of
|
|
24
|
+
Protein Ensembles
|
|
25
|
+
authors:
|
|
26
|
+
- family-names: Aina
|
|
27
|
+
given-names: Adekunle
|
|
28
|
+
- family-names: Hsueh
|
|
29
|
+
given-names: Shawn C. C.
|
|
30
|
+
- family-names: Plotkin
|
|
31
|
+
given-names: Steven S.
|
|
32
|
+
journal: "Journal of Chemical Information and Modeling"
|
|
33
|
+
volume: 63
|
|
34
|
+
issue: 11
|
|
35
|
+
start: 3453
|
|
36
|
+
end: 3461
|
|
37
|
+
year: 2023
|
|
38
|
+
doi: "10.1021/acs.jcim.3c00145"
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Contributing to Prothon
|
|
2
|
+
|
|
3
|
+
Contributions are welcome — bug reports, new order parameters, better
|
|
4
|
+
estimators, documentation.
|
|
5
|
+
|
|
6
|
+
## Getting set up
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
git clone https://github.com/aai-research-lab/Prothon.git
|
|
10
|
+
cd Prothon
|
|
11
|
+
pip install -e ".[dev]"
|
|
12
|
+
pytest
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## What a change needs
|
|
16
|
+
|
|
17
|
+
**A test.** Especially for a bug fix: the test should fail before the change
|
|
18
|
+
and pass after it, and be named so that a future regression says which
|
|
19
|
+
behaviour came back.
|
|
20
|
+
|
|
21
|
+
**A changelog entry**, under `[Unreleased]` in `CHANGELOG.md`. If a change
|
|
22
|
+
alters numerical results, say so plainly and say why the new numbers are the
|
|
23
|
+
right ones.
|
|
24
|
+
|
|
25
|
+
**Comments that explain why, not what.** The code says what it does. What a
|
|
26
|
+
reader cannot recover is why the bandwidth is chosen that way, or why a null
|
|
27
|
+
distribution is built from permutations rather than bootstrap resamples. That
|
|
28
|
+
reasoning belongs in the source.
|
|
29
|
+
|
|
30
|
+
## Adding an order parameter
|
|
31
|
+
|
|
32
|
+
1. Write `compute_<name>(traj)` in `core/representation.py`, returning an
|
|
33
|
+
`(n_frames, n_features)` array.
|
|
34
|
+
2. Register it in `MEASURES`, declaring `circular` and `per_residue`. Getting
|
|
35
|
+
`circular` wrong is silent and wrong, not loud and wrong: a linear kernel on
|
|
36
|
+
circular data produces plausible numbers that understate dissimilarity at
|
|
37
|
+
the wraparound.
|
|
38
|
+
3. Add it to `_COMPUTE`. A test checks the two stay in step.
|
|
39
|
+
4. Test the shape, the value range, and one case where you know the answer.
|
|
40
|
+
|
|
41
|
+
## Statistics
|
|
42
|
+
|
|
43
|
+
Changes to `core/dissimilarity.py` need a calibration check as well as a unit
|
|
44
|
+
test: a null case where both ensembles are drawn from the same distribution,
|
|
45
|
+
asserting that the false-positive rate stays near the nominal level. There is
|
|
46
|
+
one in `tests/test_dissimilarity.py` to copy. This is not optional — the bug
|
|
47
|
+
that motivated the 2.1 release passed every unit test in 2.0 and failed exactly
|
|
48
|
+
this check.
|
|
49
|
+
|
|
50
|
+
## Style
|
|
51
|
+
|
|
52
|
+
`ruff check src tests`. Line length 100.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023-2026 Adekunle Aina
|
|
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,207 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: prothon-ensembles
|
|
3
|
+
Version: 2.1.0
|
|
4
|
+
Summary: Efficient comparison of protein conformational ensembles using local order parameters
|
|
5
|
+
Author-email: Adekunle Aina <kunleaina@gmail.com>
|
|
6
|
+
Maintainer-email: Adekunle Aina <kunleaina@gmail.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/aai-research-lab/Prothon
|
|
9
|
+
Project-URL: Repository, https://github.com/aai-research-lab/Prothon
|
|
10
|
+
Project-URL: Issues, https://github.com/aai-research-lab/Prothon/issues
|
|
11
|
+
Project-URL: Publication, https://doi.org/10.1021/acs.jcim.3c00145
|
|
12
|
+
Keywords: protein-ensembles,conformational-ensembles,molecular-dynamics,intrinsically-disordered-proteins,jensen-shannon,order-parameters,structural-biology,biophysics
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
25
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
26
|
+
Requires-Python: <3.14,>=3.9
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Requires-Dist: numpy>=1.22
|
|
30
|
+
Requires-Dist: mdtraj>=1.9.7
|
|
31
|
+
Requires-Dist: scipy>=1.9
|
|
32
|
+
Requires-Dist: matplotlib>=3.5
|
|
33
|
+
Requires-Dist: scikit-learn>=1.0
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
36
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
37
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
<div align="center">
|
|
41
|
+
|
|
42
|
+
# Prothon
|
|
43
|
+
|
|
44
|
+
**How different are two protein ensembles — and is the difference real?**
|
|
45
|
+
|
|
46
|
+
[](https://doi.org/10.1021/acs.jcim.3c00145)
|
|
47
|
+
[](https://pypi.org/project/prothon/)
|
|
48
|
+
[](https://opensource.org/licenses/MIT)
|
|
49
|
+
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
prothon -traj wild_type.dcd,mutant.dcd -top topology.pdb -m cbcn
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
CBCN (reference: ensemble 0)
|
|
60
|
+
ensemble 1: d = 0.2841 (floor 0.0472) — 34/76 residues differ
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Prothon represents each conformational ensemble as a vector of probability
|
|
64
|
+
distributions over **local order parameters** — contact numbers, virtual bond
|
|
65
|
+
and torsion angles, solvent accessibility — and measures the Jensen–Shannon
|
|
66
|
+
distance between corresponding distributions. Because the representation is
|
|
67
|
+
local, no structural superposition is needed and the cost is linear in the
|
|
68
|
+
number of frames rather than quadratic, which is what makes ensembles of tens
|
|
69
|
+
of thousands of conformations tractable.
|
|
70
|
+
|
|
71
|
+
**It reports what it cannot resolve.** Two independent halves of a *single*
|
|
72
|
+
ensemble have a non-zero Jensen–Shannon distance, because a finite sample never
|
|
73
|
+
reproduces a continuous distribution exactly. That self-distance is the
|
|
74
|
+
resolution limit of the comparison, and Prothon measures it, prints it beside
|
|
75
|
+
every result, and draws it on every figure. A difference smaller than the floor
|
|
76
|
+
is reported as unresolvable rather than as a small difference.
|
|
77
|
+
|
|
78
|
+
## Install
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
conda install -c conda-forge prothon # preferred
|
|
82
|
+
pip install prothon-ensembles # the distribution name; see below
|
|
83
|
+
prothon --info
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The distribution on PyPI is `prothon-ensembles`, because `prothon` was
|
|
87
|
+
registered in 2020 by an unrelated protobuf generator and PyPI names are
|
|
88
|
+
permanent. The import name and the command are both `prothon`:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from prothon import Prothon
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Use it
|
|
95
|
+
|
|
96
|
+
From the command line:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
prothon -traj a.dcd,b.dcd,c.dcd -top top.pdb -m cbcn,cata -o results --seed 0
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
| flag | meaning |
|
|
103
|
+
|---|---|
|
|
104
|
+
| `-traj` | Trajectory files, one per ensemble, comma-separated. Never concatenated. |
|
|
105
|
+
| `-top` | Topology (PDB), shared by all of them. |
|
|
106
|
+
| `-m` | Measures: `cbcn`, `cacn`, `caba`, `cata`, `sasa`. |
|
|
107
|
+
| `-r` | Reference ensemble index (default 0). |
|
|
108
|
+
| `-o` | Output root. Each measure writes `<measure>_output/`. |
|
|
109
|
+
| `-d` | Projections: `pca`, `mds`, `tsne`. Off by default. |
|
|
110
|
+
| `--seed` | Set it, and the run is reproducible. |
|
|
111
|
+
|
|
112
|
+
Or from Python:
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
from prothon import Prothon
|
|
116
|
+
|
|
117
|
+
study = Prothon(["wild_type.dcd", "mutant.dcd"], "topology.pdb", random_state=0)
|
|
118
|
+
results = study.compare_ensembles(methods="cbcn")
|
|
119
|
+
|
|
120
|
+
comparison = results["cbcn"][0]
|
|
121
|
+
comparison.global_dissimilarity # 0.2841
|
|
122
|
+
comparison.noise_floor # 0.0472 — the resolution limit
|
|
123
|
+
comparison.resolved # True: the difference clears the floor
|
|
124
|
+
comparison.significant # bool array, one per residue
|
|
125
|
+
comparison.local_dissimilarity # per residue, zero where not significant
|
|
126
|
+
comparison.raw_local_dissimilarity # per residue, unmasked
|
|
127
|
+
|
|
128
|
+
print(study.summary())
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Each measure writes a directory containing the representation matrices as CSV,
|
|
132
|
+
heatmaps, global and per-residue dissimilarity figures, and a `manifest.json`
|
|
133
|
+
recording the inputs, parameters, seed and version that produced them.
|
|
134
|
+
|
|
135
|
+
## The measures
|
|
136
|
+
|
|
137
|
+
| name | quantity | circular |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| `cbcn` | C-beta contact number, smooth cutoff | |
|
|
140
|
+
| `cacn` | C-alpha contact number, smooth cutoff | |
|
|
141
|
+
| `caba` | Virtual Cα–Cα–Cα bond angle | |
|
|
142
|
+
| `cata` | Virtual Cα torsion angle | yes |
|
|
143
|
+
| `sasa` | Per-residue solvent accessible surface area | |
|
|
144
|
+
|
|
145
|
+
Torsions live on a circle, so they are estimated with a von Mises kernel on a
|
|
146
|
+
grid spanning a full turn. Each measure declares this, so the call site cannot
|
|
147
|
+
forget it.
|
|
148
|
+
|
|
149
|
+
## Upgrading from 2.0
|
|
150
|
+
|
|
151
|
+
The API is unchanged and existing scripts run without modification, but
|
|
152
|
+
**numbers will differ**, because the significance test in 2.0 was not sound: it
|
|
153
|
+
compared each ensemble against a bootstrap of itself, a null about half as wide
|
|
154
|
+
as the true sampling variability. Over 40 replicates in which both ensembles
|
|
155
|
+
were drawn from an *identical* distribution, 2.0 called 100% of residues
|
|
156
|
+
significantly different. The permutation test that replaces it sits at 1.2%.
|
|
157
|
+
|
|
158
|
+
`--legacy-statistics` reproduces the old behaviour for regenerating published
|
|
159
|
+
figures. [CHANGELOG.md](CHANGELOG.md) has the full account.
|
|
160
|
+
|
|
161
|
+
`from Prothon import Prothon` still works and warns; use
|
|
162
|
+
`from prothon import Prothon`.
|
|
163
|
+
|
|
164
|
+
## Citation
|
|
165
|
+
|
|
166
|
+
> Aina, A.; Hsueh, S. C. C.; Plotkin, S. S. PROTHON: A Local Order
|
|
167
|
+
> Parameter-Based Method for Efficient Comparison of Protein Ensembles.
|
|
168
|
+
> *J. Chem. Inf. Model.* **2023**, *63* (11), 3453–3461.
|
|
169
|
+
> DOI: [10.1021/acs.jcim.3c00145](https://doi.org/10.1021/acs.jcim.3c00145)
|
|
170
|
+
|
|
171
|
+
```bibtex
|
|
172
|
+
@article{aina2023prothon,
|
|
173
|
+
author = {Aina, Adekunle and Hsueh, Shawn C. C. and Plotkin, Steven S.},
|
|
174
|
+
title = {PROTHON: A Local Order Parameter-Based Method for Efficient
|
|
175
|
+
Comparison of Protein Ensembles},
|
|
176
|
+
journal = {Journal of Chemical Information and Modeling},
|
|
177
|
+
volume = {63},
|
|
178
|
+
number = {11},
|
|
179
|
+
pages = {3453--3461},
|
|
180
|
+
year = {2023},
|
|
181
|
+
doi = {10.1021/acs.jcim.3c00145},
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Contributing
|
|
186
|
+
|
|
187
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). The original version 1 code accompanying
|
|
188
|
+
the 2023 paper is preserved unchanged under `legacy/`.
|
|
189
|
+
|
|
190
|
+
## License
|
|
191
|
+
|
|
192
|
+
MIT. See [LICENSE](LICENSE).
|
|
193
|
+
|
|
194
|
+
Prothon was distributed under GPL-3.0 up to and including version 2.0.0.
|
|
195
|
+
From 2.1.0 the project is MIT-licensed. Copies already obtained under
|
|
196
|
+
GPL-3.0 remain governed by that licence — relicensing is not retroactive
|
|
197
|
+
and takes nothing away from anyone who has a copy.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
<div align="center">
|
|
202
|
+
|
|
203
|
+
Built in the [AAI Research Lab](https://aai-research-lab.github.io) at
|
|
204
|
+
California State University Dominguez Hills, on MDTraj, NumPy, SciPy,
|
|
205
|
+
scikit-learn and Matplotlib.
|
|
206
|
+
|
|
207
|
+
</div>
|