marimo-mmp 0.0.1__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.
- marimo_mmp-0.0.1/.gitignore +17 -0
- marimo_mmp-0.0.1/LICENSE +21 -0
- marimo_mmp-0.0.1/PKG-INFO +228 -0
- marimo_mmp-0.0.1/README.md +195 -0
- marimo_mmp-0.0.1/frontend/transform_graph/controls.ts +289 -0
- marimo_mmp-0.0.1/frontend/transform_graph/depiction.ts +5 -0
- marimo_mmp-0.0.1/frontend/transform_graph/dom.ts +38 -0
- marimo_mmp-0.0.1/frontend/transform_graph/encoding.ts +17 -0
- marimo_mmp-0.0.1/frontend/transform_graph/graph.ts +330 -0
- marimo_mmp-0.0.1/frontend/transform_graph/layout.ts +38 -0
- marimo_mmp-0.0.1/frontend/transform_graph/selection.ts +75 -0
- marimo_mmp-0.0.1/frontend/transform_graph/shell.ts +67 -0
- marimo_mmp-0.0.1/frontend/transform_graph/tooltips.ts +210 -0
- marimo_mmp-0.0.1/frontend/transform_graph/types.ts +191 -0
- marimo_mmp-0.0.1/frontend/transform_graph/viewport.ts +140 -0
- marimo_mmp-0.0.1/frontend/transform_graph.css +163 -0
- marimo_mmp-0.0.1/frontend/transform_graph.ts +123 -0
- marimo_mmp-0.0.1/package-lock.json +627 -0
- marimo_mmp-0.0.1/package.json +20 -0
- marimo_mmp-0.0.1/pyproject.toml +105 -0
- marimo_mmp-0.0.1/scripts/hatch_build.py +43 -0
- marimo_mmp-0.0.1/src/marimo_mmp/__init__.py +33 -0
- marimo_mmp-0.0.1/src/marimo_mmp/dataset.py +425 -0
- marimo_mmp-0.0.1/src/marimo_mmp/depiction.py +88 -0
- marimo_mmp-0.0.1/src/marimo_mmp/models.py +241 -0
- marimo_mmp-0.0.1/src/marimo_mmp/parsing.py +329 -0
- marimo_mmp-0.0.1/src/marimo_mmp/provenance.py +131 -0
- marimo_mmp-0.0.1/src/marimo_mmp/py.typed +0 -0
- marimo_mmp-0.0.1/src/marimo_mmp/static/transform_graph.css +1 -0
- marimo_mmp-0.0.1/src/marimo_mmp/static/transform_graph.js +4 -0
- marimo_mmp-0.0.1/src/marimo_mmp/widget.py +627 -0
- marimo_mmp-0.0.1/tsconfig.json +14 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv
|
|
11
|
+
|
|
12
|
+
# Rebuildable mmpdb intermediate
|
|
13
|
+
data/processed/*.fragdb
|
|
14
|
+
__marimo__
|
|
15
|
+
node_modules/
|
|
16
|
+
src/marimo_mmp/static/transform_graph.js
|
|
17
|
+
src/marimo_mmp/static/transform_graph.css
|
marimo_mmp-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Anton Siomchen
|
|
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,228 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: marimo-mmp
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Reactive visualization of mmpdb transform results
|
|
5
|
+
Project-URL: Homepage, https://github.com/asiomchen/marimo_mmp
|
|
6
|
+
Project-URL: Repository, https://github.com/asiomchen/marimo_mmp
|
|
7
|
+
Project-URL: Issues, https://github.com/asiomchen/marimo_mmp/issues
|
|
8
|
+
Project-URL: Documentation, https://github.com/asiomchen/marimo_mmp/blob/main/README.md
|
|
9
|
+
Author-email: Anton Siomchen <41703271+asiomchen@users.noreply.github.com>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: anywidget,cheminformatics,marimo,matched molecular pairs,medicinal chemistry,mmpdb,rdkit,visualization
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.11
|
|
26
|
+
Requires-Dist: anywidget>=0.9
|
|
27
|
+
Requires-Dist: pandas>=2.2.2
|
|
28
|
+
Requires-Dist: rdkit>=2024.9.1
|
|
29
|
+
Requires-Dist: traitlets>=5
|
|
30
|
+
Provides-Extra: notebook
|
|
31
|
+
Requires-Dist: marimo>=0.24.0; extra == 'notebook'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# marimo_mmp
|
|
35
|
+
|
|
36
|
+
[](https://github.com/asiomchen/marimo_mmp/blob/main/pyproject.toml)
|
|
37
|
+
[](https://github.com/asiomchen/marimo_mmp/blob/main/tsconfig.json)
|
|
38
|
+
[](https://anywidget.dev/)
|
|
39
|
+
|
|
40
|
+
`marimo-mmp` visualizes `mmpdb transform` results as an interactive molecular
|
|
41
|
+
graph: query compound, transformation rules, and generated products. Filter by
|
|
42
|
+
effect and support, select products, and inspect source pairs. It uses anywidget;
|
|
43
|
+
marimo is optional. Packaged JavaScript and CSS need no CDN or runtime npm.
|
|
44
|
+
|
|
45
|
+
Use `mmpdb>=3.1.3` to [prepare input data](#preparing-data-with-mmpdb).
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
## Quickstart
|
|
49
|
+
|
|
50
|
+
Requires Python ≥3.11. Install with pip:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
pip install 'marimo-mmp[notebook]'
|
|
54
|
+
```
|
|
55
|
+
Or with uv:
|
|
56
|
+
```bash
|
|
57
|
+
uv add 'marimo-mmp[notebook]'
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
import marimo as mo
|
|
63
|
+
|
|
64
|
+
from marimo_mmp import (
|
|
65
|
+
EvidenceThresholds,
|
|
66
|
+
TransformDataset,
|
|
67
|
+
TransformFilters,
|
|
68
|
+
TransformGraph,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
dataset = TransformDataset.from_tsv(
|
|
72
|
+
"transforms.tsv",
|
|
73
|
+
original_smiles="CCO", # optional query SMILES
|
|
74
|
+
mmpdb_path="assay.mmpdb", # optional provenance database
|
|
75
|
+
evidence_thresholds=EvidenceThresholds(moderate=2, strong=5),
|
|
76
|
+
)
|
|
77
|
+
graph = mo.ui.anywidget(
|
|
78
|
+
TransformGraph(
|
|
79
|
+
dataset,
|
|
80
|
+
property_name="pIC50",
|
|
81
|
+
filters=TransformFilters(effect="gain", min_support=2),
|
|
82
|
+
max_nodes=100,
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
graph
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
In marimo, assign `graph` in one cell and read its immutable
|
|
89
|
+
`TransformGraphState` in a downstream cell that reruns on interaction:
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
state = graph.state
|
|
93
|
+
state.selected_compound, state.selected_stats # typed records, or None
|
|
94
|
+
state.property_name, state.filters # active property and typed filters
|
|
95
|
+
state.shown_count, state.matching_count # rendered versus matching products
|
|
96
|
+
state.rows() # table-ready rows
|
|
97
|
+
state.source_pairs() # in-memory pairs for selected product
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`graph.value` is marimo's synchronized trait dictionary; `graph.widget` is the
|
|
101
|
+
raw widget. `graph.update(dataset, property_name=..., filters=..., max_nodes=...)`
|
|
102
|
+
retains a still-visible selection. Omitted options select the dataset's first
|
|
103
|
+
property, all products, and a limit of 100; direction retains its current value
|
|
104
|
+
unless supplied. Other anywidget hosts display `TransformGraph(dataset)` directly. The
|
|
105
|
+
[explorer notebook](https://github.com/asiomchen/marimo_mmp/blob/main/notebooks/transform_explorer.py) includes the full state reference.
|
|
106
|
+
|
|
107
|
+
Changed-atom highlighting is off by default. Enable it with
|
|
108
|
+
`TransformGraph(dataset, highlight_changes=True)` when the dataset has query SMILES.
|
|
109
|
+
Highlighting can make the first render slower because it searches for the common
|
|
110
|
+
substructure of each product and the query; subsequent renders reuse cached SVGs.
|
|
111
|
+
|
|
112
|
+
## Preparing data with mmpdb
|
|
113
|
+
|
|
114
|
+
Use [mmpdb](https://github.com/rdkit/mmpdb) to build a matched-pair database and
|
|
115
|
+
apply its transformations to a query compound. With `compounds.smi` containing
|
|
116
|
+
SMILES and compound IDs, and `properties.tsv` containing an `ID` column and a
|
|
117
|
+
numeric `pIC50` column with matching IDs:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
pip install 'mmpdb>=3.1.3'
|
|
121
|
+
mmpdb fragment compounds.smi --num-jobs 1 -o compounds.fragdb
|
|
122
|
+
mmpdb index compounds.fragdb --properties properties.tsv -o assay.mmpdb
|
|
123
|
+
mmpdb transform assay.mmpdb --smiles 'CCO' --property pIC50 -o transforms.tsv
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Replace `CCO` and `pIC50` with your query SMILES and property name. Use the same
|
|
127
|
+
query SMILES as `original_smiles` when loading the output in the quickstart.
|
|
128
|
+
|
|
129
|
+
| Output | Use in the widget |
|
|
130
|
+
|---|---|
|
|
131
|
+
| `transforms.tsv` from `mmpdb transform` | Required input: generated product SMILES, transformation rules, environments, and property-change statistics. |
|
|
132
|
+
| `assay.mmpdb` from `mmpdb index` | Optional SQLite input via `mmpdb_path=...`: source compound pairs and their measured property values for provenance. Use the same database that generated the TSV. |
|
|
133
|
+
| `compounds.fragdb` from `mmpdb fragment` | Intermediate used by indexing; the widget does not read it. |
|
|
134
|
+
|
|
135
|
+
Keep property statistics in the transform output; `--no-properties`,
|
|
136
|
+
`mmpdb generate` output, and pair tables exported by `mmpdb index` do not supply the columns the widget requires. The widget loads existing TSV and SQLite files directly, so the `mmpdb` Python package is needed only for data generation. The
|
|
137
|
+
repository's development dependency group includes its CLI.
|
|
138
|
+
|
|
139
|
+
## Data and API
|
|
140
|
+
|
|
141
|
+
`TransformDataset.from_tsv` accepts paths, bytes, or readable streams of UTF-8
|
|
142
|
+
TSV/CSV; `from_df` accepts pandas DataFrames. Both validate
|
|
143
|
+
`ID`, `SMILES`, and mmpdb statistic columns and discover property families.
|
|
144
|
+
Invalid transform data raises `TransformValidationError`. Optional MMPDBs are
|
|
145
|
+
validated and opened read-only during loading. Duplicate column names, empty
|
|
146
|
+
rule fragments, negative standard deviations, p-values outside `[0, 1]`, and
|
|
147
|
+
out-of-order min/quartile/median/max summaries are rejected. Source pairs for
|
|
148
|
+
every transform and property, including pairs with missing values, are stored in memory;
|
|
149
|
+
`source_pairs()` needs no further database access. The database file can be
|
|
150
|
+
removed after loading. `dataset.mmpdb_path` retains its original path as source
|
|
151
|
+
metadata. Larger provenance sets increase loading time and memory use.
|
|
152
|
+
|
|
153
|
+
| Parameter | Meaning |
|
|
154
|
+
|---|---|
|
|
155
|
+
| `TransformGraph(dataset, property_name=..., max_nodes=100)` | Property from `dataset.properties` (default: first); product limit after filtering and ranking. |
|
|
156
|
+
| `TransformGraph(..., direction="higher")` | Favorable orientation: `higher` or `lower`; controls gain/loss filtering and colors. |
|
|
157
|
+
| `TransformFilters(effect=...)` | `all` (default), `gain`, `loss`, or `neutral`, following the orientation. |
|
|
158
|
+
| Other filter fields | `min_abs_effect`, `min_support`, `radii`, `quality`, `text`, `max_std`, `max_p_value`. Use tuples for radii and evidence names in `quality`. |
|
|
159
|
+
| `EvidenceThresholds(moderate=2, strong=5)` | Inclusive pair-count minima: Moderate ≥2; Strong > Moderate. |
|
|
160
|
+
| `TransformGraph(..., height=1220)` | Stage height cap in pixels (minimum 480), also limited by the viewport. |
|
|
161
|
+
| `TransformGraph(..., highlight_changes=False)` | Constructor setting for changed-atom highlights; retained across updates and copies. Query structure remains visible when highlighting is off. |
|
|
162
|
+
|
|
163
|
+
Default evidence tiers summarize database support: **Exploratory** = 1 pair,
|
|
164
|
+
**Moderate** = 2–4, **Strong** ≥5. Generated products are not experimentally
|
|
165
|
+
validated by these labels. Missing standard deviation, quartiles, or p-values
|
|
166
|
+
produce warnings. Effects are supplied property deltas. Changing evidence chips
|
|
167
|
+
resets minimum support to 1; changing minimum support selects all evidence levels.
|
|
168
|
+
|
|
169
|
+
For data-only filtering and table export, `dataset.view(...)` remains available
|
|
170
|
+
and provides `rows()` and `source_pairs()` without constructing a widget.
|
|
171
|
+
|
|
172
|
+
## Example data
|
|
173
|
+
|
|
174
|
+
The explorer and tests use `data/processed/bilastine_transforms.tsv` and
|
|
175
|
+
`data/processed/h1_ic50.mmpdb`. These examples derive from ChEMBL 37 data for the
|
|
176
|
+
human histamine H1 receptor (HRH1, UniProt `P35367`,
|
|
177
|
+
[ChEMBL target `CHEMBL231`](https://www.ebi.ac.uk/chembl/explore/target/CHEMBL231)),
|
|
178
|
+
retrieved on August 26, 2026. Cite ChEMBL 37 when reusing this derived data.
|
|
179
|
+
[build_report.json](https://github.com/asiomchen/marimo_mmp/blob/main/data/processed/build_report.json) records the release,
|
|
180
|
+
retrieval timestamp, and validation counts.
|
|
181
|
+
|
|
182
|
+
The database uses exact, positive IC50 measurements in nM from direct human H1
|
|
183
|
+
binding assays, excluding potential duplicates and records with data-validity
|
|
184
|
+
comments. RDKit cleanup and parent-fragment selection standardized structures.
|
|
185
|
+
Each measurement was converted to `pIC50 = 9 - log10(IC50_nM)`; the median per
|
|
186
|
+
parent ChEMBL molecule became its sole property. The selection retained 117
|
|
187
|
+
measurements across 107 compounds, with 74 compounds indexed in the MMPDB.
|
|
188
|
+
|
|
189
|
+
## Contributing
|
|
190
|
+
|
|
191
|
+
Use uv with Python 3.11 and Node.js ≥20. From the repository root:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
npm ci
|
|
195
|
+
uv sync --locked --python 3.11 --group dev
|
|
196
|
+
npm run build
|
|
197
|
+
uv run marimo edit notebooks/transform_explorer.py
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Sources: Python in `src/marimo_mmp/`, TypeScript/CSS in `frontend/`, examples in
|
|
201
|
+
`notebooks/`, tools in `scripts/`. See [WIDGET_ARCHITECTURE.md](https://github.com/asiomchen/marimo_mmp/blob/main/WIDGET_ARCHITECTURE.md)
|
|
202
|
+
for internals and [AGENTS.md](https://github.com/asiomchen/marimo_mmp/blob/main/AGENTS.md) for conventions.
|
|
203
|
+
|
|
204
|
+
Run the CI checks and package verification:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
npm run check
|
|
208
|
+
uv run ruff check src tests scripts
|
|
209
|
+
uv run ruff format --check src tests scripts
|
|
210
|
+
uv run ty check
|
|
211
|
+
uv run pytest
|
|
212
|
+
uv run marimo check --strict notebooks/*.py
|
|
213
|
+
uv run hatch build --clean
|
|
214
|
+
uv run python scripts/verify_distribution_assets.py dist/*
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
`npm run check` type-checks TypeScript and tests rebuilt assets. After frontend
|
|
218
|
+
edits, run `npm run build`, or `npm run dev` to watch. Runtime assets in
|
|
219
|
+
`src/marimo_mmp/static/` are gitignored; Hatch builds missing assets and includes
|
|
220
|
+
them in wheels/sdists. Use `uv run hatch version [VERSION]` to inspect/update the
|
|
221
|
+
version. Ruff also runs via pre-commit.
|
|
222
|
+
|
|
223
|
+
## License
|
|
224
|
+
|
|
225
|
+
Code and documentation are licensed under the [MIT License](https://github.com/asiomchen/marimo_mmp/blob/main/LICENSE).
|
|
226
|
+
The ChEMBL-derived example data is distributed under
|
|
227
|
+
[CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/); see
|
|
228
|
+
[Example data](#example-data) for provenance and attribution.
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# marimo_mmp
|
|
2
|
+
|
|
3
|
+
[](https://github.com/asiomchen/marimo_mmp/blob/main/pyproject.toml)
|
|
4
|
+
[](https://github.com/asiomchen/marimo_mmp/blob/main/tsconfig.json)
|
|
5
|
+
[](https://anywidget.dev/)
|
|
6
|
+
|
|
7
|
+
`marimo-mmp` visualizes `mmpdb transform` results as an interactive molecular
|
|
8
|
+
graph: query compound, transformation rules, and generated products. Filter by
|
|
9
|
+
effect and support, select products, and inspect source pairs. It uses anywidget;
|
|
10
|
+
marimo is optional. Packaged JavaScript and CSS need no CDN or runtime npm.
|
|
11
|
+
|
|
12
|
+
Use `mmpdb>=3.1.3` to [prepare input data](#preparing-data-with-mmpdb).
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## Quickstart
|
|
16
|
+
|
|
17
|
+
Requires Python ≥3.11. Install with pip:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
pip install 'marimo-mmp[notebook]'
|
|
21
|
+
```
|
|
22
|
+
Or with uv:
|
|
23
|
+
```bash
|
|
24
|
+
uv add 'marimo-mmp[notebook]'
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
import marimo as mo
|
|
30
|
+
|
|
31
|
+
from marimo_mmp import (
|
|
32
|
+
EvidenceThresholds,
|
|
33
|
+
TransformDataset,
|
|
34
|
+
TransformFilters,
|
|
35
|
+
TransformGraph,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
dataset = TransformDataset.from_tsv(
|
|
39
|
+
"transforms.tsv",
|
|
40
|
+
original_smiles="CCO", # optional query SMILES
|
|
41
|
+
mmpdb_path="assay.mmpdb", # optional provenance database
|
|
42
|
+
evidence_thresholds=EvidenceThresholds(moderate=2, strong=5),
|
|
43
|
+
)
|
|
44
|
+
graph = mo.ui.anywidget(
|
|
45
|
+
TransformGraph(
|
|
46
|
+
dataset,
|
|
47
|
+
property_name="pIC50",
|
|
48
|
+
filters=TransformFilters(effect="gain", min_support=2),
|
|
49
|
+
max_nodes=100,
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
graph
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
In marimo, assign `graph` in one cell and read its immutable
|
|
56
|
+
`TransformGraphState` in a downstream cell that reruns on interaction:
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
state = graph.state
|
|
60
|
+
state.selected_compound, state.selected_stats # typed records, or None
|
|
61
|
+
state.property_name, state.filters # active property and typed filters
|
|
62
|
+
state.shown_count, state.matching_count # rendered versus matching products
|
|
63
|
+
state.rows() # table-ready rows
|
|
64
|
+
state.source_pairs() # in-memory pairs for selected product
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`graph.value` is marimo's synchronized trait dictionary; `graph.widget` is the
|
|
68
|
+
raw widget. `graph.update(dataset, property_name=..., filters=..., max_nodes=...)`
|
|
69
|
+
retains a still-visible selection. Omitted options select the dataset's first
|
|
70
|
+
property, all products, and a limit of 100; direction retains its current value
|
|
71
|
+
unless supplied. Other anywidget hosts display `TransformGraph(dataset)` directly. The
|
|
72
|
+
[explorer notebook](https://github.com/asiomchen/marimo_mmp/blob/main/notebooks/transform_explorer.py) includes the full state reference.
|
|
73
|
+
|
|
74
|
+
Changed-atom highlighting is off by default. Enable it with
|
|
75
|
+
`TransformGraph(dataset, highlight_changes=True)` when the dataset has query SMILES.
|
|
76
|
+
Highlighting can make the first render slower because it searches for the common
|
|
77
|
+
substructure of each product and the query; subsequent renders reuse cached SVGs.
|
|
78
|
+
|
|
79
|
+
## Preparing data with mmpdb
|
|
80
|
+
|
|
81
|
+
Use [mmpdb](https://github.com/rdkit/mmpdb) to build a matched-pair database and
|
|
82
|
+
apply its transformations to a query compound. With `compounds.smi` containing
|
|
83
|
+
SMILES and compound IDs, and `properties.tsv` containing an `ID` column and a
|
|
84
|
+
numeric `pIC50` column with matching IDs:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
pip install 'mmpdb>=3.1.3'
|
|
88
|
+
mmpdb fragment compounds.smi --num-jobs 1 -o compounds.fragdb
|
|
89
|
+
mmpdb index compounds.fragdb --properties properties.tsv -o assay.mmpdb
|
|
90
|
+
mmpdb transform assay.mmpdb --smiles 'CCO' --property pIC50 -o transforms.tsv
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Replace `CCO` and `pIC50` with your query SMILES and property name. Use the same
|
|
94
|
+
query SMILES as `original_smiles` when loading the output in the quickstart.
|
|
95
|
+
|
|
96
|
+
| Output | Use in the widget |
|
|
97
|
+
|---|---|
|
|
98
|
+
| `transforms.tsv` from `mmpdb transform` | Required input: generated product SMILES, transformation rules, environments, and property-change statistics. |
|
|
99
|
+
| `assay.mmpdb` from `mmpdb index` | Optional SQLite input via `mmpdb_path=...`: source compound pairs and their measured property values for provenance. Use the same database that generated the TSV. |
|
|
100
|
+
| `compounds.fragdb` from `mmpdb fragment` | Intermediate used by indexing; the widget does not read it. |
|
|
101
|
+
|
|
102
|
+
Keep property statistics in the transform output; `--no-properties`,
|
|
103
|
+
`mmpdb generate` output, and pair tables exported by `mmpdb index` do not supply the columns the widget requires. The widget loads existing TSV and SQLite files directly, so the `mmpdb` Python package is needed only for data generation. The
|
|
104
|
+
repository's development dependency group includes its CLI.
|
|
105
|
+
|
|
106
|
+
## Data and API
|
|
107
|
+
|
|
108
|
+
`TransformDataset.from_tsv` accepts paths, bytes, or readable streams of UTF-8
|
|
109
|
+
TSV/CSV; `from_df` accepts pandas DataFrames. Both validate
|
|
110
|
+
`ID`, `SMILES`, and mmpdb statistic columns and discover property families.
|
|
111
|
+
Invalid transform data raises `TransformValidationError`. Optional MMPDBs are
|
|
112
|
+
validated and opened read-only during loading. Duplicate column names, empty
|
|
113
|
+
rule fragments, negative standard deviations, p-values outside `[0, 1]`, and
|
|
114
|
+
out-of-order min/quartile/median/max summaries are rejected. Source pairs for
|
|
115
|
+
every transform and property, including pairs with missing values, are stored in memory;
|
|
116
|
+
`source_pairs()` needs no further database access. The database file can be
|
|
117
|
+
removed after loading. `dataset.mmpdb_path` retains its original path as source
|
|
118
|
+
metadata. Larger provenance sets increase loading time and memory use.
|
|
119
|
+
|
|
120
|
+
| Parameter | Meaning |
|
|
121
|
+
|---|---|
|
|
122
|
+
| `TransformGraph(dataset, property_name=..., max_nodes=100)` | Property from `dataset.properties` (default: first); product limit after filtering and ranking. |
|
|
123
|
+
| `TransformGraph(..., direction="higher")` | Favorable orientation: `higher` or `lower`; controls gain/loss filtering and colors. |
|
|
124
|
+
| `TransformFilters(effect=...)` | `all` (default), `gain`, `loss`, or `neutral`, following the orientation. |
|
|
125
|
+
| Other filter fields | `min_abs_effect`, `min_support`, `radii`, `quality`, `text`, `max_std`, `max_p_value`. Use tuples for radii and evidence names in `quality`. |
|
|
126
|
+
| `EvidenceThresholds(moderate=2, strong=5)` | Inclusive pair-count minima: Moderate ≥2; Strong > Moderate. |
|
|
127
|
+
| `TransformGraph(..., height=1220)` | Stage height cap in pixels (minimum 480), also limited by the viewport. |
|
|
128
|
+
| `TransformGraph(..., highlight_changes=False)` | Constructor setting for changed-atom highlights; retained across updates and copies. Query structure remains visible when highlighting is off. |
|
|
129
|
+
|
|
130
|
+
Default evidence tiers summarize database support: **Exploratory** = 1 pair,
|
|
131
|
+
**Moderate** = 2–4, **Strong** ≥5. Generated products are not experimentally
|
|
132
|
+
validated by these labels. Missing standard deviation, quartiles, or p-values
|
|
133
|
+
produce warnings. Effects are supplied property deltas. Changing evidence chips
|
|
134
|
+
resets minimum support to 1; changing minimum support selects all evidence levels.
|
|
135
|
+
|
|
136
|
+
For data-only filtering and table export, `dataset.view(...)` remains available
|
|
137
|
+
and provides `rows()` and `source_pairs()` without constructing a widget.
|
|
138
|
+
|
|
139
|
+
## Example data
|
|
140
|
+
|
|
141
|
+
The explorer and tests use `data/processed/bilastine_transforms.tsv` and
|
|
142
|
+
`data/processed/h1_ic50.mmpdb`. These examples derive from ChEMBL 37 data for the
|
|
143
|
+
human histamine H1 receptor (HRH1, UniProt `P35367`,
|
|
144
|
+
[ChEMBL target `CHEMBL231`](https://www.ebi.ac.uk/chembl/explore/target/CHEMBL231)),
|
|
145
|
+
retrieved on August 26, 2026. Cite ChEMBL 37 when reusing this derived data.
|
|
146
|
+
[build_report.json](https://github.com/asiomchen/marimo_mmp/blob/main/data/processed/build_report.json) records the release,
|
|
147
|
+
retrieval timestamp, and validation counts.
|
|
148
|
+
|
|
149
|
+
The database uses exact, positive IC50 measurements in nM from direct human H1
|
|
150
|
+
binding assays, excluding potential duplicates and records with data-validity
|
|
151
|
+
comments. RDKit cleanup and parent-fragment selection standardized structures.
|
|
152
|
+
Each measurement was converted to `pIC50 = 9 - log10(IC50_nM)`; the median per
|
|
153
|
+
parent ChEMBL molecule became its sole property. The selection retained 117
|
|
154
|
+
measurements across 107 compounds, with 74 compounds indexed in the MMPDB.
|
|
155
|
+
|
|
156
|
+
## Contributing
|
|
157
|
+
|
|
158
|
+
Use uv with Python 3.11 and Node.js ≥20. From the repository root:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
npm ci
|
|
162
|
+
uv sync --locked --python 3.11 --group dev
|
|
163
|
+
npm run build
|
|
164
|
+
uv run marimo edit notebooks/transform_explorer.py
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Sources: Python in `src/marimo_mmp/`, TypeScript/CSS in `frontend/`, examples in
|
|
168
|
+
`notebooks/`, tools in `scripts/`. See [WIDGET_ARCHITECTURE.md](https://github.com/asiomchen/marimo_mmp/blob/main/WIDGET_ARCHITECTURE.md)
|
|
169
|
+
for internals and [AGENTS.md](https://github.com/asiomchen/marimo_mmp/blob/main/AGENTS.md) for conventions.
|
|
170
|
+
|
|
171
|
+
Run the CI checks and package verification:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
npm run check
|
|
175
|
+
uv run ruff check src tests scripts
|
|
176
|
+
uv run ruff format --check src tests scripts
|
|
177
|
+
uv run ty check
|
|
178
|
+
uv run pytest
|
|
179
|
+
uv run marimo check --strict notebooks/*.py
|
|
180
|
+
uv run hatch build --clean
|
|
181
|
+
uv run python scripts/verify_distribution_assets.py dist/*
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
`npm run check` type-checks TypeScript and tests rebuilt assets. After frontend
|
|
185
|
+
edits, run `npm run build`, or `npm run dev` to watch. Runtime assets in
|
|
186
|
+
`src/marimo_mmp/static/` are gitignored; Hatch builds missing assets and includes
|
|
187
|
+
them in wheels/sdists. Use `uv run hatch version [VERSION]` to inspect/update the
|
|
188
|
+
version. Ruff also runs via pre-commit.
|
|
189
|
+
|
|
190
|
+
## License
|
|
191
|
+
|
|
192
|
+
Code and documentation are licensed under the [MIT License](https://github.com/asiomchen/marimo_mmp/blob/main/LICENSE).
|
|
193
|
+
The ChEMBL-derived example data is distributed under
|
|
194
|
+
[CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/); see
|
|
195
|
+
[Example data](#example-data) for provenance and attribution.
|