Benchmark report

Alignment-free QC benchmark: snipe

How closely snipe's sketch-based QC estimates match alignment ground truth, scored per sequencing workload and per k-mer configuration on the dog genome. Whole-genome assays, exome capture, and RNA are each scored separately.

Note
This page previews the whole benchmark. The manuscript reports a chosen set of metrics and configurations (justified there). As shown below, other configurations can score higher: the Free (all k) mode is the best achievable if every k-mer parameter were tuned. Use this to explore the space.
The experiment

What we tested, and why

Sequencing quality control normally means aligning reads to a reference and reading depth, coverage, error and mapping statistics off the alignment. By contrast, snipe skips that step: it builds a FracMinHash k-mer sketch of the raw reads, compares it to a sketch of the reference, and estimates the same quantities directly. Whether that shortcut is trustworthy is an empirical question, and this benchmark addresses it directly. We simulated reads for which the truth is known exactly, ran both a sketch-based and an alignment-based pass over the same reads, and measured how closely the two agree.

The appeal of the alignment-free route is practical. Aligning deep libraries is slow and reference-heavy, and QC is often the one step you want before committing to that cost. If a compact sketch can reproduce the alignment's verdict, QC becomes something you can run directly on the raw reads, with no alignment step. But QC is only useful if it is right, and a sketch discards most of the data by construction, so the estimates have to be validated against the alignment they are meant to replace, across the range of conditions a real library might present.

We built that range on the dog genome, Canis familiaris CanFam3.1. Reads were simulated across a grid of two independent perturbations: sequencing error, the noise a sequencer adds to otherwise-correct reads, and mutation, real differences between the sampled genome and the reference. Both were swept from zero to 5%, from an exact reference_match control to heavily diverged libraries, so the grid spans both the easy cases and the divergence where a sketch should fail.

Datasets & commands

Five assay types

A whole-genome library and an exome capture fail in different ways, so we simulated five assay types, not one.

  • Whole-genome shotgun 43 libraries
    wgsim, 150 bp paired-end, depths 0.5×, 1×, 5×, 30×
    Tests QC from barely-there to comfortable coverage.
  • Whole-genome with indels 33 libraries
    wgsim, held at 5×, indels raised to 15%, 30%, 45% of all mutations
    A targeted stress test of the metric most sensitive to gaps.
  • Whole-exome capture 33 libraries
    NEAT, depths 10×, 40×, 80×
    Reads concentrate on a small target, so depth and breadth are scored on the captured regions rather than genome-wide, and it is scored on its own.
  • Metagenomic 11 libraries
    5× dog reads plus a fixed block of real off-reference reads (SRR8073716); only 45.8% on-reference
    A direct test of whether the sketch recovers the true on-reference fraction.
  • RNA 30 libraries
    Polyester, 5–25M reads against a 61,007-transcript reference; scored on its own
    A short, isoform-redundant transcriptome behaves unlike any genomic library, so mixing it in would only blur both.

Every library is defined by the same error × mutation grid below, crossed with that assay's own depth, indel, or read-count axis.

Against each library we run the two arms on identical reads. On one arm, snipe sketches the reads and estimates QC without ever aligning them; in parallel, bwa memsamtools → Qualimap, with a custom CIGAR/MD parser, produce the alignment-based truth. Sequence change is counted as events (one SNP is one, a 20 bp indel is one) to match what the sketch actually measures; mapping rate is taken read-level (mapped reads over total, which unlike the base-level rate is not blind to unmapped reads); and for the exome, depth and breadth are measured on-target. What the tables and figures below report is simply how far snipe's estimate sits from that truth, summarised as a single score, across every assay and every k-mer setting.

The error × mutation grid

The eleven conditions every genomic assay is swept across (RNA uses a ten-condition variant). Sequencing error is added by the read simulator; mutation is introduced into the reference before reads are drawn.

conditionsequencing errormutation
reference_match00
no_error_low_variance00.1%
no_error_med_variance01%
no_error_hi_variance05%
low_error_no_variance0.1%0
low_error_low_variance0.1%0.1%
med_error_no_variance1%0
med_error_med_variance1%1%
hi_error_no_variance5%0
hi_error_low_variance5%0.1%
hi_error_med_variance5%1%
Software, commands & parameters

Every command below is templated from the workflow; ⟨angle-bracket⟩ terms are the values swept across libraries. Reads are 150 bp paired-end throughout; genomic fragments are 350 ± 50 bp, RNA fragments 200 ± 25 bp. The reference is Canis familiaris CanFam3.1 (GCF_000002285.3).

wgsim  →  WGS, WGS+indels, metagenomic

These three assays are the same wgsim command; they differ only in the depth, the indel sweep, and, for metagenomic, a spike-in appended afterwards. Sequencing error and mutation are each swept over 0 / 0.001 / 0.01 / 0.05 in all three.

wgsim -h \                          # haploid
      -N ⟨n_reads⟩ -1 150 -2 150 \         # paired 150 bp
      -d 350 -s 50 \                       # fragment 350 ± 50 bp
      -e ⟨error⟩ -r ⟨mutation⟩ \             # swept 0 / 0.001 / 0.01 / 0.05
      -R ⟨indel_frac⟩ -X ⟨indel_ext⟩ \       # see per-assay settings below
      -S ⟨seed⟩  CanFam3.1.fa  r1.fq  r2.fq
seqkit fq2fa r1.fq > r1.fa               # reads are sketched as FASTA
assaydepth (-N)indels (-R / -X)thenlibraries
WGS0.5×, 1×, 5×, 30×0.15 / 0.3 (fixed)none43
WGS+indels0.15/0.30/0.45, 0.3/0.6/0.9none33
metagenomic0.15 / 0.3 (fixed)+ spike-in ↓11

Metagenomic only: append a fixed block of real, off-reference metagenome reads (SRR8073716), leaving 45.8% of reads on-reference.

cat 50M_SRR8073716_1.fa >> r1.fa          # real off-reference spike-in
cat 50M_SRR8073716_2.fa >> r2.fa
NEAT  →  WXS (whole-exome capture)

On-target exome sequence is extracted per chromosome so NEAT sees only capture regions; coverage then equals on-target depth (10× / 40× / 80×). The golden VCF gives the true variant count.

bedtools getfasta -fi CanFam3.1.fa -bed ⟨chrom⟩_exome.bed -fo exome.fa
neat read-simulator -c config.yml -o out -p n
# config.yml:  read_len 150, coverage ⟨10/40/80⟩, ploidy 1, paired_ended true
#              fragment_mean 350, fragment_st_dev 50
#              avg_seq_error ⟨error⟩, mutation_rate ⟨mutation⟩, rng_seed ⟨seed⟩
Polyester  →  RNA

Mutations are introduced as SNP substitutions (length-preserving, no indels), the transcriptome (61,007 transcripts) is extracted from the mutated genome, and Polyester draws reads with uniform fragmentation (no positional bias).

python mutate_genome.py --input CanFam3.1.fa \
      --rate ⟨mutation⟩ --output mutated.fa   # SNP substitutions only
# → extract 61,007-transcript transcriptome from the mutated genome
Rscript simulate_polyester.R --transcriptome txome.fa \
      --num-reads ⟨5M/15M/25M⟩ --error-rate ⟨error⟩ \
      --read-length 150 --frag-mean 200 --frag-sd 25  # Polyester, bias=none, paired
Alignment ground truth (bwa, samtools, Qualimap)

The same reads are aligned and profiled. Qualimap gives depth, breadth and mapping; a custom parser counts sequence change as events (one SNP = 1, a 20 bp indel = 1) to match what the sketch measures.

bwa index CanFam3.1.fa
bwa mem -t N CanFam3.1.fa r1.fa r2.fa | samtools view -bS - > aln.bam
samtools sort -o aln.sorted.bam aln.bam  &&  samtools index aln.sorted.bam
qualimap bamqc -bam aln.sorted.bam -outdir qc -nt N --java-mem-size=24G
python bamqc_final.py aln.sorted.bam            # event-based sequence-change truth
snipe  →  alignment-free QC (v2.1.0)

Each library is sketched and QC'd against a reference sketch. For the exome, the merged capture regions are passed as --amplicon so depth and breadth are reported on-target.

snipe sketch --sample reads.fa -o reads.sig \
      --k1-size ⟨k1⟩ --k2-size ⟨k2⟩ --scale ⟨scale⟩ --name ⟨id⟩
snipe qc --samples-list siglist.txt \
      --reference genome.sig --amplicon exome.sig \    # --amplicon = exome ROI (drives the WXS on-target metrics)
      -o qc.tsv -v --advanced --hidden

The full k-mer sweep behind these pages, 231 configurations per library:

k1 (core)21, 25, 31, 35, 41, 45, 51, 55, 61, 65, 71  (11 values)
k2 (edge)k1 + {2, 4, 6, 8, 10, 14, 18}  (7 extensions)
scale1,000 / 10,000 / 100,000  (FracMinHash)
Software
snipe v2.1.0alignment-free QC (FracMinHash sketch + qc)
wgsimwhole-genome, indel & metagenomic reads
NEATwhole-exome capture reads
Polyester (R)RNA-seq reads
bwa, samtools, Qualimapalignment ground truth
seqkit, bedtoolsread/format and region handling

The snipe version is verified as v2.1.0; other tool versions are pinned in the project conda environments.

Scoring

How a single score is built

Each cell in the tables below is one number in [0,1] that summarises how closely snipe's estimate matches the alignment, blended across the four QC metrics and aggregated across the assays in a workload. Expand for the exact formula.

The full definition

Every value below is in [0,1], higher is better, and is the best achievable score for the current filters, shown with the k-mer configuration that achieves it.

Four QC metrics

Sequence-change rate, mean depth, mapping rate, coverage breadth. (The manuscript states why these metrics were selected; here they are all shown.) snipe's estimate for each is compared to the alignment ground truth (Qualimap / bamqc; read-level mapping rate; event-based sequence-change rate).

Per-metric accuracy (hybrid)

Each metric's accuracy combines two things equally:

accuracy = ½ × [ (1 − min(MdAPE, 1))  +  max(0, r) ]

Closeness is 1 − min(MdAPE, 1), where MdAPE is the median across a dataset's libraries of the relative error |estimate − truth| / truth (median absolute percentage error, the median rather than the usual mean; a 5% typical error gives closeness 0.95). Agreement is max(0, r), the Pearson correlation between snipe's estimates and the truth across libraries, clamped at 0. The two are averaged 50 / 50. The agreement term is only included where the ground truth actually varies (so a correlation is meaningful); where the truth is near-constant, accuracy is closeness alone.

Aggregation

Per assay: the four metric accuracies are combined into two flavors, a plain average (equal) and one that weights sequence-change ×2 (the metric the alignment truth pins down most directly). Per workload: the geometric mean across the assays in the bundle, so a single weak assay pulls the bundle down harder than a plain average would.

Two k-modes

Fixed restricts to k1 ∈ {21, 31, 51} (the manuscript's operating points). Free covers the entire sweep (k1 ∈ {21…71}, all edge extensions, all scales) and reports the best score.

Why WXS and RNA are separate

Exome capture (WXS) and RNA are targeted or transcriptome assays with a small effective reference, so both do best at small k1 (RNA strongly so, WXS only mildly), whereas the whole-genome assays (WGS, indels, metagenomic) favour large k1. They are scored on their own: WXS because its depth and breadth are measured on-target rather than genome-wide, RNA because it maps to a separate transcriptome; bundling either into the large-k1 whole-genome group would average opposite behaviors together.

Results

Scores by workload & configuration

Reading the score. Every number below measures how closely snipe's alignment-free estimate reproduces what the alignment actually found, combining how close the estimate is with how well it tracks the truth across a dataset's libraries. 1.00 means snipe matches the alignment result. At their best k-mer setting, genomic assays reach 0.98–0.99 (estimates you can act on); RNA, the hardest case, tops out near 0.90 (still usable, but expect real error). Lower scores mean growing disagreement with the alignment.
0.50weak 0.90RNA 0.95strong 1.00exact

Genomic workloads

the 3 whole-genome datasets and every combination of them

Each row is a workload: one dataset, or a bundle of several. A bundle's score is the geometric mean across its datasets; it answers “how well does snipe do overall if I run these assay types?”, and it is not a mixed sample. 1.00 = snipe reproduces the alignment result exactly. Hover a label to see the dataset; click to see every k-mer setting.

relative to shown0.501.00

Exome capture (WXS), scored independently

targeted assay, small effective reference

WXS is not mixed with the whole-genome assays. Its reads cover only the captured exome, so depth and breadth are scored on-target, and its small effective reference makes it favour small k1, like RNA.

RNA, scored independently

transcriptome, k-sensitive

RNA is not mixed with the genomic assays. Its accuracy peaks at small k1 and degrades as k1 grows (edge-mer saturation on the short transcriptome reference).

Decision explorer

how the score moves across configurations

Does the k-mer setting matter for my data? A flat curve means snipe is insensitive to the choice; a falling curve means the setting matters and small k-mers are better.

config sensitivity

Score vs core k-mer size

k1 × k2 surface

Score heatmap

candidate scan

Every workload at the chosen config

config

Conclusions
Findings & conclusions

What the benchmark shows. On the Canis familiaris CanFam3.1 reference, across simulated sequencing workloads, snipe's alignment-free QC estimates reproduce alignment-derived ground truth closely, with best-achievable composite accuracy above 0.96 for the whole-genome workloads and for exome capture, and about 0.90 for RNA, the hardest case. These are the best scores over the k-mer sweep; a single compromise configuration stays within 0.02 of each workload's own best, RNA excepted (below).

Genomic QC is recovered without alignment

For whole-genome (150 bp), indel-enriched and metagenomically-contaminated reads, composite scores sit near 0.98 (WGS 0.98, indels 0.99, metagenomic 0.98). Sequence-change rate is the strongest signal: snipe's estimate matches the event-based alignment truth at r ≥ 0.999 for all three. Where a metric carries genuine dynamic range (sequence-change, and depth in coverage-varying designs), snipe tracks it closely; where the truth is saturated by construction (mapping and breadth for fully on-reference reads) the estimates agree in value even though a correlation there is uninformative. Because those two metrics are near 1 by construction for on-reference reads, they contribute high closeness almost automatically; the sequence-change-weighted score is the more stringent test of snipe's skill.

Exome capture is close behind, as a targeted assay

Whole-exome capture (WXS) is scored on its own because it is a targeted assay: reads cover only the captured regions, so depth and breadth are measured on-target rather than genome-wide. Its best composite accuracy is about 0.97, close to the whole-genome workloads, but it peaks at small k1 (best at k1 = 21) rather than large, because only a small fraction of the genome is on-target and the informative sketch is correspondingly small. Sequence change is recovered well (r ≈ 0.97 at k1 = 21, falling to 0.90 by k1 = 51), while mapping and breadth saturate near 1.0, as expected for reads that are almost entirely on-target.

Mapping rate reflects on-reference content in mixed samples

The metagenomic workload is dog whole-genome reads spiked with a fixed block of off-reference reads; mapping such a sample to the dog reference recovers only its on-reference fraction. Measured against the appropriate read-level ground truth (mapped reads / total), snipe's alignment-free mapping estimate agrees closely (0.46 versus the fixed true fraction of 0.458): the sketch-based rate reflects the same on-reference fraction the aligner does. The base-level Qualimap rate is computed only over reads that already mapped, so it saturates near 1.0 and is blind to the unmapped fraction; using it as ground truth is what previously made this metric look like a failure. This is agreement on a mixed sample once the unmapped noise is isolated, not an active contamination-detection claim.

RNA is the systematic exception

Scored independently against the transcriptome, RNA is the one workload where accuracy is materially lower (0.88–0.90) and where k-mer choice matters. Its sequence-change accuracy rises from r ≈ 0.53 at k1 = 51 to r ≈ 0.87 at k1 = 21, and the composite peaks near k1 = 21–25 before declining monotonically. This is consistent with edge-mer saturation on a short, isoform-redundant reference: a single change removes roughly k2 consecutive k-mers, so long extensions leave too few surviving k-mers and the inferred per-base rate runs to its ceiling. A residual ~1% floor in the alignment truth itself (cross-isoform mismatches under a splice-unaware aligner) further limits agreement at low divergence. Small core k-mers are therefore the appropriate operating point for transcriptomic input.

Why the best core k-mer size depends on the assay

The core k-mer size (k1) that gives the most accurate scores is not the same for every assay. For whole-genome, indel and metagenomic reads, accuracy climbs as k1 grows, so the best size is the largest one tested (composite accuracy, averaged over the edge and scale settings at each k1 rather than the best-achievable maximum, rises from about 0.95 at k1 = 21 to 0.97 at k1 = 51). For exome and RNA reads it does the reverse, falling as k1 grows (exome 0.95 down to 0.92, RNA 0.84 down to 0.64), so the best size is the smallest one tested. The dominant driver is visible directly in the sketches, and it centres on a single quantity: how many informative k-mers, meaning the k-mers a sample shares with the reference, survive in the sketch.

A larger core k-mer makes each estimate cleaner, because long k-mers rarely match the reference by chance, so the error, depth and coverage signals are sharper. But long k-mers are also rarer, so the sketch keeps fewer of them. Whether this cleaner-but-sparser trade pays off depends on how many informative k-mers the reference can supply. The dog genome (2.4 Gb) always supplies plenty: its reference sketch even grows, from about 201,000 to 225,000 distinct k-mers, as k1 rises, and a whole-genome sample still matches roughly 100,000 of them at k1 = 21 and 67,000 at k1 = 51. With that much signal to spare, the cleaner long-k-mer estimate wins, so the genomic assays do best at large k1.

The exome target and the transcriptome are tiny by comparison, so their sketches are starved of informative k-mers, and a larger k1 only makes them sparser. An exome sample matches only about 11,000 k-mers (only around 5% of the genome is on-target), and an RNA sample only about 4,000 at k1 = 21, dropping to 2,700 at k1 = 51 as the transcriptome sketch itself shrinks by roughly 30%. At the limit, an RNA sample at k1 = 51 has to estimate its entire error and mutation rate from only a handful of distinguishing k-mer observations (single digits for the low-divergence libraries), so the estimate turns noisy and its agreement with truth falls from 0.87 to 0.53. With so little signal, the smaller k-mer wins, so exome and RNA peak at k1 = 21.

The evidence points to sketch size, rather than any property of the sequences themselves, as the driver. Shrinking the sketch a different way, by coarsening the FracMinHash scale at a fixed k1 = 51, reproduces the same collapse: RNA's sequence-change agreement falls from 0.84 to 0.60 to 0.15 as the scale discards ten and then a hundred times more k-mers, with k1 never changing. Two plausible alternative explanations do not hold. The simulated error and mutation levels are identical across all five assays, so divergence cannot be responsible; and coverage runs the opposite way, since the exome reaches the highest on-target depths tested (up to 80×) yet still prefers the smallest k1, because extra reads add depth per k-mer but cannot add new informative k-mers.

Accuracy is robust to k, with one caveat

For genomic workloads the composite is nearly invariant to core k-mer size, edge extension and FracMinHash scale: a single compromise configuration (k1 = 31, k2-extension = 6, scale = 1,000) lands within 0.02 of every genomic workload's own optimum, and of the exome's. Only RNA benefits materially from tuning (+0.06 by moving to k1 = 21–25). Searching the full sweep instead of the fixed k1 ∈ {21, 31, 51} grid recovers only marginal accuracy (for example the genomic bundle rises from 0.980 to 0.984 by allowing k1 = 71), indicating the method is not sensitive to precise parameter choice for genomic and exome workloads within a sensible range (RNA excepted, as above).

One caveat on the yardstick itself: the alignment is treated as ground truth, but it is not error-free. Under the most diverged conditions (5% error or mutation) bwa mis-maps and soft-clips a fraction of reads, so the truth carries its own uncertainty, most visibly for RNA, where cross-isoform mapping leaves a ~1% floor, but present for the genomic assays too. A perfect score is agreement with the aligner, not with absolute reality. More broadly, these results are simulation-derived and specific to CanFam3.1; absolute values will shift with reference completeness, read chemistry and divergence. The metrics and configurations emphasized in the manuscript are selected for the reasons stated there; this page previews the entire configuration space so the sensitivity of each conclusion to the k-mer parameters can be inspected below.

Data

Downloads

The source tables and the computed scores behind every number on this page. Run the two build scripts on the two source inputs to reproduce the computed tables exactly.

filewhat it is
snipe_benchmark_bundle.zipeverything below except the large master table (tables, scripts, README)
Source inputs
comparison_subset.tsvsnipe estimates vs the alignment ground truth, per sample and k-config. The main input.
consolidated_df_clean.tsv.gzfull master table (gzipped, about 20 MB); source of the read-level mapping ground truth.
Computed tables
composite_scores.tsvcomposite score per workload and config, all six flavors.
accuracy_atomic.tsvper assay, config and metric: MAPE, Pearson r, accuracy.
composite_full_all_k.tsvfull per-config grid (the drill-down source).
best_config_per_combo.tsvrecommended config per workload.
headline_scores.tsvbest score per workload.
robustness.tsvone global config versus each workload's own best.
score_app_data.jsonthe exact data object this page renders.
Build scripts
build_composite_score.pysource inputs to the composite tables.
build_score_app_data.pycomposite tables to the page data.
_readlevel_mapping.pyread-level mapping ground-truth helper.
README.txtfile descriptions, the k-mer grid and the grouping.

Grid. The full k-mer grid is complete for every assay: core size k1 (11 values), edge extension k2 (2, 4, 6, 8, 10, 14, 18) and FracMinHash scale (3 values).