Before you begin
- qpAdm identifies models that are not rejected relative to chosen references; it does not discover true ancestors automatically.
- A p-value above 0.05 is not proof, and the highest p-value is not a source ranking.
- Freeze candidate sources and right populations before viewing results; rotate systematically instead of tuning until a favorite model passes.
- Consumer arrays are sparse, diploid views of one person. Treat cross-chip agreement as technical robustness, not biological replication.
What qpAdm Actually Tests
qpAdm evaluates whether a target can be represented as a mixture of specified left-side source populations relative to a set of right-side reference populations. Its tail probability comes from a rank test. A low value can reject the proposed model; a high value means the test did not find enough evidence to reject it under that design.
Three consequences follow:
- Different proxy populations can all be plausible because they share the drift qpAdm can see.
- A plausible model can still be historically wrong if the real source is unsampled or the demographic history violates the model assumptions.
- Changing right populations after inspecting results changes the question. Exploratory tuning must be labelled exploratory and confirmed on a frozen design.
The Reproducible Workflow
Evidence figure
A model-competition workflow, not a p-value hunt
- Audit build, strand, overlap, and privacy
- Freeze targets, sources, rights, and chronology
- Compute f2 and model-free f3/f4 checks
- Rotate models and apply deterministic gates
- Report all survivors and the resolution ceiling
1. Environment and Data
This tutorial uses ADMIXTOOLS 2 in R and the AADR v66.0 release. Use Linux, macOS, or WSL with current R and enough storage for the genotype panel and extracted f2 blocks.
# In R
install.packages('remotes')
remotes::install_github('uqrmaie1/admixtools')
library(admixtools)
packageVersion('admixtools')Record the AADR release DOI, genotype-panel type, ADMIXTOOLS version, operating system, input checksums, and every transformation command. A filename such as “latest” is not sufficient provenance.
2. Prepare Consumer Data Safely
Raw consumer genotypes are identifying data. Keep them out of public repositories, cloud build logs, screenshots, and browser-only ancestry calculators. Work locally and publish aggregate outputs only.
Before merging with AADR:
- Confirm the consumer file’s genome build and lift over only with a documented chain.
- Normalize chromosome names, reference/alternate alleles, and strand orientation.
- Remove ambiguous A/T and C/G SNPs unless strand orientation is independently known.
- Resolve duplicate positions and sample identifiers deterministically.
- Measure post-merge overlap; never infer it from the advertised chip size.
- Create a second view only when it represents a genuinely different overlap or QC condition.
A single modern individual can be used as a target for personal exploration, but standard errors and idiosyncratic family history limit population-level interpretation. Do not call one person a representative “Jatt,” “Punjabi,” or “Indo-Aryan population.”
3. Freeze Hypotheses
Write a machine-readable manifest before running qpAdm. It should name the target, candidate source families, fixed rights, chronological constraints, minimum SNP count, coefficient bounds, p-value threshold, multiple-testing procedure, and sensitivity checks.
target: TARGET_SAMPLE
source_families:
aasi: [AASI_PROXY_1, AASI_PROXY_2]
farmer: [TURAN_PROXY_1, TURAN_PROXY_2]
steppe: [STEPPE_PROXY_1, STEPPE_PROXY_2]
right_fixed: [OUTGROUP_1, OUTGROUP_2, OUTGROUP_3]
gates:
p_min: 0.05
coefficients: [0, 1]
require_target_younger_than_sources: true
require_source_order_invariance: true
report_all_survivors: trueThe placeholder labels are intentional. Select actual AADR population labels only after checking their archaeological date ranges, sample composition, relatedness exclusions, coverage, and publication metadata.
4. Compute f2 Blocks
ADMIXTOOLS 2 auto-detects EIGENSTRAT, packed ancestry map, PLINK, and PLINK 2 prefixes. Restrict extraction to the populations needed for the frozen analysis; large, indiscriminate right sets can create conditioning problems.
library(admixtools)
geno_prefix <- '/private/genotypes/analysis_panel'
f2_dir <- '/private/derived/f2_blocks'
analysis_pops <- unique(c(target, sources, right_fixed, rotating_candidates))
extract_f2(
prefix = geno_prefix,
outdir = f2_dir,
pops = analysis_pops,
overwrite = FALSE
)
f2_blocks <- f2_from_precomp(f2_dir, pops = analysis_pops)
count_snps(f2_blocks)The default missingness behavior is deliberately conservative. If you change maxmiss or use genotype-direct allsnps = TRUE, record the choice and confirm key results under an alternative missing-data treatment.
5. Run Model-Free Checks
Before mixture fitting, ask whether the target displays the broad relationships your hypothesis requires. Admixture f3 can support mixture between populations related to two sources; focused f4 contrasts can test whether the target distinguishes competing proxies.
# Negative f3 with |Z| >= 3 supports admixture between
# populations related to source_a and source_b.
f3_results <- f3(
f2_blocks,
pop1 = target,
pop2 = source_a,
pop3 = source_b
)
# Focused proxy comparison; choose A, B, C, D from a frozen design.
f4_results <- f4(f2_blocks, pop1 = A, pop2 = B, pop3 = C, pop4 = D)A non-significant f4 result does not prove two sources are identical. It can indicate insufficient resolution at the available SNP overlap.
6. Run and Rotate qpAdm
Run a predeclared model first, then rotate candidates systematically. The target is not part of the source vector.
fit <- qpadm(
f2_blocks,
left = sources,
right = right_fixed,
target = target
)
fit$weights
fit$popdrop
fit$f4_var_rcond
fit$f4_var_singular_loadingsFor a rotating design, split a frozen candidate pool between left and right while retaining fixed references:
rotation <- qpadm_rotate(
f2_blocks,
leftright = rotating_candidates,
target = target,
rightfix = right_fixed,
full_results = TRUE
)Use qpadm_multi() or qpadm_sweep() when the model grid is explicitly enumerated. Preserve the complete grid, including rejected and infeasible models.
7. Apply Acceptance Gates
| Gate | Reject or flag when | Why |
|---|---|---|
| Tail probability | Below the frozen threshold after the chosen multiplicity treatment | The specified model is rejected relative to the right set. |
| Coefficients | Outside [0,1], or uncertainty crosses implausible values | Weights are infeasible or poorly identified. |
| Chronology | A proposed source is younger than the target or historical event | A proxy cannot be a literal ancestor from the future. |
| Numerical conditioning | Covariance diagnostics indicate near-singularity | Collinear rights can make weights appear more precise than they are. |
| Stability | The conclusion collapses under source order, chromosome blocks, or leave-one-out checks | A robust interpretation should not depend on an arbitrary representation. |
| Competition | A simpler or historically better proxy model survives equally well | One passing model does not identify a unique source. |
8. Interpret Without Overclaiming
Name the target, proxies, right set, p-value, weights, uncertainty, SNP count, and software version.
State whether chronology or another prior changed the rank and list statistically similar survivors.
qpAdm p-values are not posterior probabilities of cultural or genealogical identity.
Do not interpret negative coefficients as proof that a culture contributed nothing. Do not interpret failure of one Gonur group as absence of all BMAC-related ancestry. Do not combine two chips from the same person and call them independent replication.
9. Reproducible Reporting
A publishable result should include:
- AADR release DOI and annotation version.
- Target data source, build, merge procedure, final SNP overlap, and privacy statement.
- Every source and right population with dates and sample counts.
- The full attempted model grid, not only passing models.
- Weights, standard errors, p-values, rank information, and conditioning diagnostics.
- Frozen rejection gates, multiple-testing treatment, and all sensitivity checks.
- A plain-language claim ceiling naming what the analysis cannot distinguish.
- Checksums for scripts, manifests, and aggregate outputs.
Worked South Asian Example
In the current Sohi analysis, broad AASI-related and Steppe-related admixture is supported by model-free tests, while a Central Asian farmer-related axis recurs across the qpAdm screens. Several Steppe proxies survive: Czech Corded Ware passes 14 of 15 panels and Samara Srubnaya 13 of 15, while chronology weighting favors Srubnaya operationally. Only 5.5% of focused Steppe-proxy pairs are separable.
The correct conclusion is therefore not “Srubnaya was the ancestor.” It is: a Steppe-related source is robust, a 1900–1500 BCE Steppe–Turan contact window is historically admissible, and the exact Steppe and farmer cultures remain unresolved.
Evidence figure
Broad signal, narrow identification
Primary references
- ADMIXTOOLS 2 documentation and vignettes.
- Harney et al. 2021, simulation-based qpAdm assessment and user guide.
- Yüncü et al. 2024, recent and complex demographies.
- Allen Ancient DNA Resource v66.0.