$ admissible v0.1.0
Exome evidence audit

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.

$ pipx install admissible Get started View source
153 tests passing Python 3.10 – 3.14 zero runtime dependencies MIT licensed DOI 10.5281/zenodo.22738502
admissible audit family/*.vcf --ped family.ped
$ 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.

CHECK 01 · IDENTITY

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.

CHECK 02 · GENOTYPE

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.

CHECK 03 · PROVENANCE

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.

CHECK 04 · CALLABILITY

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.

CHECK 05 · MODELS

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.

DESIGN RULE

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.

0 wrong
16 of 17 sex calls correct; 1 returned undetermined at the boundary rather than guessed.
0 / 136
false duplicate pairs across 136 comparisons; 0 of 11 truly unrelated pairs called related.
0.38 ≠ 0.22
joint callable fraction vs. the product of per-sample fractions on real capture — the product is 41% low.

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.

not a variant interpreter no bundled annotation database reads only your own files degree unresolved on single-sample VCFs