mimyr 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.
- mimyr-0.1.0/LICENSE +21 -0
- mimyr-0.1.0/PKG-INFO +479 -0
- mimyr-0.1.0/README.md +445 -0
- mimyr-0.1.0/pyproject.toml +57 -0
- mimyr-0.1.0/setup.cfg +4 -0
- mimyr-0.1.0/src/mimyr/__init__.py +27 -0
- mimyr-0.1.0/src/mimyr/_resources.py +10 -0
- mimyr-0.1.0/src/mimyr/analysis.py +112 -0
- mimyr-0.1.0/src/mimyr/api.py +638 -0
- mimyr-0.1.0/src/mimyr/data_loader.py +1216 -0
- mimyr-0.1.0/src/mimyr/data_modes.py +31 -0
- mimyr-0.1.0/src/mimyr/evaluator.py +202 -0
- mimyr-0.1.0/src/mimyr/gene_exp_model.py +84 -0
- mimyr-0.1.0/src/mimyr/inference.py +914 -0
- mimyr-0.1.0/src/mimyr/metrics.py +747 -0
- mimyr-0.1.0/src/mimyr/models/__init__.py +0 -0
- mimyr-0.1.0/src/mimyr/models/biological_model.py +395 -0
- mimyr-0.1.0/src/mimyr/models/celltype_model.py +627 -0
- mimyr-0.1.0/src/mimyr/models/combined_model.py +106 -0
- mimyr-0.1.0/src/mimyr/models/diffusion_model.py +623 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/Mimyr.py +799 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/__init__.py +7 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/data_util.py +619 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/finetune_mimyr.py +1701 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/metadata/4hierarchy_metainfo_mouse_geneunion2_DAG.pt +0 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/metadata/edges_x.pkl +0 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/metadata/edges_y.pkl +0 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/metadata/edges_z.pkl +0 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/metadata/hierarchy.pkl +0 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/metadata/id_to_subclass.pkl +0 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/model/__init__.py +0 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/model/model.py +990 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/model/model_kvcache.py +1144 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/model/wtf_bias.py +185 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/reference/GeneSymbolUniform/__init__.py +0 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/reference/GeneSymbolUniform/pyGSUni.py +424 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/reference/GeneSymbolUniform/total_gene_list_42117.txt +42118 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/reference/__init__.py +0 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/utils/__init__.py +1 -0
- mimyr-0.1.0/src/mimyr/models/generative_transformer/utils/hf_tokenizer.py +31 -0
- mimyr-0.1.0/src/mimyr/pretrained.py +187 -0
- mimyr-0.1.0/src/mimyr.egg-info/PKG-INFO +479 -0
- mimyr-0.1.0/src/mimyr.egg-info/SOURCES.txt +44 -0
- mimyr-0.1.0/src/mimyr.egg-info/dependency_links.txt +1 -0
- mimyr-0.1.0/src/mimyr.egg-info/requires.txt +18 -0
- mimyr-0.1.0/src/mimyr.egg-info/top_level.txt +1 -0
mimyr-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Spencer Krieger, Ajinkya Deshpande, and Zhilei Bei
|
|
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.
|
mimyr-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mimyr
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Generative modeling of spatial transcriptomics: cell locations, cell types, and gene expression for unseen tissue sections.
|
|
5
|
+
Author: Ajinkya Deshpande, Zhilei Bei, Jian Ma
|
|
6
|
+
Author-email: Spencer Krieger <skrieger@andrew.cmu.edu>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Repository, https://github.com/gkrieg/mimyr
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: numpy>=2.2.6
|
|
16
|
+
Requires-Dist: scipy>=1.15.3
|
|
17
|
+
Requires-Dist: pandas>=2.3.3
|
|
18
|
+
Requires-Dist: scikit-learn>=1.7.2
|
|
19
|
+
Requires-Dist: torch>=2.5.1
|
|
20
|
+
Requires-Dist: transformers>=4.30.2
|
|
21
|
+
Requires-Dist: scanpy>=1.11.5
|
|
22
|
+
Requires-Dist: anndata>=0.10.2
|
|
23
|
+
Requires-Dist: shapely>=2.1.2
|
|
24
|
+
Requires-Dist: slafdb>=0.5.2
|
|
25
|
+
Requires-Dist: tqdm>=4.67.3
|
|
26
|
+
Requires-Dist: loguru>=0.7.0
|
|
27
|
+
Requires-Dist: wandb>=0.21.0
|
|
28
|
+
Requires-Dist: matplotlib>=3.10.9
|
|
29
|
+
Requires-Dist: seaborn>=0.13.2
|
|
30
|
+
Requires-Dist: huggingface_hub>=0.23
|
|
31
|
+
Requires-Dist: filelock
|
|
32
|
+
Requires-Dist: pyyaml>=6.0
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+

|
|
36
|
+
|
|
37
|
+
# MIMYR
|
|
38
|
+
|
|
39
|
+
MIMYR is a generative framework for spatial transcriptomics. Given neighboring
|
|
40
|
+
tissue sections registered to the Allen Common Coordinate Framework (CCF), it
|
|
41
|
+
generates an unseen section: where the cells are, what type each cell is, and
|
|
42
|
+
what genes each cell expresses.
|
|
43
|
+
|
|
44
|
+
It has three components, run in sequence:
|
|
45
|
+
|
|
46
|
+
1. **Location model**: a conditional diffusion model (DDPM) that samples cell
|
|
47
|
+
coordinates in the plane of the new section, with optional backward guidance
|
|
48
|
+
from a KDE fit to a neighboring reference section.
|
|
49
|
+
2. **Cell-type model**: a classifier that predicts each cell's type from its CCF
|
|
50
|
+
coordinates.
|
|
51
|
+
3. **Expression model**: an autoregressive transformer that generates each cell's
|
|
52
|
+
expression profile, conditioned on its location and cell type.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
MIMYR requires Python 3.10 or newer.
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
conda create --name mimyr python=3.10
|
|
62
|
+
conda activate mimyr
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
If you have an NVIDIA GPU, first install the PyTorch build that matches your CUDA
|
|
66
|
+
version (see [pytorch.org](https://pytorch.org/get-started/locally/)); otherwise
|
|
67
|
+
`pip` installs the default build.
|
|
68
|
+
|
|
69
|
+
Then install MIMYR:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install mimyr
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
This installs the `mimyr` package, its dependencies, and the gene and cell-type
|
|
76
|
+
metadata the models need. To run `main.py`, the demo, or the scripts that reproduce
|
|
77
|
+
the paper, clone the repository and install from source instead:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
git clone https://github.com/gkrieg/mimyr.git
|
|
81
|
+
cd mimyr
|
|
82
|
+
pip install -e .
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Quickstart
|
|
86
|
+
|
|
87
|
+
From the repository root:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
python main.py
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
This runs the full pipeline (location, cell type, and expression) with the
|
|
94
|
+
pretrained models on a small demo dataset in `demo_data/`. It generates one
|
|
95
|
+
section from its two neighbors and scores it against the real section, using the
|
|
96
|
+
model and settings behind the paper's Fig. 2. The first run downloads that model's
|
|
97
|
+
checkpoints (about 475 MB) from the Hugging Face Hub. The metrics are written to
|
|
98
|
+
`results/output.csv` and the generated section to `artifacts/`.
|
|
99
|
+
|
|
100
|
+
The demo data is the first rq1 test section (`sec_14`) and the two reference
|
|
101
|
+
sections next to it (`sec_13`, `sec_15`), each randomly subsampled to 5% of its
|
|
102
|
+
cells (3,562 to 4,719 cells per section). Because the sections are subsampled, its
|
|
103
|
+
scores are not comparable to the paper's. `demo_data/make_demo_data.py` rebuilds it
|
|
104
|
+
from the full rq1 data.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Python API
|
|
109
|
+
|
|
110
|
+
`main.py` reproduces the paper's experiments. To use MIMYR on your own sections,
|
|
111
|
+
call it from Python. Sections are AnnData objects in the [input format](#input-format).
|
|
112
|
+
|
|
113
|
+
### Generate a section
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
import anndata as ad
|
|
117
|
+
import mimyr
|
|
118
|
+
|
|
119
|
+
left = ad.read_h5ad("demo_data/sec_13.h5ad")
|
|
120
|
+
right = ad.read_h5ad("demo_data/sec_15.h5ad")
|
|
121
|
+
|
|
122
|
+
model = mimyr.Mimyr.from_pretrained("merscope") # paper Fig. 2 model, from the Hub
|
|
123
|
+
section = model.generate(reference=[left, right], position=10.9, seed=0)
|
|
124
|
+
section.write_h5ad("generated.h5ad")
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`position` is where the new section goes, in mm along the section axis: `x_ccf`
|
|
128
|
+
for coronal models, `z_ccf` for the sagittal `zhuang3-finetuned`. By default the
|
|
129
|
+
section has the references' extent and their mean number of cells; set `n_cells`
|
|
130
|
+
and `bounds` (e.g. `{"y_ccf": (1.0, 7.5), "z_ccf": (0.5, 10.5)}`) to change that.
|
|
131
|
+
The result has one row per generated cell, with:
|
|
132
|
+
|
|
133
|
+
- positions in `obs["x_ccf"]`, `obs["y_ccf"]`, `obs["z_ccf"]`;
|
|
134
|
+
- cell types in `obs["class"]`, `obs["subclass"]`, `obs["supertype"]` and `obs["cluster"]`;
|
|
135
|
+
- expression over the model's 2,000-gene panel in `X`, log1p-scaled like the input.
|
|
136
|
+
|
|
137
|
+
Expression is pulled toward the nearest same-type cell in the references
|
|
138
|
+
(reference guidance) at the strength the paper used. `reference_guidance=0` turns
|
|
139
|
+
it off, and then `reference` is optional if you pass `n_cells` and `bounds`.
|
|
140
|
+
|
|
141
|
+
Each stage can be swapped for a baseline: `location="closest_slice"`,
|
|
142
|
+
`cell_types="majority_baseline"` or `expression="lookup"`.
|
|
143
|
+
|
|
144
|
+
### Evaluate against a held-out section
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
held_out = ad.read_h5ad("demo_data/sec_14.h5ad")
|
|
148
|
+
section = model.generate(reference=[left, right], position=held_out, seed=0)
|
|
149
|
+
mimyr.evaluate(section, held_out)
|
|
150
|
+
# {'soft_accuracy@0.03': ..., 'soft_spearman_correlation_radius@0.05': ..., 'soft_f1_radius@0.05': ..., ...}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Passing a section as `position` generates it again at the same position, with the
|
|
154
|
+
same extent and number of cells. Its expression is never read. `evaluate` takes
|
|
155
|
+
`metrics=` (any name in `mimyr.evaluator.METRICS`) and `sample=` (the percentage of
|
|
156
|
+
real cells scored).
|
|
157
|
+
|
|
158
|
+
### Train on your own data
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
model = mimyr.Mimyr.from_pretrained("merscope")
|
|
162
|
+
model.train(train=train_sections, val=val_sections, output_dir="runs/my_lab", epochs=20)
|
|
163
|
+
model.save("my_model/")
|
|
164
|
+
|
|
165
|
+
model = mimyr.Mimyr.from_pretrained("my_model/") # later
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
`train` fine-tunes the cell-type classifier and the expression model, starting
|
|
169
|
+
from the current weights; pass `components=("expression",)` to train just one.
|
|
170
|
+
The pretrained location model covers the whole mouse brain in CCF space, so it
|
|
171
|
+
works for any CCF-registered mouse data. To fine-tune it on your sections as well,
|
|
172
|
+
add `"location"` to `components` (`location_epochs`, default 400). Location
|
|
173
|
+
training supports coronal models only. It normalizes coordinates with fixed
|
|
174
|
+
constants for the CCF mouse brain, so the data must be in CCF mm.
|
|
175
|
+
|
|
176
|
+
The models use a fixed vocabulary: the 2,000-gene panel and the 5,274 Allen Brain
|
|
177
|
+
Cell Atlas clusters. Data must use these gene symbols and cluster names; other
|
|
178
|
+
genes are ignored. `mimyr.validate(sections)` reports what's missing or outside the
|
|
179
|
+
vocabulary. To train the expression model on several GPUs, run the script with
|
|
180
|
+
`torchrun --nproc_per_node=4 train.py`. Weights & Biases logging is off unless
|
|
181
|
+
`WANDB_MODE` is set. Batches load in the main process; `num_workers=4` moves loading
|
|
182
|
+
into worker processes. Each worker re-imports your script, so put its code under
|
|
183
|
+
`if __name__ == "__main__":` first.
|
|
184
|
+
|
|
185
|
+
`generate`, `train` and `evaluate` prepare raw sections themselves. To prepare
|
|
186
|
+
large sections once and reuse them across calls, use `mimyr.prepare(sections)`.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Pretrained models and data
|
|
191
|
+
|
|
192
|
+
The pretrained checkpoints are hosted on the Hugging Face Hub at
|
|
193
|
+
[gkrieg13/mimyr](https://huggingface.co/gkrieg13/mimyr), and the benchmark data at
|
|
194
|
+
[gkrieg13/mimyr-data](https://huggingface.co/datasets/gkrieg13/mimyr-data). Both are
|
|
195
|
+
downloaded on first use and cached by `huggingface_hub` (`~/.cache/huggingface` by
|
|
196
|
+
default; set `HF_HOME` to move it).
|
|
197
|
+
|
|
198
|
+
`--pretrained` selects one of the models from the paper. It provides any checkpoint
|
|
199
|
+
you do not pass explicitly, and the inference settings used for that model in the
|
|
200
|
+
paper:
|
|
201
|
+
|
|
202
|
+
| `--pretrained` | Paper | Use with | Settings it applies |
|
|
203
|
+
|---|---|---|---|
|
|
204
|
+
| `merscope` (default) | Fig. 2 | `--data_mode rq1` or `demo` | reference guidance 75, `--metric_filter_by_gt` |
|
|
205
|
+
| `zhuang1` | Fig. 3, zero-shot | `--data_mode rq3_v2` | reference guidance 75, `--metric_filter_by_gt`, `--omit_x` |
|
|
206
|
+
| `zhuang2-finetuned` | Fig. 3 | `--data_mode rq3_v2` | reference guidance 75, `--metric_filter_by_gt`, `--omit_x` |
|
|
207
|
+
| `zhuang3-finetuned` | Fig. 4 | `--data_mode rq4` | reference guidance 50, `--metric_filter_by_gt` |
|
|
208
|
+
|
|
209
|
+
Settings are resolved in this order, each overriding the previous one: the built-in
|
|
210
|
+
defaults, the `--pretrained` model's settings, a `--config` file, and flags on the
|
|
211
|
+
command line. For example, `--no-expression_weak_teacher_forcing` turns reference
|
|
212
|
+
guidance off, and `--no-omit_x` and `--no-metric_filter_by_gt` undo the other two
|
|
213
|
+
settings.
|
|
214
|
+
|
|
215
|
+
Benchmark data is downloaded only for the data mode you run (the demo needs none) and
|
|
216
|
+
extracted into `--data_dir` (default `data/`):
|
|
217
|
+
|
|
218
|
+
| Archive | Size | Contents | Data modes |
|
|
219
|
+
|---|---|---|---|
|
|
220
|
+
| `rq1-merscope.zip` | 1.3 GB | 53 MERSCOPE sections from one brain | `rq1` |
|
|
221
|
+
| `Zhuang-ABCA-1.zip` | 1.0 GB | Zhuang-ABCA-1 (147 sections) | `base_zhuang1`, `rq4_noref` |
|
|
222
|
+
| `Zhuang-ABCA-2.zip` | 0.4 GB | Zhuang-ABCA-2 (66 sections) | `rq3`, `rq3_v2*`, `rq4_rq3` |
|
|
223
|
+
| `Zhuang-ABCA-3.zip` | 0.5 GB | Zhuang-ABCA-3 (23 sagittal sections) | `rq4*` |
|
|
224
|
+
| `Zhuang-ABCA-4.zip` | 0.05 GB | Zhuang-ABCA-4 (3 sections) | none |
|
|
225
|
+
|
|
226
|
+
These sections come from the Allen Brain Cell Atlas (Yao et al., *Nature* 2023; Zhang
|
|
227
|
+
et al., *Nature* 2023); please cite those papers if you use them.
|
|
228
|
+
|
|
229
|
+
### Input format
|
|
230
|
+
|
|
231
|
+
Each section is an `.h5ad` file (`.slaf` is also supported) with:
|
|
232
|
+
|
|
233
|
+
- `obs["x_ccf"]`, `obs["y_ccf"]`, `obs["z_ccf"]`: CCF coordinates in mm, which MIMYR
|
|
234
|
+
stacks into `obsm["aligned_spatial"]`
|
|
235
|
+
- `obs["cluster"]`: cell-type labels (choose a different column with `--data_label`).
|
|
236
|
+
Labels are mapped to tokens using the bundled Allen Brain Cell atlas vocabulary,
|
|
237
|
+
so they must use ABC-atlas cluster names (e.g. `0001 CLA-EPd-CTX Car3 Glut_1`).
|
|
238
|
+
The Python API fills in `class`, `subclass` and `supertype` from the cluster
|
|
239
|
+
when they are missing.
|
|
240
|
+
- `X`: the gene expression matrix, with gene symbols as `var_names`.
|
|
241
|
+
If any value is above 10, the matrix is taken to be counts and log1p-transformed
|
|
242
|
+
(it is not normalized first).
|
|
243
|
+
- optionally `obs["technology"]` (`M550` for MERSCOPE 550-gene data, `M1100` for
|
|
244
|
+
the Zhuang MERFISH data; default `M550`), `obs["species"]` and
|
|
245
|
+
`obs["disease_state"]` (default `mouse`, `healthy`)
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Running inference
|
|
250
|
+
|
|
251
|
+
`main.py` is the entry point. It loads a dataset according to `--data_mode`,
|
|
252
|
+
generates each test section from its neighboring reference sections, scores the
|
|
253
|
+
result against the real section, and writes the metrics to a CSV.
|
|
254
|
+
|
|
255
|
+
Each of the three stages is controlled by its own flag:
|
|
256
|
+
|
|
257
|
+
| Flag | Default | Values |
|
|
258
|
+
|---|---|---|
|
|
259
|
+
| `--location_inference_type` | `model` | `model` (DDPM), `closest_slice` (copy the nearest reference section) |
|
|
260
|
+
| `--cluster_inference_type` | `model` | `model` (classifier), `majority_baseline` |
|
|
261
|
+
| `--expression_inference_type` | `model` | `model` (transformer), `lookup` (nearest same-type reference cell), `averaging` |
|
|
262
|
+
|
|
263
|
+
Every stage also accepts two special values:
|
|
264
|
+
|
|
265
|
+
- `skip` uses the **ground truth** for that stage instead of predicting it
|
|
266
|
+
(useful for evaluating one stage in isolation).
|
|
267
|
+
- `end` stops the pipeline after the previous stage.
|
|
268
|
+
|
|
269
|
+
The defaults run every stage with its model. To run the full pipeline on the rq1
|
|
270
|
+
benchmark instead of the demo:
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
python main.py --data_mode rq1 --out_csv results/rq1.csv
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
To evaluate the expression model alone, given the true locations and cell types:
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
python main.py --location_inference_type skip --cluster_inference_type skip
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
The baselines used in the paper:
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
python main.py --data_mode rq1 \
|
|
286
|
+
--location_inference_type closest_slice \
|
|
287
|
+
--cluster_inference_type majority_baseline \
|
|
288
|
+
--expression_inference_type lookup \
|
|
289
|
+
--metrics soft_spearman_correlation,soft_f1 --metric_sampling 100
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
To reproduce the paper's results from the published models and data, use the
|
|
293
|
+
scripts in [`reproducibility/`](https://github.com/gkrieg/mimyr/blob/main/reproducibility/README.md), one per figure or
|
|
294
|
+
supplementary analysis.
|
|
295
|
+
|
|
296
|
+
### Data modes
|
|
297
|
+
|
|
298
|
+
`--data_mode` selects the dataset and the train/validation/test/reference split:
|
|
299
|
+
|
|
300
|
+
| Mode | Dataset | Paths it reads |
|
|
301
|
+
|---|---|---|
|
|
302
|
+
| `demo` (default) | one rq1 test section and its two neighbors, subsampled to 5% | `--demo_data_dir` (default `demo_data/`) |
|
|
303
|
+
| `rq1` | coronal sections from one brain, fixed held-out sections | `--data_dir/subclass_z1_d338_0_rotated/` |
|
|
304
|
+
| `rq3`, `rq3_v2`, `rq3_v2_d1` … `rq3_v2_d4` | Zhuang-ABCA-2 (coronal); the `_d*` modes vary the distance to the reference sections | `--zhuang_data_dir/Zhuang-ABCA-2/`, `--data_dir/ccf-ABCA-2.csv` |
|
|
305
|
+
| `rq4`, `rq4_rq3`, `rq4_noref` | Zhuang-ABCA-3 (sagittal); `rq4_noref` uses all of Zhuang-ABCA-1 as the reference pool | `--zhuang_data_dir/Zhuang-ABCA-3/` (and `-1`, `-2`), `--data_dir/ccf-ABCA-*.csv` |
|
|
306
|
+
| `rq5` | diseased (Trem2 / 5xFAD) sections; not distributed, so supply your own | `--diseased_data_dir` |
|
|
307
|
+
| `base_zhuang1` | Zhuang-ABCA-1, for training the base models | `--zhuang_data_dir/Zhuang-ABCA-1/` |
|
|
308
|
+
|
|
309
|
+
### Main options
|
|
310
|
+
|
|
311
|
+
- `--pretrained`: which pretrained model to use (see above)
|
|
312
|
+
- `--location_model_checkpoint`, `--cluster_model_checkpoint`, `--expression_model_checkpoint`:
|
|
313
|
+
use these checkpoint files instead of the `--pretrained` model's
|
|
314
|
+
- `--guidance_signal`: strength of KDE backward guidance for the location model
|
|
315
|
+
(default `0.0`, off); `--kde_bandwidth` sets the KDE bandwidth (default `0.01`)
|
|
316
|
+
- `--metrics`: comma-separated metrics (default
|
|
317
|
+
`soft_accuracy,soft_spearman_correlation,soft_f1`). Available:
|
|
318
|
+
`soft_accuracy`, `soft_spearman_correlation`, `soft_correlation_top_100`, `soft_f1`,
|
|
319
|
+
`gridized_l1_distance`, `gridized_kl_divergence`, `celltype_abundance`,
|
|
320
|
+
`composition_entropy`, `composition_pairwise`, `delauney_colocalization`.
|
|
321
|
+
Results go in one column per radius, e.g. `soft_f1_radius@0.05`
|
|
322
|
+
- `--metric_sampling`: percentage of ground-truth cells the metrics are computed
|
|
323
|
+
on (default `100`)
|
|
324
|
+
- `--metric_gene_set_file`: restrict expression metrics to the genes listed in a
|
|
325
|
+
file, one per line (e.g. `gene_overlap.txt`); `--metric_filter_by_gt` restricts
|
|
326
|
+
them to genes expressed in the ground truth
|
|
327
|
+
- `--eval_workers`: number of sections scored in parallel (default `1`)
|
|
328
|
+
- `--device`: `cuda` (default) or `cpu`
|
|
329
|
+
|
|
330
|
+
Expression decoding can be tuned with `--top_k`,
|
|
331
|
+
`--expression_select_max_index_margin`, and the weak teacher forcing options
|
|
332
|
+
(`--expression_weak_teacher_forcing`, `--wtf_*`), which pull generation toward the
|
|
333
|
+
nearest same-type reference cell. The `--pretrained` model sets the guidance
|
|
334
|
+
strength; see `python main.py --help` for the full list.
|
|
335
|
+
|
|
336
|
+
### Output
|
|
337
|
+
|
|
338
|
+
- `--out_csv` (default `results/output.csv`): one row per test section, containing
|
|
339
|
+
the full configuration and the metrics. Rows are appended, and a section is
|
|
340
|
+
**skipped** if a row with the same configuration is already in the CSV.
|
|
341
|
+
- `--artifact_dir` (default `artifacts/`): one timestamped folder per test section
|
|
342
|
+
with `config.json`, `results.json`, `pred.pkl` (the generated AnnData), and plots
|
|
343
|
+
of the predicted and ground-truth locations and cell types.
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Training
|
|
348
|
+
|
|
349
|
+
### Expression model
|
|
350
|
+
|
|
351
|
+
`--run_mode train` trains the expression transformer with distributed
|
|
352
|
+
data-parallel training. Launch it with `torchrun`:
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
torchrun --nproc_per_node=<NUM_GPUS> main.py \
|
|
356
|
+
--run_mode train \
|
|
357
|
+
--skip_combined_fit \
|
|
358
|
+
--data_mode rq1 \
|
|
359
|
+
--expression_output_dir /path/to/save/checkpoints \
|
|
360
|
+
--expression_epochs 265 \
|
|
361
|
+
--expression_batch_size 128
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
This fine-tunes the `--pretrained` model's expression transformer (by default
|
|
365
|
+
`merscope`, saved at epoch 165) for 100 more epochs. To try training on the demo data,
|
|
366
|
+
run `torchrun --nproc_per_node=1 main.py --run_mode train --skip_combined_fit --expression_epochs 166`.
|
|
367
|
+
|
|
368
|
+
- Training and validation data come from the `--data_mode` split, the same as for
|
|
369
|
+
inference. The preprocessed data is cached in `--expression_output_dir`, so later
|
|
370
|
+
runs with the same output directory skip preprocessing.
|
|
371
|
+
- A checkpoint is saved every `--expression_save_frequency` epochs (default `10`).
|
|
372
|
+
- Training starts from the weights in `--expression_model_checkpoint` and
|
|
373
|
+
continues its epoch count from the `epochN` in the checkpoint's filename.
|
|
374
|
+
`--expression_epochs` is the **last epoch number**, not a count: starting from the
|
|
375
|
+
`merscope` model (epoch 165), `--expression_epochs 265` trains epochs 166 to 265.
|
|
376
|
+
- `--expression_random_init` uses only the checkpoint's architecture and starts from
|
|
377
|
+
random weights. To train from scratch without a checkpoint, pass
|
|
378
|
+
`--expression_model_checkpoint ""` together with
|
|
379
|
+
`--expression_model_size small|medium|large`.
|
|
380
|
+
- Training logs to Weights & Biases. Set `WANDB_MODE=offline` to log locally.
|
|
381
|
+
|
|
382
|
+
Other useful options: `--expression_lr` (default `5e-5`), `--expression_lambda_val`
|
|
383
|
+
(weight of the regression loss, default `1.0`), `--expression_max_len` (default
|
|
384
|
+
`512`), `--expression_epoch_samples` (cells per epoch; `-1`, the default, uses all of
|
|
385
|
+
them), `--expression_xyz_noise` / `--expression_xyz_noise_magnitude` (coordinate
|
|
386
|
+
noise), and `--expression_adata2` (an extra `.h5ad`, e.g. scRNA-seq, merged into
|
|
387
|
+
training).
|
|
388
|
+
|
|
389
|
+
### Cell-type and location models
|
|
390
|
+
|
|
391
|
+
Without `--skip_combined_fit`, `--run_mode train` first trains the cell-type
|
|
392
|
+
classifier on the `.h5ad`/`.slaf` files in `--training_slice_directory` and
|
|
393
|
+
`--val_slice_directory` (default `data/cleaned_versions`). These files also need an
|
|
394
|
+
`obs["token"]` column. The best model is saved to `./best_model.pt`.
|
|
395
|
+
|
|
396
|
+
`main.py` does not train the location model (the Python API does; see above).
|
|
397
|
+
`train_location_zhuang1.py` and
|
|
398
|
+
`train_celltype_zhuang1.py` retrain the location and cell-type models on
|
|
399
|
+
Zhuang-ABCA-1; they currently contain cluster-specific data paths.
|
|
400
|
+
|
|
401
|
+
### Configuration files
|
|
402
|
+
|
|
403
|
+
Any option can be put in a YAML file and passed with `--config`. Each key is an
|
|
404
|
+
argument name (for example `data_dir:` or `expression_model_checkpoint:`), and flags
|
|
405
|
+
given on the command line override the file:
|
|
406
|
+
|
|
407
|
+
```bash
|
|
408
|
+
python main.py --config config.yaml
|
|
409
|
+
torchrun --nproc_per_node=4 main.py --config configs/train_base.yaml --run_mode train
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
`config.yaml` and the files in `configs/` hold settings from the lab's experiments,
|
|
413
|
+
and [`reproducibility/training_configs/`](https://github.com/gkrieg/mimyr/blob/main/reproducibility/README.md#training-configurations)
|
|
414
|
+
the ones that trained the published checkpoints. They contain absolute paths on the
|
|
415
|
+
lab's cluster, so copy one and change the paths before using it. Because they set
|
|
416
|
+
their checkpoints and guidance explicitly, they are not affected by `--pretrained`.
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
## Project structure
|
|
421
|
+
|
|
422
|
+
```
|
|
423
|
+
MIMYR/
|
|
424
|
+
├── pyproject.toml # Package definition (pip install -e .)
|
|
425
|
+
├── main.py # Entry point: inference and training
|
|
426
|
+
├── demo_data/ # Small demo dataset (default data_mode)
|
|
427
|
+
├── hub/ # Hugging Face model and dataset cards
|
|
428
|
+
├── scripts/ # Maintainer scripts for publishing to the Hub
|
|
429
|
+
├── config.yaml # Example configuration
|
|
430
|
+
├── configs/ # Per-experiment configurations
|
|
431
|
+
├── reproducibility/ # Scripts that regenerate the paper's results
|
|
432
|
+
├── gene_overlap.txt # Shared gene set for rq1/rq3 evaluation
|
|
433
|
+
├── train_location_zhuang1.py # Retrain the location model on Zhuang-ABCA-1
|
|
434
|
+
├── train_celltype_zhuang1.py # Retrain the cell-type model on Zhuang-ABCA-1
|
|
435
|
+
└── src/mimyr/ # The installable `mimyr` package
|
|
436
|
+
├── pretrained.py # Pretrained models and data on the Hugging Face Hub
|
|
437
|
+
├── data_loader.py # SliceDataLoader: data modes, splits, preprocessing
|
|
438
|
+
├── inference.py # The three-stage generation pipeline
|
|
439
|
+
├── evaluator.py # Runs the selected metrics
|
|
440
|
+
├── metrics.py # Metric implementations
|
|
441
|
+
├── gene_exp_model.py # Cell-type label to token mapping
|
|
442
|
+
└── models/
|
|
443
|
+
├── diffusion_model.py # Location model (DDPM)
|
|
444
|
+
├── celltype_model.py # Cell-type classifier
|
|
445
|
+
├── biological_model.py # KDE used for location guidance
|
|
446
|
+
├── combined_model.py # Loads the location and cell-type models
|
|
447
|
+
└── generative_transformer/ # Expression model
|
|
448
|
+
├── Mimyr.py # Generation and inference helpers
|
|
449
|
+
├── finetune_mimyr.py # Training loop (DDP)
|
|
450
|
+
├── data_util.py # Data harmonization and loaders
|
|
451
|
+
├── metadata/ # Bundled gene and cell-type metadata
|
|
452
|
+
├── model/ # Transformer implementation
|
|
453
|
+
├── reference/ # Gene symbol reference list
|
|
454
|
+
└── utils/ # Tokenizer
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
## Citation
|
|
458
|
+
|
|
459
|
+
If you use MIMYR, please cite:
|
|
460
|
+
|
|
461
|
+
> Deshpande A, Bei Z, Ma J, Krieger S. MIMYR: Generative modeling of missing tissue
|
|
462
|
+
> in spatial transcriptomics. *bioRxiv* [Preprint]. 2025 Nov 27:2025.11.24.690239.
|
|
463
|
+
> doi: [10.1101/2025.11.24.690239](https://doi.org/10.1101/2025.11.24.690239).
|
|
464
|
+
> PMID: 41394599; PMCID: PMC12697367.
|
|
465
|
+
|
|
466
|
+
```bibtex
|
|
467
|
+
@article{deshpande2025mimyr,
|
|
468
|
+
title = {{MIMYR}: Generative modeling of missing tissue in spatial transcriptomics},
|
|
469
|
+
author = {Deshpande, A. and Bei, Z. and Ma, J. and Krieger, S.},
|
|
470
|
+
journal = {bioRxiv},
|
|
471
|
+
year = {2025},
|
|
472
|
+
doi = {10.1101/2025.11.24.690239},
|
|
473
|
+
note = {Preprint. PMID: 41394599; PMCID: PMC12697367}
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
## License
|
|
478
|
+
|
|
479
|
+
MIMYR is released under the [MIT License](https://github.com/gkrieg/mimyr/blob/main/LICENSE).
|