Skip to content
Ancestrify
All stories

qpAdm

By Andi Thomaj
9 min read

ADMIXTOOLS 2 parameters that change your qpAdm results, and how to match classic ADMIXTOOLS

The settings tutorials skip and reviewers ask about: extract_f2 versus genotype input, allsnps, maxmiss, fudge and fudge_twice, blgsize, boot, afprod and constrained. What each does, the measured stakes, and the settings that reproduce a classic ADMIXTOOLS result.

qpAdmMethodologyGuides

  1. The decision before all others: f2 blocks or genotype input
  2. The numerics: fudge, once or twice
  3. The uncertainty machinery: blgsize and boot
  4. The semantics: afprod, constrained and the rest
  5. Matching classic ADMIXTOOLS
  6. What does not differ
  7. Where the defaults part
  8. Which classic you are matching
  9. The reproduction recipe
  10. The reproducibility block
  11. References

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:

  1. The same AADR release and the same population labels.
  2. The same site regime. For a run with allsnps: YES from before the qpfstats switch: genotype input with allsnps = TRUE. For a default allsnps: NO run: genotype input with allsnps left at FALSE, or f2 extracted for exactly the model's populations at maxmiss = 0. For a run fed by qpfstats: the qpfstats = TRUE extraction.
  3. fudge_twice = TRUE (no setting reproduces a recent release's default covariance shrinkage).
  4. 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.

From €29.99 · one-time
The tested version of this question
A qpAdm model tested against AADR v66 and approved by a person, published with its p-value, every source's standard error and z-score, and the full right set, so the result can be argued with.
See Ancient Ancestry

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).

Related posts

Is Ancestrify legit? What it is, who runs it, and what it does not do (2026)
Is Ancestrify legit? What it is, who runs it, and what it does not do (2026)

A first-person answer to "is Ancestrify legit": the registered trader behind it, what each of the three analyses delivers and costs, where the data lives, how refunds work, what it never claims, and how to verify every statement yourself.

6 min read
Learn qpAdm: the complete guide, from zero to defensible models
Learn qpAdm: the complete guide, from zero to defensible models

A structured learning path through everything qpAdm: what to read in what order, from the f4-statistics underneath to running models in R, choosing outgroups, reading results and knowing the method's measured limits.

4 min read
qpAdm best practices: a working checklist, and where each rule comes from
qpAdm best practices: a working checklist, and where each rule comes from

A working qpAdm checklist: history type, pre-study odds, temporal order, right sets, parsimony, acceptance and reporting, each rule with its source and limits.

8 min read
Back to all stories
Ancestrify

Combining cutting-edge genomic science with rich historical records to map your ancestry across generations and continents.


© 2026 Ancestrify. All rights reserved. · Ancestrify is a trading name of Andi Thomaj, a sole trader registered in Tiranë, Albania · NUIS M61725001N
Card payments processed by POK Payments (RPay Ltd)VISAMASTERCARD