Unify downstream task layout and document dataset launch commands
Browse filesPlace 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.
- BioMod/.env.example +0 -13
- BioMod/.gitignore +1 -5
- BioMod/README.md +371 -358
- BioMod/cell_annotation/README.md +282 -0
- BioMod/cell_annotation/cmd_finetune.md +0 -21
- BioMod/cell_annotation/{biomod_finetune.py β train.py} +32 -5
- BioMod/{toturials/cell_annotation.ipynb β cell_annotation/tutorial.ipynb} +4 -4
- BioMod/drug_combination/README.md +79 -54
- BioMod/drug_combination/{train_drug_combination_biomod.py β train.py} +1 -1
- BioMod/{toturials/drug_combination.ipynb β drug_combination/tutorial.ipynb} +5 -5
- BioMod/drug_response/README.md +70 -0
- BioMod/drug_response/cmd.txt +0 -10
- BioMod/drug_response/{train_drug_biomod.py β train.py} +2 -2
- BioMod/{toturials/drug_response_prediction.ipynb β drug_response/tutorial.ipynb} +6 -6
- BioMod/gene_perturbation/README.md +102 -45
- BioMod/gene_perturbation/components/__init__.py +1 -0
- BioMod/gene_perturbation/{data_utils_local.py β components/data_utils.py} +2 -2
- BioMod/gene_perturbation/{pertdata_local.py β components/dataset.py} +3 -3
- BioMod/gene_perturbation/{inference_local.py β components/inference.py} +1 -1
- BioMod/gene_perturbation/{model_biomod.py β components/model.py} +3 -3
- BioMod/gene_perturbation/{gears_reduce_local.py β components/trainer.py} +5 -5
- BioMod/gene_perturbation/{scfm_utils_local.py β components/training_utils.py} +1 -1
- BioMod/gene_perturbation/{utils.py β components/utils.py} +0 -0
- BioMod/gene_perturbation/{train_biomod.py β train.py} +8 -21
- BioMod/{toturials/gene_perturbation.ipynb β gene_perturbation/tutorial.ipynb} +5 -5
- BioMod/zero_shot_batch/README.md +151 -123
- BioMod/zero_shot_batch/{biomod_zero_shot.py β evaluate.py} +0 -0
- BioMod/zero_shot_batch/{sequencing_depth/cmd.txt β tools/sequencing_depth/README.md} +74 -42
- BioMod/zero_shot_batch/{sequencing_depth β tools/sequencing_depth}/make_low_depth_h5ad.py +0 -0
- BioMod/zero_shot_batch/{sequencing_depth β tools/sequencing_depth}/run_zero_shot_low_depth.py +3 -3
- BioMod/zero_shot_batch/{visualize_results.py β tools/visualize_results.py} +0 -0
- BioMod/{toturials/zero_shot_batch_integration.ipynb β zero_shot_batch/tutorial.ipynb} +4 -4
- README.md +70 -53
- data/downstream/final_data/drug_combination_synergy/README.md +1 -1
- data/downstream/final_data/single_drug_response/README.md +1 -1
- {BioMod/cell_annotation/biomod_data β model_dependencies/biomod_data_sources}/biomod1_hallmarks.json +0 -0
- {BioMod/cell_annotation/biomod_data β model_dependencies/biomod_data_sources}/biomod2_reactome_2022_filtered.json +0 -0
- {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 |
-
|
| 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 |
-
```
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
βββ
|
| 39 |
-
β βββ README.md
|
| 40 |
-
β
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
β
|
| 44 |
-
βββ
|
| 45 |
-
β
|
| 46 |
-
|
| 47 |
-
β βββ
|
| 48 |
-
β βββ
|
| 49 |
-
β
|
| 50 |
-
|
| 51 |
-
β βββ
|
| 52 |
-
β βββ
|
| 53 |
-
β
|
| 54 |
-
βββ
|
| 55 |
-
β
|
| 56 |
-
βββ
|
| 57 |
-
β βββ
|
| 58 |
-
β βββ
|
| 59 |
-
β
|
| 60 |
-
β βββ
|
| 61 |
-
β
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
β
|
| 65 |
-
|
| 66 |
-
β
|
| 67 |
-
β βββ
|
| 68 |
-
β βββ
|
| 69 |
-
β
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
βββ .
|
| 73 |
-
βββ
|
| 74 |
-
|
| 75 |
-
βββ
|
| 76 |
-
βββ
|
| 77 |
-
βββ biomod.py
|
| 78 |
-
βββ
|
| 79 |
-
βββ
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
conda
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
```
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
$BIOMOD_ROOT/
|
| 159 |
-
βββ
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
βββ
|
| 164 |
-
β βββ
|
| 165 |
-
β βββ
|
| 166 |
-
β
|
| 167 |
-
|
| 168 |
-
β
|
| 169 |
-
βββ
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
`
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|--
|
| 232 |
-
|--
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
`
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
--
|
| 269 |
-
--
|
| 270 |
-
--
|
| 271 |
-
--
|
| 272 |
-
--
|
| 273 |
-
--
|
| 274 |
-
--
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
--
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
|
| 313 |
-
|
| 314 |
-
|
| 315 |
-
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
|
| 320 |
-
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
|
| 324 |
-
|
| 325 |
-
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
|
| 329 |
-
|
| 330 |
-
##
|
| 331 |
-
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
|
| 336 |
-
|
| 337 |
-
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
| 343 |
-
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 =
|
| 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
|
| 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 =
|
| 1310 |
-
labels = label_encoder.
|
| 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/
|
| 19 |
]
|
| 20 |
},
|
| 21 |
{
|
|
@@ -24,7 +24,7 @@
|
|
| 24 |
"source": [
|
| 25 |
"## Inputs and workflow\n",
|
| 26 |
"\n",
|
| 27 |
-
"- Entry point: `BioMod/cell_annotation/
|
| 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/
|
| 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' / '
|
| 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,
|
| 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 |
-
##
|
| 22 |
|
| 23 |
-
The
|
|
|
|
| 24 |
|
| 25 |
-
``
|
| 26 |
-
|
| 27 |
-
|
|
| 28 |
-
|
|
| 29 |
-
|
|
| 30 |
-
|
| 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.
|
| 36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
|
| 38 |
## Dependencies
|
| 39 |
|
|
@@ -44,66 +60,75 @@ used as the validation set for checkpoint selection.
|
|
| 44 |
- scikit-learn
|
| 45 |
- pandas, numpy
|
| 46 |
|
| 47 |
-
##
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
```bash
|
| 68 |
-
python BioMod/drug_combination/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
--checkpoint_path weight/BioMod.pth \
|
| 70 |
--hyper_params_path weight/BioMod.pkl \
|
| 71 |
--biomod_data_dir model_dependencies/biomod_data_all \
|
| 72 |
-
--
|
| 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 |
-
--
|
| 81 |
-
--
|
| 82 |
-
--pool_method max
|
| 83 |
```
|
| 84 |
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
|
| 87 |
-
|
|
|
|
|
|
|
| 88 |
|
| 89 |
-
|
| 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 |
-
|
|
|
|
|
|
|
| 98 |
|
| 99 |
```bash
|
| 100 |
-
python BioMod/drug_combination/
|
|
|
|
| 101 |
--checkpoint_path weight/BioMod.pth \
|
| 102 |
--hyper_params_path weight/BioMod.pkl \
|
| 103 |
--biomod_data_dir model_dependencies/biomod_data_all \
|
| 104 |
-
--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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/
|
| 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/
|
| 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/
|
| 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/
|
| 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/
|
| 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 / '
|
| 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/
|
| 14 |
-
python BioMod/drug_response/
|
| 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 `
|
| 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/
|
| 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/
|
| 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/
|
| 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/
|
| 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 / '
|
| 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` (`
|
| 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` (`
|
| 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 (`
|
| 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
-
|
|
|
|
|
|
|
|
|
|
| 68 |
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
- Gene mapping file, such as `gene2ens.csv`.
|
| 73 |
|
| 74 |
-
### 2. Run
|
| 75 |
|
| 76 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
|
| 78 |
```bash
|
| 79 |
-
|
| 80 |
-
|
| 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 |
-
--
|
| 91 |
-
--
|
|
|
|
| 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
|
|
|
|
| 137 |
|
| 138 |
-
|
| 139 |
-
|
| 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/
|
| 193 |
-
βββ
|
| 194 |
-
βββ
|
| 195 |
-
βββ
|
| 196 |
-
βββ
|
| 197 |
-
βββ
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
βββ README.md
|
| 199 |
-
βββ
|
| 200 |
-
|
| 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 |
-
|
| 236 |
-
|
| 237 |
-
|
| 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 |
-
``
|
| 250 |
-
|
| 251 |
-
|
| 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 (
|
| 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 (
|
| 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
|
| 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 (
|
| 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 (
|
| 4 |
================================================================================
|
| 5 |
|
| 6 |
[Model Architecture Overview]
|
|
@@ -55,7 +55,7 @@
|
|
| 55 |
sanitize_biomod_config,
|
| 56 |
)
|
| 57 |
except ModuleNotFoundError:
|
| 58 |
-
project_root =
|
| 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[
|
| 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 (
|
| 4 |
================================================================================
|
| 5 |
|
| 6 |
[Module function]
|
|
@@ -46,14 +46,14 @@
|
|
| 46 |
# ============================================================
|
| 47 |
# Use native modules (optimized versions)
|
| 48 |
# ============================================================
|
| 49 |
-
from
|
| 50 |
-
from
|
| 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
|
| 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 (
|
| 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 (
|
| 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 |
-
|
| 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.
|
| 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
|
| 86 |
-
from utils import print_sys
|
| 87 |
-
from
|
| 88 |
|
| 89 |
# Import module model
|
| 90 |
-
from
|
| 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/
|
| 19 |
]
|
| 20 |
},
|
| 21 |
{
|
|
@@ -24,7 +24,7 @@
|
|
| 24 |
"source": [
|
| 25 |
"## Inputs and workflow\n",
|
| 26 |
"\n",
|
| 27 |
-
"- Entry point: `BioMod/gene_perturbation/
|
| 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/
|
| 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 / '
|
| 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 |
-
"`
|
| 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 |
-
##
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
|
| 19 |
```bash
|
| 20 |
-
python BioMod/zero_shot_batch/
|
| 21 |
-
--
|
| 22 |
-
--
|
| 23 |
-
--
|
| 24 |
-
--
|
| 25 |
-
--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
```
|
| 27 |
|
| 28 |
-
###
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
|
| 30 |
```bash
|
| 31 |
-
python BioMod/zero_shot_batch/
|
| 32 |
-
--
|
| 33 |
-
--
|
| 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 |
-
--
|
| 39 |
-
--
|
| 40 |
-
--
|
| 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/
|
| 50 |
-
--
|
| 51 |
-
--
|
| 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 |
-
--
|
| 57 |
-
--
|
| 58 |
-
--
|
| 59 |
-
--batch_size 128 \
|
| 60 |
-
--metrics_mode scgpt \
|
| 61 |
-
--output_dir tutorial_runs/zero_shot_max \
|
| 62 |
-
--pool_method max
|
| 63 |
```
|
| 64 |
|
| 65 |
-
###
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
| 85 |
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 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 |
-
|
| 138 |
|
| 139 |
-
|
| 140 |
|
| 141 |
-
|
|
|
|
|
|
|
|
|
|
| 142 |
|
| 143 |
-
|
| 144 |
|
| 145 |
-
|
|
|
|
| 146 |
|
| 147 |
-
**
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
|
| 149 |
-
|
| 150 |
-
|
|
|
|
|
|
|
|
|
|
| 151 |
|
| 152 |
-
##
|
| 153 |
|
| 154 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
|
| 156 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 157 |
|
| 158 |
-
|
| 159 |
-
|
|
|
|
|
|
|
|
|
| 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 |
-
#
|
| 2 |
-
|
| 3 |
-
--
|
| 4 |
-
-
|
| 5 |
-
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
-
|
| 13 |
-
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
data/downstream/final_data/Kim2020_Lung.h5ad \
|
| 28 |
-
tutorial_runs/sequencing_depth/inputs
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
--
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
--
|
| 41 |
-
--
|
| 42 |
-
--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 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[
|
| 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().
|
| 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/
|
| 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: `.
|
| 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/
|
| 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' / '
|
| 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/
|
| 85 |
-
| Zero-shot cell embeddings and batch-effect evaluation | [Embedding and evaluation script](BioMod/zero_shot_batch/
|
| 86 |
-
| Single-drug response regression (IC50) | [Training script](BioMod/drug_response/
|
| 87 |
-
| Drug-pair synergy classification | [Training script](BioMod/drug_combination/
|
| 88 |
-
| Gene perturbation response prediction | [Training script](BioMod/gene_perturbation/
|
| 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 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
|
|
|
|
|
|
| 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/
|
| 174 |
-
βββ BioMod/
|
| 175 |
-
β βββ cell_annotation/
|
| 176 |
-
β β βββ
|
| 177 |
-
β β
|
| 178 |
-
β β
|
| 179 |
-
β
|
| 180 |
-
β β βββ cmd_finetune.md
|
| 181 |
-
β β βββ biomod_finetune.py
|
| 182 |
-
β βββ drug_combination/ # Drug-combination synergy prediction
|
| 183 |
β β βββ README.md
|
| 184 |
-
β β
|
| 185 |
-
β
|
| 186 |
-
β
|
| 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 |
-
β β βββ
|
| 196 |
-
β β
|
| 197 |
-
β
|
| 198 |
-
β βββ
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
β β βββ test_training_utils.py
|
| 200 |
-
β βββ
|
| 201 |
-
β β βββ
|
| 202 |
-
β β βββ
|
| 203 |
-
β β βββ
|
| 204 |
-
β β βββ
|
| 205 |
-
β β βββ
|
| 206 |
-
β
|
| 207 |
-
β β βββ
|
| 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 |
-
β β βββ
|
| 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/
|
| 226 |
-
β βββ biomod_data_all/
|
| 227 |
β β βββ create_uncovered_biomods.py
|
| 228 |
β β βββ merge_biomods.py
|
| 229 |
β β βββ merged_biomods.json
|
| 230 |
-
β βββ
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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/
|
| 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/
|
| 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/
|
| 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
|