Foundation Model Encoders
manylatents-omics provides pretrained foundation model encoders for biological sequences. All encoders inherit from FoundationEncoder, which provides lazy model loading, batched encoding with automatic OOM retry, and a standard fit/transform interface compatible with the manylatents experiment pipeline.
Encoder Summary
| Encoder | Domain | Embedding Dim | VRAM | Architecture |
|---|---|---|---|---|
| ESM3 | Protein | 1536 | 16 GB+ | Transformer (1.4B params) |
| Evo2 | DNA | 1920 / 4096 / 8192 | 24 GB+ (Ampere+) | StripedHyena 2 (1B/7B/40B) |
| Orthrus | RNA | 256 / 512 | 8 GB+ | Mamba SSM |
| AlphaGenome | DNA | 1536 / 3072 | 40 GB+ | JAX-based (DeepMind) |
ESM3
Domain: Protein sequences (amino acids)
ESM3 is a frontier multimodal protein model from EvolutionaryScale that jointly reasons across sequence, structure, and function. The open model (esm3-sm-open-v1) has 1.4 billion parameters.
- Embedding dimension: 1536
- VRAM: 16 GB+
- Pooling: Masked mean pooling over sequence length
- Batched inference: True GPU batching with tokenizer padding
Key features:
- True batched forward pass (single GPU kernel per micro-batch)
- Automatic sequence truncation via
max_length - Loads from HuggingFace or local weights
from manylatents.dogma.encoders.esm3 import ESM3Encoder
encoder = ESM3Encoder(max_length=2000)
embedding = encoder.encode("MKFGVRA") # (1, 1536)
Reference: Hayes et al. (2024) "Simulating 500 million years of evolution with a language model"
Evo2
Domain: DNA sequences (nucleotides)
Evo2 is a DNA language model using the StripedHyena 2 architecture, modeling DNA at single-nucleotide resolution with up to 1 million base pair context length. Available in 1B, 7B, and 40B parameter variants.
- Embedding dimensions: 1920 (1B), 4096 (7B), 8192 (40B)
- VRAM: 24 GB+ (requires Ampere or newer GPU)
- Pooling: Masked mean pooling over sequence length
- Multi-layer extraction: Extracts from multiple internal layers simultaneously
Key features:
- Multi-layer embedding extraction (default: 3 layers at 56%, 76%, 92% depth for 1B)
- Returns
dict[str, Tensor]when multi-layer mode is active - True batched forward pass with tokenizer padding
- OOM retry with automatic batch size halving
| Model | Parameters | Hidden Dim | Default Layers |
|---|---|---|---|
evo2_1b_base |
1B | 1920 | blocks.14, blocks.19, blocks.23 |
evo2_7b |
7B | 4096 | blocks.16 |
evo2_40b |
40B | 8192 | blocks.32 |
from manylatents.dogma.encoders.evo2 import Evo2Encoder
encoder = Evo2Encoder(model_name="evo2_1b_base")
result = encoder.encode("ATGAAGTTTGGCGTCCGTGCCTGA")
# Multi-layer default: result is dict with 3 layer keys
Reference: Nguyen et al. (2025) "Genome modeling and design across all domains of life with Evo 2"
Orthrus
Domain: RNA sequences (nucleotides)
Orthrus is a Mamba SSM-based RNA foundation model. The manylatents-omics implementation is a native re-implementation compatible with mamba-ssm 2.x, avoiding version conflicts with Evo2.
- Embedding dimensions: 256 (4-track base), 512 (6-track large)
- VRAM: 8 GB+
- Input encoding: One-hot (A, C, G, U)
- Pooling: Length-aware mean pooling (respects padding)
Key features:
- Native mamba-ssm 2.x implementation (no dependency conflict with Evo2)
- Supports multi-layer intermediate capture
- Loads pretrained weights from HuggingFace
| Model | Tracks | Hidden Dim | Layers |
|---|---|---|---|
orthrus-base-4-track |
4 | 256 | 8 |
orthrus-large-6-track |
6 | 512 | 12 |
from manylatents.dogma.encoders.orthrus_native import OrthrusNativeEncoder
encoder = OrthrusNativeEncoder()
embedding = encoder.encode("AUGCAUGCAUGCAUGC") # (1, 256)
Reference: Fradkin et al. (2024) "Orthrus: Towards Evolutionary and Functional RNA Foundation Models"
AlphaGenome
Domain: DNA sequences with regulatory predictions
AlphaGenome is a JAX-based genomics foundation model from Google DeepMind that predicts regulatory features at single base-pair resolution across 1 Mb context windows.
- Embedding dimensions: 1536 (1bp resolution), 3072 (128bp resolution)
- VRAM: 40 GB+
- Framework: JAX internally, PyTorch tensor output via
torch-jax-interop - Context length: 1,000,000 bp
Key features:
- Dual mode: embeddings (
encode) and regulatory track predictions (predict) - Chunked encoding for sequences longer than context window
- Regulatory track prediction (ATAC, CAGE, DNASE, RNA-seq, and more)
- Automatic JAX compatibility patching for older JAX versions
| Model | Resolution | Embedding Dim | Default Layer |
|---|---|---|---|
alphagenome |
1 bp | 1536 | embeddings_1bp |
alphagenome_128bp |
128 bp | 3072 | embeddings_128bp |
from manylatents.dogma.encoders.alphagenome import AlphaGenomeEncoder
encoder = AlphaGenomeEncoder()
embedding = encoder.encode("ATGAAGTTTGGCGTCCGTGCCTGA") # (1, 1536)
predictions = encoder.predict("ATGAAGTTTGGCGTCCGTGCCTGA") # dict of track tensors
Reference: "AlphaGenome: Foundation model for the human genome" (Google DeepMind)
FoundationEncoder Base Class
All encoders inherit from FoundationEncoder, which extends LatentModule with:
- Lazy loading: Models are loaded on first
encode()call, not at instantiation - Batched encoding:
encode_batch()chunks inputs into micro-batches with automatic OOM retry (halves batch size on CUDA OOM, retries without resetting) - fit/transform interface:
fit()is a no-op;transform()reads sequences from the datamodule and callsencode_batch() - True batched forward: Subclasses that implement
_tokenize_batch()and_extract_embeddings()get single-kernel-per-batch GPU inference instead of looped single-sample encoding
# All encoders follow the same interface
encoder.fit(x) # no-op for pretrained models
embeddings = encoder.transform(x) # encodes sequences from datamodule
embeddings = encoder.encode_batch(seqs) # direct batched encoding
Non-coding variant benchmarks
pip install 'manylatents-omics[noncoding]'
from manylatents.dogma import atlas
from manylatents.dogma.data import traitgym
variants = traitgym.load_variants("mendelian_traits_matched_9") # chrom, pos, ref, alt, label, variant_id
client = atlas.create_client() # reads ALPHAGENOME_API_KEY
print(list(client.scorer_metadata())) # available scorer names
atlas.fetch_atlas_scores(client, variants, ["<scorer>"], cache_dir="atlas_cache")
matrix = atlas.load_atlas_matrix("atlas_cache", "<scorer>", variants["variant_id"])
matrix.values # (n_variants, n_tracks) float32, rows in the order given
matrix.tracks # one row of track metadata per column
fetch_atlas_scores is resumable: finished chunks are skipped on the next
call. Variants the service cannot serve are listed by
atlas.missing_variants(cache_dir, scorer) and are never stored as rows of
zeros; asking load_atlas_matrix for one raises AtlasScoresMissing.
Gene-scoped scorers return one row per variant and gene, so reading them needs
gene_reduce="maxabs".
AlphaGenome Atlas outputs are subject to Google DeepMind's terms of use, which restrict them to non-commercial use and exclude training other machine-learning models on them. Read the terms before fetching.
Locus helpers use only NumPy and pandas:
from manylatents.dogma.benchmarks.loci import (
chain_loci, genomic_separation, positional_scores, distant_neighbour_distances,
)
loci = chain_loci(variants, gap=1000) # controls inherit their matched positive's locus
separation = genomic_separation(variants)
scores = positional_scores(variants) # the nearest-positive score uses labels
# distance is a feature-distance matrix with infinity on its diagonal.
nearest = distant_neighbour_distances(distance, separation, exclusion=1000, k=10)
Sample a background from a full TraitGym pool, excluding benchmark IDs:
import numpy as np
pool = traitgym.load_pool("mendelian_traits_all")
background = traitgym.sample_background(
pool, 1000, np.random.default_rng(42), exclude=variants["variant_id"],
match_to=variants, column="consequence",
)
print(background.attrs["shortfall"], background.attrs["shortfall_by_stratum"])
Omit match_to for uniform sampling. Matched quotas use largest-remainder
rounding; scarce strata return all available candidates without redistributing
the shortfall. Both modes return rows in pool order.
Read all available scores across local cache shards without a service call:
matrix = atlas.load_cached_scores(
["scores/shard_000_of_002", "scores/shard_001_of_002"], "DNASE",
)
Empty caches are skipped. Duplicate variants or differing track metadata raise
ValueError; no cached scores raises AtlasScoresMissing. Pass layer or
gene_reduce as for load_atlas_matrix.
Score a variant TSV locally using an already cached AlphaGenome checkpoint:
python -m manylatents.dogma.score_tracks --variants variants.tsv --out scores \
--fasta reference.fa --shard 0 --n-shards 2
--fasta is required. shard_slice(n_rows, shard, n_shards) produces contiguous
shards; prefilter_variants(variants, fasta_path, sequence_length) returns kept
and dropped tables, with a reason column on dropped rows. Input to the helper
uses canonical chromosome names and 1-based pos; the CLI adds canonical
identifiers from chrom, pos, ref, alt. FASTA access is lazy, and --help
does not load the model libraries.
Track geometry evaluation
manylatents.dogma.benchmarks.track_geometry.run evaluates a variant-by-track
query matrix against named reference matrices (the same track columns), with
None selecting the query itself as a transductive cloud. Supply an aligned
variants table with chrom, pos and boolean label, the primary cloud and
transform, sensitivity transforms, and (cloud, transform, k) control settings.
A frozen Settings holds neighbour counts, PCA dimensions, resampling counts,
control seeds, locus exclusions and score orientations.
import numpy as np
from manylatents.dogma.benchmarks.track_geometry import Settings, run
settings = Settings()
report, scores = run(
query=query, clouds={"reference": reference, "transductive": None},
variants=variants, primary_cloud="reference", primary_transform="raw",
transforms=("raw", "zscore", "unit"),
control_settings=(("reference", "raw", settings.primary_k),),
random_tracks=None, rng=np.random.default_rng(settings.seed), report={},
settings=settings,
)
The report includes all primary label-free scores, chromosome-weighted AUPRC
in both orientations, bootstrap errors, a within-chromosome label-permutation
null, a cloud/transform/neighbour-count sensitivity grid, row-shuffled and
Gaussian-reference controls, and magnitude and locus-confound analyses. The
permutation null gives the chance level: chromosome-weighted AUPRC for an
uninformative score sits above prevalence. scores contains the primary
per-variant arrays; undefined measurements are counted in the report.
An optional random_tracks(rng) callable supplies an alternative query and
cloud mapping for random-track controls. Pass log to receive progress
messages (default: print). This module requires the upstream geometry,
grouped-average-precision and surrogate helpers; until the dependency pin is
updated, use a development installation containing those helpers.