bindsight 0.3.5__py3-none-any.whl
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.
- bindsight/README.md +44 -0
- bindsight/__init__.py +15 -0
- bindsight/benchmark/__init__.py +71 -0
- bindsight/benchmark/core.py +497 -0
- bindsight/benchmark/defaults.py +28 -0
- bindsight/benchmark/designer_bench.py +899 -0
- bindsight/benchmark/outcomes.py +508 -0
- bindsight/benchmark/panel.py +621 -0
- bindsight/benchmark/rediscovery.py +1153 -0
- bindsight/benchmark/statistics.py +622 -0
- bindsight/benchmark/study.py +1153 -0
- bindsight/benchmark/study_figures.py +164 -0
- bindsight/benchmark/study_report.py +607 -0
- bindsight/cli.py +2429 -0
- bindsight/config.py +451 -0
- bindsight/cost.py +258 -0
- bindsight/deg/__init__.py +7 -0
- bindsight/deg/pydeseq2_runner.py +285 -0
- bindsight/design/__init__.py +23 -0
- bindsight/design/_common.py +501 -0
- bindsight/design/bindcraft.py +78 -0
- bindsight/design/boltzgen.py +79 -0
- bindsight/design/developability.py +140 -0
- bindsight/design/embeddings.py +165 -0
- bindsight/design/prescreen.py +169 -0
- bindsight/design/protocol.py +111 -0
- bindsight/design/rfdiff_mpnn.py +93 -0
- bindsight/epitopes/__init__.py +7 -0
- bindsight/epitopes/surface_bind.py +134 -0
- bindsight/export/__init__.py +7 -0
- bindsight/export/ro_crate.py +595 -0
- bindsight/io/__init__.py +19 -0
- bindsight/io/cbioportal.py +118 -0
- bindsight/io/gdc.py +343 -0
- bindsight/io/paths.py +124 -0
- bindsight/pipelines/__init__.py +9 -0
- bindsight/pipelines/caveats.py +60 -0
- bindsight/pipelines/discover.py +1443 -0
- bindsight/pipelines/full_run.py +410 -0
- bindsight/plugins.py +335 -0
- bindsight/provenance/__init__.py +34 -0
- bindsight/provenance/append.py +199 -0
- bindsight/provenance/fragments.py +216 -0
- bindsight/provenance/manifest.py +506 -0
- bindsight/rank/__init__.py +7 -0
- bindsight/rank/scoring.py +355 -0
- bindsight/report/__init__.py +39 -0
- bindsight/report/format.py +100 -0
- bindsight/report/html.py +645 -0
- bindsight/report/showcase.py +653 -0
- bindsight/report/templates/report.css +67 -0
- bindsight/report/templates/report.html.j2 +420 -0
- bindsight/report/theme.py +231 -0
- bindsight/report/web/__init__.py +35 -0
- bindsight/report/web/app.py +624 -0
- bindsight/report/web/static/binder_viewer.js +245 -0
- bindsight/report/web/static/bindsight.css +455 -0
- bindsight/report/web/static/charts.js +425 -0
- bindsight/report/web/static/vendor/3Dmol-min.js +2 -0
- bindsight/report/web/static/vendor/3Dmol.LICENSE +90 -0
- bindsight/report/web/static/your_data_check.js +370 -0
- bindsight/report/web/templates/base.html.j2 +48 -0
- bindsight/report/web/templates/evidence.html.j2 +341 -0
- bindsight/report/web/templates/overview.html.j2 +140 -0
- bindsight/report/web/templates/runs.html.j2 +125 -0
- bindsight/report/web/templates/try.html.j2 +155 -0
- bindsight/report/web/templates/your_data.html.j2 +46 -0
- bindsight/runners/__init__.py +7 -0
- bindsight/runners/colab.py +158 -0
- bindsight/runners/job_exec.py +1110 -0
- bindsight/runners/kaggle.py +425 -0
- bindsight/runners/kaggle_kernel.py +489 -0
- bindsight/runners/local_docker.py +154 -0
- bindsight/runners/mock.py +167 -0
- bindsight/runners/modal_runner.py +199 -0
- bindsight/runners/notebook.py +116 -0
- bindsight/runners/notebook_content.py +217 -0
- bindsight/runners/protocol.py +81 -0
- bindsight/runners/source_wheel.py +104 -0
- bindsight/runners/tools.py +997 -0
- bindsight/structures/__init__.py +7 -0
- bindsight/structures/alphafolddb.py +93 -0
- bindsight/structures/plddt.py +92 -0
- bindsight/structures/topology.py +227 -0
- bindsight/surfaceome/__init__.py +42 -0
- bindsight/surfaceome/data/surfaceome_extended.tsv +4814 -0
- bindsight/surfaceome/data/surfy_offline.txt +17 -0
- bindsight/surfaceome/data/surfy_v1.ensembl.tsv +3380 -0
- bindsight/surfaceome/data/surfy_v1.uniprot.txt +2901 -0
- bindsight/surfaceome/surfy.py +441 -0
- bindsight/targets/__init__.py +7 -0
- bindsight/targets/ensembl_uniprot.py +56 -0
- bindsight/targets/gtex.py +250 -0
- bindsight/targets/open_targets.py +239 -0
- bindsight/validate/__init__.py +7 -0
- bindsight/validate/af2_ig.py +49 -0
- bindsight/validate/boltz2.py +256 -0
- bindsight/validate/chai1r.py +42 -0
- bindsight/validate/protocol.py +188 -0
- bindsight-0.3.5.data/data/bindsight_demo/config.yaml +54 -0
- bindsight-0.3.5.dist-info/METADATA +495 -0
- bindsight-0.3.5.dist-info/RECORD +106 -0
- bindsight-0.3.5.dist-info/WHEEL +4 -0
- bindsight-0.3.5.dist-info/entry_points.txt +20 -0
- bindsight-0.3.5.dist-info/licenses/COPYRIGHT +24 -0
- bindsight-0.3.5.dist-info/licenses/LICENSE +681 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 Mikhaeel Atef Rizk Wahba
|
|
2
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
+
"""SURFACE-Bind targetable-site lookup.
|
|
4
|
+
|
|
5
|
+
SURFACE-Bind (Balbi et al., PNAS 2026; https://github.com/hamedkhakzad/SURFACE-Bind,
|
|
6
|
+
BSD-3) ships pre-computed targetable interfaces for ~2,800 human surface
|
|
7
|
+
proteins, with binder seeds for each. bindsight treats it as the canonical
|
|
8
|
+
keystone for v0.1: given a UniProt ID, look up sites + seeds and skip the
|
|
9
|
+
expensive epitope-prediction step.
|
|
10
|
+
|
|
11
|
+
Distribution: SURFACE-Bind has no public REST API. The repo provides
|
|
12
|
+
pre-computed result archives that we pin at a specific commit SHA and either
|
|
13
|
+
(a) clone-and-vendor at install time or (b) require the user to download once
|
|
14
|
+
and point at via env var. See ``data/surface_bind/README.md`` for the recipe.
|
|
15
|
+
|
|
16
|
+
The lookup is implemented over a *vendored* data tree (the SURFACE-Bind data
|
|
17
|
+
itself is user-supplied — there is no public API; see
|
|
18
|
+
``data/surface_bind/README.md`` for the recipe). When no data is vendored,
|
|
19
|
+
discovery falls back to whole-surface design and says so in the run manifest.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import json
|
|
25
|
+
import logging
|
|
26
|
+
import os
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
from typing import Any
|
|
29
|
+
|
|
30
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
31
|
+
|
|
32
|
+
LOG = logging.getLogger(__name__)
|
|
33
|
+
|
|
34
|
+
# Default vendored location, configurable via env var for CI / paid runners.
|
|
35
|
+
SURFACE_BIND_DATA_ENV = "BINDSIGHT_SURFACE_BIND_DATA"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class TargetableSite(BaseModel):
|
|
39
|
+
"""One targetable interface on a surface protein."""
|
|
40
|
+
|
|
41
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
42
|
+
|
|
43
|
+
uniprot_id: str
|
|
44
|
+
site_id: str = Field(..., description="SURFACE-Bind site ID, e.g. 'P04626_site_3'.")
|
|
45
|
+
chain: str = Field("A", description="Chain ID in the structure (default 'A').")
|
|
46
|
+
residues: list[int] = Field(..., min_length=1, description="Residue indices in the epitope.")
|
|
47
|
+
score: float | None = Field(None, description="SURFACE-Bind composite druggability score.")
|
|
48
|
+
seed_pdb_path: str | None = Field(
|
|
49
|
+
None,
|
|
50
|
+
description="Relative path to the docked binder seed (PDB), if available.",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class SurfaceBindClient:
|
|
55
|
+
"""Lookup client over a vendored SURFACE-Bind data tree."""
|
|
56
|
+
|
|
57
|
+
def __init__(self, data_root: Path | str | None = None) -> None:
|
|
58
|
+
env = os.environ.get(SURFACE_BIND_DATA_ENV)
|
|
59
|
+
chosen = data_root or env
|
|
60
|
+
if chosen is None:
|
|
61
|
+
raise RuntimeError(
|
|
62
|
+
f"SURFACE-Bind data root not configured. Set the environment variable "
|
|
63
|
+
f"{SURFACE_BIND_DATA_ENV} or pass data_root=. See "
|
|
64
|
+
"data/surface_bind/README.md for the install recipe."
|
|
65
|
+
)
|
|
66
|
+
self.data_root = Path(chosen)
|
|
67
|
+
if not self.data_root.exists():
|
|
68
|
+
raise FileNotFoundError(f"SURFACE-Bind data root does not exist: {self.data_root}")
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def _sites_dir(self) -> Path:
|
|
72
|
+
"""Directory holding one subdirectory per UniProt.
|
|
73
|
+
|
|
74
|
+
Accepts a ``data_root`` that either *contains* a ``sites/`` subtree (the
|
|
75
|
+
vendored ``data/surface_bind/`` layout) or *is* the sites tree itself
|
|
76
|
+
(the ``BINDSIGHT_SURFACE_BIND_DATA=.../sites`` env form).
|
|
77
|
+
"""
|
|
78
|
+
nested = self.data_root / "sites"
|
|
79
|
+
return nested if nested.is_dir() else self.data_root
|
|
80
|
+
|
|
81
|
+
def has(self, uniprot_id: str) -> bool:
|
|
82
|
+
"""Return True if SURFACE-Bind has any site for the given UniProt ID."""
|
|
83
|
+
return (self._sites_dir / uniprot_id / "sites.json").is_file()
|
|
84
|
+
|
|
85
|
+
def sites(self, uniprot_id: str) -> list[TargetableSite]:
|
|
86
|
+
"""Return all targetable sites for a UniProt ID; empty list if none.
|
|
87
|
+
|
|
88
|
+
Reads ``<sites>/<uniprot_id>/sites.json`` — a JSON array of records
|
|
89
|
+
``{site_id, chain, residues, score, seed_pdb}`` (bindsight's vendoring
|
|
90
|
+
contract; see ``data/surface_bind/README.md``). Records with no residues
|
|
91
|
+
are skipped (a site needs at least one). Seed paths are resolved relative
|
|
92
|
+
to the UniProt directory. Sites are returned best-score-first.
|
|
93
|
+
"""
|
|
94
|
+
path = self._sites_dir / uniprot_id / "sites.json"
|
|
95
|
+
if not path.is_file():
|
|
96
|
+
return []
|
|
97
|
+
records = json.loads(path.read_text(encoding="utf-8"))
|
|
98
|
+
out: list[TargetableSite] = []
|
|
99
|
+
for i, rec in enumerate(records):
|
|
100
|
+
residues = [int(r) for r in rec.get("residues", [])]
|
|
101
|
+
if not residues:
|
|
102
|
+
continue
|
|
103
|
+
seed = rec.get("seed_pdb") or rec.get("seed_pdb_path")
|
|
104
|
+
seed_path = str(self._sites_dir / uniprot_id / seed) if seed else None
|
|
105
|
+
score = rec.get("score")
|
|
106
|
+
out.append(
|
|
107
|
+
TargetableSite(
|
|
108
|
+
uniprot_id=uniprot_id,
|
|
109
|
+
site_id=str(rec.get("site_id") or f"{uniprot_id}_site_{i + 1}"),
|
|
110
|
+
chain=str(rec.get("chain", "A")),
|
|
111
|
+
residues=residues,
|
|
112
|
+
score=float(score) if score is not None else None,
|
|
113
|
+
seed_pdb_path=seed_path,
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
# Best-scored sites first; sites without a score sort last.
|
|
117
|
+
out.sort(key=lambda s: (s.score is not None, s.score or 0.0), reverse=True)
|
|
118
|
+
return out
|
|
119
|
+
|
|
120
|
+
def metadata(self) -> dict[str, Any]:
|
|
121
|
+
"""Return the pinned SURFACE-Bind release metadata (commit SHA, root)."""
|
|
122
|
+
commit_file = self.data_root / ".commit_sha"
|
|
123
|
+
if not commit_file.is_file():
|
|
124
|
+
# data_root may be the sites/ dir; the SHA sits beside it.
|
|
125
|
+
alt = self._sites_dir.parent / ".commit_sha"
|
|
126
|
+
commit_file = alt if alt.is_file() else commit_file
|
|
127
|
+
commit = commit_file.read_text(encoding="utf-8").strip() if commit_file.is_file() else None
|
|
128
|
+
return {
|
|
129
|
+
"source": "SURFACE-Bind (Balbi et al., PNAS 2026)",
|
|
130
|
+
"url": "https://github.com/hamedkhakzad/SURFACE-Bind",
|
|
131
|
+
"license": "BSD-3-Clause",
|
|
132
|
+
"commit_sha": commit,
|
|
133
|
+
"data_root": str(self.data_root),
|
|
134
|
+
}
|