Audit whether exome data can support an interpretation — before you interpret it.
admissible does not tell you whether a variant is pathogenic. It tells you whether your evidence is admissible: whether the samples are who the pedigree says they are, whether the file is the file you think it is, and whether you searched enough of the exome to be allowed to report a negative.
$ admissible audit family/*.vcf --ped family.ped COHORT FAM_B VERDICT: NOT INTERPRETABLE Identity .......... FAIL 2 duplicate pair(s), 2 sex mismatch(es) Provenance ........ WARN CODING_ONLY + PASS_FILTERED + SUBSET Callable .......... UNKNOWN no coverage supplied; a VCF cannot answer this Genotype QC ....... WARN 318 of 2104 homozygous calls unsupported (15%) Models ............ WARN 0 candidates under 4 models; not rarity-filtered DO NOT CONCLUDE: "no monogenic cause" NEXT STEPS: 1. resolve sample identity (blocking) 2. re-call without the coding-only interval file
Why this exists
A candidate variant held up for a year turned out to be a false homozygous call supported by two reads. Chasing it surfaced two more failures nobody's pipeline had raised: two exomes filed under one family belonged to different people, and the VCFs had been pre-filtered to coding-only, PASS-only before delivery — so only a fraction of the exome was ever searchable.
Interpretation platforms, annotators and by-the-book
workflows all answer the same question — is this variant
pathogenic? None answers the one that comes first: can I trust
this data, and did I actually search enough? That gap is this tool.
It never interprets a variant; it audits the evidence base an
interpretation would rest on, and where your inputs cannot answer a
question it reports UNKNOWN rather than guessing.
Five checks, one verdict
Input is a family's VCFs and a PED file (optionally mosdepth coverage). Output is a one-page verdict in human-readable text and machine-readable JSON.
Is each sample who the pedigree says?
Cohort-wide duplicate detection, relatedness (Jaccard, genotype agreement, or KING-robust kinship + IBS0 on joint calls) and sex from chrX heterozygosity — calibrated on your cohort, not hard-coded.
Which calls aren't supported by their own evidence?
Likelihood and allele-balance arms flag homozygous calls that
the reads don't back — reading AD, RO/AO
and DP4, not just one spelling of depth.
Is this file actually a whole exome?
Detects coding-only extracts, PASS-only deliveries, sites-only exports and merges that rewrote genotypes — naming the transformation, not just flagging that something is off.
How much of the target did you really search?
The joint callable fraction is an intersection, never a product —
measured on real capture. Reports UNKNOWN from VCFs
alone, because a VCF genuinely cannot answer it.
What does the inheritance-model profile look like?
Every model in the sweep carries its own callable fraction. A count is never printed without its denominator — because zero over 20% and zero over 95% are not the same finding.
Nothing raises.
A tool whose job is to describe broken files must not die on one. Truncated, double-gzipped, headerless, or not-a-VCF-at-all — each yields a typed failure with a stated reason. The suite fuzzes for it.
Install & run
The command is admissible, abbreviated
adm. Zero required runtime dependencies.
INSTALL
# its own environment, nothing else touched pipx install admissible # or into the current environment pip install admissible # or with Docker — CLI and site in one image docker run --rm admissible audit \ family/*.vcf --ped family.ped
AUDIT
# build the pedigree from your VCFs admissible ped-template family/*.vcf.gz \ > family.ped # the full audit, text + JSON admissible audit family/*.vcf \ --ped family.ped --json report.json # or one check at a time admissible identity family/*.vcf -v admissible provenance family/*.vcf
Exit codes: 0
nothing blocking · 1 a check failed or raised a blocking
finding · 2 the inputs could not answer the question.
Validated on public data
Synthetic fixtures written by the author of the code are weak evidence, so checks run against CEPH pedigree 1463 (the Utah three-generation family, as distributed with peddy) and real 1000 Genomes capture — where they found real defects, now fixed.
Allele depth is not always spelled AD.
freebayes writes RO/AO, older samtools pipelines
DP4. Reading only AD left the whole
allele-balance arm silently inert on freebayes output — now it
fires, and finds 20 false-homozygote candidates the likelihood
arm alone misses.
Gene assignment is not always an ANNOVAR key.
VEP writes CSQ, SnpEff writes ANN.
Reading only flat keys made compound-heterozygous report
not-applicable on most annotated VCFs, CEPH included.
It now computes.
A heterozygote read as a homozygote is the one failure this tool exists to prevent.
The ANNOVAR reader was committing it — every multiallelic
1/2 became a homozygous alternate because
AC=1,1 sums to two. It now reads the original
FORMAT columns: 120 of 120 genotypes correct.
What it cannot see
Stated so it can be challenged rather than discovered.
Callability here is depth-based, so it is blind to structural variation:
a heterozygous deletion leaves depth above any sensible floor, the
surviving allele is called homozygous with clean allele balance, and both
checks pass while the genotype is still wrong. Where a CNV is plausible,
a read-depth or split-read caller answers a question this tool does not
ask. The target BED is taken on trust; only a gross mismatch trips
NOT_INTERVAL_RESTRICTED.