Two analysts run "the same" qpAdm model and get different p-values. Neither made an error — they made different choices among the parameters every tutorial waves past. This is the reference for those choices: what each ADMIXTOOLS 2 setting actually does, which results it moves, and the measured stakes where the audit literature provides them. The companion piece for the workflow itself is the R tutorial; this page is why its numbers are what they are.
The decision before all others: f2 blocks or genotype input#
ADMIXTOOLS 2's speed comes from extract_f2(): compute all pairwise f2-statistics once, then run
thousands of models from the cache. The cost is hidden in a default: precomputed f2 restricts
every statistic to the sites present across all populations in the extraction — and with
low-coverage ancients in the set, that intersection collapses.
The alternative is passing the genotype prefix directly with allsnps = TRUE, which computes
each f4-statistic on every site available for that statistic's four populations — classic
qpAdm's behaviour. The measured stakes, from the Harney audit: at 25% missingness the two agree
(SE 0.006 both ways); at 85% missingness it is SE 0.020 with allsnps against 0.066 without; at
90%, 0.035 against a meaningless 9.99. On real ancient panels, allsnps is usually right; its
price is that per-statistic SNP sets differ (the counts print per f4) and the covariance is
approximated. The unbreakable rule either way:
hold the choice constant across every model you compare.
If you do extract f2, maxmiss governs the same trade at extraction time: maxmiss = 0
keeps only sites complete in every population (clean, brutal on sparse panels); raising it admits
sites with missingness and quietly changes which sites underlie everything downstream. Extract
per project, not per lifetime — an f2 directory silently inherited across projects is a
reproducibility bug waiting to publish.
The numerics: fudge and fudge_twice#
The weights solve a least-squares system weighted by the f4 covariance matrix; near-singular
covariance matrices invert badly, so a small ridge — fudge, default 1e-4 times the trace —
is added to the diagonal first. You will essentially never tune it. fudge_twice = TRUE
applies the ridge a second time, and exists for one purpose the name hides: matching classic
ADMIXTOOLS' p-values. Comparing against a published table computed with the original software?
Set it. Otherwise, pick one setting and never vary it mid-project —
the classic-versus-2 differences have their own guide.
The uncertainty machinery: blgsize and boot#
Standard errors come from resampling genome blocks. blgsize sets the block: 0.05 Morgans —
5 centimorgans — by default, long enough that linkage disequilibrium does not tie neighbouring
blocks together; values of 100+ are read as base pairs instead. Published qpAdm SEs live on the
5 cM jackknife convention, so changing this is choosing incomparability. boot swaps the
jackknife for block-bootstrap resampling (an integer sets the replicate count) — used in the
ADMIXTOOLS 2 paper's own model comparisons, but jackknife remains the setting whose errors compare
to the literature's tables.
The semantics: afprod, constrained, auto_only#
afprod switches f-statistics from the unbiased estimator to allele-frequency products —
which changes how missing data and small samples enter every number. It has legitimate uses;
mixing regimes across compared models is not one of them. constrained = TRUE forces weights
non-negative via quadratic programming — and should stay off for screening, because a negative
unconstrained weight is diagnosis, not noise: it
says the source pool brackets the target wrongly. Constrain only what you already understand.
auto_only = TRUE (default) keeps analysis to chromosomes 1–22, where it belongs;
poly_only drops globally monomorphic sites, and getcov = FALSE buys speed by
forfeiting the weight covariance — and with it honest errors on anything derived from the
weights.
The reproducibility block#
The parameter regime is part of a result. The reporting floor
best practices sets out includes it, and the honest minimum is one
sentence of the form: ADMIXTOOLS 2 version X, genotype input with allsnps = TRUE (or f2 blocks
with maxmiss = m), default fudge, jackknife at 5 cM, unconstrained. Our own
published model records carry exactly that block, because
"the same model" is only the same model inside one regime — which is where this post began.
Terms used here are defined in the glossary.
References#
- Maier, R. et al. (2023). On the limits of fitting complex models of population history to f-statistics. eLife, 12, e85492. (ADMIXTOOLS 2; parameter semantics per its documentation.)
- Harney, É., Patterson, N., Reich, D. & Wakeley, J. (2021). Assessing the performance of qpAdm. Genetics, 217(4), iyaa045. (The allsnps/missingness table.)
- Patterson, N. et al. (2012). Ancient admixture in human history. Genetics, 192(3), 1065–1093. (Block jackknife convention.)
- ADMIXTOOLS 2 documentation: qpadm() and extract_f2() references.



