Authors
- Boyang Fu
- Sameer Gabbita
- George Dasoulas
- Xiang Lin
- Shanghua Gao
- Xiaorui Su
- Soumya Ghosh
- Marinka Zitnik
Advances in Neural Information Processing Systems (NeurIPS), 2026
STRAND predicts single-cell transcriptional responses by conditioning on the regulatory DNA sequence at the perturbed locus rather than on a gene identifier, so perturbations that target different genomic sites within the same gene can receive different predicted responses.
Most single-cell perturbation models represent a perturbation as a discrete gene identifier or a node in a gene graph, which collapses every targeted site inside a gene into one representation and closes the perturbation vocabulary to annotated genes. STRAND instead takes a reference DNA window and a perturbation mask at a user-specified locus, so the perturbation is defined by sequence and position. This supports zero-shot inference at targets unseen during training and locus-resolved inputs across a 524 kb window at 128 bp model resolution.
Figure 1. Perturbations targeting the same gene at different genomic locations (sp1, sp2) can induce distinct transcriptional responses.
Regulatory DNA and a target mask enter a frozen DNA foundation model; a learnable DNA Perturbation Module turns the masked sequence context into a perturbation condition; a control-anchored latent transport module carries the control cell state to the perturbed state under that condition; and a residual hurdle decoder predicts perturbed expression relative to a reconstructed control baseline.
Figure 2. The frozen encoders are Borzoi (DNA, 128 bp output bins over a 524 kb window) and SCimilarity (RNA). The learnable components are the DNA Perturbation Module gφ, the Cellular Transport Module eθ (a control-anchored I²SB bridge), and the gene-level decoder. An auxiliary sequence–expression alignment objective links the DNA condition to the mean transcriptional effect.
git clone https://github.com/mims-harvard/STRAND.git && cd STRAND
pip install -r requirements.txtRequires Python ≥ 3.10 (tested: Python 3.11, PyTorch 2.9.0). Run commands from the repository
root; tests: python -m pytest tests.
Point the pipeline at the reference genome, the annotation and your data roots:
export DATA_ROOT="/path/to/data_root" # curated .h5ad + embeddings
export OUTPUT_ROOT="/path/to/outputs" # checkpoints + DNA cache
export DNA_REFERENCE_PATH="/path/to/hg38_fasta_dir" # per-chromosome FASTA (GRCh38)
export GENE_ANNOTATION_PATH="/path/to/gencode.v47.transcript.annotation.gtf"
export HGNC_COMPLETE_SET_PATH="/path/to/hgnc_complete_set.txt" # gene symbol -> Ensembl ID
export CCRE_BED_PATH="/path/to/ENCFF234XEZ.bed.gz" # ENCODE cCREs (cCRE bias)
export DNA_CACHE_DIR="$OUTPUT_ROOT/dna_cache" # DNA embeddings, built in step 02, read by steps 04-05Train a per-cell-line model with the configuration used in the paper (after data steps 01–03 below):
bash scripts/04_train/train.sh k562 # k562 | jurkat | rpe1 | combined_perturbqa_hvg2kPredict the test split with a trained checkpoint (writes paired predicted / measured .h5ad files):
python scripts/05_evaluate/evaluate.py \
--config configs/k562_config.yaml --dname k562 \
--checkpoint_path /path/to/best_model.pt \
--result_path outputs/k562_evalInspect or build a sequence-defined perturbation directly. strand.locus needs only NumPy, and
reproduces the coordinate and mask construction the model uses at inference:
from strand import Locus, masked_tokens
locus = Locus.centered("chrX", 48_786_590, half_width=200, tag="GATA1", dataset="k562")
print(locus.label) # chrX:48786390-48786790(+)-GATA1-k562
print(masked_tokens(locus, 156_040_895)) # DNA context tokens selected by the maskstrand.STRAND.from_checkpoint(...) loads a trained checkpoint and exposes predict and scan
for single loci and sliding-window scans; see docs below for
the model dependencies this requires.
The pipeline runs in numbered order:
| Step | What it does | Where |
|---|---|---|
| 01 | Curate the PerturbQA screens into per-cell-line .h5ad files |
scripts/01_curate/ |
| 02 | SCimilarity embeddings and OT pairing of control and perturbed cells (the split column chosen here sets zero-shot or few-shot); Borzoi DNA embedding cache | scripts/02_embed_and_match/ |
| 03 | Train/validation split of the OT training pairs | scripts/03_make_splits/ |
| 04 | Train STRAND | scripts/04_train/ |
| 05 | Predict the test split with a trained checkpoint | scripts/05_evaluate/ |
| Also | Where |
|---|---|
| Datasets, sources and the perturbation-coordinate protocol | docs/data.md |
| Training configurations (one per cell line, plus Combined) | configs/ |
| STRAND model (paper Fig. 2) and the two Fig. 4 ablations | src/diffusion_ot/models/ |
| DNA Perturbation Module over the Borzoi backbone | PModule/DNA_modeling.py |
| Baselines (GEARS, BioLord, STATE, STACK) | benchmark/ |
Perturbation coordinates. Public CRISPRi datasets carry gene-level labels rather than exact
guide coordinates, so the default benchmark uses a TSS-centered proxy: gene symbols are resolved to
Ensembl IDs, a canonical transcript is chosen by tag priority, and a ±200 bp mask is placed on the
TSS inside a 524 kb window. Exact guide coordinates can be supplied when available; the paper
reports a sensitivity analysis comparing the two. docs/data.md documents the full procedure.
External dependencies. Not bundled here: the Borzoi/Flashzoi DNA backbone (borzoi-pytorch), the SCimilarity RNA encoder (Genentech/scimilarity), the HiRef optimal-transport solver (raphael-group/HiRef) and the GRCh38 reference with GENCODE annotation.
Scope. Training and evaluation use CRISPRi data in K562, Jurkat and RPE1. HCT116 appears only as an external cross-study transfer evaluation and is not part of the training data. STRAND operates at 128 bp model resolution, set by the DNA encoder's output binning.
@inproceedings{fu2026strand,
title = {{STRAND}: Sequence-Conditioned Transport for Single-Cell Perturbations},
author = {Fu, Boyang and Gabbita, Sameer and Dasoulas, George and Lin, Xiang and
Gao, Shanghua and Su, Xiaorui and Ghosh, Soumya and Zitnik, Marinka},
booktitle = {Advances in Neural Information Processing Systems},
year = {2026}
}Questions: please open an issue in this repository or contact marinka@hms.harvard.edu.

