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.
Pre-built static binaries are available on the GitHub Releases page — most 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+ |
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 -1A 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 --helpImportant
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.
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/CRAMAbout: 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.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.listRecommended 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.listCall 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.listCall 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.listInclude 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.cramPer-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.listSee the example sample_group.txt file for the expected format (column 1: sample ID, column 2: Group name).
Since v2.5.0, basevar caller uses a two-pass Bayesian architecture for genotype calling:
- First pass : collect per-sample PL and hard-count AC_obs/AN_obs (backward compatible).
- 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.listINFO 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.listFor 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
basevarbinary as a native C++ subcommand.
| 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.
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.shGenerate 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.shGenerate 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.shRun 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.shAfter 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.gzConcatenate 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.gzExtract 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-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 500is a good starting point.--filename-has-samplename: If your BAM files are named{SampleID}.bamor{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.bbiindex 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.gzas the output filename — BaseVar automatically writes bgzipped output when the extension is.vcf.gz.
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