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,231 @@
1
+ # SPDX-FileCopyrightText: 2026 Mikhaeel Atef Rizk Wahba
2
+ # SPDX-License-Identifier: AGPL-3.0-or-later
3
+ """Shared brand constants and CSS for every bindsight presentation surface.
4
+
5
+ Before this module the brand navy, the page title, and the page icon were
6
+ re-declared independently in the app and the report
7
+ and ``report/templates/report.css``, and the docs site used an unrelated teal.
8
+ Three surfaces of one product drifted apart.
9
+
10
+ This is the single source of truth, in the same spirit as
11
+ :mod:`bindsight.pipelines.caveats` — which already shares one limitations list
12
+ between the pipeline logs, the manifest, and the HTML report.
13
+
14
+ The module deliberately imports nothing beyond the standard library so it stays
15
+ importable without the web extra (see ``tests/test_package_imports.py``).
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ # --- Identity --------------------------------------------------------------
21
+
22
+ TAGLINE = (
23
+ "RNA-seq counts → ranked de novo protein binder candidates, "
24
+ "with full provenance back to the patient cohort."
25
+ )
26
+
27
+ # --- Palette ---------------------------------------------------------------
28
+ # The navy is the established brand colour (report.css and the web interface
29
+ # already used it); everything else is derived from it.
30
+
31
+ NAVY = "#0b5394"
32
+ NAVY_DARK = "#083b6b"
33
+ NAVY_TINT = "#e8f0fb"
34
+ ACCENT = "#0f9d8f"
35
+
36
+ INK = "#1b1f24"
37
+ # Moved with docs/stylesheets/extra.css's --bs-muted, which mirrors this
38
+ # table. At #6c757d it was 4.08:1 on NAVY_TINT and 4.45:1 on CANVAS, both
39
+ # under WCAG AA, and it is used for the label under a headline number --
40
+ # the caveat, not the claim, which is the wrong half to make unreadable.
41
+ MUTED = "#5f6873"
42
+ RULE = "#e3e6ea"
43
+ SURFACE = "#ffffff"
44
+ CANVAS = "#f7f9fc"
45
+
46
+ # The web interface chose these six for contrast and its own tests hold them
47
+ # there; the values below were chosen separately and drifted, so the success
48
+ # colour ended up as #2e7d32 here, #1f7a3d on the documentation site and
49
+ # #1f6f35 in the app -- one product, three greens. The app's are now the
50
+ # shared ones, and docs/stylesheets/extra.css names all six as --bs- tokens so
51
+ # TestTheTwoPalettesAgree holds this file to them instead of parsing them and
52
+ # comparing nothing.
53
+ OK = "#1f6f35"
54
+ OK_TINT = "#e8f4ea"
55
+ WARN = "#8a6100"
56
+ WARN_TINT = "#fdf3dd"
57
+ ERR = "#a32020"
58
+ ERR_TINT = "#fbeaea"
59
+
60
+ # --- Canonical URLs --------------------------------------------------------
61
+ # These were previously hardcoded (and in the About page, pointed at raw GitHub
62
+ # blob URLs rather than the deployed documentation site).
63
+
64
+ GITHUB_URL = "https://github.com/mikhaeelatefrizk/bindsight"
65
+ DOCS_URL = "https://mikhaeelatefrizk.github.io/bindsight/"
66
+
67
+ # There was a third URL here, for a hosted deployment, and a flag recording
68
+ # whether that deployment was serving this build. It never was: the sync
69
+ # workflow uploaded nothing without a secret and reported success anyway. The
70
+ # deployment is retired and both are gone -- ``tests/test_no_hosted_space.py``
71
+ # asserts they stay gone, because a URL nothing points at is a URL something
72
+ # points at again.
73
+
74
+
75
+ def citation_line() -> str:
76
+ """How to cite: the repository, the tag and the checksums, since there is no DOI.
77
+
78
+ This function used to hold a DOI and return it as a *Markdown* link. Its
79
+ one consumer, ``overview.html.j2``, interpolates the result into HTML under
80
+ Jinja's autoescape with no Markdown filter, so the paragraph would have
81
+ rendered the brackets. It never did: the identifier was a placeholder, the
82
+ placeholder branch returned prose, and the branch that returned Markdown
83
+ never ran. The test of this very paragraph was written as
84
+ ``if theme.DOI_IS_PENDING:``, so it would have stopped running at the
85
+ instant the bug started rendering. Plain text now; the template makes the
86
+ link, and the test of it is unconditional.
87
+ """
88
+ return (
89
+ "This release is not archived under a DOI. Cite the repository, the "
90
+ "tag you ran and the checksums attached to the release: "
91
+ )
92
+
93
+
94
+ LICENSE_NAME = "AGPL-3.0-or-later"
95
+
96
+
97
+ # --- Plain-language framing ------------------------------------------------
98
+ # A one-paragraph, jargon-free description for a non-specialist visitor. Kept
99
+ # here so the web app and the docs site tell the same story. This is the
100
+ # on-ramp; the technical framing (TAGLINE) sits directly beneath it.
101
+ PLAIN_SUMMARY = (
102
+ "In plain terms: bindsight reads a tumour's gene-activity data and looks for "
103
+ "proteins that stud the surface of cancer cells but not healthy ones. It then "
104
+ "designs small custom proteins — molecular “keys” — shaped to latch onto those "
105
+ "targets, checks each design with an AI structure model to see whether it would "
106
+ "actually stick, ranks the best candidates, and keeps a complete record of how "
107
+ "it reached every answer."
108
+ )
109
+
110
+ #: Plain-English glossary of the core terms this project uses.
111
+ #:
112
+ #: ``scripts/build_docs_results.py`` regenerates ``docs/glossary.md`` from this
113
+ #: tuple and ``tests/test_docs_results.py`` fails when the committed file drifts
114
+ #: from it, so the definitions a reader sees are these ones.
115
+ #:
116
+ #: This said "single source of truth: the web app's Glossary page renders this"
117
+ #: as well, which described a second renderer that the served interface does not
118
+ #: have. One sink is not a drift risk; it is just a source.
119
+ #:
120
+ #: It lives in the package rather than beside the generator so the vocabulary
121
+ #: travels with the software, and a reader who has the package has the
122
+ #: definitions. Each entry is ``(term, plain-language definition)``.
123
+ GLOSSARY: tuple[tuple[str, str], ...] = (
124
+ (
125
+ "RNA-seq",
126
+ "A lab method that measures which genes are switched on in a tissue sample, "
127
+ "and how strongly, by sequencing its RNA. It is the starting input to bindsight.",
128
+ ),
129
+ (
130
+ "Differential expression (DEG)",
131
+ "Comparing gene activity between two groups — here tumour versus healthy "
132
+ "tissue — to find the genes turned notably up or down in disease.",
133
+ ),
134
+ (
135
+ "log2 fold-change (log2FC)",
136
+ "How many times higher or lower a gene's activity is between the two groups, "
137
+ "on a log2 scale: a value of 4 means about 16× higher in tumour.",
138
+ ),
139
+ (
140
+ "padj / FDR",
141
+ "A confidence figure that a difference is real rather than chance, adjusted "
142
+ "for testing thousands of genes at once. Smaller is stronger (e.g. 1e-59 is "
143
+ "overwhelming evidence).",
144
+ ),
145
+ (
146
+ "Antigen",
147
+ "A molecule a drug or the immune system can recognise and target. In bindsight "
148
+ "the antigens of interest are proteins sitting on the cell surface.",
149
+ ),
150
+ (
151
+ "Surfaceome",
152
+ "The full set of proteins that sit on the outer surface of cells — the ones a "
153
+ "binder could physically reach. bindsight keeps only surface proteins as targets.",
154
+ ),
155
+ (
156
+ "De novo protein binder",
157
+ "A small protein designed from scratch (rather than borrowed from nature) to "
158
+ "stick tightly and specifically to a chosen target protein.",
159
+ ),
160
+ (
161
+ "RFdiffusion + ProteinMPNN",
162
+ "Two AI models used together: RFdiffusion invents a plausible 3-D shape for a "
163
+ "binder against the target, and ProteinMPNN chooses an amino-acid sequence that "
164
+ "would fold into that shape.",
165
+ ),
166
+ (
167
+ "Boltz-2",
168
+ "An AI model that predicts the 3-D structure of the binder and target locked "
169
+ "together, and reports how confident it is in that predicted interface. "
170
+ "Confidence is not a binding measurement: bindsight's own paired control "
171
+ "folded each design beside a shuffle of its own sequence, and the shuffles "
172
+ "scored as well. Treat these numbers as a filter to triage wet-lab work, "
173
+ "never as evidence that a design binds.",
174
+ ),
175
+ (
176
+ "ipTM",
177
+ "A 0–1 score of how confident the structure model is in the predicted "
178
+ "interface between two proteins. 0.65 is the threshold the de novo design "
179
+ "literature commonly uses, and bindsight reports against it for "
180
+ "comparability — but its own scramble control could not separate real "
181
+ "designs from shuffles of the same composition at that cutoff, so a value "
182
+ "above 0.65 is not on its own evidence of a binder. See the calibration.",
183
+ ),
184
+ (
185
+ "PAE (interaction)",
186
+ "Predicted Aligned Error at the binding interface, in ångströms — how uncertain "
187
+ "the model is about the contact. Lower means a more trustworthy predicted grip.",
188
+ ),
189
+ (
190
+ "Developability",
191
+ "How practical a designed protein would be to actually make and use: is it "
192
+ "stable, soluble, and free of trouble-prone residues? Good scores mean fewer "
193
+ "surprises in the lab.",
194
+ ),
195
+ (
196
+ "Provenance / RO-Crate",
197
+ "A complete, machine-readable record of every input, tool version and step, "
198
+ "packaged (as an RO-Crate) so anyone can retrace and reproduce a result — and "
199
+ "cite it.",
200
+ ),
201
+ (
202
+ "ERBB2 (HER2)",
203
+ "A well-known breast-cancer cell-surface antigen and an approved drug target — "
204
+ "the canonical positive control for a discovery pipeline. bindsight does *not* "
205
+ "rediscover it: in the whole unstratified TCGA-BRCA cohort it measures log2fc "
206
+ "0.92, below the fold-change floor, so it does not clear the "
207
+ "significance rule. That is a limit of bulk differential expression, not of "
208
+ "the ranking; see benchmarks/study/RESULTS.md.",
209
+ ),
210
+ )
211
+
212
+
213
+ def docs_url(page: str = "") -> str:
214
+ """Build a URL into the deployed documentation site.
215
+
216
+ Args:
217
+ page: Page slug without extension, e.g. ``"what-is-bindsight"``.
218
+ Empty string returns the docs home.
219
+
220
+ Returns:
221
+ Absolute URL on the GitHub Pages documentation site.
222
+ """
223
+ if not page:
224
+ return DOCS_URL
225
+ return f"{DOCS_URL}{page.strip('/')}/"
226
+
227
+
228
+ # No stylesheet is emitted from this module. The design system is one CSS file
229
+ # under ``report/web/static/``, shared between the served interface and the
230
+ # standalone HTML report, so the two cannot drift apart. What lives here is the
231
+ # palette and the vocabulary those surfaces are built from.
@@ -0,0 +1,35 @@
1
+ # SPDX-FileCopyrightText: 2026 Mikhaeel Atef Rizk Wahba
2
+ # SPDX-License-Identifier: AGPL-3.0-or-later
3
+ """The bindsight web interface.
4
+
5
+ Server-rendered HTML over the same data layer the standalone report reads
6
+ (:mod:`bindsight.report.showcase`), with one stylesheet shared between them so
7
+ the interactive app and the file a collaborator opens from an email look like
8
+ the same instrument.
9
+
10
+ Replaces the Streamlit app. That is a reduction, not an addition: Streamlit
11
+ declares 34 requirements against this stack's handful, and every number on a
12
+ Streamlit page had to be expressed through a widget whose layout the caller does
13
+ not control -- which is how confidence intervals ended up inside hover tooltips
14
+ underneath a paragraph promising every rate carried its interval.
15
+
16
+ Nothing here needs a build step, a package manager, or a network. The one
17
+ third-party asset is 3Dmol.js, vendored under ``static/vendor/`` so the
18
+ structure viewer works offline; the previous viewer fetched it from a CDN, so it
19
+ silently required internet.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ __all__ = ["create_app", "serve"]
25
+
26
+
27
+ def __getattr__(name: str) -> object:
28
+ # Imported lazily so ``import bindsight.report`` does not require the web
29
+ # extra. ``bindsight doctor`` and the CLI's non-UI paths must work on an
30
+ # install that never asked for a server.
31
+ if name in __all__:
32
+ from bindsight.report.web.app import create_app, serve
33
+
34
+ return {"create_app": create_app, "serve": serve}[name]
35
+ raise AttributeError(name)