Ancestrify
All stories

qpadm

By Andi Thomaj
4 min read

Running qpAdm in R with ADMIXTOOLS 2: a working tutorial

From genotype files to a tested model: f2 extraction, qpadm() and its output tables, the arguments that silently change results (allsnps, fudge_twice, constrained), and the protocol discipline the code will not enforce for you.

qpadmguidemethodology

  1. Setup
  2. The two-step workflow
  3. Reading the output
  4. The arguments that silently change results
  5. The discipline the code will not enforce
  6. References

Everything qpAdm — the method behind a decade of ancient-DNA papers and our paid analysis — is free software: the qpadm() function of the ADMIXTOOLS 2 R package (Maier et al. 2023). This is a working tutorial for running it yourself: the setup, the calls, the output tables, and — the part no README covers — the arguments and protocol choices that silently change your results.

If you want the modelling without the pipeline, that exists too: the free AdmixTools 2 Lab runs f-statistics, qpWave and qpAdm against a curated ancient panel in the browser, and the Model Lab does it on your own genome merged into AADR. This post is for the readers who want the R console.

Setup#

ADMIXTOOLS 2 installs from GitHub (uqrmaie1/admixtools); on most systems devtools::install_github("uqrmaie1/admixtools") plus a compiler is the whole story. Data must be EIGENSTRAT or PACKEDANCESTRYMAP genotypes — practically, that means the AADR download, with your own genotypes merged in if you intend to model yourself. The merge is its own craft (position intersection, strand hygiene, build discipline); sanity-check any consumer file first with the free file check.

The two-step workflow#

ADMIXTOOLS 2's speed comes from precomputing f2-statistics once, then reusing them across thousands of models:

library(admixtools)
 
extract_f2("path/to/geno_prefix", "f2_dir",
           pops = my_pops, maxmiss = 0)   # once, slow
f2 <- f2_from_precomp("f2_dir")           # fast forever after
 
left  <- c("Anatolia_N", "Yamnaya_Samara", "WHG")
right <- c("Mbuti.DG", "Ust_Ishim.DG", "Kostenki14", "MA1",
           "Han.DG", "Papuan.DG", "Onge.DG", "Karitiana.DG",
           "EHG", "Iran_N", "Levant_N")
qpadm(f2, left, right, target = "MyKit")

The right set above is the standard spine plus era contrasts — not a decoration to copy blindly but the half of the model that decides whether it can be tested at all.

The sparse-data exception, immediately: precomputed f2 blocks restrict every statistic to sites present across all populations. With low-coverage ancients that discards most of the data — the audit's measured penalty reaches SE 9.994 versus 0.035 at 90% missingness. The fix is classic qpAdm's allsnps behaviour, which in ADMIXTOOLS 2 requires skipping the f2 directory and passing the genotype prefix directly:

qpadm("path/to/geno_prefix", left, right, target = "MyKit",
      allsnps = TRUE)

Slower, and usually right for real ancient panels. Whichever you choose, hold it constant across every model you intend to compare.

Reading the output#

qpadm() returns the tables a published model record is built from:

  • weights — per source: weight, se, z. The three-number reading: a weight whose 2-SE interval covers 0 is a source the data cannot certify; negative weights are a diagnosis, not a nuisance.
  • rankdrop — the rank test: chi-square, dof (= outgroups − sources for the full model) and p per tested rank, plus p_nested comparing adjacent ranks.
  • popdrop — every sub-model from dropping sources: its p, weights and a feasible flag. The discipline it encodes: if a simpler model survives, publish the simpler model.

The arguments that silently change results#

  • allsnps — see above; the largest single lever on sparse data.
  • fudge_twice = TRUE — applies the numerical ridge a second time, matching classic qpAdm's p-values. Set it when comparing against published numbers; either way, consistently.
  • constrained = TRUE — forces weights non-negative. Never for screening: an unconstrained negative weight is information about a wrong or missing source, and constraining hides it.
  • blgsize — jackknife block size, default 0.05 Morgans (5 cM). The convention behind every published SE; change it only knowingly.
  • boot — bootstrap instead of jackknife resampling. Jackknife SEs are the ones comparable to the published literature.

Every knob above has a fuller treatment — what it does, the measured stakes, when to deviate — in the parameters reference, with the classic-vs-2 guide covering the settings that reproduce published numbers from the original software. And if your own file is not yet merged into the AADR, the data-preparation guide is the missing chapter before this one.

Batch helpers exist (qpadm_rotate(), qpadm_multi()) and they are exactly where the false-discovery hazard lives: an unstratified rotating screen runs a measured 72–100% FDR. Enumerate to map the space; never let the enumeration pick the winner.

The discipline the code will not enforce#

qpadm() will happily run models that violate every assumption behind the statistics. The protocol — from the audit literature, and the difference between output and results:

  1. Temporal stratification: no source younger than the target. (A modern kit against ancient sources satisfies this automatically.)
  2. Lowest rank first: one-stream explanations before two, two before three; p_nested as referee.
  3. Never rank surviving models by p — the best p identifies the true model 48% of the time. Margins, feasibility and stability across right-set variations do the choosing.
  4. Composite feasibility: p above threshold and weights bounded inside (0,1) within error and trailing simpler models rejected — the criteria that cut measured FDR severalfold.
  5. Report the family, not the winner — state which models also passed and what they agree on; single-winner claims are the overfit the auditors keep finding.

That protocol, applied by hand at roughly four hundred runs per order against one bar (p > 0.05, every |Z| > 3, every SE < 0.10), is the entirety of what the paid analysis adds to the free software you have just installed — plus the merge, the curated panels, and a written model record at the end. Run it yourself, buy it run, or both: the method is the same, which is exactly the point.

From €29.99 · one-time
The tested version of this question
A qpAdm model composed, run and checked by hand against AADR v66, 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 the qpAdm analysis

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.)
  • Harney, É., Patterson, N., Reich, D. & Wakeley, J. (2021). Assessing the performance of qpAdm. Genetics, 217(4), iyaa045.
  • Flegontova, O. et al. (2025). Performance of qpAdm-based screens. Genetics, 230(1), iyaf047.
  • ADMIXTOOLS 2 documentation and source: uqrmaie1.github.io/admixtools.

Related posts

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.

3 min read
qpAdm best practices: the current checklist, with the numbers behind every rule
qpAdm best practices: the current checklist, with the numbers behind every rule

The definitive working checklist for qpAdm in 2026 — temporal stratification, right-set construction, lowest-rank-first search, composite feasibility and reporting standards — each rule carrying its measured justification from the 2021–2025 audit literature.

4 min read
Classic ADMIXTOOLS vs ADMIXTOOLS 2: why your qpAdm numbers differ, and how to match them
Classic ADMIXTOOLS vs ADMIXTOOLS 2: why your qpAdm numbers differ, and how to match them

Same model, different p-value: the real differences between original qpAdm and ADMIXTOOLS 2 — allsnps semantics, fudge_twice, f2 precomputation — and the settings that reproduce classic behaviour when you need to.

3 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