Caller-agnostic locus disambiguation engine for paralog and pseudogene regions — ONT long-read only.
LocusGuard annotates variants in problematic genomic regions with the true locus of origin plus a confidence score, supported by multi-evidence scoring (PSV match, haplotype consistency, MAPQ pattern, soft-clip, coverage ratio) and reports homozygous-deletion status per paralog in the summary JSON. It does not call variants; it augments the output of your existing caller (Clair3, DeepVariant, etc.).
Each annotated variant carries:
TRUE_LOCUS— assigned locusLOCUS_CONF— confidence in[0, 1]LOCUS_STATUS—RESOLVED|PROBABLE|AMBIGUOUS|UNASSIGNEDLOCUS_EVIDENCE— per-source decompositionLOCUS_KEY— cross-output traceability keyGENE_CONVERSION_FLAG— 1 if gene conversion suspected
Phase 2.8. Supported: SMN1/SMN2 on GRCh38. ONT long-read input only. Three data types accepted: --data-type wgs | wes | panel. Multi-evidence scoring (PSV match, haplotype consistency, MAPQ pattern, soft-clip, coverage ratio), haplotype clustering, gene-conversion detection, and homozygous-deletion detection are all active. WES and Panel modes silence the coverage-ratio adapter (capture asymmetry breaks its assumptions) and accept an optional --capture-bed <path.bed> for PSV coverage validation — when provided, missing PSVs are reported in the summary and manifest warnings. ont_wes and ont_panel profile weights are scaffolds mirroring ont_wgs; real-data calibration pending.
Absolute copy-number quantitation was removed in Phase 2.6-alt — benchmarking on HG002 R10.4.1 Dorado sup and olgu1 (R9/R10) showed the depth-based estimator is sensitive to aligner primary/secondary mapping decisions, yielding chemistry- and pipeline-dependent bias that cannot be closed with a static calibration factor. For absolute CN (SMA carrier screening etc.), use an orthogonal method (MLPA, ddPCR).
Not yet supported: ONT WES/Panel weight calibration with real data (future phase), GBA/PMS2 (Phase 3), BAM output (Phase 3), packaging for Bioconda/Docker/nf-core (Phase 4).
pip install git+https://github.com/enes-ak/locusguard.gitOr from source:
git clone https://github.com/enes-ak/locusguard
cd locusguard
pip install -e ".[dev]"export LOCUSGUARD_GRCH38_FASTA=/refs/grch38.primary.fa
locusguard annotate \
--bam patient.bam \
--vcf patient.vcf.gz \
--reference grch38 \
--data-type wgs \
--locus SMN1,SMN2 \
--emit-report \
--output patient.lg.vcf.gzOutputs:
patient.lg.vcf.gz— annotated VCF with per-variantLOCUS_*INFO fieldspatient.lg.summary.json— per-locus status +deletion_statusper locuspatient.lg.manifest.json— versions, config hashes, command, runtimepatient.lg.report.html— human-readable report with Deletion Status panel
For ONT Panel or WES input with a capture bed:
locusguard annotate \
--bam patient.bam \
--vcf patient.vcf.gz \
--reference grch38 \
--data-type panel \
--capture-bed my_panel.bed \
--locus SMN1,SMN2 \
--emit-report \
--output patient.lg.vcf.gzThe --capture-bed flag activates PSV-coverage validation: any PSV position
outside the capture bed is reported as missing in the summary JSON and
flagged in the manifest warnings.
from pathlib import Path
from locusguard.api import Annotator
from locusguard.config import load_config
from locusguard.deletion import classify_deletion
configs = [load_config(p) for p in ["SMN1.yaml", "SMN2.yaml"]]
annotator = Annotator(
configs=configs,
reference_fasta=Path("/refs/grch38.primary.fa"),
data_type="wgs",
)
result = annotator.annotate_vcf(
bam=Path("patient.bam"),
vcf_in=Path("patient.vcf.gz"),
vcf_out=Path("patient.lg.vcf.gz"),
html_report_path=Path("patient.lg.report.html"),
)
for locus_id, assignments in result.assignments_by_locus.items():
print(f"{locus_id}: deletion_status = {classify_deletion(assignments)}")MIT