andes benchmarks¶
andes is benchmarked on public PRIDE datasets for identification (high-res, TMT-labelled and
low-res LFQ, phospho, glyco) and for quantification (label-free with match between runs, and
TMT). Identifications are counted after Percolator at q ≤ 0.01. Where the database carries an
entrapment component, the page also gives the true false discovery proportion (FDP), which
is what tells you whether the nominal 1% holds. Other tools are named with the version compared.
Their numbers come either from runs on the same host with the same rescoring, or from a public
leaderboard. Section 2 gives the date and the andes commit behind each row.
1. Summary¶
All andes rows: 2051616b (origin/main, 2026-10-23), default settings plus the dataset's mods,
Percolator 3.7.1 -Y, seeds 42, 1 and 2. Comparison rows keep the date they were measured.
Identification (PSMs at Percolator q ≤ 0.01, 8 threads):
| benchmark | dataset | andes | comparison | true FDP at nominal 1% | andes wall |
|---|---|---|---|---|---|
| Standard, high-res | Astral HCD LFQ, PXD070049 (1 file) | 52,169–52,437 PSMs, 31,147–31,238 peptides | Comet 2025.01 31,435 PSMs, 217 s (2026-10-05) | 0.89–1.08% (peptide-level shuffle); 0.99–1.05% (Arabidopsis) | 114–117 s |
| TMT-labelled, low-res | a05058, PXD007683 (1 file, ion-trap CID) | 13,443–13,516 PSMs | Comet 2025.01 10,504, 77 s (2026-10-05) | 0.67–0.76% (peptide-level); 0.83–1.05% (Arabidopsis) | 40–47 s |
| TMT-labelled, high-res | TKO hrMS2 TMTpro, PXD017803 (1 file) | 6,628–6,686 PSMs (entrapment database) | — | 0.98–1.31% (peptide-level) | 4 s † |
| Low-res LFQ | UPS1, PXD001819 (1 file, ion-trap CID) | 16,049–16,242 PSMs | Comet 2025.01 14,734, 42 s (2026-10-05); Java MS-GF+ v20240326 15,904 (earlier session) | 2.07–2.19% (natural E. coli); 0.91–0.98% (peptide-level) | 30–48 s |
| Phospho-enriched | mouse liver, PXD007653 (1 file, Q Exactive) | 38,596–38,629 PSMs, 27,693–27,724 phospho-bearing | Comet 2025.01 33,984 at 1.77% FDP, 1,096 s (2026-10-06; whole-protein shuffle) | 0.80–0.99% (peptide-level); 1.22–1.36% (Arabidopsis) | 337 s |
| timsTOF DDA-PASEF | plasma, PXD053748 (2 files) | 14,336–14,393 and 17,491–17,550 PSMs | — | 0.62–0.90% (peptide-level); 0.78–1.14% (natural yeast) | 43–51 s † |
| timsTOF DDA-PASEF | astrocytes, PXD064202 (2 files) | 34,210–34,249 and 55,590–55,609 PSMs | — | 0.98–1.03% (peptide-level); 1.29–1.55% (natural yeast) | 43–64 s † |
| Glyco, quick tier | mouse liver, PXD005553 (1 fraction) | 6,992–7,072 glycoPSMs | 88.2–88.4% of pGlyco2's and 89.3–89.7% of MSFragger-Glyco's identifications confirmed | 0.61–1.35% (peptide-level) | 5.8–6.6 min † |
| Glyco, deep tier | mouse liver, PXD005553 (5 fractions) | 31,666 ± 9 glycoPSMs (2026-09-05) | 78.9% (pGlyco2) and 88.0% (MSFragger-Glyco) confirmed | 1.11% ± 0.03 (whole-protein shuffle) | 23–29 min per fraction, 16 threads |
† On a cluster node (8 threads); the other walls are on the benchmark VM (8 cores), the host the Comet times come from. Wall times compare only within one host.
Quantification (andes defaults, 2026-10-23 at 2051616b):
| benchmark | dataset | andes | comparison (leaderboard snapshot 2026-07-16) | error control | andes cost |
|---|---|---|---|---|---|
| Label-free, match between runs (ProteoBench "Quant LFQ DDA ion QExactive") | PXD028735, 6 runs, Q Exactive HF-X, human/yeast/E. coli mix | 65,012 precursors in ≥ 3 runs; median |ε| 0.163, CV 0.118 (transfer q 0.01) | median |ε| 0.190 (FragPipe 23.0); CV 0.120 (i2MassChroQ 1.2.0, no MBR); most precursors 81,933 (Sage 0.15.0-beta.2, median |ε| 0.388, transferred values not error-controlled) | PSM FDP 0.83–0.85%; entrapment-only quantified precursors 0.20–0.22% | 6.9k CPU-s for 6 runs |
| Label-free, match between runs (ProteoBench "Quant LFQ DDA ion Astral") | PXD070049, 6 runs, Astral, human/yeast/E. coli mix | 37,352 precursors in ≥ 3 runs; median |ε| 0.193, CV 0.113 (transfer q 0.01) | median |ε| 0.123 (DIA-NN 2.6.0, 16,363 precursors); CV 0.070 (Sage 0.14.6); most precursors 93,237 (DIA-NN 2.6.0, median |ε| 0.277) | not measured | 6.4k CPU-s for 6 runs |
| TMT reporter ions | yeast triple knockout, TMTpro 16-plex, PXD017803 | knockout-channel interference 0.064 (SPS-MS3), 0.023 (RTS-MS3), 0.182 (hrMS2) | 0.139 with OpenMS precursor purity ≥ 0.9 (SPS-MS3, 2026-10-10) | — | — |
| TMT reporter ions | human + yeast TMT11, PXD007683 (11 fractions, SPS-MS3) | yeast A/C log2 ratio 1.591 (expected 1.585), protein MAE 0.212 | — | — | 9.6 min, 17.5 GB, 16 threads |
| Large study, match between runs | PXD042233, 500 runs (Q Exactive HF/HF-X, Exploris 480) | 243,895 precursors in ≥ 3 runs, 9,208 protein groups (transfer q 0.01) | — | PSM, precursor and protein q ≤ 0.01 | 146 CPU-h end to end (§2) |
Opt-in modes (Astral, PSMs / distinct peptides, Percolator seeds 42, 1 and 2; measured
2026-10-05 to 2026-10-13 on earlier builds and not re-measured at 2051616b):
| mode | andes | without the mode |
|---|---|---|
--chimeric (second and later peptides per spectrum), at an entrapment true FDP of 1% |
66,377–66,424 / 29,384–29,400 | 43,076–43,145 / 26,723–26,746 |
--refine (PTM discovery, high-res only) |
48,312 PSMs, 28,728 peptides at q ≤ 0.01; its second-pass PSMs at ~1.2–1.8% FDP |
47,080 / 28,932 |
2. The benchmarks¶
Where and how. Every andes number on this page was measured on 2026-10-23 at 2051616b
unless a row says otherwise. PSM counts, wall time, CPU time and peak memory of the four standard
sets (Astral, TMT a05058, UPS1, phospho) come from the benchmark VM (8 cores, 8 threads,
/usr/bin/time, two runs except phospho), on the plain databases the Comet rows used. The true
FDP of every set and all other rows come from a cluster node (8 threads), with each target
database extended by an entrapment component: three peptide-level shuffled realisations
(build_shuffled_entrap.py seeds 1, 2 and 3) for Astral, phospho and glyco, one realisation for
UPS1, TMT, TKO and timsTOF, plus a foreign (reviewed Arabidopsis) or natural entrapment where
one was used before. Percolator 3.7.1 -Y --num-threads 8, seeds 42, 1 and 2. "At a true FDP
of 1%" is the deepest score-sorted list whose entrapment-estimated FDP stays at or below 1%.
Standard, high-res (Astral). One 15-minute DDA run of the ProteoBench human/yeast/E. coli
sample against the 31,889-entry HYE FASTA. 52,169–52,437 PSMs and 31,147–31,238 peptides at
q ≤ 0.01. With the peptide-level entrapment (T/E 1.075) the nominal 1% reads 0.89–1.08% true
FDP over nine database × seed combinations, and andes keeps 47,267–47,977 PSMs and
28,141–28,857 peptides at a true FDP of 1%; with the Arabidopsis entrapment (T/E 2.228),
0.99–1.05% and 49,965–50,185 PSMs. 114–117 s wall, 569–636 CPU-s, 4.8 GB. Comet 2025.01 was run
on the same VM with matched parameters and the same Percolator rescoring on 2026-10-05.
TMT-labelled, low-res. One ion-trap CID run of a TMT 10-plex sample against human + yeast
reviewed proteins (26,483 sequences): 13,443–13,516 PSMs and 11,852–11,922 peptides at
q ≤ 0.01; 40–47 s, 200–216 CPU-s, 1.7 GB. With a peptide-level entrapment (T/E 1.073) the
nominal 1% is 0.67–0.76% true FDP (13,325–13,371 PSMs at a true FDP of 1%); with Arabidopsis
(T/E 2.021), 0.83–1.05% (13,161–13,388).
TMT-labelled, high-res (TKO hrMS2). Fig2_m23142_hrMS2 of PXD017803 (TMTpro, Orbitrap
MS2), --protocol TMT, against reviewed yeast + cRAP with a peptide-level entrapment (T/E 1.039):
6,628–6,686 PSMs at q ≤ 0.01, 0.98–1.31% true FDP, 6,607–6,662 PSMs at a true FDP of 1%.
Low-res LFQ (UPS1). One run of the UPS1 standard in yeast, searched against yeast plus an
E. coli entrapment proteome: 16,049–16,242 PSMs and 4,123–4,183 peptides at q ≤ 0.01;
30–48 s, 162–166 CPU-s, 1.3 GB. Against the natural E. coli entrapment (T/E 2.351) the
nominal 1% is 2.07–2.19% true FDP, and andes keeps 14,457–14,605 PSMs at a true FDP of 1%.
With a peptide-level shuffle of the same targets instead (T/E 1.039) it reads 0.91–0.98%
(16,199–16,206 PSMs at 1%). The two entrapments disagree on this low-res set; the natural one is
the established reference here. Java MS-GF+ (v20240326, earlier session, not re-run) reported
15,904 PSMs on this file.
Phospho-enriched. One single-shot EasyPhos mouse liver file
(20151014_QEp6_NaKr_SA_totalliver_control2_phospho.raw, as mzML), not in any model's
training data, 80 Da index slices. Against mouse reviewed proteins plus the whole-protein shuffled
entrapment that the Comet row used: 38,596–38,629 PSMs (27,693–27,724 phospho-bearing) and
20,422–20,461 peptides, 337 s, 2,160 CPU-s, 7.9 GB. Comet 2025.01 reported 33,984 at 1.77% true
FDP on 2026-10-06 (on the whole-protein shuffle, which can read low). andes's true FDP on three
peptide-level shuffles (T/E 1.061) is 0.80–0.99%, with 38,604–38,843 PSMs at a true FDP of 1%;
on Arabidopsis (T/E 1.403), 1.22–1.36% and 38,298–38,412. Phosphosite localisation is
not scored. Against the depositors' MaxQuant identifications (PEP ≤ 0.01, 23,563 scans)
andes covered 82.4% with 95.3% same-scan backbone agreement on 2026-10-07 (40774aca); not
re-measured.
timsTOF DDA-PASEF. Native .d input, 20 ppm precursor tolerance, 2 missed cleavages,
--top-n 1, 80 Da index slices, Carbamidomethyl C fixed, Oxidation M and protein N-terminal
Acetyl variable, against reviewed human proteins with a reviewed yeast entrapment proteome
(natural, T/E 3.845) or a peptide-level shuffle of the human targets (T/E 1.064).
| run | PSMs at q ≤ 0.01 (peptide-level) |
true FDP | PSMs at a true FDP of 1% | natural yeast: PSMs / true FDP / at 1% |
|---|---|---|---|---|
PXD053748 ..._4363 (plasma, 30 min) |
14,336–14,393 | 0.62–0.63% | 14,772–14,877 | 14,923–14,959 / 0.94–1.14% / 14,788–15,033 |
PXD053748 ..._4367 (plasma, 50 min) |
17,491–17,550 | 0.87–0.90% | 17,644–17,660 | 18,081–18,136 / 0.78–0.91% / 18,379–18,434 |
PXD064202 ..._2442 (astrocytes) |
34,210–34,249 | 0.98–1.02% | 34,216–34,222 | 35,105–35,150 / 1.53–1.55% / 33,744–33,959 |
PXD064202 ..._2403 (astrocytes) |
55,590–55,609 | 0.98–1.03% | 55,561–55,655 | 56,801–56,836 / 1.29–1.32% / 56,028–56,088 |
On the astrocyte runs the natural yeast entrapment reads above nominal (1.29–1.55%) where the peptide-level shuffle reads 0.98–1.03%. 43–64 s per run, 2.8–3.9 GB.
Glyco. Mouse liver glycoproteome data (PXD005553), against mouse proteins plus an entrapment,
with --glyco --glyco-species mouse --decoy-strategy sequon. Two published reference
identification sets for the same spectra ship in glyco/truth/: pGlyco2 (the
depositors') and MSFragger-Glyco (a later reanalysis, PXD031032). "Confirmed" is the share of a
reference's spectra that andes identifies with the same peptide.
- Quick tier: the MouseLiver-Z-T-1 fraction as converted mzML, three peptide-level shuffled
databases × Percolator seeds 42, 1 and 2: 6,992–7,072 glycoPSMs at 1%, true FDP 0.61–1.35%,
pGlyco2 88.2–88.4% and MSFragger-Glyco 89.3–89.7% confirmed; 5.8–6.6 min and 5.4–5.6 GB on 8
threads. Each run has only 20–45 entrapment hits, so the spread is mostly counting noise.
Reading the .raw natively, as the commands below do, can give somewhat different counts.
- Deep tier: all five fractions, pooled before Percolator, five seeds. Measured 2026-09-05 at
14818d3e on an older, smaller glycan list and converted mzML; not re-measured since.
- The open problem is selection, not generation: almost every reference spectrum produces a
candidate row, but in the deep tier about a fifth of pGlyco2's spectra lose the per-scan
choice.
Label-free quantification with match between runs (ProteoBench).
- Data and measurement: the two ProteoBench "Quant LFQ DDA ion" modules, six runs each, where
the human, yeast and E. coli ratios between conditions A and B are known: QExactive
(LFQ_Orbitrap_DDA_Condition_{A,B}_Sample_Alpha_0{1,2,3}, PXD028735, Q Exactive HF-X) and
Astral (LFQ_Astral_DDA_15min_50ng_Condition_{A,B}_REP{1,2,3}, PXD070049). Measured
2026-10-23 at 2051616b on a cluster node (8 threads per run), andes defaults throughout
(§3, --predict rt), Percolator 3.7.1 through --rescore (seed 42). Scored with the official
proteobench package 0.18.6 ("Custom" format, converted by
proteobench/andes_to_proteobench.py).
- Which quantity is scored: quantity_normalized of the MBR table, which removes each run's
loading level and its drift along the gradient, unless the table says raw. The raw quantity
is what andes hands to quantms.
- Results at a minimum of 3 runs; precursors / median |ε| / E. coli |ε| / CV:
| module | transfer q ≤ 0.01, normalised | raw quantity | transfer q ≤ 0.05, normalised | identified only, normalised |
|---|---|---|---|---|
| QExactive | 65,012 / 0.163 / 0.275 / 0.118 | 0.228 / 0.323 / 0.246 | 71,243 / 0.176 / 0.442 / 0.132 | 52,037 / 0.154 / 0.189 / 0.105 |
| Astral | 37,352 / 0.193 / 0.258 / 0.113 | 0.213 / 0.256 / 0.115 | 42,656 / 0.211 / 0.343 / 0.130 | 30,759 / 0.194 / 0.243 / 0.103 |
At least 1 / 6 runs (transfer q 0.01): QExactive 79,126 / 40,258, Astral 47,774 / 22,033.
The opt-in --predict settings rt,ms2 and ms2,peptdeep-rt,deeplc-rt (AlphaPeptDeep and
DeepLC models, --predictor-models, ONNX Runtime backend) were measured on 2026-10-21 at
a27a72c, before the extraction change of #240: on QExactive 67,906 and 68,077 precursors
against 65,391 for the default on that build, on Astral 34,413 and 33,987 against 33,876.
- By abundance (transfer q 0.01, normalised; quartiles of each module's own mean intensity,
|ε| / E. coli |ε| / CV): QExactive Q1 0.292 / 0.535 / 0.198, Q2 0.175 / 0.273 / 0.130,
Q3 0.140 / 0.200 / 0.104, Q4 0.117 / 0.164 / 0.078; Astral Q1 0.317 / 0.415 / 0.191, Q2 0.217 /
0.320 / 0.136, Q3 0.164 / 0.219 / 0.103, Q4 0.135 / 0.185 / 0.070.
- Cost (six runs, CPU seconds): QExactive search with prediction and Percolator 5.8k, library
under 10, extract 0.8k, finalize 0.4k per transfer threshold; Astral 6.1k, under 10, under 0.1k
and 0.2k. Each search takes 3–4 minutes of wall time, each extract under 20 seconds (QExactive)
or about 2 seconds (Astral), finalize under a minute.
- Error control is measured on the QExactive runs with the HYE database plus a peptide-level
shuffled entrapment (T/E 1.075), andes defaults, Percolator 3.7.1 -Y seeds 42, 1 and 2
outside andes. PSM FDP at q 0.01 is 0.83–0.85%; precursors quantified in at least 3 runs at
transfer q 0.01 are 0.20–0.22% entrapment-only (0.26–0.30% at 0.05). Of the accepted
transfers, the entrapment measures a false-donor share of 0.24–0.33% at transfer q 0.01 and
0.37–0.49% at 0.05; the identity-decoy estimate is 0.33–0.34% and 0.45–0.47%. The estimate is
at or above the measured share at 0.01 in all three seeds and below it at 0.05 in one (0.45%
against 0.49%), so it tracks the false-donor share but is not an upper bound. The wrong-peak
part has no entrapment check.
Comparison with the ProteoBench leaderboard. Public results of both modules
(Results_quant_ion_DDA and Results_quant_ion_DDA_Astral, both last updated 2026-07-16; read
2026-10-21; scored by proteobench 0.17.0). For each tool the submission with the most
precursors and, when different, the one with the lowest median |ε|, at a minimum of 3 runs.
The last column says what limits the error of transferred (match-between-runs) values, taken
from the submission's parameters, comment and the tool's own output; "not checked" means the
submission's parameter file could not be retrieved (the ProteoBench data server was unreachable
on 2026-10-21).
QExactive:
| tool (submission) | MBR | precursors | median |ε| | E. coli |ε| | CV | error control on transferred values |
|---|---|---|---|---|---|---|
| andes, default (2026-10-23) | yes | 65,012 | 0.163 | 0.275 | 0.118 | PSM q ≤ 0.01; transfer q ≤ 0.01 (decoy-estimated wrong peaks and wrong donors) |
| andes, default, transfer q ≤ 0.05 | yes | 71,243 | 0.176 | 0.442 | 0.132 | transfer q ≤ 0.05 |
| andes, default, raw quantity | yes | 65,012 | 0.228 | 0.323 | 0.246 | as the default |
| FragPipe 23.0, most precursors | yes | 63,701 | 0.200 | 0.306 | 0.156 | identifications 1%; transfers at IonQuant MBR ion FDR 0.01 (submitted workflow) |
| FragPipe 23.0, lowest |ε| | yes | 54,374 | 0.190 | 0.257 | 0.154 | as above |
| MaxQuant 1.5.3.30, most precursors | yes | 44,299 | 0.210 | 0.386 | 0.219 | PSM and protein 1%; transfers not checked |
| MaxQuant 2.4.13.0, lowest |ε| | no | 29,737 | 0.192 | 0.263 | 0.199 | no transfers |
| i2MassChroQ 1.0.16, most precursors | yes | 74,697 | 0.222 | 0.460 | 0.132 | identifications about 1%; no transfer error setting in the submitted parameters |
| i2MassChroQ 1.2.0, lowest |ε| | no | 49,433 | 0.198 | 0.263 | 0.120 | no transfers |
| AlphaPept 0.5.0, most precursors | yes | 37,760 | 0.219 | 0.281 | 0.165 | PSM and protein 1%; transfers not checked |
| AlphaPept 0.5.3, lowest |ε| | no | 36,176 | 0.214 | 0.255 | 0.165 | no transfers |
| Sage 0.15.0-beta.2 | yes | 81,933 | 0.388 | 0.877 | 0.393 | peptide q ≤ 0.01 on identifications only; every charge state 2–4 of those peptides is integrated in every run and its peak q-value is not applied |
| MSAngel 2.2.10 | yes | 60,206 | 0.216 | 0.514 | 0.227 | PSM 1%; transfers not checked |
| ProlineStudio 2.3.0-SNAPSHOT | yes | 55,639 | 0.210 | 0.508 | 0.226 | PSM 1%; transfers not checked |
| WOMBAT 0.9.11, most precursors | yes | 55,943 | 0.211 | 0.692 | 0.235 | identifications 1%; transfers not checked |
| WOMBAT 0.9.11, lowest |ε| | yes | 41,016 | 0.195 | 0.394 | 0.213 | as above |
| PEAKS 13 | no | 72,741 | 0.289 | 0.741 | 0.216 | no transfers |
| quantms v1.3.1dev (OpenMS ProteomicsLFQ) | no | 33,040 | 0.209 | 0.387 | 0.224 | no transfers |
| quantms (OpenMS ProteomicsLFQ), our run (2026-10-17, its default) | no | 34,677 | 0.210 | 0.401 | 0.225 | no transfers |
| quantms (OpenMS ProteomicsLFQ), our run, its feature-linking MBR | yes | 39,257 | 0.221 | 0.563 | 0.234 | feature-quality score; no transfer error rate |
andes's rows use its own normalisation (quantity_normalized: median |ε| 0.163, CV 0.118). Its
raw quantity reads |ε| 0.228 and CV 0.246, less accurate than most submissions; normalisation
differs between tools, so the |ε| column does not compare extraction alone. Among the
submissions, FragPipe 23.0 reaches median |ε| 0.190 at 54,374 precursors, and i2MassChroQ 1.2.0
a CV of 0.120 without match between runs. Six submissions report more precursors than andes
(Sage, i2MassChroQ's four largest and PEAKS 13), at a median |ε| of 0.214–0.388. The two quantms
runs marked "our run" are ours (2026-10-17, its development version, raw intensities).
On the precursors andes shares (default, transfer q 0.01; the submission's values | andes raw | andes normalised, median |ε| / E. coli |ε| / CV):
| submission | shared | submission | andes raw | andes normalised | only in the submission |
|---|---|---|---|---|---|
| FragPipe 23.0, most precursors | 51,940 | 0.190 / 0.273 / 0.155 | 0.211 / 0.280 / 0.241 | 0.147 / 0.216 / 0.109 | 11,761 at 0.266 / 0.725 |
| FragPipe 23.0, lowest |ε| | 48,916 | 0.187 / 0.243 / 0.155 | 0.207 / 0.269 / 0.241 | 0.144 / 0.204 / 0.108 | 5,458 at 0.214 / 0.490 |
| i2MassChroQ 1.0.16, most precursors | 51,156 | 0.208 / 0.353 / 0.125 | 0.214 / 0.300 / 0.243 | 0.153 / 0.245 / 0.113 | 23,541 at 0.266 / 0.935 |
| i2MassChroQ 1.2.4, 57,787 precursors | 50,058 | 0.202 / 0.352 / 0.123 | 0.214 / 0.302 / 0.243 | 0.152 / 0.246 / 0.112 | 7,729 at 0.270 / 0.835 |
| Sage 0.15.0-beta.2, our reproduction | 55,218 | 0.311 / 0.628 / 0.321 | 0.220 / 0.303 / 0.245 | 0.158 / 0.254 / 0.116 | 25,139 at 0.685 / 1.349 |
Sage's per-submission table was not retrievable, so its row uses a reproduction (2026-10-21): the same Sage version on the same six mzML files with the submission's stated parameters and per-charge output gives 80,357 precursors at |ε| 0.388, E. coli 0.878 and CV 0.394 (submission: 81,933, 0.388, 0.877, 0.393). Most of its precursors that andes does not report are charge states that Sage never identified or are above its own peak q-value of 0.01, which it reports but does not apply.
Astral:
| tool (submission) | MBR | precursors | median |ε| | E. coli |ε| | CV | error control on transferred values |
|---|---|---|---|---|---|---|
| andes, default (2026-10-23) | yes | 37,352 | 0.193 | 0.258 | 0.113 | PSM q ≤ 0.01; transfer q ≤ 0.01 (decoy-estimated) |
| andes, default, transfer q ≤ 0.05 | yes | 42,656 | 0.211 | 0.343 | 0.130 | transfer q ≤ 0.05 |
| andes, default, raw quantity | yes | 37,352 | 0.213 | 0.256 | 0.115 | as the default |
| FragPipe 23.0, most precursors | yes | 39,057 | 0.212 | 0.250 | 0.127 | identifications 1%; transfers not checked |
| FragPipe 22.1-build02, lowest |ε| | yes | 29,105 | 0.181 | 0.405 | 0.078 | as above |
| MaxQuant 2.6.7.0 | yes | 20,283 | 0.160 | 0.158 | 0.092 | PSM and protein 1%; transfers within a condition only (submission comment), not checked |
| i2MassChroQ 1.2.6, most precursors | yes | 36,469 | 0.197 | 0.417 | 0.095 | identifications about 1%; transfers not checked |
| i2MassChroQ 1.2.9, lowest |ε| | no | 24,803 | 0.178 | 0.245 | 0.077 | no transfers |
| Sage 0.14.6 | yes | 30,319 | 0.167 | 0.338 | 0.070 | peptide q ≤ 0.01 on identifications only; peak q-value not applied (as in QExactive) |
| DIA-NN 2.6.0, most precursors | yes | 93,237 | 0.277 | 0.691 | 0.159 | run and global precursor q ≤ 0.01 (submission comment) |
| DIA-NN 2.6.0, lowest |ε| | yes | 16,363 | 0.123 | 0.168 | 0.079 | as above, plus MS1-level q ≤ 0.01 |
On Astral, MaxQuant 2.6.7.0 (20,283 precursors, median |ε| 0.160), Sage 0.14.6 (30,319, 0.167, CV 0.070) and i2MassChroQ 1.2.6 (36,469, 0.197, CV 0.095) report fewer precursors than andes (37,352, 0.193) and FragPipe 23.0 more (39,057, 0.212); DIA-NN 2.6.0 reports 93,237 at 0.277, and its 16,363-precursor submission has the lowest median |ε| (0.123). andes's CV (0.113) is above most submissions. Normalisation changes little here (raw |ε| 0.213, CV 0.115). Shared-precursor comparisons need the per-submission tables, which could not be retrieved; they are not given.
TMT quantification.
- Data and measurement: PXD017803 (yeast triple knockout, TMTpro 16-plex; two files each of
hrMS2, SPS-MS3 and RTS-MS3) and PXD007683 (human + yeast TMT11 with known yeast ratios, 11
SPS-MS3 fractions, ion-trap CID MS2), as mzML, with the kit impurity sheet. andes defaults,
including the quantification gate (precursor purity ≥ 0.7 and Percolator PEP ≤ 0.05;
§10 of DOCS.md), --rescore, 16 threads; measured 2026-10-23 at 2051616b.
- Extraction: reporter extraction and impurity correction match OpenMS IsobaricAnalyzer
exactly on the same scans.
- Knockout interference (median ratio of knockout to non-knockout channel intensity over the
PSMs of the three knocked-out proteins, lower is better; hrMS2 only scans whose window starts
below 126 Th):
| acquisition | PSMs at 1% | PSMs quantified (gate passed) | interference | without the gate | purity ≥ 0.9 |
|---|---|---|---|---|---|
| SPS-MS3 | 9,816 | 8,626 | 0.064 | 0.128 | 0.032 |
| RTS-MS3 | 14,307 | 10,605 | 0.023 | 0.033 | 0.015 |
| hrMS2 | 13,464 | 3,618 | 0.182 | 0.185 | 0.134 |
Few knockout PSMs stand behind each value (36–91), so read them as a direction. OpenMS
precursor purity at ≥ 0.9 gave 0.139 on SPS-MS3 (2026-10-10). On hrMS2 only 3,618 of the
13,464 PSMs have a reporter scan whose range covers the reporter ions.
--tmt-unmix on hrMS2 sets the median knockout ratio to 0.000 at a background CV of 0.124
(0.080 without).
- Known ratios (PXD007683): 149,133 rank-1 target PSMs at 1% over the 11 fractions, 128,177 quantified;
yeast log2 A/C 1.591 (expected 1.585), A/B 1.192, B/C 0.396, with protein-level MAE 0.212,
0.228 and 0.215 (without the gate: A/C 1.464, MAE 0.271). 9.6 minutes and 17.5 GB in one
process.
Large study (PXD042233, 500 runs). Label-free DDA from Q Exactive HF, HF-X and Exploris 480,
.raw read natively, human reviewed proteins + contaminants, 5 ppm, 2 missed cleavages,
--top-n 1, Carbamidomethyl C fixed, Oxidation M and protein N-terminal Acetyl variable. Each
run is searched as its own job (8 threads, --quant-dir); the per-run PINs share one header
(it depends only on the command line) and are concatenated into one Percolator run (16 threads,
--subset-max-train 1000000); then quant library, quant extract per run (8 threads) and
quant finalize (16 threads). Measured 2026-10-23 at 2051616b on cluster nodes.
| stage | wall | CPU | peak memory |
|---|---|---|---|
| search, 500 jobs | 0.7 min per run (at most 1.0) | 19.5 h | 3.6 GB |
| PIN concatenation (53.1 million rows) | 17 s | — | — |
| Percolator | 12.9 min | 0.7 h | 26.0 GB |
quant library |
6.6 min | 0.1 h | 5.6 GB |
quant extract, 500 jobs |
2.1 min per run (two runs 45 and 72 min) | 121.5 h | 12.7 GB (median 4.7) |
quant finalize, transfer q 0.01, with the QPX views and protein inference |
25.8 min | 4.1 h | 45.2 GB |
quant finalize, transfer q 0.05, without QPX views |
18.0 min | 3.9 h | 11.7 GB |
Outputs: 30.6 million PSMs at q ≤ 0.01. At transfer q 0.01, 194,370 accepted transfers
(175,087 transfer_ms1, 19,283 transfer_ms2) and 294,362 / 243,895 / 127,315 precursors
quantified in at least 1 / 3 / 50 runs (identified only: 294,362 / 243,730 / 126,741); 9,208
protein groups at protein q ≤ 0.01. At transfer q 0.05, 4,622,956 accepted transfers and
294,362 / 250,847 / 141,734 precursors. Extract is 83% of the CPU, and most of its transfer fits
are rejected (121 million below_threshold rows at q 0.01).
3. How to reproduce¶
You need andes on PATH, Docker (for the pinned Percolator image), curl and python3. Build
andes with --features thermo and install the .NET 8 runtime to read .raw directly; this is
preferred over converting (see reproduce/README.md).
Standard sets: Astral, TMT, UPS1 (tested scripts)¶
DATA=~/andes-bench # ~10 GB for these three
cd docs/benchmarks/reproduce
./build_databases.sh "$DATA" # UniProt download, ~1 min; prints the UPS1 T/E factor
./fetch_spectra.sh "$DATA" astral tmt ups1 # 4.8 GB from PRIDE
./run.sh "$DATA" astral tmt ups1 # search + Percolator; prints wall, PSMs, entrapment hits
run.sh uses 8 threads (THREADS= to change), Percolator 3.7.1 --seed 42 -Y, and the
configs/ mods files (Astral: astral_mods.txt, --precursor-tol 10ppm; TMT: mods-tmt.txt).
UniProt is versioned and the original HYE FASTA is no longer served, so counts will differ
slightly from the table; the scripts print a sha256 and sequence count for each input.
Phospho (commands)¶
GLYCO=1 ./build_databases.sh "$DATA" # also writes databases/mouse_entrap.fasta and prints its T/E
./fetch_spectra.sh "$DATA" phospho # 3.7 GB
andes --spectrum "$DATA"/phospho/20151014_QEp6_NaKr_SA_totalliver_control2_phospho.raw \
--database "$DATA"/databases/mouse_entrap.fasta \
--mods ../configs/mods-phospho.txt --threads 8 \
--fragment-index-slice-da 80 --output-pin phospho.pin
docker run --rm -v "$PWD":/r quay.io/biocontainers/percolator:3.7.1--h3b5f4bd_2 percolator \
--seed 42 -Y --results-psms /r/phospho.t.psms --decoy-results-psms /r/phospho.d.psms /r/phospho.pin
Count rows at q-value ≤ 0.01 and their entrapment hits with python3 ../entrap_common.py count
phospho.t.psms "$DATA"/databases/mouse_entrap.fasta 0.01 (FDP = hits / PSMs × (1 + T/E), with the
T/E that build_databases.sh printed), and peptides carrying 79.96. Expect about 6 minutes on 8 threads
(337 s on the benchmark VM). The slice width is pinned because it sets peak memory (7.9 GB at 80 Da).
Glyco (commands; scripts in glyco/)¶
GLYCO=1 ./build_databases.sh "$DATA"
./fetch_spectra.sh "$DATA" glyco-mouse # 5 fractions, 12.6 GB; the quick tier needs only T-1
cd .. # docs/benchmarks
DB="$DATA"/databases/mouse_entrap.fasta
# --decoy-strategy sequon is required: other generated decoys carry fewer sequons than their targets.
for f in MouseLiver-Z-T-1 MouseLiver-Z-T-2 MouseLiver-Z-T-3 MouseLiver-Z-T-4 MouseLiver-Z-T-5; do
andes --spectrum "$DATA"/glyco-mouse/$f.raw --database "$DB" \
--glyco --glyco-species mouse --decoy-strategy sequon \
--threads 8 --output-pin $f.pin # writes $f.glyco.pin
done
python3 glyco/pool_pins.py MouseLiver-Z-T-*.glyco.pin > pooled.pin # pool BEFORE Percolator
docker run --rm -v "$PWD":/r quay.io/biocontainers/percolator:3.7.1--h3b5f4bd_2 percolator \
--seed 42 -Y --results-psms /r/pooled.t.psms --decoy-results-psms /r/pooled.d.psms /r/pooled.pin
python3 glyco/eval_yield.py pooled.pin pooled.t.psms
python3 glyco/eval_entrap.py pooled.pin pooled.t.psms 0.01 "$DB"
for ref in glyco/truth/*_mouse_liver.tsv.gz; do # the two reference sets
python3 glyco/score_vs_truth.py "$ref" pooled.pin pooled.t.psms
done
For the quick tier, search MouseLiver-Z-T-1 alone, run Percolator on its .glyco.pin without
pooling, and pass --run MouseLiver-Z-T-1 to score_vs_truth.py (a single-file run writes
SpecIds without a file name). About 6 minutes and 6 GB on 8 threads. Pool the deep tier's
fractions: one fraction alone has too few glyco decoys for a stable 1% threshold.
Label-free quantification, ProteoBench (commands; converter tested)¶
Inputs: the six runs of a module and the HYE FASTA linked from the ProteoBench module
documentation (ProteoBenchFASTA_MixedSpecies_HYE.fasta, 31,889 entries).
- QExactive: LFQ_Orbitrap_DDA_Condition_{A,B}_Sample_Alpha_0{1,2,3}.raw of PXD028735 (about 21 GB).
- Astral: LFQ_Astral_DDA_15min_50ng_Condition_{A,B}_REP{1,2,3}.raw of PXD070049 (about 15 GB).
The measured runs read mzML peak-picked from these files. R is each run's stem. Every flag not
shown is the andes default (20 ppm precursor tolerance, one missed cleavage, Carbamidomethyl C
fixed, Oxidation M and protein N-terminal Acetyl variable, --predict rt).
# 1. per run: search, Percolator (--rescore) and the run's MS1, MS2 and PSM tables in q/
andes --spectrum $R.mzML --database ProteoBenchFASTA_MixedSpecies_HYE.fasta \
--rescore --output-pin $R.pin --quant-dir q/ --threads 8
# 2. once: the library, from every run's Percolator results (one --psms/--decoy-psms per run)
andes quant library --quant-dir q/ --psms $R=$R.percolator.target.psms.txt \
--decoy-psms $R=$R.percolator.decoy.psms.txt ...
# 3. per run
andes quant extract --quant-dir q/ --run $R
# 4. once per transfer threshold (the default --mbr-fdr is 0.01)
andes quant finalize --quant-dir q/ -o pb
andes quant finalize --quant-dir q/ -o pb05 --mbr-fdr 0.05
# 5. ProteoBench "Custom" table (python3 + pyarrow); --module qe or astral
python3 proteobench/andes_to_proteobench.py --mbr pb.mbr.parquet --quant-dir q/ \
--module qe --column quantity_normalized -o custom_input.tsv
- Score with
proteobench0.18.6:DDAQuantIonModuleQExactive(orDDAQuantIonAstralModule).benchmarking(custom_input.tsv, "Custom", ...)reports minimum 1 to 6 runs in one pass.
The converter keeps the identified, transfer_ms2 and transfer_ms1 rows of the MBR table,
takes each precursor's peptidoform and proteins from the quant directory, and writes Unimod
names in ProForma. --column quantity writes the raw quantity instead of quantity_normalized,
and --evidence identified writes the identification-only table. Its tests:
python3 -I tests/test_proteobench_convert.py.
andes --spectrum ... --spectrum ... --rescore --lfq --mbr --quant-dir q/ runs the same stages
in one process, with one Percolator over all runs; it was not the configuration measured here.
TMT quantification, knockout (commands, not a tested script)¶
The PXD017803 files Fig2_m23142_hrMS2.raw and Fig2_m23145_SPSms3.raw, reviewed yeast
proteins, and a mods file with Carbamidomethyl C and TMTpro (304.20715) on K and the peptide
N-terminus as fixed modifications, plus Oxidation M as variable. The measured runs read mzML
converted from these files (both files of each acquisition in one process), with 16 threads:
andes --spectrum Fig2_m23142_hrMS2.raw --database yeast.fasta --mods mods_tmtpro.txt \
--precursor-tol 20ppm --protocol TMT --rescore --fdr 0.01 \
--tmt tmt16 --tmt-level 2 --tmt-correction <kit impurity sheet> --output-tsv hr.tsv
andes --spectrum Fig2_m23145_SPSms3.raw --database yeast.fasta --mods mods_tmtpro.txt \
--precursor-tol 20ppm --protocol TMT --rescore --fdr 0.01 \
--tmt tmt16 --tmt-level 3 --tmt-correction <kit impurity sheet> --output-tsv sps.tsv
Channel layout: MET6 (P05694) is knocked out in 126–128N, HIS4 (P00815) in 128C–130N and URA2
(P07259) in 130C–132N; 132C–134N is the parental strain. For each PSM of those proteins, divide
the mean of its knockout channels by the mean of the other channels in <stem>.tmt.parquet
(rows with quant_gate_passed). Report
the median, using only scans whose reporter scan window starts below 126 Th. Repeat on PSMs
with purity ≥ 0.9.
4. Method notes¶
- True FDP by entrapment. A target PSM that matches only entrapment sequences is false by construction: FDP = (entrapment hits / accepted) × (1 + T/E), where T/E is the ratio of searchable target to entrapment peptides, measured for each database and never assumed to be
- A PSM whose peptide also occurs in a target protein counts as a target: it is entrapment
only when all its proteins are entrapment and its peptide, with I folded to L (the two
are isobaric), occurs in no target protein sequence.
entrap_common.pyholds this rule forrun.sh,build_databases.sh(the T/E factor) and the glyco evaluators. - Entrapment design. Shuffled entrapment is built peptide by peptide
(
build_shuffled_entrap.py): each tryptic peptide of each target protein is shuffled with its C-terminal residue fixed, as in the peptide-level entrapment construction of Wen et al., Nat. Methods 2025. Every entrapment peptide then has a target of the same composition and mass. The earlier builder shuffled whole proteins: 89.6% of its entrapment peptides on the HYE database had no same-composition target peptide, and on the same Astral search it read 0.81% where the peptide-level databases read 0.92–1.02% and a foreign proteome (reviewed Arabidopsis, T/E 2.228) 0.99% (#225). On phospho it agreed with the peptide-level databases (1.05% against 0.95–1.04%). FDPs marked "whole-protein shuffle" were measured that way and may read low. - Percolator. Version 3.7.1,
--seed 42 -Y, on plain FASTA with andes'sXXX_decoys, for every engine compared on the same host. Percolator's q-value has a floor of 1 / (number of top targets), so small or sparse runs return few or no identifications at 1%; pool glyco fractions for this reason. - ProteoBench terms. "Min runs" is the number of the six runs in which a precursor (peptidoform and charge) must be quantified to be counted. Epsilon is the difference between the measured log2 A/B ratio and the expected one; the headline is its median absolute value over all precursors. CV is the median coefficient of variation within a condition, averaged over the two conditions. A transfer q-value is an internal quant-quality score for the peak a precursor is matched to in a run where it was not identified; it is not an identification FDR.
- Comparisons. Identification comparisons are runs on the same host with matched parameters and the same rescoring. ProteoBench comparisons are submissions on its public leaderboard. Wall times compare only within one host and session; counts are portable.
5. Known gaps¶
- Label-free quantification rests on two datasets and one Percolator seed (three for the
error control), and its best scores use andes's own normalisation (
quantity_normalized; the rawquantityis the quantms contract). On Astral andes's CV (0.113) is above most submissions, and its match-between-runs entrapment error is measured on QExactive only. The leaderboard was scored byproteobench0.17.0 and andes by 0.18.6; several engines' transfer error control could not be checked. - Entrapment designs can disagree. On UPS1 the natural E. coli entrapment reads the nominal 1% as 2.07–2.19% and a peptide-level shuffle as 0.91–0.98%; on the timsTOF astrocyte runs natural yeast reads 1.29–1.55% and the shuffle 0.98–1.03%. The 500-run study has no entrapment in this measurement.
- Not re-measured at
2051616b: the glyco deep tier, the compared phospho FDP (Comet), the--chimericand--refineopt-in table, the non-default--predictsettings and the phospho agreement with MaxQuant. - Single files. Phospho is one file, peptide-level only;
--refineis measured on Astral only. - Glyco composition on fucose-rich tissue. On heart and lung the backbone agrees with pGlyco2 94–99% of the time but the composition only 68–78% (97% on liver).
- Not benchmarked: iTRAQ, phosphosite localisation, timsTOF quantification. Java MS-GF+ was not re-run under the current defaults; its counts are historical.
Layout¶
docs/benchmarks/
README.md this page
reproduce/ database, download and run scripts (no hardcoded paths)
glyco/ glyco harness: pooling, yield, entrapment, reference scoring
configs/ mods files and per-engine parameter files
proteobench/ andes MBR output -> ProteoBench "Custom" table (python3 + pyarrow)
entrap_common.py shared entrapment rules (ALL-ENTRAP_, I/L rescue, T/E)
tests/ tests: python3 -I tests/test_entrap.py (stdlib), tests/test_proteobench_convert.py
Bulk spectra and third-party engine binaries stay outside git.