Repository navigation
Releases: natera-open-source/vep-rs
Release list
vep-rs 0.4.0
vep-rs 0.4.0 moves the reference to Ensembl VEP 116.2 and reads structural-variant records as Ensembl VEP's parser does, with adjusted F1 of 1.000000000 against that reference on every whole-genome dataset and structural-variant file set. Anyone comparing output with Ensembl VEP 116, or annotating structural variants, should upgrade.
Highlights
- A newer Ensembl VEP release is the reference, and the headers, defaults, golden corpora and consequence calls follow it.
- Structural-variant records are routed, typed and named as Ensembl VEP reads them, breakends and tandem-repeat alleles included.
Upgrade notes
- Breaking: Stop-codon, breakend, multi-allelic and JSON-coordinate output and
Uploaded_variationfor;-joined or missing IDs follow Ensembl VEP release 116; re-annotate before comparing with output of an earlier version. - Breaking: The headers and the banner read Ensembl VEP
v116.2,--cache_versiondefaults to 116, andtests/golden/116/replacestests/golden/115/; point any script at the new corpus.
Added
--protein_versionappends the translation version toENSP,--mask_header_cache_pathmasks the cache directory in the output headers, and--regulatory_gff,--extended_promotersand--custom_suppress_filterare refused, naming what each would do. (#44)- The plugin-visible
InputVariantJSON carriesinput_line_name,record_so_termandallele_num(the record's input-line name, class term and printed ALLELE_NUM), andmate_idonly on a record naming a mate. (#44) - Comparators take
--reference-release {115.2,116.2}(default 116.2) with a registry of records Ensembl VEP drops or annotates differently; release pages tabulate whole-genome and structural-variant F1; documentation: https://natera-open-source.github.io/vep-rs/. (#43, #44, #50, #57)
Changed
- Ensembl VEP 116.2 is the reference release: headers and banner read
v116.2,--cache_versiondefaults to 116,tests/golden/116/replacestests/golden/115/, anddocs/intended-divergences.mdis rewritten against it. (#38, #44, #45) - Stop-codon consequences follow Ensembl VEP release 116: an edit beginning inside the stop codon is
stop_lostorstop_retained_variantwithoutframeshift_variant; indels decidestop_retained_varianton the genomic span. (#44) - Breakend records follow Ensembl VEP 116: an
intergenic_variantrow per allele when no transcript is reached, own breakendN.without MATEID at ALLELE_NUM 0,<BND>mates named through CHR2. (#44) - A multi-allelic structural variant takes one class from its joined ALTs and writes one row per ALT, each labelled with the record's class term, as Ensembl VEP 116 does. (#44)
- Records Ensembl VEP 116 drops before annotation are annotated, the divergence the golden manifests class
reference_skipped_record, and--max_sv_size -1lifts the size limit in every output format. (#44) - JSON
cdna_end,cds_endandprotein_endare omitted when the end is undefined (445-?writescdna_startalone), and a structural record'sallele_stringcarries every ALT as written (Ensembl VEP 116). (#44) Uploaded_variationreads a VCF record's first;-joined ID, and a record whose ID is., empty,0or absent is named from its input line (Ensembl VEP 116). (#44, #51)--hgvsfollows Ensembl VEP 116: a deletion past a transcript's edge written over the bases inside it, a stop-codon frameshift as an extension, a stop-codon indel by its peptides. (#44)
Fixed
- Structural-variant records are routed, typed and spanned as Ensembl VEP's parser reads them, in one module shared by the command-line parser and the
vep-ioreader; no coordinate wraps. (#44) <CNV:TR>alleles follow Ensembl VEP 116: the length reads RUC before RB and sums the RN sequences, and a repeat longer than--max_sv_size, or any under-1, stays symbolic. (#44)- A structural deletion or copy-number loss over the stop-codon window takes
stop_lostunless its first base in transcript order lies in the incomplete terminal codon (Ensembl VEP 116). (#58) --proteinfills ENSP on every structural-variant row of a translated transcript, and the## VEP command-lineheader keeps--max_sv_size -1and thekey=prefix of a masked--custompath. (#44)- JSON
idof a record whose first ID is empty or0is the generated name, and the header cache path without--json_cachefollows Ensembl VEP's<dir_cache>/<species>/<version>_<assembly>layout. (#51) - The concordance harness passes
run_splice_predictions:0to Perl LoFTEE and keys its Perl output cache on plugin arguments, and--plugin LoFTEEwarns when asked for that unimplemented splice layer. (#47, #49)
Concordance and wall time
Whole genome against Ensembl VEP 116.2: the population datasets one run per chromosome, each ClinVar release one genome-wide file; wall time is the sum of the per-chromosome medians of 20 machines at 16 threads on c8gd.8xlarge (ARM) and c8id.8xlarge (x86) for the population datasets, and the whole-file median of 20 machines on r8gd.8xlarge (ARM) and r8id.8xlarge (x86) for the ClinVar files, another instance class and protocol, so the All six row carries no wall time; peak memory at most 2.6 GB on any chromosome; tuple counts, per-chromosome rows and per-file counts are in the provenance records.
| Dataset | Raw F1 | Adjusted F1 | ARM (s) | x86 (s) |
|---|---|---|---|---|
| gnomAD v4.1 | 0.999999353 | 1.000000000 | 881 | 1,365 |
| gnomAD v2.1.1 | 0.999999521 | 1.000000000 | 282 | 472 |
| 1000 Genomes Phase 3 | 0.999999714 | 1.000000000 | 49 | 76 |
| 1000 Genomes high-coverage | 0.999991204 | 1.000000000 | 85 | 116 |
| ClinVar GRCh37 | 0.999979065 | 1.000000000 | 5 | 6 |
| ClinVar GRCh38 | 0.999972446 | 1.000000000 | 14 | 14 |
| All six | 0.999998408 | 1.000000000 |
Structural-variant file sets measured on the released binary against the same reference, each set's files pooled by summed counts; the paper's own figures stay as published in docs/published-figures.md.
| File set | Assembly | Raw F1 | Adjusted F1 |
|---|---|---|---|
| ClinVar SV | GRCh37 | 0.999952183 | 1.000000000 |
| gnomAD SV | GRCh37 | 0.726719694 | 1.000000000 |
| 1000 Genomes SV | GRCh37 | 1.000000000 | 1.000000000 |
| Synthetic (13 files) | GRCh37 | 0.986694682 | 1.000000000 |
| ClinVar SV | GRCh38 | 1.000000000 | 1.000000000 |
| gnomAD SV | GRCh38 | 0.791428005 | 1.000000000 |
| 1000 Genomes SV | GRCh38 | 0.989455966 | 1.000000000 |
| Synthetic (13 files) | GRCh38 | 0.983528044 | 1.000000000 |
Install
vep-0.4.0-x86_64-unknown-linux-gnu.tar.gz: Linux x86_64, glibc 2.39 or later, x86-64-v3 (AVX2, BMI2, FMA: Intel Haswell 2013 or later, AMD Zen or later); sha256d72ff534447dd38ceef576c7d51d479cb7af354c09bba42c47f0991343bcb3a8vep-0.4.0-aarch64-unknown-linux-gnu.tar.gz: Linux aarch64, glibc 2.39 or later, Armv8.4-A with SVE (Arm Neoverse V1 or later: AWS Graviton3 and later, not Graviton2, Ampere Altra or Raspberry Pi); sha2566057da61fb971e4ff822b1fe5c5b2e6c7f251fadedf2737f9b94ac2c195537d0vep-0.4.0-aarch64-apple-darwin.tar.gz: macOS 11 or later on Apple silicon, any Apple M-series; sha256b22283552d1e4c995090025c04dedbc884f1b1afc477ee9f88334f9bb4674fc2- Each archive unpacks to
vep-0.4.0-<target>/holdingvep,vep-cache-builderandvep-cache-converter; a binary below its CPU floor aborts with an illegal-instruction fault, so on such a host build from source (Rust 1.88 or later), which compiles for the machine it runs on:RUSTFLAGS="-C target-cpu=native" cargo build --release --locked - Container image:
docker pull ghcr.io/natera-open-source/vep-rs:0.4.0(linux/amd64: the x86_64 binaries with theduckdbCLI that Parquet output needs) - Built by the release workflow from tag
v0.4.0(commitf64272326dee8f813a57f9fa832539ccd8067dab) with Rust 1.97.1; every file inSHA256SUMScarries a GitHub build-provenance attestation:gh attestation verify <file> --repo natera-open-source/vep-rs vep-rs-0.4.0.tar.gzisgit archive --format=tar.gz --prefix=vep-rs-0.4.0/ v0.4.0; sha2560ff936860386d74d5f532ef86d0b19f4c31eadc90998062d0291c5bc402756ab
Cite
Porter M, Borkowski R. vep-rs, version 0.4.0. 2026. doi:10.5281/zenodo.22837896
Full changelog: CHANGELOG · v0.3.2...v0.4.0
vep-rs 0.3.2
vep-rs 0.3.2 is a performance release with no change in output: on every gated input the annotation is byte-identical to 0.3.1, and the whole of each batch is now annotated, filtered, rendered and freed in one pass over the worker pool, with bgzip input inflated through libdeflate. Measured against 0.3.1 under the same whole-genome protocol (the median of 20 machines per chromosome at 16 threads, summed over the chromosomes), the whole of gnomAD v4.1 falls from 974 to 724 s on ARM Graviton4 and from 1,219 to 1,169 s on x86, and the whole of gnomAD v2.1.1 from 586 to 282 s and from 835 to 476 s, with peak memory at most 2.4 GB on any chromosome; the two smallest datasets, 1000 Genomes Phase 3 and high-coverage, are 24 to 35 percent faster on ARM and within 2 percent of 0.3.1 on x86. The default thread count now stops at 32 logical CPUs, where the wall time stops improving; anyone running on hosts wider than 32 vCPUs with the default --fork should upgrade.
vep-rs is a from-scratch Rust implementation of the Ensembl Variant Effect Predictor: the same
inputs and flags, VEP's consequence vocabulary in VEP's output formats plus Parquet, measured for
concordance against Ensembl VEP at population scale.
Upgrade notes
--fork 0, the default, uses every logical CPU up to 32 instead of every logical CPU. A host with more than 32 logical CPUs annotates faster under the new default; an explicit--fork Nbehaves as before and is never capped.- Flags, input formats, output formats and the JSON cache format are unchanged; a cache converted for 0.3.0 is valid.
Changes
Changed
--fork 0(the default) uses every logical CPU up to 32 instead of every
logical CPU: one reader feeds the worker pool, so the wall time stops falling
past about 32 workers and rises on wider hosts (gnomAD v4.1 chromosome 2 took
1.8 times longer at 192 workers than at 32 on a 192-vCPU host). An explicit
--fork Nis never capped.- A batch is annotated, filtered, rendered and freed in one pass over the worker
pool, each finished variant freed by the thread that annotated it and the
task size following the pool's thread count, instead of five pool barriers per
batch with the coordinator freeing every variant serially between batches. The
output is byte-identical. Together with the libdeflate inflate below, measured
against 0.3.1 under the same whole-genome protocol (the median of 20 machines
per chromosome at 16 threads, summed over the chromosomes), the whole of gnomAD
v4.1 falls from 974 to 724 s on ARM Graviton4 and from 1,219 to 1,169 s on x86
and the whole of gnomAD v2.1.1 from 586 to 282 s and from 835 to 476 s, with
CPU time down 19 to 44 percent on those inputs and peak memory at most 2.4 GB
on any chromosome against 4.9 GB. - bgzip blocks inflate through libdeflate (
noodles-bgzfwith itslibdeflate
feature), and the cache builder's MySQL client takes its Rust deflate backend
so that no crate of the workspace links C zlib: the single-inflater floor on
gnomAD v4.1 chromosome 21 falls from 73.8 s to 34.5 s.
Full entry: CHANGELOG.md (this version is its first section) ·
Full Changelog: v0.3.1...v0.3.2
Concordance and wall time for this release
The paper's published figures are unchanged; these are the released version's own, from the
release's provenance records under docs/concordance-provenance/
(method: scripts/concordance/run_clone_measurement.sh).
Whole-genome concordance of the released binary on four population datasets, one run per
chromosome on ARM Graviton4, against Ensembl VEP 115.2's output on the same inputs; a variant is
one VCF record, a tuple one output row reduced to its Location, Allele, Feature, Feature_type and
Consequence set, and F1 pools the chromosomes by summed counts:
| Dataset | Assembly | Chromosomes | Variants | VEP tuples | vep-rs tuples | Matched | Raw F1 | Adjusted F1 |
|---|---|---|---|---|---|---|---|---|
| gnomAD v4.1, whole genome | GRCh38 | 24 | 759,336,320 | 7,409,818,550 | 7,409,818,550 | 7,409,815,011 | 0.999999522 | 1.000000000 |
| gnomAD v2.1.1, whole genome | GRCh37 | 23 | 261,942,336 | 885,664,902 | 885,664,902 | 885,664,478 | 0.999999521 | 1.000000000 |
| 1000 Genomes Phase 3, whole genome | GRCh37 | 25 | 84,805,772 | 286,649,478 | 286,649,478 | 286,649,396 | 0.999999714 | 1.000000000 |
| 1000 Genomes high-coverage, whole genome | GRCh38 | 23 | 73,554,796 | 699,522,065 | 699,534,118 | 699,521,778 | 0.999990975 | 1.000000000 |
| All four | GRCh37 and GRCh38 | 95 | 1,179,639,224 | 9,281,654,995 | 9,281,667,048 | 9,281,650,663 | 0.999998884 | 1.000000000 |
Whole-genome wall time as the sum of the per-chromosome medians, each the median of 20 independent
machines, ARM Graviton4 (c8gd.8xlarge) and x86 Intel (c8id.8xlarge), 16 threads, local NVMe,
sites-only inputs, the discarded warmup's output deleted before the timed run: gnomAD v4.1 724 s ARM / 1,169 s x86; gnomAD v2.1.1 282 s ARM / 476 s x86; 1000 Genomes Phase 3 46 s ARM / 74 s x86; 1000 Genomes high-coverage 69 s ARM / 99 s x86.
The chromosome 21 suites, the paper's cells measured on the released binary:
| Dataset | Assembly | Raw F1 | Adjusted F1 | VEP tuples | vep-rs tuples | Matched |
|---|---|---|---|---|---|---|
| ClinVar full | GRCh37 | 0.999979065 | 1.000000000 | 33,483,881 | 33,483,881 | 33,483,180 |
| ClinVar full | GRCh38 | 0.999974091 | 1.000000000 | 91,552,813 | 91,552,813 | 91,550,441 |
| gnomAD v2.1.1 chr21 | GRCh37 | 0.999999729 | 1.000000000 | 11,075,422 | 11,075,422 | 11,075,419 |
| gnomAD v4.1 chr21 | GRCh38 | 0.999999303 | 1.000000000 | 110,503,269 | 110,503,269 | 110,503,192 |
| 1KG Phase 3 chr21 | GRCh37 | 1.000000000 | 1.000000000 | 3,603,259 | 3,603,259 | 3,603,259 |
| 1KG high-cov chr21 | GRCh38 | 0.999999904 | 1.000000000 | 10,420,122 | 10,420,122 | 10,420,121 |
| SV per-VCF (16 files) | GRCh37 | 0.969197320 | 1.000000000 | 329,864 | 337,513 | 323,410 |
| SV per-VCF (16 files) | GRCh38 | 0.902664038 | 1.000000000 | 1,117,037 | 1,274,145 | 1,079,217 |
Wall time, median of 20 independent machines per cell, ARM Graviton4 (r8gd.8xlarge)
and x86 Intel (r8id.8xlarge), 16 threads, local NVMe, sites-only inputs, the discarded warmup's
output deleted before the timed run: ClinVar GRCh37 4.31 s ARM / 5.64 s x86; ClinVar GRCh38 10.43 s ARM / 11.46 s x86; gnomAD v2.1.1 chr21 3.32 s ARM / 5.86 s x86; gnomAD v4.1 chr21 9.66 s ARM / 15.64 s x86; 1KG Phase 3 chr21 0.56 s ARM / 0.98 s x86; 1KG high-cov chr21 0.95 s ARM / 1.42 s x86.
Install
| File | Platform | CPU floor | SHA256 |
|---|---|---|---|
| vep-0.3.2-x86_64-unknown-linux-gnu.tar.gz | Linux x86_64 (glibc 2.39 or later) | x86-64-v3: AVX2, BMI2, FMA (Intel Haswell 2013 or later, AMD Zen or later) | a52df441c299e7690c6732d81da13e54192801f577814b5db282820eee32baf4 |
| vep-0.3.2-aarch64-unknown-linux-gnu.tar.gz | Linux aarch64 (glibc 2.39 or later) | Armv8.4-A with SVE (Arm Neoverse V1 or later: AWS Graviton3 and later; not Graviton2, Ampere Altra or Raspberry Pi) | 692c66dbb11af0056bdd1511ec4028aedf462a1b761576ff5c1dfc1d56458217 |
| vep-0.3.2-aarch64-apple-darwin.tar.gz | macOS 11 or later on Apple silicon | any Apple M-series | 3b138436813751ebfc265f72605786dd9069cb51669d0389b9ba0623e8e8729e |
Each archive unpacks to vep-0.3.2-<target>/ holding vep, vep-cache-builder and
vep-cache-converter. A binary run on a CPU below its floor aborts with an illegal-instruction
fault rather than running slowly; on such a host build from source, which compiles for the machine
it runs on when RUSTFLAGS="-C target-cpu=native" is set.
curl -LO https://github.com/natera-open-source/vep-rs/releases/download/v0.3.2/vep-0.3.2-x86_64-unknown-linux-gnu.tar.gz
curl -LO https://github.com/natera-open-source/vep-rs/releases/download/v0.3.2/SHA256SUMS
sha256sum -c --ignore-missing SHA256SUMS # macOS: shasum -a 256 -c --ignore-missing SHA256SUMS
tar xzf vep-0.3.2-x86_64-unknown-linux-gnu.tar.gzContainer image, pushed when this release is published: docker pull ghcr.io/natera-open-source/vep-rs:0.3.2
(linux/amd64: the x86_64 binaries above and the duckdb CLI that Parquet output needs).
From source (Rust 1.88 or newer): cargo build --release --locked. The README covers
the JSON transcript cache every run needs.
Verify
Built by the release workflow
from tag v0.3.2 (commit dd55b91219a9bf433608906950acbc29645493f1) with Rust 1.97.1 and cargo build --release --locked.
Every file in SHA256SUMS carries a GitHub build-provenance attestation:
gh attestation verify vep-0.3.2-x86_64-unknown-linux-gnu.tar.gz --repo natera-open-source/vep-rsSource archive
vep-rs-0.3.2.tar.gz is git archive --format=tar.gz --prefix=vep-rs-0.3.2/ v0.3.2, sha256 cc61520bc8542e96289218e68af9e57f05fab313edbab9fb6cb13ea3cb2518b9.
Citing
Porter M, Borkowski R. vep-rs, version 0.3.2. 2026. doi:10.5281/zenodo.22837896.
CITATION.cff carries the citation in machine-readable form; the README's Citing section names the
accompanying paper.
vep-rs 0.3.1
vep-rs 0.3.1 carries exact adjusted concordance with Ensembl VEP 115.2 from the chromosome 21 measurement to the whole genome: on gnomAD v4.1, gnomAD v2.1.1, 1000 Genomes Phase 3 and 1000 Genomes high-coverage, 1,179,639,224 variants and 9,281,654,995 annotation tuples, every tuple outside the documented divergence classes is matched, after four consequence rules at the edges of the coding region and the coordinates of a symbolic insertion were brought to Ensembl VEP's reading; anyone annotating whole-genome call sets, and anyone annotating symbolic insertions, should upgrade.
vep-rs is a from-scratch Rust implementation of the Ensembl Variant Effect Predictor: the same
inputs and flags, VEP's consequence vocabulary in VEP's output formats plus Parquet, measured for
concordance against Ensembl VEP at population scale.
Upgrade notes
- Consequence terms move on the records the changelog's Fixed entries name: an insertion between an intron's last base and the coding region's edge base is a UTR variant beside its splice term; a variant in a frameshift intron on the UTR side of the coding region takes the UTR term instead of
coding_sequence_variant; structuralstop_lostrequires the deletion to overlap the coding region and an exon; a structural span starting on the first base of a transcript whose coding region starts there carries no 5' UTR term. - A symbolic insertion whose
ENDis its position or whoseSVLENis 0 (the<INS:MT>and<INS:ME:*>records of 1000 Genomes Phase 3 and call sets of that shape) is the insertion between two bases: its Location names both flanks (11:7309883-7309884, where 0.3.0 wrote11:7309884), its row carries noOverlapBPorOverlapPC, and its consequence terms read the pair. Tooling keyed on the Location column of such rows sees the new form. - Flags, input formats, output formats and the JSON cache format are unchanged; a cache converted for 0.3.0 is valid.
Changes
Added
- The SNP/indel comparator applies the transcript-selection class of
docs/intended-divergences.md(section 3) to the records of a whole-genome
input that Ensembl VEP marks skipped, under the structural-variant
comparator's two guards, and reports it assv_transcript_selection; the
scope test is defined once and shared by the two comparators.
Fixed
Each entry names the Ensembl VEP mechanism vep-rs follows.
- A symbolic insertion whose
ENDis its position or whoseSVLENis 0 is the
insertion between the two bases,start = POS + 1, end = POS, as ensembl-io's
get_endreads it: its Location names both flanks, its predicates read the
pair as_intron_effectsreads a sequence insertion (both flanks inside a
region, the two insertion special cases at the intron edges, the UTR special
cases at the coding region's edges,within_cdnathroughmap_insert), and
the row carries noOverlapBPorOverlapPC(an overlap length of 0). A
symbolic record with neither field stays the single base atPOS + 1, which
is also ensembl-io's reading. - UTR term on an insertion at the edge of the coding region:
_before_coding
and_after_codingspecial-case an insertion whose start is the coding
region start or whose end is the coding region end, so an insertion between
the last base of an intron and the first base of a coding exon (or between
the coding region's last base and the intron after it) is5_prime_UTR_variantor
3_prime_UTR_variantby strand beside its splice term, where it carried the
splice term alone. - A frameshift intron on the UTR side of the coding region:
within_cds
requires the span to overlap the coding region, and_bvfo_predssetsutr
rather thancodingfor a span that does not, so a variant inside an intron
of twelve bases or fewer that lies before the coding region is
5_prime_UTR_variant(or3_prime_UTR_variantafter it) rather than
coding_sequence_variant. - Structural
stop_lostbehind thecodingpre-predicate: the term carries
include {coding => 1}, and_bvfo_predssetscodingonly for a span that
overlaps the coding region and an exon, so a deletion inside the intron that
splits a stop codon isnon_codingand carries nostop_lost, although the
codon window drawn on genomic coordinates reaches into that intron. - No UTR term on a structural span that starts on the first base of a
transcript whose coding region starts there (cds_start_NF, and likewise at
the last base withcds_end_NF):_before_codingis
overlap(start, end, transcript start, coding_region_start - 1), an inverted
window that admits only a span starting before the transcript.
Full entry: CHANGELOG.md (this version is its first section) ·
Full Changelog: v0.3.0...v0.3.1
Concordance and wall time for this release
The paper's published figures are unchanged; these are the released version's own, from the
release's provenance record under docs/concordance-provenance/
(method: scripts/concordance/run_clone_measurement.sh).
| Dataset | Assembly | Raw F1 | Adjusted F1 | VEP tuples | vep-rs tuples | Matched |
|---|---|---|---|---|---|---|
| ClinVar full | GRCh37 | 0.999979 | 1.000000 | 33,483,881 | 33,483,881 | 33,483,180 |
| ClinVar full | GRCh38 | 0.999974 | 1.000000 | 91,552,813 | 91,552,813 | 91,550,441 |
| gnomAD v2.1.1 chr21 | GRCh37 | 1.000000 | 1.000000 | 11,075,422 | 11,075,422 | 11,075,419 |
| gnomAD v4.1 chr21 | GRCh38 | 0.999999 | 1.000000 | 110,503,269 | 110,503,269 | 110,503,192 |
| 1KG Phase 3 chr21 | GRCh37 | 1.000000 | 1.000000 | 3,603,259 | 3,603,259 | 3,603,259 |
| 1KG high-cov chr21 | GRCh38 | 1.000000 | 1.000000 | 10,420,122 | 10,420,122 | 10,420,121 |
| SV per-VCF (16 files) | GRCh37 | 0.969197 | 1.000000 | 329,864 | 337,513 | 323,410 |
| SV per-VCF (16 files) | GRCh38 | 0.902664 | 1.000000 | 1,117,037 | 1,274,145 | 1,079,217 |
Whole-genome concordance of the released binary on four population datasets, one run per
chromosome on ARM Graviton4, against Ensembl VEP 115.2's output on the same inputs; a variant is
one VCF record, a tuple one output row reduced to its Location, Allele, Feature, Feature_type and
Consequence set, and F1 pools the chromosomes by summed counts:
| Dataset | Assembly | Chromosomes | Variants | VEP tuples | vep-rs tuples | Matched | Raw F1 | Adjusted F1 |
|---|---|---|---|---|---|---|---|---|
| gnomAD v4.1, whole genome | GRCh38 | 24 | 759,336,320 | 7,409,818,550 | 7,409,818,550 | 7,409,815,011 | 1.000000 | 1.000000 |
| gnomAD v2.1.1, whole genome | GRCh37 | 23 | 261,942,336 | 885,664,902 | 885,664,902 | 885,664,478 | 1.000000 | 1.000000 |
| 1000 Genomes Phase 3, whole genome | GRCh37 | 25 | 84,805,772 | 286,649,478 | 286,649,478 | 286,649,396 | 1.000000 | 1.000000 |
| 1000 Genomes high-coverage, whole genome | GRCh38 | 23 | 73,554,796 | 699,522,065 | 699,534,118 | 699,521,778 | 0.999991 | 1.000000 |
| All four | GRCh37 and GRCh38 | 95 | 1,179,639,224 | 9,281,654,995 | 9,281,667,048 | 9,281,650,663 | 0.999999 | 1.000000 |
Wall time, median of 20 independent machines per cell, ARM Graviton4 (r8gd.8xlarge)
and x86 Intel (r8id.8xlarge), 16 threads, local NVMe, sites-only inputs, the discarded warmup's
output deleted before the timed run: ClinVar GRCh37 5.76 s ARM / 6.02 s x86; ClinVar GRCh38 11.93 s ARM / 12.14 s x86; gnomAD v2.1.1 chr21 6.77 s ARM / 9.84 s x86; gnomAD v4.1 chr21 12.88 s ARM / 16.56 s x86; 1KG Phase 3 chr21 0.84 s ARM / 0.97 s x86; 1KG high-cov chr21 1.20 s ARM / 1.39 s x86.
Install
| File | Platform | CPU floor | SHA256 |
|---|---|---|---|
| vep-0.3.1-x86_64-unknown-linux-gnu.tar.gz | Linux x86_64 (glibc 2.39 or later) | x86-64-v3: AVX2, BMI2, FMA (Intel Haswell 2013 or later, AMD Zen or later) | d61bc06086ff2c244bd596af31841d2e2b58cef1524f96f81ab5bda9636c1f92 |
| vep-0.3.1-aarch64-unknown-linux-gnu.tar.gz | Linux aarch64 (glibc 2.39 or later) | Armv8.4-A with SVE (Arm Neoverse V1 or later: AWS Graviton3 and later; not Graviton2, Ampere Altra or Raspberry Pi) | ec489cb55669ecdea09e226bf77b451f944537b72d765921e8c7d05e325cafb8 |
| vep-0.3.1-aarch64-apple-darwin.tar.gz | macOS 11 or later on Apple silicon | any Apple M-series | 6261cb155f66f370581c7651e3afd63ed3595e0b894bb1c29cfbdc698f11db60 |
Each archive unpacks to vep-0.3.1-<target>/ holding vep, vep-cache-builder and
vep-cache-converter. A binary run on a CPU below its floor aborts with an illegal-instruction
fault rather than running slowly; on such a host build from source, which compiles for the machine
it runs on when RUSTFLAGS="-C target-cpu=native" is set.
curl -LO https://github.com/natera-open-source/vep-rs/releases/download/v0.3.1/vep-0.3.1-x86_64-unknown-linux-gnu.tar.gz
curl -LO https://github.com/natera-open-source/vep-rs/releases/download/v0.3.1/SHA256SUMS
sha256sum -c --ignore-missing SHA256SUMS # macOS: shasum -a 256 -c --ignore-missing SHA256SUMS
tar xzf vep-0.3.1-x86_64-unknown-linux-gnu.tar.gzContainer image, pushed when this release is published: docker pull ghcr.io/natera-open-source/vep-rs:0.3.1
(linux/amd64: the x86_64 binaries above and the duckdb CLI that Parquet output needs).
From source (Rust 1.88 or newer): cargo build --release --locked. The README covers
the JSON transcript cache every run needs.
...
vep-rs 0.3.0
vep-rs 0.3.0 reaches exact adjusted concordance with Ensembl VEP 115.2 on every dataset of the measurement, on ClinVar (whole genome) and on chromosome 21 of gnomAD and 1000 Genomes for both assemblies: ten consequence-engine changes port the Ensembl mechanisms 0.2.0 lacked, the JSON cache carries each translation's sequence edits, and every class of disagreement the adjusted figure sets aside is documented with a worked example in docs/intended-divergences.md; anyone annotating structural variants, or annotating from a converted cache, should upgrade.
vep-rs is a from-scratch Rust implementation of the Ensembl Variant Effect Predictor: the same
inputs and flags, VEP's consequence vocabulary in VEP's output formats plus Parquet, measured for
concordance against Ensembl VEP at population scale.
Upgrade notes
- The JSON cache format gains
variation_effect_feature_cache.seq_edits, the translation's sequence edits, whichscripts/data/storable_to_json.plwrites. A cache converted by an earlier version loads and applies no edit, so a variant at codon 1 of a transcript with an alternative initiation codon is called from the cached peptide (synonymous_variantwhere Ensembl VEP writesstart_lost); convert the cache again to get Ensembl VEP's call there. - Two structural-variant outputs depart from Ensembl VEP's, each a documented class on
docs/intended-divergences.md: a gVCF<NON_REF>reference block is written as oneintergenic_variantrow with a warning instead of transcript rows (class 10), and the mate-side row of a paired breakend describes the mate breakend at the mate coordinate instead of reproducing Ensembl VEP'sfeature_truncationorintergenic_variantfall-through (class 11). Raw concordance on the structural-variant sets is lower than 0.2.0's because those rows leave the raw intersection and no other row does; adjusted concordance is 1.0 on both sets. - Consequence terms move on the records of the other eight mechanisms, each listed in the changelog with the Ensembl module it follows: an alternative initiation codon is
start_lost, splice terms skip a frameshift intron,transcript_ablationrequires a deletion, and structural alleles take the polypyrimidine tract term, a mate-proximity gate on a breakend's bracket allele, biotype-gated context terms andstart_lostover a start codon. Flags and input formats are unchanged.
Changes
Added
- A container image,
ghcr.io/natera-open-source/vep-rs, for each published
release from 0.2.0: the release's attested x86_64 Linux binaries and the
duckdbCLI on Debian 13, smoke-tested on the GRCh37 corpus before it is
pushed, with a build-provenance attestation on the pushed digest
(.github/workflows/docker.yml). docs/intended-divergences.md: every class the adjusted concordance sets
aside, each with the record, both engines' rows, the mechanism in Ensembl
VEP's source, and a command that reproduces it.- Structural-variant comparator masks for the second side of two classes and
for three more: theintergenic_variantrow vep-rs writes for a record
whose VEP tuples all name transcripts on another chromosome
(filter_cross_chromosome_orphan_intergenic); the mate allele of a
breakend above--max_sv_sizethat VEP never wrote, gated on the mate
lying within 5 kb of the transcript span
(filter_giant_breakend_mate_divergences); the SNP/indel registry's
excluding rules applied to structural pairs (filter_registry_swap_pairs);
VEP's batch-dependent Transcript tuples on a<NON_REF>record
(filter_non_ref_batch_divergences); and a mate-side row VEP evaluated at
the local coordinate (filter_breakend_mate_local_read_pairs), with
scripts/validation/breakend_mate_context.pyderiving the mate-coordinate
and local-coordinate readings from the JSON cache. The transcript-selection
mask's unsupported-type scope names<CPX>and<CTX>. - The golden classifier names
breakend_mate_local_read, computed by the
same derivation over the corpus's own pruned cache. - The comparators write the adjusted residual:
discordant_open.tsvbeside
discordant.tsvfor the SNP and indel sets anddiscordant_adjusted.tsv
for the structural-variant sets, each the one-sided rows every mask leaves
in place. Per-class mode caches the per-term VEP totals of a reference
output (--vep-totals-cache).
Changed
- JSON cache format: each transcript's
variation_effect_feature_cache
carriesseq_edits, the translation'sBio::EnsEMBL::SeqEditlist
(start,endandalt_seqin protein coordinates, withcode,name
andlength_diff), whichscripts/data/storable_to_json.plwrites from
the Storable cache. vep-rs applies the edits overlapping a variant's
translation span to the reference allele's peptide, as
TranscriptVariationAllele::peptidedoes. A cache converted without the
key still loads: no edit is applied, and a variant at codon 1 of a
transcript with an alternative initiation codon is called from the cached
peptide. Convert such a cache again to get VEP's calls there. - The deletion-shaped evaluation of a same-chromosome breakend span borrows
the variant for each overlapping transcript instead of copying it with the
consequences accumulated so far, which grew with the square of the
transcript count. Output is unchanged.
Fixed
Each entry names the Ensembl VEP mechanism vep-rs follows.
- Start codon on an alternative initiation codon: with
seq_editsin the
cache, aninitial_metoramino_acid_subedit over a non-ATG start
codon gives a referenceMagainst the alternate allele's literal
residue, so the variant isstart_lostrather thansynonymous_variant
andAmino_acidsprints the edited residue. - Splice terms across a frameshift intron:
_intron_effectsskips an intron
of twelve bases or fewer for every differing region that overlaps it, in
both of its loops, so a deletion running from one exon across such an
intron into the next carries no splice term; the coding predicates alone
decide the row. The exonic splice windows apply the same skip, so a donor
window that crosses such an intron yields nosplice_donor_5th_base_variant. transcript_ablationrequires Perl'sdeletionpre-predicate (the
reference span longer than the ALT sequence) besidecomplete_overlap. A
same-length substitution or a longer ALT covering a whole transcript takes
the tier-3 predicates instead: the biotype's context term with the UTR,
intron and splice terms of the span.splice_polypyrimidine_tract_varianton structural alleles: a structural
allele whose span reaches the 15 bp window inside an intron's acceptor end
carries the term unless the span touches an exon of the transcript, as
Ensembl's predicate does for every BaseVariationFeature. A<CNV:TR>
allele keeps its endpoint test.- A paired breakend's bracket allele gets a row for a transcript only when
the mate coordinate lies withinMAX_DISTANCE_FROM_TRANSCRIPT(5 kb) of
it (StructuralVariationOverlap::_close_to_feature); the local POS is
carried by the single-breakend allele. - A single-breakend allele above
--max_sv_sizethat partially covers a
coding transcript takes the region predicates like every other
same-chromosome span; VEP requirescomplete_overlap_featurefor
coding_transcript_variantat any span. - The context term of a transcript a structural allele engulfs follows the
biotype, as VEP's include hashes do:coding_transcript_variantonly for
protein_coding,NMD_transcript_variantonly for
nonsense_mediated_decay,non_coding_transcript_variantonly without a
translation, andintergenic_variantfor a translated transcript of any
other biotype. One rule serves the inversion, copy-number, insertion and
breakend arms. - Structural insertions, mobile-element insertions and duplications whose
span covers a start-codon base with both ends in exons emitstart_lost,
the genomic-overlap predicate the deletion arm applies.
start_retained_variant, which VEP co-emits there without reading
sequence, is not emitted. - The mate-side Transcript row of a paired breakend describes the mate
breakend at the mate coordinate:feature_truncationwith the region term
when the mate lies inside the transcript,upstream_gene_variantor
downstream_gene_variantwith the distance when it lies within the window
outside, and no row beyond it. VEP evaluates every predicate but
feature_truncationat the local coordinate there. - A gVCF
<NON_REF>record is a reference-confidence block, not an
alternate allele. It is written as oneintergenic_variantrow spanning
POS+1 to END with the allele as written andIMPACT=MODIFIER, with a
warning per record; that is the row VEP writes when no other record in the
batch loads the region. A<NON_REF>carrying a supportedINFO/SVTYPE
keeps that type.
Full entry: CHANGELOG.md (this version is its first section) ·
Full Changelog: v0.2.0...v0.3.0
Concordance and wall time for this release
The paper's published figures are unchanged; these are the released version's own, from the
release's provenance record under docs/concordance-provenance/
(method: scripts/concordance/run_clone_measurement.sh).
| Dataset | Assembly | Raw F1 | Adjusted F1 | VEP tuples | vep-rs tuples | Matched |
|---|---|---|---|---|---|---|
| ClinVar full | GRCh37 | 0.999979 | 1.000000 | 33,483,881 | 33,483,881 | 33,483,180 |
| ClinVar full | GRCh38 | 0.999974 | 1.000000 | 91,552,813 | 91,552,813 | 91,550,441 |
| gnomAD v2.1.1 chr21 | GRCh37 | 1.000000 | 1.000000 | 11,075,422 | 11,075,422 | 11,075,419 |
vep-rs 0.2.0
vep-rs 0.2.0 prints Ensembl VEP's own HGVSc and HGVSp, ported whole from VEP's hgvs_transcript and hgvs_protein, adds HGVS_OFFSET beside them, and moves every dependency to its current release; anyone annotating with --hgvs should upgrade.
vep-rs is a from-scratch Rust implementation of the Ensembl Variant Effect Predictor: the same
inputs and flags, VEP's consequence vocabulary in VEP's output formats plus Parquet, measured for
concordance against Ensembl VEP at population scale.
Upgrade notes
--hgvsoutput changes. HGVSp is printed for in-frame insertions between codons, duplications, stop-loss extensions, insertions carrying a stop codon and deletions shifted at the peptide level, where 0.1.0 printed nothing or a different string; HGVSc changes on deletions that cross an exon boundary or the start or stop codon, reverse-stranddelinsranges, insertions without a readable reference and variants outside the transcript span; andHGVS_OFFSETappears as a new key wherever an insertion or deletion was shifted, in every output format. A pipeline that diffs HGVS strings between versions will see those rows move to VEP's values. Flags, input formats and the cache format are unchanged.
Changes
Fixed
- HGVSp is Perl VEP's
hgvs_protein, ported whole. In-frame insertions
between codons, duplications, stop-loss extensions (extTer{n}and
extTer?), insertions carrying a stop codon and deletions shifted at the
peptide level print VEP's string where they printed nothing or a different
one. The coding gate is read from the allele as annotated and the
frameshift test from its 3'-shifted span, as VEP reads them, and the
transcript peptide asTranscript::translatewrites it (Met1for any
start codon of the table). The one intended difference: on a variant that
keeps the start codon intact and is reported asstart_retained_variant,
VEP printsp.Met1?from its ownstart_lostcall while vep-rs prints
the peptide change. - HGVSc is Perl VEP's
hgvs_transcript, ported whole: the 3' shift within
1,000 bases of flank, the variant typing and duplication lookup of
hgvs_variant_notation, allele clipping and_get_cDNA_position.
Deletions that cross an exon boundary or the start or stop codon,
reverse-stranddelinsranges, insertions without a readable reference
and variants outside the transcript span now match VEP. HGVS_OFFSETis emitted besideHGVScandHGVSpwhen an insertion or
deletion was shifted, signed by the transcript strand as VEP signs it.
Added
- A GRCh37 chromosome 21 golden corpus generated with
--hgvs
(tests/golden/115/GRCh37-hgvs/), carrying the complete chromosome 21
reference so the golden tests compareHGVSc,HGVSpandHGVS_OFFSET
against Ensembl VEP's output in every format with no external file. - Release measurements beside the paper's: the README's "Current release"
section states the released version's ten-suite concordance and its wall
times (20 independent machines per cell on both architectures) beneath the
paper's tables, which stay as published, from the release's provenance
record underdocs/concordance-provenance/.
Changed
- Releases: the workflow creates a draft that a maintainer publishes, with a
body rendered from the repository's files (scripts/release/render_release_notes.py);
the archives arevep-X.Y.Z-<target>.tar.gz, each unpacking to its own
directory; agit archivesource tarball ships with its.sha256; one
SHA256SUMScovers every archive and every file in it carries a build
provenance attestation (gh attestation verify);MD5SUMSis not published.
workflow_dispatchruns the same build as a dry run without a release. - Dependencies: noodles 0.109 (the last release declaring rust-version 1.88;
the bgzf readers and writer and the tabix index loader moved to their
ioandfsmodules), mysql 28 (vep-cache-builder), rand 0.10
(vep-cache-converter), criterion 0.8 (benches), rustls 0.23.45, and the
minor and patch releases of bigtools, bstr, clap, crossbeam-channel,
flate2, indexmap, rayon, rustc-hash, serde, serde_json, smallvec, tempfile,
thiserror and tracing-subscriber. The declared rust-version stays 1.88. - Workflows: every action is pinned to a commit sha with its tag beside it,
each rust-toolchain step names its Rust version through thetoolchain:
input, and the CI workflow's token is read-only. Dependabot ignores
noodles 0.110 and later (rust-version 1.89) and the pinned toolchain refs. - Golden corpus provenance records the digest of the released 0.1.0 binary
that classified the manifests. - The measurement harness (
scripts/concordance/run_clone_measurement.sh)
flushes and deletes the discarded warmup's output before every timed run,
so the timed run starts with the memory the warmup had; the warmup's
pages otherwise had to be reclaimed while the timed run wrote its own,
and that reclaim landed in the timed wall time while user and system time
stayed unchanged.
Security
- Cleared from the dependency tree: RUSTSEC-2026-0235 (rkyv),
RUSTSEC-2026-0173 (proc-macro-error2), RUSTSEC-2026-0002 (lru 0.12) and
RUSTSEC-2026-0097 (rand 0.8), all through the mysql and rand updates, and
RUSTSEC-2026-0285 (rustls) through the rustls update. None was reachable
from thevepbinary; all sat under vep-cache-builder or
vep-cache-converter.
Full entry: CHANGELOG.md (this version is its first section) ·
Full Changelog: v0.1.0...v0.2.0
Concordance and wall time for this release
The paper's published figures are unchanged; these are the released version's own, from the
release's provenance record under docs/concordance-provenance/
(method: scripts/concordance/run_clone_measurement.sh).
| Dataset | Assembly | Raw F1 | Adjusted F1 | VEP tuples | vep-rs tuples | Matched |
|---|---|---|---|---|---|---|
| ClinVar full | GRCh37 | 0.999979 | 1.000000 | 33,483,881 | 33,483,881 | 33,483,179 |
| ClinVar full | GRCh38 | 0.999974 | 1.000000 | 91,552,813 | 91,552,813 | 91,550,431 |
| gnomAD v2.1.1 chr21 | GRCh37 | 0.999999 | 1.000000 | 11,075,422 | 11,075,422 | 11,075,415 |
| gnomAD v4.1 chr21 | GRCh38 | 0.999999 | 1.000000 | 110,503,269 | 110,503,269 | 110,503,192 |
| 1KG Phase 3 chr21 | GRCh37 | 1.000000 | 1.000000 | 3,603,259 | 3,603,259 | 3,603,259 |
| 1KG high-cov chr21 | GRCh38 | 1.000000 | 1.000000 | 10,420,122 | 10,420,122 | 10,420,121 |
| SV per-VCF (16 files) | GRCh37 | 0.975395 | 0.998524 | 329,864 | 339,623 | 326,507 |
| SV per-VCF (16 files) | GRCh38 | 0.909998 | 0.998031 | 1,117,037 | 1,280,886 | 1,091,052 |
Wall time, median of 20 independent machines per cell, ARM Graviton4 (r8gd.8xlarge)
and x86 Intel (r8id.8xlarge), 16 threads, local NVMe, sites-only inputs, the discarded warmup's
output deleted before the timed run: ClinVar GRCh37 5.73 s ARM / 6.05 s x86; ClinVar GRCh38 11.71 s ARM / 12.22 s x86; gnomAD v2.1.1 chr21 6.78 s ARM / 9.86 s x86; gnomAD v4.1 chr21 13.08 s ARM / 16.74 s x86; 1KG Phase 3 chr21 0.85 s ARM / 0.96 s x86; 1KG high-cov chr21 1.23 s ARM / 1.42 s x86.
Install
| File | Platform | CPU floor | SHA256 |
|---|---|---|---|
| vep-0.2.0-x86_64-unknown-linux-gnu.tar.gz | Linux x86_64 (glibc 2.17 or later) | x86-64-v3: AVX2, BMI2, FMA (Intel Haswell 2013 or later, AMD Zen or later) | 2cf01951ca8772f5e2b0db4dbe137d65d2b7824167c46f1f37ec704b8339cc6c |
| vep-0.2.0-aarch64-unknown-linux-gnu.tar.gz | Linux aarch64 (glibc 2.17 or later) | Armv8.4-A with SVE (Arm Neoverse V1 or later: AWS Graviton3 and later; not Graviton2, Ampere Altra or Raspberry Pi) | 81c774df6da1eaa929432ed3930659c429dc15cce3ff1bc006e9393062afc109 |
| vep-0.2.0-aarch64-apple-darwin.tar.gz | macOS 11 or later on Apple silicon | any Apple M-series | f026f738d12a809ecb232a069a7fb4399c4300d98567e7a77ef64242cad411bd |
Each archive unpacks to vep-0.2.0-<target>/ holding vep, vep-cache-builder and
vep-cache-converter. A binary run on a CPU below its floor aborts with an illegal-instruction
fault rather than running slowly; on such a host build from source, which compiles for the machine
it runs on when RUSTFLAGS="-C target-cpu=native" is set.
curl -LO https://github.com/natera-open-source/vep-rs/releases/download/v0.2.0/vep-0.2.0-x86_64-unknown-linux-gnu.tar.gz
curl -LO https://github.com/natera-open-source/vep-rs/releases/download/v0.2.0/SHA256SUMS
sha256sum -c --ignore-missing SHA256SUMS # macOS: shasum -a 256 -c --ignore-missing SHA256SUMS
tar xzf vep-0.2.0-x86_64-unknown-linux-gnu.tar.gzFrom source (Rust 1.88 or newer): cargo build --release --locked. The README covers
the JSON transcript cache every run needs.
Verify
Built by the release workflow
from tag v0.2.0 (commit 5f3dc135b3e2556801cb529f2470a88dec2e9f80) with Rust 1.97.1 and cargo build --release --locked.
Every file in SHA256SUMS carries a GitHub build-provenance attestation:
gh attestation verify vep-0.2.0-x86_64-unknown-linux-gnu.tar.gz --repo natera-open-source/vep-rsSource archive and DOI
vep-rs-0.2.0.tar.gz is git archive --format=tar.gz --prefix=vep-rs-0.2.0/ v0.2.0, sha256 7eccedd3418ebb950c6133dd358f3fae6dbb8a7d3be794bb8ea382f941b6edd6.
This version has no Zenodo...
vep-rs 0.1.0
First public release of vep-rs, a from-scratch Rust implementation of the Ensembl Variant Effect Predictor.
Archived source: Zenodo, doi:10.5281/zenodo.22837897 (version DOI; all versions: 10.5281/zenodo.22837896). The archived vep-rs-0.1.0.tar.gz is git archive --format=tar.gz --prefix=vep-rs-0.1.0/ v0.1.0 of this repository, sha256 0312f420f80dabac639ffae674ff1bbf148fdaf0c53e431ef075ffda20cc92b1.
Binaries (built by the release workflow on this tag): Linux x86_64 (AVX2 required), Linux aarch64, macOS aarch64, with SHA256SUMS and MD5SUMS. Building from source needs Rust 1.88 or newer; see the README.
What is in 0.1.0: the vep annotator with VEP's default, VCF, JSON and Tab output formats plus Parquet; vep-cache-builder and vep-cache-converter; ten supported built-in plugins; the concordance and wall-time harness and the released measurement data under manuscript/data/. Details in CHANGELOG.md.
Citing: CITATION.cff carries the software citation; the accompanying paper's citation is added to the README on publication.