This repo contains a PyTorch implementation for the paper "Designing DNA With Tunable Regulatory Activity Using Discrete Diffusion". The training and sampling part of the code is inspired by Score entropy discrete diffusion.
D3-DNA-Discrete-Diffusion/
βββ scripts/ # Base classes + entry-point scripts
β βββ train.py # Base training (PyTorch Lightning)
β βββ evaluate.py # Base evaluation with common metrics
β βββ sample.py # Base sampling (Predictor-Corrector)
β βββ sampling.py # Predictor / Denoiser implementations
β βββ deepstarr_attributions_template.py # Oracle-check + DeepLIFT-SHAP template
β βββ shuffled_evaluations.py # Dinuc-shuffle baseline evaluations
βββ model_zoo/ # Dataset-specific implementations
β βββ deepstarr/ # DeepSTARR enhancers (249 bp)
β βββ lentimpra/ # LentiMPRA K562/HepG2/WTC11 (230 bp)
β βββ mpra/ # MPRA (200 bp)
β βββ promoter/ # Promoter w/ expression (1024 bp)
β βββ atacseq/ # ATAC-seq
β βββ ccre/ # cCRE
βββ utils/ # Shared utilities
β βββ data_utils.py # cycle_loader, one-hot, reverse-complement, ...
β βββ graph_lib.py # Discrete diffusion graphs (Uniform / Absorbing)
β βββ noise_lib.py # GeometricNoise schedule
β βββ losses.py # Score-entropy loss, optimizer setup
β βββ inpainting.py # InpaintingManager for constrained generation
β βββ dinuc_shuffle.py # Dinucleotide-preserving shuffle
β βββ sp_mse_callback.py # Base oracle-based validation callback
β βββ catsample.py # Categorical Gumbel sampling
βββ model/ # Pure architectures (dataset-agnostic)
β βββ transformer.py # Transformer w/ rotary + flash-attn
β βββ cnn.py # Convolutional w/ dilated convs
β βββ rotary.py # Rotary embeddings
β βββ layers.py # TimestepEmbedder, LabelEmbedder, ...
βββ environment_new.yml # Conda environment (`d3-new`)
βββ post_install.sh # Pip steps yml can't express (torch cu121, flash-attn, -e install)
βββ setup_new.sh # Wrapper that runs the two steps above
βββ pyproject.toml # Package configuration
The environment is split between a conda yml (system + pure-pip packages) and a tiny post-install script (the things yml can't express: torch from the cu121 index URL, flash-attn with --no-build-isolation, and the editable install of this repo):
git clone https://github.com/anirbansarkar-cs/D3-DNA-Discrete-Diffusion.git
cd D3-DNA-Discrete-Diffusion
conda env create -f environment_new.yml -n d3-new
conda activate d3-new
bash post_install.shsetup_new.sh wraps all three steps if you'd rather run a single command.
After install, d3-new includes:
- PyTorch 2.5.1 (cu121 wheels, ships its own CUDA 12 runtime), flash-attn 2.7.4.post1 (prebuilt wheel β no source build)
- PyTorch Lightning, einops, h5py, omegaconf, wandb, matplotlib, seaborn, scikit-learn
- evoaug2 (data augmentation:
RobustLoader,RandomRC,RandomMutation, ...) - fsspec / pyfaidx / s3fs (for S3 FASTA access in the cCRE benchmark)
The attribution template depends on a TangerMeme fix that's currently an open PR upstream. Install from the PR branch until it lands:
pip install -e ~/tangermeme-worktrees/add-hook-stacks# Train DeepSTARR with transformer
python model_zoo/deepstarr/train.py --architecture transformer
# Train LentiMPRA with convolutional architecture
python model_zoo/lentimpra/train.py --architecture convolutional
# Train Promoter with custom config
python model_zoo/promoter/train.py --architecture transformer --config custom.yaml
# Multi-GPU (4 GPUs)
python model_zoo/deepstarr/train.py --architecture transformer --ngpus 4
# Resume from checkpoint
python model_zoo/deepstarr/train.py --architecture transformer --resume /path/to/checkpoint.ckpt# Diffusion metrics only
python model_zoo/deepstarr/evaluate.py --architecture transformer --checkpoint model.ckpt
# With oracle (SP-MSE)
python model_zoo/deepstarr/evaluate.py --architecture transformer \
--checkpoint model.ckpt --use_oracle --oracle_checkpoint oracle.ckptThe base scripts/sample.py defines all shared CLI args (--checkpoint, --architecture, --num_samples, --steps, --batch_size, --output, --format, --initial_condition, --start_at_timestep, --inpainting_*, --use_wandb, ...). Each dataset's model_zoo/<dataset>/sample.py adds its own conditioning args.
# Unconditional DeepSTARR
python model_zoo/deepstarr/sample.py \
--architecture transformer --checkpoint model.ckpt \
--num_samples 1000 --unconditional
# DeepSTARR conditioned on dev + hk activities
python model_zoo/deepstarr/sample.py \
--architecture transformer --checkpoint model.ckpt \
--num_samples 1000 --dev_activity 2.0 --hk_activity 1.5
# LentiMPRA single-cell-line (K562)
python model_zoo/lentimpra/sample.py \
--architecture transformer --checkpoint model.ckpt \
--num_samples 1000 --activity 1.5
# LentiMPRA multi-class (K562 / HepG2 / WTC11)
python model_zoo/lentimpra/sample.py \
--architecture transformer --checkpoint model.ckpt \
--num_samples 1000 --k562_activity 2.0 --hepg2_activity 1.0 --wtc11_activity 0.5
# Promoter conditioned on expression
python model_zoo/promoter/sample.py \
--architecture transformer --checkpoint model.ckpt \
--num_samples 1000 --expression_target 3.0python model_zoo/deepstarr/sample.py \
--architecture transformer --checkpoint model.ckpt \
--num_samples 1000 --dev_activity 2.0 --hk_activity 1.5 \
--use_wandb --wandb_project d3-deepstarr-sampling --wandb_name dev2.0-hk1.5# Start from a custom set of sequences in an H5 file, beginning at timestep 25
python model_zoo/lentimpra/sample.py \
--architecture transformer --checkpoint model.ckpt \
--num_samples 1000 --activity 1.5 \
--custom_inits_path /path/to/seed_seqs.h5 --custom_inits_step 25
# Initialize from nucleotide frequencies and start the reverse process at timestep 10
python model_zoo/deepstarr/sample.py \
--architecture transformer --checkpoint model.ckpt \
--num_samples 1000 --unconditional \
--initial_condition nuc_freq --start_at_timestep 10utils/inpainting.py implements an InpaintingManager that constrains the reverse-diffusion process. Run sampling with --inpainting_mode {inpaint_motifs, inpaint_not_motifs} and an H5 of pre-extracted motif spans:
# Keep motif spans fixed, regenerate flanks
python model_zoo/deepstarr/sample.py \
--architecture transformer --checkpoint model.ckpt \
--num_samples 100 --dev_activity 2.0 --hk_activity 1.5 \
--inpainting_mode inpaint_motifs \
--inpainting_data inpainting_data/all_hits_combined.h5 \
--inpainting_iterations 5
# Inverse: keep flanks, regenerate motif spans
python model_zoo/deepstarr/sample.py \
--architecture transformer --checkpoint model.ckpt \
--num_samples 100 --dev_activity 2.0 --hk_activity 1.5 \
--inpainting_mode inpaint_not_motifs \
--inpainting_data inpainting_data/all_hits_combined.h5scripts/deepstarr_attributions_template.py is a template script with two sub-commands. The attributions subcommand requires the TangerMeme PR fix (see Installation, above).
# Sanity-check the oracle on originals vs dinuc-shuffled motif/flank segments
python scripts/deepstarr_attributions_template.py oracle-check \
--data_path samples.h5 --ckpt_path oracle.ckpt --mode motif
# DeepLIFT-SHAP attributions for dev + hk heads, per-timestep
python scripts/deepstarr_attributions_template.py attributions \
--h5-samples samples.h5 --h5-config config.h5 \
--deepstarr-ckpt oracle.ckpt --output-file attributions.h5- Purpose: Enhancer activity prediction
- Sequence Length: 249 bp
- Labels: 2 (developmental + housekeeping enhancer activities)
- Oracle:
PL_DeepSTARRconvolutional predictor for SP-MSE
- Purpose: Regulatory activity in lentiviral MPRA across cell lines
- Sequence Length: 230 bp
- Labels: 1 (K562) or 3 (K562 + HepG2 + WTC11)
- Oracle: LegNet (
model_zoo/lentimpra/mpralegnet.py)
- Purpose: Regulatory sequence analysis
- Sequence Length: 200 bp
- Labels: 3 (regulatory activity measurements)
- Oracle:
PL_mprapredictor for SP-MSE
- Purpose: Gene expression prediction
- Sequence Length: 1024 bp
- Labels: Expression values (concatenated with sequences)
- Oracle: SEI (Sequence-to-Expression and Interaction) model
- Purpose: Chromatin-accessibility-derived regulatory sequence modeling
- Available in
model_zoo/atacseq/(train/evaluate/sample)
- Purpose: Candidate cis-Regulatory Element modeling
- Available in
model_zoo/ccre/(train/evaluate/sample);traitgym_benchmark.pyfor downstream TraitGym evaluation
- Multi-head attention with rotary positional embeddings
- Flash-attention (flash-attn 2.7.x) for fixed-length sequences
- Layer normalization, AdaLN time-modulation, residual connections
- Conditional generation via additive label embeddings
- Configurable depth (
n_blocks) and width (hidden_size)
- Multi-scale convolutional layers with dilated convolutions (
[1,1,4,16,64]Γ4) - Group normalization, residual connections
- Adaptive pooling for variable-length inputs
- Conditional generation via concatenated label features
- Predictor-Corrector with
EulerPredictor,AnalyticPredictor(Tweedie's formula), and a finalDenoiserat t=0 β seescripts/sampling.py. - Conditional generation via global label conditioning (additive on transformer, concatenative on CNN).
- Custom initial conditions: load arbitrary starting sequences (
--custom_inits_path), or initialize from nucleotide frequencies (--initial_condition nuc_freq). - Delayed sampling: start the reverse process partway through (
--start_at_timestep N). - Motif inpainting:
--inpainting_mode inpaint_motifs/inpaint_not_motifswith an H5 of motif spans. - WandB logging at sampling time (sequences, oracle activities, artifacts) via
--use_wandb.
Evaluate biological relevance during training using oracle models:
# In dataset config
sp_mse_validation:
enabled: true
validation_freq: 5000
validation_samples: 1000
early_stopping_patience: 3ngpus: 4
nnodes: 1
training:
batch_size: 1024
accum: 1The modular architecture makes adding datasets simple:
-
Create dataset directory:
mkdir model_zoo/my_dataset
-
Implement required files:
# model_zoo/my_dataset/data.py def get_my_dataset_datasets(): # Dataset loading logic pass # model_zoo/my_dataset/models.py def create_model(config, architecture): # Model creation logic pass
-
Create training script:
# model_zoo/my_dataset/train.py from scripts.train import BaseTrainer class MyDatasetTrainer(BaseTrainer): # Inherit shared functionality pass
-
Add configs: Place YAML files in
model_zoo/my_dataset/configs/
That's it! No changes to core codebase needed.
Each dataset has architecture-specific configs:
# model_zoo/deepstarr/configs/transformer.yaml
dataset:
name: deepstarr
data_file: model_zoo/deepstarr/DeepSTARR_data.h5
sequence_length: 249
model:
architecture: transformer
hidden_size: 768
n_blocks: 12
n_heads: 12
training:
batch_size: 256
n_iters: 1000000
lr: 0.0003Our models achieve state-of-the-art performance:
- DeepSTARR: High correlation with enhancer activities
- MPRA / LentiMPRA: Accurate regulatory predictions
- Promoter: Precise expression control
Evaluation metrics include:
- SP-MSE (oracle-based biological relevance)
- Standard diffusion metrics (loss, perplexity)
- Dataset-specific biological metrics
- Base classes provide shared functionality
- Dataset-specific classes inherit and customize
- No hardcoded dataset logic in shared components
- Configuration-driven behavior
- Clean separation of concerns
- Fully type-hinted Python
- Comprehensive docstrings
- Modular, testable design
- Professional packaging with
pyproject.toml
- DeepSTARR Transformer
- DeepSTARR Convolutional
- MPRA Transformer
- MPRA Convolutional
- Promoter Transformer
- Promoter Convolutional
@article{sarkar2024d3dna,
title = {Designing {DNA} With Tunable Regulatory Activity Using Discrete Diffusion},
author = {Sarkar, Anirban and Duran, Alejandra and Yu, Yiyang and Lin, Da-Wei and Kang, Yijie and Somia, Nirali and Mantilla, Pablo and Zhou, Jessica and Nagai, Masayuki and Tang, Ziqi and Hanington, Kaarina and Chang, Kenneth and Koo, Peter K.},
journal = {bioRxiv},
year = {2024},
doi = {10.1101/2024.05.23.595630},
url = {https://www.biorxiv.org/content/10.1101/2024.05.23.595630v3},
publisher = {Cold Spring Harbor Laboratory},
note = {Preprint, version 3}
}MIT License - see LICENSE file for details.