Skip to content

Repository files navigation


A high-performance C++17 tool for variants calling from ultra low-depth WGS data

GitHub Actions CI License: AGPL v3 or later Install with bioconda

Download: Lastest version of linux-static-binary

BaseVar is a fast, memory-efficient variant caller for ultra-low-depth (<1×) sequencing data, designed for non-invasive prenatal testing (NIPT) and population-scale genomics. It simultaneously identifies genomic variants and estimates allele frequencies in cohorts of tens to hundreds of thousands of samples. BaseVar was originally introduced in our Cell paper in 2018, and the first stable release was described and benchmarked in Cell Genomics. This repository contains a completely redesigned C++17 implementation focused on performance and scalability.

The new implemention is over 100× faster than the original Python implementation and 5–10× faster than BaseVar v1, while using substantially less memory. With -B 200 and a single thread, it typically requires only 3–4 GB of RAM, compared with more than 20 GB for the original Python implementation.


Installation and quick start

Pre-built static binaries are available on the GitHub Releases pagemost users should simply download the binary and run.

Platform Download Notes
Linux (x86_64) basevar-linux-static Requires glibc ≥ 2.35 (see below)
macOS (arm64 / Intel) basevar-macos-static Requires macOS 12+

System requirements for basevar-linux-static

The Linux binary is a partial-static build (built on Ubuntu 22.04 / glibc 2.35). It bundles libstdc++, libgcc, htslib, zlib, bzip2, xz and openssl statically; only the system C library (glibc) is linked dynamically — and glibc symbol versions are forward-compatible only, so the binary requires the host glibc to be ≥ 2.35.

Quick check on your machine:

# If the printed glibc version is >= 2.35, basevar-linux-static will run.
ldd --version | head -1

A typical incompatibility error looks like:

./basevar-linux-static: /lib64/libc.so.6: version `GLIBC_2.35' not found (required by ./basevar-linux-static)

If you see this — or you are on CentOS / RHEL / Rocky / AlmaLinux / older Ubuntu / older Debian — you can compile from source instead (see below).

# Linux
wget https://github.com/ShujiaHuang/BaseVar2/releases/latest/download/basevar-linux-static
chmod +x basevar-linux-static
mv basevar-linux-static basevar
./basevar --help
# macOS
curl -LO https://github.com/ShujiaHuang/BaseVar2/releases/latest/download/basevar-macos-static
chmod +x basevar-macos-static
mv basevar-macos-static basevar
./basevar --help

Important

Rename the downloaded binary to basevar for convenience. You may also move it to a directory in your $PATH (e.g. /usr/local/bin) for system-wide access.

Tip

If the pre-built binary does not work on your system (e.g. glibc < 2.35 on older Linux), you can compile from source instead. Detailed build instructions (CMake build, static build, and manual g++ fallback) are available in docs/INSTALL_FROM_SOURCE.md.

Commands overview

Usage: basevar <command> [options]

Commands:
  caller    Call variants and estimate allele frequencies
  pipeline  Generate per-region `basevar caller` commands for whole-genome calling
  concat    Concatenate per-region VCF files into a whole-genome VCF
  subsam    Extract a subset of samples from a VCF file
  motif     Count cfDNA end-motif (k-mer) frequencies from BAM/CRAM

basevar caller — Variant calling

Full parameter reference

About: Call variants and estimate allele frequency by BaseVar.
Usage: basevar caller [options] <-f Fasta> <-o output_file> [-L bam.list/cram.list] in1.bam [in2.bam ...] ...

Required arguments:
  -f, --reference FILE         Input reference FASTA file.
  -o, --output    FILE         Output VCF file (supports .vcf.gz).

Optional options:
  -L, --align-file-list=FILE   BAM/CRAM files list, one file per row.
  -r, --regions=REG[,...]      Restrict calling to these regions (comma-separated).
                               Formats: chr | chr:start | chr:start-end
                               Example: chr1,chr2:1000000,chr3:5000000-10000000
  -G, --pop-group=FILE         Calculate allele frequency per population group.

  -m, --min-af=float           Prior MAF threshold; positions below this are skipped.
                               Default: min(0.001, 100/num_samples). Usually auto-set.
  -Q, --min-BQ=INT             Minimum base quality [10]
  -q, --mapq=INT               Minimum mapping quality [5]
  -B, --batch-count=INT        Samples per batch file [500]
  -t, --thread=INT             Number of threads [auto]

  --filename-has-samplename    If BAM/CRAM filenames start with the sample ID
                               (e.g. SampleID.bam), set this flag to skip reading
                               the BAM header for sample names — saves significant time.
  --ref-bias=FLOAT             Reference bias coefficient (β) for genotype likelihood.
                               β=0.5 means no bias (default); β<0.5 corrects for
                               alignment reference bias. Typical: 0.45-0.48. [0.5]
  --max-alleles=INT            Maximum active alleles allowed at a site. Sites
                               exceeding this threshold will be skipped. [6]
  --smart-rerun                Skip completed batch files and resume an interrupted run.
                               Validates BBI index footer integrity to detect truncated files.
  -h, --help                   Show this help message and exit.

Usage examples

Minimal call from a list of BAM files (or CRAM files):

basevar caller \
    -f reference.fasta \
    -o output.vcf.gz \
    -L bamfile.list
  
basevar caller \
    -f reference.fasta \
    -o output.vcf.gz \
    -L cramfile.list

Recommended call with quality filters, smart-rerun option and sample name optimization:

basevar caller \
    -f reference.fasta \
    -o output.vcf.gz \
    -Q 20 -q 30 -B 500 -t 24 \
    --filename-has-samplename \
    --smart-rerun \
    -L bamfile.list

Call a specific region:

basevar caller \
    -f reference.fasta \
    -o chr11_region.vcf.gz \
    -Q 20 -q 30 -B 500 -t 24 \
    --filename-has-samplename \
    -r chr11:5246595-5248428 \
    --smart-rerun \
    -L bamfile.list

Call multiple disjoint regions in one run:

basevar caller \
    -f reference.fasta \
    -o multi_region.vcf.gz \
    -Q 20 -q 30 -B 500 -t 24 \
    --regions chr11:5246595-5248428,chr17:41197764-41276135 \
    --filename-has-samplename \
    --smart-rerun \
    -L bamfile.list

Include BAM/CRAM files directly on the command line:

basevar caller \
    -f reference.fasta \
    -o output.vcf.gz \
    -Q 20 -q 30 -B 500 \
    --filename-has-samplename \
    -L bamfile.list \
    --smart-rerun \
    sample1.cram sample2.cram sample3.cram

Per-population allele frequency calculation:

basevar caller \
    -f reference.fasta \
    -o output.vcf.gz \
    -Q 20 -q 30 -B 500 -t 24 \
    --filename-has-samplename \
    --pop-group sample_group.txt \
    --smart-rerun \
    -L bamfile.list

See the example sample_group.txt file for the expected format (column 1: sample ID, column 2: Group name).

Bayesian genotype calling

Since v2.5.0, basevar caller uses a two-pass Bayesian architecture for genotype calling:

  1. First pass : collect per-sample PL and hard-count AC_obs/AN_obs (backward compatible).
  2. Second pass: use the LRT-estimated population AF as a Hardy-Weinberg prior to compute per-sample genotype posteriors. GT is called as argmax(posterior), GQ is −10 log₁₀(1 − P(best GT)).

This is the default behavior. To revert to the previous pure-likelihood mode:

basevar caller --gt-mode legacy -f ref.fa -o out.vcf.gz -L bamfile.list

INFO field structure (three complementary tiers):

Tier Fields Description
Posterior (recommended) AF, AC, AN Expected values from posterior probabilities over all possible genotypes (with population prior). AF is the recommended allele frequency metric.
Observed AC_obs, AN_obs, AF_obs Discrete counts from argmin(PL) genotypes (most likely without population prior).
GT-based AC_GT, AN_GT, AF_GT Discrete counts directly from the VCF GT column (with population prior).

Backward compatibility: all existing fields (INFO/AC, INFO/AF, FORMAT/PL, FORMAT/AD, FORMAT/DP) retain their original values. The additional observed and GT-based fields are additive. Use --gt-mode legacy to produce output identical to pre-v2.5.0.

Important

In general, AF should differ only slightly from AF_obs for NIPT large-scale cohorts.

Resume an interrupted run:

basevar caller \
    -f reference.fasta \
    -o output.vcf.gz \
    -Q 20 -q 30 -B 500 -t 24 \
    --filename-has-samplename \
    --smart-rerun \
    -L bamfile.list

basevar pipeline — Whole-genome pipeline generator

For whole-genome variant calling, the pipeline subcommand splits the genome into sub-regions and prints one basevar caller command per sub-region to stdout. The resulting shell script can be executed sequentially, in parallel with GNU parallel, or submitted to a job scheduler (SGE / SLURM / PBS).

Since v2.2.0, this functionality is built directly into the basevar binary as a native C++ subcommand.

Pipeline-specific options

Option Description Default
-o, --outdir Output directory for VCF files and logs required
--ref_fai Reference FASTA index file (.fai) required
-d, --delta Size of each sub-region (bp) 2000000
-c, --chrom Restrict to comma-separated chromosome(s) all chromosomes

All other options (-f, -L, -r, -Q, -q, -B, -t, --filename-has-samplename, --pop-group, ...) are passed through verbatim to basevar caller. This means any new caller option works automatically without changes to the pipeline subcommand.

When -r/--regions is supplied, those regions are further split into --delta-sized windows; otherwise every chromosome in the .fai (filtered by --chrom if set) is processed.

Examples

Generate whole-genome pipeline (all chromosomes, 2 Mb windows):

basevar pipeline \
    -o /path/to/outdir \
    --ref_fai reference.fasta.fai \
    -f reference.fasta \
    -L bamfile.list \
    -Q 20 -q 30 -B 500 -t 4 \
    --filename-has-samplename \
    --smart-rerun \
    > basevar_wgs.sh

Generate pipeline for a single chromosome (5 Mb windows):

basevar pipeline \
    -o /path/to/outdir \
    --ref_fai reference.fasta.fai \
    -c chr20 -d 5000000 \
    -f reference.fasta \
    -L bamfile.list \
    -Q 20 -q 30 -B 500 -t 4 \
    --filename-has-samplename \
    --smart-rerun \
    > basevar.chr20.sh

Generate pipeline for specific regions:

basevar pipeline \
    -o /path/to/outdir \
    --ref_fai reference.fasta.fai \
    -d 1000000 \
    -r chr11:5000000-7000000,chr17 \
    -f reference.fasta \
    -L bamfile.list \
    -Q 20 -q 30 -B 500 -t 4 \
    --filename-has-samplename \
    --smart-rerun \
    > basevar.targets.sh

Run the generated pipeline:

# Sequential (local):
bash basevar.chr20.sh

# Parallel with GNU parallel:
cat basevar_wgs.sh | parallel -j 8

# Or submit each line as a cluster job (SGE/SLURM example):
while IFS= read -r cmd; do
    echo "$cmd" | qsub -V -cwd -pe smp 4
done < basevar_wgs.sh

After all sub-jobs finish, concatenate the per-region VCFs using basevar concat --naive:

ls /path/to/outdir/*.vcf.gz | sort -V > vcf.list
basevar concat -n -L vcf.list -o final_output.vcf.gz

basevar concat — Concatenate VCF files

Concatenate per-region VCF files into a single whole-genome VCF. The files must be provided in the correct genomic order (the tool does not sort positions).

Two modes are available:

Mode Flag Description Speed
Naive (recommended) -n / --naive BGZF block-level raw concatenation without decompression/recompression ~150× faster
Default (none) Line-by-line decompression and recompression Baseline

The naive mode is ideal when all input VCFs are produced by the same basevar caller run (same header, non-overlapping regions). It checks sample compatibility automatically. Use --naive-force to skip the header check when you are certain the files are compatible.

Usage: basevar concat [options] -o <output.vcf.gz> [-L vcf.list] in1.vcf.gz [in2.vcf.gz ...]

Required:
  -o, --output=FILE      Output VCF file. Format is determined by suffix:
                         '.vcf.gz' for BGZF-compressed, '.vcf' for plain text.
                         Note: --naive mode always produces BGZF-compressed output.

Optional:
  -L, --file-list=FILE   List of input VCF files, one per line.
  -n, --naive            Fast mode: BGZF block-level concat (no recompression, ~150× faster).
      --naive-force      Same as --naive but skip header compatibility check.

Example:

# Naive mode (recommended, ~150× faster than default)
basevar concat -n -L vcf.list -o merged.vcf.gz

# Naive mode with inline files
basevar concat -n chr1_1_2000000.vcf.gz chr1_2000001_4000000.vcf.gz -o chr1.vcf.gz

# Skip header check (when files are known to be compatible)
basevar concat --naive-force -L vcf.list -o merged.vcf.gz

# Default mode (line-by-line, supports uncompressed .vcf output)
basevar concat -L vcf.list -o merged.vcf.gz

basevar subsam — Extract samples from VCF

Extract a subset of samples from a BaseVar VCF and output a new VCF with recalculated INFO fields (AC/AN/AF).

Usage: basevar subsam [options] -i <input.vcf[.gz]> -o <output.vcf[.gz]> [-s <samplelist>]

Options:
  -i, --input FILE      Input VCF/BCF file (required).
  -o, --output FILE     Output VCF/BCF file (required).
  -s, --sample FILE     File with sample names to keep (one per line).
  -O, --output-type     v: VCF | z: bgzipped VCF | b: BCF | u: uncompressed BCF
                        Default: inferred from output filename extension.
  --no-update-info      Do not recalculate AC/AN/AF INFO fields.
  --keep-all-site       Retain sites that become reference-only after subsetting.

Examples:

# Extract samples listed in a file
basevar subsam \
    -i full_cohort.vcf.gz \
    -o subset.vcf.gz \
    -s sample_names.txt

# Extract two specific samples, output as plain VCF
basevar subsam \
    -i full_cohort.vcf.gz \
    -o subset.vcf \
    -O v \
    SampleA SampleB

# Keep all sites (including ref-only after subsetting) and skip INFO update
basevar subsam \
    -i full_cohort.vcf.gz \
    -o subset.vcf.gz \
    -s sample_names.txt \
    --keep-all-site --no-update-info

Tips and best practices for using basevar caller

  • -B / --batch-count: Controls how many samples are processed per batch. Lower values reduce per-thread memory but increase I/O. For large cohorts (>10,000 samples) -B 500 is a good starting point.
  • --filename-has-samplename: If your BAM files are named {SampleID}.bam or {SampleID}.cram, always set this flag — it avoids reading every BAM header and can save hours on large cohorts.
  • --smart-rerun: Safe to add on any re-run; the program checks existing batch files and validates the .bbi index footer integrity marker to detect truncated files before resuming.
  • memory estimation: threads × batch_size / 200 × ~3–4 GB. E.g., 24 threads, -B 200 → ~72–96 GB total.
  • output compression: Always use .vcf.gz as the output filename — BaseVar automatically writes bgzipped output when the extension is .vcf.gz.

Citation

If you use BaseVar in your research work, please cite the following paper:

Liu, S., Liu, Y., Gu, Y., Lin, X., Zhu, H., Liu, H., Xu, Z., Cheng, S., Lan, X., Li, L., Huang, M., Li, H., Nielsen, R., Davies, RW., Albrechtsen, A., Chen, GB., Qiu, X., Jin, X., Huang, S., (2024). Utilizing non-invasive prenatal test sequencing data for human genetic investigation. Cell Genomics 4(10), 100669. doi:10.1016/j.xgen.2024.100669

About

This is the official development repository for BaseVar, which call variants for large-scale ultra low-depth(<1.0x) WGS data, especially for NIPT data and ancient DNA

Topics

Resources

Stars

10 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages