CaLM¶
Extract codon-level embeddings from a 12-layer transformer pretrained on cross-organism CDS sequences. Complementary to CodonTransformer (which is generative): CaLM produces representations, CodonTransformer optimizes codon usage.
- Paper: Nature Machine Intelligence 2024 — Outeiral & Deane, "Codon language embeddings provide strong signals for use in protein engineering"
- GitHub:
oxpig/CaLM - License: BSD-3-Clause (code + weights)
- Device: CPU or GPU. Two image variants:
rnazoo-calm:latest— CUDA-enabled (default, used with-profile gpu)rnazoo-calm-cpu:latest— CPU-only (smaller, used with-profile cpu)
What it does¶
CaLM is a 12-layer, 768-dimensional codon-level transformer (~86M params) pretrained on millions of CDSs from across the tree of life. Unlike single-nucleotide RNA LMs (RNA-FM, RiNALMo, ERNIE-RNA, PlantRNA-FM), CaLM tokenizes the input as in-frame 3-letter codons and treats each codon as an atomic unit — which preserves coding-frame structure that gets lost under nucleotide tokenization.
Input is up to 1024 codons (~3 kb of CDS); 64 codons + a few special tokens make up the vocabulary. The model uses rotary position embeddings (no fixed positional limit beyond the 1024-codon training window).
Where it slots in: CaLM embeddings have been shown to carry strong signal for protein-engineering downstream tasks — e.g. predicting protein expression, solubility, melting temperature — directly from coding sequence. Pair this with CodonTransformer (generative codon optimization) for an embedding+design loop.
Input format¶
FASTA file of RNA / CDS sequences. The wrapper:
- Uppercases the input and converts T → U automatically.
- Trims any sequence that is not a multiple of 3 nucleotides to the largest codon-aligned prefix (with a warning).
- Truncates inputs longer than 1024 codons (3072 nt) (with a warning).
Example (reuses tests/data/rnafm_test.fa for the in-pipeline smoke test):
>test_rna_1
GGGUGCGAUCAUACCAGCACUAAUGCCCUCCUGGGAAGUCCUCGUGUUGCACCUGACUGUCUUUCCGAACGGGCGUUUCUUUUCCUCCGCGCUACCUGCCAGG
>test_rna_2
AUUCCGAGAGCUAACGGAGAACUCUGUUCGAUUUAAGCUGUAAGAUGGCAGUAGCUUACUAGGCAGGAAAAGACCCUGUUGAGCUUGACUCUAGUU
Output format¶
A directory containing:
sequence_embeddings.npy: NumPy array of shape(N, 768)— one 768-d embedding per input sequence (mean-pooled across codon positions, excluding<cls>and<eos>)labels.txt: one FASTA header per line, in the same order as the embedding rows
With --per-token:
<label>_tokens.npy: per-sequence NumPy array of shape(L+2, 768)— one 768-d embedding per codon position including<cls>(row 0) and<eos>(last row), so L+2 rows for an L-codon input
Run with Docker¶
See the Direct Docker guide for the shared
docker runrecipe (UID,HOME,USERenv vars, and GPU flag). Below are the model-specific parts.
# CPU
docker run --rm \
-v /path/to/input.fa:/data/input.fa \
-v /path/to/output:/out \
ghcr.io/ericmalekos/rnazoo-calm-cpu:latest \
calm_predict.py -i /data/input.fa -o /out
# GPU
docker run --rm --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=all \
-v /path/to/input.fa:/data/input.fa \
-v /path/to/output:/out \
ghcr.io/ericmalekos/rnazoo-calm:latest \
calm_predict.py -i /data/input.fa -o /out
Add --per-token to either invocation for per-codon embeddings.
Run with Nextflow¶
# CPU
nextflow run main.nf -profile docker,cpu --calm_input /path/to/input.fa
# GPU
nextflow run main.nf -profile docker,gpu --calm_input /path/to/input.fa
Only models with input provided will run — no ignore flags needed.
Results appear in results/calm/calm_out/.
Parameters¶
| Parameter | Default | Description |
|---|---|---|
--calm_per_token |
false |
Also output per-codon (L+2 x 768) embeddings per sequence |
--calm_max_codons |
1024 |
Truncate to this many codons (CaLM's max_positions cap, ~3 kb of CDS) |
Reading the output¶
import numpy as np
embeddings = np.load("calm_out/sequence_embeddings.npy") # (N, 768)
labels = open("calm_out/labels.txt").read().strip().split("\n")
for label, emb in zip(labels, embeddings):
print(f"{label}: {emb.shape}") # (768,)
Comparison with the other foundation models in the zoo¶
| Model | Embedding | Pooling | Tokenization | Training set | Max input | Bundled license |
|---|---|---|---|---|---|---|
| RNA-FM | 640-d | Mean (excl CLS+EOS) | Single nt | 23M ncRNAs (RNAcentral) | 1022 nt | MIT |
| RiNALMo | 1280-d | Mean (excl CLS+EOS) | Single nt | 36M ncRNAs (RNAcentral) | ~11k nt (memory-bound) | Apache-2.0 |
| ERNIE-RNA | 768-d | [CLS] | Single nt | 20M ncRNAs (RNAcentral) | 1022 nt | MIT |
| RNAErnie | 768-d | Mean (excl CLS+SEP) | Single nt | 23M ncRNAs (RNAcentral) | 2046 nt | Apache-2.0 |
| Orthrus | 512-d | Mean (mean_unpadded) |
Single nt (Mamba SSM) | 32.7M mRNAs (GENCODE+RefSeq) | unbounded (linear mem) | MIT |
| PlantRNA-FM | 480-d | Mean (excl CLS+EOS) | Single nt | ~25M plant RNAs (1124 species) | 1024 nt | MIT |
| CaLM | 768-d | Mean (excl CLS+EOS) | Codon (3-letter) | Cross-organism CDSs (ENA codingseqs) | 1024 codons (~3 kb) | BSD-3-Clause |
CaLM is the zoo's only codon-level foundation model. The other six tokenize at the nucleotide level — which loses reading-frame structure unless the downstream head reconstructs it. For protein-engineering and CDS-level tasks (translation efficiency, expression, solubility, thermal stability), codon tokenization is the natural inductive bias.
Pairing notes:
- CodonTransformer (in the Translation track) is generative — given a protein it produces optimized DNA. CaLM is the embedding counterpart — given a CDS it produces a fixed-dim representation. Use both for design + scoring loops.
- For non-coding RNA, prefer the nt-tokenized models. CaLM's pretraining data is CDSs; non-coding sequences fall outside its training distribution.
Limitations¶
- Codon-aligned input required. Sequences whose length is not a multiple of 3 are trimmed to the largest codon-aligned prefix; if your sequence has 5'UTR + CDS + 3'UTR concatenated without removing the UTRs, CaLM will treat the whole thing as codons and the embedding will be partly noise. Strip the UTRs first.
- Maximum 1024 codons (~3 kb). Longer CDSs are truncated. For long mRNAs use Orthrus (Mamba, linear memory).
- Inference-only. Upstream
training.pyexists for from-scratch pretraining but no fine-tuning recipe is shipped — fine-tuning support is not currently exposed in the pipeline.
Fine-tuning¶
RNAZoo exposes a generic head trainer (linear / MLP / XGBoost, regression or classification) on top of frozen 768-d codon-level CaLM embeddings. See the Fine Tuning guide for input format, head choice, the two execution paths (full chain vs. precomputed embeddings), and worked examples.
CaLM-specific parameters¶
| Parameter | Default | Description |
|---|---|---|
--calm_finetune_input |
null |
TSV/CSV with name, sequence (CDS), label column |
--calm_finetune_label |
(required) | Column name with target values |
--calm_finetune_embeddings |
null |
Precomputed (N, D) .npy — switches to the head-only path |
--calm_finetune_head_type |
linear |
linear, mlp, or xgboost (xgboost requires _embeddings) |
--calm_finetune_task |
auto |
auto, regression, or classification |
--calm_finetune_epochs |
20 | Max training epochs (torch heads) |
--calm_finetune_lr |
1e-3 | Adam (torch) or XGBoost learning rate |