Skip to content

Menu

Search

🔍

qpAdm Tutorial: A Reproducible Workflow for Consumer DNA and AADR v66

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:

  1. Different proxy populations can all be plausible because they share the drift qpAdm can see.
  2. A plausible model can still be historically wrong if the real source is unsampled or the demographic history violates the model assumptions.
  3. 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
  1. Audit build, strand, overlap, and privacy
  2. Freeze targets, sources, rights, and chronology
  3. Compute f2 and model-free f3/f4 checks
  4. Rotate models and apply deterministic gates
  5. Report all survivors and the resolution ceiling
The critical change from the older tutorial is step 2: hypotheses and rejection gates are frozen before results are inspected. Every survivor remains a compatible proxy model, not a recovered people.ADMIXTOOLS 2

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: true

The 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_loadings

For 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

GateReject or flag whenWhy
Tail probabilityBelow the frozen threshold after the chosen multiplicity treatmentThe specified model is rejected relative to the right set.
CoefficientsOutside [0,1], or uncertainty crosses implausible valuesWeights are infeasible or poorly identified.
ChronologyA proposed source is younger than the target or historical eventA proxy cannot be a literal ancestor from the future.
Numerical conditioningCovariance diagnostics indicate near-singularityCollinear rights can make weights appear more precise than they are.
StabilityThe conclusion collapses under source order, chromosome blocks, or leave-one-out checksA robust interpretation should not depend on an arbitrary representation.
CompetitionA simpler or historically better proxy model survives equally wellOne passing model does not identify a unique source.

8. Interpret Without Overclaiming

Say“The model is compatible”

Name the target, proxies, right set, p-value, weights, uncertainty, SNP count, and software version.

Qualify“This proxy ranks well”

State whether chronology or another prior changed the rank and list statistically similar survivors.

Do not say“The highest p-value is the ancestor”

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
This is the pattern a careful qpAdm report should expose: strong separation across ancestry axes, weak separation among closely related Steppe proxies.AADR v66

Primary references