| --- |
| license: apache-2.0 |
| tags: |
| - biology |
| - diffusion |
| - single-cell |
| - transcriptomics |
| - microscopy |
| - image-to-rna |
| - conditional-generation |
| - scgpt |
| - vit |
| datasets: |
| - altoslabs/scGeneScope |
| pipeline_tag: feature-extraction |
| model-index: |
| - name: PhenoSeq |
| results: |
| - task: |
| type: feature-extraction |
| name: Image-conditioned RNA-seq generation |
| metrics: |
| - type: loss |
| value: 0.1683 |
| name: Validation MSE Loss (epoch 87) |
| --- |
| |
| # PhenoSeq: Image-Conditioned Diffusion for Single-Cell Transcriptomics |
|
|
| [](https://huggingface.co/Sentinal4D/PhenoSeq) |
| [](https://openreview.net/forum?id=ACHMa1e8J1) |
| [](https://github.com/reednaidoo/PhenoSeq) |
|
|
| PhenoSeq is a Gaussian diffusion model that **generates scGPT RNA-seq embeddings conditioned on ViT-L microscopy imaging features**. Given fluorescence microscopy images of a cell or well, it predicts a 512-dimensional scGPT embedding representing the transcriptomic state of individual cells β enabling image-to-transcriptome translation at single-cell resolution. |
|
|
| ## Model summary |
|
|
| | Property | Value | |
| |---|---| |
| | Input | ViT-L imaging features β `(N, 5120)` per sample (5 fluorescence channels Γ 1,024 dims) | |
| | Output | scGPT embeddings β `(n_cells, 512)` | |
| | Architecture | Cross-attention diffusion denoiser | |
| | Diffusion steps | 1,000 (cosine schedule) | |
| | Inference steps | 50 (DDIM, default) | |
| | Model parameters | ~168 M | |
| | Training dataset | [scGeneScope](https://huggingface.co/datasets/altoslabs/scGeneScope) | |
| | Best val MSE loss | 0.1683 (epoch 87) | |
|
|
| ## Architecture |
|
|
| The denoiser uses a **cross-attention transformer** stack: |
|
|
| 1. **Imaging encoder** β 2-layer self-attention transformer projects `(B, N, 5120)` β `(B, N, 1024)` context. |
| 2. **RNA + time input** β noisy scGPT embedding and sinusoidal time embedding are projected to `model_dim`. |
| 3. **Cross-attention blocks** (Γ6) β RNA queries attend to imaging context, with self-attention and adaptive layer normalization conditioned on the timestep. |
| 4. **Output projection** β predicts noise `Ξ΅ β β^{512}` for the denoising objective. |
|
|
| The diffusion process uses a cosine beta schedule over T=1,000 steps with EMA weight averaging (decay 0.9999). |
|
|
| ## Quick start |
|
|
| ```bash |
| pip install torch numpy huggingface_hub |
| python example.py |
| ``` |
|
|
| ```python |
| import numpy as np |
| from pipeline import PhenoSeqPipeline |
| |
| pipe = PhenoSeqPipeline.from_pretrained("Sentinal4D/PhenoSeq") |
| |
| # img_features: ViT-L embeddings β (n_cells, n_imaging_cells=16, 5120) |
| img_features = np.random.randn(8, 16, 5120).astype(np.float32) |
| rna_predictions = pipe(img_features) # β (8, 512) |
| ``` |
|
|
| ## Inputs and outputs |
|
|
| ### Input: imaging features |
|
|
| `img_features` must be ViT-L image embeddings extracted from **5 fluorescence channels** using a ViT-L/14 backbone, resulting in 5 Γ 1,024 = 5,120 dimensions per imaging cell. Each sample/well typically provides **N = 16** imaging cells (evenly spaced from the available pool) that form the conditioning context. |
|
|
| Shape: `(B, N, 5120)` where `B` is the number of target RNA cells to predict. |
|
|
| > **Imaging normalisation** β `img_norm.npz` contains the per-feature mean and std computed from the training split of scGeneScope. These are applied automatically by `PhenoSeqPipeline`. If you work with a different dataset you will need to recompute and supply your own normalisation stats. |
| |
| ### Output: RNA embeddings |
| |
| Shape: `(B, 512)` β scGPT-space embeddings un-normalized back to the original scGPT embedding scale. These can be used directly for downstream tasks such as cell-type classification (see `classify_improved.py`), clustering, or trajectory inference. |
|
|
| ## Imaging normalisation stats |
|
|
| The pipeline requires `img_norm.npz` (per-feature mean and std from the training split). This file is distributed alongside `best_model.pt` in this repo. If you retrain or use different data, regenerate it: |
|
|
| ```bash |
| python save_img_norm.py --config config.yaml --output img_norm.npz |
| ``` |
|
|
| ## Full inference on scGeneScope data |
|
|
| For large-scale inference over the cached scGeneScope data (`.npz` per sample): |
|
|
| ```bash |
| # Fast (DDIM, 50 steps) |
| python infer.py --checkpoint best_model.pt --ddim_steps 50 |
| |
| # Val split only |
| python infer.py --checkpoint best_model.pt --split val --output_dir results/predictions |
| |
| # Full DDPM sampling (slower, ~1000 steps) |
| python infer.py --checkpoint best_model.pt --ddim_steps 0 |
| ``` |
|
|
| Output: one `{Sample_ID}.npz` per sample under `results/predictions/`, with key `X` of shape `(n_cells, 512)`. |
|
|
| ## Downstream: cell-type classification |
|
|
| Predicted RNA embeddings can be evaluated with the included classifier: |
|
|
| ```bash |
| python classify_improved.py |
| ``` |
|
|
|
|
| ## Training |
|
|
| The model was trained from scratch on scGeneScope using: |
|
|
| ```bash |
| python train.py --config config.yaml |
| ``` |
|
|
| ## Data |
|
|
| Training and evaluation data come from the [scGeneScope](https://huggingface.co/datasets/altoslabs/scGeneScope) dataset (Altos Labs): |
|
|
| - **Imaging features**: ViT-L/14 embeddings extracted from 5-channel fluorescence microscopy images, stored as `.h5ad` files. |
| - **RNA-seq features**: scGPT cell embeddings (512-dim) from paired single-cell RNA-seq, stored as `.h5ad` files. |
| - Samples are matched by `Sample_ID` at well level. |
|
|
| Prepare the local cache before training: |
|
|
| ```bash |
| python prepare_data.py |
| ``` |
|
|
| ## Repository structure |
|
|
| ``` |
| PhenoSeq/ |
| βββ pipeline.py β self-contained inference pipeline (start here) |
| βββ best_model.pt β trained checkpoint with EMA weights & RNA norm stats |
| βββ img_norm.npz β imaging normalisation stats (mean/std, training split) |
| βββ config.yaml β full training configuration |
| βββ infer.py β batch inference over cached scGeneScope data |
| βββ save_img_norm.py β helper to (re)generate img_norm.npz |
| βββ train.py β training entry point |
| βββ prepare_data.py β extract imaging/RNA features β .npz cache |
| βββ models/ |
| β βββ denoiser.py β cross-attention denoiser |
| β βββ diffusion.py β Gaussian diffusion process (forward + reverse) |
| β βββ lit_module.py β PyTorch Lightning training wrapper |
| βββ data/ |
| βββ dataset.py β paired imaging-RNA dataset & dataloader |
| ``` |
|
|
| ## Requirements |
|
|
| ``` |
| torch>=2.0 |
| anndata>=0.10 |
| numpy>=1.24 |
| scipy>=1.10 |
| PyYAML>=6.0 |
| tqdm>=4.65 |
| # Optional: huggingface_hub (for from_pretrained with a Hub repo id) |
| ``` |
|
|
| Install: |
| ```bash |
| pip install -r requirements.txt |
| ``` |
|
|
| ## License |
|
|
| Apache 2.0 β see [LICENSE](LICENSE). |
|
|
| ## Citation |
|
|
| If you use PhenoSeq, please cite our paper: |
|
|
| ```bibtex |
| @inproceedings{naidoo2026phenoseq, |
| title = {Cell Painting Generates Single-Cell Transcriptomics via Conditional Diffusion}, |
| author = {Naidoo, Reed and Hu, Jingyu and Tripodi, Giuseppe and Bakal, Chris and Chakraborti, Tapabrata}, |
| booktitle = {ICML 2026 Workshop on Multi-modal Foundation Models and Large Language Models for Life Sciences (FM4LS)}, |
| year = {2026}, |
| url = {https://openreview.net/forum?id=ACHMa1e8J1} |
| } |
| ``` |
|
|
| Please also cite the training dataset: |
|
|
| ```bibtex |
| @dataset{scgenescope, |
| author = {Altos Labs}, |
| title = {scGeneScope}, |
| year = {2024}, |
| publisher = {HuggingFace}, |
| url = {https://huggingface.co/datasets/altoslabs/scGeneScope} |
| } |
| ``` |
|
|