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.
Files changed (106) hide show
  1. bindsight/README.md +44 -0
  2. bindsight/__init__.py +15 -0
  3. bindsight/benchmark/__init__.py +71 -0
  4. bindsight/benchmark/core.py +497 -0
  5. bindsight/benchmark/defaults.py +28 -0
  6. bindsight/benchmark/designer_bench.py +899 -0
  7. bindsight/benchmark/outcomes.py +508 -0
  8. bindsight/benchmark/panel.py +621 -0
  9. bindsight/benchmark/rediscovery.py +1153 -0
  10. bindsight/benchmark/statistics.py +622 -0
  11. bindsight/benchmark/study.py +1153 -0
  12. bindsight/benchmark/study_figures.py +164 -0
  13. bindsight/benchmark/study_report.py +607 -0
  14. bindsight/cli.py +2429 -0
  15. bindsight/config.py +451 -0
  16. bindsight/cost.py +258 -0
  17. bindsight/deg/__init__.py +7 -0
  18. bindsight/deg/pydeseq2_runner.py +285 -0
  19. bindsight/design/__init__.py +23 -0
  20. bindsight/design/_common.py +501 -0
  21. bindsight/design/bindcraft.py +78 -0
  22. bindsight/design/boltzgen.py +79 -0
  23. bindsight/design/developability.py +140 -0
  24. bindsight/design/embeddings.py +165 -0
  25. bindsight/design/prescreen.py +169 -0
  26. bindsight/design/protocol.py +111 -0
  27. bindsight/design/rfdiff_mpnn.py +93 -0
  28. bindsight/epitopes/__init__.py +7 -0
  29. bindsight/epitopes/surface_bind.py +134 -0
  30. bindsight/export/__init__.py +7 -0
  31. bindsight/export/ro_crate.py +595 -0
  32. bindsight/io/__init__.py +19 -0
  33. bindsight/io/cbioportal.py +118 -0
  34. bindsight/io/gdc.py +343 -0
  35. bindsight/io/paths.py +124 -0
  36. bindsight/pipelines/__init__.py +9 -0
  37. bindsight/pipelines/caveats.py +60 -0
  38. bindsight/pipelines/discover.py +1443 -0
  39. bindsight/pipelines/full_run.py +410 -0
  40. bindsight/plugins.py +335 -0
  41. bindsight/provenance/__init__.py +34 -0
  42. bindsight/provenance/append.py +199 -0
  43. bindsight/provenance/fragments.py +216 -0
  44. bindsight/provenance/manifest.py +506 -0
  45. bindsight/rank/__init__.py +7 -0
  46. bindsight/rank/scoring.py +355 -0
  47. bindsight/report/__init__.py +39 -0
  48. bindsight/report/format.py +100 -0
  49. bindsight/report/html.py +645 -0
  50. bindsight/report/showcase.py +653 -0
  51. bindsight/report/templates/report.css +67 -0
  52. bindsight/report/templates/report.html.j2 +420 -0
  53. bindsight/report/theme.py +231 -0
  54. bindsight/report/web/__init__.py +35 -0
  55. bindsight/report/web/app.py +624 -0
  56. bindsight/report/web/static/binder_viewer.js +245 -0
  57. bindsight/report/web/static/bindsight.css +455 -0
  58. bindsight/report/web/static/charts.js +425 -0
  59. bindsight/report/web/static/vendor/3Dmol-min.js +2 -0
  60. bindsight/report/web/static/vendor/3Dmol.LICENSE +90 -0
  61. bindsight/report/web/static/your_data_check.js +370 -0
  62. bindsight/report/web/templates/base.html.j2 +48 -0
  63. bindsight/report/web/templates/evidence.html.j2 +341 -0
  64. bindsight/report/web/templates/overview.html.j2 +140 -0
  65. bindsight/report/web/templates/runs.html.j2 +125 -0
  66. bindsight/report/web/templates/try.html.j2 +155 -0
  67. bindsight/report/web/templates/your_data.html.j2 +46 -0
  68. bindsight/runners/__init__.py +7 -0
  69. bindsight/runners/colab.py +158 -0
  70. bindsight/runners/job_exec.py +1110 -0
  71. bindsight/runners/kaggle.py +425 -0
  72. bindsight/runners/kaggle_kernel.py +489 -0
  73. bindsight/runners/local_docker.py +154 -0
  74. bindsight/runners/mock.py +167 -0
  75. bindsight/runners/modal_runner.py +199 -0
  76. bindsight/runners/notebook.py +116 -0
  77. bindsight/runners/notebook_content.py +217 -0
  78. bindsight/runners/protocol.py +81 -0
  79. bindsight/runners/source_wheel.py +104 -0
  80. bindsight/runners/tools.py +997 -0
  81. bindsight/structures/__init__.py +7 -0
  82. bindsight/structures/alphafolddb.py +93 -0
  83. bindsight/structures/plddt.py +92 -0
  84. bindsight/structures/topology.py +227 -0
  85. bindsight/surfaceome/__init__.py +42 -0
  86. bindsight/surfaceome/data/surfaceome_extended.tsv +4814 -0
  87. bindsight/surfaceome/data/surfy_offline.txt +17 -0
  88. bindsight/surfaceome/data/surfy_v1.ensembl.tsv +3380 -0
  89. bindsight/surfaceome/data/surfy_v1.uniprot.txt +2901 -0
  90. bindsight/surfaceome/surfy.py +441 -0
  91. bindsight/targets/__init__.py +7 -0
  92. bindsight/targets/ensembl_uniprot.py +56 -0
  93. bindsight/targets/gtex.py +250 -0
  94. bindsight/targets/open_targets.py +239 -0
  95. bindsight/validate/__init__.py +7 -0
  96. bindsight/validate/af2_ig.py +49 -0
  97. bindsight/validate/boltz2.py +256 -0
  98. bindsight/validate/chai1r.py +42 -0
  99. bindsight/validate/protocol.py +188 -0
  100. bindsight-0.3.5.data/data/bindsight_demo/config.yaml +54 -0
  101. bindsight-0.3.5.dist-info/METADATA +495 -0
  102. bindsight-0.3.5.dist-info/RECORD +106 -0
  103. bindsight-0.3.5.dist-info/WHEEL +4 -0
  104. bindsight-0.3.5.dist-info/entry_points.txt +20 -0
  105. bindsight-0.3.5.dist-info/licenses/COPYRIGHT +24 -0
  106. 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
+ }
@@ -0,0 +1,7 @@
1
+ # SPDX-FileCopyrightText: 2026 Mikhaeel Atef Rizk Wahba
2
+ # SPDX-License-Identifier: AGPL-3.0-or-later
3
+ """Export a finished run as a portable, FAIR-compliant bundle."""
4
+
5
+ from bindsight.export.ro_crate import export_ro_crate
6
+
7
+ __all__ = ["export_ro_crate"]