allelix 2.2.3__tar.gz → 2.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {allelix-2.2.3 → allelix-2.3.1}/PKG-INFO +40 -32
- {allelix-2.2.3 → allelix-2.3.1}/README.md +39 -31
- {allelix-2.2.3 → allelix-2.3.1}/allelix/annotators/gwas.py +43 -9
- {allelix-2.2.3 → allelix-2.3.1}/allelix/annotators/snpedia.py +85 -12
- {allelix-2.2.3 → allelix-2.3.1}/allelix/cli/_helpers.py +82 -19
- {allelix-2.2.3 → allelix-2.3.1}/allelix/cli/_options.py +14 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/cli/analyze.py +4 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/cli/db.py +10 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/databases/snpedia_parser.py +64 -10
- {allelix-2.2.3 → allelix-2.3.1}/allelix/reports/_pipeline.py +95 -16
- {allelix-2.2.3 → allelix-2.3.1}/allelix/reports/html.py +2 -1
- allelix-2.3.1/allelix/reports/vcf.py +628 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/utils/build_detect.py +15 -8
- {allelix-2.2.3 → allelix-2.3.1}/allelix.egg-info/PKG-INFO +40 -32
- {allelix-2.2.3 → allelix-2.3.1}/allelix.egg-info/SOURCES.txt +2 -0
- {allelix-2.2.3 → allelix-2.3.1}/pyproject.toml +1 -1
- {allelix-2.2.3 → allelix-2.3.1}/tests/test_cli.py +143 -3
- allelix-2.3.1/tests/test_cli_vcf_out.py +363 -0
- {allelix-2.2.3 → allelix-2.3.1}/LICENSE +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/__init__.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/annotators/__init__.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/annotators/alphamissense.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/annotators/base.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/annotators/cadd.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/annotators/clinvar.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/annotators/gnomad.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/annotators/pharmgkb.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/cli/__init__.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/cli/config.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/cli/focused.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/cli/utility.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/compare.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/config.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/data/__init__.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/data/clinvar_clnsig_snapshot.yaml +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/data/high_value_snps.yaml +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/databases/__init__.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/databases/_versions.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/databases/alphamissense_loader.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/databases/cadd_loader.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/databases/cpic_loader.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/databases/gnomad_loader.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/databases/gwas_loader.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/databases/loader_utils.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/databases/manager.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/databases/pharmgkb_loader.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/databases/schema.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/databases/snpedia_loader.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/exporters/__init__.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/exporters/plink.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/models.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/parsers/__init__.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/parsers/_helpers.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/parsers/ancestrydna.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/parsers/base.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/parsers/ftdna.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/parsers/ftdna_famfinder.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/parsers/ftdna_illumina.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/parsers/livingdna.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/parsers/myhappygenes.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/parsers/myheritage.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/parsers/twentythreeandme.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/parsers/vcf.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/py.typed +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/reports/__init__.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/reports/diff.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/reports/high_value.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/reports/json_report.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/reports/methylation.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/reports/terminal.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/utils/__init__.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix/utils/allele.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix.egg-info/dependency_links.txt +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix.egg-info/entry_points.txt +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix.egg-info/requires.txt +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/allelix.egg-info/top_level.txt +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/setup.cfg +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/tests/test_changelog_sanitize.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/tests/test_cli_helpers.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/tests/test_compare.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/tests/test_config.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/tests/test_end_to_end.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/tests/test_extract_rsidless_gh128.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/tests/test_mock_data_invariants.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/tests/test_models.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/tests/test_original_rsid_never_serializes.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/tests/test_registry.py +0 -0
- {allelix-2.2.3 → allelix-2.3.1}/tests/test_version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: allelix
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.1
|
|
4
4
|
Summary: Open-source genotype analysis toolkit. Format-agnostic ingestion, database-agnostic annotation, offline-first.
|
|
5
5
|
Author: Allelix
|
|
6
6
|
Maintainer-email: dial481 <dial481@users.noreply.github.com>
|
|
@@ -43,7 +43,7 @@ Dynamic: license-file
|
|
|
43
43
|
|
|
44
44
|
**Open-source genotype analysis. Format-agnostic. Offline-first.**
|
|
45
45
|
|
|
46
|
-
[Website](https://allelix.io) · [Quickstart](#quickstart) · [Changelog](https://github.com/allelix/allelix/blob/main/CHANGELOG.md)
|
|
46
|
+
[Website](https://allelix.io) · [Demo](https://analyze.allelix.io) · [Quickstart](#quickstart) · [Changelog](https://github.com/allelix/allelix/blob/main/CHANGELOG.md)
|
|
47
47
|
|
|
48
48
|
[](https://www.python.org/downloads/)
|
|
49
49
|
[](https://pypi.org/project/allelix/)
|
|
@@ -55,7 +55,7 @@ Dynamic: license-file
|
|
|
55
55
|
|
|
56
56
|
# Allelix
|
|
57
57
|
|
|
58
|
-
> **Status:** Production.
|
|
58
|
+
> **Status:** Production. Nine parser formats (including VCF + gVCF), four annotators (ClinVar + ClinPGx + GWAS Catalog + SNPedia), three GRCh38-only enrichment sources (gnomAD + AlphaMissense + CADD), licensable-source gating for commercial users, dual-build ClinVar caches (GRCh37 + GRCh38), HTML/JSON/terminal reports and annotated VCF output for pipeline integration (v2.3.0+), methylation + pharmacogenomics focused commands, report diffing, persistent config with commercial-mode safety switch. Modern-build position detection requires at least three concordant seed SNPs and an 80% winning ratio before it overrides a fallback or header signal; a tentative GRCh36 signal instead fails closed to GRCh36 because no modern position cache is safe for it (ADR-0025, ADR-0037). No regex on prose anywhere in production. The [Changelog](https://github.com/allelix/allelix/blob/main/CHANGELOG.md) tracks every release.
|
|
59
59
|
|
|
60
60
|
## Quickstart
|
|
61
61
|
|
|
@@ -66,7 +66,8 @@ pip install allelix
|
|
|
66
66
|
|
|
67
67
|
# Download reference databases (~16 GB default install; ~22 GB if you opt into CADD).
|
|
68
68
|
# Use --no-gnomad / --no-alphamissense to skip the large ones.
|
|
69
|
-
# CADD is opt-in: allelix db update --cadd
|
|
69
|
+
# CADD is opt-in: download with `allelix db update --cadd`, then pass
|
|
70
|
+
# `--cadd` to an analysis or set `sources.cadd = true` persistently.
|
|
70
71
|
allelix db update
|
|
71
72
|
|
|
72
73
|
# Analyze a genotype file
|
|
@@ -80,6 +81,12 @@ allelix analyze trio.vcf.gz --sample HG002 --output report.html
|
|
|
80
81
|
|
|
81
82
|
# Filter to a custom panel (rsIDs + gene names, one per line; '#' comments and blank lines ignored)
|
|
82
83
|
allelix analyze your_genotype_file.txt --filter-file my_panel.txt --output report.html
|
|
84
|
+
|
|
85
|
+
# Annotated VCF output — VCF-in / VCF-out for pipeline integration
|
|
86
|
+
# Writes a valid VCF with annotations as INFO fields + full provenance in the header.
|
|
87
|
+
# Missing ##contig declarations are synthesized; raw CHROM names are preserved.
|
|
88
|
+
# Refuses to overwrite; requires VCF or gVCF input.
|
|
89
|
+
allelix analyze your_wgs.vcf.gz --vcf-out annotated.vcf
|
|
83
90
|
```
|
|
84
91
|
|
|
85
92
|
See [Development](#development) for source installs and running tests, [Managing your data](#managing-your-data) for cache locations and cleanup, and [Troubleshooting](#troubleshooting) for common failure states.
|
|
@@ -105,10 +112,9 @@ Adding a new format means adding one file to `allelix/parsers/` and registering
|
|
|
105
112
|
| Release | Theme |
|
|
106
113
|
|---|---|
|
|
107
114
|
| **v2.2** | Annotation model expansion (cross-source conflict surfacing, risk-allele display, structured MTAG flag), custom-panel UX improvements, methylation panel retune + citations, ClinVar source switch (VCF → `variant_summary.txt`), CLI cleanups (`db clean` / `db path`). |
|
|
108
|
-
| **v2.3** |
|
|
109
|
-
| **v2.4** |
|
|
110
|
-
| **
|
|
111
|
-
| **v3.0** | Ancestry estimation (PCA + 1KG/HGDP reference panels), Polygenic Risk Score (PRS) integration. |
|
|
115
|
+
| **v2.3** | Annotated VCF output plus v2.3.1 correctness hardening: cross-build enrichment guards, GWAS effect-type disambiguation, conservative build confidence, SNPedia orientation handling, and strict slow-suite drift verification. |
|
|
116
|
+
| **v2.4** | Forward-strand normalization for GWAS risk alleles, broader and chromosome-aware build sampling with explicit provenance, test isolation, and deferred cache-loader hardening. |
|
|
117
|
+
| **Later** | Variant consequences, CNVs and repeat expansions, gnomAD genomes, supplemental genotype-file merging, ancestry estimation, and PRS support. These are directional themes rather than release commitments. |
|
|
112
118
|
|
|
113
119
|
Issues and milestones are tracked at [github.com/allelix/allelix/issues](https://github.com/allelix/allelix/issues). Annotator-level strand-aware carrier matching (R-1) shipped in v2.1.0's ADR-0035 cluster.
|
|
114
120
|
|
|
@@ -119,34 +125,30 @@ Issues and milestones are tracked at [github.com/allelix/allelix/issues](https:/
|
|
|
119
125
|
| ClinVar (GRCh37 + GRCh38) | ✓ | Public domain (NCBI). SNVs + indels + multi-allelic sites. **Both builds cached**; `analyze` dispatches by detected build (ADR-0021). Carrier rule (ADR-0007) requires the user to carry the ALT allele. Indel-anchor protection (ADR-0011) prevents single-base array readouts from matching anchor-base indels. |
|
|
120
126
|
| ClinPGx (formerly PharmGKB) | ✓ | CC BY-SA 4.0. Clinical annotations only — single-rsid SNVs; star alleles and haplotypes deferred (ADR-0009). **Primary non-finding filter is the ClinVar REF carrier rule (ADR-0023):** if ClinVar publishes a single-base REF for the rsid and the user is homozygous for it, the row is suppressed. CPIC's `(rsid, base) → function_class` join (ADR-0020) survives as a secondary tier for rsids ClinVar doesn't catalog. Earlier prose tiers (ADR-0013, ADR-0017, ADR-0018) are superseded. |
|
|
121
127
|
| CPIC (per-allele function table) | ✓ | Internal data source for the ClinPGx filter. Fetched from `api.cpicpgx.org` at `db update` time. Used to populate the `pharmgkb_allele_function` table — not surfaced to end users as its own annotator. |
|
|
122
|
-
| SNPedia | ✓ | CC BY-NC-SA 3.0 US. Pre-built cache downloaded via `db update` (~216K wiki pages, ~105K genotype rows). If the
|
|
123
|
-
| GWAS Catalog | ✓ | Public domain (EBI/NHGRI). Trait–SNP associations with p-values and effect sizes. Carrier rule (ADR-0007) requires the user to carry the risk allele. P-value magnitude scoring
|
|
124
|
-
| gnomAD | ✓ | ODbL v1.0. **
|
|
125
|
-
| AlphaMissense | ✓ | CC BY 4.0. **
|
|
126
|
-
| CADD | ✓ | LicenseRef-CADD (non-commercial). **
|
|
128
|
+
| SNPedia | ✓ | CC BY-NC-SA 3.0 US. Pre-built cache downloaded via `db update` (~216K wiki pages, ~105K genotype rows). The cache carries SNPedia's orientation metadata: minus-strand alleles are complemented before matching, while unknown-orientation palindromic genotypes abstain rather than risk a false match. If the database is absent, analysis runs without it. For commercial use, pass `--exclude-snpedia`. The cache can also be rebuilt from source via `scripts/scrape_snpedia.py` + `scripts/parse_snpedia.py`. |
|
|
129
|
+
| GWAS Catalog | ✓ | Public domain (EBI/NHGRI). Trait–SNP associations with p-values and effect sizes. Carrier rule (ADR-0007) requires the user to carry the risk allele. P-value magnitude scoring maps continuous p-values to the 0–10 scale; only a confidence-interval field that positively identifies a bare odds ratio receives the odds-ratio modifier. Beta coefficients and ambiguous or unit-bearing effects receive no modifier (ADR-0038). Unknown-risk-allele entries fire on rsID match alone but are capped at 3.0. GWAS risk-allele strand normalization remains deferred to v2.4. |
|
|
130
|
+
| gnomAD | ✓ | ODbL v1.0. **GRCh38-only enrichment annotator** — adds population allele frequency context to existing annotations. Shows how common each variant is in the general population (~16M exome variants from 730K individuals). A pathogenic variant that 35% of people carry reads very differently from one seen in 0.001%. Pre-built cache downloaded via `db update` (~6GB on disk). It is deliberately disabled, including for rsID resolution, on GRCh37 and GRCh36 inputs. Use `--no-gnomad` to skip. |
|
|
131
|
+
| AlphaMissense | ✓ | CC BY 4.0. **GRCh38-only enrichment annotator** — adds DeepMind's protein-structure-based pathogenicity predictions to existing annotations. Scores 71M missense variants on a 0–1 scale: <0.34 = likely benign, >0.564 = likely pathogenic. Complements ClinVar's expert classifications with computational predictions — especially valuable for variants ClinVar hasn't reviewed yet. Pre-built cache downloaded via `db update` (~8GB on disk). It is deliberately disabled on GRCh37 and GRCh36 inputs. Use `--no-alphamissense` to skip. |
|
|
132
|
+
| CADD | ✓ | LicenseRef-CADD (non-commercial). **GRCh38-only enrichment annotator** — adds PHRED-scaled deleteriousness scores from CADD v1.7. **Opt-in**, disabled by default and always disabled on GRCh37 and GRCh36 inputs; see [CADD modes](#cadd-modes) below for details. |
|
|
127
133
|
|
|
128
134
|
### CADD modes
|
|
129
135
|
|
|
130
136
|
CADD ranks how deleterious any single-nucleotide variant is using 100+ annotation tracks (coding, non-coding, regulatory). PHRED 10 = top 10% most deleterious, 20 = top 1%, 30 = top 0.1%.
|
|
131
137
|
|
|
132
|
-
**Opt-in**:
|
|
138
|
+
**Opt-in**: download the cache with `allelix db update --cadd`. Then pass `--cadd` to an analysis for a one-run override, or enable it persistently with `allelix config set sources.cadd true`. Downloading the cache alone does not change persistent configuration. Use `--no-cadd` to skip enrichment for a single run when it is enabled in config.
|
|
133
139
|
|
|
134
140
|
Two modes:
|
|
135
141
|
|
|
136
|
-
- **Cache mode** (default): pre-built ~5.8 GB SQLite cache (~120M variant keys). Covers nearly every position allelix can annotate from its other databases (gnomAD, AlphaMissense, ClinVar).
|
|
142
|
+
- **Cache mode** (default): pre-built ~5.8 GB SQLite cache (~120M GRCh38 variant keys). Covers nearly every GRCh38 position allelix can annotate from its other databases (gnomAD, AlphaMissense, ClinVar). It is deliberately disabled for GRCh37 and GRCh36 input, even when an rsID happens to exist in the cache.
|
|
137
143
|
- **Full mode** (`options.cadd_full = true`): tabix queries against the complete CADD v1.7 file via pysam (GRCh38 only). Adds coverage for novel or private variants that appear only in WGS/WES data and are not in any pre-computed database. Requires `pip install allelix[cadd]` for the pysam dependency.
|
|
138
144
|
|
|
139
|
-
If your input is a genotyping chip file, cache mode is all you need.
|
|
145
|
+
If your input is a GRCh38 genotyping chip file, cache mode is normally all you need. CADD enrichment is unavailable for GRCh37 and GRCh36 chip files.
|
|
140
146
|
|
|
141
147
|
### Build coverage asymmetry (GRCh37 vs GRCh38)
|
|
142
148
|
|
|
143
|
-
ClinVar dispatches per
|
|
144
|
-
|
|
145
|
-
Despite that equivalence, the same person's WGS file produces noticeably more annotations as GRCh37 than as GRCh38. The mechanism is in the resolution step, not in upstream-data shape. Position-keyed rsID resolution requires exact `(chromosome, position, ref, alt)` alignment between the user's variant call and ClinVar's stored row. Lift-over between builds does not preserve that alignment perfectly: the `~0.4%` of the genome where the reference assembly was rebuilt has different REF alleles, multi-allelic sites split differently, and some benchmark VCF positions drop out entirely in the GRCh38 lift. Each misalignment loses one resolution, which in turn loses all the rsID-keyed downstream annotations that rsID would have driven (ClinVar's own carrier annotation, plus GWAS Catalog, SNPedia, and ClinPGx).
|
|
146
|
-
|
|
147
|
-
Real GIAB HG002 benchmark, surviving the default `--min-magnitude 5.0` filter: GRCh37 surfaces 520 distinct rsIDs across all sources, GRCh38 surfaces 341. The two sets overlap on 331 rsIDs; 189 are GRCh37-only and 10 are GRCh38-only — pure asymmetric loss in the GRCh38 lift, not different upstream coverage. The unfiltered totals (65,965 vs 4,867) magnify the same pattern at lower magnitudes, mostly via GWAS-Catalog weak-association rows.
|
|
149
|
+
ClinVar dispatches per build and ships with both GRCh37 and GRCh38 caches. gnomAD v4.1 exomes, AlphaMissense, and CADD v1.7 are GRCh38 datasets in Allelix's current data model. Their enrichment and provenance are therefore emitted only for GRCh38 analyses; GRCh37 and GRCh36 analyses intentionally receive none of those values. This guard prevents an rsID or coordinate collision from attaching a valid GRCh38 score to the wrong allele on another assembly.
|
|
148
150
|
|
|
149
|
-
|
|
151
|
+
The same rule applies to position-based rsID recovery: ClinVar can resolve against the selected GRCh37 or GRCh38 cache, while the broader gnomAD resolver participates only on GRCh38. GRCh37 files with rsIDs still use ClinPGx, GWAS Catalog, and SNPedia normally, but an rsID-less GRCh37 VCF has narrower recovery coverage. If you convert between assemblies, re-normalize REF/ALT as part of the conversion and pass `--build` explicitly when the file does not carry a trustworthy build signal.
|
|
150
152
|
|
|
151
153
|
### Known ClinPGx limitation: reference-genotype rows where ClinVar and CPIC both lack data
|
|
152
154
|
|
|
@@ -165,7 +167,7 @@ Two ClinVar rows in real-world reports are known upstream artifacts, not Allelix
|
|
|
165
167
|
|
|
166
168
|
- **PKD1 rs199476100 GG (Pathogenic/Likely pathogenic, magnitude 8.5).** This is a stop-gained variant with a gnomAD frequency of 0.0005% (7 observations in 1.38 million chromosomes). Homozygosity for this variant is biologically implausible — PKD1 is autosomal dominant and the nonsense variant would be embryonic-lethal or devastating in homozygous state. The chip genotyping call is almost certainly a probe artifact. The code correctly reports what ClinVar says and what the chip reads; the error is upstream of Allelix. Future work: population-frequency filtering could flag ultra-rare variants where the chip call is likely unreliable.
|
|
167
169
|
|
|
168
|
-
- **IL10 rs1800896 CT (Pathogenic, magnitude 9.0).** This is a common polymorphism (MAF ~20–40%) in the IL-10 promoter. ClinVar's Pathogenic classification comes from a single submitter for hepatitis C susceptibility;
|
|
170
|
+
- **IL10 rs1800896 CT (Pathogenic, magnitude 9.0).** This is a common polymorphism (MAF ~20–40%) in the IL-10 promoter. ClinVar's Pathogenic classification comes from a single submitter for hepatitis C susceptibility; another submission classifies the allele as "Uncertain risk allele" for leprosy susceptibility. Allelix's per-SCV loader keeps each submitter's significance paired with its own condition, so it does not create cross-submission combinations. The remaining concern is the upstream strength of a single-submitter classification on a common variant. Future work: review-status weighting could down-weight that evidence.
|
|
169
171
|
|
|
170
172
|
Neither issue affects Allelix's filter logic. Both are inherent to ClinVar's aggregation model and the limitations of array-based genotyping chips.
|
|
171
173
|
|
|
@@ -230,7 +232,7 @@ Not all databases are equal in size. `allelix db update` downloads them all by d
|
|
|
230
232
|
| GWAS Catalog | ~200MB | 1–2 min | Trait-SNP associations from genome-wide studies. |
|
|
231
233
|
| gnomAD | ~6GB | 5–15 min | Population allele frequencies (how common is this variant?). |
|
|
232
234
|
| AlphaMissense | ~8GB | 5–15 min | Missense pathogenicity predictions (how likely to break protein function?). |
|
|
233
|
-
| CADD (opt-in) | ~5GB | 5–15 min | Variant deleteriousness scores (how damaging is this variant?).
|
|
235
|
+
| CADD (opt-in) | ~5GB | 5–15 min | Variant deleteriousness scores (how damaging is this variant?). Download with `db update --cadd`; enable per analysis or in config. |
|
|
234
236
|
|
|
235
237
|
gnomAD and AlphaMissense are the largest but add the most interpretive context. gnomAD answers "is this variant rare or common?" — a pathogenic variant carried by 35% of the population reads very differently from one seen in 3 people. AlphaMissense answers "does this missense change likely damage the protein?" — especially valuable for the thousands of variants ClinVar hasn't reviewed yet.
|
|
236
238
|
|
|
@@ -284,14 +286,15 @@ du -sh "$ALLELIX_DATA"
|
|
|
284
286
|
allelix db path --check
|
|
285
287
|
```
|
|
286
288
|
|
|
287
|
-
**The one thing worth backing up: `config.toml`.** It lives
|
|
289
|
+
**The one thing worth backing up: `config.toml`.** It lives inside the resolved data directory (typically `~/.local/share/allelix/config.toml`) and stores your license assertions (commercial-mode toggle, CADD opt-in confirmation) and per-source enable/disable settings. It's the only non-reproducible state in the install. The caches will rebuild on the next `db update`; `config.toml` won't. `allelix db clean` always preserves it.
|
|
288
290
|
|
|
289
291
|
To fully uninstall allelix and reclaim everything:
|
|
290
292
|
|
|
291
293
|
```bash
|
|
294
|
+
ALLELIX_DATA=$(allelix db path)
|
|
295
|
+
allelix db clean --yes # reference database caches
|
|
296
|
+
rm -f "$ALLELIX_DATA/config.toml" # license + source-toggle config
|
|
292
297
|
pip uninstall allelix
|
|
293
|
-
allelix db clean --yes # reference database caches
|
|
294
|
-
rm -rf ~/.config/allelix/ # license + source-toggle config
|
|
295
298
|
```
|
|
296
299
|
|
|
297
300
|
## Data Sources & Licensing
|
|
@@ -305,9 +308,9 @@ Allelix source code is licensed under the **GNU Affero General Public License v3
|
|
|
305
308
|
| ClinPGx (formerly PharmGKB) | clinpgx.org | CC BY-SA 4.0 | Attribution required |
|
|
306
309
|
| CPIC | cpicpgx.org | CC BY-SA 4.0 | Attribution required. Per-allele function data fetched from `api.cpicpgx.org` at `db update` time; used internally for the ClinPGx non-finding filter (ADR-0020), not surfaced as its own annotator. |
|
|
307
310
|
| SNPedia | snpedia.com | CC BY-NC-SA 3.0 US | Attribution required, **non-commercial only**. Use `--exclude-snpedia` to omit. |
|
|
308
|
-
| gnomAD | gnomad.broadinstitute.org | ODbL v1.0 | Attribution required.
|
|
309
|
-
| AlphaMissense | zenodo.org/records/10813168 | CC BY 4.0 | Attribution required. Cheng et al., Science 2023.
|
|
310
|
-
| CADD | cadd.gs.washington.edu | LicenseRef-CADD | Attribution required, **non-commercial by default**. Commercial licenses available from UW CoMotion.
|
|
311
|
+
| gnomAD | gnomad.broadinstitute.org | ODbL v1.0 | Attribution required. GRCh38-only population allele frequencies for context; not a clinical annotator. Use `--no-gnomad` to omit. |
|
|
312
|
+
| AlphaMissense | zenodo.org/records/10813168 | CC BY 4.0 | Attribution required. Cheng et al., Science 2023. GRCh38-only missense variant pathogenicity predictions. Use `--no-alphamissense` to omit. |
|
|
313
|
+
| CADD | cadd.gs.washington.edu | LicenseRef-CADD | Attribution required, **non-commercial by default**. Commercial licenses available from UW CoMotion. GRCh38-only enrichment; download with `allelix db update --cadd`, then enable per analysis with `--cadd` or persistently in config. Use `--no-cadd` to omit. |
|
|
311
314
|
|
|
312
315
|
**Commercial users:** When `license.commercial = true`, non-commercial sources are gated by a three-state permission model. SNPedia is permanently blocked (no commercial license is available). CADD is blocked by default but can be unlocked — the University of Washington offers commercial licenses at `https://els2.comotion.uw.edu/product/cadd-scores`; after purchasing, assert your license with `allelix config set license.cadd true` to re-enable CADD in commercial mode. All other databases (ClinVar, ClinPGx, GWAS Catalog, gnomAD, AlphaMissense) are compatible with commercial use. `allelix config show` displays the permission state for each source.
|
|
313
316
|
|
|
@@ -336,6 +339,8 @@ Of the 104,806 genotype pages in the archive:
|
|
|
336
339
|
|
|
337
340
|
None of these are scraping errors. They are editorial inconsistencies on the source wiki. The annotator handles all of them correctly: incomplete entries are skipped, variant title formats are matched, and no false annotations are produced.
|
|
338
341
|
|
|
342
|
+
The v2.3.1 cache format also preserves each page's SNPedia orientation. Known minus-strand rows are complemented to forward orientation before genotype matching. For palindromic A/T or C/G genotypes whose orientation is unknown, Allelix abstains because the source data cannot distinguish the strands safely. Re-run `allelix db update` after upgrading so a pre-v2.3.1 SNPedia cache is rebuilt.
|
|
343
|
+
|
|
339
344
|
## Troubleshooting
|
|
340
345
|
|
|
341
346
|
### `ImportError: cannot import name 'UTC' from 'datetime'`
|
|
@@ -344,7 +349,7 @@ You're on Python 3.10 or older. Allelix requires 3.11+. `python --version` to ch
|
|
|
344
349
|
|
|
345
350
|
### `allelix db update` failed partway through
|
|
346
351
|
|
|
347
|
-
Run it again. The update is idempotent — completed downloads are skipped (signal-matched against the upstream freshness probe), so re-running picks up where it left off. If a specific source keeps failing,
|
|
352
|
+
Run it again. The update is idempotent — completed downloads are skipped (signal-matched against the upstream freshness probe), so re-running picks up where it left off. If a specific optional source keeps failing, use its `--no-*` flag to finish the other sources, then remove the skip flag and re-run the full update later. `--only clinvar` exists for the ClinVar-only CI and recovery path; other sources do not currently have standalone `--only` selectors.
|
|
348
353
|
|
|
349
354
|
If the failure is a network timeout on the same source repeatedly, the issue is likely on the source's end (HuggingFace / NCBI / EBI / etc. transient outage). Wait an hour and retry.
|
|
350
355
|
|
|
@@ -354,7 +359,7 @@ Almost always a schema or interpreter version bump in a recent allelix release t
|
|
|
354
359
|
|
|
355
360
|
### Build mismatch warning when analyzing a known-good file
|
|
356
361
|
|
|
357
|
-
Either: (a) the file's header claims one build and the position data
|
|
362
|
+
Either: (a) the file's header claims one build and the position data confidently indicates another (real-world MHG / Tempus exports do this — header says 37, positions are 38), or (b) the position signal is too small or mixed to be authoritative. Allelix requires at least three concordant seed SNPs and an 80% winning ratio; weaker GRCh37/38 evidence is reported as tentative and the header or fallback remains effective. A tentative GRCh36 winner is the safety exception: Allelix uses GRCh36 so it cannot accidentally query a modern position cache. Modern position-keyed caches are unavailable for that build (see [`docs/grch36-liftover.md`](https://github.com/allelix/allelix/blob/main/docs/grch36-liftover.md)).
|
|
358
363
|
|
|
359
364
|
If you trust the file's header more than allelix's detection, force the build: `--build grch37` or `--build grch38`. The build banner in the analyze output will reflect what was actually used.
|
|
360
365
|
|
|
@@ -383,6 +388,9 @@ Notable load-bearing ADRs:
|
|
|
383
388
|
- **ADR-0007 — Genotype matching requires the user to carry the ALT allele.** Applies to ClinVar.
|
|
384
389
|
- **ADR-0009 — ClinPGx matches the user's exact normalized diploid call.**
|
|
385
390
|
- **ADR-0015 — Mock data generators are the contract.** Fixture shape must mirror real data shape; invariants tested.
|
|
391
|
+
- **ADR-0036 — Annotated VCF output contract.** JSON and annotated VCF schemas evolve independently.
|
|
392
|
+
- **ADR-0037 — Conservative position-based build confidence.** A winning build needs at least three matches and an 80% ratio; weaker signals remain diagnostic only.
|
|
393
|
+
- **ADR-0038 — GWAS effect-modifier disambiguation.** Only positively identified odds ratios receive an effect-size modifier; beta and ambiguous effects abstain.
|
|
386
394
|
|
|
387
395
|
Release history: see [`CHANGELOG.md`](https://github.com/allelix/allelix/blob/main/CHANGELOG.md).
|
|
388
396
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
**Open-source genotype analysis. Format-agnostic. Offline-first.**
|
|
6
6
|
|
|
7
|
-
[Website](https://allelix.io) · [Quickstart](#quickstart) · [Changelog](https://github.com/allelix/allelix/blob/main/CHANGELOG.md)
|
|
7
|
+
[Website](https://allelix.io) · [Demo](https://analyze.allelix.io) · [Quickstart](#quickstart) · [Changelog](https://github.com/allelix/allelix/blob/main/CHANGELOG.md)
|
|
8
8
|
|
|
9
9
|
[](https://www.python.org/downloads/)
|
|
10
10
|
[](https://pypi.org/project/allelix/)
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
# Allelix
|
|
18
18
|
|
|
19
|
-
> **Status:** Production.
|
|
19
|
+
> **Status:** Production. Nine parser formats (including VCF + gVCF), four annotators (ClinVar + ClinPGx + GWAS Catalog + SNPedia), three GRCh38-only enrichment sources (gnomAD + AlphaMissense + CADD), licensable-source gating for commercial users, dual-build ClinVar caches (GRCh37 + GRCh38), HTML/JSON/terminal reports and annotated VCF output for pipeline integration (v2.3.0+), methylation + pharmacogenomics focused commands, report diffing, persistent config with commercial-mode safety switch. Modern-build position detection requires at least three concordant seed SNPs and an 80% winning ratio before it overrides a fallback or header signal; a tentative GRCh36 signal instead fails closed to GRCh36 because no modern position cache is safe for it (ADR-0025, ADR-0037). No regex on prose anywhere in production. The [Changelog](https://github.com/allelix/allelix/blob/main/CHANGELOG.md) tracks every release.
|
|
20
20
|
|
|
21
21
|
## Quickstart
|
|
22
22
|
|
|
@@ -27,7 +27,8 @@ pip install allelix
|
|
|
27
27
|
|
|
28
28
|
# Download reference databases (~16 GB default install; ~22 GB if you opt into CADD).
|
|
29
29
|
# Use --no-gnomad / --no-alphamissense to skip the large ones.
|
|
30
|
-
# CADD is opt-in: allelix db update --cadd
|
|
30
|
+
# CADD is opt-in: download with `allelix db update --cadd`, then pass
|
|
31
|
+
# `--cadd` to an analysis or set `sources.cadd = true` persistently.
|
|
31
32
|
allelix db update
|
|
32
33
|
|
|
33
34
|
# Analyze a genotype file
|
|
@@ -41,6 +42,12 @@ allelix analyze trio.vcf.gz --sample HG002 --output report.html
|
|
|
41
42
|
|
|
42
43
|
# Filter to a custom panel (rsIDs + gene names, one per line; '#' comments and blank lines ignored)
|
|
43
44
|
allelix analyze your_genotype_file.txt --filter-file my_panel.txt --output report.html
|
|
45
|
+
|
|
46
|
+
# Annotated VCF output — VCF-in / VCF-out for pipeline integration
|
|
47
|
+
# Writes a valid VCF with annotations as INFO fields + full provenance in the header.
|
|
48
|
+
# Missing ##contig declarations are synthesized; raw CHROM names are preserved.
|
|
49
|
+
# Refuses to overwrite; requires VCF or gVCF input.
|
|
50
|
+
allelix analyze your_wgs.vcf.gz --vcf-out annotated.vcf
|
|
44
51
|
```
|
|
45
52
|
|
|
46
53
|
See [Development](#development) for source installs and running tests, [Managing your data](#managing-your-data) for cache locations and cleanup, and [Troubleshooting](#troubleshooting) for common failure states.
|
|
@@ -66,10 +73,9 @@ Adding a new format means adding one file to `allelix/parsers/` and registering
|
|
|
66
73
|
| Release | Theme |
|
|
67
74
|
|---|---|
|
|
68
75
|
| **v2.2** | Annotation model expansion (cross-source conflict surfacing, risk-allele display, structured MTAG flag), custom-panel UX improvements, methylation panel retune + citations, ClinVar source switch (VCF → `variant_summary.txt`), CLI cleanups (`db clean` / `db path`). |
|
|
69
|
-
| **v2.3** |
|
|
70
|
-
| **v2.4** |
|
|
71
|
-
| **
|
|
72
|
-
| **v3.0** | Ancestry estimation (PCA + 1KG/HGDP reference panels), Polygenic Risk Score (PRS) integration. |
|
|
76
|
+
| **v2.3** | Annotated VCF output plus v2.3.1 correctness hardening: cross-build enrichment guards, GWAS effect-type disambiguation, conservative build confidence, SNPedia orientation handling, and strict slow-suite drift verification. |
|
|
77
|
+
| **v2.4** | Forward-strand normalization for GWAS risk alleles, broader and chromosome-aware build sampling with explicit provenance, test isolation, and deferred cache-loader hardening. |
|
|
78
|
+
| **Later** | Variant consequences, CNVs and repeat expansions, gnomAD genomes, supplemental genotype-file merging, ancestry estimation, and PRS support. These are directional themes rather than release commitments. |
|
|
73
79
|
|
|
74
80
|
Issues and milestones are tracked at [github.com/allelix/allelix/issues](https://github.com/allelix/allelix/issues). Annotator-level strand-aware carrier matching (R-1) shipped in v2.1.0's ADR-0035 cluster.
|
|
75
81
|
|
|
@@ -80,34 +86,30 @@ Issues and milestones are tracked at [github.com/allelix/allelix/issues](https:/
|
|
|
80
86
|
| ClinVar (GRCh37 + GRCh38) | ✓ | Public domain (NCBI). SNVs + indels + multi-allelic sites. **Both builds cached**; `analyze` dispatches by detected build (ADR-0021). Carrier rule (ADR-0007) requires the user to carry the ALT allele. Indel-anchor protection (ADR-0011) prevents single-base array readouts from matching anchor-base indels. |
|
|
81
87
|
| ClinPGx (formerly PharmGKB) | ✓ | CC BY-SA 4.0. Clinical annotations only — single-rsid SNVs; star alleles and haplotypes deferred (ADR-0009). **Primary non-finding filter is the ClinVar REF carrier rule (ADR-0023):** if ClinVar publishes a single-base REF for the rsid and the user is homozygous for it, the row is suppressed. CPIC's `(rsid, base) → function_class` join (ADR-0020) survives as a secondary tier for rsids ClinVar doesn't catalog. Earlier prose tiers (ADR-0013, ADR-0017, ADR-0018) are superseded. |
|
|
82
88
|
| CPIC (per-allele function table) | ✓ | Internal data source for the ClinPGx filter. Fetched from `api.cpicpgx.org` at `db update` time. Used to populate the `pharmgkb_allele_function` table — not surfaced to end users as its own annotator. |
|
|
83
|
-
| SNPedia | ✓ | CC BY-NC-SA 3.0 US. Pre-built cache downloaded via `db update` (~216K wiki pages, ~105K genotype rows). If the
|
|
84
|
-
| GWAS Catalog | ✓ | Public domain (EBI/NHGRI). Trait–SNP associations with p-values and effect sizes. Carrier rule (ADR-0007) requires the user to carry the risk allele. P-value magnitude scoring
|
|
85
|
-
| gnomAD | ✓ | ODbL v1.0. **
|
|
86
|
-
| AlphaMissense | ✓ | CC BY 4.0. **
|
|
87
|
-
| CADD | ✓ | LicenseRef-CADD (non-commercial). **
|
|
89
|
+
| SNPedia | ✓ | CC BY-NC-SA 3.0 US. Pre-built cache downloaded via `db update` (~216K wiki pages, ~105K genotype rows). The cache carries SNPedia's orientation metadata: minus-strand alleles are complemented before matching, while unknown-orientation palindromic genotypes abstain rather than risk a false match. If the database is absent, analysis runs without it. For commercial use, pass `--exclude-snpedia`. The cache can also be rebuilt from source via `scripts/scrape_snpedia.py` + `scripts/parse_snpedia.py`. |
|
|
90
|
+
| GWAS Catalog | ✓ | Public domain (EBI/NHGRI). Trait–SNP associations with p-values and effect sizes. Carrier rule (ADR-0007) requires the user to carry the risk allele. P-value magnitude scoring maps continuous p-values to the 0–10 scale; only a confidence-interval field that positively identifies a bare odds ratio receives the odds-ratio modifier. Beta coefficients and ambiguous or unit-bearing effects receive no modifier (ADR-0038). Unknown-risk-allele entries fire on rsID match alone but are capped at 3.0. GWAS risk-allele strand normalization remains deferred to v2.4. |
|
|
91
|
+
| gnomAD | ✓ | ODbL v1.0. **GRCh38-only enrichment annotator** — adds population allele frequency context to existing annotations. Shows how common each variant is in the general population (~16M exome variants from 730K individuals). A pathogenic variant that 35% of people carry reads very differently from one seen in 0.001%. Pre-built cache downloaded via `db update` (~6GB on disk). It is deliberately disabled, including for rsID resolution, on GRCh37 and GRCh36 inputs. Use `--no-gnomad` to skip. |
|
|
92
|
+
| AlphaMissense | ✓ | CC BY 4.0. **GRCh38-only enrichment annotator** — adds DeepMind's protein-structure-based pathogenicity predictions to existing annotations. Scores 71M missense variants on a 0–1 scale: <0.34 = likely benign, >0.564 = likely pathogenic. Complements ClinVar's expert classifications with computational predictions — especially valuable for variants ClinVar hasn't reviewed yet. Pre-built cache downloaded via `db update` (~8GB on disk). It is deliberately disabled on GRCh37 and GRCh36 inputs. Use `--no-alphamissense` to skip. |
|
|
93
|
+
| CADD | ✓ | LicenseRef-CADD (non-commercial). **GRCh38-only enrichment annotator** — adds PHRED-scaled deleteriousness scores from CADD v1.7. **Opt-in**, disabled by default and always disabled on GRCh37 and GRCh36 inputs; see [CADD modes](#cadd-modes) below for details. |
|
|
88
94
|
|
|
89
95
|
### CADD modes
|
|
90
96
|
|
|
91
97
|
CADD ranks how deleterious any single-nucleotide variant is using 100+ annotation tracks (coding, non-coding, regulatory). PHRED 10 = top 10% most deleterious, 20 = top 1%, 30 = top 0.1%.
|
|
92
98
|
|
|
93
|
-
**Opt-in**:
|
|
99
|
+
**Opt-in**: download the cache with `allelix db update --cadd`. Then pass `--cadd` to an analysis for a one-run override, or enable it persistently with `allelix config set sources.cadd true`. Downloading the cache alone does not change persistent configuration. Use `--no-cadd` to skip enrichment for a single run when it is enabled in config.
|
|
94
100
|
|
|
95
101
|
Two modes:
|
|
96
102
|
|
|
97
|
-
- **Cache mode** (default): pre-built ~5.8 GB SQLite cache (~120M variant keys). Covers nearly every position allelix can annotate from its other databases (gnomAD, AlphaMissense, ClinVar).
|
|
103
|
+
- **Cache mode** (default): pre-built ~5.8 GB SQLite cache (~120M GRCh38 variant keys). Covers nearly every GRCh38 position allelix can annotate from its other databases (gnomAD, AlphaMissense, ClinVar). It is deliberately disabled for GRCh37 and GRCh36 input, even when an rsID happens to exist in the cache.
|
|
98
104
|
- **Full mode** (`options.cadd_full = true`): tabix queries against the complete CADD v1.7 file via pysam (GRCh38 only). Adds coverage for novel or private variants that appear only in WGS/WES data and are not in any pre-computed database. Requires `pip install allelix[cadd]` for the pysam dependency.
|
|
99
105
|
|
|
100
|
-
If your input is a genotyping chip file, cache mode is all you need.
|
|
106
|
+
If your input is a GRCh38 genotyping chip file, cache mode is normally all you need. CADD enrichment is unavailable for GRCh37 and GRCh36 chip files.
|
|
101
107
|
|
|
102
108
|
### Build coverage asymmetry (GRCh37 vs GRCh38)
|
|
103
109
|
|
|
104
|
-
ClinVar dispatches per
|
|
105
|
-
|
|
106
|
-
Despite that equivalence, the same person's WGS file produces noticeably more annotations as GRCh37 than as GRCh38. The mechanism is in the resolution step, not in upstream-data shape. Position-keyed rsID resolution requires exact `(chromosome, position, ref, alt)` alignment between the user's variant call and ClinVar's stored row. Lift-over between builds does not preserve that alignment perfectly: the `~0.4%` of the genome where the reference assembly was rebuilt has different REF alleles, multi-allelic sites split differently, and some benchmark VCF positions drop out entirely in the GRCh38 lift. Each misalignment loses one resolution, which in turn loses all the rsID-keyed downstream annotations that rsID would have driven (ClinVar's own carrier annotation, plus GWAS Catalog, SNPedia, and ClinPGx).
|
|
107
|
-
|
|
108
|
-
Real GIAB HG002 benchmark, surviving the default `--min-magnitude 5.0` filter: GRCh37 surfaces 520 distinct rsIDs across all sources, GRCh38 surfaces 341. The two sets overlap on 331 rsIDs; 189 are GRCh37-only and 10 are GRCh38-only — pure asymmetric loss in the GRCh38 lift, not different upstream coverage. The unfiltered totals (65,965 vs 4,867) magnify the same pattern at lower magnitudes, mostly via GWAS-Catalog weak-association rows.
|
|
110
|
+
ClinVar dispatches per build and ships with both GRCh37 and GRCh38 caches. gnomAD v4.1 exomes, AlphaMissense, and CADD v1.7 are GRCh38 datasets in Allelix's current data model. Their enrichment and provenance are therefore emitted only for GRCh38 analyses; GRCh37 and GRCh36 analyses intentionally receive none of those values. This guard prevents an rsID or coordinate collision from attaching a valid GRCh38 score to the wrong allele on another assembly.
|
|
109
111
|
|
|
110
|
-
|
|
112
|
+
The same rule applies to position-based rsID recovery: ClinVar can resolve against the selected GRCh37 or GRCh38 cache, while the broader gnomAD resolver participates only on GRCh38. GRCh37 files with rsIDs still use ClinPGx, GWAS Catalog, and SNPedia normally, but an rsID-less GRCh37 VCF has narrower recovery coverage. If you convert between assemblies, re-normalize REF/ALT as part of the conversion and pass `--build` explicitly when the file does not carry a trustworthy build signal.
|
|
111
113
|
|
|
112
114
|
### Known ClinPGx limitation: reference-genotype rows where ClinVar and CPIC both lack data
|
|
113
115
|
|
|
@@ -126,7 +128,7 @@ Two ClinVar rows in real-world reports are known upstream artifacts, not Allelix
|
|
|
126
128
|
|
|
127
129
|
- **PKD1 rs199476100 GG (Pathogenic/Likely pathogenic, magnitude 8.5).** This is a stop-gained variant with a gnomAD frequency of 0.0005% (7 observations in 1.38 million chromosomes). Homozygosity for this variant is biologically implausible — PKD1 is autosomal dominant and the nonsense variant would be embryonic-lethal or devastating in homozygous state. The chip genotyping call is almost certainly a probe artifact. The code correctly reports what ClinVar says and what the chip reads; the error is upstream of Allelix. Future work: population-frequency filtering could flag ultra-rare variants where the chip call is likely unreliable.
|
|
128
130
|
|
|
129
|
-
- **IL10 rs1800896 CT (Pathogenic, magnitude 9.0).** This is a common polymorphism (MAF ~20–40%) in the IL-10 promoter. ClinVar's Pathogenic classification comes from a single submitter for hepatitis C susceptibility;
|
|
131
|
+
- **IL10 rs1800896 CT (Pathogenic, magnitude 9.0).** This is a common polymorphism (MAF ~20–40%) in the IL-10 promoter. ClinVar's Pathogenic classification comes from a single submitter for hepatitis C susceptibility; another submission classifies the allele as "Uncertain risk allele" for leprosy susceptibility. Allelix's per-SCV loader keeps each submitter's significance paired with its own condition, so it does not create cross-submission combinations. The remaining concern is the upstream strength of a single-submitter classification on a common variant. Future work: review-status weighting could down-weight that evidence.
|
|
130
132
|
|
|
131
133
|
Neither issue affects Allelix's filter logic. Both are inherent to ClinVar's aggregation model and the limitations of array-based genotyping chips.
|
|
132
134
|
|
|
@@ -191,7 +193,7 @@ Not all databases are equal in size. `allelix db update` downloads them all by d
|
|
|
191
193
|
| GWAS Catalog | ~200MB | 1–2 min | Trait-SNP associations from genome-wide studies. |
|
|
192
194
|
| gnomAD | ~6GB | 5–15 min | Population allele frequencies (how common is this variant?). |
|
|
193
195
|
| AlphaMissense | ~8GB | 5–15 min | Missense pathogenicity predictions (how likely to break protein function?). |
|
|
194
|
-
| CADD (opt-in) | ~5GB | 5–15 min | Variant deleteriousness scores (how damaging is this variant?).
|
|
196
|
+
| CADD (opt-in) | ~5GB | 5–15 min | Variant deleteriousness scores (how damaging is this variant?). Download with `db update --cadd`; enable per analysis or in config. |
|
|
195
197
|
|
|
196
198
|
gnomAD and AlphaMissense are the largest but add the most interpretive context. gnomAD answers "is this variant rare or common?" — a pathogenic variant carried by 35% of the population reads very differently from one seen in 3 people. AlphaMissense answers "does this missense change likely damage the protein?" — especially valuable for the thousands of variants ClinVar hasn't reviewed yet.
|
|
197
199
|
|
|
@@ -245,14 +247,15 @@ du -sh "$ALLELIX_DATA"
|
|
|
245
247
|
allelix db path --check
|
|
246
248
|
```
|
|
247
249
|
|
|
248
|
-
**The one thing worth backing up: `config.toml`.** It lives
|
|
250
|
+
**The one thing worth backing up: `config.toml`.** It lives inside the resolved data directory (typically `~/.local/share/allelix/config.toml`) and stores your license assertions (commercial-mode toggle, CADD opt-in confirmation) and per-source enable/disable settings. It's the only non-reproducible state in the install. The caches will rebuild on the next `db update`; `config.toml` won't. `allelix db clean` always preserves it.
|
|
249
251
|
|
|
250
252
|
To fully uninstall allelix and reclaim everything:
|
|
251
253
|
|
|
252
254
|
```bash
|
|
255
|
+
ALLELIX_DATA=$(allelix db path)
|
|
256
|
+
allelix db clean --yes # reference database caches
|
|
257
|
+
rm -f "$ALLELIX_DATA/config.toml" # license + source-toggle config
|
|
253
258
|
pip uninstall allelix
|
|
254
|
-
allelix db clean --yes # reference database caches
|
|
255
|
-
rm -rf ~/.config/allelix/ # license + source-toggle config
|
|
256
259
|
```
|
|
257
260
|
|
|
258
261
|
## Data Sources & Licensing
|
|
@@ -266,9 +269,9 @@ Allelix source code is licensed under the **GNU Affero General Public License v3
|
|
|
266
269
|
| ClinPGx (formerly PharmGKB) | clinpgx.org | CC BY-SA 4.0 | Attribution required |
|
|
267
270
|
| CPIC | cpicpgx.org | CC BY-SA 4.0 | Attribution required. Per-allele function data fetched from `api.cpicpgx.org` at `db update` time; used internally for the ClinPGx non-finding filter (ADR-0020), not surfaced as its own annotator. |
|
|
268
271
|
| SNPedia | snpedia.com | CC BY-NC-SA 3.0 US | Attribution required, **non-commercial only**. Use `--exclude-snpedia` to omit. |
|
|
269
|
-
| gnomAD | gnomad.broadinstitute.org | ODbL v1.0 | Attribution required.
|
|
270
|
-
| AlphaMissense | zenodo.org/records/10813168 | CC BY 4.0 | Attribution required. Cheng et al., Science 2023.
|
|
271
|
-
| CADD | cadd.gs.washington.edu | LicenseRef-CADD | Attribution required, **non-commercial by default**. Commercial licenses available from UW CoMotion.
|
|
272
|
+
| gnomAD | gnomad.broadinstitute.org | ODbL v1.0 | Attribution required. GRCh38-only population allele frequencies for context; not a clinical annotator. Use `--no-gnomad` to omit. |
|
|
273
|
+
| AlphaMissense | zenodo.org/records/10813168 | CC BY 4.0 | Attribution required. Cheng et al., Science 2023. GRCh38-only missense variant pathogenicity predictions. Use `--no-alphamissense` to omit. |
|
|
274
|
+
| CADD | cadd.gs.washington.edu | LicenseRef-CADD | Attribution required, **non-commercial by default**. Commercial licenses available from UW CoMotion. GRCh38-only enrichment; download with `allelix db update --cadd`, then enable per analysis with `--cadd` or persistently in config. Use `--no-cadd` to omit. |
|
|
272
275
|
|
|
273
276
|
**Commercial users:** When `license.commercial = true`, non-commercial sources are gated by a three-state permission model. SNPedia is permanently blocked (no commercial license is available). CADD is blocked by default but can be unlocked — the University of Washington offers commercial licenses at `https://els2.comotion.uw.edu/product/cadd-scores`; after purchasing, assert your license with `allelix config set license.cadd true` to re-enable CADD in commercial mode. All other databases (ClinVar, ClinPGx, GWAS Catalog, gnomAD, AlphaMissense) are compatible with commercial use. `allelix config show` displays the permission state for each source.
|
|
274
277
|
|
|
@@ -297,6 +300,8 @@ Of the 104,806 genotype pages in the archive:
|
|
|
297
300
|
|
|
298
301
|
None of these are scraping errors. They are editorial inconsistencies on the source wiki. The annotator handles all of them correctly: incomplete entries are skipped, variant title formats are matched, and no false annotations are produced.
|
|
299
302
|
|
|
303
|
+
The v2.3.1 cache format also preserves each page's SNPedia orientation. Known minus-strand rows are complemented to forward orientation before genotype matching. For palindromic A/T or C/G genotypes whose orientation is unknown, Allelix abstains because the source data cannot distinguish the strands safely. Re-run `allelix db update` after upgrading so a pre-v2.3.1 SNPedia cache is rebuilt.
|
|
304
|
+
|
|
300
305
|
## Troubleshooting
|
|
301
306
|
|
|
302
307
|
### `ImportError: cannot import name 'UTC' from 'datetime'`
|
|
@@ -305,7 +310,7 @@ You're on Python 3.10 or older. Allelix requires 3.11+. `python --version` to ch
|
|
|
305
310
|
|
|
306
311
|
### `allelix db update` failed partway through
|
|
307
312
|
|
|
308
|
-
Run it again. The update is idempotent — completed downloads are skipped (signal-matched against the upstream freshness probe), so re-running picks up where it left off. If a specific source keeps failing,
|
|
313
|
+
Run it again. The update is idempotent — completed downloads are skipped (signal-matched against the upstream freshness probe), so re-running picks up where it left off. If a specific optional source keeps failing, use its `--no-*` flag to finish the other sources, then remove the skip flag and re-run the full update later. `--only clinvar` exists for the ClinVar-only CI and recovery path; other sources do not currently have standalone `--only` selectors.
|
|
309
314
|
|
|
310
315
|
If the failure is a network timeout on the same source repeatedly, the issue is likely on the source's end (HuggingFace / NCBI / EBI / etc. transient outage). Wait an hour and retry.
|
|
311
316
|
|
|
@@ -315,7 +320,7 @@ Almost always a schema or interpreter version bump in a recent allelix release t
|
|
|
315
320
|
|
|
316
321
|
### Build mismatch warning when analyzing a known-good file
|
|
317
322
|
|
|
318
|
-
Either: (a) the file's header claims one build and the position data
|
|
323
|
+
Either: (a) the file's header claims one build and the position data confidently indicates another (real-world MHG / Tempus exports do this — header says 37, positions are 38), or (b) the position signal is too small or mixed to be authoritative. Allelix requires at least three concordant seed SNPs and an 80% winning ratio; weaker GRCh37/38 evidence is reported as tentative and the header or fallback remains effective. A tentative GRCh36 winner is the safety exception: Allelix uses GRCh36 so it cannot accidentally query a modern position cache. Modern position-keyed caches are unavailable for that build (see [`docs/grch36-liftover.md`](https://github.com/allelix/allelix/blob/main/docs/grch36-liftover.md)).
|
|
319
324
|
|
|
320
325
|
If you trust the file's header more than allelix's detection, force the build: `--build grch37` or `--build grch38`. The build banner in the analyze output will reflect what was actually used.
|
|
321
326
|
|
|
@@ -344,6 +349,9 @@ Notable load-bearing ADRs:
|
|
|
344
349
|
- **ADR-0007 — Genotype matching requires the user to carry the ALT allele.** Applies to ClinVar.
|
|
345
350
|
- **ADR-0009 — ClinPGx matches the user's exact normalized diploid call.**
|
|
346
351
|
- **ADR-0015 — Mock data generators are the contract.** Fixture shape must mirror real data shape; invariants tested.
|
|
352
|
+
- **ADR-0036 — Annotated VCF output contract.** JSON and annotated VCF schemas evolve independently.
|
|
353
|
+
- **ADR-0037 — Conservative position-based build confidence.** A winning build needs at least three matches and an 80% ratio; weaker signals remain diagnostic only.
|
|
354
|
+
- **ADR-0038 — GWAS effect-modifier disambiguation.** Only positively identified odds ratios receive an effect-size modifier; beta and ambiguous effects abstain.
|
|
347
355
|
|
|
348
356
|
Release history: see [`CHANGELOG.md`](https://github.com/allelix/allelix/blob/main/CHANGELOG.md).
|
|
349
357
|
|
|
@@ -64,6 +64,10 @@ _BATCH_CHUNK = 500 # SQLite default SQLITE_MAX_VARIABLE_NUMBER is 999
|
|
|
64
64
|
# ``Annotation.trait``; ``description`` is rebuilt below from the structured
|
|
65
65
|
# parts so display surfaces still show the PheCode label.
|
|
66
66
|
_PHECODE_SUFFIX_RE = re.compile(r"\s*\(PheCode\s+([\d.]+)\)\s*$")
|
|
67
|
+
_POSITIVE_CI_NUMBER = r"(?:\d+(?:\.\d*)?|\.\d+)(?:[Ee][+-]?\d+)?"
|
|
68
|
+
_ODDS_RATIO_CI_RE = re.compile(
|
|
69
|
+
rf"^\[\s*{_POSITIVE_CI_NUMBER}\s*(?:-|\u2013)\s*{_POSITIVE_CI_NUMBER}\s*\]$"
|
|
70
|
+
)
|
|
67
71
|
|
|
68
72
|
|
|
69
73
|
def _split_trait_and_phecode(raw_trait: str) -> tuple[str, str]:
|
|
@@ -79,14 +83,36 @@ def _split_trait_and_phecode(raw_trait: str) -> tuple[str, str]:
|
|
|
79
83
|
return raw_trait[: m.start()].rstrip(), m.group(1)
|
|
80
84
|
|
|
81
85
|
|
|
82
|
-
def
|
|
83
|
-
"""
|
|
86
|
+
def _ci_identifies_odds_ratio(ci_text: str | None) -> bool:
|
|
87
|
+
"""True only for GWAS Catalog's bare positive ratio-interval shape.
|
|
88
|
+
|
|
89
|
+
``OR or BETA`` combines two incompatible measures. The adjacent
|
|
90
|
+
``95% CI (TEXT)`` column is the only discriminator the Catalog export
|
|
91
|
+
provides: odds ratios use a bare positive interval such as
|
|
92
|
+
``[0.95-1.05]``; beta rows carry units or direction text such as
|
|
93
|
+
``[0.01-0.03] unit increase``. Missing, descriptive, negative, and
|
|
94
|
+
otherwise ambiguous intervals abstain so beta values never receive
|
|
95
|
+
odds-ratio thresholds.
|
|
96
|
+
"""
|
|
97
|
+
return ci_text is not None and _ODDS_RATIO_CI_RE.fullmatch(ci_text.strip()) is not None
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _magnitude(
|
|
101
|
+
p_value: float | None,
|
|
102
|
+
or_beta: float | None,
|
|
103
|
+
ci_text: str | None = None,
|
|
104
|
+
) -> float:
|
|
105
|
+
"""Derive magnitude from p-value and a confirmed odds ratio.
|
|
84
106
|
|
|
85
107
|
GH #17: boundary comparisons are inclusive (``<=``) so the canonical
|
|
86
108
|
genome-wide-significance threshold ``p = 5e-8`` lands inside the
|
|
87
109
|
significant bucket rather than the suggestive bucket below it.
|
|
88
110
|
Strict ``<`` made the exact threshold value fall a full magnitude
|
|
89
111
|
below a barely-significant hit.
|
|
112
|
+
|
|
113
|
+
``or_beta`` is not interpreted as an odds ratio unless
|
|
114
|
+
``ci_text`` positively identifies the Catalog's ratio-interval shape.
|
|
115
|
+
Beta coefficients are unit-dependent and receive no modifier.
|
|
90
116
|
"""
|
|
91
117
|
if p_value is None:
|
|
92
118
|
base = 2.0
|
|
@@ -103,7 +129,7 @@ def _magnitude(p_value: float | None, or_beta: float | None) -> float:
|
|
|
103
129
|
else:
|
|
104
130
|
base = 2.0
|
|
105
131
|
|
|
106
|
-
if or_beta is not None and or_beta > 0:
|
|
132
|
+
if _ci_identifies_odds_ratio(ci_text) and or_beta is not None and or_beta > 0:
|
|
107
133
|
if or_beta >= 3.0 or or_beta <= 0.33:
|
|
108
134
|
base = min(base + 1.0, 9.0)
|
|
109
135
|
elif or_beta >= 2.0 or or_beta <= 0.5:
|
|
@@ -274,7 +300,7 @@ class GWASCatalogAnnotator(Annotator):
|
|
|
274
300
|
return []
|
|
275
301
|
|
|
276
302
|
sql = (
|
|
277
|
-
"SELECT risk_allele, trait, p_value, or_beta, gene, "
|
|
303
|
+
"SELECT risk_allele, trait, p_value, or_beta, ci_text, gene, "
|
|
278
304
|
"study_accession, pubmed_id, trait_category "
|
|
279
305
|
"FROM gwas_associations WHERE rsid = ?"
|
|
280
306
|
)
|
|
@@ -288,6 +314,7 @@ class GWASCatalogAnnotator(Annotator):
|
|
|
288
314
|
trait,
|
|
289
315
|
p_value,
|
|
290
316
|
or_beta,
|
|
317
|
+
ci_text,
|
|
291
318
|
gene,
|
|
292
319
|
study_accession,
|
|
293
320
|
pubmed_id,
|
|
@@ -300,14 +327,17 @@ class GWASCatalogAnnotator(Annotator):
|
|
|
300
327
|
if risk_allele is not None:
|
|
301
328
|
if variant.allele1 != risk_allele and variant.allele2 != risk_allele:
|
|
302
329
|
continue
|
|
303
|
-
mag = _magnitude(p_value, or_beta)
|
|
330
|
+
mag = _magnitude(p_value, or_beta, ci_text)
|
|
304
331
|
risk_note = ""
|
|
305
332
|
else:
|
|
306
333
|
# ADR-0024: unknown risk allele fires on rsID match alone
|
|
307
334
|
# but capped at 3.0 so it doesn't pass typical --min-magnitude
|
|
308
335
|
# thresholds. Without knowing which allele is the risk allele,
|
|
309
336
|
# we can't apply the carrier rule (ADR-0007).
|
|
310
|
-
mag = min(
|
|
337
|
+
mag = min(
|
|
338
|
+
_magnitude(p_value, or_beta, ci_text),
|
|
339
|
+
_UNKNOWN_RISK_ALLELE_MAG_CAP,
|
|
340
|
+
)
|
|
311
341
|
risk_note = " (risk allele not specified in study)"
|
|
312
342
|
|
|
313
343
|
clean_trait, phecode = _split_trait_and_phecode(trait)
|
|
@@ -370,7 +400,7 @@ class GWASCatalogAnnotator(Annotator):
|
|
|
370
400
|
chunk = rsids[start : start + _BATCH_CHUNK]
|
|
371
401
|
placeholders = ",".join("?" * len(chunk))
|
|
372
402
|
cursor = conn.execute(
|
|
373
|
-
f"SELECT rsid, risk_allele, trait, p_value, or_beta, gene, "
|
|
403
|
+
f"SELECT rsid, risk_allele, trait, p_value, or_beta, ci_text, gene, "
|
|
374
404
|
f"study_accession, pubmed_id, trait_category "
|
|
375
405
|
f"FROM gwas_associations WHERE rsid IN ({placeholders})",
|
|
376
406
|
chunk,
|
|
@@ -389,6 +419,7 @@ class GWASCatalogAnnotator(Annotator):
|
|
|
389
419
|
trait,
|
|
390
420
|
p_value,
|
|
391
421
|
or_beta,
|
|
422
|
+
ci_text,
|
|
392
423
|
gene,
|
|
393
424
|
study_accession,
|
|
394
425
|
pubmed_id,
|
|
@@ -401,10 +432,13 @@ class GWASCatalogAnnotator(Annotator):
|
|
|
401
432
|
if risk_allele is not None:
|
|
402
433
|
if variant.allele1 != risk_allele and variant.allele2 != risk_allele:
|
|
403
434
|
continue
|
|
404
|
-
mag = _magnitude(p_value, or_beta)
|
|
435
|
+
mag = _magnitude(p_value, or_beta, ci_text)
|
|
405
436
|
risk_note = ""
|
|
406
437
|
else:
|
|
407
|
-
mag = min(
|
|
438
|
+
mag = min(
|
|
439
|
+
_magnitude(p_value, or_beta, ci_text),
|
|
440
|
+
_UNKNOWN_RISK_ALLELE_MAG_CAP,
|
|
441
|
+
)
|
|
408
442
|
risk_note = " (risk allele not specified in study)"
|
|
409
443
|
|
|
410
444
|
clean_trait, phecode = _split_trait_and_phecode(trait)
|