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.
Files changed (46) hide show
  1. mimyr-0.1.0/LICENSE +21 -0
  2. mimyr-0.1.0/PKG-INFO +479 -0
  3. mimyr-0.1.0/README.md +445 -0
  4. mimyr-0.1.0/pyproject.toml +57 -0
  5. mimyr-0.1.0/setup.cfg +4 -0
  6. mimyr-0.1.0/src/mimyr/__init__.py +27 -0
  7. mimyr-0.1.0/src/mimyr/_resources.py +10 -0
  8. mimyr-0.1.0/src/mimyr/analysis.py +112 -0
  9. mimyr-0.1.0/src/mimyr/api.py +638 -0
  10. mimyr-0.1.0/src/mimyr/data_loader.py +1216 -0
  11. mimyr-0.1.0/src/mimyr/data_modes.py +31 -0
  12. mimyr-0.1.0/src/mimyr/evaluator.py +202 -0
  13. mimyr-0.1.0/src/mimyr/gene_exp_model.py +84 -0
  14. mimyr-0.1.0/src/mimyr/inference.py +914 -0
  15. mimyr-0.1.0/src/mimyr/metrics.py +747 -0
  16. mimyr-0.1.0/src/mimyr/models/__init__.py +0 -0
  17. mimyr-0.1.0/src/mimyr/models/biological_model.py +395 -0
  18. mimyr-0.1.0/src/mimyr/models/celltype_model.py +627 -0
  19. mimyr-0.1.0/src/mimyr/models/combined_model.py +106 -0
  20. mimyr-0.1.0/src/mimyr/models/diffusion_model.py +623 -0
  21. mimyr-0.1.0/src/mimyr/models/generative_transformer/Mimyr.py +799 -0
  22. mimyr-0.1.0/src/mimyr/models/generative_transformer/__init__.py +7 -0
  23. mimyr-0.1.0/src/mimyr/models/generative_transformer/data_util.py +619 -0
  24. mimyr-0.1.0/src/mimyr/models/generative_transformer/finetune_mimyr.py +1701 -0
  25. mimyr-0.1.0/src/mimyr/models/generative_transformer/metadata/4hierarchy_metainfo_mouse_geneunion2_DAG.pt +0 -0
  26. mimyr-0.1.0/src/mimyr/models/generative_transformer/metadata/edges_x.pkl +0 -0
  27. mimyr-0.1.0/src/mimyr/models/generative_transformer/metadata/edges_y.pkl +0 -0
  28. mimyr-0.1.0/src/mimyr/models/generative_transformer/metadata/edges_z.pkl +0 -0
  29. mimyr-0.1.0/src/mimyr/models/generative_transformer/metadata/hierarchy.pkl +0 -0
  30. mimyr-0.1.0/src/mimyr/models/generative_transformer/metadata/id_to_subclass.pkl +0 -0
  31. mimyr-0.1.0/src/mimyr/models/generative_transformer/model/__init__.py +0 -0
  32. mimyr-0.1.0/src/mimyr/models/generative_transformer/model/model.py +990 -0
  33. mimyr-0.1.0/src/mimyr/models/generative_transformer/model/model_kvcache.py +1144 -0
  34. mimyr-0.1.0/src/mimyr/models/generative_transformer/model/wtf_bias.py +185 -0
  35. mimyr-0.1.0/src/mimyr/models/generative_transformer/reference/GeneSymbolUniform/__init__.py +0 -0
  36. mimyr-0.1.0/src/mimyr/models/generative_transformer/reference/GeneSymbolUniform/pyGSUni.py +424 -0
  37. mimyr-0.1.0/src/mimyr/models/generative_transformer/reference/GeneSymbolUniform/total_gene_list_42117.txt +42118 -0
  38. mimyr-0.1.0/src/mimyr/models/generative_transformer/reference/__init__.py +0 -0
  39. mimyr-0.1.0/src/mimyr/models/generative_transformer/utils/__init__.py +1 -0
  40. mimyr-0.1.0/src/mimyr/models/generative_transformer/utils/hf_tokenizer.py +31 -0
  41. mimyr-0.1.0/src/mimyr/pretrained.py +187 -0
  42. mimyr-0.1.0/src/mimyr.egg-info/PKG-INFO +479 -0
  43. mimyr-0.1.0/src/mimyr.egg-info/SOURCES.txt +44 -0
  44. mimyr-0.1.0/src/mimyr.egg-info/dependency_links.txt +1 -0
  45. mimyr-0.1.0/src/mimyr.egg-info/requires.txt +18 -0
  46. 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
+ ![MIMYR Method](https://raw.githubusercontent.com/gkrieg/mimyr/main/mimyr.jpg)
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).