AlphaFold confidence across a protein family
AlphaFold scores every residue it models with pLDDT, a confidence from 0 to 100 that AlphaFold DB bands as very high (above 90), confident (70 to 90), low (50 to 70) and very low (below 50). TDP-43, the protein the TARDBP gene encodes, has three folded domains and a 150-residue C-terminal region, so its models score at both ends of that range, and the folded domains should score high in every model. For fourteen vertebrate TDP-43 orthologs, we:
- fetch the UniProt sequences, align them and infer a tree
- read the pLDDT from each AlphaFold model and add the mean per column as a track
- mark the Pfam domains and each row’s runs under pLDDT 50
- add one strip per domain with each row’s band
- check two columns against the model files and open the result
Prerequisites
curl- ClustalW,
apt install clustalwon Debian or Ubuntu,brew install clustal-won macOS. ClustalW both aligns and infers a tree, so this page needs no other aligner. - python3, standard library only
The data
Fourteen UniProtKB entries and their AlphaFold models. AlphaFold DB is keyed on UniProt accession, so one accession fetches the sequence and the model both. Nothing to download: the commands below fetch these.
| What it is | File |
|---|---|
| Every sequence in one request, shown here with two of the fourteen accessions | uniprotkb-accessions |
| One AlphaFold record per accession, which names its files, for example | Q13148 |
| The model that record names, whose B-factor column holds the pLDDT, for example | AF-Q13148-F1-model_v6.pdb |
| The Pfam matches of the human sequence | Q13148 |
The files this page writes, hosted for the figure links
| What it is | File |
|---|---|
| The row table the commands below start from | tardbp-rows.tsv |
| The alignment they write | tardbp.afa |
| Its tree | tardbp.nwk |
| The runs each model scores under 50 | tardbp-lowconf.gff |
| The band each row falls in per domain | tardbp-rowdata.json |
| The tracks and the highlights, the layers the links below carry | tardbp-layers.json |
1. Name the rows
Write one species per line: the label the viewer draws, then the UniProtKB
accession. The label becomes the FASTA defline, the tree tip, the GFF seq_id and
the row of every layer.
Human Q13148
Mouse Q921F2
Cow G3MX91
Elephant G3TD75
Opossum A0A5F8GU32
Platypus F7EDX1
Chicken Q5ZLN5
Turtle K7FJ67
Lizard A0A670IXJ6
Frog Q28F51
Coelacanth H3BC22
Zebrafish Q802C7
Seabream A0A671WI33
Ghostshark A0A4W3GN84
Both teleost entries are the tardbpb paralog, which runs the full length of
the protein.
2. Fetch the sequences
One request takes every accession, and a short script rewrites each defline to the species label:
accessions=$(awk -F'\t' '{printf "%s%s", sep, $2; sep=","}' rows.tsv)
curl -sf "https://rest.uniprot.org/uniprotkb/accessions?accessions=$accessions&format=fasta" \
-o tardbp-uniprot.fasta
Human Q13148 414 aa
Mouse Q921F2 414 aa
Cow G3MX91 414 aa
Elephant G3TD75 414 aa
Opossum A0A5F8GU32 414 aa
Platypus F7EDX1 414 aa
Chicken Q5ZLN5 414 aa
Turtle K7FJ67 414 aa
Lizard A0A670IXJ6 415 aa
Frog Q28F51 409 aa
Coelacanth H3BC22 412 aa
Zebrafish Q802C7 412 aa
Seabream A0A671WI33 406 aa
Ghostshark A0A4W3GN84 404 aa
3. Align and infer a tree
ClustalW aligns the sequences in input order and infers a neighbor-joining tree:
clustalw -INFILE=tardbp.fasta -ALIGN -TYPE=PROTEIN -OUTORDER=INPUT \
-OUTPUT=FASTA -OUTFILE=tardbp.afa
clustalw -INFILE=tardbp.afa -TREE -TYPE=PROTEIN -OUTPUTTREE=phylip
tr -d '[:space:]' < tardbp.ph > tardbp.nwk
14 rows, 431 columns
(((((Human:0.01799,((Chicken:0.01026,(Turtle:0.00330,Lizard:0.02575):0.00303):0.00546,
(Frog:0.07202,(Coelacanth:0.08469,((Zebrafish:0.08572,Seabream:0.08841):0.05655,
Ghostshark:0.07870):0.03228):0.01066):0.02077):0.01299):0.00134,Mouse:0.01773):0.00213,
Cow:0.00108):0.00132,Platypus:0.00236):0.00000,Elephant:0.00238,Opossum:0.00000);

4. Read the pLDDT from the models
The AlphaFold API record for each accession names its model file. Send a
User-Agent header, since the API answers a request without one with a 403:
url=$(curl -sf -A "$UA" "https://alphafold.ebi.ac.uk/api/prediction/Q13148" |
python3 -c 'import json,sys; print(json.load(sys.stdin)[0]["pdbUrl"])')
curl -sf -A "$UA" "$url" -o models/Q13148.pdb
AlphaFold writes each residue’s pLDDT into the B-factor column of its CA atom, beside the residue name, so one pass reads the model’s sequence and confidence together:
def read_model(path):
seq, plddt = '', []
for line in open(path):
if line.startswith('ATOM') and line[12:16].strip() == 'CA':
seq += THREE_TO_ONE[line[17:20]]
plddt.append(float(line[60:66]))
return seq, plddt
A model follows the UniProt sequence of the day it was built, so the script compares it to the row letter by letter first:
Human Q13148 model 414 aa matches the row, mean pLDDT 65.2, 156 residues under 50
Mouse Q921F2 model 414 aa matches the row, mean pLDDT 63.8, 162 residues under 50
Cow G3MX91 model 414 aa matches the row, mean pLDDT 61.6, 172 residues under 50
Elephant G3TD75 model 414 aa matches the row, mean pLDDT 62.0, 178 residues under 50
Opossum A0A5F8GU32 model 414 aa matches the row, mean pLDDT 62.4, 169 residues under 50
Platypus F7EDX1 model 414 aa matches the row, mean pLDDT 61.9, 175 residues under 50
Chicken Q5ZLN5 model 414 aa matches the row, mean pLDDT 65.8, 155 residues under 50
Turtle K7FJ67 model 414 aa matches the row, mean pLDDT 61.4, 175 residues under 50
Lizard A0A670IXJ6 model 415 aa matches the row, mean pLDDT 62.3, 173 residues under 50
Frog Q28F51 model 409 aa matches the row, mean pLDDT 66.5, 156 residues under 50
Coelacanth H3BC22 model 412 aa matches the row, mean pLDDT 61.5, 167 residues under 50
Zebrafish Q802C7 model 412 aa matches the row, mean pLDDT 65.9, 149 residues under 50
Seabream A0A671WI33 model 406 aa matches the row, mean pLDDT 61.6, 170 residues under 50
Ghostshark A0A4W3GN84 model 404 aa matches the row, mean pLDDT 62.0, 172 residues under 50
Every model matches its row. The column track holds the rounded mean over the
rows with a residue in each column, and a text track writes each column’s band
as one letter, V, C, L or D from very high to very low:
means = [round(sum(values) / len(values)) for values in by_column]
bands = ''.join(band(m) for m in means)
columns by mean pLDDT band: 6 very high, 214 confident, 24 low, 187 very low

5. Mark the Pfam domains
InterPro serves the Pfam matches of the human sequence in one request:
curl -sf https://www.ebi.ac.uk/interpro/api/entry/pfam/protein/uniprot/Q13148 \
-o tardbp-pfam.json
The script writes each match as a highlight on the Human row, in that row’s residue numbering:
TDP43_N PF18694 Human 4-76: columns 5-77, mean pLDDT 84.0
RRM1 PF00076 Human 106-164: columns 112-170, mean pLDDT 85.5
RRM2 PF00076 Human 193-241: columns 203-251, mean pLDDT 82.7
TDP43_C PF20910 Human 262-371: columns 272-387, mean pLDDT 38.4

6. Mark each row’s low-confidence runs
The script writes each model’s runs of five or more residues under pLDDT 50 to a GFF, in that row’s residue numbering:
gff.write(f'{label}\tAlphaFold\tpolypeptide_region\t{start + 1}\t{i}\t.\t.\t.\t'
f'Name=pLDDT<50;color=%23ff7d45\n')
71 runs of 5 or more residues under pLDDT 50 across the 14 rows

7. Add one strip per domain
For each row and Pfam domain, the script writes the band of the row’s mean pLDDT over the domain’s columns:
{
"Human": {
"TDP43_N": "confident",
"RRM1": "confident",
"TDP43_C": "very low"
}
}
TDP43_N 14 rows confident
RRM1 14 rows confident
RRM2 14 rows confident
TDP43_C 14 rows very low
Four strip panels read those fields through one scale from band to color under
one title, so the four share one legend:
"rowPanels": [
{
"kind": "strip",
"field": "RRM1",
"title": "pLDDT band",
"domain": ["very high", "confident", "low", "very low"],
"range": ["#0053d6", "#65cbf3", "#ffdb13", "#ff7d45"]
}
]

8. Check two columns against the models
The script reads each model file at one column inside RRM1 and one inside the C-terminal region:
RRM1, alignment column 133 (Human residue 127):
Human F 86.4
Mouse F 87.6
Cow F 84.4
Elephant F 85.2
Opossum F 84.9
Platypus F 85.1
Chicken F 87.9
Turtle F 84.8
Lizard F 85.5
Frog F 88.2
Coelacanth F 82.8
Zebrafish F 87.3
Seabream F 82.4
Ghostshark F 85.2
TDP43_C, alignment column 316 (Human residue 303):
Human Q 47.4
Mouse Q 40.7
Cow Q 31.6
Elephant Q 30.5
Opossum Q 33.3
Platypus Q 32.8
Chicken Q 45.2
Turtle Q 31.9
Lizard Q 32.9
Frog Q 46.6
Coelacanth Q 34.5
Zebrafish S 39.3
Seabream T 30.9
Ghostshark P 48.8


One stretch of the C-terminal region rises out of the very low band:
inside TDP43_C, columns 335-339 rise to a mean of 52, which is Human residues 320-324

9. Open the result
The snapshot loads the four files by URL:
{
"msaview": {
"type": "MsaView",
"colWidth": 3.2,
"rowHeight": 22,
"colorSchemeName": "clustalx_protein_dynamic",
"msaFilehandle": { "uri": "https://example.org/tardbp.afa" },
"treeFilehandle": { "uri": "https://example.org/tardbp.nwk" },
"gffFilehandle": { "uri": "https://example.org/tardbp-lowconf.gff" },
"treeMetadataFilehandle": {
"uri": "https://example.org/tardbp-rowdata.json"
}
}
}Add the columnTracks, highlights and rowPanels entries from
tardbp-layers.json beside them, URL-encode the object, and append it to the
app URL as #data=, about 5,400 characters in all.

ggmsaview reads the four hosted files, and
msaview() takes the row data and layers from tardbp-layers.json through
jsonlite as they stand:
library(ggmsaview)
data <- "https://gmod.org/JBrowseMSA/demo/data/tdp43/"
layers <- jsonlite::fromJSON(paste0(data, "tardbp-layers.json"),
simplifyVector = FALSE)
w <- msaview(
msa = paste0(data, "tardbp.afa"),
tree = paste0(data, "tardbp.nwk"),
gff = paste0(data, "tardbp-lowconf.gff"),
color_scheme = "clustalx_protein_dynamic",
row_data = jsonlite::fromJSON(paste0(data, "tardbp-rowdata.json")),
column_tracks = layers$columnTracks,
highlights = layers$highlights,
row_panels = layers$rowPanels
)
w
ggplot2::ggsave("alphafold-confidence-r.png",
msaview_plot(w, tracks = c("plddt-mean", "plddt-band")),
width = 12, height = 6)
Reproduce it end to end
build_alphafold_confidence.sh
runs the commands and the Python above in order:
- It fetches the fourteen sequences from UniProt and names each FASTA record by its species label, which every layer uses as the row name.
- ClustalW aligns the records and infers a neighbor-joining tree.
- It downloads each AlphaFold model and the human Pfam matches, and stops if a model’s sequence differs from its row.
- It writes the tracks, highlights, GFF and strip fields, then prints the residue check of step 8.
It needs the tools under Prerequisites.
curl -O https://raw.githubusercontent.com/GMOD/JBrowseMSA/main/docs/tutorials/scripts/build_alphafold_confidence.sh
bash build_alphafold_confidence.sh
With no arguments the script writes the row table above, builds every file beside it and prints every number on this page. For another family, pass a table of labels and UniProt accessions:
bash build_alphafold_confidence.sh my-rows.tsv out/
The script takes the first Human line as the reference row, and its SHORT
map names the Pfam domains for the highlights and strips.
See also
- Data layers
- Where p53’s damaging variants fall
- Hemoglobin’s two subunits and the interfaces between them
- User guide
References
- Jumper J, Evans R, Pritzel A, et al. Highly accurate protein structure prediction with AlphaFold. Nature 596:583-589.
- Tunyasuvunakool K, Adler J, Wu Z, et al. Highly accurate protein structure prediction for the human proteome. Nature 596:590-596.
- Varadi M, Anyango S, Deshpande M, et al. AlphaFold Protein Structure Database: massively expanding the structural coverage of protein-sequence space with high-accuracy models. Nucleic Acids Res 50:D439-D444.
- Conicella AE, Zerze GH, Mittal J, Fawzi NL. ALS mutations disrupt phase separation mediated by alpha-helical structure in the TDP-43 low-complexity C-terminal domain. Structure 24:1537-1549.
- Lukavsky PJ, Daujotyte D, Tollervey JR, et al. Molecular basis of UG-rich RNA recognition by the human splicing factor TDP-43. Nat Struct Mol Biol 20:1443-1449.
- Thompson JD, Higgins DG, Gibson TJ. CLUSTAL W: improving the sensitivity of progressive multiple sequence alignment through sequence weighting, position-specific gap penalties and weight matrix choice. Nucleic Acids Res 22:4673-4680.