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, or one of them ran classic ADMIXTOOLS and the other ADMIXTOOLS 2. This is the reference for both cases: what each ADMIXTOOLS 2 setting actually does, which results it moves, the measured stakes where the audit literature provides them, and how to match a classic ADMIXTOOLS result when a comparison demands it. 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: at maxmiss = 0, 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: the
per-statistic mode classic qpAdm has long called allsnps: YES (recent classic releases reroute
that setting, see below). ADMIXTOOLS 2 offers it only on
genotype input, never on precomputed f2. 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. Those simulations scattered the
missing sites at random, and there allsnps sharpened model choice without bias; the ADMIXTOOLS 2
documentation still warns that with large amounts of missing data it "might lead to false positive
results". So it is the common choice in the literature for sparse data, not a free one: every
f4-statistic sits on its own site set (the counts print per statistic), a departure from the
theory that Harney and colleagues flag themselves. 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, and quietly
decides which sites underlie everything downstream. maxmiss = 0 keeps only sites complete in
every extracted population: clean, and brutal on sparse panels, because the more populations you
extract, the fewer sites survive. Raising it admits sites with missingness; at maxmiss = 1 each
f2 uses every site its own pair shares, the least conservative of the three regimes the
documentation ranks, with the most room for bias when sites are not missing at random. The
documented middle road is qpfstats = TRUE: smoothed f2 that use the sparse sites with less bias
than a raised maxmiss. Extract per project, not per lifetime: an f2 directory silently inherited
across projects is a reproducibility bug waiting to publish.
The numerics: fudge, once or twice#
The weights solve a least-squares system weighted by the inverse of the f4 covariance matrix;
near-singular covariance matrices invert badly, so a small ridge, fudge (default 1e-4) times
the matrix's trace, is added to its 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: in the documentation's words, p-values "that better match those in the original qpAdm
program". It is off by default, which is why a rerun of a classic table with everything else
matched can still drift in p because of this one flag. Comparing against a published table
computed with the original software? Set it, and read the classic comparison
first. Otherwise, pick one setting and never vary it mid-project.
The uncertainty machinery: blgsize and boot#
Standard errors come from resampling genome blocks. blgsize sets the block: 0.05 Morgans
(5 centimorgans) by default, in ADMIXTOOLS 2 and classic qpAdm alike, long enough that linkage
disequilibrium does not tie neighbouring blocks together; values of 100 or more 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; TRUE uses one per block), which the ADMIXTOOLS 2 paper uses to
compare admixture-graph fits; the jackknife remains the setting whose errors compare to the
literature's qpAdm tables.
The semantics: afprod, constrained and the rest#
afprod decides whether f4-statistics are assembled from f2 estimates or from
allele-frequency products. extract_f2() writes both; qpadm() reads the products whenever you
hand it the f2 directory, while f2_from_precomp() returns plain f2 unless you pass
afprod = TRUE. With no site missing the two agree closely; once maxmiss has admitted missing
sites, the documentation prefers the products for qpadm(), because the f2 small-sample
correction suffers more from uneven site sets. So qpadm(f2_dir, ...) and
qpadm(f2_from_precomp(f2_dir), ...) are not quite the same run: pick one path and keep it across
every model you compare.
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 (the default) keeps analysis to chromosomes 1 to 22, where it belongs;
poly_only drops sites whose allele frequency is identical in every population; and
getcov = FALSE buys speed by skipping the weight covariance, which leaves every weight
without a standard error or a Z.
Matching classic ADMIXTOOLS#
You re-run a model from a 2018 paper in ADMIXTOOLS 2. The weights land close, the p-value does not, and the forum thread you consult contains one person shouting "broken" and another shouting "user error". Usually it is neither. The two implementations share their mathematics and part at a few documented defaults, and "classic ADMIXTOOLS" has itself changed between releases. This is the map of those points, and the settings that make the new software speak the old one's dialect.
What does not differ#
The method. ADMIXTOOLS 2 uses the same f-statistic identities,
the same qpAdm fit (its qpadm() reference is the original qpAdm supplement, Haak et al. 2015)
and the same 5 cM block jackknife by default; its documentation says results "should generally
match" the original's. The paper that introduced it benchmarked f4-statistics both ways: classic
qpDstat and ADMIXTOOLS 2 reading genotypes directly gave identical results, while the
precomputed-f2 route matched only when no data were missing (Maier et al. 2023, Appendix 1). For
qpAdm itself, Flegontova and colleagues ran 8,580 models through ADMIXTOOLS 2 and classic
ADMIXTOOLS 7.0 on low-quality simulated data and found the two not identical but highly
correlated: Pearson 0.99 for p-values (a measure dominated by the high ones), 0.73 for their
logarithms and 0.79 for the logarithm of the SE. What the rewrite added is speed (precomputed
f2-statistics cut runtime and memory by orders of magnitude, and classic ADMIXTOOLS has since
adopted some of those ideas) and an R interface in place of parameter files. Nobody chooses
between them for correctness; you choose for workflow, and translate settings when numbers must
line up.
Where the defaults part#
The site set. Both programs default to one set of sites for every f4-statistic in a model,
but they draw it from different populations. Classic qpAdm's default (allsnps: NO) intersects
the sites of the model's own left and right populations. ADMIXTOOLS 2's fast route fixes the set
when you extract f2: at the default maxmiss = 0, the sites present in every population in the
extraction. That equals the classic set only when the extraction holds exactly the model's
populations, and is stricter whenever it holds more, so a model re-run from a shared f2 cache sits
on fewer sites than the classic run it copies, before anyone errs. On genotype input the defaults
agree: allsnps = FALSE there is the model-wide intersection, and allsnps = TRUE is
the per-statistic mode above.
The ridge. Both stabilise the covariance inversion with a small ridge, and
fudge_twice = TRUE is ADMIXTOOLS 2's documented way to bring its p-values closer to the original
program's (fudge, above). Flegontova and colleagues set it
for their comparison for exactly that reason.
The input pipeline. Classic programs read the genotype files on every run; ADMIXTOOLS 2
workflows usually read an extract_f2 directory, whose population list and maxmiss decided the
site set long before the model ran. That extraction also detects pseudohaploid samples
automatically, where classic ADMIXTOOLS with inbreed: NO counts each observed site of a
pseudohaploid sample as two alleles (adjust_pseudohaploid = FALSE is the documented equivalent
of that setting). Add any gap between the panel a paper used and today's (a 2018 paper's AADR
predates the current release, and
labels move between releases) and most
"discrepancies" dissolve into inventory, not mystery.
Which classic you are matching#
"Classic ADMIXTOOLS" is not one program, and the version decides what a setting meant; a classic
log prints it on its ## qpAdm version: line. Up to ADMIXTOOLS 7.0 (qpAdm 1201), allsnps: YES
computed each f4-statistic on its own sites, as allsnps = TRUE does in ADMIXTOOLS 2. By 8.0.1
(qpAdm 2050) the same line calls qpfstats, an algorithm Flegontova and colleagues describe as
substantially different from ADMIXTOOLS 2's allsnps = TRUE; ADMIXTOOLS 2's counterpart is
extract_f2(..., qpfstats = TRUE). Recent classic releases also shrink the f4 covariance matrix
by default ("Oracle Assisted Shrinkage", oracle: YES), an adjustment the classic README calls
small with good genome-wide coverage and more noticeable with little data. qpadm() has no
argument for it; oracle: NO is the classic side's switch for compatibility with older releases.
The reproduction recipe#
To match a classic qpAdm result in ADMIXTOOLS 2, in order:
- The same AADR release and the same population labels.
- The same site regime. For a run with
allsnps: YESfrom before the qpfstats switch: genotype input withallsnps = TRUE. For a defaultallsnps: NOrun: genotype input withallsnpsleft atFALSE, or f2 extracted for exactly the model's populations atmaxmiss = 0. For a run fed byqpfstats: theqpfstats = TRUEextraction. fudge_twice = TRUE(no setting reproduces a recent release's default covariance shrinkage).- The default jackknife at 5 cM, no bootstrap, unconstrained weights.
Then expect close agreement, not identity. Residual daylight after all that points first at the
site set: print the per-statistic SNP counts and compare them with the paper's, if it reported
any (many did not, which is its own lesson:
reporting standards exist for this exact reason).
With the classic binaries installed, qpadm_wrapper() runs the original qpAdm from R and parses
its output, and plot_comparison() sets the two runs side by side.
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 on AADR
release Y, genotype input with allsnps = TRUE (or f2 blocks with maxmiss = m), default fudge
without fudge_twice, jackknife at 5 cM, unconstrained.
Ancient Ancestry, our qpAdm analysis, runs every model in one regime: genotype input with
allsnps = TRUE, the default fudge, block-jackknife errors and unconstrained weights. The model
record in each report's Your model view shows the counts that regime leaves behind (minimum SNPs per
f4, merged SNPs, jackknife blocks) beside the fit and every source's weight, SE and Z;
the record explained walks through it.
When you are not reproducing anything, do not copy classic settings out of habit: ADMIXTOOLS 2's defaults are fine choices for fresh work. What they are not, like any regime, is interchangeable mid-project. "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; its Appendix 1 benchmarks it against classic ADMIXTOOLS.)
- Harney, É., Patterson, N., Reich, D. & Wakeley, J. (2021). Assessing the performance of qpAdm. Genetics, 217(4), iyaa045. (The allsnps and missingness comparison.)
- Flegontova, O. et al. (2025). Performance of qpAdm-based screens for genetic admixture on graph-shaped histories and stepping stone landscapes. Genetics, 230(1), iyaf047. (The 8,580-model comparison of ADMIXTOOLS 2 with classic ADMIXTOOLS 7.0.)
- Patterson, N. et al. (2012). Ancient admixture in human history. Genetics, 192(3), 1065 to 1093. (Classic ADMIXTOOLS and the block jackknife convention.)
- Haak, W. et al. (2015). Massive migration from the steppe was a source for Indo-European languages in Europe. Nature, 522, 207 to 211. (The original qpAdm supplement.)
- ADMIXTOOLS 2 documentation: the qpadm(), extract_f2(), f2_from_precomp(), f4blockdat_from_geno() and qpfstats() references, the f-statistics article, and the tutorial's section on comparing results with classic ADMIXTOOLS.
- Classic ADMIXTOOLS: README.qpWave and README.qpfstats (the allsnps, qpfstats and oracle options).



