beiken1201 commited on
Commit
3830179
Β·
verified Β·
1 Parent(s): 49ee329

Unify downstream task layout and document dataset launch commands

Browse files

Place each task notebook beside its README and train/evaluate entry point; organize helper code and shared module-source definitions. Add complete per-dataset launch commands and preserve declared zero-count cell annotation classes. Remove the unused environment template and stale ignore rules, and refresh project and data-directory README paths. Pretrained weights, paired configuration and raw data remain unchanged.

Files changed (38) hide show
  1. BioMod/.env.example +0 -13
  2. BioMod/.gitignore +1 -5
  3. BioMod/README.md +371 -358
  4. BioMod/cell_annotation/README.md +282 -0
  5. BioMod/cell_annotation/cmd_finetune.md +0 -21
  6. BioMod/cell_annotation/{biomod_finetune.py β†’ train.py} +32 -5
  7. BioMod/{toturials/cell_annotation.ipynb β†’ cell_annotation/tutorial.ipynb} +4 -4
  8. BioMod/drug_combination/README.md +79 -54
  9. BioMod/drug_combination/{train_drug_combination_biomod.py β†’ train.py} +1 -1
  10. BioMod/{toturials/drug_combination.ipynb β†’ drug_combination/tutorial.ipynb} +5 -5
  11. BioMod/drug_response/README.md +70 -0
  12. BioMod/drug_response/cmd.txt +0 -10
  13. BioMod/drug_response/{train_drug_biomod.py β†’ train.py} +2 -2
  14. BioMod/{toturials/drug_response_prediction.ipynb β†’ drug_response/tutorial.ipynb} +6 -6
  15. BioMod/gene_perturbation/README.md +102 -45
  16. BioMod/gene_perturbation/components/__init__.py +1 -0
  17. BioMod/gene_perturbation/{data_utils_local.py β†’ components/data_utils.py} +2 -2
  18. BioMod/gene_perturbation/{pertdata_local.py β†’ components/dataset.py} +3 -3
  19. BioMod/gene_perturbation/{inference_local.py β†’ components/inference.py} +1 -1
  20. BioMod/gene_perturbation/{model_biomod.py β†’ components/model.py} +3 -3
  21. BioMod/gene_perturbation/{gears_reduce_local.py β†’ components/trainer.py} +5 -5
  22. BioMod/gene_perturbation/{scfm_utils_local.py β†’ components/training_utils.py} +1 -1
  23. BioMod/gene_perturbation/{utils.py β†’ components/utils.py} +0 -0
  24. BioMod/gene_perturbation/{train_biomod.py β†’ train.py} +8 -21
  25. BioMod/{toturials/gene_perturbation.ipynb β†’ gene_perturbation/tutorial.ipynb} +5 -5
  26. BioMod/zero_shot_batch/README.md +151 -123
  27. BioMod/zero_shot_batch/{biomod_zero_shot.py β†’ evaluate.py} +0 -0
  28. BioMod/zero_shot_batch/{sequencing_depth/cmd.txt β†’ tools/sequencing_depth/README.md} +74 -42
  29. BioMod/zero_shot_batch/{sequencing_depth β†’ tools/sequencing_depth}/make_low_depth_h5ad.py +0 -0
  30. BioMod/zero_shot_batch/{sequencing_depth β†’ tools/sequencing_depth}/run_zero_shot_low_depth.py +3 -3
  31. BioMod/zero_shot_batch/{visualize_results.py β†’ tools/visualize_results.py} +0 -0
  32. BioMod/{toturials/zero_shot_batch_integration.ipynb β†’ zero_shot_batch/tutorial.ipynb} +4 -4
  33. README.md +70 -53
  34. data/downstream/final_data/drug_combination_synergy/README.md +1 -1
  35. data/downstream/final_data/single_drug_response/README.md +1 -1
  36. {BioMod/cell_annotation/biomod_data β†’ model_dependencies/biomod_data_sources}/biomod1_hallmarks.json +0 -0
  37. {BioMod/cell_annotation/biomod_data β†’ model_dependencies/biomod_data_sources}/biomod2_reactome_2022_filtered.json +0 -0
  38. {BioMod/cell_annotation/biomod_data β†’ model_dependencies/biomod_data_sources}/load_biomod.py +0 -0
BioMod/.env.example DELETED
@@ -1,13 +0,0 @@
1
- # Copy this file to `.env` or export the variables in your shell.
2
- # Never commit real API keys.
3
-
4
- # Alibaba DashScope OpenAI-compatible API, used by Qwen embedding/chat utilities.
5
- DASHSCOPE_API_KEY=
6
- DASHSCOPE_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
7
-
8
- # Optional OpenAI-compatible DeepSeek endpoint used by archived text-quality scripts.
9
- DEEPSEEK_API_KEY=
10
- DEEPSEEK_BASE_URL=
11
-
12
- # Optional experiment tracking.
13
- WANDB_API_KEY=
 
 
 
 
 
 
 
 
 
 
 
 
 
 
BioMod/.gitignore CHANGED
@@ -14,7 +14,6 @@ htmlcov/
14
  # Local environments and secrets
15
  .env
16
  .env.*
17
- !.env.example
18
  .venv/
19
  venv/
20
  env/
@@ -44,10 +43,7 @@ nohup.out
44
  *.hickle
45
 
46
  # Generated task outputs and caches
47
- gene_inverse_norman/outputs/
48
- toturials/execution_checks/
49
- stage2_alignment/archive_text_quality_eval/qwen_cache/
50
- stage2_alignment/best_scheme_qwen/cached_text_embeddings.pt
51
 
52
  # OS/editor files
53
  .DS_Store
 
14
  # Local environments and secrets
15
  .env
16
  .env.*
 
17
  .venv/
18
  venv/
19
  env/
 
43
  *.hickle
44
 
45
  # Generated task outputs and caches
46
+ **/execution_checks/
 
 
 
47
 
48
  # OS/editor files
49
  .DS_Store
BioMod/README.md CHANGED
@@ -1,358 +1,371 @@
1
- # BioMod
2
-
3
- Source code and tutorial notebooks for BioMod single-cell pretraining and
4
- downstream experiments using BioMod representations.
5
-
6
- This source directory contains the pretraining entry point and shared training
7
- utilities, alongside downstream task runners, tutorial notebooks, environment
8
- files, and plotting helpers.
9
-
10
- ## Highlights
11
-
12
- | Area | What is included |
13
- | --- | --- |
14
- | Representation | Module-based single-cell encoder utilities and module metadata |
15
- | Annotation | Supervised cell-type annotation workflows |
16
- | Integration | Zero-shot batch integration and UMAP/scIB-style reporting |
17
- | Perturbation | Norman gene-perturbation training and evaluation tutorial |
18
- | Drug response | Single-drug response prediction with GDSC/CCLE data and validation-based model selection |
19
- | Drug combinations | Drug-combination synergy prediction with validation-based model selection |
20
- | Figures | Notebook-level PDF/PNG/SVG plotting cells for paper and GitHub display |
21
-
22
- ## Repository Layout
23
-
24
- This is the `BioMod/` source directory inside the project root. See the
25
- [full project layout](../README.md#repository-layout) for sibling
26
- `model_dependencies/` and `weight/` directories; `data/` and `.cache/` are omitted
27
- from these repository trees.
28
-
29
- ```text
30
- BioMod/ # Task code: training, evaluation and tutorials
31
- β”œβ”€β”€ cell_annotation/ # Cell-type annotation and model fine-tuning
32
- β”‚ β”œβ”€β”€ biomod_data/ # Hallmark and Reactome modules with loading utilities
33
- β”‚ β”‚ β”œβ”€β”€ load_biomod.py
34
- β”‚ β”‚ β”œβ”€β”€ biomod1_hallmarks.json
35
- β”‚ β”‚ └── biomod2_reactome_2022_filtered.json
36
- β”‚ β”œβ”€β”€ cmd_finetune.md
37
- β”‚ └── biomod_finetune.py
38
- β”œβ”€β”€ drug_combination/ # Drug-combination synergy prediction
39
- β”‚ β”œβ”€β”€ README.md
40
- β”‚ └── train_drug_combination_biomod.py
41
- β”œβ”€β”€ drug_response/ # Single-drug response prediction and training
42
- β”‚ β”œβ”€β”€ cmd.txt
43
- β”‚ └── train_drug_biomod.py
44
- β”œβ”€β”€ gene_perturbation/ # Perturbation response prediction: processing, training and inference
45
- β”‚ β”œβ”€β”€ data_utils_local.py
46
- β”‚ β”œβ”€β”€ gears_reduce_local.py
47
- β”‚ β”œβ”€β”€ inference_local.py
48
- β”‚ β”œβ”€β”€ model_biomod.py
49
- β”‚ β”œβ”€β”€ pertdata_local.py
50
- β”‚ β”œβ”€β”€ README.md
51
- β”‚ β”œβ”€β”€ scfm_utils_local.py
52
- β”‚ β”œβ”€β”€ train_biomod.py
53
- β”‚ └── utils.py
54
- β”œβ”€β”€ tests/ # CPU tests for shared training utilities
55
- β”‚ └── test_training_utils.py
56
- β”œβ”€β”€ toturials/ # Jupyter tutorials for five downstream tasks
57
- β”‚ β”œβ”€β”€ cell_annotation.ipynb
58
- β”‚ β”œβ”€β”€ drug_combination.ipynb
59
- β”‚ β”œβ”€β”€ drug_response_prediction.ipynb
60
- β”‚ β”œβ”€β”€ gene_perturbation.ipynb
61
- β”‚ └── zero_shot_batch_integration.ipynb
62
- β”œβ”€β”€ zero_shot_batch/ # Zero-shot batch integration, evaluation and visualization
63
- β”‚ β”œβ”€β”€ sequencing_depth/ # Low-depth data generation and zero-shot evaluation
64
- β”‚ β”‚ β”œβ”€β”€ cmd.txt
65
- β”‚ β”‚ β”œβ”€β”€ make_low_depth_h5ad.py
66
- β”‚ β”‚ └── run_zero_shot_low_depth.py
67
- β”‚ β”œβ”€β”€ biomod_zero_shot.py
68
- β”‚ β”œβ”€β”€ README.md
69
- β”‚ └── visualize_results.py
70
- β”œβ”€β”€ .env.example
71
- β”œβ”€β”€ .gitattributes
72
- β”œβ”€β”€ .gitignore
73
- β”œβ”€β”€ command.txt
74
- β”œβ”€β”€ environment.yml
75
- β”œβ”€β”€ models_biomod.py
76
- β”œβ”€β”€ biomod_dataset.py
77
- β”œβ”€β”€ biomod.py
78
- β”œβ”€β”€ README.md
79
- β”œβ”€β”€ requirements.txt
80
- └── training_utils.py
81
- ```
82
-
83
- The notebook directory is intentionally named `toturials` to preserve existing
84
- paths used by the project.
85
-
86
- ## Quick Start
87
-
88
- From the outer repository root, enter the source directory and create a fresh
89
- environment:
90
-
91
- ```bash
92
- cd BioMod
93
- conda env create -f environment.yml
94
- conda activate biomod
95
- ```
96
-
97
- Or install Python packages into an existing CUDA/PyTorch environment:
98
-
99
- ```bash
100
- python -m pip install -r requirements.txt
101
- ```
102
-
103
- From this source directory, activate the supplied environment and start Jupyter
104
- with the tutorial directory as its working directory:
105
-
106
- ```bash
107
- conda activate biomod
108
- cd toturials
109
- jupyter lab
110
- ```
111
-
112
- ### Training utility checks
113
-
114
- The pretraining entry point imports `training_utils.py` explicitly. This local
115
- module supplies random seeding, a sequential distributed validation sampler,
116
- cosine learning-rate scheduling with warmup and restarts, scalar metric
117
- reduction, and resumable checkpoint saving. It does not depend on a separate
118
- package named `utils` or on a downstream task's utility module.
119
-
120
- From this source directory, run the CPU utility tests and check entry-point
121
- imports after installing the dependencies:
122
-
123
- ```bash
124
- python -B -m unittest discover -s tests -p test_training_utils.py -v
125
- python -B biomod.py --help
126
- ```
127
-
128
- The utility tests use synthetic tensors and temporary checkpoints; they do not
129
- load the supplied pretrained weights. Passing these checks does not validate a
130
- full training run. The pretraining entry point requires CUDA and an NCCL
131
- process group. Supply `--data_path` explicitly: the pretraining corpus is not
132
- bundled. Configure module inputs with `--biomod_data_dir` or `--biomod_data_path`.
133
- Generated checkpoints default to `tutorial_runs/pretraining/` under the outer
134
- repository root, with periodic latest checkpoints under its `latest/` subdirectory.
135
-
136
- ## Shared Assets
137
-
138
- The BioMod model weights and matching configuration are stored in
139
- the outer repository's `weight/`. Use the supplied `.pth` and `.pkl`
140
- together.
141
-
142
- Tutorials expect a pretrained BioMod checkpoint and shared
143
- gene assets. For the shell examples below, set `BIOMOD_ROOT` to the directory containing
144
- `weight/` and `model_dependencies/` (the outer `BioMod/` project directory).
145
-
146
- ```bash
147
- # Run this from the inner BioMod/ source directory.
148
- export BIOMOD_ROOT="$(cd .. && pwd)"
149
- ```
150
-
151
- Current local asset files:
152
-
153
- ```text
154
- $BIOMOD_ROOT/weight/ # BioMod model weights and matching configuration
155
- β”œβ”€β”€ BioMod.pkl
156
- └── BioMod.pth
157
-
158
- $BIOMOD_ROOT/model_dependencies/ # Shared gene mappings, gene lists, embeddings and model components
159
- β”œβ”€β”€ biomod_data_all/ # Shared module definitions and construction tools
160
- β”‚ β”œβ”€β”€ create_uncovered_biomods.py
161
- β”‚ β”œβ”€β”€ merge_biomods.py
162
- β”‚ └── merged_biomods.json
163
- β”œβ”€β”€ pytorch_cont/ # Attention and model components
164
- β”‚ β”œβ”€β”€ __init__.py
165
- β”‚ β”œβ”€β”€ ding_models.py
166
- β”‚ β”œβ”€β”€ pytorch.py
167
- β”‚ β”œβ”€β”€ pytorch_old.py
168
- β”‚ └── reversible.py
169
- β”œβ”€β”€ gene2ens.csv
170
- β”œβ”€β”€ selected_gene2vec_27k.npy
171
- └── selected_genes_27k.txt
172
- ```
173
-
174
- Module definitions and construction tools are shared through
175
- `$BIOMOD_ROOT/model_dependencies/biomod_data_all/`.
176
-
177
- ## BioMod model weights
178
-
179
- Use `BioMod.pth` with
180
- `BioMod.pkl` from the shared-assets directory above. The supplied
181
- configuration specifies a 2-layer encoder, a 27,874-gene axis, and 660 module
182
- definitions. Keep this configuration paired with the weights so that task
183
- runners can restore the corresponding architecture settings.
184
-
185
- ## Tutorials
186
-
187
- | Task | Notebook | Main entry point | Default output style |
188
- | --- | --- | --- | --- |
189
- | Cell-type annotation | `toturials/cell_annotation.ipynb` | task script under `cell_annotation/` | metrics, classification report, confusion matrix |
190
- | Zero-shot batch integration | `toturials/zero_shot_batch_integration.ipynb` | `zero_shot_batch/` runner | UMAP PDF/PNG, avgBatch, avgBio |
191
- | Gene perturbation | `toturials/gene_perturbation.ipynb` | `gene_perturbation/` runner | selected model, configuration, parameters, and training log |
192
- | Drug response prediction | `toturials/drug_response_prediction.ipynb` | `drug_response/train_drug_biomod.py` | scatter, residuals, ROC, per-drug and per-cancer tables |
193
- | Drug-combination synergy | `toturials/drug_combination.ipynb` | `drug_combination/train_drug_combination_biomod.py` | label balance, loss, validation metrics, and ROC curves |
194
-
195
- Each notebook derives paths from `PROJECT_ROOT = Path('../..').resolve()` when
196
- Jupyter runs from `BioMod/toturials/`. From the repository root, change this to
197
- `Path('.').resolve()`. Training is disabled by default with `RUN_TRAINING = False`;
198
- zero-shot inference uses `RUN_EVALUATION = False`. Review the configuration and
199
- path checks before enabling execution. The shell variable `BIOMOD_ROOT` is for
200
- the command examples only and does not override notebook configuration cells.
201
-
202
- ## Data Layout
203
-
204
- The Hugging Face repository includes datasets under the project-root `data/`
205
- directory. Individual tasks may require additional inputs or a different data
206
- layout. Check each task's required files, then configure its data paths for the
207
- local environment; the presence of `data/` does not imply that every tutorial
208
- has all of its inputs.
209
-
210
- ### Single-Drug Response
211
-
212
- Expected clean data root:
213
-
214
- ```text
215
- data/downstream/final_data/single_drug_response/data/
216
- |-- CCLE/
217
- | |-- Cell_lines_annotations_20181226.txt
218
- | |-- GDSC_IC50.csv
219
- | `-- genomic_expression_561celllines_697genes_demap_features.csv
220
- `-- GDSC/
221
- |-- 1.Drug_listMon Jun 24 09_00_55 2019.csv
222
- `-- drug_graph_feat/
223
- ```
224
-
225
- ### Drug-Combination Synergy
226
-
227
- Expected clean data root:
228
-
229
- ```text
230
- data/downstream/final_data/drug_combination_synergy/data_summary/
231
- |-- new_labels_0_10.csv
232
- |-- new_cell_features_954.csv
233
- |-- smiles_0_10.csv
234
- `-- test_data/
235
- |-- independent_input.csv
236
- `-- independent_cell_features_954.csv
237
- ```
238
-
239
- The drug-combination tutorial reads the metric tables and ROC artifacts produced
240
- by its training script. The script does not export per-example prediction CSVs.
241
-
242
- ## Example Commands
243
-
244
- Run these commands from the inner `BioMod/` source directory after setting
245
- `BIOMOD_ROOT` as shown above. Drug response prediction with the BioMod model weights:
246
-
247
- ```bash
248
- python drug_response/train_drug_biomod.py \
249
- --gpu_id 0 \
250
- --data_path "$BIOMOD_ROOT/data/downstream/final_data/single_drug_response/data" \
251
- --checkpoint_path "$BIOMOD_ROOT/weight/BioMod.pth" \
252
- --hyper_params_path "$BIOMOD_ROOT/weight/BioMod.pkl" \
253
- --biomod_data_dir "$BIOMOD_ROOT/model_dependencies/biomod_data_all" \
254
- --gene_list_path "$BIOMOD_ROOT/model_dependencies/selected_genes_27k.txt" \
255
- --gene_mapping_path "$BIOMOD_ROOT/model_dependencies/gene2ens.csv" \
256
- --gene2vec_path "$BIOMOD_ROOT/model_dependencies/selected_gene2vec_27k.npy" \
257
- --symbol2ens_path "$BIOMOD_ROOT/model_dependencies/gene2ens.csv" \
258
- --save_dir "$BIOMOD_ROOT/tutorial_runs/drug_response_prediction" \
259
- --epochs 300 \
260
- --batch_size 32 \
261
- --pool_method max
262
- ```
263
-
264
- Drug-combination synergy prediction:
265
-
266
- ```bash
267
- python drug_combination/train_drug_combination_biomod.py \
268
- --checkpoint_path "$BIOMOD_ROOT/weight/BioMod.pth" \
269
- --hyper_params_path "$BIOMOD_ROOT/weight/BioMod.pkl" \
270
- --biomod_data_dir "$BIOMOD_ROOT/model_dependencies/biomod_data_all" \
271
- --gene_list_path "$BIOMOD_ROOT/model_dependencies/selected_genes_27k.txt" \
272
- --gene_mapping_path "$BIOMOD_ROOT/model_dependencies/gene2ens.csv" \
273
- --gene2vec_path "$BIOMOD_ROOT/model_dependencies/selected_gene2vec_27k.npy" \
274
- --symbol2ens_path "$BIOMOD_ROOT/model_dependencies/gene2ens.csv" \
275
- --data_dir "$BIOMOD_ROOT/data/downstream/final_data/drug_combination_synergy/data_summary" \
276
- --output_dir "$BIOMOD_ROOT/tutorial_runs/drug_combination/results" \
277
- --epochs 500 \
278
- --batch_size 256 \
279
- --lr 1e-4 \
280
- --n_folds 1 \
281
- --pool_method max
282
- ```
283
-
284
- ## Display Outputs
285
-
286
- The notebooks regenerate figure files in task output directories. Typical files
287
- include:
288
-
289
- | Task | Generated display files |
290
- | --- | --- |
291
- | Zero-shot integration | A4 UMAP PDF/PNG panels, combined cell-type and batch views |
292
- | Drug response | `drug_response_overall_scatter.pdf`, `drug_response_median_threshold_roc.svg`, per-drug and per-cancer CSV summaries |
293
- | Drug combination | `drug_combination_metric_curves.pdf`, `drug_combination_roc_curves.pdf`, `drug_combination_label_balance.pdf` |
294
- | Cell annotation | confusion matrices and classification reports |
295
- | Gene perturbation | training logs containing perturbation evaluation metrics |
296
-
297
- For GitHub display, use PNG files. For manuscripts, use the PDF/SVG exports.
298
- The plotting cells use embedded, editable PDF fonts where supported.
299
-
300
- ## Evaluation Results
301
-
302
- This README does not provide verified benchmark scores for the bundled BioMod
303
- model weights. Run the relevant task with a recorded data split and configuration
304
- before reporting performance. Notebook plotting cells and historical outputs
305
- alone do not establish performance for the supplied weights.
306
-
307
- ## Reproducibility Conventions
308
-
309
- - Record the exact command line, checkpoint, hyper-parameter pkl, data version,
310
- random seed, and output directory for every final run.
311
- - Keep raw data, cached embeddings, model checkpoints, metric tables, and paper
312
- figures in separate directories.
313
- - Prefer shared storage for large `.h5ad`, `.npy`, and checkpoint outputs.
314
- - Do not commit private data, raw model weights, API keys, or personal absolute
315
- paths.
316
-
317
- ## Troubleshooting
318
-
319
- ### Missing data
320
-
321
- Open the relevant notebook and run the path-check cell. It prints all required
322
- files and shows which entries are missing.
323
-
324
- ### Missing model assets
325
-
326
- Check `BIOMOD_ROOT` for shell commands or `PROJECT_ROOT` in a notebook, and verify that the BioMod model weights, matching
327
- `.pkl` configuration, gene2vec file, gene list, gene mapping, and
328
- `pytorch_cont/` directory exist at the paths listed under Shared Assets.
329
-
330
- ### No space left on device
331
-
332
- Large `.h5ad`, `.npy`, checkpoint, and figure outputs can fill local disks.
333
- Move result directories to shared storage and remove partial failed outputs only
334
- after confirming they are not needed.
335
-
336
- ### Matplotlib font warnings
337
-
338
- The notebooks request Arial first and fall back to DejaVu Sans when Arial is not
339
- installed. PDF font embedding is enabled through `pdf.fonttype = 42`.
340
-
341
- ## GitHub Release Checklist
342
-
343
- - Keep `README.md`, `requirements.txt`, `environment.yml`, `.gitignore`, and
344
- `.gitattributes` at the repository root.
345
- - Confirm tutorial notebooks open without personal paths.
346
- - Keep large data and checkpoints outside Git, then document download or
347
- placement instructions.
348
- - Add final figure examples under a small `docs/` or `assets/` directory if the
349
- repository needs rendered images on the GitHub landing page.
350
- - Add license, citation, and data-availability text before public release.
351
-
352
- ## Changelog
353
-
354
- | Date | Change |
355
- | --- | --- |
356
- | 2026-06-15 | Added paper-style plotting cells for single-drug and drug-combination tutorials. |
357
- | 2026-06-15 | Removed `stage2_alignment/` from the active repository scope. |
358
- | 2026-06-15 | Added root environment files and GitHub-ready repository documentation. |
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # BioMod
2
+
3
+ Source code and tutorial notebooks for BioMod single-cell pretraining and
4
+ downstream experiments using BioMod representations.
5
+
6
+ This source directory contains the pretraining entry point and shared training
7
+ utilities, alongside downstream task runners, tutorial notebooks, environment
8
+ files, and plotting helpers.
9
+
10
+ ## Highlights
11
+
12
+ | Area | What is included |
13
+ | --- | --- |
14
+ | Representation | Module-based single-cell encoder utilities and module metadata |
15
+ | Annotation | Supervised cell-type annotation workflows |
16
+ | Integration | Zero-shot batch integration and UMAP/scIB-style reporting |
17
+ | Perturbation | Norman gene-perturbation training and evaluation tutorial |
18
+ | Drug response | Single-drug response prediction with GDSC/CCLE data and validation-based model selection |
19
+ | Drug combinations | Drug-combination synergy prediction with validation-based model selection |
20
+ | Figures | Notebook-level PDF/PNG/SVG plotting cells for paper and GitHub display |
21
+
22
+ ## Repository Layout
23
+
24
+ This is the `BioMod/` source directory inside the project root. See the
25
+ [full project layout](../README.md#repository-layout) for sibling
26
+ `model_dependencies/` and `weight/` directories; `data/` and `.cache/` are omitted
27
+ from these repository trees.
28
+
29
+ Each downstream task provides a `README.md`, a `tutorial.ipynb`, and a `train.py`
30
+ entry point, except zero-shot evaluation, which uses `evaluate.py`. Gene
31
+ perturbation keeps its supporting code in `components/`; zero-shot visualization
32
+ and sequencing-depth helpers are under `tools/`. Optional Hallmark and Reactome
33
+ source definitions are shared under `model_dependencies/biomod_data_sources/`
34
+ in the outer project root.
35
+
36
+ ```text
37
+ BioMod/ # Task code: training, evaluation and tutorials
38
+ β”œβ”€β”€ cell_annotation/ # Cell-type annotation and model fine-tuning
39
+ β”‚ β”œβ”€β”€ README.md
40
+ β”‚ β”œβ”€β”€ train.py
41
+ β”‚ └── tutorial.ipynb
42
+ β”œβ”€β”€ drug_combination/ # Drug-combination synergy prediction
43
+ β”‚ β”œβ”€β”€ README.md
44
+ β”‚ β”œβ”€β”€ train.py
45
+ β”‚ └── tutorial.ipynb
46
+ β”œβ”€β”€ drug_response/ # Single-drug response prediction
47
+ β”‚ β”œβ”€β”€ README.md
48
+ β”‚ β”œβ”€β”€ train.py
49
+ β”‚ └── tutorial.ipynb
50
+ β”œβ”€β”€ gene_perturbation/ # Gene perturbation response prediction
51
+ β”‚ β”œβ”€β”€ components/ # Task models, datasets, training and inference helpers
52
+ β”‚ β”‚ β”œβ”€β”€ __init__.py
53
+ β”‚ β”‚ β”œβ”€β”€ data_utils.py
54
+ β”‚ β”‚ β”œβ”€β”€ dataset.py
55
+ β”‚ β”‚ β”œβ”€β”€ inference.py
56
+ β”‚ β”‚ β”œβ”€β”€ model.py
57
+ β”‚ β”‚ β”œβ”€β”€ trainer.py
58
+ β”‚ β”‚ β”œβ”€β”€ training_utils.py
59
+ β”‚ β”‚ └── utils.py
60
+ β”‚ β”œβ”€β”€ README.md
61
+ β”‚ β”œβ”€β”€ train.py
62
+ β”‚ └── tutorial.ipynb
63
+ β”œβ”€β”€ tests/ # CPU tests for shared training utilities
64
+ β”‚ └── test_training_utils.py
65
+ β”œβ”€β”€ zero_shot_batch/ # Zero-shot integration and evaluation
66
+ β”‚ β”œβ”€β”€ tools/ # Optional visualization and evaluation tools
67
+ β”‚ β”‚ β”œβ”€β”€ sequencing_depth/ # Low-depth expression generation and evaluation
68
+ β”‚ β”‚ β”‚ β”œβ”€β”€ make_low_depth_h5ad.py
69
+ β”‚ β”‚ β”‚ β”œβ”€β”€ README.md
70
+ β”‚ β”‚ β”‚ └── run_zero_shot_low_depth.py
71
+ β”‚ β”‚ └── visualize_results.py
72
+ β”‚ β”œβ”€β”€ evaluate.py
73
+ β”‚ β”œβ”€β”€ README.md
74
+ β”‚ └── tutorial.ipynb
75
+ β”œβ”€β”€ .gitattributes
76
+ β”œβ”€β”€ .gitignore
77
+ β”œβ”€β”€ biomod.py
78
+ β”œβ”€β”€ biomod_dataset.py
79
+ β”œβ”€β”€ command.txt
80
+ β”œβ”€β”€ environment.yml
81
+ β”œβ”€β”€ models_biomod.py
82
+ β”œβ”€β”€ README.md
83
+ β”œβ”€β”€ requirements.txt
84
+ └── training_utils.py
85
+ ```
86
+
87
+ ## Quick Start
88
+
89
+ From the outer repository root, enter the source directory and create a fresh
90
+ environment:
91
+
92
+ ```bash
93
+ cd BioMod
94
+ conda env create -f environment.yml
95
+ conda activate biomod
96
+ ```
97
+
98
+ Or install Python packages into an existing CUDA/PyTorch environment:
99
+
100
+ ```bash
101
+ python -m pip install -r requirements.txt
102
+ ```
103
+
104
+ From this source directory, activate the supplied environment and start Jupyter
105
+ in the chosen task directory. For cell annotation:
106
+
107
+ ```bash
108
+ conda activate biomod
109
+ cd cell_annotation
110
+ jupyter lab tutorial.ipynb
111
+ ```
112
+
113
+ Use `drug_response`, `drug_combination`, `gene_perturbation`, or `zero_shot_batch`
114
+ in place of `cell_annotation` to open another task.
115
+
116
+ ### Training utility checks
117
+
118
+ The pretraining entry point imports `training_utils.py` explicitly. This local
119
+ module supplies random seeding, a sequential distributed validation sampler,
120
+ cosine learning-rate scheduling with warmup and restarts, scalar metric
121
+ reduction, and resumable checkpoint saving. It does not depend on a separate
122
+ package named `utils` or on a downstream task's utility module.
123
+
124
+ From this source directory, run the CPU utility tests and check entry-point
125
+ imports after installing the dependencies:
126
+
127
+ ```bash
128
+ python -B -m unittest discover -s tests -p test_training_utils.py -v
129
+ python -B biomod.py --help
130
+ ```
131
+
132
+ The utility tests use synthetic tensors and temporary checkpoints; they do not
133
+ load the supplied pretrained weights. Passing these checks does not validate a
134
+ full training run. The pretraining entry point requires CUDA and an NCCL
135
+ process group. Supply `--data_path` explicitly: the pretraining corpus is not
136
+ bundled. Configure module inputs with `--biomod_data_dir` or `--biomod_data_path`.
137
+ Generated checkpoints default to `tutorial_runs/pretraining/` under the outer
138
+ repository root, with periodic latest checkpoints under its `latest/` subdirectory.
139
+
140
+ ## Shared Assets
141
+
142
+ The BioMod model weights and matching configuration are stored in
143
+ the outer repository's `weight/`. Use the supplied `.pth` and `.pkl`
144
+ together.
145
+
146
+ Tutorials expect a pretrained BioMod checkpoint and shared
147
+ gene assets. For the shell examples below, set `BIOMOD_ROOT` to the directory containing
148
+ `weight/` and `model_dependencies/` (the outer `BioMod/` project directory).
149
+
150
+ ```bash
151
+ # Run this from the inner BioMod/ source directory.
152
+ export BIOMOD_ROOT="$(cd .. && pwd)"
153
+ ```
154
+
155
+ Current local asset files:
156
+
157
+ ```text
158
+ $BIOMOD_ROOT/weight/ # BioMod model weights and matching configuration
159
+ β”œβ”€β”€ BioMod.pkl
160
+ └── BioMod.pth
161
+
162
+ $BIOMOD_ROOT/model_dependencies/ # Shared gene mappings, gene lists, embeddings and model components
163
+ β”œβ”€β”€ biomod_data_all/ # Shared module definitions and construction tools
164
+ β”‚ β”œβ”€β”€ create_uncovered_biomods.py
165
+ β”‚ β”œβ”€β”€ merge_biomods.py
166
+ β”‚ └── merged_biomods.json
167
+ β”œβ”€β”€ biomod_data_sources/ # Optional Hallmark and Reactome source definitions
168
+ β”‚ β”œβ”€β”€ biomod1_hallmarks.json
169
+ β”‚ β”œβ”€β”€ biomod2_reactome_2022_filtered.json
170
+ β”‚ └── load_biomod.py
171
+ β”œβ”€β”€ pytorch_cont/ # Attention and model components
172
+ β”‚ β”œβ”€β”€ __init__.py
173
+ β”‚ β”œβ”€β”€ ding_models.py
174
+ β”‚ β”œβ”€β”€ pytorch.py
175
+ β”‚ β”œβ”€β”€ pytorch_old.py
176
+ β”‚ └── reversible.py
177
+ β”œβ”€β”€ gene2ens.csv
178
+ β”œβ”€β”€ selected_gene2vec_27k.npy
179
+ └── selected_genes_27k.txt
180
+ ```
181
+
182
+ Default runtime module definitions and construction tools are shared through
183
+ `$BIOMOD_ROOT/model_dependencies/biomod_data_all/`. The optional
184
+ [Hallmark and Reactome source definitions](../model_dependencies/biomod_data_sources/)
185
+ and JSON loading helper are stored in `biomod_data_sources/`. These source
186
+ resources do not replace the default definitions paired with the supplied checkpoint.
187
+
188
+ ## BioMod model weights
189
+
190
+ Use `BioMod.pth` with
191
+ `BioMod.pkl` from the shared-assets directory above. The supplied
192
+ configuration specifies a 2-layer encoder, a 27,874-gene axis, and 660 module
193
+ definitions. Keep this configuration paired with the weights so that task
194
+ runners can restore the corresponding architecture settings.
195
+
196
+ ## Tutorials
197
+
198
+ | Task | Notebook | Main entry point | Default output style |
199
+ | --- | --- | --- | --- |
200
+ | Cell-type annotation | [Notebook](cell_annotation/tutorial.ipynb) | `cell_annotation/train.py` | metrics, classification report, confusion matrix |
201
+ | Zero-shot batch integration | [Notebook](zero_shot_batch/tutorial.ipynb) | `zero_shot_batch/evaluate.py` | UMAP PDF/PNG, avgBatch, avgBio |
202
+ | Gene perturbation | [Notebook](gene_perturbation/tutorial.ipynb) | `gene_perturbation/train.py` | selected model, configuration, parameters, and training log |
203
+ | Drug response prediction | [Notebook](drug_response/tutorial.ipynb) | `drug_response/train.py` | scatter, residuals, ROC, per-drug and per-cancer tables |
204
+ | Drug-combination synergy | [Notebook](drug_combination/tutorial.ipynb) | `drug_combination/train.py` | label balance, loss, validation metrics, and ROC curves |
205
+
206
+ Each notebook derives paths from `PROJECT_ROOT = Path('../..').resolve()` when
207
+ its kernel runs from the corresponding task directory, such as
208
+ `BioMod/cell_annotation/`. With a different kernel working directory, set
209
+ `PROJECT_ROOT` explicitly to the outer repository root. Training is disabled by
210
+ default with `RUN_TRAINING = False`; zero-shot inference uses
211
+ `RUN_EVALUATION = False`. Review the configuration and
212
+ path checks before enabling execution. The shell variable `BIOMOD_ROOT` is for
213
+ the command examples only and does not override notebook configuration cells.
214
+
215
+ ## Data Layout
216
+
217
+ The Hugging Face repository includes datasets under the project-root `data/`
218
+ directory. Individual tasks may require additional inputs or a different data
219
+ layout. Check each task's required files, then configure its data paths for the
220
+ local environment; the presence of `data/` does not imply that every tutorial
221
+ has all of its inputs.
222
+
223
+ ### Single-Drug Response
224
+
225
+ Expected clean data root:
226
+
227
+ ```text
228
+ data/downstream/final_data/single_drug_response/data/
229
+ |-- CCLE/
230
+ | |-- Cell_lines_annotations_20181226.txt
231
+ | |-- GDSC_IC50.csv
232
+ | `-- genomic_expression_561celllines_697genes_demap_features.csv
233
+ `-- GDSC/
234
+ |-- 1.Drug_listMon Jun 24 09_00_55 2019.csv
235
+ `-- drug_graph_feat/
236
+ ```
237
+
238
+ ### Drug-Combination Synergy
239
+
240
+ Expected clean data root:
241
+
242
+ ```text
243
+ data/downstream/final_data/drug_combination_synergy/data_summary/
244
+ |-- new_labels_0_10.csv
245
+ |-- new_cell_features_954.csv
246
+ |-- smiles_0_10.csv
247
+ `-- test_data/
248
+ |-- independent_input.csv
249
+ `-- independent_cell_features_954.csv
250
+ ```
251
+
252
+ The drug-combination tutorial reads the metric tables and ROC artifacts produced
253
+ by its training script. The script does not export per-example prediction CSVs.
254
+
255
+ ## Example Commands
256
+
257
+ Run these commands from the inner `BioMod/` source directory after setting
258
+ `BIOMOD_ROOT` as shown above. Drug response prediction with the BioMod model weights:
259
+
260
+ ```bash
261
+ python drug_response/train.py \
262
+ --gpu_id 0 \
263
+ --data_path "$BIOMOD_ROOT/data/downstream/final_data/single_drug_response/data" \
264
+ --checkpoint_path "$BIOMOD_ROOT/weight/BioMod.pth" \
265
+ --hyper_params_path "$BIOMOD_ROOT/weight/BioMod.pkl" \
266
+ --biomod_data_dir "$BIOMOD_ROOT/model_dependencies/biomod_data_all" \
267
+ --gene_list_path "$BIOMOD_ROOT/model_dependencies/selected_genes_27k.txt" \
268
+ --gene_mapping_path "$BIOMOD_ROOT/model_dependencies/gene2ens.csv" \
269
+ --gene2vec_path "$BIOMOD_ROOT/model_dependencies/selected_gene2vec_27k.npy" \
270
+ --symbol2ens_path "$BIOMOD_ROOT/model_dependencies/gene2ens.csv" \
271
+ --save_dir "$BIOMOD_ROOT/tutorial_runs/drug_response_prediction" \
272
+ --epochs 300 \
273
+ --batch_size 32 \
274
+ --pool_method max
275
+ ```
276
+
277
+ Drug-combination synergy prediction:
278
+
279
+ ```bash
280
+ python drug_combination/train.py \
281
+ --checkpoint_path "$BIOMOD_ROOT/weight/BioMod.pth" \
282
+ --hyper_params_path "$BIOMOD_ROOT/weight/BioMod.pkl" \
283
+ --biomod_data_dir "$BIOMOD_ROOT/model_dependencies/biomod_data_all" \
284
+ --gene_list_path "$BIOMOD_ROOT/model_dependencies/selected_genes_27k.txt" \
285
+ --gene_mapping_path "$BIOMOD_ROOT/model_dependencies/gene2ens.csv" \
286
+ --gene2vec_path "$BIOMOD_ROOT/model_dependencies/selected_gene2vec_27k.npy" \
287
+ --symbol2ens_path "$BIOMOD_ROOT/model_dependencies/gene2ens.csv" \
288
+ --data_dir "$BIOMOD_ROOT/data/downstream/final_data/drug_combination_synergy/data_summary" \
289
+ --output_dir "$BIOMOD_ROOT/tutorial_runs/drug_combination/results" \
290
+ --epochs 500 \
291
+ --batch_size 256 \
292
+ --lr 1e-4 \
293
+ --n_folds 1 \
294
+ --pool_method max
295
+ ```
296
+
297
+ ## Display Outputs
298
+
299
+ The notebooks regenerate figure files in task output directories. Typical files
300
+ include:
301
+
302
+ | Task | Generated display files |
303
+ | --- | --- |
304
+ | Zero-shot integration | A4 UMAP PDF/PNG panels, combined cell-type and batch views |
305
+ | Drug response | `drug_response_overall_scatter.pdf`, `drug_response_median_threshold_roc.svg`, per-drug and per-cancer CSV summaries |
306
+ | Drug combination | `drug_combination_metric_curves.pdf`, `drug_combination_roc_curves.pdf`, `drug_combination_label_balance.pdf` |
307
+ | Cell annotation | confusion matrices and classification reports |
308
+ | Gene perturbation | training logs containing perturbation evaluation metrics |
309
+
310
+ For GitHub display, use PNG files. For manuscripts, use the PDF/SVG exports.
311
+ The plotting cells use embedded, editable PDF fonts where supported.
312
+
313
+ ## Evaluation Results
314
+
315
+ This README does not provide verified benchmark scores for the bundled BioMod
316
+ model weights. Run the relevant task with a recorded data split and configuration
317
+ before reporting performance. Notebook plotting cells and historical outputs
318
+ alone do not establish performance for the supplied weights.
319
+
320
+ ## Reproducibility Conventions
321
+
322
+ - Record the exact command line, checkpoint, hyper-parameter pkl, data version,
323
+ random seed, and output directory for every final run.
324
+ - Keep raw data, cached embeddings, model checkpoints, metric tables, and paper
325
+ figures in separate directories.
326
+ - Prefer shared storage for large `.h5ad`, `.npy`, and checkpoint outputs.
327
+ - Do not commit private data, raw model weights, API keys, or personal absolute
328
+ paths.
329
+
330
+ ## Troubleshooting
331
+
332
+ ### Missing data
333
+
334
+ Open the relevant notebook and run the path-check cell. It prints all required
335
+ files and shows which entries are missing.
336
+
337
+ ### Missing model assets
338
+
339
+ Check `BIOMOD_ROOT` for shell commands or `PROJECT_ROOT` in a notebook, and verify that the BioMod model weights, matching
340
+ `.pkl` configuration, gene2vec file, gene list, gene mapping, and
341
+ `pytorch_cont/` directory exist at the paths listed under Shared Assets.
342
+
343
+ ### No space left on device
344
+
345
+ Large `.h5ad`, `.npy`, checkpoint, and figure outputs can fill local disks.
346
+ Move result directories to shared storage and remove partial failed outputs only
347
+ after confirming they are not needed.
348
+
349
+ ### Matplotlib font warnings
350
+
351
+ The notebooks request Arial first and fall back to DejaVu Sans when Arial is not
352
+ installed. PDF font embedding is enabled through `pdf.fonttype = 42`.
353
+
354
+ ## GitHub Release Checklist
355
+
356
+ - Keep `README.md`, `requirements.txt`, `environment.yml`, `.gitignore`, and
357
+ `.gitattributes` at the repository root.
358
+ - Confirm tutorial notebooks open without personal paths.
359
+ - Keep large data and checkpoints outside Git, then document download or
360
+ placement instructions.
361
+ - Add final figure examples under a small `docs/` or `assets/` directory if the
362
+ repository needs rendered images on the GitHub landing page.
363
+ - Add license, citation, and data-availability text before public release.
364
+
365
+ ## Changelog
366
+
367
+ | Date | Change |
368
+ | --- | --- |
369
+ | 2026-06-15 | Added paper-style plotting cells for single-drug and drug-combination tutorials. |
370
+ | 2026-06-15 | Removed `stage2_alignment/` from the active repository scope. |
371
+ | 2026-06-15 | Added root environment files and GitHub-ready repository documentation. |
BioMod/cell_annotation/README.md ADDED
@@ -0,0 +1,282 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Cell Annotation with BioMod
2
+
3
+ Fine-tune BioMod to predict cell-type labels from single-cell gene expression.
4
+ The training script supports frozen, partially unfrozen, and fully trainable
5
+ backbones with several cell-embedding heads.
6
+
7
+ ## Notebook
8
+
9
+ See the [task notebook](tutorial.ipynb) for a step-by-step workflow.
10
+
11
+ ## Files
12
+
13
+ | File or directory | Purpose |
14
+ | --- | --- |
15
+ | [README.md](README.md) | File guide and command-line training example. |
16
+ | [tutorial.ipynb](tutorial.ipynb) | Task configuration, execution, and result review in a Jupyter notebook. |
17
+ | [train.py](train.py) | Train and evaluate the cell-type classifier with the BioMod backbone. |
18
+
19
+ ## Optional Module Sources
20
+
21
+ The optional [Hallmark and Reactome source definitions](../../model_dependencies/biomod_data_sources/)
22
+ are stored separately from this task. They include
23
+ [Hallmark modules](../../model_dependencies/biomod_data_sources/biomod1_hallmarks.json),
24
+ [filtered Reactome modules](../../model_dependencies/biomod_data_sources/biomod2_reactome_2022_filtered.json),
25
+ and a [JSON loading helper](../../model_dependencies/biomod_data_sources/load_biomod.py).
26
+ These source resources are not the default runtime module definitions for the
27
+ supplied checkpoint. The training example below continues to use
28
+ `model_dependencies/biomod_data_all/` with the matching BioMod weights and configuration.
29
+
30
+ ## Dataset Commands
31
+
32
+ The manuscript's annotation task covers seven benchmarks. The commands below
33
+ map those benchmarks to the files currently bundled in this repository; paired
34
+ files are one benchmark, not two separate datasets. Kim Lung has an unresolved
35
+ missing-label policy documented in its section.
36
+
37
+ Run from the outer repository root after installing the environment. Explicit
38
+ relative paths resolve from the working directory. Each command writes to its
39
+ own `tutorial_runs/` directory. Ordinary `python` supports one GPU; CUDA DDP with
40
+ multiple processes additionally requires a working NCCL environment.
41
+
42
+ The command blocks use Bash line continuations (`\`). Run them in Bash, such as
43
+ Linux, WSL or Git Bash. In PowerShell, join each command into a single line
44
+ instead of copying the Bash continuation characters.
45
+
46
+ ### Training Protocol and Limits
47
+
48
+ The settings shared by these examples follow the available options for the
49
+ annotation method described in manuscript Section 4.5 (PDF pages 24–25): attention
50
+ pooling, a three-layer classifier, dropout 0.2, full encoder-path fine-tuning,
51
+ AdamW, backbone and head learning rates of `1e-4`, and weight decay `0.01`.
52
+ The script applies cosine annealing internally. `--label_smoothing 0` selects
53
+ the plain cross-entropy loss shown in the manuscript instead of the script's
54
+ default label smoothing of 0.1.
55
+
56
+ The manuscript does not specify the annotation batch size, epoch limit, patience,
57
+ or complete seed list in this section. The examples explicitly use batch size
58
+ 32, 50 epochs, patience 10 and seed 0 as launch settings; these values are not
59
+ claimed to reproduce the reported five-run results. Reduce the batch size to
60
+ fit available GPU memory and retain the actual experiment settings for reporting.
61
+ The best checkpoint is selected by validation macro-F1, then evaluated on the
62
+ test set.
63
+
64
+ The classification report and confusion matrix include every declared class,
65
+ including rows with zero test support. The report's macro average covers this
66
+ full class list. Training and evaluation `macro_f1` values use the classes
67
+ present in the true or predicted labels, so the two averages can differ when
68
+ some declared classes are absent from both. Checkpoint selection keeps the
69
+ existing validation metric.
70
+
71
+ For single files, the entry point creates a stratified 70% / 10% / 20% split.
72
+ For paired files, it splits the supplied training file 90% / 10% and uses the
73
+ entire supplied test file for final evaluation. Stored split columns in `obs`
74
+ are not used. The manuscript does not list these exact filenames, so the
75
+ reference/query mapping is based on the bundled file organization and metadata.
76
+
77
+ Both expression filtering thresholds are explicitly zero to preserve the supplied
78
+ cells and genes. The entry point reads `adata.X` as supplied: it does not select
79
+ `layers["counts"]` or `.raw`, normalize counts, or apply `log1p`. Metadata checks
80
+ do not establish that each expression matrix has the intended preprocessing.
81
+ Model training and manuscript-result reproduction have not been validated by
82
+ these command examples.
83
+
84
+ ### 1. Kim Lung
85
+
86
+ **Conditional configuration: missing-label handling must be resolved before
87
+ benchmarking.** The file contains 32,493 cells, including 2,021 cells with missing
88
+ `cell_type`. The current classifier converts labels to strings, so the command
89
+ below would treat missing values as an extra class instead of excluding them.
90
+ The manuscript does not specify the annotation policy for these cells. This
91
+ block records the intended file and fields; it is not a verified reproduction
92
+ command. Do not silently relabel or remove cells from the original file.
93
+
94
+ ```bash
95
+ python BioMod/cell_annotation/train.py \
96
+ --data_path data/downstream/final_data/Kim2020_Lung.h5ad \
97
+ --label_column cell_type --gene_name_column gene_name \
98
+ --val_ratio 0.1 --test_ratio 0.2 \
99
+ --biomod_checkpoint weight/BioMod.pth --config_pkl weight/BioMod.pkl \
100
+ --biomod_data_dir model_dependencies/biomod_data_all \
101
+ --gene_list_path model_dependencies/selected_genes_27k.txt \
102
+ --gene2ens_file model_dependencies/gene2ens.csv --gene_mapping_path model_dependencies/gene2ens.csv \
103
+ --gene2vec_data_path model_dependencies/selected_gene2vec_27k.npy \
104
+ --head_type attn_pool --finetune_mode full --cls_decoder_layers 3 \
105
+ --dropout 0.2 --label_smoothing 0 \
106
+ --lr_head 1e-4 --lr_backbone 1e-4 --weight_decay 0.01 \
107
+ --min_genes 0 --min_cells 0 \
108
+ --batch_size 32 --epochs 50 --patience 10 --seed 0 \
109
+ --save_test_artifacts --output_dir tutorial_runs/cell_annotation_kim_lung --run_name seed0
110
+ ```
111
+
112
+ ### 2. Immune
113
+
114
+ Use the 33,506-cell matrix and its 16 `final_annotation` classes. Gene symbols
115
+ are stored in `var.index`. A new stratified 70% / 10% / 20% split is created.
116
+
117
+ ```bash
118
+ python BioMod/cell_annotation/train.py \
119
+ --data_path data/downstream/final_data/Immune_ALL_human.h5ad \
120
+ --label_column final_annotation --gene_name_column index \
121
+ --val_ratio 0.1 --test_ratio 0.2 \
122
+ --biomod_checkpoint weight/BioMod.pth --config_pkl weight/BioMod.pkl \
123
+ --biomod_data_dir model_dependencies/biomod_data_all \
124
+ --gene_list_path model_dependencies/selected_genes_27k.txt \
125
+ --gene2ens_file model_dependencies/gene2ens.csv --gene_mapping_path model_dependencies/gene2ens.csv \
126
+ --gene2vec_data_path model_dependencies/selected_gene2vec_27k.npy \
127
+ --head_type attn_pool --finetune_mode full --cls_decoder_layers 3 \
128
+ --dropout 0.2 --label_smoothing 0 \
129
+ --lr_head 1e-4 --lr_backbone 1e-4 --weight_decay 0.01 \
130
+ --min_genes 0 --min_cells 0 \
131
+ --batch_size 32 --epochs 50 --patience 10 --seed 0 \
132
+ --save_test_artifacts --output_dir tutorial_runs/cell_annotation_immune --run_name seed0
133
+ ```
134
+
135
+ ### 3. Liver
136
+
137
+ Use the 8,444-cell matrix and its 20 `cell_type` classes. Gene symbols are stored
138
+ in `var.index`. A new stratified 70% / 10% / 20% split is created.
139
+
140
+ ```bash
141
+ python BioMod/cell_annotation/train.py \
142
+ --data_path data/downstream/final_data/liver.h5ad \
143
+ --label_column cell_type --gene_name_column index \
144
+ --val_ratio 0.1 --test_ratio 0.2 \
145
+ --biomod_checkpoint weight/BioMod.pth --config_pkl weight/BioMod.pkl \
146
+ --biomod_data_dir model_dependencies/biomod_data_all \
147
+ --gene_list_path model_dependencies/selected_genes_27k.txt \
148
+ --gene2ens_file model_dependencies/gene2ens.csv --gene_mapping_path model_dependencies/gene2ens.csv \
149
+ --gene2vec_data_path model_dependencies/selected_gene2vec_27k.npy \
150
+ --head_type attn_pool --finetune_mode full --cls_decoder_layers 3 \
151
+ --dropout 0.2 --label_smoothing 0 \
152
+ --lr_head 1e-4 --lr_backbone 1e-4 --weight_decay 0.01 \
153
+ --min_genes 0 --min_cells 0 \
154
+ --batch_size 32 --epochs 50 --patience 10 --seed 0 \
155
+ --save_test_artifacts --output_dir tutorial_runs/cell_annotation_liver --run_name seed0
156
+ ```
157
+
158
+ ### 4. MS
159
+
160
+ Keep the 13,468-cell external test file separate. The 7,844-cell training file
161
+ is split 90% / 10% for training and validation. All 18 test labels occur in the
162
+ training file. Some training classes contain only three or four cells, so a
163
+ small validation split may not contain every rare class.
164
+
165
+ Use `index_column`, which contains Ensembl IDs in both files. The training file
166
+ has an index *named* `gene_name`, but no `var["gene_name"]` column. Consequently,
167
+ the unmodified `--dataset_preset ms` gene-column default is incompatible with
168
+ that file. The explicit configuration below avoids that default.
169
+
170
+ ```bash
171
+ python BioMod/cell_annotation/train.py \
172
+ --train_data_path data/downstream/final_data/MS/c_data.h5ad \
173
+ --test_data_path data/downstream/final_data/MS/filtered_ms_adata.h5ad \
174
+ --label_column celltype --test_label_column celltype --gene_name_column index_column \
175
+ --val_ratio 0.1 \
176
+ --biomod_checkpoint weight/BioMod.pth --config_pkl weight/BioMod.pkl \
177
+ --biomod_data_dir model_dependencies/biomod_data_all \
178
+ --gene_list_path model_dependencies/selected_genes_27k.txt \
179
+ --gene2ens_file model_dependencies/gene2ens.csv --gene_mapping_path model_dependencies/gene2ens.csv \
180
+ --gene2vec_data_path model_dependencies/selected_gene2vec_27k.npy \
181
+ --head_type attn_pool --finetune_mode full --cls_decoder_layers 3 \
182
+ --dropout 0.2 --label_smoothing 0 \
183
+ --lr_head 1e-4 --lr_backbone 1e-4 --weight_decay 0.01 \
184
+ --min_genes 0 --min_cells 0 \
185
+ --batch_size 32 --epochs 50 --patience 10 --seed 0 \
186
+ --save_test_artifacts --output_dir tutorial_runs/cell_annotation_ms --run_name seed0
187
+ ```
188
+
189
+ ### 5. hPancreas
190
+
191
+ The 10,600-cell training file declares 14 categorical labels and contains cells
192
+ from 13 of them. `MHC class II` is already declared in its `Celltype` categories
193
+ with a training count of **0**; the 4,218-cell test file contains **5** such cells.
194
+ The entry point preserves the predefined training categories when constructing
195
+ the classifier and label encoder, including categories with zero training cells.
196
+ It does not create cells, add test cells to training, or infer the class list from
197
+ the test labels. Stratification still operates only on the observed training
198
+ cells. Keeping the output category does not supply positive training examples
199
+ for it.
200
+
201
+ Both files use `Celltype` and gene symbols in `var.index`. This annotation
202
+ benchmark is distinct from the 16,382-cell hPNC integration dataset.
203
+
204
+ ```bash
205
+ python BioMod/cell_annotation/train.py \
206
+ --train_data_path data/downstream/final_data/hp14/demo_train_with_MHC_class_II.h5ad \
207
+ --test_data_path data/downstream/final_data/hp14/demo_test.h5ad \
208
+ --label_column Celltype --test_label_column Celltype --gene_name_column index \
209
+ --val_ratio 0.1 \
210
+ --biomod_checkpoint weight/BioMod.pth --config_pkl weight/BioMod.pkl \
211
+ --biomod_data_dir model_dependencies/biomod_data_all \
212
+ --gene_list_path model_dependencies/selected_genes_27k.txt \
213
+ --gene2ens_file model_dependencies/gene2ens.csv --gene_mapping_path model_dependencies/gene2ens.csv \
214
+ --gene2vec_data_path model_dependencies/selected_gene2vec_27k.npy \
215
+ --head_type attn_pool --finetune_mode full --cls_decoder_layers 3 \
216
+ --dropout 0.2 --label_smoothing 0 \
217
+ --lr_head 1e-4 --lr_backbone 1e-4 --weight_decay 0.01 \
218
+ --min_genes 0 --min_cells 0 \
219
+ --batch_size 32 --epochs 50 --patience 10 --seed 0 \
220
+ --save_test_artifacts --output_dir tutorial_runs/cell_annotation_hpancreas --run_name seed0
221
+ ```
222
+
223
+ ### 6. Zheng68K
224
+
225
+ Use the 68,450-cell matrix and its 11 `celltype` classes. Gene symbols are stored
226
+ in `var.index`. The 20% test split contains 13,690 cells, matching the test-set
227
+ size reported in the manuscript; exact cell identities still depend on the seed
228
+ and input ordering.
229
+
230
+ ```bash
231
+ python BioMod/cell_annotation/train.py \
232
+ --data_path data/downstream/final_data/Zheng68K.h5ad \
233
+ --label_column celltype --gene_name_column index \
234
+ --val_ratio 0.1 --test_ratio 0.2 \
235
+ --biomod_checkpoint weight/BioMod.pth --config_pkl weight/BioMod.pkl \
236
+ --biomod_data_dir model_dependencies/biomod_data_all \
237
+ --gene_list_path model_dependencies/selected_genes_27k.txt \
238
+ --gene2ens_file model_dependencies/gene2ens.csv --gene_mapping_path model_dependencies/gene2ens.csv \
239
+ --gene2vec_data_path model_dependencies/selected_gene2vec_27k.npy \
240
+ --head_type attn_pool --finetune_mode full --cls_decoder_layers 3 \
241
+ --dropout 0.2 --label_smoothing 0 \
242
+ --lr_head 1e-4 --lr_backbone 1e-4 --weight_decay 0.01 \
243
+ --min_genes 0 --min_cells 0 \
244
+ --batch_size 32 --epochs 50 --patience 10 --seed 0 \
245
+ --save_test_artifacts --output_dir tutorial_runs/cell_annotation_zheng68k --run_name seed0
246
+ ```
247
+
248
+ ### 7. Myeloid
249
+
250
+ Use the 9,748-cell reference file for training/validation and retain the
251
+ 3,430-cell query file as the external test set. The reference contains 21
252
+ observed labels and the query contains 11; every query label occurs in the
253
+ reference. Both files use `cell_type` and gene symbols in `var.index`.
254
+
255
+ ```bash
256
+ python BioMod/cell_annotation/train.py \
257
+ --train_data_path data/downstream/final_data/Myeloid/reference_adata.h5ad \
258
+ --test_data_path data/downstream/final_data/Myeloid/query_adata.h5ad \
259
+ --label_column cell_type --test_label_column cell_type --gene_name_column index \
260
+ --val_ratio 0.1 \
261
+ --biomod_checkpoint weight/BioMod.pth --config_pkl weight/BioMod.pkl \
262
+ --biomod_data_dir model_dependencies/biomod_data_all \
263
+ --gene_list_path model_dependencies/selected_genes_27k.txt \
264
+ --gene2ens_file model_dependencies/gene2ens.csv --gene_mapping_path model_dependencies/gene2ens.csv \
265
+ --gene2vec_data_path model_dependencies/selected_gene2vec_27k.npy \
266
+ --head_type attn_pool --finetune_mode full --cls_decoder_layers 3 \
267
+ --dropout 0.2 --label_smoothing 0 \
268
+ --lr_head 1e-4 --lr_backbone 1e-4 --weight_decay 0.01 \
269
+ --min_genes 0 --min_cells 0 \
270
+ --batch_size 32 --epochs 50 --patience 10 --seed 0 \
271
+ --save_test_artifacts --output_dir tutorial_runs/cell_annotation_myeloid --run_name seed0
272
+ ```
273
+
274
+ ## Related Datasets
275
+
276
+ `BMMC_processed.h5ad`, `human_pancreas_norm_complexBatch_with_gene_name.h5ad`,
277
+ and the lung file without malignant cells belong to the documented
278
+ [zero-shot integration conditions](../zero_shot_batch/README.md#dataset-commands).
279
+ `norman/perturb_processed.h5ad` belongs to
280
+ [gene perturbation prediction](../gene_perturbation/README.md).
281
+ Their presence in the data directory does not add annotation benchmarks to the
282
+ seven listed above.
BioMod/cell_annotation/cmd_finetune.md DELETED
@@ -1,21 +0,0 @@
1
- # Cell annotation command
2
-
3
- Run this command from the repository root in a CUDA/NCCL environment. Resource defaults resolve from the script location; explicit relative paths resolve from the working directory.
4
-
5
- ```bash
6
- torchrun --nproc_per_node=4 BioMod/cell_annotation/biomod_finetune.py \
7
- --config_pkl weight/BioMod.pkl \
8
- --biomod_checkpoint weight/BioMod.pth \
9
- --data_path data/downstream/final_data/Zheng68K.h5ad \
10
- --label_column celltype \
11
- --head_type attn_pool \
12
- --finetune_mode last_n \
13
- --unfreeze_last_n 1 \
14
- --cls_decoder_layers 3 \
15
- --lr_head 1e-4 \
16
- --lr_backbone 1e-5 \
17
- --batch_size 256 \
18
- --epochs 300 \
19
- --biomod_data_dir model_dependencies/biomod_data_all \
20
- --output_dir tutorial_runs/cell_annotation_zheng68k
21
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
BioMod/cell_annotation/{biomod_finetune.py β†’ train.py} RENAMED
@@ -244,9 +244,16 @@ def preprocess_adata(
244
  max_cells: Optional[int] = None,
245
  dataset_name: str = "dataset",
246
  gene_name_column: Optional[str] = None,
 
247
  ) -> Tuple[ad.AnnData, dict]:
248
  logger.info("Loading data from %s", adata_path)
249
  adata = ad.read_h5ad(adata_path)
 
 
 
 
 
 
250
  matrix = adata.X
251
 
252
  if sparse.issparse(matrix):
@@ -266,6 +273,10 @@ def preprocess_adata(
266
  chosen = np.sort(rng.choice(adata.n_obs, size=max_cells, replace=False))
267
  adata = adata[chosen].copy()
268
 
 
 
 
 
269
  reindex_state = self._build_reindex_state(
270
  adata,
271
  dataset_name=dataset_name,
@@ -869,6 +880,15 @@ def load_backbone(args, device: torch.device) -> Tuple["BioMod", List[List[int]]
869
  return backbone, biomod_data, model_config
870
 
871
 
 
 
 
 
 
 
 
 
 
872
  def stratified_split(
873
  labels: np.ndarray,
874
  seed: int,
@@ -1247,6 +1267,7 @@ def main():
1247
  max_cells=args.max_cells,
1248
  dataset_name="train",
1249
  gene_name_column=args.gene_name_column,
 
1250
  )
1251
  test_adata, test_reindex_state = preprocessor.preprocess_adata(
1252
  str(resolve_path(args.test_data_path)),
@@ -1255,20 +1276,23 @@ def main():
1255
  max_cells=None,
1256
  dataset_name="test",
1257
  gene_name_column=args.gene_name_column,
 
1258
  )
1259
 
1260
  train_label_column = args.label_column
1261
  test_label_column = args.test_label_column or args.label_column
1262
- label_encoder = LabelEncoder()
1263
  train_labels_raw = train_adata.obs[train_label_column].astype(str).to_numpy()
1264
- label_encoder.fit(train_labels_raw)
1265
  labels_train = label_encoder.transform(train_labels_raw)
 
 
 
1266
 
1267
  test_labels_raw = test_adata.obs[test_label_column].astype(str).to_numpy()
1268
  unseen_test_labels = sorted(set(test_labels_raw) - set(label_encoder.classes_))
1269
  if unseen_test_labels:
1270
  raise ValueError(
1271
- "External test set contains labels unseen in training data: "
1272
  + ", ".join(unseen_test_labels[:10])
1273
  )
1274
  labels_test = label_encoder.transform(test_labels_raw)
@@ -1304,10 +1328,11 @@ def main():
1304
  max_cells=args.max_cells,
1305
  dataset_name="data",
1306
  gene_name_column=args.gene_name_column,
 
1307
  )
1308
 
1309
- label_encoder = LabelEncoder()
1310
- labels = label_encoder.fit_transform(adata.obs[args.label_column].astype(str).to_numpy())
1311
  num_classes = len(label_encoder.classes_)
1312
  train_idx, val_idx, test_idx = stratified_split(
1313
  labels=labels,
@@ -1547,8 +1572,10 @@ def main():
1547
  report = classification_report(
1548
  test_metrics["labels"],
1549
  test_metrics["preds"],
 
1550
  target_names=label_encoder.classes_.tolist(),
1551
  digits=4,
 
1552
  )
1553
  conf, conf_norm, conf_df, conf_norm_df = build_confusion_tables(
1554
  test_metrics["labels"],
 
244
  max_cells: Optional[int] = None,
245
  dataset_name: str = "dataset",
246
  gene_name_column: Optional[str] = None,
247
+ label_column: Optional[str] = None,
248
  ) -> Tuple[ad.AnnData, dict]:
249
  logger.info("Loading data from %s", adata_path)
250
  adata = ad.read_h5ad(adata_path)
251
+ label_dtype = None
252
+ if label_column is not None:
253
+ if label_column not in adata.obs:
254
+ raise ValueError(f"[{dataset_name}] Missing label column: {label_column}")
255
+ if isinstance(adata.obs[label_column].dtype, pd.CategoricalDtype):
256
+ label_dtype = adata.obs[label_column].dtype
257
  matrix = adata.X
258
 
259
  if sparse.issparse(matrix):
 
273
  chosen = np.sort(rng.choice(adata.n_obs, size=max_cells, replace=False))
274
  adata = adata[chosen].copy()
275
 
276
+ # AnnData slicing can drop declared classes with no remaining cells.
277
+ if label_dtype is not None:
278
+ adata.obs[label_column] = adata.obs[label_column].astype(label_dtype)
279
+
280
  reindex_state = self._build_reindex_state(
281
  adata,
282
  dataset_name=dataset_name,
 
880
  return backbone, biomod_data, model_config
881
 
882
 
883
+ def fit_label_encoder(labels: pd.Series) -> LabelEncoder:
884
+ """Keep declared training classes even when their observed count is zero."""
885
+ values = labels.astype(str).to_numpy()
886
+ if isinstance(labels.dtype, pd.CategoricalDtype):
887
+ declared = labels.cat.categories.astype(str).to_numpy()
888
+ values = np.concatenate([values, declared])
889
+ return LabelEncoder().fit(values)
890
+
891
+
892
  def stratified_split(
893
  labels: np.ndarray,
894
  seed: int,
 
1267
  max_cells=args.max_cells,
1268
  dataset_name="train",
1269
  gene_name_column=args.gene_name_column,
1270
+ label_column=args.label_column,
1271
  )
1272
  test_adata, test_reindex_state = preprocessor.preprocess_adata(
1273
  str(resolve_path(args.test_data_path)),
 
1276
  max_cells=None,
1277
  dataset_name="test",
1278
  gene_name_column=args.gene_name_column,
1279
+ label_column=args.test_label_column or args.label_column,
1280
  )
1281
 
1282
  train_label_column = args.label_column
1283
  test_label_column = args.test_label_column or args.label_column
1284
+ label_encoder = fit_label_encoder(train_adata.obs[train_label_column])
1285
  train_labels_raw = train_adata.obs[train_label_column].astype(str).to_numpy()
 
1286
  labels_train = label_encoder.transform(train_labels_raw)
1287
+ zero_count_classes = sorted(set(label_encoder.classes_) - set(train_labels_raw))
1288
+ if zero_count_classes:
1289
+ logger.info("Declared classes with zero training-file cells: %s", zero_count_classes)
1290
 
1291
  test_labels_raw = test_adata.obs[test_label_column].astype(str).to_numpy()
1292
  unseen_test_labels = sorted(set(test_labels_raw) - set(label_encoder.classes_))
1293
  if unseen_test_labels:
1294
  raise ValueError(
1295
+ "External test set contains labels not declared or observed in training data: "
1296
  + ", ".join(unseen_test_labels[:10])
1297
  )
1298
  labels_test = label_encoder.transform(test_labels_raw)
 
1328
  max_cells=args.max_cells,
1329
  dataset_name="data",
1330
  gene_name_column=args.gene_name_column,
1331
+ label_column=args.label_column,
1332
  )
1333
 
1334
+ label_encoder = fit_label_encoder(adata.obs[args.label_column])
1335
+ labels = label_encoder.transform(adata.obs[args.label_column].astype(str).to_numpy())
1336
  num_classes = len(label_encoder.classes_)
1337
  train_idx, val_idx, test_idx = stratified_split(
1338
  labels=labels,
 
1572
  report = classification_report(
1573
  test_metrics["labels"],
1574
  test_metrics["preds"],
1575
+ labels=np.arange(num_classes),
1576
  target_names=label_encoder.classes_.tolist(),
1577
  digits=4,
1578
+ zero_division=0,
1579
  )
1580
  conf, conf_norm, conf_df, conf_norm_df = build_confusion_tables(
1581
  test_metrics["labels"],
BioMod/{toturials/cell_annotation.ipynb β†’ cell_annotation/tutorial.ipynb} RENAMED
@@ -15,7 +15,7 @@
15
  "source": [
16
  "## Project paths\n",
17
  "\n",
18
- "Start Jupyter from `BioMod/toturials/`. The setup cell uses `Path(\"../..\").resolve()` to select the repository root, following the project-relative path convention used in scGPT tutorials. All code, data, model weight, and output paths are derived from this root and resolved to absolute paths for the training command. If Jupyter starts at the repository root, change that line to `Path(\".\").resolve()`. For another launch location, set `PROJECT_ROOT` to the checkout root."
19
  ]
20
  },
21
  {
@@ -24,7 +24,7 @@
24
  "source": [
25
  "## Inputs and workflow\n",
26
  "\n",
27
- "- Entry point: `BioMod/cell_annotation/biomod_finetune.py`.\n",
28
  "- Dataset: `data/downstream/final_data/Zheng68K.h5ad`.\n",
29
  "- Model weights and matching configuration: the `.pth` / `.pkl` pair under `weight/`.\n",
30
  "- Gene vocabulary, mapping, embeddings, and module definitions: `model_dependencies/`.\n",
@@ -56,7 +56,7 @@
56
  "PROJECT_ROOT = Path('../..').resolve()\n",
57
  "if not (PROJECT_ROOT / 'BioMod' / 'models_biomod.py').is_file() or not (PROJECT_ROOT / 'model_dependencies').is_dir():\n",
58
  " raise FileNotFoundError(\n",
59
- " 'Project root not found. Start Jupyter from BioMod/toturials, or set '\n",
60
  " 'PROJECT_ROOT to your repository root (use Path(\".\").resolve() if '\n",
61
  " 'Jupyter was started at the repository root).'\n",
62
  " )\n",
@@ -64,7 +64,7 @@
64
  "\n",
65
  "SOURCE_DIR = PROJECT_ROOT / 'BioMod'\n",
66
  "ASSET_ROOT = PROJECT_ROOT / 'model_dependencies'\n",
67
- "SCRIPT = SOURCE_DIR / 'cell_annotation' / 'biomod_finetune.py'\n",
68
  "DATA_PATH = PROJECT_ROOT / 'data' / 'downstream' / 'final_data' / 'Zheng68K.h5ad'\n",
69
  "\n",
70
  "# Keep the BioMod model weights and their matching configuration together.\n",
 
15
  "source": [
16
  "## Project paths\n",
17
  "\n",
18
+ "Start Jupyter from `BioMod/cell_annotation/`. The setup cell uses `Path(\"../..\").resolve()` to select the repository root, following the project-relative path convention used in scGPT tutorials. All code, data, model weight, and output paths are derived from this root and resolved to absolute paths for the training command. If Jupyter starts at the repository root, change that line to `Path(\".\").resolve()`. For another launch location, set `PROJECT_ROOT` to the checkout root."
19
  ]
20
  },
21
  {
 
24
  "source": [
25
  "## Inputs and workflow\n",
26
  "\n",
27
+ "- Entry point: `BioMod/cell_annotation/train.py`.\n",
28
  "- Dataset: `data/downstream/final_data/Zheng68K.h5ad`.\n",
29
  "- Model weights and matching configuration: the `.pth` / `.pkl` pair under `weight/`.\n",
30
  "- Gene vocabulary, mapping, embeddings, and module definitions: `model_dependencies/`.\n",
 
56
  "PROJECT_ROOT = Path('../..').resolve()\n",
57
  "if not (PROJECT_ROOT / 'BioMod' / 'models_biomod.py').is_file() or not (PROJECT_ROOT / 'model_dependencies').is_dir():\n",
58
  " raise FileNotFoundError(\n",
59
+ " 'Project root not found. Start Jupyter from BioMod/cell_annotation, or set '\n",
60
  " 'PROJECT_ROOT to your repository root (use Path(\".\").resolve() if '\n",
61
  " 'Jupyter was started at the repository root).'\n",
62
  " )\n",
 
64
  "\n",
65
  "SOURCE_DIR = PROJECT_ROOT / 'BioMod'\n",
66
  "ASSET_ROOT = PROJECT_ROOT / 'model_dependencies'\n",
67
+ "SCRIPT = SOURCE_DIR / 'cell_annotation' / 'train.py'\n",
68
  "DATA_PATH = PROJECT_ROOT / 'data' / 'downstream' / 'final_data' / 'Zheng68K.h5ad'\n",
69
  "\n",
70
  "# Keep the BioMod model weights and their matching configuration together.\n",
BioMod/drug_combination/README.md CHANGED
@@ -8,32 +8,48 @@ It is adapted from scLong's drug-combination implementation
8
  (DeepDDs), replacing the scfm/geneformer cell-line representation with
9
  BioMod.
10
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  ## Model Architecture
12
 
13
  | Component | Description |
14
  | --- | --- |
15
  | Drug branch | Three PyG GCNConv layers (78 -> 78 -> 156 -> 312), `global_max_pool`, and two fully connected layers to 128 dimensions |
16
- | Cell branch | Pretrained BioMod encoder, module mean pooling, and an MLP to 128 dimensions |
17
  | Fusion layer | `concat(drug1, drug2, cell) = 384 -> MLP -> 2-class prediction` |
18
 
19
  The drug1 and drug2 branches share weights, matching scLong.
20
 
21
- ## Data
22
 
23
- The bundled data are under `data/downstream/final_data/drug_combination_synergy/data_summary/`:
 
24
 
25
- ```text
26
- data_summary/
27
- |-- new_labels_0_10.csv # Training labels (drug1, drug2, cell, label)
28
- |-- new_cell_features_954.csv # Training cell features (30 cell lines x 954 genes)
29
- |-- smiles_0_10.csv # Drug SMILES
30
- `-- test_data/
31
- |-- independent_input.csv # Validation labels (668 samples)
32
- `-- independent_cell_features_954.csv # Validation cell features (1020 cell lines x 954 genes)
33
- ```
34
 
35
- The directory name `test_data/` is retained for compatibility. These files are
36
- used as the validation set for checkpoint selection.
 
 
 
 
 
 
37
 
38
  ## Dependencies
39
 
@@ -44,66 +60,75 @@ used as the validation set for checkpoint selection.
44
  - scikit-learn
45
  - pandas, numpy
46
 
47
- ## Usage
48
-
49
- Run all commands below from the repository root. Built-in resource defaults resolve from the script location. Explicit relative paths resolve from the working directory.
50
-
51
- ```bash
52
- pip install RDKit -i https://pypi.tuna.tsinghua.edu.cn/simple
53
- ```
54
-
55
- ### Basic Run (Domain Generalization Mode, Default)
56
-
57
- ```bash
58
- python BioMod/drug_combination/train_drug_combination_biomod.py \
59
- --checkpoint_path weight/BioMod.pth \
60
- --hyper_params_path weight/BioMod.pkl \
61
- --biomod_data_dir model_dependencies/biomod_data_all \
62
- --data_dir data/downstream/final_data/drug_combination_synergy/data_summary
63
- ```
64
 
65
- ### Custom Paths
 
 
 
 
 
 
66
 
67
  ```bash
68
- python BioMod/drug_combination/train_drug_combination_biomod.py \
 
 
 
 
 
69
  --checkpoint_path weight/BioMod.pth \
70
  --hyper_params_path weight/BioMod.pkl \
71
  --biomod_data_dir model_dependencies/biomod_data_all \
72
- --gene_list_path model_dependencies/selected_genes_27k.txt\
73
- --gene_mapping_path model_dependencies/gene2ens.csv \
74
- --gene2vec_path model_dependencies/selected_gene2vec_27k.npy \
75
- --symbol2ens_path model_dependencies/gene2ens.csv \
76
- --data_dir data/downstream/final_data/drug_combination_synergy/data_summary \
77
- --output_dir tutorial_runs/drug_combination \
78
  --epochs 500 \
79
  --batch_size 256 \
80
- --lr 1e-4 \
81
- --n_folds 1 \
82
- --pool_method max
83
  ```
84
 
85
- Reference note: `1e-4 500 0.6824301861702127`.
 
 
 
 
 
86
 
87
- ### Five-Fold Cross-Validation (Disable Domain Generalization)
 
 
88
 
89
- ```bash
90
- python BioMod/drug_combination/train_drug_combination_biomod.py \
91
- --checkpoint_path weight/BioMod.pth \
92
- --hyper_params_path weight/BioMod.pkl \
93
- --biomod_data_dir model_dependencies/biomod_data_all \
94
- --no_domain_gen
95
- ```
96
 
97
- ### Force Reprocessing After Changing the Model or Data
 
 
98
 
99
  ```bash
100
- python BioMod/drug_combination/train_drug_combination_biomod.py \
 
101
  --checkpoint_path weight/BioMod.pth \
102
  --hyper_params_path weight/BioMod.pkl \
103
  --biomod_data_dir model_dependencies/biomod_data_all \
104
- --force_preprocess
 
 
 
 
 
105
  ```
106
 
 
 
 
 
 
 
 
 
 
 
 
107
  ## Main Arguments
108
 
109
  | Argument | Default | Description |
 
8
  (DeepDDs), replacing the scfm/geneformer cell-line representation with
9
  BioMod.
10
 
11
+ ## Notebook
12
+
13
+ See the [task notebook](tutorial.ipynb) for a step-by-step workflow.
14
+
15
+ ## Files
16
+
17
+ | File or directory | Purpose |
18
+ | --- | --- |
19
+ | [README.md](README.md) | File guide, model and data descriptions, training commands, and evaluation details. |
20
+ | [tutorial.ipynb](tutorial.ipynb) | Task configuration, execution, and result review in a Jupyter notebook. |
21
+ | [train.py](train.py) | Train and validate drug-combination synergy prediction with drug graph encoders and BioMod cell embeddings. |
22
+
23
  ## Model Architecture
24
 
25
  | Component | Description |
26
  | --- | --- |
27
  | Drug branch | Three PyG GCNConv layers (78 -> 78 -> 156 -> 312), `global_max_pool`, and two fully connected layers to 128 dimensions |
28
+ | Cell branch | Pretrained BioMod encoder, configurable pooling, and an MLP to 128 dimensions |
29
  | Fusion layer | `concat(drug1, drug2, cell) = 384 -> MLP -> 2-class prediction` |
30
 
31
  The drug1 and drug2 branches share weights, matching scLong.
32
 
33
+ ## Bundled dataset
34
 
35
+ The current entry point uses one collection with separate training and validation
36
+ inputs under `data/downstream/final_data/drug_combination_synergy/data_summary/`.
37
 
38
+ | Input below `data_summary/` | Purpose |
39
+ | --- | --- |
40
+ | `new_labels_0_10.csv` | 12,415 training records with `drug1`, `drug2`, `cell`, and `label` columns. |
41
+ | `new_cell_features_954.csv` | Training expression; the loader removes the transcript-ID row and obtains 31 cell rows by 954 genes. |
42
+ | `test_data/independent_input.csv` | 668 validation records used for checkpoint selection. |
43
+ | `test_data/independent_cell_features_954.csv` | Validation expression; the loader removes the transcript-ID row and obtains 1,019 cell rows by 954 genes. |
 
 
 
44
 
45
+ The directory name `test_data/` is retained for compatibility. The current script
46
+ uses these files as validation inputs. Drug molecular graphs are constructed from
47
+ the SMILES strings already stored in the label tables' `drug1` and `drug2` columns.
48
+ `smiles_0_10.csv` and the other source tables are retained for reference and are not
49
+ additional required inputs to this entry point.
50
+
51
+ The older `data/downstream/final_data/drug_response_pytorch/drug_combination/`
52
+ package is a reference copy, not another dataset for this task.
53
 
54
  ## Dependencies
55
 
 
60
  - scikit-learn
61
  - pandas, numpy
62
 
63
+ ## Run the bundled training and validation collection
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
+ Activate the environment described in the [project README](../../README.md), then
66
+ run these commands in Bash from the outer repository root containing `BioMod/`,
67
+ `data/`, `model_dependencies/`, and `weight/`. The backslashes continue commands
68
+ across lines in Bash; they are not PowerShell continuation characters. Use a
69
+ Linux or WSL Bash shell with the required environment. Built-in resource defaults
70
+ resolve from the script location; explicit relative paths resolve from the
71
+ working directory.
72
 
73
  ```bash
74
+ python BioMod/drug_combination/train.py \
75
+ --data_dir data/downstream/final_data/drug_combination_synergy/data_summary \
76
+ --label_file new_labels_0_10.csv \
77
+ --cell_file new_cell_features_954.csv \
78
+ --validation_label_file test_data/independent_input.csv \
79
+ --validation_cell_file test_data/independent_cell_features_954.csv \
80
  --checkpoint_path weight/BioMod.pth \
81
  --hyper_params_path weight/BioMod.pkl \
82
  --biomod_data_dir model_dependencies/biomod_data_all \
83
+ --n_folds 1 \
 
 
 
 
 
84
  --epochs 500 \
85
  --batch_size 256 \
86
+ --pool_method max \
87
+ --output_dir tutorial_runs/drug_combination_synergy
 
88
  ```
89
 
90
+ These are example settings for the bundled inputs, not a verified reproduction
91
+ of manuscript results. The default domain-generalization mode trains on the full
92
+ training collection and selects a checkpoint using the separate validation
93
+ collection. `--n_folds 1` requests one run; leaving its default of 5 in this mode
94
+ repeats full-training/full-validation runs rather than performing five-fold
95
+ cross-validation.
96
 
97
+ The manuscript describes the 668-sample collection as an independent test set.
98
+ The current code uses it for checkpoint selection, so its reported AUROC is a
99
+ validation result and must not be presented as an independent final test estimate.
100
 
101
+ ### Optional five-fold cross-validation on the same collection
 
 
 
 
 
 
102
 
103
+ This is an alternative validation protocol, not a second dataset. The current
104
+ implementation still reads all four input tables before selecting the held-out
105
+ folds from the training collection.
106
 
107
  ```bash
108
+ python BioMod/drug_combination/train.py \
109
+ --data_dir data/downstream/final_data/drug_combination_synergy/data_summary \
110
  --checkpoint_path weight/BioMod.pth \
111
  --hyper_params_path weight/BioMod.pkl \
112
  --biomod_data_dir model_dependencies/biomod_data_all \
113
+ --no_domain_gen \
114
+ --n_folds 5 \
115
+ --epochs 500 \
116
+ --batch_size 256 \
117
+ --pool_method max \
118
+ --output_dir tutorial_runs/drug_combination_synergy_cv
119
  ```
120
 
121
+ ### Input and cache changes
122
+
123
+ Use `--gene_list_path`, `--gene_mapping_path`, `--gene2vec_path`, and
124
+ `--symbol2ens_path` only when replacing the bundled shared assets. After changing
125
+ model weights, pooling, or input tables, append `--force_preprocess` to regenerate
126
+ the embedding cache and the PyG datasets under `data_summary/processed/`; an
127
+ existing cache is not automatically keyed by all model and input settings.
128
+
129
+ The input files and command arguments have been checked. This documentation update
130
+ did not execute training or verify checkpoint performance.
131
+
132
  ## Main Arguments
133
 
134
  | Argument | Default | Description |
BioMod/drug_combination/{train_drug_combination_biomod.py β†’ train.py} RENAMED
@@ -10,7 +10,7 @@
10
 
11
  Usage:
12
  # Run from the repository root.
13
- python BioMod/drug_combination/train_drug_combination_biomod.py \
14
  --checkpoint_path <ckpt> --hyper_params_path <pkl> \
15
  --biomod_data_dir model_dependencies/biomod_data_all \
16
  --data_dir data/downstream/final_data/drug_combination_synergy/data_summary
 
10
 
11
  Usage:
12
  # Run from the repository root.
13
+ python BioMod/drug_combination/train.py \
14
  --checkpoint_path <ckpt> --hyper_params_path <pkl> \
15
  --biomod_data_dir model_dependencies/biomod_data_all \
16
  --data_dir data/downstream/final_data/drug_combination_synergy/data_summary
BioMod/{toturials/drug_combination.ipynb β†’ drug_combination/tutorial.ipynb} RENAMED
@@ -7,7 +7,7 @@
7
  "# Drug combination synergy prediction with BioMod\n",
8
  "\n",
9
  "This notebook checks the bundled drug-combination inputs, prepares a command for\n",
10
- "`BioMod/drug_combination/train_drug_combination_biomod.py`, and plots\n",
11
  "available training outputs. It uses the BioMod model weights and configuration.\n",
12
  "\n",
13
  "`RUN_TRAINING = False` by default. Set it to `True` only when you are ready to train\n",
@@ -21,7 +21,7 @@
21
  "source": [
22
  "## Project paths and dataset layout\n",
23
  "\n",
24
- "Start Jupyter from `BioMod/toturials/`. The path cell uses `Path('../..')` for the\n",
25
  "repository root and resolves project-relative paths for the training subprocess.\n",
26
  "If Jupyter starts at the repository root, use `Path('.')` instead. The dataset is\n",
27
  "already included in the project:\n",
@@ -65,13 +65,13 @@
65
  " def display(obj):\n",
66
  " print(obj)\n",
67
  "\n",
68
- "# Start Jupyter with BioMod/toturials as the working directory.\n",
69
  "# If Jupyter starts at the repository root, change this line to Path('.').resolve().\n",
70
  "PROJECT_ROOT = Path('../..').resolve()\n",
71
  "SOURCE_DIR = PROJECT_ROOT / 'BioMod'\n",
72
  "if not (SOURCE_DIR / 'models_biomod.py').is_file() or not (PROJECT_ROOT / 'model_dependencies').is_dir():\n",
73
  " raise FileNotFoundError(\n",
74
- " 'Start Jupyter from BioMod/toturials, or set PROJECT_ROOT to the repository root '\n",
75
  " \"(use Path('.').resolve() if Jupyter was launched at that root).\"\n",
76
  " )\n",
77
  "REPO_ROOT = PROJECT_ROOT\n",
@@ -86,7 +86,7 @@
86
  ")\n",
87
  "\n",
88
  "TASK_ROOT = SOURCE_DIR / 'drug_combination'\n",
89
- "TRAIN_SCRIPT = TASK_ROOT / 'train_drug_combination_biomod.py'\n",
90
  "CHECKPOINT_PATH = WEIGHT_DIR / 'BioMod.pth'\n",
91
  "HYPER_PARAMS_PATH = WEIGHT_DIR / 'BioMod.pkl'\n",
92
  "GENE_LIST_PATH = DEPENDENCY_ROOT / 'selected_genes_27k.txt'\n",
 
7
  "# Drug combination synergy prediction with BioMod\n",
8
  "\n",
9
  "This notebook checks the bundled drug-combination inputs, prepares a command for\n",
10
+ "`BioMod/drug_combination/train.py`, and plots\n",
11
  "available training outputs. It uses the BioMod model weights and configuration.\n",
12
  "\n",
13
  "`RUN_TRAINING = False` by default. Set it to `True` only when you are ready to train\n",
 
21
  "source": [
22
  "## Project paths and dataset layout\n",
23
  "\n",
24
+ "Start Jupyter from `BioMod/drug_combination/`. The path cell uses `Path('../..')` for the\n",
25
  "repository root and resolves project-relative paths for the training subprocess.\n",
26
  "If Jupyter starts at the repository root, use `Path('.')` instead. The dataset is\n",
27
  "already included in the project:\n",
 
65
  " def display(obj):\n",
66
  " print(obj)\n",
67
  "\n",
68
+ "# Start Jupyter with BioMod/drug_combination as the working directory.\n",
69
  "# If Jupyter starts at the repository root, change this line to Path('.').resolve().\n",
70
  "PROJECT_ROOT = Path('../..').resolve()\n",
71
  "SOURCE_DIR = PROJECT_ROOT / 'BioMod'\n",
72
  "if not (SOURCE_DIR / 'models_biomod.py').is_file() or not (PROJECT_ROOT / 'model_dependencies').is_dir():\n",
73
  " raise FileNotFoundError(\n",
74
+ " 'Start Jupyter from BioMod/drug_combination, or set PROJECT_ROOT to the repository root '\n",
75
  " \"(use Path('.').resolve() if Jupyter was launched at that root).\"\n",
76
  " )\n",
77
  "REPO_ROOT = PROJECT_ROOT\n",
 
86
  ")\n",
87
  "\n",
88
  "TASK_ROOT = SOURCE_DIR / 'drug_combination'\n",
89
+ "TRAIN_SCRIPT = TASK_ROOT / 'train.py'\n",
90
  "CHECKPOINT_PATH = WEIGHT_DIR / 'BioMod.pth'\n",
91
  "HYPER_PARAMS_PATH = WEIGHT_DIR / 'BioMod.pkl'\n",
92
  "GENE_LIST_PATH = DEPENDENCY_ROOT / 'selected_genes_27k.txt'\n",
BioMod/drug_response/README.md ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Drug Response Prediction with BioMod
2
+
3
+ Predict drug response from drug molecular graphs and BioMod cell embeddings.
4
+ The training script combines a graph-based drug encoder with the pretrained
5
+ BioMod backbone.
6
+
7
+ ## Notebook
8
+
9
+ See the [task notebook](tutorial.ipynb) for a step-by-step workflow.
10
+
11
+ ## Files
12
+
13
+ | File or directory | Purpose |
14
+ | --- | --- |
15
+ | [README.md](README.md) | File guide and command-line training example. |
16
+ | [tutorial.ipynb](tutorial.ipynb) | Task configuration, execution, and result review in a Jupyter notebook. |
17
+ | [train.py](train.py) | Load drug-response data, build the model, train, and evaluate validation metrics. |
18
+
19
+ ## Bundled dataset
20
+
21
+ The current entry point uses one joint GDSC-CCLE collection. GDSC supplies drug
22
+ information and responses; CCLE supplies cell-line annotations and expression.
23
+ They are complementary inputs to one run, rather than separate training datasets.
24
+ Use the cleaned collection under
25
+ `data/downstream/final_data/single_drug_response/data/`.
26
+
27
+ | Input below the data directory | Purpose |
28
+ | --- | --- |
29
+ | `GDSC/1.Drug_listMon Jun 24 09_00_55 2019.csv` | Map drug IDs to PubChem IDs. |
30
+ | `GDSC/drug_graph_feat/*.hkl` | Precomputed molecular graphs; 223 files are bundled. |
31
+ | `CCLE/Cell_lines_annotations_20181226.txt` | Map cell-line IDs to cancer types. |
32
+ | `CCLE/genomic_expression_561celllines_697genes_demap_features.csv` | Expression for 561 cell lines and 697 genes. |
33
+ | `CCLE/GDSC_IC50.csv` | Drug-response matrix used to construct matched response records. |
34
+
35
+ The older `data/downstream/final_data/drug_response_pytorch/` package is retained
36
+ for reference. It is not an additional dataset for this task. Files under
37
+ `single_drug_response/optional_reference/` are not consumed by this entry point.
38
+
39
+ ## Run the bundled GDSC-CCLE collection
40
+
41
+ Activate the environment described in the [project README](../../README.md), then
42
+ run these commands in Bash from the outer repository root containing `BioMod/`,
43
+ `data/`, `model_dependencies/`, and `weight/`. The backslashes continue commands
44
+ across lines in Bash; they are not PowerShell continuation characters. Use a
45
+ Linux or WSL Bash shell with the required environment. Built-in resource defaults
46
+ resolve from the script location; explicit relative paths resolve from the
47
+ working directory.
48
+
49
+ ```bash
50
+ python BioMod/drug_response/train.py \
51
+ --gpu_id 0 \
52
+ --data_path data/downstream/final_data/single_drug_response/data \
53
+ --checkpoint_path weight/BioMod.pth \
54
+ --hyper_params_path weight/BioMod.pkl \
55
+ --biomod_data_dir model_dependencies/biomod_data_all \
56
+ --epochs 300 \
57
+ --batch_size 32 \
58
+ --pool_method max \
59
+ --save_dir tutorial_runs/drug_response_gdsc_ccle
60
+ ```
61
+
62
+ This is a command for the bundled inputs, with example training settings. It has
63
+ not been validated as a reproduction of the manuscript results. The current code
64
+ uses a fixed seed of 0 and splits matched records by cancer type into approximately
65
+ 95% training and 5% validation. Validation Pearson correlation determines the best
66
+ checkpoint. It does not create a separate final test set, and it does not implement
67
+ the manuscript's 70%/10%/20% train/validation/test protocol.
68
+
69
+ The data and asset paths have been checked for existence. A complete training run
70
+ and checkpoint performance have not been verified by this documentation update.
BioMod/drug_response/cmd.txt DELETED
@@ -1,10 +0,0 @@
1
- # Run from the repository root.
2
- python BioMod/drug_response/train_drug_biomod.py \
3
- --gpu_id 0 \
4
- --data_path data/downstream/final_data/single_drug_response/data \
5
- --checkpoint_path weight/BioMod.pth \
6
- --hyper_params_path weight/BioMod.pkl \
7
- --epochs 300 \
8
- --biomod_data_dir model_dependencies/biomod_data_all \
9
- --save_dir tutorial_runs/drug_response \
10
- --pool_method max
 
 
 
 
 
 
 
 
 
 
 
BioMod/drug_response/{train_drug_biomod.py β†’ train.py} RENAMED
@@ -10,8 +10,8 @@
10
  - Optimization strategy: AdamW + cosine annealing + early stopping
11
 
12
  How to use:
13
- # Run from the repository root; see drug_response/cmd.txt for a full example.
14
- python BioMod/drug_response/train_drug_biomod.py \
15
  --gpu_id 0 --epochs 300 \
16
  --checkpoint_path weight/BioMod.pth \
17
  --hyper_params_path weight/BioMod.pkl
 
10
  - Optimization strategy: AdamW + cosine annealing + early stopping
11
 
12
  How to use:
13
+ # Run from the repository root; see drug_response/README.md for a full example.
14
+ python BioMod/drug_response/train.py \
15
  --gpu_id 0 --epochs 300 \
16
  --checkpoint_path weight/BioMod.pth \
17
  --hyper_params_path weight/BioMod.pkl
BioMod/{toturials/drug_response_prediction.ipynb β†’ drug_response/tutorial.ipynb} RENAMED
@@ -7,7 +7,7 @@
7
  "# Drug response prediction with BioMod\n",
8
  "\n",
9
  "This notebook uses the BioMod model weights, drug graph features, and the bundled\n",
10
- "GDSC/CCLE response data with `train_drug_biomod.py`.\n",
11
  "\n",
12
  "By default, `RUN_TRAINING = False`: the notebook checks inputs and prepares the\n",
13
  "training command. Result and plotting cells run only when `predictions.npz`\n",
@@ -23,7 +23,7 @@
23
  "source": [
24
  "## Project paths\n",
25
  "\n",
26
- "Start Jupyter from `BioMod/toturials/`. The next cell uses `Path('../..')` for the\n",
27
  "repository root and resolves project-relative paths for the training subprocess.\n",
28
  "If Jupyter starts at the repository root, use `Path('.')` instead. All inputs come\n",
29
  "from this project; no private server alias or external reference run is required.\n"
@@ -35,7 +35,7 @@
35
  "source": [
36
  "## Inputs and outputs\n",
37
  "\n",
38
- "- Training script: `BioMod/drug_response/train_drug_biomod.py`\n",
39
  "- Dataset: `data/downstream/final_data/single_drug_response/data/`\n",
40
  "- BioMod model weights and configuration: `weight/`\n",
41
  "- Shared model assets: `model_dependencies/`\n",
@@ -72,13 +72,13 @@
72
  "\n",
73
  "from scipy.stats import pearsonr\n",
74
  "\n",
75
- "# Start Jupyter with BioMod/toturials as the working directory.\n",
76
  "# If Jupyter starts at the repository root, change this line to Path('.').resolve().\n",
77
  "PROJECT_ROOT = Path('../..').resolve()\n",
78
  "SOURCE_DIR = PROJECT_ROOT / 'BioMod'\n",
79
  "if not (SOURCE_DIR / 'models_biomod.py').is_file() or not (PROJECT_ROOT / 'model_dependencies').is_dir():\n",
80
  " raise FileNotFoundError(\n",
81
- " 'Start Jupyter from BioMod/toturials, or set PROJECT_ROOT to the repository root '\n",
82
  " \"(use Path('.').resolve() if Jupyter was launched at that root).\"\n",
83
  " )\n",
84
  "REPO_ROOT = PROJECT_ROOT\n",
@@ -93,7 +93,7 @@
93
  ")\n",
94
  "\n",
95
  "TASK_ROOT = SOURCE_DIR / 'drug_response'\n",
96
- "SCRIPT = TASK_ROOT / 'train_drug_biomod.py'\n",
97
  "DATA_ROOT = REPO_ROOT / 'data/downstream/final_data/single_drug_response/data'\n",
98
  "CKPT_PATH = WEIGHT_DIR / 'BioMod.pth'\n",
99
  "CONFIG_PKL = WEIGHT_DIR / 'BioMod.pkl'\n",
 
7
  "# Drug response prediction with BioMod\n",
8
  "\n",
9
  "This notebook uses the BioMod model weights, drug graph features, and the bundled\n",
10
+ "GDSC/CCLE response data with `train.py`.\n",
11
  "\n",
12
  "By default, `RUN_TRAINING = False`: the notebook checks inputs and prepares the\n",
13
  "training command. Result and plotting cells run only when `predictions.npz`\n",
 
23
  "source": [
24
  "## Project paths\n",
25
  "\n",
26
+ "Start Jupyter from `BioMod/drug_response/`. The next cell uses `Path('../..')` for the\n",
27
  "repository root and resolves project-relative paths for the training subprocess.\n",
28
  "If Jupyter starts at the repository root, use `Path('.')` instead. All inputs come\n",
29
  "from this project; no private server alias or external reference run is required.\n"
 
35
  "source": [
36
  "## Inputs and outputs\n",
37
  "\n",
38
+ "- Training script: `BioMod/drug_response/train.py`\n",
39
  "- Dataset: `data/downstream/final_data/single_drug_response/data/`\n",
40
  "- BioMod model weights and configuration: `weight/`\n",
41
  "- Shared model assets: `model_dependencies/`\n",
 
72
  "\n",
73
  "from scipy.stats import pearsonr\n",
74
  "\n",
75
+ "# Start Jupyter with BioMod/drug_response as the working directory.\n",
76
  "# If Jupyter starts at the repository root, change this line to Path('.').resolve().\n",
77
  "PROJECT_ROOT = Path('../..').resolve()\n",
78
  "SOURCE_DIR = PROJECT_ROOT / 'BioMod'\n",
79
  "if not (SOURCE_DIR / 'models_biomod.py').is_file() or not (PROJECT_ROOT / 'model_dependencies').is_dir():\n",
80
  " raise FileNotFoundError(\n",
81
+ " 'Start Jupyter from BioMod/drug_response, or set PROJECT_ROOT to the repository root '\n",
82
  " \"(use Path('.').resolve() if Jupyter was launched at that root).\"\n",
83
  " )\n",
84
  "REPO_ROOT = PROJECT_ROOT\n",
 
93
  ")\n",
94
  "\n",
95
  "TASK_ROOT = SOURCE_DIR / 'drug_response'\n",
96
+ "SCRIPT = TASK_ROOT / 'train.py'\n",
97
  "DATA_ROOT = REPO_ROOT / 'data/downstream/final_data/single_drug_response/data'\n",
98
  "CKPT_PATH = WEIGHT_DIR / 'BioMod.pth'\n",
99
  "CONFIG_PKL = WEIGHT_DIR / 'BioMod.pkl'\n",
BioMod/gene_perturbation/README.md CHANGED
@@ -5,6 +5,27 @@ the `BioMod` encoder. The
5
  [BioMod model weights and matching configuration](../../README.md#biomod-model-weights)
6
  are shared with the other downstream tasks.
7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  ## Overview
9
 
10
  This adaptation replaces the original GEARS gene perturbation model based on
@@ -17,7 +38,7 @@ are:
17
 
18
  ## Main Adaptations
19
 
20
- ### 1. `SCFM_BioMod` (`model_biomod.py`)
21
 
22
  `SCFM_BioMod` wraps `BioMod` and provides these functions:
23
 
@@ -42,7 +63,7 @@ for gene_idx in range(len(self.scfm_index_positions) - 1):
42
  gene_emb = module_encodings.mean(dim=1) # B, D (global average)
43
  ```
44
 
45
- ### 2. `GEARS_Model_BioMod` (`model_biomod.py`)
46
 
47
  `GEARS_Model_BioMod` inherits the original GEARS architecture. Main changes:
48
 
@@ -50,7 +71,7 @@ for gene_idx in range(len(self.scfm_index_positions) - 1):
50
  - **Module data loading** supports loading module data from hyper-parameters or file paths.
51
  - **Other components remain unchanged**, including the GNN layers and decoder.
52
 
53
- ### 3. Training Script (`train_biomod.py`)
54
 
55
  The training script is based on `GEARS/train_dual_ddp_reduce_dec.py`. Main changes:
56
 
@@ -62,38 +83,80 @@ The training script is based on `GEARS/train_dual_ddp_reduce_dec.py`. Main chang
62
 
63
  ## Usage
64
 
65
- ### 1. Prepare Data
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
- Make sure the following files exist:
 
 
 
68
 
69
- - Perturbation data, such as Norman, Adamson, or Dixit.
70
- - BioMod model weights and their matching configuration file.
71
- - Module data in JSON format.
72
- - Gene mapping file, such as `gene2ens.csv`.
73
 
74
- ### 2. Run Training
75
 
76
- Run from the repository root in a Linux CUDA/NCCL environment. Built-in asset defaults are derived from the script location; explicit relative paths resolve from the working directory.
 
 
 
 
 
 
 
77
 
78
  ```bash
79
- # DDP training on multiple GPUs.
80
- python -m torch.distributed.run --standalone --nproc_per_node=4 \
81
- BioMod/gene_perturbation/train_biomod.py \
82
  --data_dir data/downstream/final_data \
83
  --data_name norman \
 
 
 
84
  --scfm_hyper_params_path weight/BioMod.pkl \
85
  --scfm_ckpt_path weight/BioMod.pth \
86
  --biomod_data_dir model_dependencies/biomod_data_all \
87
  --gene_mapping_path model_dependencies/gene2ens.csv \
88
  --scfm_genes_list_path model_dependencies/selected_genes_27k.txt \
89
  --scfm_gene2vec_file model_dependencies/selected_gene2vec_27k.npy \
90
- --result_dir tutorial_runs/gene_perturbation \
91
- --run_name norman_module_experiment \
 
92
  --epochs 20 \
93
  --batch_size 32 \
94
  --lr 1e-3
95
  ```
96
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  ### 3. Arguments
98
 
99
  **Model arguments** (defaults point to the bundled BioMod assets):
@@ -133,19 +196,11 @@ python -m torch.distributed.run --standalone --nproc_per_node=4 \
133
 
134
  To compare model performance:
135
 
136
- 1. **Run original sclong**:
 
137
 
138
- ```bash
139
- # Requires a separate checkout of the original scLong/GEARS code.
140
- python /path/to/upstream/GEARS/train_dual_ddp_reduce_dec.py [arguments...]
141
- ```
142
-
143
- 2. **Run the module version**:
144
-
145
- ```bash
146
- # Run from the BioMod repository root.
147
- python -m torch.distributed.run --standalone --nproc_per_node=1 BioMod/gene_perturbation/train_biomod.py [arguments...]
148
- ```
149
 
150
  3. **Compare metrics**:
151
 
@@ -189,16 +244,19 @@ This strategy:
189
  ## File Structure
190
 
191
  ```text
192
- BioMod/gene_perturbation/ # Perturbation response prediction: processing, training and inference
193
- β”œβ”€β”€ data_utils_local.py
194
- β”œβ”€β”€ gears_reduce_local.py
195
- β”œβ”€β”€ inference_local.py
196
- β”œβ”€β”€ model_biomod.py
197
- β”œβ”€β”€ pertdata_local.py
 
 
 
 
198
  β”œβ”€β”€ README.md
199
- β”œβ”€β”€ scfm_utils_local.py
200
- β”œβ”€β”€ train_biomod.py
201
- └── utils.py
202
  ```
203
 
204
  ## Notes
@@ -232,10 +290,9 @@ This implementation supports two feature extraction modes controlled by
232
 
233
  ### Method 1: Gene-Based (Default, Recommended)
234
 
235
- ```bash
236
- # Default mode; do not pass --use_biomod_level or set it to False.
237
- python -m torch.distributed.run --standalone --nproc_per_node=1 BioMod/gene_perturbation/train_biomod.py [other arguments...]
238
- ```
239
 
240
  **Characteristics**:
241
 
@@ -246,10 +303,10 @@ python -m torch.distributed.run --standalone --nproc_per_node=1 BioMod/gene_pert
246
 
247
  ### Method 2: Module-Based (Experimental, Not Fully Implemented)
248
 
249
- ```bash
250
- # Enable module-level mode.
251
- python -m torch.distributed.run --standalone --nproc_per_node=1 BioMod/gene_perturbation/train_biomod.py --use_biomod_level [other arguments...]
252
- ```
253
 
254
  **Characteristics**:
255
 
 
5
  [BioMod model weights and matching configuration](../../README.md#biomod-model-weights)
6
  are shared with the other downstream tasks.
7
 
8
+ ## Notebook
9
+
10
+ See the [task notebook](tutorial.ipynb) for a step-by-step workflow.
11
+
12
+ ## Files
13
+
14
+ | File or directory | Purpose |
15
+ | --- | --- |
16
+ | [README.md](README.md) | File guide, model details, training commands, and troubleshooting notes. |
17
+ | [tutorial.ipynb](tutorial.ipynb) | Task configuration, execution, and result review in a Jupyter notebook. |
18
+ | [train.py](train.py) | Configure and launch distributed gene perturbation training. |
19
+ | [components/](components/) | Model, data-processing, training, and evaluation helpers. |
20
+ | [components/model.py](components/model.py) | Define the BioMod-backed GEARS model and recover gene-level features. |
21
+ | [components/trainer.py](components/trainer.py) | Manage model training, checkpointing, and evaluation. |
22
+ | [components/dataset.py](components/dataset.py) | Prepare perturbation datasets, splits, and graph data loaders. |
23
+ | [components/data_utils.py](components/data_utils.py) | Compute differential-expression annotations and construct data splits. |
24
+ | [components/inference.py](components/inference.py) | Run inference and compute perturbation prediction metrics. |
25
+ | [components/training_utils.py](components/training_utils.py) | Provide distributed training, checkpoint, logging, and optimization helpers. |
26
+ | [components/utils.py](components/utils.py) | Provide perturbation parsing, gene-network, loss, and prediction utilities. |
27
+ | [components/__init__.py](components/__init__.py) | Mark the helper directory as a Python package. |
28
+
29
  ## Overview
30
 
31
  This adaptation replaces the original GEARS gene perturbation model based on
 
38
 
39
  ## Main Adaptations
40
 
41
+ ### 1. `SCFM_BioMod` (`components/model.py`)
42
 
43
  `SCFM_BioMod` wraps `BioMod` and provides these functions:
44
 
 
63
  gene_emb = module_encodings.mean(dim=1) # B, D (global average)
64
  ```
65
 
66
+ ### 2. `GEARS_Model_BioMod` (`components/model.py`)
67
 
68
  `GEARS_Model_BioMod` inherits the original GEARS architecture. Main changes:
69
 
 
71
  - **Module data loading** supports loading module data from hyper-parameters or file paths.
72
  - **Other components remain unchanged**, including the GNN layers and decoder.
73
 
74
+ ### 3. Training Script (`train.py`)
75
 
76
  The training script is based on `GEARS/train_dual_ddp_reduce_dec.py`. Main changes:
77
 
 
83
 
84
  ## Usage
85
 
86
+ ### 1. Bundled dataset: Norman
87
+
88
+ Norman is the only perturbation dataset currently bundled with this repository.
89
+ The following files are present under `data/downstream/final_data/norman/`:
90
+
91
+ | Input | Purpose |
92
+ | --- | --- |
93
+ | `perturb_processed.h5ad` | Processed expression and perturbation annotations. |
94
+ | `data_pyg/cell_graphs.pkl` | Prepared per-cell PyG graph cache. |
95
+ | `splits/norman_simulation_1_0.75.pkl` | Existing simulation split for seed 1 and training-gene fraction 0.75. |
96
+ | `splits/norman_simulation_1_0.75_subgroup.pkl` | Test-condition categories for that simulation split. |
97
+ | `go.csv` | Gene Ontology similarity graph. |
98
+ | `simulation_1_0.75_0.4_20_co_expression_network.csv` | Coexpression graph for the same split and default graph settings. |
99
 
100
+ These files were checked for existence without deserializing the graph cache,
101
+ split files, or model weights. The shared BioMod weights, configuration, module
102
+ JSON, gene list, gene2vec array, and gene-mapping CSV are also present at the paths
103
+ used below.
104
 
105
+ The loader also contains support for other public perturbation datasets, including
106
+ Adamson and Dixit, but their data are not bundled. They require separate data
107
+ preparation or downloading and are not additional ready-to-run local collections.
 
108
 
109
+ ### 2. Run the bundled Norman simulation split
110
 
111
+ Activate the environment described in the [project README](../../README.md), then
112
+ run this command in Bash from the outer repository root containing `BioMod/`,
113
+ `data/`, `model_dependencies/`, and `weight/`. A Linux CUDA/NCCL environment is
114
+ required, including when using Linux through WSL. The backslashes continue the
115
+ command across lines in Bash; they are not PowerShell continuation characters.
116
+ One GPU still requires the distributed launcher. Built-in asset defaults resolve
117
+ from the script location; explicit relative paths resolve from the working
118
+ directory.
119
 
120
  ```bash
121
+ python -m torch.distributed.run --standalone --nproc_per_node=1 \
122
+ BioMod/gene_perturbation/train.py \
 
123
  --data_dir data/downstream/final_data \
124
  --data_name norman \
125
+ --split simulation \
126
+ --seed 1 \
127
+ --train_gene_set_size 0.75 \
128
  --scfm_hyper_params_path weight/BioMod.pkl \
129
  --scfm_ckpt_path weight/BioMod.pth \
130
  --biomod_data_dir model_dependencies/biomod_data_all \
131
  --gene_mapping_path model_dependencies/gene2ens.csv \
132
  --scfm_genes_list_path model_dependencies/selected_genes_27k.txt \
133
  --scfm_gene2vec_file model_dependencies/selected_gene2vec_27k.npy \
134
+ --finetune_method frozen \
135
+ --result_dir tutorial_runs/gene_perturbation_norman \
136
+ --run_name norman_biomod \
137
  --epochs 20 \
138
  --batch_size 32 \
139
  --lr 1e-3
140
  ```
141
 
142
+ The split arguments select the bundled split and graph caches. The explicit
143
+ `--finetune_method frozen` setting selects the frozen pretrained branch described
144
+ in the manuscript; omitting it uses the script's current full-fine-tuning default.
145
+ To use several GPUs, change `--nproc_per_node` to the number of available GPUs.
146
+
147
+ This is a single bundled-data run with example training settings, not a verified
148
+ reproduction of the manuscript's repeated-seed results. The training code selects
149
+ the checkpoint with the lowest validation MSE on the top 20 differentially
150
+ expressed genes and then evaluates that checkpoint on the test split. The stored
151
+ split contents, reported cell counts, and model performance were not revalidated
152
+ by this documentation update.
153
+
154
+ Norman already includes `go.csv`, so no external GO annotation file is required
155
+ for this command. If regenerating a missing GO graph for prepared data, supply a
156
+ compatible `gene2go_all.pkl` through `BIOMOD_GENE2GO_PATH`; that optional annotation
157
+ resource is not bundled. Different seeds or split settings require new split and
158
+ coexpression caches and do not reuse the files listed above.
159
+
160
  ### 3. Arguments
161
 
162
  **Model arguments** (defaults point to the bundled BioMod assets):
 
196
 
197
  To compare model performance:
198
 
199
+ 1. **Run original scLong** using its own documentation and a separate checkout
200
+ of the upstream GEARS code. That external workflow is not bundled here.
201
 
202
+ 2. **Run BioMod** using the complete
203
+ [Norman simulation command](#2-run-the-bundled-norman-simulation-split) above.
 
 
 
 
 
 
 
 
 
204
 
205
  3. **Compare metrics**:
206
 
 
244
  ## File Structure
245
 
246
  ```text
247
+ BioMod/gene_perturbation/ # Perturbation response prediction
248
+ β”œβ”€β”€ components/ # Model, data, training, and evaluation helpers
249
+ β”‚ β”œβ”€β”€ __init__.py
250
+ β”‚ β”œβ”€β”€ data_utils.py
251
+ β”‚ β”œβ”€β”€ dataset.py
252
+ β”‚ β”œβ”€β”€ inference.py
253
+ β”‚ β”œβ”€β”€ model.py
254
+ β”‚ β”œβ”€β”€ trainer.py
255
+ β”‚ β”œβ”€β”€ training_utils.py
256
+ β”‚ └── utils.py
257
  β”œβ”€β”€ README.md
258
+ β”œβ”€β”€ train.py
259
+ └── tutorial.ipynb
 
260
  ```
261
 
262
  ## Notes
 
290
 
291
  ### Method 1: Gene-Based (Default, Recommended)
292
 
293
+ Use the complete [Norman simulation command](#2-run-the-bundled-norman-simulation-split)
294
+ above. It uses gene-level recovery by omitting `--use_biomod_level`; this is a
295
+ boolean switch, so do not append a value such as `False`.
 
296
 
297
  **Characteristics**:
298
 
 
303
 
304
  ### Method 2: Module-Based (Experimental, Not Fully Implemented)
305
 
306
+ The `--use_biomod_level` switch selects an experimental mode whose downstream
307
+ architecture is incomplete. It is not included in the runnable
308
+ [Norman simulation command](#2-run-the-bundled-norman-simulation-split). Use the
309
+ default gene-level workflow for the bundled dataset.
310
 
311
  **Characteristics**:
312
 
BioMod/gene_perturbation/components/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """Implementation components for gene perturbation prediction."""
BioMod/gene_perturbation/{data_utils_local.py β†’ components/data_utils.py} RENAMED
@@ -1,6 +1,6 @@
1
  """
2
  ================================================================================
3
- Data processing utility functions (data_utils_local.py)
4
  ================================================================================
5
 
6
  [Module function]
@@ -28,7 +28,7 @@
28
  import warnings
29
  warnings.filterwarnings("ignore")
30
 
31
- from utils import parse_single_pert, parse_combo_pert, parse_any_pert, print_sys
32
 
33
  def rank_genes_groups_by_cov(
34
  adata,
 
1
  """
2
  ================================================================================
3
+ Data processing utility functions (data_utils.py)
4
  ================================================================================
5
 
6
  [Module function]
 
28
  import warnings
29
  warnings.filterwarnings("ignore")
30
 
31
+ from .utils import parse_single_pert, parse_combo_pert, parse_any_pert, print_sys
32
 
33
  def rank_genes_groups_by_cov(
34
  adata,
BioMod/gene_perturbation/{pertdata_local.py β†’ components/dataset.py} RENAMED
@@ -1,6 +1,6 @@
1
  """
2
  ================================================================================
3
- Perturbation data processing module (pertdata_local.py)
4
  ================================================================================
5
 
6
  [Module function]
@@ -45,8 +45,8 @@
45
  # ============================================================
46
  # Use local modules and avoid external gears_reduce imports
47
  # ============================================================
48
- from utils import print_sys, zip_data_download_wrapper, filter_pert_cond_in_go
49
- from data_utils_local import get_DE_genes, get_dropout_non_zero_genes, DataSplitter
50
 
51
  class PertData:
52
 
 
1
  """
2
  ================================================================================
3
+ Perturbation data processing module (dataset.py)
4
  ================================================================================
5
 
6
  [Module function]
 
45
  # ============================================================
46
  # Use local modules and avoid external gears_reduce imports
47
  # ============================================================
48
+ from .utils import print_sys, zip_data_download_wrapper, filter_pert_cond_in_go
49
+ from .data_utils import get_DE_genes, get_dropout_non_zero_genes, DataSplitter
50
 
51
  class PertData:
52
 
BioMod/gene_perturbation/{inference_local.py β†’ components/inference.py} RENAMED
@@ -1,6 +1,6 @@
1
  """
2
  ================================================================================
3
- Model evaluation module (inference_local.py)
4
  ================================================================================
5
 
6
  [Module function]
 
1
  """
2
  ================================================================================
3
+ Model evaluation module (inference.py)
4
  ================================================================================
5
 
6
  [Module function]
BioMod/gene_perturbation/{model_biomod.py β†’ components/model.py} RENAMED
@@ -1,6 +1,6 @@
1
  """
2
  ================================================================================
3
- Genetic perturbation task model definition (model_biomod.py)
4
  ================================================================================
5
 
6
  [Model Architecture Overview]
@@ -55,7 +55,7 @@
55
  sanitize_biomod_config,
56
  )
57
  except ModuleNotFoundError:
58
- project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
59
  if project_root not in sys.path:
60
  sys.path.insert(0, project_root)
61
  from BioMod.models_biomod import (
@@ -485,7 +485,7 @@ def __init__(self, args):
485
  module_data_path=args.get('module_data_path'),
486
  module_data_dir=args.get('module_data_dir'),
487
  gene_list_path=args.get('scfm_genes_list_path'),
488
- gene_mapping_path=args.get('gene_mapping_path', str(Path(__file__).resolve().parents[2] / 'model_dependencies' / 'gene2ens.csv')),
489
  verbose=True
490
  )
491
  else:
 
1
  """
2
  ================================================================================
3
+ Genetic perturbation task model definition (model.py)
4
  ================================================================================
5
 
6
  [Model Architecture Overview]
 
55
  sanitize_biomod_config,
56
  )
57
  except ModuleNotFoundError:
58
+ project_root = str(Path(__file__).resolve().parents[3])
59
  if project_root not in sys.path:
60
  sys.path.insert(0, project_root)
61
  from BioMod.models_biomod import (
 
485
  module_data_path=args.get('module_data_path'),
486
  module_data_dir=args.get('module_data_dir'),
487
  gene_list_path=args.get('scfm_genes_list_path'),
488
+ gene_mapping_path=args.get('gene_mapping_path', str(Path(__file__).resolve().parents[3] / 'model_dependencies' / 'gene2ens.csv')),
489
  verbose=True
490
  )
491
  else:
BioMod/gene_perturbation/{gears_reduce_local.py β†’ components/trainer.py} RENAMED
@@ -1,6 +1,6 @@
1
  """
2
  ================================================================================
3
- GEARS training and evaluation controller (gears_reduce_local.py)
4
  ================================================================================
5
 
6
  [Module function]
@@ -46,14 +46,14 @@
46
  # ============================================================
47
  # Use native modules (optimized versions)
48
  # ============================================================
49
- from model_biomod import GEARS_Model_BioMod
50
- from inference_local import evaluate, compute_metrics, deeper_analysis, \
51
  non_dropout_analysis, compute_synergy_loss
52
- from utils import loss_fct, uncertainty_loss_fct, parse_any_pert, \
53
  get_similarity_network, print_sys, GeneSimNetwork, \
54
  create_cell_graph_dataset_for_prediction, get_mean_control, \
55
  get_GI_genes_idx, get_GI_params
56
- from scfm_utils_local import *
57
 
58
  torch.manual_seed(0)
59
 
 
1
  """
2
  ================================================================================
3
+ GEARS training and evaluation controller (trainer.py)
4
  ================================================================================
5
 
6
  [Module function]
 
46
  # ============================================================
47
  # Use native modules (optimized versions)
48
  # ============================================================
49
+ from .model import GEARS_Model_BioMod
50
+ from .inference import evaluate, compute_metrics, deeper_analysis, \
51
  non_dropout_analysis, compute_synergy_loss
52
+ from .utils import loss_fct, uncertainty_loss_fct, parse_any_pert, \
53
  get_similarity_network, print_sys, GeneSimNetwork, \
54
  create_cell_graph_dataset_for_prediction, get_mean_control, \
55
  get_GI_genes_idx, get_GI_params
56
+ from .training_utils import *
57
 
58
  torch.manual_seed(0)
59
 
BioMod/gene_perturbation/{scfm_utils_local.py β†’ components/training_utils.py} RENAMED
@@ -1,6 +1,6 @@
1
  """
2
  ================================================================================
3
- Single cell basic model tool module (scfm_utils_local.py)
4
  ================================================================================
5
 
6
  [Module function]
 
1
  """
2
  ================================================================================
3
+ Single cell basic model tool module (training_utils.py)
4
  ================================================================================
5
 
6
  [Module function]
BioMod/gene_perturbation/{utils.py β†’ components/utils.py} RENAMED
File without changes
BioMod/gene_perturbation/{train_biomod.py β†’ train.py} RENAMED
@@ -1,6 +1,6 @@
1
  """
2
  ================================================================================
3
- Genetic perturbation task training script (train_biomod.py)
4
  ================================================================================
5
 
6
  [Task Overview]
@@ -49,23 +49,10 @@
49
  DOWNSTREAM_DATA_DIR = REPO_ROOT / "data" / "downstream" / "final_data"
50
  WEIGHTS_DIR = REPO_ROOT / "weight"
51
 
52
- # ============================================================
53
- # [Key] Correctly set the order of sys.path
54
- # Local modules must take precedence and avoid importing into external utils.py
55
- # This is a common Python module import trap: if a module with the same name exists in the project root directory,
56
- # can be imported incorrectly, causing problems that are difficult to debug
57
- # ============================================================
58
- current_dir = os.path.dirname(os.path.abspath(__file__))
59
- project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
60
-
61
- # First add the project root directory (for pytorch_cont)
62
  if project_root not in sys.path:
63
- sys.path.append(project_root)
64
-
65
- # Finally add the current directory (make sure local modules take precedence)
66
- # Use append instead of insert(0), but since the current directory is empty there will be no conflict
67
- if current_dir not in sys.path:
68
- sys.path.insert(0, current_dir)
69
 
70
  # ============================================================
71
  # [Key] Create an independent Numba cache directory for each process
@@ -82,12 +69,12 @@
82
  # [Module Import] Use completely independent local modules
83
  # These local modules are to avoid conflicts with modules of the same name in other parts of the project
84
  # ============================================================
85
- from gears_reduce_local import GEARS
86
- from utils import print_sys
87
- from pertdata_local import PertData # Local version, does not rely on external gears_reduce
88
 
89
  # Import module model
90
- from model_biomod import GEARS_Model_BioMod
91
 
92
  def main(parser):
93
  """
 
1
  """
2
  ================================================================================
3
+ Genetic perturbation task training script (train.py)
4
  ================================================================================
5
 
6
  [Task Overview]
 
49
  DOWNSTREAM_DATA_DIR = REPO_ROOT / "data" / "downstream" / "final_data"
50
  WEIGHTS_DIR = REPO_ROOT / "weight"
51
 
52
+ # Resolve package imports from the repository root, independently of the working directory.
53
+ project_root = str(REPO_ROOT)
 
 
 
 
 
 
 
 
54
  if project_root not in sys.path:
55
+ sys.path.insert(0, project_root)
 
 
 
 
 
56
 
57
  # ============================================================
58
  # [Key] Create an independent Numba cache directory for each process
 
69
  # [Module Import] Use completely independent local modules
70
  # These local modules are to avoid conflicts with modules of the same name in other parts of the project
71
  # ============================================================
72
+ from BioMod.gene_perturbation.components.trainer import GEARS
73
+ from BioMod.gene_perturbation.components.utils import print_sys
74
+ from BioMod.gene_perturbation.components.dataset import PertData # Local version, does not rely on external gears_reduce
75
 
76
  # Import module model
77
+ from BioMod.gene_perturbation.components.model import GEARS_Model_BioMod
78
 
79
  def main(parser):
80
  """
BioMod/{toturials/gene_perturbation.ipynb β†’ gene_perturbation/tutorial.ipynb} RENAMED
@@ -15,7 +15,7 @@
15
  "source": [
16
  "## Project paths\n",
17
  "\n",
18
- "Start Jupyter from `BioMod/toturials/`. The setup cell uses `Path(\"../..\").resolve()` to select the repository root, following the project-relative path convention used in scGPT tutorials. All code, data, model weight, and output paths are derived from this root and resolved to absolute paths for the training command. If Jupyter starts at the repository root, change that line to `Path(\".\").resolve()`. For another launch location, set `PROJECT_ROOT` to the checkout root."
19
  ]
20
  },
21
  {
@@ -24,7 +24,7 @@
24
  "source": [
25
  "## Inputs and workflow\n",
26
  "\n",
27
- "- Entry point: `BioMod/gene_perturbation/train_biomod.py`.\n",
28
  "- Dataset parent: `data/downstream/final_data/`; the loader appends `norman/`.\n",
29
  "- Processed expression: `norman/perturb_processed.h5ad` under that parent.\n",
30
  "- Split: `simulation`, seed `1`, training-gene fraction `0.75`.\n",
@@ -58,7 +58,7 @@
58
  "PROJECT_ROOT = Path('../..').resolve()\n",
59
  "if not (PROJECT_ROOT / 'BioMod' / 'models_biomod.py').is_file() or not (PROJECT_ROOT / 'model_dependencies').is_dir():\n",
60
  " raise FileNotFoundError(\n",
61
- " 'Project root not found. Start Jupyter from BioMod/toturials, or set '\n",
62
  " 'PROJECT_ROOT to your repository root (use Path(\".\").resolve() if '\n",
63
  " 'Jupyter was started at the repository root).'\n",
64
  " )\n",
@@ -67,7 +67,7 @@
67
  "SOURCE_DIR = PROJECT_ROOT / 'BioMod'\n",
68
  "ASSET_ROOT = PROJECT_ROOT / 'model_dependencies'\n",
69
  "TASK_ROOT = SOURCE_DIR / 'gene_perturbation'\n",
70
- "TRAIN_SCRIPT = TASK_ROOT / 'train_biomod.py'\n",
71
  "DATA_DIR = PROJECT_ROOT / 'data' / 'downstream' / 'final_data'\n",
72
  "DATA_NAME = 'norman'\n",
73
  "SPLIT = 'simulation'\n",
@@ -169,7 +169,7 @@
169
  "source": [
170
  "## Training command\n",
171
  "\n",
172
- "`train_biomod.py` initializes distributed training even for one GPU. The command therefore uses `python -m torch.distributed.run --standalone --nproc_per_node=1`. Review the settings below, then set `RUN_TRAINING = True` in the setup cell to launch. The training script selects a checkpoint using validation MSE on the top 20 differentially expressed genes, then evaluates the selected checkpoint on the test split. Batch sizes, epoch count, and learning rate are configurable examples, not a verified benchmark recipe."
173
  ]
174
  },
175
  {
 
15
  "source": [
16
  "## Project paths\n",
17
  "\n",
18
+ "Start Jupyter from `BioMod/gene_perturbation/`. The setup cell uses `Path(\"../..\").resolve()` to select the repository root, following the project-relative path convention used in scGPT tutorials. All code, data, model weight, and output paths are derived from this root and resolved to absolute paths for the training command. If Jupyter starts at the repository root, change that line to `Path(\".\").resolve()`. For another launch location, set `PROJECT_ROOT` to the checkout root."
19
  ]
20
  },
21
  {
 
24
  "source": [
25
  "## Inputs and workflow\n",
26
  "\n",
27
+ "- Entry point: `BioMod/gene_perturbation/train.py`.\n",
28
  "- Dataset parent: `data/downstream/final_data/`; the loader appends `norman/`.\n",
29
  "- Processed expression: `norman/perturb_processed.h5ad` under that parent.\n",
30
  "- Split: `simulation`, seed `1`, training-gene fraction `0.75`.\n",
 
58
  "PROJECT_ROOT = Path('../..').resolve()\n",
59
  "if not (PROJECT_ROOT / 'BioMod' / 'models_biomod.py').is_file() or not (PROJECT_ROOT / 'model_dependencies').is_dir():\n",
60
  " raise FileNotFoundError(\n",
61
+ " 'Project root not found. Start Jupyter from BioMod/gene_perturbation, or set '\n",
62
  " 'PROJECT_ROOT to your repository root (use Path(\".\").resolve() if '\n",
63
  " 'Jupyter was started at the repository root).'\n",
64
  " )\n",
 
67
  "SOURCE_DIR = PROJECT_ROOT / 'BioMod'\n",
68
  "ASSET_ROOT = PROJECT_ROOT / 'model_dependencies'\n",
69
  "TASK_ROOT = SOURCE_DIR / 'gene_perturbation'\n",
70
+ "TRAIN_SCRIPT = TASK_ROOT / 'train.py'\n",
71
  "DATA_DIR = PROJECT_ROOT / 'data' / 'downstream' / 'final_data'\n",
72
  "DATA_NAME = 'norman'\n",
73
  "SPLIT = 'simulation'\n",
 
169
  "source": [
170
  "## Training command\n",
171
  "\n",
172
+ "`train.py` initializes distributed training even for one GPU. The command therefore uses `python -m torch.distributed.run --standalone --nproc_per_node=1`. Review the settings below, then set `RUN_TRAINING = True` in the setup cell to launch. The training script selects a checkpoint using validation MSE on the top 20 differentially expressed genes, then evaluates the selected checkpoint on the test split. Batch sizes, epoch count, and learning rate are configurable examples, not a verified benchmark recipe."
173
  ]
174
  },
175
  {
BioMod/zero_shot_batch/README.md CHANGED
@@ -4,156 +4,184 @@ This directory contains code for extracting BioMod cell embeddings and
4
  evaluating batch effects without fine-tuning. Use the
5
  [BioMod model weights and matching configuration](../../README.md#biomod-model-weights).
6
 
7
- ## Features
8
-
9
- - **Task objective**: evaluate batch effects in cell embeddings extracted with the BioMod model weights.
10
- - **Evaluation metrics**: compute ASW_label/batch metrics with the scib package.
11
- - **Data format**: supports single-cell data in h5ad format.
12
-
13
- ## Usage
14
-
15
- Run these commands from the repository root. Built-in resource defaults resolve from the script location; explicit relative paths resolve from the working directory.
16
-
17
- ### Basic Usage
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  ```bash
20
- python BioMod/zero_shot_batch/biomod_zero_shot.py \
21
- --scfm_hyper_params_path weight/BioMod.pkl \
22
- --scfm_ckpt_path weight/BioMod.pth \
23
- --biomod_data_path model_dependencies/biomod_data_all/merged_biomods.json \
24
- --data_path data/downstream/final_data/Kim2020_Lung.h5ad \
25
- --dataset_preset lung
 
 
 
 
 
26
  ```
27
 
28
- ### Full Argument Example
 
 
 
 
 
 
29
 
30
  ```bash
31
- python BioMod/zero_shot_batch/biomod_zero_shot.py \
32
- --gene2vec_path model_dependencies/selected_gene2vec_27k.npy \
33
- --scfm_hyper_params_path weight/BioMod.pkl \
34
- --scfm_ckpt_path weight/BioMod.pth \
35
  --biomod_data_dir model_dependencies/biomod_data_all \
 
36
  --gene_mapping_path model_dependencies/gene2ens.csv \
37
  --scfm_genes_file model_dependencies/selected_genes_27k.txt \
38
- --data_path data/downstream/final_data/Kim2020_Lung.h5ad \
39
- --dataset_preset lung \
40
- --output_key X_sclong_module \
41
- --n_cells all \
42
- --batch_size 256 \
43
- --output_dir tutorial_runs/zero_shot_first_module \
44
- --metrics_mode simple \
45
- --pool_method first_module
46
  ```
47
 
 
 
 
 
 
 
 
48
  ```bash
49
- python BioMod/zero_shot_batch/biomod_zero_shot.py \
50
- --gene2vec_path model_dependencies/selected_gene2vec_27k.npy \
51
- --scfm_hyper_params_path weight/BioMod.pkl \
52
- --scfm_ckpt_path weight/BioMod.pth \
53
  --biomod_data_dir model_dependencies/biomod_data_all \
 
54
  --gene_mapping_path model_dependencies/gene2ens.csv \
55
  --scfm_genes_file model_dependencies/selected_genes_27k.txt \
56
- --dataset_preset lung \
57
- --data_path data/downstream/final_data/Kim2020_Lung.h5ad \
58
- --output_key X_sclong_module \
59
- --batch_size 128 \
60
- --metrics_mode scgpt \
61
- --output_dir tutorial_runs/zero_shot_max \
62
- --pool_method max
63
  ```
64
 
65
- ### Arguments
66
-
67
- | Argument | Description | Default |
68
- | --- | --- | --- |
69
- | `--scfm_hyper_params_path` | Path to the matching BioMod model configuration; required | - |
70
- | `--scfm_ckpt_path` | Path to the BioMod model weights; required | - |
71
- | `--biomod_data_path` | Path to one module JSON file | None |
72
- | `--biomod_data_dir` | Directory containing multiple module JSON files | None |
73
- | `--gene2vec_path` | Path to the Gene2Vec file | model_dependencies/selected_gene2vec_27k.npy |
74
- | `--gene_mapping_path` | CSV mapping gene symbols to Ensembl IDs | model_dependencies/gene2ens.csv |
75
- | `--scfm_genes_file` | BioMod gene list file | model_dependencies/selected_genes_27k.txt |
76
- | `--data_path` | Input h5ad data file | Required |
77
- | `--output_key` | Key name for embeddings in `adata.obsm` | X_sclong_module |
78
- | `--n_cells` | Number of cells to process; `all` means all cells | all |
79
- | `--batch_size` | Inference batch size | 4 |
80
- | `--output_dir` | Output directory | `BioMod/zero_shot_batch/res/` under the repository |
81
-
82
- ## Outputs
83
 
84
- After the run finishes, the following files are generated under `--output_dir`:
 
 
 
85
 
86
- 1. **`sclong_module_batch_cell_emb_mode.csv`**: evaluation metrics in CSV format.
87
- - Contains three columns: metric, label, and value.
88
- - Main metric: ASW_label/batch. Larger values are better and indicate stronger batch-correction performance.
89
-
90
- 2. **`sclong_module_batch_cell_emb_mode_ce.npy`**: NumPy array of cell embeddings.
91
- - Shape: `(n_cells, embed_dim)`.
92
- - Can be used for downstream analysis or visualization.
93
-
94
- ## Workflow
95
-
96
- 1. **Data loading**: load single-cell data in h5ad format.
97
- 2. **Gene mapping**: convert input gene symbols to Ensembl IDs and map them to the BioMod gene list.
98
- 3. **Model inference**:
99
- - Reindex gene expression values to the BioMod gene order.
100
- - Obtain encodings with the BioMod model.
101
- - Extract cell embeddings using the selected `--pool_method`.
102
- 4. **Evaluation**: compute batch-correction metrics with scib.
103
-
104
- ## Cell Embedding Extraction
105
-
106
- The model output must contain `module_encodings`. Pooling is selected explicitly:
107
-
108
- - `auto`: use `cls_encoding` when present, otherwise mean-pool module encodings.
109
- - `cls`: use `cls_encoding`; if absent, log a warning and use mean pooling.
110
- - `mean` or `max`: pool module encodings along the module dimension.
111
- - `first_module`: restore the original module order with `ids_restore` and select the first module.
112
-
113
- The current script does not fall back to decoder outputs when module encodings are absent.
114
-
115
- ## Comparison with Original scLong
116
-
117
- | Feature | scLong | BioMod |
118
- | --- | --- | --- |
119
- | Model architecture | DualEncoder (mini + large) | Single Encoder |
120
- | Input format | Flat gene expression | Module-based |
121
- | Embedding extraction | `merged_decodings[:, 0, :]` | `module_encodings.mean(dim=1)` |
122
- | Gene handling | Directly uses 27k genes | Aggregates through modules |
123
-
124
- ## Notes
125
-
126
- 1. **Module data**: make sure the correct module data path is provided with `--biomod_data_path` or `--biomod_data_dir`.
127
- 2. **Gene mapping**: make sure the mapping file (`gene2ens.csv`) contains the required gene-symbol to Ensembl-ID mappings.
128
- 3. **Memory usage**: for large datasets, set `--n_cells` to limit the number of processed cells.
129
- 4. **Batch size**: adjust `--batch_size` according to GPU memory.
130
-
131
- ## Troubleshooting
132
-
133
- ### Issue 1: Module Data Not Found
134
-
135
- **Error**: `KeyError: 'module_sets'`
136
 
137
- **Fix**: make sure `--biomod_data_path` or `--biomod_data_dir` is provided.
138
 
139
- ### Issue 2: Gene Mapping Failed
140
 
141
- **Error**: `KeyError: 'gene_symbol'`
 
 
 
142
 
143
- **Fix**: check the format of `--gene_mapping_path` and make sure it contains the `Ensembl gene ID` column.
144
 
145
- ### Issue 3: Model Output Key Missing
 
146
 
147
- **Error**: `KeyError: 'module_encodings'`
 
 
 
 
148
 
149
- **Fix**: use the BioMod model weights and their matching configuration, and
150
- check that the model provides the required output.
 
 
 
151
 
152
- ### Issue 4: Out of Memory
153
 
154
- **Error**: `RuntimeError: CUDA out of memory`
 
 
 
 
155
 
156
- **Fix**:
 
 
 
 
 
157
 
158
- - Decrease `--batch_size`.
159
- - Use `--n_cells` to limit the number of processed cells.
 
 
 
4
  evaluating batch effects without fine-tuning. Use the
5
  [BioMod model weights and matching configuration](../../README.md#biomod-model-weights).
6
 
7
+ ## Notebook
8
+
9
+ See the [task notebook](tutorial.ipynb) for a step-by-step workflow.
10
+
11
+ ## Files
12
+
13
+ | File or directory | Purpose |
14
+ | --- | --- |
15
+ | [README.md](README.md) | File guide, evaluation commands, arguments, and output descriptions. |
16
+ | [tutorial.ipynb](tutorial.ipynb) | Task configuration, execution, and result review in a Jupyter notebook. |
17
+ | [evaluate.py](evaluate.py) | Extract BioMod cell embeddings and evaluate cell-type and batch-effect metrics. |
18
+ | [tools/](tools/) | Optional visualization and sequencing-depth analysis helpers. |
19
+ | [tools/visualize_results.py](tools/visualize_results.py) | Plot saved embeddings and compare batch ASW metrics. |
20
+ | [tools/sequencing_depth/](tools/sequencing_depth/) | Generate reduced-depth inputs and compare zero-shot evaluation results. |
21
+ | [tools/sequencing_depth/make_low_depth_h5ad.py](tools/sequencing_depth/make_low_depth_h5ad.py) | Create reduced-depth h5ad datasets by thinning raw integer counts. |
22
+ | [tools/sequencing_depth/run_zero_shot_low_depth.py](tools/sequencing_depth/run_zero_shot_low_depth.py) | Run evaluation over multiple input datasets and summarize the results. |
23
+ | [tools/sequencing_depth/README.md](tools/sequencing_depth/README.md) | Commands for the sequencing-depth evaluation workflow. |
24
+
25
+ ## Dataset Commands
26
+
27
+ The manuscript evaluates three atlases under four conditions: hPNC, BMMC, and
28
+ Kim Lung with and without malignant cells. Each command below evaluates one
29
+ complete bundled file with `--n_cells all`, max pooling and the scIB metric
30
+ bundle selected by `--metrics_mode scgpt`. These choices follow manuscript
31
+ Section 4.6 (PDF page 25). No additional gene or cell filtering is enabled.
32
+
33
+ Run from the outer repository root after installing the environment. Each
34
+ condition has a separate output directory. A batch size of 1 limits the per-step
35
+ inference memory requirement; all cells are still processed. This is a launch
36
+ setting, not a batch size reported in the manuscript. The complete expression
37
+ matrix and metric calculations can still require substantial host memory.
38
+
39
+ The command blocks use Bash line continuations (`\`). Run them in Bash, such as
40
+ Linux, WSL or Git Bash. In PowerShell, join each command into a single line
41
+ instead of copying the Bash continuation characters.
42
+
43
+ The encoder receives only expression values, not batch or cell-type labels.
44
+ The batch and label fields below are used for evaluation after embedding
45
+ extraction. The entry point reads `adata.X` without additional normalization or
46
+ `log1p`; it does not select counts layers or `.raw`. The commands establish
47
+ file/field wiring, not preprocessing correctness or reproduced performance.
48
+
49
+ | Condition | Cells embedded | Genes in file | Label field | Batch field | Observed batches |
50
+ | --- | ---: | ---: | --- | --- | ---: |
51
+ | hPNC | 16,382 | 19,093 | `celltype` | `tech` | 9 |
52
+ | BMMC | 90,261 | 14,087 | `cell_type` | `batch` | 12 |
53
+ | Kim Lung, malignant cells retained | 32,493 | 20,793 | `cell_type` | `sample` | 14 |
54
+ | Kim Lung, malignant cells removed | 21,955 | 20,793 | `cell_type` | `sample` | 14 |
55
+
56
+ ### 1. hPNC
57
+
58
+ Use the 16,382-cell pancreas atlas, not the paired `hp14/` files used for
59
+ annotation. Its `tech` field contains nine observed values: `celseq`, `celseq2`,
60
+ `fluidigmc1`, `inDrop1`–`inDrop4`, `smarter` and `smartseq2`. The manuscript states
61
+ six batches. No six-batch harmonization is defined in the current entry point;
62
+ this command evaluates the nine values stored in the file and must not be
63
+ presented as a verified six-batch reproduction.
64
 
65
  ```bash
66
+ python BioMod/zero_shot_batch/evaluate.py \
67
+ --data_path data/downstream/final_data/human_pancreas_norm_complexBatch_with_gene_name.h5ad \
68
+ --dataset_preset auto --gene_col gene_name --batch_key tech --label_key celltype \
69
+ --scfm_ckpt_path weight/BioMod.pth --scfm_hyper_params_path weight/BioMod.pkl \
70
+ --biomod_data_dir model_dependencies/biomod_data_all \
71
+ --gene2vec_path model_dependencies/selected_gene2vec_27k.npy \
72
+ --gene_mapping_path model_dependencies/gene2ens.csv \
73
+ --scfm_genes_file model_dependencies/selected_genes_27k.txt \
74
+ --n_cells all --batch_size 1 --pool_method max --metrics_mode scgpt \
75
+ --min_genes_per_cell 0 --min_cells_per_gene 0 \
76
+ --output_dir tutorial_runs/zero_shot_hPNC
77
  ```
78
 
79
+ ### 2. BMMC
80
+
81
+ Use the stored `gene_id` column, which decodes to Ensembl identifiers, and the
82
+ 45 observed `cell_type` classes. The gene column has 98 missing entries and 36
83
+ duplicate nonmissing identifiers. The current mapping leaves missing IDs
84
+ unmapped and uses the last input column for duplicate IDs; it does not aggregate
85
+ duplicates. These existing input semantics have not been changed.
86
 
87
  ```bash
88
+ python BioMod/zero_shot_batch/evaluate.py \
89
+ --data_path data/downstream/final_data/BMMC_processed.h5ad \
90
+ --dataset_preset auto --gene_col gene_id --batch_key batch --label_key cell_type \
91
+ --scfm_ckpt_path weight/BioMod.pth --scfm_hyper_params_path weight/BioMod.pkl \
92
  --biomod_data_dir model_dependencies/biomod_data_all \
93
+ --gene2vec_path model_dependencies/selected_gene2vec_27k.npy \
94
  --gene_mapping_path model_dependencies/gene2ens.csv \
95
  --scfm_genes_file model_dependencies/selected_genes_27k.txt \
96
+ --n_cells all --batch_size 1 --pool_method max --metrics_mode scgpt \
97
+ --min_genes_per_cell 0 --min_cells_per_gene 0 \
98
+ --output_dir tutorial_runs/zero_shot_bmmc
 
 
 
 
 
99
  ```
100
 
101
+ ### 3. Kim Lung: Malignant Cells Retained
102
+
103
+ All 32,493 cells receive embeddings. The file has 10 observed cell-type labels
104
+ and 2,021 unlabeled cells. The evaluator excludes cells with missing labels from
105
+ metrics, so 30,472 cells remain for labeled evaluation. This metadata exclusion
106
+ does not remove rows from the input file or the saved embedding array.
107
+
108
  ```bash
109
+ python BioMod/zero_shot_batch/evaluate.py \
110
+ --data_path data/downstream/final_data/Kim2020_Lung.h5ad \
111
+ --dataset_preset auto --gene_col gene_name --batch_key sample --label_key cell_type \
112
+ --scfm_ckpt_path weight/BioMod.pth --scfm_hyper_params_path weight/BioMod.pkl \
113
  --biomod_data_dir model_dependencies/biomod_data_all \
114
+ --gene2vec_path model_dependencies/selected_gene2vec_27k.npy \
115
  --gene_mapping_path model_dependencies/gene2ens.csv \
116
  --scfm_genes_file model_dependencies/selected_genes_27k.txt \
117
+ --n_cells all --batch_size 1 --pool_method max --metrics_mode scgpt \
118
+ --min_genes_per_cell 0 --min_cells_per_gene 0 \
119
+ --output_dir tutorial_runs/zero_shot_kim_lung
 
 
 
 
120
  ```
121
 
122
+ ### 4. Kim Lung: Malignant Cells Removed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
+ Use the existing 21,955-cell file with malignant cells already excluded. It
125
+ retains nine observed cell-type labels and the same 2,021 unlabeled cells, giving
126
+ 19,934 cells for labeled evaluation. The command does not modify or regenerate
127
+ either lung file.
128
 
129
+ ```bash
130
+ python BioMod/zero_shot_batch/evaluate.py \
131
+ --data_path data/downstream/final_data/Kim2020_Lung_noMalignant.h5ad \
132
+ --dataset_preset auto --gene_col gene_name --batch_key sample --label_key cell_type \
133
+ --scfm_ckpt_path weight/BioMod.pth --scfm_hyper_params_path weight/BioMod.pkl \
134
+ --biomod_data_dir model_dependencies/biomod_data_all \
135
+ --gene2vec_path model_dependencies/selected_gene2vec_27k.npy \
136
+ --gene_mapping_path model_dependencies/gene2ens.csv \
137
+ --scfm_genes_file model_dependencies/selected_genes_27k.txt \
138
+ --n_cells all --batch_size 1 --pool_method max --metrics_mode scgpt \
139
+ --min_genes_per_cell 0 --min_cells_per_gene 0 \
140
+ --output_dir tutorial_runs/zero_shot_kim_lung_no_malignant
141
+ ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
 
143
+ ## Outputs and Metric Definitions
144
 
145
+ Each output directory contains:
146
 
147
+ - `sclong_module_batch_cell_emb_mode.csv`: metrics with `metric`, `label` and
148
+ `value` columns.
149
+ - `sclong_module_batch_cell_emb_mode_ce.npy`: one embedding row per processed
150
+ input cell, before the metric-only removal of missing batch/label values.
151
 
152
+ With `--metrics_mode scgpt`, the script reports individual scIB metrics plus:
153
 
154
+ - `avg_bio = (NMI_cluster/label + ARI_cluster/label + ASW_label) / 3`.
155
+ - `avg_batch = (graph_conn + ASW_label/batch) / 2`.
156
 
157
+ The manuscript defines `avg_score = 0.6 * avg_bio + 0.4 * avg_batch`, but the
158
+ current entry point does not write an `avg_score` row. Compute that aggregate
159
+ from the two reported values when needed; do not mistake `ASW_label/batch`
160
+ alone for the overall score. `--metrics_mode simple` computes only the batch
161
+ silhouette metric and is not the manuscript's complete metric bundle.
162
 
163
+ The manuscript reports five runs with seeds 0–4. This entry point has no general
164
+ `--seed` argument or five-run driver. The existing `--shuffle_seed` controls an
165
+ optional gene-to-module reshuffling experiment; it is not an evaluation seed
166
+ and must not be used as a substitute. Reproducing the reported run-to-run
167
+ variation requires the original randomization protocol.
168
 
169
+ ## Gene Alignment and Optional Workflows
170
 
171
+ The gene column is mapped to the model vocabulary, with unavailable model genes
172
+ filled with zero. `--gene_col` takes an actual `adata.var` column name; to use
173
+ `var.index`, omit this argument with `--dataset_preset auto`. The optional
174
+ `lung` preset supplies `gene_name`, `sample` and `cell_type`, while the examples
175
+ above make every field explicit.
176
 
177
+ Keep saved embedding rows aligned with the original input when plotting.
178
+ The [task notebook](tutorial.ipynb) provides result-review cells, and
179
+ [tools/](tools/) contains standalone plotting and sequencing-depth workflows.
180
+ Reduced-depth evaluation is an additional analysis, not a fifth integration
181
+ condition in the manuscript. The supplied counts layers and any source file
182
+ must remain unchanged unless a separate preprocessing task is explicitly chosen.
183
 
184
+ The remaining bundled H5AD files serve the documented
185
+ [annotation benchmarks](../cell_annotation/README.md#dataset-commands) and
186
+ [gene perturbation task](../gene_perturbation/README.md); their presence does not
187
+ establish additional manuscript integration benchmarks.
BioMod/zero_shot_batch/{biomod_zero_shot.py β†’ evaluate.py} RENAMED
File without changes
BioMod/zero_shot_batch/{sequencing_depth/cmd.txt β†’ tools/sequencing_depth/README.md} RENAMED
@@ -1,42 +1,74 @@
1
- # Run from the repository root. The selected input/layer must contain raw integer counts.
2
- python BioMod/zero_shot_batch/sequencing_depth/make_low_depth_h5ad.py \
3
- --input_path data/downstream/final_data/Kim2020_Lung.h5ad \
4
- --output_dir tutorial_runs/sequencing_depth/inputs \
5
- --keep_ratios 0.5,0.25,0.1,0.05 \
6
- --seeds 0,1,2
7
-
8
- python BioMod/zero_shot_batch/sequencing_depth/run_zero_shot_low_depth.py \
9
- --data_paths \
10
- data/downstream/final_data/Kim2020_Lung.h5ad \
11
- tutorial_runs/sequencing_depth/inputs/*.h5ad \
12
- --scfm_ckpt_path weight/BioMod.pth \
13
- --scfm_hyper_params_path weight/BioMod.pkl \
14
- --output_root tutorial_runs/sequencing_depth/results \
15
- --gene_mapping_path model_dependencies/gene2ens.csv \
16
- --scfm_genes_file model_dependencies/selected_genes_27k.txt \
17
- --biomod_data_dir model_dependencies/biomod_data_all \
18
- --dataset_preset lung \
19
- --output_key X_sclong_module \
20
- --batch_size 256 \
21
- --metrics_mode scgpt \
22
- --pool_method max
23
-
24
-
25
- python BioMod/zero_shot_batch/sequencing_depth/run_zero_shot_low_depth.py \
26
- --data_paths \
27
- data/downstream/final_data/Kim2020_Lung.h5ad \
28
- tutorial_runs/sequencing_depth/inputs/Kim2020_Lung_ld0p5_seed0.h5ad \
29
- tutorial_runs/sequencing_depth/inputs/Kim2020_Lung_ld0p25_seed0.h5ad \
30
- tutorial_runs/sequencing_depth/inputs/Kim2020_Lung_ld0p1_seed0.h5ad \
31
- tutorial_runs/sequencing_depth/inputs/Kim2020_Lung_ld0p05_seed0.h5ad \
32
- --scfm_ckpt_path weight/BioMod.pth \
33
- --scfm_hyper_params_path weight/BioMod.pkl \
34
- --output_root tutorial_runs/sequencing_depth/results \
35
- --gene_mapping_path model_dependencies/gene2ens.csv \
36
- --scfm_genes_file model_dependencies/selected_genes_27k.txt \
37
- --biomod_data_dir model_dependencies/biomod_data_all \
38
- --dataset_preset lung \
39
- --output_key X_sclong_module \
40
- --batch_size 256 \
41
- --metrics_mode scgpt \
42
- --pool_method max
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Sequencing-Depth Evaluation with BioMod
2
+
3
+ Create reduced-depth single-cell datasets by thinning raw integer counts, then
4
+ compare BioMod zero-shot embeddings and evaluation metrics across input depths.
5
+ See the [zero-shot task guide](../../README.md) and
6
+ [task notebook](../../tutorial.ipynb) for the main workflow.
7
+
8
+ ## Files
9
+
10
+ | File | Purpose |
11
+ | --- | --- |
12
+ | [make_low_depth_h5ad.py](make_low_depth_h5ad.py) | Generate reduced-depth h5ad datasets at specified retention ratios and random seeds. |
13
+ | [run_zero_shot_low_depth.py](run_zero_shot_low_depth.py) | Run the zero-shot evaluation entrypoint on each input and summarize the resulting metrics. |
14
+ | [README.md](README.md) | Commands for generating inputs and comparing evaluation results. |
15
+
16
+ ## Usage
17
+
18
+ Run from the repository root. The selected input matrix or layer must contain
19
+ raw integer counts. Built-in resource defaults resolve from the script location;
20
+ explicit relative paths resolve from the working directory.
21
+
22
+ ### Generate Reduced-Depth Inputs
23
+
24
+ ```bash
25
+ # Run from the repository root. The selected input/layer must contain raw integer counts.
26
+ python BioMod/zero_shot_batch/tools/sequencing_depth/make_low_depth_h5ad.py \
27
+ --input_path data/downstream/final_data/Kim2020_Lung.h5ad \
28
+ --output_dir tutorial_runs/sequencing_depth/inputs \
29
+ --keep_ratios 0.5,0.25,0.1,0.05 \
30
+ --seeds 0,1,2
31
+ ```
32
+
33
+ ### Evaluate All Generated Inputs
34
+
35
+ ```bash
36
+ python BioMod/zero_shot_batch/tools/sequencing_depth/run_zero_shot_low_depth.py \
37
+ --data_paths \
38
+ data/downstream/final_data/Kim2020_Lung.h5ad \
39
+ tutorial_runs/sequencing_depth/inputs/*.h5ad \
40
+ --scfm_ckpt_path weight/BioMod.pth \
41
+ --scfm_hyper_params_path weight/BioMod.pkl \
42
+ --output_root tutorial_runs/sequencing_depth/results \
43
+ --gene_mapping_path model_dependencies/gene2ens.csv \
44
+ --scfm_genes_file model_dependencies/selected_genes_27k.txt \
45
+ --biomod_data_dir model_dependencies/biomod_data_all \
46
+ --dataset_preset lung \
47
+ --output_key X_sclong_module \
48
+ --batch_size 256 \
49
+ --metrics_mode scgpt \
50
+ --pool_method max
51
+ ```
52
+
53
+ ### Evaluate Selected Inputs
54
+
55
+ ```bash
56
+ python BioMod/zero_shot_batch/tools/sequencing_depth/run_zero_shot_low_depth.py \
57
+ --data_paths \
58
+ data/downstream/final_data/Kim2020_Lung.h5ad \
59
+ tutorial_runs/sequencing_depth/inputs/Kim2020_Lung_ld0p5_seed0.h5ad \
60
+ tutorial_runs/sequencing_depth/inputs/Kim2020_Lung_ld0p25_seed0.h5ad \
61
+ tutorial_runs/sequencing_depth/inputs/Kim2020_Lung_ld0p1_seed0.h5ad \
62
+ tutorial_runs/sequencing_depth/inputs/Kim2020_Lung_ld0p05_seed0.h5ad \
63
+ --scfm_ckpt_path weight/BioMod.pth \
64
+ --scfm_hyper_params_path weight/BioMod.pkl \
65
+ --output_root tutorial_runs/sequencing_depth/results \
66
+ --gene_mapping_path model_dependencies/gene2ens.csv \
67
+ --scfm_genes_file model_dependencies/selected_genes_27k.txt \
68
+ --biomod_data_dir model_dependencies/biomod_data_all \
69
+ --dataset_preset lung \
70
+ --output_key X_sclong_module \
71
+ --batch_size 256 \
72
+ --metrics_mode scgpt \
73
+ --pool_method max
74
+ ```
BioMod/zero_shot_batch/{sequencing_depth β†’ tools/sequencing_depth}/make_low_depth_h5ad.py RENAMED
File without changes
BioMod/zero_shot_batch/{sequencing_depth β†’ tools/sequencing_depth}/run_zero_shot_low_depth.py RENAMED
@@ -17,7 +17,7 @@ def parse_args() -> argparse.Namespace:
17
  parser = argparse.ArgumentParser(
18
  description="Run biomod zero-shot on multiple full/low-depth h5ad files and aggregate metrics."
19
  )
20
- parser.add_argument("--script_path", type=str, default=None, help="Path to biomod_zero_shot.py")
21
  parser.add_argument("--data_paths", nargs="+", required=True, help="One or more full/low-depth h5ad files")
22
  parser.add_argument("--output_root", type=str, required=True, help="Root directory for per-run outputs")
23
  parser.add_argument("--scfm_hyper_params_path", type=str, required=True)
@@ -26,7 +26,7 @@ def parse_args() -> argparse.Namespace:
26
  parser.add_argument("--biomod_data_dir", "--module_data_dir", type=str, default=None, dest='module_data_dir')
27
  parser.add_argument("--gene_mapping_path", type=str, required=True)
28
  parser.add_argument("--scfm_genes_file", type=str, required=True)
29
- parser.add_argument("--gene2vec_path", type=str, default=str(Path(__file__).resolve().parents[3] / "model_dependencies" / "selected_gene2vec_27k.npy"))
30
  parser.add_argument("--dataset_preset", type=str, default="lung")
31
  parser.add_argument("--gene_col", type=str, default=None)
32
  parser.add_argument("--batch_key", type=str, default=None)
@@ -49,7 +49,7 @@ def parse_args() -> argparse.Namespace:
49
  def resolve_script_path(script_path: Optional[str]) -> Path:
50
  if script_path is not None:
51
  return Path(script_path).resolve()
52
- return (Path(__file__).resolve().parent.parent / "biomod_zero_shot.py").resolve()
53
 
54
 
55
  def slugify_path(path: Path) -> str:
 
17
  parser = argparse.ArgumentParser(
18
  description="Run biomod zero-shot on multiple full/low-depth h5ad files and aggregate metrics."
19
  )
20
+ parser.add_argument("--script_path", type=str, default=None, help="Path to evaluate.py")
21
  parser.add_argument("--data_paths", nargs="+", required=True, help="One or more full/low-depth h5ad files")
22
  parser.add_argument("--output_root", type=str, required=True, help="Root directory for per-run outputs")
23
  parser.add_argument("--scfm_hyper_params_path", type=str, required=True)
 
26
  parser.add_argument("--biomod_data_dir", "--module_data_dir", type=str, default=None, dest='module_data_dir')
27
  parser.add_argument("--gene_mapping_path", type=str, required=True)
28
  parser.add_argument("--scfm_genes_file", type=str, required=True)
29
+ parser.add_argument("--gene2vec_path", type=str, default=str(Path(__file__).resolve().parents[4] / "model_dependencies" / "selected_gene2vec_27k.npy"))
30
  parser.add_argument("--dataset_preset", type=str, default="lung")
31
  parser.add_argument("--gene_col", type=str, default=None)
32
  parser.add_argument("--batch_key", type=str, default=None)
 
49
  def resolve_script_path(script_path: Optional[str]) -> Path:
50
  if script_path is not None:
51
  return Path(script_path).resolve()
52
+ return (Path(__file__).resolve().parents[2] / "evaluate.py").resolve()
53
 
54
 
55
  def slugify_path(path: Path) -> str:
BioMod/zero_shot_batch/{visualize_results.py β†’ tools/visualize_results.py} RENAMED
File without changes
BioMod/{toturials/zero_shot_batch_integration.ipynb β†’ zero_shot_batch/tutorial.ipynb} RENAMED
@@ -15,12 +15,12 @@
15
  "source": [
16
  "## Project paths and environment\n",
17
  "\n",
18
- "Start Jupyter with `BioMod/toturials` as its working directory and select the environment described in [the project README](../../README.md). Paths below are relative to this notebook directory, following the project-relative layout used in scGPT tutorials. `Path.resolve()` turns them into absolute paths for subprocesses. If Jupyter was started at the repository root, set `PROJECT_ROOT = Path('.').resolve()` instead.\n",
19
  "\n",
20
  "- Data: `../../data/downstream/final_data/Kim2020_Lung_noMalignant.h5ad`\n",
21
  "- BioMod model weights and configuration: `../../weight/`\n",
22
  "- Shared assets: `../../model_dependencies/`\n",
23
- "- Runner: `../zero_shot_batch/biomod_zero_shot.py`\n",
24
  "- Results: `../../tutorial_runs/zero_shot_kim_lung_no_malignant/`\n",
25
  "\n",
26
  "Review the configuration, then set `RUN_EVALUATION = True` to run inference. The runner consumes `adata.X` without normalization or log transformation; check that its expression preprocessing is appropriate for the checkpoint and your experiment. It loads the input dataset into memory before batching inference.\n"
@@ -41,12 +41,12 @@
41
  "PROJECT_ROOT = Path('../..').resolve()\n",
42
  "if not (PROJECT_ROOT / 'BioMod').is_dir() or not (PROJECT_ROOT / 'model_dependencies').is_dir():\n",
43
  " raise FileNotFoundError(\n",
44
- " 'Start Jupyter from BioMod/toturials, or set PROJECT_ROOT to the repository root '\n",
45
  " \"(use Path('.').resolve() when launched at the repository root).\"\n",
46
  " )\n",
47
  "SOURCE_DIR = PROJECT_ROOT / 'BioMod'\n",
48
  "DEPENDENCIES_DIR = PROJECT_ROOT / 'model_dependencies'\n",
49
- "SCRIPT = SOURCE_DIR / 'zero_shot_batch' / 'biomod_zero_shot.py'\n",
50
  "DATA_PATH = PROJECT_ROOT / 'data' / 'downstream' / 'final_data' / 'Kim2020_Lung_noMalignant.h5ad'\n",
51
  "WEIGHT_DIR = PROJECT_ROOT / 'weight'\n",
52
  "CONFIG_PKL = WEIGHT_DIR / 'BioMod.pkl'\n",
 
15
  "source": [
16
  "## Project paths and environment\n",
17
  "\n",
18
+ "Start Jupyter with `BioMod/zero_shot_batch` as its working directory and select the environment described in [the project README](../../README.md). Paths below are relative to this notebook directory, following the project-relative layout used in scGPT tutorials. `Path.resolve()` turns them into absolute paths for subprocesses. If Jupyter was started at the repository root, set `PROJECT_ROOT = Path('.').resolve()` instead.\n",
19
  "\n",
20
  "- Data: `../../data/downstream/final_data/Kim2020_Lung_noMalignant.h5ad`\n",
21
  "- BioMod model weights and configuration: `../../weight/`\n",
22
  "- Shared assets: `../../model_dependencies/`\n",
23
+ "- Runner: `evaluate.py`\n",
24
  "- Results: `../../tutorial_runs/zero_shot_kim_lung_no_malignant/`\n",
25
  "\n",
26
  "Review the configuration, then set `RUN_EVALUATION = True` to run inference. The runner consumes `adata.X` without normalization or log transformation; check that its expression preprocessing is appropriate for the checkpoint and your experiment. It loads the input dataset into memory before batching inference.\n"
 
41
  "PROJECT_ROOT = Path('../..').resolve()\n",
42
  "if not (PROJECT_ROOT / 'BioMod').is_dir() or not (PROJECT_ROOT / 'model_dependencies').is_dir():\n",
43
  " raise FileNotFoundError(\n",
44
+ " 'Start Jupyter from BioMod/zero_shot_batch, or set PROJECT_ROOT to the repository root '\n",
45
  " \"(use Path('.').resolve() when launched at the repository root).\"\n",
46
  " )\n",
47
  "SOURCE_DIR = PROJECT_ROOT / 'BioMod'\n",
48
  "DEPENDENCIES_DIR = PROJECT_ROOT / 'model_dependencies'\n",
49
+ "SCRIPT = SOURCE_DIR / 'zero_shot_batch' / 'evaluate.py'\n",
50
  "DATA_PATH = PROJECT_ROOT / 'data' / 'downstream' / 'final_data' / 'Kim2020_Lung_noMalignant.h5ad'\n",
51
  "WEIGHT_DIR = PROJECT_ROOT / 'weight'\n",
52
  "CONFIG_PKL = WEIGHT_DIR / 'BioMod.pkl'\n",
README.md CHANGED
@@ -53,6 +53,17 @@ Pretraining uses CUDA/NCCL. The zero-shot
53
  runner selects CUDA when available and otherwise uses CPU. Native Windows
54
  execution has not been validated for the supplied environment.
55
 
 
 
 
 
 
 
 
 
 
 
 
56
  ## BioMod model weights
57
 
58
  This release includes the **BioMod model weights** and their matching
@@ -70,6 +81,9 @@ architecture and gene-module definitions.
70
 
71
  The model components are bundled under
72
  [`model_dependencies/pytorch_cont/`](model_dependencies/pytorch_cont/).
 
 
 
73
  Task-specific checkpoint arguments are listed under
74
  [Usage notes](#checkpoint-arguments).
75
 
@@ -81,11 +95,11 @@ to end with the bundled checkpoint.
81
 
82
  | Task | Implementation | Notebook |
83
  | --- | --- | --- |
84
- | Cell-type annotation | [Fine-tuning script](BioMod/cell_annotation/biomod_finetune.py) | [Notebook](BioMod/toturials/cell_annotation.ipynb) |
85
- | Zero-shot cell embeddings and batch-effect evaluation | [Embedding and evaluation script](BioMod/zero_shot_batch/biomod_zero_shot.py) | [Notebook](BioMod/toturials/zero_shot_batch_integration.ipynb) |
86
- | Single-drug response regression (IC50) | [Training script](BioMod/drug_response/train_drug_biomod.py) | [Notebook](BioMod/toturials/drug_response_prediction.ipynb) |
87
- | Drug-pair synergy classification | [Training script](BioMod/drug_combination/train_drug_combination_biomod.py) | [Notebook](BioMod/toturials/drug_combination.ipynb) |
88
- | Gene perturbation response prediction | [Training script](BioMod/gene_perturbation/train_biomod.py) | [Notebook](BioMod/toturials/gene_perturbation.ipynb) |
89
 
90
  ### Pretraining
91
 
@@ -109,10 +123,12 @@ The project root contains `BioMod/`, `model_dependencies/`, `weight/`, and
109
  may assume different working directories; adjust relative paths when following
110
  a guide.
111
 
112
- Start Jupyter from `BioMod/toturials/`. Each notebook sets
113
- `PROJECT_ROOT = Path('../..').resolve()` and derives absolute runtime paths from
114
- the outer repository root. If Jupyter starts at the repository root, use
115
- `Path('.').resolve()` instead. Review the configuration cells before running:
 
 
116
 
117
  | Setting | Location |
118
  | --- | --- |
@@ -170,64 +186,65 @@ readability. Folder descriptions explain where to find each component.
170
  <summary>Expand the full repository structure</summary>
171
 
172
  ```text
173
- BioMod/ # Project root: source code, model dependencies and weights
174
- β”œβ”€β”€ BioMod/ # Task code: training, evaluation and tutorials
175
- β”‚ β”œβ”€β”€ cell_annotation/ # Cell-type annotation and model fine-tuning
176
- β”‚ β”‚ β”œβ”€β”€ biomod_data/ # Hallmark and Reactome modules with loading utilities
177
- β”‚ β”‚ β”‚ β”œβ”€β”€ load_biomod.py
178
- β”‚ β”‚ β”‚ β”œβ”€β”€ biomod1_hallmarks.json
179
- β”‚ β”‚ β”‚ └── biomod2_reactome_2022_filtered.json
180
- β”‚ β”‚ β”œβ”€β”€ cmd_finetune.md
181
- β”‚ β”‚ └── biomod_finetune.py
182
- β”‚ β”œβ”€β”€ drug_combination/ # Drug-combination synergy prediction
183
  β”‚ β”‚ β”œβ”€β”€ README.md
184
- β”‚ β”‚ └── train_drug_combination_biomod.py
185
- β”‚ β”œβ”€β”€ drug_response/ # Single-drug response prediction and training
186
- β”‚ β”‚ β”œβ”€β”€ cmd.txt
187
- β”‚ β”‚ └── train_drug_biomod.py
188
- β”‚ β”œβ”€β”€ gene_perturbation/ # Perturbation response prediction: processing, training and inference
189
- β”‚ β”‚ β”œβ”€β”€ data_utils_local.py
190
- β”‚ β”‚ β”œβ”€β”€ gears_reduce_local.py
191
- β”‚ β”‚ β”œβ”€β”€ inference_local.py
192
- β”‚ β”‚ β”œβ”€β”€ model_biomod.py
193
- β”‚ β”‚ β”œβ”€β”€ pertdata_local.py
194
  β”‚ β”‚ β”œβ”€β”€ README.md
195
- β”‚ β”‚ β”œβ”€β”€ scfm_utils_local.py
196
- β”‚ β”‚ β”œβ”€β”€ train_biomod.py
197
- β”‚ β”‚ └── utils.py
198
- β”‚ β”œβ”€β”€ tests/ # CPU tests for shared training utilities
 
 
 
 
 
 
 
 
 
 
 
 
199
  β”‚ β”‚ └── test_training_utils.py
200
- β”‚ β”œβ”€β”€ toturials/ # Jupyter tutorials for five downstream tasks
201
- β”‚ β”‚ β”œβ”€β”€ cell_annotation.ipynb
202
- β”‚ β”‚ β”œβ”€β”€ drug_combination.ipynb
203
- β”‚ β”‚ β”œβ”€β”€ drug_response_prediction.ipynb
204
- β”‚ β”‚ β”œβ”€β”€ gene_perturbation.ipynb
205
- β”‚ β”‚ └── zero_shot_batch_integration.ipynb
206
- β”‚ β”œβ”€β”€ zero_shot_batch/ # Zero-shot batch integration, evaluation and visualization
207
- β”‚ β”‚ β”œβ”€β”€ sequencing_depth/ # Low-depth data generation and zero-shot evaluation
208
- β”‚ β”‚ β”‚ β”œβ”€β”€ cmd.txt
209
- β”‚ β”‚ β”‚ β”œβ”€β”€ make_low_depth_h5ad.py
210
- β”‚ β”‚ β”‚ └── run_zero_shot_low_depth.py
211
- β”‚ β”‚ β”œβ”€β”€ biomod_zero_shot.py
212
  β”‚ β”‚ β”œβ”€β”€ README.md
213
- β”‚ β”‚ └── visualize_results.py
214
- β”‚ β”œβ”€β”€ .env.example
215
  β”‚ β”œβ”€β”€ .gitattributes
216
  β”‚ β”œβ”€β”€ .gitignore
 
 
217
  β”‚ β”œβ”€β”€ command.txt
218
  β”‚ β”œβ”€β”€ environment.yml
219
  β”‚ β”œβ”€β”€ models_biomod.py
220
- β”‚ β”œβ”€β”€ biomod_dataset.py
221
- β”‚ β”œβ”€β”€ biomod.py
222
  β”‚ β”œβ”€β”€ README.md
223
  β”‚ β”œβ”€β”€ requirements.txt
224
  β”‚ └── training_utils.py
225
- β”œβ”€β”€ model_dependencies/ # Shared gene mappings, gene lists, embeddings and model components
226
- β”‚ β”œβ”€β”€ biomod_data_all/ # Shared module definitions and construction tools
227
  β”‚ β”‚ β”œβ”€β”€ create_uncovered_biomods.py
228
  β”‚ β”‚ β”œβ”€β”€ merge_biomods.py
229
  β”‚ β”‚ └── merged_biomods.json
230
- β”‚ β”œβ”€β”€ pytorch_cont/ # Attention and model components
 
 
 
 
231
  β”‚ β”‚ β”œβ”€β”€ __init__.py
232
  β”‚ β”‚ β”œβ”€β”€ ding_models.py
233
  β”‚ β”‚ β”œβ”€β”€ pytorch.py
@@ -236,7 +253,7 @@ BioMod/ # Project root: source
236
  β”‚ β”œβ”€β”€ gene2ens.csv
237
  β”‚ β”œβ”€β”€ selected_gene2vec_27k.npy
238
  β”‚ └── selected_genes_27k.txt
239
- β”œβ”€β”€ weight/ # Pretrained weights and matching model configurations
240
  β”‚ β”œβ”€β”€ BioMod.pkl
241
  β”‚ └── BioMod.pth
242
  β”œβ”€β”€ .gitattributes
 
53
  runner selects CUDA when available and otherwise uses CPU. Native Windows
54
  execution has not been validated for the supplied environment.
55
 
56
+ To open a tutorial, choose its task directory. For cell annotation, run the
57
+ following from the outer repository root:
58
+
59
+ ```bash
60
+ cd BioMod/cell_annotation
61
+ jupyter lab tutorial.ipynb
62
+ ```
63
+
64
+ Use `drug_response`, `drug_combination`, `gene_perturbation`, or `zero_shot_batch`
65
+ in place of `cell_annotation` to open another task.
66
+
67
  ## BioMod model weights
68
 
69
  This release includes the **BioMod model weights** and their matching
 
81
 
82
  The model components are bundled under
83
  [`model_dependencies/pytorch_cont/`](model_dependencies/pytorch_cont/).
84
+ Optional [Hallmark and Reactome source definitions](model_dependencies/biomod_data_sources/)
85
+ are kept in `biomod_data_sources/`. They are separate from the default checkpoint
86
+ runtime definitions in `biomod_data_all/`.
87
  Task-specific checkpoint arguments are listed under
88
  [Usage notes](#checkpoint-arguments).
89
 
 
95
 
96
  | Task | Implementation | Notebook |
97
  | --- | --- | --- |
98
+ | Cell-type annotation | [Fine-tuning script](BioMod/cell_annotation/train.py) | [Notebook](BioMod/cell_annotation/tutorial.ipynb) |
99
+ | Zero-shot cell embeddings and batch-effect evaluation | [Embedding and evaluation script](BioMod/zero_shot_batch/evaluate.py) | [Notebook](BioMod/zero_shot_batch/tutorial.ipynb) |
100
+ | Single-drug response regression (IC50) | [Training script](BioMod/drug_response/train.py) | [Notebook](BioMod/drug_response/tutorial.ipynb) |
101
+ | Drug-pair synergy classification | [Training script](BioMod/drug_combination/train.py) | [Notebook](BioMod/drug_combination/tutorial.ipynb) |
102
+ | Gene perturbation response prediction | [Training script](BioMod/gene_perturbation/train.py) | [Notebook](BioMod/gene_perturbation/tutorial.ipynb) |
103
 
104
  ### Pretraining
105
 
 
123
  may assume different working directories; adjust relative paths when following
124
  a guide.
125
 
126
+ Each task keeps its notebook in `BioMod/<task>/tutorial.ipynb`. Start Jupyter
127
+ from the selected task directory, as shown in [Installation](#installation).
128
+ Each notebook sets `PROJECT_ROOT = Path('../..').resolve()` and derives absolute
129
+ runtime paths from the outer repository root. If the notebook kernel uses a
130
+ different working directory, set `PROJECT_ROOT` to the outer repository root
131
+ explicitly before running the path checks. Review the configuration cells before running:
132
 
133
  | Setting | Location |
134
  | --- | --- |
 
186
  <summary>Expand the full repository structure</summary>
187
 
188
  ```text
189
+ BioMod/ # Project root: source code, model dependencies and weights
190
+ β”œβ”€β”€ BioMod/ # Task code: training, evaluation and tutorials
191
+ β”‚ β”œβ”€β”€ cell_annotation/ # Cell-type annotation and model fine-tuning
192
+ β”‚ β”‚ β”œβ”€β”€ README.md
193
+ β”‚ β”‚ β”œβ”€β”€ train.py
194
+ β”‚ β”‚ └── tutorial.ipynb
195
+ β”‚ β”œβ”€β”€ drug_combination/ # Drug-combination synergy prediction
 
 
 
196
  β”‚ β”‚ β”œβ”€β”€ README.md
197
+ β”‚ β”‚ β”œβ”€β”€ train.py
198
+ β”‚ β”‚ └── tutorial.ipynb
199
+ β”‚ β”œβ”€β”€ drug_response/ # Single-drug response prediction
 
 
 
 
 
 
 
200
  β”‚ β”‚ β”œβ”€β”€ README.md
201
+ β”‚ β”‚ β”œβ”€β”€ train.py
202
+ β”‚ β”‚ └── tutorial.ipynb
203
+ β”‚ β”œβ”€β”€ gene_perturbation/ # Gene perturbation response prediction
204
+ β”‚ β”‚ β”œβ”€β”€ components/ # Task models, datasets, training and inference helpers
205
+ β”‚ β”‚ β”‚ β”œβ”€β”€ __init__.py
206
+ β”‚ β”‚ β”‚ β”œβ”€β”€ data_utils.py
207
+ β”‚ β”‚ β”‚ β”œβ”€β”€ dataset.py
208
+ β”‚ β”‚ β”‚ β”œβ”€β”€ inference.py
209
+ β”‚ β”‚ β”‚ β”œβ”€β”€ model.py
210
+ β”‚ β”‚ β”‚ β”œβ”€β”€ trainer.py
211
+ β”‚ β”‚ β”‚ β”œβ”€β”€ training_utils.py
212
+ β”‚ β”‚ β”‚ └── utils.py
213
+ β”‚ β”‚ β”œβ”€β”€ README.md
214
+ β”‚ β”‚ β”œβ”€β”€ train.py
215
+ β”‚ β”‚ └── tutorial.ipynb
216
+ β”‚ β”œβ”€β”€ tests/ # CPU tests for shared training utilities
217
  β”‚ β”‚ └── test_training_utils.py
218
+ β”‚ β”œβ”€β”€ zero_shot_batch/ # Zero-shot integration and evaluation
219
+ β”‚ β”‚ β”œβ”€β”€ tools/ # Optional visualization and evaluation tools
220
+ β”‚ β”‚ β”‚ β”œβ”€β”€ sequencing_depth/ # Low-depth expression generation and evaluation
221
+ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ make_low_depth_h5ad.py
222
+ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ README.md
223
+ β”‚ β”‚ β”‚ β”‚ └── run_zero_shot_low_depth.py
224
+ β”‚ β”‚ β”‚ └── visualize_results.py
225
+ β”‚ β”‚ β”œβ”€β”€ evaluate.py
 
 
 
 
226
  β”‚ β”‚ β”œβ”€β”€ README.md
227
+ β”‚ β”‚ └── tutorial.ipynb
 
228
  β”‚ β”œβ”€β”€ .gitattributes
229
  β”‚ β”œβ”€β”€ .gitignore
230
+ β”‚ β”œβ”€β”€ biomod.py
231
+ β”‚ β”œβ”€β”€ biomod_dataset.py
232
  β”‚ β”œβ”€β”€ command.txt
233
  β”‚ β”œβ”€β”€ environment.yml
234
  β”‚ β”œβ”€β”€ models_biomod.py
 
 
235
  β”‚ β”œβ”€β”€ README.md
236
  β”‚ β”œβ”€β”€ requirements.txt
237
  β”‚ └── training_utils.py
238
+ β”œβ”€β”€ model_dependencies/ # Shared gene mappings, embeddings and model components
239
+ β”‚ β”œβ”€β”€ biomod_data_all/ # Default merged module definitions and construction tools
240
  β”‚ β”‚ β”œβ”€β”€ create_uncovered_biomods.py
241
  β”‚ β”‚ β”œβ”€β”€ merge_biomods.py
242
  β”‚ β”‚ └── merged_biomods.json
243
+ β”‚ β”œβ”€β”€ biomod_data_sources/ # Optional source gene sets and their loading helper
244
+ β”‚ β”‚ β”œβ”€β”€ biomod1_hallmarks.json
245
+ β”‚ β”‚ β”œβ”€β”€ biomod2_reactome_2022_filtered.json
246
+ β”‚ β”‚ └── load_biomod.py
247
+ β”‚ β”œβ”€β”€ pytorch_cont/ # Attention and model components
248
  β”‚ β”‚ β”œβ”€β”€ __init__.py
249
  β”‚ β”‚ β”œβ”€β”€ ding_models.py
250
  β”‚ β”‚ β”œβ”€β”€ pytorch.py
 
253
  β”‚ β”œβ”€β”€ gene2ens.csv
254
  β”‚ β”œβ”€β”€ selected_gene2vec_27k.npy
255
  β”‚ └── selected_genes_27k.txt
256
+ β”œβ”€β”€ weight/ # Pretrained weights and matching model configuration
257
  β”‚ β”œβ”€β”€ BioMod.pkl
258
  β”‚ └── BioMod.pth
259
  β”œβ”€β”€ .gitattributes
data/downstream/final_data/drug_combination_synergy/README.md CHANGED
@@ -9,7 +9,7 @@ data/downstream/final_data/drug_response_pytorch/drug_combination
9
 
10
  ## Runnable data path
11
 
12
- From the repository root, use this directory as `--data_dir` for `BioMod/drug_combination/train_drug_combination_biomod.py`:
13
 
14
  ```text
15
  data/downstream/final_data/drug_combination_synergy/data_summary
 
9
 
10
  ## Runnable data path
11
 
12
+ From the repository root, use this directory as `--data_dir` for `BioMod/drug_combination/train.py`:
13
 
14
  ```text
15
  data/downstream/final_data/drug_combination_synergy/data_summary
data/downstream/final_data/single_drug_response/README.md CHANGED
@@ -9,7 +9,7 @@ data/downstream/final_data/drug_response_pytorch/drug_response_pytorch
9
 
10
  ## Runnable data path
11
 
12
- From the repository root, use this directory as `--data_path` for `BioMod/drug_response/train_drug_biomod.py`:
13
 
14
  ```text
15
  data/downstream/final_data/single_drug_response/data
 
9
 
10
  ## Runnable data path
11
 
12
+ From the repository root, use this directory as `--data_path` for `BioMod/drug_response/train.py`:
13
 
14
  ```text
15
  data/downstream/final_data/single_drug_response/data
{BioMod/cell_annotation/biomod_data β†’ model_dependencies/biomod_data_sources}/biomod1_hallmarks.json RENAMED
File without changes
{BioMod/cell_annotation/biomod_data β†’ model_dependencies/biomod_data_sources}/biomod2_reactome_2022_filtered.json RENAMED
File without changes
{BioMod/cell_annotation/biomod_data β†’ model_dependencies/biomod_data_sources}/load_biomod.py RENAMED
File without changes