Using your own data

The tutorial runs on a small simulated dataset with human-like parameters. Applying sweepLink to your own data is the same workflow, but a handful of settings stop being someone else’s defaults and become decisions you have to make.

This page is the checklist. Each item links to the detail.

1. Get your data into the right shape

SweepLink reads allele counts through time, not a VCF, so you need to use sweeplink-vcf2input script:

$ sweeplink-vcf2input --vcf mydata.vcf.gz --samples samples.txt \
      --time-direction bp --out-prefix mydata

Two things to get right:

--time-direction

Whether a larger number in your sample list means older (bp) or newer (forward). There is no default, because guessing wrong silently reverses your time series and every inference with it.

--ploidy

diploid by default. Use pseudo-haploid for low-coverage ancient DNA, where one allele is sampled per individual rather than a genotype called.

Full options: sweeplink-vcf2input. Formats: file formats.

Note

Unphased genotypes are fine. SweepLink never resolves haplotypes — it only ever reads a count of one allele out of n sampled chromosomes, so counting copies per site is all that is needed. The correlation between neighbouring loci is modelled from their physical distance in base pairs, not from linkage disequilibrium, so no recombination map is needed either.

What the defaults do assume is that you know which allele is derived. That is a separate question from phasing, and it is the next step.

2. Set the mutation rates, and decide whether your data is polarised

--mu_a_A is mandatory and has no default. The tutorial’s 1e-8 is a human per-generation rate; use one appropriate to your species.

By default sweepLink assumes you know which allele is ancestral. Two defaults encode that assumption:

Default

What it assumes

--mu_A_a 0

The derived allele can arise but never revert — a direction you have to know to assert.

--newMutPrior neutral

The 1/x density, which describes a derived variant entering at low frequency.

If your data is polarised — you have an outgroup, or otherwise know the ancestral state — leave both alone.

If it is not, change both: make the mutation rates symmetric and both priors uniform.

$ ./sweeplink infer ... --mu_a_A 1e-8 --mu_A_a 1e-8 \
      --forwardPrior uniform --newMutPrior uniform

Any REF/ALT assignment then works. The magnitude of s stays meaningful; its sign does not, since it now refers to whichever allele you happened to label. Details in the FAQ.

3. Check the prior on the population size

This is the default most likely to be wrong for you. SweepLink puts a Gamma prior on log10N whose defaults centre it on N = 10,000 with a spread of one order of magnitude — a human-shaped assumption.

If your species is far from that, re-centre it:

$ ./sweeplink infer ... --log10N.alpha 36 --log10N.lambda 12   # centres on N = 1,000

The arithmetic, a table of worked values, and a way to check where your data alone put N before you choose, are in the FAQ.

Warning

--N sets only the value the chain starts from. It does not move the prior.

4. Decide how to split the work

Runtime scales with loci × time points × iterations, and the likelihood parallelises across loci (--numThreads). For anything genome-scale, run one job per chromosome rather than one large job.

Put each run in its own directory with a shared name, and the companion scripts will treat them as one analysis:

$ sweeplink-plot   --dirs chr1 chr2 chr3 --run-name sweeplink
$ sweeplink-extract --dirs chr1 chr2 chr3 --run-name sweeplink --out-prefix round2

See combining several runs.

5. Run the two rounds

From here the workflow is exactly the tutorial’s:

  1. Scaninfer across all loci, linkage on, N estimated.

  2. Shortlistsweeplink-extract picks the loci under selection and prints the command for round 2, with N already filled in.

  3. Refineinfer again on the shortlist only, with N fixed and --linkage false, because the survivors are no longer neighbours.

Step 3 and Step 4 walk through both, and how it works explains why the second round is a separate run rather than a setting.

Sanity checks before you trust the output

  • The echoed configuration. Every run prints what it read — loci, samples, chromosomes, the grid on s, the mutation rates. If the locus or sample count is not what you expect, the input files are not what you think they are.

  • Acceptance rates after burn-in. SweepLink retunes proposals between burn-in rounds; rates near 0 or 1 after tuning mean the chain is struggling.

  • The posterior of N. sweeplink-plot-posteriors --prefix myrun shows the whole shape. If it is pinned against the edge of your prior, the prior is fighting the data.

  • Two seeds. Runs with different --fixedSeed that disagree have not converged. Raise --iterations.