foldmetrics 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 (34) hide show
  1. foldmetrics-0.1.0/.github/workflows/ci.yml +26 -0
  2. foldmetrics-0.1.0/.github/workflows/publish.yml +36 -0
  3. foldmetrics-0.1.0/.gitignore +30 -0
  4. foldmetrics-0.1.0/LICENSE +21 -0
  5. foldmetrics-0.1.0/PKG-INFO +241 -0
  6. foldmetrics-0.1.0/README.md +211 -0
  7. foldmetrics-0.1.0/docs/assets/demo_batch.png +0 -0
  8. foldmetrics-0.1.0/docs/assets/demo_comparison.png +0 -0
  9. foldmetrics-0.1.0/docs/assets/demo_summary.png +0 -0
  10. foldmetrics-0.1.0/examples/README.md +92 -0
  11. foldmetrics-0.1.0/examples/make_demo_data.py +207 -0
  12. foldmetrics-0.1.0/examples/python_api.py +72 -0
  13. foldmetrics-0.1.0/pyproject.toml +76 -0
  14. foldmetrics-0.1.0/src/foldmetrics/__init__.py +30 -0
  15. foldmetrics-0.1.0/src/foldmetrics/api.py +97 -0
  16. foldmetrics-0.1.0/src/foldmetrics/cli.py +274 -0
  17. foldmetrics-0.1.0/src/foldmetrics/metrics.py +390 -0
  18. foldmetrics-0.1.0/src/foldmetrics/models.py +155 -0
  19. foldmetrics-0.1.0/src/foldmetrics/parsers/__init__.py +120 -0
  20. foldmetrics-0.1.0/src/foldmetrics/parsers/alphafold2.py +211 -0
  21. foldmetrics-0.1.0/src/foldmetrics/parsers/alphafold3.py +175 -0
  22. foldmetrics-0.1.0/src/foldmetrics/parsers/base.py +140 -0
  23. foldmetrics-0.1.0/src/foldmetrics/parsers/boltz.py +136 -0
  24. foldmetrics-0.1.0/src/foldmetrics/parsers/chai.py +114 -0
  25. foldmetrics-0.1.0/src/foldmetrics/parsers/colabfold.py +92 -0
  26. foldmetrics-0.1.0/src/foldmetrics/parsers/protenix.py +111 -0
  27. foldmetrics-0.1.0/src/foldmetrics/parsers/structure.py +122 -0
  28. foldmetrics-0.1.0/src/foldmetrics/py.typed +0 -0
  29. foldmetrics-0.1.0/src/foldmetrics/render.py +115 -0
  30. foldmetrics-0.1.0/src/foldmetrics/viz.py +510 -0
  31. foldmetrics-0.1.0/tests/conftest.py +265 -0
  32. foldmetrics-0.1.0/tests/test_cli.py +78 -0
  33. foldmetrics-0.1.0/tests/test_metrics.py +139 -0
  34. foldmetrics-0.1.0/tests/test_parsers.py +130 -0
@@ -0,0 +1,26 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ${{ matrix.os }}
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ os: [ubuntu-latest, macos-latest]
15
+ python: ["3.10", "3.13"]
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: astral-sh/setup-uv@v5
19
+ - name: Install
20
+ run: |
21
+ uv venv --python ${{ matrix.python }}
22
+ uv pip install -e ".[dev]"
23
+ - name: Test
24
+ run: .venv/bin/pytest
25
+ - name: Lint
26
+ run: .venv/bin/ruff check src tests examples
@@ -0,0 +1,36 @@
1
+ name: Publish to PyPI
2
+
3
+ # Triggered by pushing a version tag, e.g.: git push origin v0.1.0
4
+ # Requires a PyPI "trusted publisher" configured for this repository
5
+ # (project: foldmetrics, workflow: publish.yml, environment: pypi).
6
+ on:
7
+ push:
8
+ tags: ["v*"]
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: astral-sh/setup-uv@v5
16
+ - name: Build sdist and wheel
17
+ run: uv build
18
+ - uses: actions/upload-artifact@v4
19
+ with:
20
+ name: dist
21
+ path: dist/
22
+
23
+ publish:
24
+ needs: build
25
+ runs-on: ubuntu-latest
26
+ environment:
27
+ name: pypi
28
+ url: https://pypi.org/p/foldmetrics
29
+ permissions:
30
+ id-token: write
31
+ steps:
32
+ - uses: actions/download-artifact@v4
33
+ with:
34
+ name: dist
35
+ path: dist/
36
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,30 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ .venv/
9
+ venv/
10
+
11
+ # Tooling caches
12
+ .pytest_cache/
13
+ .ruff_cache/
14
+ .mypy_cache/
15
+ .coverage
16
+ htmlcov/
17
+
18
+ # Editors / OS
19
+ .DS_Store
20
+ .idea/
21
+ .vscode/
22
+
23
+ # Local working notes (not part of the published project)
24
+ CLAUDE.md
25
+ .claude/
26
+
27
+ # Local outputs
28
+ foldmetrics_plots/
29
+ *.tsv
30
+ !tests/**/*.tsv
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jiajun Li
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,241 @@
1
+ Metadata-Version: 2.5
2
+ Name: foldmetrics
3
+ Version: 0.1.0
4
+ Summary: Unified confidence metrics (pTM, ipTM, pLDDT, ipLDDT, PAE, ipSAE, pDockQ, pDockQ2, LIS) for AlphaFold2/3, ColabFold, Boltz, Chai-1 and Protenix predictions
5
+ Project-URL: Homepage, https://github.com/ChiaChunL/foldmetrics
6
+ Project-URL: Repository, https://github.com/ChiaChunL/foldmetrics
7
+ Project-URL: Issues, https://github.com/ChiaChunL/foldmetrics/issues
8
+ Author-email: Jiajun Li <ChiaChun.Le@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: alphafold,bioinformatics,boltz,chai-1,ipsae,iptm,pae,pdockq,plddt,protein-complex,protenix,structure-prediction
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Operating System :: OS Independent
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: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: gemmi>=0.6.4
23
+ Requires-Dist: matplotlib>=3.7
24
+ Requires-Dist: numpy>=1.23
25
+ Requires-Dist: pandas>=2.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=7.4; extra == 'dev'
28
+ Requires-Dist: ruff>=0.5; extra == 'dev'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # foldmetrics
32
+
33
+ Unified confidence metrics for structure-prediction models.
34
+
35
+ `foldmetrics` ingests the raw output folders of the mainstream structure
36
+ predictors — **AlphaFold2 / AlphaFold-Multimer, ColabFold, AlphaFold3, Boltz,
37
+ Chai-1, Protenix** — and computes a consistent set of quality metrics for
38
+ monomers and complexes (protein, nucleic acid and small-molecule ligands),
39
+ for a single model or whole batches:
40
+
41
+ | Metric | What it tells you | Source |
42
+ |---|---|---|
43
+ | `ptm`, `iptm` | global / interface predicted TM-score | read from tool output |
44
+ | `ranking_score` | tool-native model ranking (AF3 `ranking_score`, Boltz `confidence_score`, Chai `aggregate_score`, AF2 `ranking_confidence`) | read from tool output |
45
+ | `plddt_mean` | mean per-token pLDDT | computed |
46
+ | `iplddt` | mean pLDDT over interface residues (contact atoms within 8 Å across chains) | computed |
47
+ | `pae_mean`, `ipae_mean` | mean PAE (all off-diagonal / inter-chain blocks) | computed |
48
+ | `ipsae` | interface score from PAE with per-residue d0 (Dunbrack 2025) | computed |
49
+ | `pdockq` | interface score from contacts + pLDDT (Bryant 2022) | computed |
50
+ | `pdockq2` | interface score from contacts + pLDDT + PAE (Zhu 2023) | computed |
51
+ | `lis` | Local Interaction Score from PAE (Kim 2024) | computed |
52
+
53
+ Computed metrics were validated against the `ipsae.py` reference
54
+ implementation (Dunbrack Lab), including its exact `d0` conventions.
55
+
56
+ ## Install
57
+
58
+ ```bash
59
+ pip install foldmetrics
60
+ ```
61
+
62
+ (conda-forge packaging is planned; until then use pip inside a conda env.)
63
+
64
+ Development install:
65
+
66
+ ```bash
67
+ git clone https://github.com/ChiaChunL/foldmetrics.git && cd foldmetrics
68
+ pip install -e ".[dev]"
69
+ ```
70
+
71
+ ## Quickstart
72
+
73
+ CLI (`foldmetrics`, short alias `fmx`):
74
+
75
+ ```bash
76
+ # score every prediction found under a directory (any mix of tools)
77
+ foldmetrics score path/to/predictions/ -o metrics.tsv
78
+
79
+ # per chain-pair breakdown + summary figures (pLDDT track, PAE heatmap, metrics)
80
+ fmx score preds/ -o metrics.tsv --interfaces interfaces.tsv --plot plots/
81
+
82
+ # a single model: point at any of its files
83
+ fmx score run1/fold_job_full_data_0.json
84
+
85
+ # one metric only (every metric name is also a subcommand)
86
+ fmx ipsae preds/ --interfaces ipsae_per_pair.tsv
87
+ fmx score preds/ --metrics ipsae,pdockq2,lis
88
+
89
+ # what would be scored?
90
+ fmx detect preds/
91
+
92
+ # figures only
93
+ fmx plot preds/ -o plots/
94
+ ```
95
+
96
+ Python:
97
+
98
+ ```python
99
+ import foldmetrics as fm
100
+
101
+ df = fm.evaluate("path/to/predictions/") # one row per model
102
+ dfi = fm.evaluate_interfaces("path/to/predictions/") # one row per chain pair
103
+
104
+ # lower-level access
105
+ preds = fm.load_predictions("path/to/predictions/")
106
+ summary, interfaces = fm.compute_all(preds[0])
107
+ ```
108
+
109
+ More recipes (including runnable demo data that needs no prediction tool) live
110
+ in [examples/](examples/).
111
+
112
+ ## Visualization
113
+
114
+ `--plot DIR` (on `score` and every metric subcommand) or the `plot`
115
+ subcommand renders publication-oriented figures, adapting automatically to
116
+ the shape of the batch:
117
+
118
+ | Input shape | Figures written into DIR |
119
+ |---|---|
120
+ | every model | `<model>.png` — pLDDT-colored structure + pLDDT track + PAE heatmap + metrics panel |
121
+ | more than one model | plus `batch_overview.png` — ranked confidence dot plot + mean pLDDT bars |
122
+ | more than one target and/or tool | plus `comparison.png` — one panel per metric, grouped by target, one color per tool |
123
+
124
+ The structure panel uses **headless PyMOL** when available (auto-detected
125
+ from `FOLDMETRICS_PYMOL`, PATH, or common conda locations; ~2–3 s per
126
+ model) and falls back to a fast matplotlib backbone trace otherwise —
127
+ select explicitly with `--renderer pymol|trace`. The `plot` subcommand also
128
+ takes `--format png|pdf|svg` and `--dpi` (default 300).
129
+
130
+ Single model (AlphaFold3, SARS-CoV-2 Mpro + nirmatrelvir):
131
+
132
+ ![per-model summary](https://raw.githubusercontent.com/ChiaChunL/foldmetrics/main/docs/assets/demo_summary.png)
133
+
134
+ Targets × methods comparison (real batch: 10 complexes × 4 tools):
135
+
136
+ ![per-target comparison](https://raw.githubusercontent.com/ChiaChunL/foldmetrics/main/docs/assets/demo_comparison.png)
137
+
138
+ Batch overview (one target, AlphaFold2 + AlphaFold3 models):
139
+
140
+ ![batch overview](https://raw.githubusercontent.com/ChiaChunL/foldmetrics/main/docs/assets/demo_batch.png)
141
+
142
+ ## Supported tools and files
143
+
144
+ | Tool | Detected files | pTM/ipTM | pLDDT | PAE |
145
+ |---|---|---|---|---|
146
+ | ColabFold | `*_scores_rank_*.json` + `*_(un)relaxed_rank_*.pdb` | yes | yes | yes |
147
+ | AlphaFold2 (pickle layout) | `result_model_*.pkl` + `unrelaxed_*.pdb` / `ranked_*.pdb` | yes | yes | yes |
148
+ | AlphaFold2 (JSON layout) | `iptm_ptm.json` + `confidence_*.json` / `pae_*.json` + `unrelaxed_*.cif/.pdb` | yes | yes | yes |
149
+ | AlphaFold3 (server/local) | `*model*.cif` + `*summary_confidences*.json` + `*confidences*/full_data*.json` | yes | yes | yes |
150
+ | Boltz-1/2 | `confidence_*_model_*.json` + `*_model_*.cif` + `pae_*.npz` / `plddt_*.npz` | yes | yes | yes |
151
+ | Chai-1 | `scores.model_idx_*.npz` + `pred.model_idx_*.cif` | yes | yes | if exported |
152
+ | Protenix | `*summary_confidence*.json` + matching `.cif` (+ `*full_data*.json` with `token_pair_pae`) | yes | yes | yes |
153
+ | HelixFold3 | planned | — | — | — |
154
+
155
+ ## Validation
156
+
157
+ - Numerical parity with the `ipsae.py` reference implementation (Dunbrack
158
+ Lab) verified digit-for-digit on real AlphaFold3 server output: ipSAE
159
+ (both directions and d0chn variant), pDockQ, pDockQ2 and LIS all match to
160
+ 6 decimal places at the default cutoffs (10/10).
161
+ - Batch-tested on 720 real predictions across AlphaFold2-Multimer,
162
+ AlphaFold3 (server + local), Boltz-2 and Protenix — including
163
+ protein–small-molecule complexes, homodimers, monomers and negative
164
+ controls — with zero parse errors; known binders score ipSAE 0.9+, decoy
165
+ pairs < 0.1, monomers report NA.
166
+ - ColabFold and Chai-1 parsers are currently validated on synthetic
167
+ fixtures only; real-output samples welcome.
168
+
169
+ Native per-tool extras (e.g. Boltz `complex_iplddt`/`ligand_iptm`, AF3
170
+ `chain_pair_pae_min`, Chai clash flags) are preserved on
171
+ `Prediction.extras` and chain-pair ipTM is surfaced as `iptm_native` in the
172
+ interface table.
173
+
174
+ ## What each metric needs
175
+
176
+ The structure file is always required (it defines chains and tokens); the
177
+ table shows which additional inputs each metric consumes. When an input is
178
+ missing the metric is `NA` and a note lands in the `warnings` column —
179
+ nothing crashes.
180
+
181
+ | Metric (= subcommand) | pLDDT | Coordinates | PAE | Source |
182
+ |---|---|---|---|---|
183
+ | `ptm`, `iptm`, `ranking` | – | – | – | read from the tool's confidence file |
184
+ | `plddt` (mean pLDDT, ipLDDT) | yes | ipLDDT only | – | B-factors, or the tool's pLDDT file |
185
+ | `pae` (mean PAE, inter-chain PAE) | – | – | yes | tool's PAE matrix |
186
+ | `pdockq` | yes | yes | – | contacts at 8 Å between CB/C3' atoms |
187
+ | `pdockq2` | yes | yes | yes | |
188
+ | `ipsae`, `lis` | – | – | yes | chain mapping from the structure |
189
+
190
+ ## Outputs and paths
191
+
192
+ - Summary table → stdout; `-o FILE` writes it. The extension picks the
193
+ format: `.tsv` (default), `.csv`, `.json`; missing values are `NA`.
194
+ - `--interfaces FILE` → the per chain-pair table (same formats).
195
+ - `--plot DIR` → figures as described under Visualization; model names are
196
+ sanitized (`[^\w.-]` → `_`) for use as filenames.
197
+ - `plot -o DIR` defaults to `./foldmetrics_plots/`.
198
+ - Exit codes: `0` success, `1` nothing recognized/found, `2` bad arguments.
199
+
200
+ ## Conventions worth knowing
201
+
202
+ - **Tokens.** Standard residues are one token; ligands and modified residues
203
+ are one token per heavy atom (AF3-style), so token-level PAE matrices line
204
+ up across tools. pLDDT is stored on the 0–100 scale everywhere (Boltz 0–1
205
+ values are rescaled).
206
+ - **Complex-level interface metrics are the best interface.** For >2 chains,
207
+ `ipsae`/`pdockq`/`pdockq2`/`lis` in the summary table are the maximum over
208
+ chain pairs; use `--interfaces` for the full breakdown.
209
+ - **Ligand interfaces.** `pdockq`/`pdockq2`/`iplddt` are defined for
210
+ polymer–polymer interfaces only. For chain pairs involving a ligand chain,
211
+ `ipsae`/`lis` are computed over ligand atom tokens (experimental) and marked
212
+ `ipsae_mode = "tokens"` in the interface table.
213
+ - **Missing data degrades gracefully.** No PAE → PAE-based metrics are NaN
214
+ and a note lands in the `warnings` column; nothing crashes.
215
+ - **Directionality.** PAE is asymmetric, so `pdockq2`/`ipsae`/`lis` have two
216
+ directional values; the interface table reports both (`*_ab`, `*_ba`) plus
217
+ the aggregate used everywhere else (max for ipSAE/pDockQ2, mean for LIS,
218
+ matching the reference implementations).
219
+
220
+ ## References
221
+
222
+ - Bryant P, Pozzati G, Elofsson A. *Improved prediction of protein-protein
223
+ interactions using AlphaFold2.* Nat Commun 13, 1265 (2022). — pDockQ
224
+ - Zhu W, Shenoy A, Kundrotas P, Elofsson A. *Evaluation of AlphaFold-Multimer
225
+ prediction on multi-chain protein complexes.* Bioinformatics 39, btad424
226
+ (2023). — pDockQ2
227
+ - Dunbrack RL. *ipSAE: scoring pairwise interactions in AlphaFold models.*
228
+ bioRxiv 10.1101/2025.02.10.637595 (2025). — ipSAE
229
+ - Kim AR et al. *Enhanced protein-protein interaction discovery via
230
+ AlphaFold-Multimer.* bioRxiv 10.1101/2024.02.19.580970 (2024). — LIS
231
+
232
+ ## Roadmap
233
+
234
+ - HelixFold3 parser (sample outputs welcome — please open an issue)
235
+ - Real-output samples for ColabFold and Chai-1
236
+ - Per-interface PAE/ipSAE figures; interactive HTML report
237
+ - conda-forge feedstock; CI (lint + tests) on GitHub Actions
238
+
239
+ ## License
240
+
241
+ MIT
@@ -0,0 +1,211 @@
1
+ # foldmetrics
2
+
3
+ Unified confidence metrics for structure-prediction models.
4
+
5
+ `foldmetrics` ingests the raw output folders of the mainstream structure
6
+ predictors — **AlphaFold2 / AlphaFold-Multimer, ColabFold, AlphaFold3, Boltz,
7
+ Chai-1, Protenix** — and computes a consistent set of quality metrics for
8
+ monomers and complexes (protein, nucleic acid and small-molecule ligands),
9
+ for a single model or whole batches:
10
+
11
+ | Metric | What it tells you | Source |
12
+ |---|---|---|
13
+ | `ptm`, `iptm` | global / interface predicted TM-score | read from tool output |
14
+ | `ranking_score` | tool-native model ranking (AF3 `ranking_score`, Boltz `confidence_score`, Chai `aggregate_score`, AF2 `ranking_confidence`) | read from tool output |
15
+ | `plddt_mean` | mean per-token pLDDT | computed |
16
+ | `iplddt` | mean pLDDT over interface residues (contact atoms within 8 Å across chains) | computed |
17
+ | `pae_mean`, `ipae_mean` | mean PAE (all off-diagonal / inter-chain blocks) | computed |
18
+ | `ipsae` | interface score from PAE with per-residue d0 (Dunbrack 2025) | computed |
19
+ | `pdockq` | interface score from contacts + pLDDT (Bryant 2022) | computed |
20
+ | `pdockq2` | interface score from contacts + pLDDT + PAE (Zhu 2023) | computed |
21
+ | `lis` | Local Interaction Score from PAE (Kim 2024) | computed |
22
+
23
+ Computed metrics were validated against the `ipsae.py` reference
24
+ implementation (Dunbrack Lab), including its exact `d0` conventions.
25
+
26
+ ## Install
27
+
28
+ ```bash
29
+ pip install foldmetrics
30
+ ```
31
+
32
+ (conda-forge packaging is planned; until then use pip inside a conda env.)
33
+
34
+ Development install:
35
+
36
+ ```bash
37
+ git clone https://github.com/ChiaChunL/foldmetrics.git && cd foldmetrics
38
+ pip install -e ".[dev]"
39
+ ```
40
+
41
+ ## Quickstart
42
+
43
+ CLI (`foldmetrics`, short alias `fmx`):
44
+
45
+ ```bash
46
+ # score every prediction found under a directory (any mix of tools)
47
+ foldmetrics score path/to/predictions/ -o metrics.tsv
48
+
49
+ # per chain-pair breakdown + summary figures (pLDDT track, PAE heatmap, metrics)
50
+ fmx score preds/ -o metrics.tsv --interfaces interfaces.tsv --plot plots/
51
+
52
+ # a single model: point at any of its files
53
+ fmx score run1/fold_job_full_data_0.json
54
+
55
+ # one metric only (every metric name is also a subcommand)
56
+ fmx ipsae preds/ --interfaces ipsae_per_pair.tsv
57
+ fmx score preds/ --metrics ipsae,pdockq2,lis
58
+
59
+ # what would be scored?
60
+ fmx detect preds/
61
+
62
+ # figures only
63
+ fmx plot preds/ -o plots/
64
+ ```
65
+
66
+ Python:
67
+
68
+ ```python
69
+ import foldmetrics as fm
70
+
71
+ df = fm.evaluate("path/to/predictions/") # one row per model
72
+ dfi = fm.evaluate_interfaces("path/to/predictions/") # one row per chain pair
73
+
74
+ # lower-level access
75
+ preds = fm.load_predictions("path/to/predictions/")
76
+ summary, interfaces = fm.compute_all(preds[0])
77
+ ```
78
+
79
+ More recipes (including runnable demo data that needs no prediction tool) live
80
+ in [examples/](examples/).
81
+
82
+ ## Visualization
83
+
84
+ `--plot DIR` (on `score` and every metric subcommand) or the `plot`
85
+ subcommand renders publication-oriented figures, adapting automatically to
86
+ the shape of the batch:
87
+
88
+ | Input shape | Figures written into DIR |
89
+ |---|---|
90
+ | every model | `<model>.png` — pLDDT-colored structure + pLDDT track + PAE heatmap + metrics panel |
91
+ | more than one model | plus `batch_overview.png` — ranked confidence dot plot + mean pLDDT bars |
92
+ | more than one target and/or tool | plus `comparison.png` — one panel per metric, grouped by target, one color per tool |
93
+
94
+ The structure panel uses **headless PyMOL** when available (auto-detected
95
+ from `FOLDMETRICS_PYMOL`, PATH, or common conda locations; ~2–3 s per
96
+ model) and falls back to a fast matplotlib backbone trace otherwise —
97
+ select explicitly with `--renderer pymol|trace`. The `plot` subcommand also
98
+ takes `--format png|pdf|svg` and `--dpi` (default 300).
99
+
100
+ Single model (AlphaFold3, SARS-CoV-2 Mpro + nirmatrelvir):
101
+
102
+ ![per-model summary](https://raw.githubusercontent.com/ChiaChunL/foldmetrics/main/docs/assets/demo_summary.png)
103
+
104
+ Targets × methods comparison (real batch: 10 complexes × 4 tools):
105
+
106
+ ![per-target comparison](https://raw.githubusercontent.com/ChiaChunL/foldmetrics/main/docs/assets/demo_comparison.png)
107
+
108
+ Batch overview (one target, AlphaFold2 + AlphaFold3 models):
109
+
110
+ ![batch overview](https://raw.githubusercontent.com/ChiaChunL/foldmetrics/main/docs/assets/demo_batch.png)
111
+
112
+ ## Supported tools and files
113
+
114
+ | Tool | Detected files | pTM/ipTM | pLDDT | PAE |
115
+ |---|---|---|---|---|
116
+ | ColabFold | `*_scores_rank_*.json` + `*_(un)relaxed_rank_*.pdb` | yes | yes | yes |
117
+ | AlphaFold2 (pickle layout) | `result_model_*.pkl` + `unrelaxed_*.pdb` / `ranked_*.pdb` | yes | yes | yes |
118
+ | AlphaFold2 (JSON layout) | `iptm_ptm.json` + `confidence_*.json` / `pae_*.json` + `unrelaxed_*.cif/.pdb` | yes | yes | yes |
119
+ | AlphaFold3 (server/local) | `*model*.cif` + `*summary_confidences*.json` + `*confidences*/full_data*.json` | yes | yes | yes |
120
+ | Boltz-1/2 | `confidence_*_model_*.json` + `*_model_*.cif` + `pae_*.npz` / `plddt_*.npz` | yes | yes | yes |
121
+ | Chai-1 | `scores.model_idx_*.npz` + `pred.model_idx_*.cif` | yes | yes | if exported |
122
+ | Protenix | `*summary_confidence*.json` + matching `.cif` (+ `*full_data*.json` with `token_pair_pae`) | yes | yes | yes |
123
+ | HelixFold3 | planned | — | — | — |
124
+
125
+ ## Validation
126
+
127
+ - Numerical parity with the `ipsae.py` reference implementation (Dunbrack
128
+ Lab) verified digit-for-digit on real AlphaFold3 server output: ipSAE
129
+ (both directions and d0chn variant), pDockQ, pDockQ2 and LIS all match to
130
+ 6 decimal places at the default cutoffs (10/10).
131
+ - Batch-tested on 720 real predictions across AlphaFold2-Multimer,
132
+ AlphaFold3 (server + local), Boltz-2 and Protenix — including
133
+ protein–small-molecule complexes, homodimers, monomers and negative
134
+ controls — with zero parse errors; known binders score ipSAE 0.9+, decoy
135
+ pairs < 0.1, monomers report NA.
136
+ - ColabFold and Chai-1 parsers are currently validated on synthetic
137
+ fixtures only; real-output samples welcome.
138
+
139
+ Native per-tool extras (e.g. Boltz `complex_iplddt`/`ligand_iptm`, AF3
140
+ `chain_pair_pae_min`, Chai clash flags) are preserved on
141
+ `Prediction.extras` and chain-pair ipTM is surfaced as `iptm_native` in the
142
+ interface table.
143
+
144
+ ## What each metric needs
145
+
146
+ The structure file is always required (it defines chains and tokens); the
147
+ table shows which additional inputs each metric consumes. When an input is
148
+ missing the metric is `NA` and a note lands in the `warnings` column —
149
+ nothing crashes.
150
+
151
+ | Metric (= subcommand) | pLDDT | Coordinates | PAE | Source |
152
+ |---|---|---|---|---|
153
+ | `ptm`, `iptm`, `ranking` | – | – | – | read from the tool's confidence file |
154
+ | `plddt` (mean pLDDT, ipLDDT) | yes | ipLDDT only | – | B-factors, or the tool's pLDDT file |
155
+ | `pae` (mean PAE, inter-chain PAE) | – | – | yes | tool's PAE matrix |
156
+ | `pdockq` | yes | yes | – | contacts at 8 Å between CB/C3' atoms |
157
+ | `pdockq2` | yes | yes | yes | |
158
+ | `ipsae`, `lis` | – | – | yes | chain mapping from the structure |
159
+
160
+ ## Outputs and paths
161
+
162
+ - Summary table → stdout; `-o FILE` writes it. The extension picks the
163
+ format: `.tsv` (default), `.csv`, `.json`; missing values are `NA`.
164
+ - `--interfaces FILE` → the per chain-pair table (same formats).
165
+ - `--plot DIR` → figures as described under Visualization; model names are
166
+ sanitized (`[^\w.-]` → `_`) for use as filenames.
167
+ - `plot -o DIR` defaults to `./foldmetrics_plots/`.
168
+ - Exit codes: `0` success, `1` nothing recognized/found, `2` bad arguments.
169
+
170
+ ## Conventions worth knowing
171
+
172
+ - **Tokens.** Standard residues are one token; ligands and modified residues
173
+ are one token per heavy atom (AF3-style), so token-level PAE matrices line
174
+ up across tools. pLDDT is stored on the 0–100 scale everywhere (Boltz 0–1
175
+ values are rescaled).
176
+ - **Complex-level interface metrics are the best interface.** For >2 chains,
177
+ `ipsae`/`pdockq`/`pdockq2`/`lis` in the summary table are the maximum over
178
+ chain pairs; use `--interfaces` for the full breakdown.
179
+ - **Ligand interfaces.** `pdockq`/`pdockq2`/`iplddt` are defined for
180
+ polymer–polymer interfaces only. For chain pairs involving a ligand chain,
181
+ `ipsae`/`lis` are computed over ligand atom tokens (experimental) and marked
182
+ `ipsae_mode = "tokens"` in the interface table.
183
+ - **Missing data degrades gracefully.** No PAE → PAE-based metrics are NaN
184
+ and a note lands in the `warnings` column; nothing crashes.
185
+ - **Directionality.** PAE is asymmetric, so `pdockq2`/`ipsae`/`lis` have two
186
+ directional values; the interface table reports both (`*_ab`, `*_ba`) plus
187
+ the aggregate used everywhere else (max for ipSAE/pDockQ2, mean for LIS,
188
+ matching the reference implementations).
189
+
190
+ ## References
191
+
192
+ - Bryant P, Pozzati G, Elofsson A. *Improved prediction of protein-protein
193
+ interactions using AlphaFold2.* Nat Commun 13, 1265 (2022). — pDockQ
194
+ - Zhu W, Shenoy A, Kundrotas P, Elofsson A. *Evaluation of AlphaFold-Multimer
195
+ prediction on multi-chain protein complexes.* Bioinformatics 39, btad424
196
+ (2023). — pDockQ2
197
+ - Dunbrack RL. *ipSAE: scoring pairwise interactions in AlphaFold models.*
198
+ bioRxiv 10.1101/2025.02.10.637595 (2025). — ipSAE
199
+ - Kim AR et al. *Enhanced protein-protein interaction discovery via
200
+ AlphaFold-Multimer.* bioRxiv 10.1101/2024.02.19.580970 (2024). — LIS
201
+
202
+ ## Roadmap
203
+
204
+ - HelixFold3 parser (sample outputs welcome — please open an issue)
205
+ - Real-output samples for ColabFold and Chai-1
206
+ - Per-interface PAE/ipSAE figures; interactive HTML report
207
+ - conda-forge feedstock; CI (lint + tests) on GitHub Actions
208
+
209
+ ## License
210
+
211
+ MIT
@@ -0,0 +1,92 @@
1
+ # Examples
2
+
3
+ Everything here runs without any prediction tool installed: `make_demo_data.py`
4
+ generates realistic synthetic AlphaFold3-style outputs to play with. Substitute
5
+ your real prediction folders anywhere a `demo_predictions` path appears.
6
+
7
+ ```bash
8
+ python examples/make_demo_data.py demo_predictions
9
+ ```
10
+
11
+ ## CLI recipes
12
+
13
+ `fmx` is a short alias for `foldmetrics`; they are identical.
14
+
15
+ ### Score a batch (any mix of supported tools, scanned recursively)
16
+
17
+ ```bash
18
+ fmx score demo_predictions -o metrics.tsv --interfaces interfaces.tsv --plot plots
19
+ ```
20
+
21
+ stdout (also written to `metrics.tsv`; missing values are written as `NA`):
22
+
23
+ ```
24
+ model tool chains n_chains n_tokens n_res ptm iptm ranking_score plddt_mean iplddt pae_mean ipae_mean ipsae pdockq pdockq2 lis n_interfaces has_pae
25
+ complex_with_ligand_poor alphafold3 A,B,C 3 180 170 0.680 0.380 0.450 69.624 68.924 12.315 19.943 0.266 0.467 0.011 0.473 1 True
26
+ dimer_good alphafold3 A,B 2 195 195 0.870 0.820 0.840 88.462 88.645 3.824 4.310 0.488 0.712 0.436 0.641 1 True
27
+ receptor_peptide_medium alphafold3 A,B 2 170 170 0.720 0.550 0.580 81.796 72.580 6.130 11.326 0.052 0.278 0.029 0.142 1 True
28
+ ```
29
+
30
+ Reading `complex_with_ligand_poor` is instructive: `pdockq` is deceptively
31
+ decent (0.47 — it only sees contacts and pLDDT) while `pdockq2` (0.011) and the
32
+ per-pair ipSAE expose the bad protein–protein interface; the summary `ipsae`
33
+ (0.266) comes from the *best* interface, which is the protein–ligand pair.
34
+ The `--interfaces` table shows exactly this breakdown per chain pair, including
35
+ the two directional values (`*_ab`, `*_ba`) and the tool's own chain-pair ipTM
36
+ (`iptm_native`).
37
+
38
+ `--plot plots/` writes one summary figure per model (pLDDT-colored structure
39
+ + pLDDT track + PAE heatmap + metrics panel), plus `batch_overview.png` when
40
+ there are several models, plus `comparison.png` (targets x methods, one panel
41
+ per metric) when the batch spans several targets or tools. The structure
42
+ panel uses headless PyMOL when installed (auto-detected; ~2-3 s per model) and
43
+ a fast matplotlib backbone trace otherwise:
44
+
45
+ ```bash
46
+ fmx plot demo_predictions -o plots --renderer trace # fast, no PyMOL
47
+ fmx plot demo_predictions -o plots --format pdf # vector output
48
+ ```
49
+
50
+ ### Single metrics
51
+
52
+ Every metric name is also a subcommand, so computing just one metric over a
53
+ batch is:
54
+
55
+ ```bash
56
+ fmx ipsae demo_predictions # only ipSAE columns
57
+ fmx pdockq2 demo_predictions -o pdockq2.tsv # same options as 'score'
58
+ fmx score demo_predictions --metrics ipsae,lis # any subset
59
+ ```
60
+
61
+ Available names: `ptm`, `iptm`, `ranking`, `plddt`, `pae`, `ipsae`,
62
+ `pdockq`, `pdockq2`, `lis`.
63
+
64
+ ### Other commands
65
+
66
+ ```bash
67
+ fmx detect demo_predictions # list what would be scored, per tool
68
+ fmx plot demo_predictions -o plots # figures only
69
+ fmx score run1/fold_x_full_data_0.json # a single model, via any of its files
70
+ fmx score preds/ --tool boltz # restrict auto-detection to one tool
71
+ fmx score preds/ --pae-cutoff 15 # loosen the ipSAE PAE cutoff
72
+ fmx score run1/ run2/ model_dir/ # any number of paths
73
+ ```
74
+
75
+ Output formats follow the file extension: `.tsv` (default), `.csv`, `.json`.
76
+
77
+ ## Python API
78
+
79
+ See [python_api.py](python_api.py) for a complete walkthrough:
80
+
81
+ ```bash
82
+ python examples/python_api.py demo_predictions
83
+ ```
84
+
85
+ It covers:
86
+
87
+ 1. `fm.evaluate(path)` — summary DataFrame (one row per model)
88
+ 2. `fm.evaluate_interfaces(path)` — per chain-pair DataFrame
89
+ 3. `fm.load_predictions` + `fm.compute_all` — full access to one model,
90
+ including per-residue ipSAE profiles via `foldmetrics.metrics.ipsae_asym`
91
+ 4. Figures: `save_summary_plot`, `save_batch_plot`, and composing your own
92
+ figure from `plot_plddt` / `plot_pae`