PonTED is a per-residue flexible-linker predictor for the CAID challenge.
Flexible linkers are the disordered segments that bridge folded domains — a
distinct functional class of disorder in DisProt (IDPO:0000033, "flexible
linker"). These give domains the conformational freedom to move relative to one another. PonTED targets that specific signal to help annotate new linkers.
The base method is a small transformer head (~300k params, 1 layer, d=192) on top
of a frozen protein-language-model embedding, served as a 5-member
ensemble. It was trained on DisProt flexible-linker annotations (334 proteins, release 2025_12). Extra training data was processed from TED domains, trimming inter-domain spaces to their disordered core using Boltz structural features and homology-filtering the resulting linkers against the DisProt set. One method variant (Ponte-S) instead adds an AlphaFold pLDDT channel and 7 lightweight sequence-biophysics channels and uses no TED data as baseline.
Here we provide three variants, sharing the head architecture:
| Method | Backbone | Extra channels | Runtime inputs |
|---|---|---|---|
Ponte-S |
ESM-2 650M | AF2 pLDDT (1) + biophysics (7) | --embeddings esm2_path --af2-plddt af2_plddt_path |
PonTED |
ESM-2 650M | none | --embeddings esm2_path |
PonTED-XL |
ProtT5 | none | --embeddings prott5_path |
The package is inference-only, in two stages:
- Precompute inputs (to be run by host, needs internet and run once): the
precompute/scripts turn a FASTA into per-residue features — pLM embeddings and AlphaFold pLDDT. - Predict (offline, CPU-only):
predict_caid.pyruns one method over the FASTA + precomputed features and writes one.caidfile per sequence.
The preprint, data and training methods will be released soon.
Create a conda environment with the precompute dependencies,
conda create -n ponted-precompute python=3.11 -y && conda activate ponted-precompute
pip install -r precompute/requirements-precompute.txtThen run the processing scripts
python precompute/compute_esm2.py --fasta input.fasta --output-dir emb_esm2/
python precompute/compute_prott5.py --fasta input.fasta --output-dir emb_prott5/
python precompute/compute_af2.py --fasta input.fasta --output-dir af2/ [--id-map map.tsv]Each script writes in --output-dir one <fasta_id>.npy per sequence. ESM2 is (L, 1280), ProtT5 is (L, 1024) and AF2 pLDDT is (L,) in [0,1], all float32 values.
The heads were trained against these models:
| Feature | Model / source | dim | loader |
|---|---|---|---|
| ESM-2 embedding | ESM-2 650M — facebook/esm2_t33_650M_UR50D (33-layer, UniRef50D) |
1280 | EsmModel + AutoTokenizer |
| ProtT5 embedding | ProtT5-XL (encoder) — Rostlab/prot_t5_xl_half_uniref50-enc (UniRef50, half precision) |
1024 | T5EncoderModel + T5Tokenizer; needs sentencepiece |
| AF2 pLDDT | AlphaFold DB per-residue CA pLDDT (fetched per UniProt accession, ÷100) | 1 | EBI AFDB REST |
Notes: pLM embeddings are the per-residue last_hidden_state with CLS/EOS
stripped; pLDDT is the CA value / 100. Sequences longer than 1022 tokens are
embedded in overlapping windows (overlap averaged).
AF2 needs a UniProt-id list (only used in Ponte-S). The host supplies the mapping via --id-map — a TSV of
fasta_id<TAB>uniprot_acc, one line per sequence, using - (or nan) where no
accession is known. Coverage is expected to be partial: sequences with no
accession, or whose accession has no AlphaFold model get no pLDDT file.
Alternative — no AF2 precompute needed: if AlphaFold structure files are already
available (e.g. the CAID infrastructure mounts AlphaFold DB models), skip
compute_af2.py and pass the directory of structures to the container via
--af2-structures instead of --af2-plddt. pLDDT is then extracted in-container
from the B-factor column, fully offline. Both PDB and mmCIF are accepted
(plain or gzipped; PDB preferred), named <fasta_id>.pdb/.cif[.gz] or with the
AlphaFold DB scheme AF-<fasta_id>-F1-model_v*.pdb/.cif (when the FASTA id is the
UniProt accession). The lookup is by FASTA id, so the filenames must carry the id used in the FASTA
header
The image is published on Docker Hub. Pull it once:
docker pull lbugnon/ponted:caid# Ponte-S, reading pLDDT directly from mounted AlphaFold structures (PDB/CIF)
docker run --rm --network none \
-v $PWD/input.fasta:/data/input.fasta:ro \
-v $PWD/emb_esm2:/data/embeddings:ro \
-v $PWD/af2_structures:/data/af2_structures:ro \
-v $PWD/predictions/Ponte-S:/data/output \
lbugnon/ponted:caid --method Ponte-S \
--fasta /data/input.fasta --embeddings /data/embeddings \
--af2-structures /data/af2_structures --out /data/output --threads 8# PonTED
docker run --rm --network none \
-v $PWD/input.fasta:/data/input.fasta:ro \
-v $PWD/emb_esm2:/data/embeddings:ro \
-v $PWD/predictions/PonTED:/data/output \
lbugnon/ponted:caid --method PonTED \
--fasta /data/input.fasta --embeddings /data/embeddings \
--out /data/output --threads 8# PonTED-XL
docker run --rm --network none \
-v $PWD/input.fasta:/data/input.fasta:ro \
-v $PWD/emb_prott5:/data/embeddings:ro \
-v $PWD/predictions/PonTED-XL:/data/output \
lbugnon/ponted:caid --method PonTED-XL \
--fasta /data/input.fasta --embeddings /data/embeddings \
--out /data/output --threads 8| Flag | Required | Description |
|---|---|---|
--method |
yes | Method name |
--fasta |
yes | Input FASTA format |
--embeddings |
yes | Directory with per-id <id>.npy. |
--out |
yes | Output directory. |
--af2-plddt |
for af2 methods* | Directory of <id>.npy pLDDT in [0,1]. |
--af2-structures |
for af2 methods* | Directory of AlphaFold models (.pdb/.cif, optionally .gz); pLDDT is read from the B-factor column. Mutually exclusive with --af2-plddt. |
--threads |
no | CPU threads (default 8). |
* af2 methods (Ponte-S) need exactly one of --af2-plddt / --af2-structures.
predictions/
<id>.caid # position \t residue \t score \t binary_state
timings.csv # per-sequence wall time
Each .caid is 4-column (position, residue, score, binary state), per the CAID
output format. The score is the linker ranking signal; the binary state is
score >= binary_threshold (set per method in method.yaml).
