All notable changes to svaba are documented here.
The format is based on Keep a Changelog,
and svaba follows Semantic Versioning
(MAJOR.MINOR.PATCH):
- MAJOR — incompatible changes to output schemas (e.g.
bps.txt.gzcolumns), the VCF representation, or CLI behavior that breaks existing pipelines. - MINOR — new functionality (subcommands, flags, outputs) that is backward compatible.
- PATCH — bug fixes and internal changes with no interface impact.
- The human-edited version and date are the two constants
SVABA_VERSION/SVABA_DATEinsrc/svaba/SvabaOptions.h. To cut a release, bump those, add a section here, and tag the commit (git tag vX.Y.Z). - The build commit is stamped automatically by CMake at build time into
a generated header (
SvabaGitVersion.h) — no manual step.svaba --versionprints the semantic version plus that commit (anddescribe, and adirtyflag if the working tree had uncommitted changes), so a binary's exact provenance is recoverable even from a Docker image whose.gitwas removed. The commit also appears in the run startup banner and in the@PGlines of output BAMs. - If svaba is built from a non-git source tree, the commit shows as
unknownand--versionprints only the semantic version.
Nothing yet.
--bam-params FILE/--learn-only— cache insert-size learning across a scatter-gather run.learnParams()samples up to ~1 M reads/window across every chromosome midpoint (≈ many millions of reads, ×2 for tumor+normal) to estimate per-read-group insert size — and it ran on everysvaba runregardless of-k. In a 322-shard scatter that genome-wide sweep (+ 5.4 GB index load) was paid 322×, ≈ 5 CPU-min/shard of pure redundant overhead (≈ a quarter of the total CPU-h) plus billions of random reads against the shared BAM disk. Now:svaba run --learn-only --bam-params p.tsvlearns once and writes a tiny TSV; every shard runs--bam-params p.tsvto LOAD it and skip the sweep entirely. The cache stores per-RGisize_median/sd_isize+ per-BAMreadlen/mapq/isizemaxima, matched to the run's BAMs by path; if the file is missing/incomplete svaba transparently learns (and writes it). No effect on results — only on how insert size is obtained.
- Contig-alignment confidence now penalizes alignment non-uniqueness.
scoreContigAlignmentgained Rule E: when BWA's suboptimal scoreXSapproaches the primaryAS(XS/AS > 0.80, scaling to a full penalty at a dead tie), the contig has another near-equal placement — a repeat / paralog / segmental-dup locus that BLATs to many sites — socontig_confis lowered and the existingWEAKCONTIGgate catches it. Theas_xs_gapsignal was already computed but unused; the prior confidence measured only absolute quality (mismatch rate, AS-density), not multi-mapping. Targets the dominant remaining false-positive mode: weak/ambiguous contig alignments svaba treated as confident. Caller-side → needs a fresh run. The per-breakendcontig_conf(bps cols 40/41) is unchanged in meaning, just better calibrated;benchmark.py --events-outnow also records it (min over breakends) so it can be tuned as a slider indocs/sim_commit_compare.html.
- Span-0 FR discordant false somatics.
score_dscrd'sLOWSPANDSCRDgate guarded ongetSpan() > 0, but an intrachromosomal same-position discordant cluster hasgetSpan() == 0— a degenerate zero-length "deletion" formed when mildly-over-insert FR pairs (tagged discordant by a low insert cutoff) collapse to a single base. These leaked straight toPASSas false somatic DSCRD calls (e.g. 312 of 319 somatic-PASS DSCRD at 10× in the sim panel). Changed the guard togetSpan() >= 0, so span-0 FR clusters are correctly labeledLOWSPANDSCRD; interchromosomal events (getSpan()= −1) remain excluded. Caller-side → needs a fresh run.
Backward-compatible feature additions plus a batch of false-somatic / coordinate
correctness fixes accumulated since 2.0.0. The bps.txt.gz and VCF additions are
trailing/additive (older parsers that read by name or early columns are
unaffected), so this is a MINOR release. See CLAUDE.md for the
full engineering notes. Versioning is now Claude-maintained (see CLAUDE.md
"Versioning").
--annotation <BED>(repeatable): overlap each breakend with a labeled BED (RepeatMasker / segmental-dups / custom). New trailing bps columnsrepeat_anno(col 55,b1labels|b2labels) andpoly_a(col 56, longest poly-A/T run in the insertion = MEI signal); VCFINFO/REPEAT_ANNOandINFO/POLYA. Non-filtering. (bps schema v5 → v6.)- Somatic-safety junction-kmer net → new per-sample FORMAT subfield
KC. Reads excluded from assembly/r2c (adapter read-through, blacklist-self) that carry a breakpoint's junction kmer (≥19/20 bp, either strand) are counted and folded into the normal alt count for the somatic LOD, so a junction-spanning normal read can never be silently lost. sim/— self-contained SV simulator: non-overlapping SVs across the genome → diploid donor → ART → BWA-MEM, in-silico tumor impurity admixture, ground truth (VCF/BEDPE/TSV),benchmark.py, and one-shot panel/run drivers (build_sim_panel.sh,run_svaba_on_panel.sh).- Viewers:
docs/sim_benchmark.html(ROC / PR vs truth, dual somlod+maxlod gate, IGV-linked TP/FP/FN tables, blacklist masking) anddocs/truth_store.js(in-browser Valid/Artifact/Germline/Ambiguous labeling with auto-save to a committedground_truth.json), wired intobps_explorer.html/comparison.html. Newtracks/hg38.rmsk.bed.gz,tracks/hg38.segdups.bed.gz.
- DUPREADS now keys on the number of UNIQUE split-read genomic start
positions (
nsplit_starts), not the contig-footprint span — fixes false-flagging of real low-coverage / short-contig / duplicate-free events. - Distant-read recovery for assembly-only large SVs; blacklist-aware
region-queue pruning; coverage (DP) now counts blacklist-overlapping reads;
addCovsaverages only populated breakends.
hasAdapter: a 5′-end soft-clip is split-read signal, never adapter read-through — adapter geometry is judged on the 3′ clip only, so junction-spanning reads across small SVs are no longer dropped.- SV breakend off-by-one:
gbreakstored 0-based; every SV breakend coordinate shifts −1 vs prior output (indels unaffected). Symbolic-SV REF base intovcfnow taken at the min breakend. VCF POS/END now consistently 1-based. - Insert-size robust SD (MAD): tames heavy-tailed isize → fixes inflated discordant cutoffs that blinded the normal and produced false somatic calls; interchromosomal RF discordant reads no longer dropped.
- Confidence read-count vetoes removed for SV paths (evidence sufficiency is the
LOD's job);
LOWICSUPPORTintra-chrom guard restored.
2.0.0 - 2026-06-07
The SvABA 2.0 overhaul. This is a major release: output schemas, the
VCF representation, and several internal pipelines changed relative to the
1.x line. See CLAUDE.md for the exhaustive engineering notes;
the highlights:
svaba --version— prints the semantic version, the git commit the binary was built from,git describe, a dirty flag, and the build date.svaba postprocesssubcommand — in-process merge, BAM sort/dedup (with BGZF thread pools),bps.txt.gzsort/dedup, and r2c stamping; replaces the oldsort_output.sh/sort_and_deduplicate_bps.shshell pipeline.svaba tovcfsubcommand — standalone converter from a dedupedbps.txt.gzto VCFv4.5 (*.sv.vcf.gz+*.indel.vcf.gz), with symbolic<DEL>/<DUP>/<INV>alleles where orientation is unambiguous and paired BND records otherwise.svaba extract-pairssubcommand — BAM-native read-pair extraction by sequence match (Aho-Corasick, both strands), replacingextract_pairs_by_seq.sh.- Per-breakpoint stable IDs (
bp_id,bps.txt.gzcol 52) threaded through the BAMbi:Ztag and the r2c database for end-to-end read↔ variant traceability. - Junction k-mer (
jxn_kmer,bps.txt.gzcol 53) — a 20 bp contig-native sequence spanning each breakend junction. - r2c SQLite database (
${ID}.r2c.db) — queryable per-read read-to-contig alignment dump, written per-thread and merged in postprocess; replaces the pre-renderedalignments.txt.gz. - Blacklist-aware region pruning — fully blacklisted regions are dropped before reaching a worker thread.
- jemalloc support via
-DUSE_JEMALLOC=ON(recommended on Linux at-p 16+), plus thesvaba_jemallocLD_PRELOAD wrapper. - HTML viewer suite under
docs/(bps / r2c / runtime / learn explorers and a two-run comparison view).
- Somatic statistical model reworked (
SvabaModels.cpp): split-error somatic LOD with additional germline sub-hypotheses (GERM_sharedshaping terms and a new independent-MLEGERM_freebranch with a BIC penalty). - Split-coverage gate is now a direct comparison — a read supports a
breakend iff its r2c alignment scores strictly higher than its native
alignment and it spans the breakend. The old homology-conditioned
both_split/one_splitbranching and theT_R2C_MIN_MARGINpercentage margin were removed (the margin was read-length-dependent and silently dropped tumor support for small indels). - fermi-lite is the default local-assembly engine; its k-mer hash is pooled per worker thread and reused across regions.
- VCF output declares
VCFv4.5; somatic and germline records share one SV file and one indel file, distinguished by theSOMATICINFO flag. - Homology / inserted sequence / junction k-mer are canonicalized to
side-1 forward-strand spelling in
bps.txt.gz. - Under jemalloc, the per-flush
malloc_trim(0)calls are now compiled out (gated onSVABA_USE_JEMALLOC):malloc_trimis a glibc-only call that can't reclaim jemalloc-held memory and only exercised glibc's arena machinery. They remain active for glibc builds, where they bound RSS on high-coverage samples.
alignments.txt.gzand its ASCII emitter (superseded by the r2c database).- The standalone post-processing and pair-extraction shell scripts
(
sort_output.sh,sort_and_deduplicate_bps.sh,extract_pairs_by_seq.sh), now built-in subcommands.