allelix 2.1.0__tar.gz → 2.1.2__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.1.0 → allelix-2.1.2}/PKG-INFO +125 -28
- {allelix-2.1.0 → allelix-2.1.2}/README.md +122 -27
- {allelix-2.1.0 → allelix-2.1.2}/allelix/annotators/__init__.py +10 -12
- {allelix-2.1.0 → allelix-2.1.2}/allelix/annotators/base.py +0 -29
- {allelix-2.1.0 → allelix-2.1.2}/allelix/annotators/cadd.py +9 -7
- {allelix-2.1.0 → allelix-2.1.2}/allelix/annotators/clinvar.py +3 -2
- {allelix-2.1.0 → allelix-2.1.2}/allelix/cli/_helpers.py +7 -4
- {allelix-2.1.0 → allelix-2.1.2}/allelix/cli/utility.py +6 -36
- {allelix-2.1.0 → allelix-2.1.2}/allelix/config.py +3 -1
- {allelix-2.1.0 → allelix-2.1.2}/allelix/databases/cpic_loader.py +2 -2
- {allelix-2.1.0 → allelix-2.1.2}/allelix/databases/gwas_loader.py +2 -2
- {allelix-2.1.0 → allelix-2.1.2}/allelix/databases/snpedia_parser.py +6 -4
- {allelix-2.1.0 → allelix-2.1.2}/allelix/exporters/plink.py +50 -1
- {allelix-2.1.0 → allelix-2.1.2}/allelix/models.py +36 -1
- {allelix-2.1.0 → allelix-2.1.2}/allelix/reports/_pipeline.py +10 -5
- {allelix-2.1.0 → allelix-2.1.2}/allelix/reports/diff.py +4 -2
- {allelix-2.1.0 → allelix-2.1.2}/allelix/reports/json_report.py +3 -5
- {allelix-2.1.0 → allelix-2.1.2}/allelix.egg-info/PKG-INFO +125 -28
- {allelix-2.1.0 → allelix-2.1.2}/allelix.egg-info/requires.txt +2 -0
- {allelix-2.1.0 → allelix-2.1.2}/pyproject.toml +37 -2
- {allelix-2.1.0 → allelix-2.1.2}/tests/test_models.py +46 -0
- {allelix-2.1.0 → allelix-2.1.2}/LICENSE +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/__init__.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/annotators/alphamissense.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/annotators/gnomad.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/annotators/gwas.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/annotators/pharmgkb.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/annotators/snpedia.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/cli/__init__.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/cli/_options.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/cli/analyze.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/cli/config.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/cli/db.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/cli/focused.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/compare.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/data/__init__.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/data/clinvar_clnsig_snapshot.yaml +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/data/high_value_snps.yaml +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/databases/__init__.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/databases/_versions.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/databases/alphamissense_loader.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/databases/cadd_loader.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/databases/gnomad_loader.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/databases/loader_utils.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/databases/manager.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/databases/pharmgkb_loader.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/databases/schema.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/databases/snpedia_loader.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/exporters/__init__.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/parsers/__init__.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/parsers/_helpers.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/parsers/ancestrydna.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/parsers/base.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/parsers/ftdna.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/parsers/ftdna_illumina.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/parsers/livingdna.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/parsers/myhappygenes.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/parsers/myheritage.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/parsers/twentythreeandme.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/parsers/vcf.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/py.typed +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/reports/__init__.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/reports/high_value.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/reports/html.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/reports/methylation.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/reports/terminal.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/utils/__init__.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/utils/allele.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix/utils/build_detect.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix.egg-info/SOURCES.txt +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix.egg-info/dependency_links.txt +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix.egg-info/entry_points.txt +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/allelix.egg-info/top_level.txt +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/setup.cfg +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/tests/test_cli.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/tests/test_cli_helpers.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/tests/test_compare.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/tests/test_config.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/tests/test_end_to_end.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/tests/test_mock_data_invariants.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/tests/test_registry.py +0 -0
- {allelix-2.1.0 → allelix-2.1.2}/tests/test_version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: allelix
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.2
|
|
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>
|
|
@@ -29,37 +29,42 @@ Requires-Dist: pysam>=0.22; extra == "cadd"
|
|
|
29
29
|
Provides-Extra: vcf-index
|
|
30
30
|
Requires-Dist: pysam>=0.22; extra == "vcf-index"
|
|
31
31
|
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: mypy>=1.11; extra == "dev"
|
|
32
33
|
Requires-Dist: pre-commit>=3.7; extra == "dev"
|
|
33
34
|
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
34
35
|
Requires-Dist: pytest-cov<8,>=7; extra == "dev"
|
|
35
36
|
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
37
|
+
Requires-Dist: types-PyYAML>=6.0; extra == "dev"
|
|
36
38
|
Dynamic: license-file
|
|
37
39
|
|
|
40
|
+
<div align="center">
|
|
41
|
+
|
|
42
|
+
<img src="https://allelix.io/apple-touch-icon.png" width="180" alt="Allelix" />
|
|
43
|
+
|
|
44
|
+
**Open-source genotype analysis. Format-agnostic. Offline-first.**
|
|
45
|
+
|
|
46
|
+
[Website](https://allelix.io) · [Quickstart](#quickstart) · [Changelog](https://github.com/allelix/allelix/blob/main/CHANGELOG.md)
|
|
47
|
+
|
|
48
|
+
[](https://www.python.org/downloads/)
|
|
49
|
+
[](https://pypi.org/project/allelix/)
|
|
50
|
+
[](LICENSE)
|
|
51
|
+
[](https://github.com/allelix/allelix/actions/workflows/ci.yml)
|
|
52
|
+
[](#privacy)
|
|
53
|
+
|
|
54
|
+
</div>
|
|
55
|
+
|
|
38
56
|
# Allelix
|
|
39
57
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
> **Status:** Production — eight parser formats (including VCF + gVCF),
|
|
43
|
-
> four annotators (ClinVar + ClinPGx + GWAS Catalog + SNPedia), three
|
|
44
|
-
> enrichment sources (gnomAD population frequencies + AlphaMissense
|
|
45
|
-
> pathogenicity + CADD deleteriousness), licensable-source gating for
|
|
46
|
-
> commercial users, dual-build ClinVar caches (GRCh37 + GRCh38),
|
|
47
|
-
> HTML/JSON/terminal reports, methylation + pharmacogenomics focused
|
|
48
|
-
> commands, report diffing, persistent config with commercial-mode
|
|
49
|
-
> safety switch. Build auto-detection from position data (ADR-0021).
|
|
50
|
-
> No regex on prose anywhere in production. **Latest: v2.0.0** — VCF +
|
|
51
|
-
> gVCF parser with multi-sample handling, batched annotation pipeline
|
|
52
|
-
> for WGS scale, FTDNA Illumina raw parser, R-4 ClinVar CLNSIG drift CI
|
|
53
|
-
> test, CLI package restructure.
|
|
54
|
-
> Release notes:
|
|
55
|
-
> [`CHANGELOG.md`](https://github.com/allelix/allelix/blob/main/CHANGELOG.md).
|
|
58
|
+
> **Status:** Production. Eight parser formats (including VCF + gVCF), four annotators (ClinVar + ClinPGx + GWAS Catalog + SNPedia), three enrichment sources (gnomAD + AlphaMissense + CADD), licensable-source gating for commercial users, dual-build ClinVar caches (GRCh37 + GRCh38), HTML/JSON/terminal reports, methylation + pharmacogenomics focused commands, report diffing, persistent config with commercial-mode safety switch. Build auto-detection from position data (ADR-0021). No regex on prose anywhere in production. The [Changelog](https://github.com/allelix/allelix/blob/main/CHANGELOG.md) tracks every release.
|
|
56
59
|
|
|
57
60
|
## Quickstart
|
|
58
61
|
|
|
62
|
+
**Requires Python 3.11 or newer.** On Python 3.10 or older, `pip install allelix` succeeds but the first command fails with `ImportError: cannot import name 'UTC' from 'datetime'` — that's the symptom; the fix is to install on 3.11+. Check with `python --version`.
|
|
63
|
+
|
|
59
64
|
```bash
|
|
60
65
|
pip install allelix
|
|
61
66
|
|
|
62
|
-
# Download reference databases (~
|
|
67
|
+
# Download reference databases (~16 GB default install; ~22 GB if you opt into CADD).
|
|
63
68
|
# Use --no-gnomad / --no-alphamissense to skip the large ones.
|
|
64
69
|
# CADD is opt-in: allelix db update --cadd
|
|
65
70
|
allelix db update
|
|
@@ -77,7 +82,7 @@ allelix analyze trio.vcf.gz --sample HG002 --output report.html
|
|
|
77
82
|
allelix analyze your_genotype_file.txt --filter-file my_panel.txt --output report.html
|
|
78
83
|
```
|
|
79
84
|
|
|
80
|
-
|
|
85
|
+
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.
|
|
81
86
|
|
|
82
87
|
## Supported Formats
|
|
83
88
|
|
|
@@ -94,16 +99,17 @@ Requires Python 3.11+. See [Development](#development) for source installs and r
|
|
|
94
99
|
|
|
95
100
|
Adding a new format means adding one file to `allelix/parsers/` and registering an instance in the `PARSERS` list in `allelix/parsers/__init__.py`.
|
|
96
101
|
|
|
97
|
-
###
|
|
102
|
+
### Roadmap
|
|
98
103
|
|
|
99
|
-
|
|
|
104
|
+
| Release | Theme |
|
|
100
105
|
|---|---|
|
|
101
|
-
|
|
|
102
|
-
|
|
|
103
|
-
|
|
|
104
|
-
|
|
|
105
|
-
|
|
|
106
|
-
|
|
106
|
+
| **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`). |
|
|
107
|
+
| **v2.3** | Per-source magnitude decomposition, Good / Bad / Neutral annotation repute, JSON v3 (AI-legible output contract), plausibility flagging via zygosity × gnomAD MAF, ClinVar review-status weighting, functional-medicine +/− notation. |
|
|
108
|
+
| **v2.4** | ACMG/AMP automated classification engine, variant consequence annotation (VEP-equivalent). |
|
|
109
|
+
| **v2.5+** | CNVs and repeat-expansion support, dbSNP resolution for rsID-less VCFs, gnomAD genomes (non-coding population frequencies), supplemental genotype file merging. |
|
|
110
|
+
| **v3.0** | Ancestry estimation (PCA + 1KG/HGDP reference panels), Polygenic Risk Score (PRS) integration. |
|
|
111
|
+
|
|
112
|
+
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.
|
|
107
113
|
|
|
108
114
|
## Supported Databases
|
|
109
115
|
|
|
@@ -116,7 +122,20 @@ Adding a new format means adding one file to `allelix/parsers/` and registering
|
|
|
116
122
|
| 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 (ADR-0024) maps continuous p-values to the 0–10 scale; unknown-risk-allele entries fire on rsID match alone but are capped at 3.0. |
|
|
117
123
|
| gnomAD | ✓ | ODbL v1.0. **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). Use `--no-gnomad` to skip. |
|
|
118
124
|
| AlphaMissense | ✓ | CC BY 4.0. **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). Use `--no-alphamissense` to skip. |
|
|
119
|
-
| CADD | ✓ | LicenseRef-CADD (non-commercial). **Enrichment annotator** — adds PHRED-scaled deleteriousness scores from CADD v1.7.
|
|
125
|
+
| CADD | ✓ | LicenseRef-CADD (non-commercial). **Enrichment annotator** — adds PHRED-scaled deleteriousness scores from CADD v1.7. **Opt-in**, disabled by default; see [CADD modes](#cadd-modes) below for details. |
|
|
126
|
+
|
|
127
|
+
### CADD modes
|
|
128
|
+
|
|
129
|
+
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%.
|
|
130
|
+
|
|
131
|
+
**Opt-in**: enable via `allelix db update --cadd` or `allelix config set sources.cadd true`. Use `--no-cadd` to skip enrichment for a single run.
|
|
132
|
+
|
|
133
|
+
Two modes:
|
|
134
|
+
|
|
135
|
+
- **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). For genotyping chip data (23andMe, AncestryDNA, MyHappyGenes, etc.), this mode is functionally complete — chip probes overwhelmingly target known, cataloged variants.
|
|
136
|
+
- **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.
|
|
137
|
+
|
|
138
|
+
If your input is a genotyping chip file, cache mode is all you need.
|
|
120
139
|
|
|
121
140
|
### Build coverage asymmetry (GRCh37 vs GRCh38)
|
|
122
141
|
|
|
@@ -214,6 +233,48 @@ gnomAD and AlphaMissense are the largest but add the most interpretive context.
|
|
|
214
233
|
|
|
215
234
|
To skip either during download: `allelix db update --no-gnomad --no-alphamissense`. To disable permanently: `allelix config set sources.gnomad false`.
|
|
216
235
|
|
|
236
|
+
### Managing your data
|
|
237
|
+
|
|
238
|
+
Allelix stores reference database caches at `~/.local/share/allelix/` (Linux/macOS) or the XDG-equivalent on other platforms. Default install (no CADD) is ~16 GB on disk; with the CADD opt-in it's ~22 GB.
|
|
239
|
+
|
|
240
|
+
```
|
|
241
|
+
~/.local/share/allelix/
|
|
242
|
+
├── alphamissense.sqlite ~7.8 GB
|
|
243
|
+
├── gnomad.sqlite ~6.1 GB
|
|
244
|
+
├── cadd.sqlite ~5.8 GB (only if you opted into --cadd)
|
|
245
|
+
├── clinvar.GRCh37.sqlite ~470 MB
|
|
246
|
+
├── clinvar.GRCh38.sqlite ~480 MB
|
|
247
|
+
├── gwas_catalog_associations.tsv ~700 MB
|
|
248
|
+
├── snpedia.sqlite ~390 MB
|
|
249
|
+
├── gwas.sqlite ~190 MB
|
|
250
|
+
└── pharmgkb.sqlite ~14 MB
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**The caches are disposable and re-downloadable.** Everything here was fetched by `allelix db update` and can be re-fetched at any time. There's no per-user state in the cache — your genotype files never enter this directory. Safe to delete to reclaim space (or to force a full refresh if you suspect a cache went stale):
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
# Reclaim all ~16-22 GB
|
|
257
|
+
rm -rf ~/.local/share/allelix/
|
|
258
|
+
|
|
259
|
+
# Reclaim everything except CADD (avoids re-downloading the slowest one)
|
|
260
|
+
find ~/.local/share/allelix/ -mindepth 1 ! -name 'cadd*.sqlite*' -delete
|
|
261
|
+
|
|
262
|
+
# Re-populate from scratch next time you analyze a file
|
|
263
|
+
allelix db update
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**The one thing worth backing up: `config.toml`.** It lives separately (XDG config dir, typically `~/.config/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.
|
|
267
|
+
|
|
268
|
+
To fully uninstall allelix and reclaim everything:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
pip uninstall allelix
|
|
272
|
+
rm -rf ~/.local/share/allelix/ # reference database caches
|
|
273
|
+
rm -rf ~/.config/allelix/ # license + source-toggle config
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
A `allelix db clean` subcommand to automate the cache-clear step (with confirmation prompt and size report) is planned for v2.2 alongside `allelix db path` (prints the resolved data directory for scripting / backup integration).
|
|
277
|
+
|
|
217
278
|
## Data Sources & Licensing
|
|
218
279
|
|
|
219
280
|
Allelix source code is licensed under the **GNU Affero General Public License v3.0 or later** (AGPL-3.0-or-later). Allelix ships with **zero third-party data**. All reference databases are downloaded by the user at runtime via `allelix db update`. Each database retains its original license on the user's machine:
|
|
@@ -256,6 +317,42 @@ Of the 104,806 genotype pages in the archive:
|
|
|
256
317
|
|
|
257
318
|
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.
|
|
258
319
|
|
|
320
|
+
## Troubleshooting
|
|
321
|
+
|
|
322
|
+
### `ImportError: cannot import name 'UTC' from 'datetime'`
|
|
323
|
+
|
|
324
|
+
You're on Python 3.10 or older. Allelix requires 3.11+. `python --version` to check; upgrade and reinstall.
|
|
325
|
+
|
|
326
|
+
### `allelix db update` failed partway through
|
|
327
|
+
|
|
328
|
+
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, you can isolate it: `allelix db update --no-gnomad` (or `--no-alphamissense` etc.) to skip the failing source for now, then retry that source standalone later.
|
|
329
|
+
|
|
330
|
+
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.
|
|
331
|
+
|
|
332
|
+
### `db status` shows an annotator as "not ready" but the cache files exist on disk
|
|
333
|
+
|
|
334
|
+
Almost always a schema or interpreter version bump in a recent allelix release that invalidates the pre-bump cache. The fix is `allelix db update` — it'll re-ingest only the affected annotators (everything else signal-skips). See the relevant `CHANGELOG.md` entry for "Cache invalidation" notes per release.
|
|
335
|
+
|
|
336
|
+
### Build mismatch warning when analyzing a known-good file
|
|
337
|
+
|
|
338
|
+
Either: (a) the file's header claims one build and the position data is actually a different build (real-world MHG / Tempus exports do this — header says 37, positions are 38; ADR-0021 documents the auto-detection), or (b) the file is a GRCh36-era export (pre-2012), which allelix detects accurately but doesn't ship a ClinVar cache for (see [`docs/grch36-liftover.md`](https://github.com/allelix/allelix/blob/main/docs/grch36-liftover.md) for the external-liftover path).
|
|
339
|
+
|
|
340
|
+
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.
|
|
341
|
+
|
|
342
|
+
### Is my database stale? How fresh is the data?
|
|
343
|
+
|
|
344
|
+
`allelix db status` shows the ingestion date of each cache. The freshness model is signal-driven: `allelix db update` queries an upstream freshness signal (md5 / etag) per source and re-ingests only when the signal changed. There's no time-based staleness — a 6-month-old cache against an unchanged source IS current.
|
|
345
|
+
|
|
346
|
+
If you want to force a refresh: `allelix db update --force` re-downloads every cache regardless of freshness signal.
|
|
347
|
+
|
|
348
|
+
### Output reports contain real genome annotations
|
|
349
|
+
|
|
350
|
+
Anything `allelix analyze` writes to disk contains real annotations of your genome. Treat the output files (HTML, JSON, terminal redirects) as sensitive — they're as private as the input genotype file. Allelix does not transmit them; the lifecycle is local.
|
|
351
|
+
|
|
352
|
+
### Where does allelix store its data?
|
|
353
|
+
|
|
354
|
+
See [Managing your data](#managing-your-data) above for cache locations, the disposability rule, what to back up, and the uninstall procedure.
|
|
355
|
+
|
|
259
356
|
## Architecture & Design Decisions
|
|
260
357
|
|
|
261
358
|
The "why" behind major design choices lives in [`docs/adr/`](https://github.com/allelix/allelix/blob/main/docs/adr/README.md) as Architecture Decision Records. Read these before proposing changes that touch the parser/annotator interfaces, the regulatory posture, or the data-handling model.
|
|
@@ -1,28 +1,31 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="https://allelix.io/apple-touch-icon.png" width="180" alt="Allelix" />
|
|
4
|
+
|
|
5
|
+
**Open-source genotype analysis. Format-agnostic. Offline-first.**
|
|
6
|
+
|
|
7
|
+
[Website](https://allelix.io) · [Quickstart](#quickstart) · [Changelog](https://github.com/allelix/allelix/blob/main/CHANGELOG.md)
|
|
8
|
+
|
|
9
|
+
[](https://www.python.org/downloads/)
|
|
10
|
+
[](https://pypi.org/project/allelix/)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+
[](https://github.com/allelix/allelix/actions/workflows/ci.yml)
|
|
13
|
+
[](#privacy)
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
1
17
|
# Allelix
|
|
2
18
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
> **Status:** Production — eight parser formats (including VCF + gVCF),
|
|
6
|
-
> four annotators (ClinVar + ClinPGx + GWAS Catalog + SNPedia), three
|
|
7
|
-
> enrichment sources (gnomAD population frequencies + AlphaMissense
|
|
8
|
-
> pathogenicity + CADD deleteriousness), licensable-source gating for
|
|
9
|
-
> commercial users, dual-build ClinVar caches (GRCh37 + GRCh38),
|
|
10
|
-
> HTML/JSON/terminal reports, methylation + pharmacogenomics focused
|
|
11
|
-
> commands, report diffing, persistent config with commercial-mode
|
|
12
|
-
> safety switch. Build auto-detection from position data (ADR-0021).
|
|
13
|
-
> No regex on prose anywhere in production. **Latest: v2.0.0** — VCF +
|
|
14
|
-
> gVCF parser with multi-sample handling, batched annotation pipeline
|
|
15
|
-
> for WGS scale, FTDNA Illumina raw parser, R-4 ClinVar CLNSIG drift CI
|
|
16
|
-
> test, CLI package restructure.
|
|
17
|
-
> Release notes:
|
|
18
|
-
> [`CHANGELOG.md`](https://github.com/allelix/allelix/blob/main/CHANGELOG.md).
|
|
19
|
+
> **Status:** Production. Eight parser formats (including VCF + gVCF), four annotators (ClinVar + ClinPGx + GWAS Catalog + SNPedia), three enrichment sources (gnomAD + AlphaMissense + CADD), licensable-source gating for commercial users, dual-build ClinVar caches (GRCh37 + GRCh38), HTML/JSON/terminal reports, methylation + pharmacogenomics focused commands, report diffing, persistent config with commercial-mode safety switch. Build auto-detection from position data (ADR-0021). No regex on prose anywhere in production. The [Changelog](https://github.com/allelix/allelix/blob/main/CHANGELOG.md) tracks every release.
|
|
19
20
|
|
|
20
21
|
## Quickstart
|
|
21
22
|
|
|
23
|
+
**Requires Python 3.11 or newer.** On Python 3.10 or older, `pip install allelix` succeeds but the first command fails with `ImportError: cannot import name 'UTC' from 'datetime'` — that's the symptom; the fix is to install on 3.11+. Check with `python --version`.
|
|
24
|
+
|
|
22
25
|
```bash
|
|
23
26
|
pip install allelix
|
|
24
27
|
|
|
25
|
-
# Download reference databases (~
|
|
28
|
+
# Download reference databases (~16 GB default install; ~22 GB if you opt into CADD).
|
|
26
29
|
# Use --no-gnomad / --no-alphamissense to skip the large ones.
|
|
27
30
|
# CADD is opt-in: allelix db update --cadd
|
|
28
31
|
allelix db update
|
|
@@ -40,7 +43,7 @@ allelix analyze trio.vcf.gz --sample HG002 --output report.html
|
|
|
40
43
|
allelix analyze your_genotype_file.txt --filter-file my_panel.txt --output report.html
|
|
41
44
|
```
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
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.
|
|
44
47
|
|
|
45
48
|
## Supported Formats
|
|
46
49
|
|
|
@@ -57,16 +60,17 @@ Requires Python 3.11+. See [Development](#development) for source installs and r
|
|
|
57
60
|
|
|
58
61
|
Adding a new format means adding one file to `allelix/parsers/` and registering an instance in the `PARSERS` list in `allelix/parsers/__init__.py`.
|
|
59
62
|
|
|
60
|
-
###
|
|
63
|
+
### Roadmap
|
|
61
64
|
|
|
62
|
-
|
|
|
65
|
+
| Release | Theme |
|
|
63
66
|
|---|---|
|
|
64
|
-
|
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
67
|
+
| **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`). |
|
|
68
|
+
| **v2.3** | Per-source magnitude decomposition, Good / Bad / Neutral annotation repute, JSON v3 (AI-legible output contract), plausibility flagging via zygosity × gnomAD MAF, ClinVar review-status weighting, functional-medicine +/− notation. |
|
|
69
|
+
| **v2.4** | ACMG/AMP automated classification engine, variant consequence annotation (VEP-equivalent). |
|
|
70
|
+
| **v2.5+** | CNVs and repeat-expansion support, dbSNP resolution for rsID-less VCFs, gnomAD genomes (non-coding population frequencies), supplemental genotype file merging. |
|
|
71
|
+
| **v3.0** | Ancestry estimation (PCA + 1KG/HGDP reference panels), Polygenic Risk Score (PRS) integration. |
|
|
72
|
+
|
|
73
|
+
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.
|
|
70
74
|
|
|
71
75
|
## Supported Databases
|
|
72
76
|
|
|
@@ -79,7 +83,20 @@ Adding a new format means adding one file to `allelix/parsers/` and registering
|
|
|
79
83
|
| 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 (ADR-0024) maps continuous p-values to the 0–10 scale; unknown-risk-allele entries fire on rsID match alone but are capped at 3.0. |
|
|
80
84
|
| gnomAD | ✓ | ODbL v1.0. **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). Use `--no-gnomad` to skip. |
|
|
81
85
|
| AlphaMissense | ✓ | CC BY 4.0. **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). Use `--no-alphamissense` to skip. |
|
|
82
|
-
| CADD | ✓ | LicenseRef-CADD (non-commercial). **Enrichment annotator** — adds PHRED-scaled deleteriousness scores from CADD v1.7.
|
|
86
|
+
| CADD | ✓ | LicenseRef-CADD (non-commercial). **Enrichment annotator** — adds PHRED-scaled deleteriousness scores from CADD v1.7. **Opt-in**, disabled by default; see [CADD modes](#cadd-modes) below for details. |
|
|
87
|
+
|
|
88
|
+
### CADD modes
|
|
89
|
+
|
|
90
|
+
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%.
|
|
91
|
+
|
|
92
|
+
**Opt-in**: enable via `allelix db update --cadd` or `allelix config set sources.cadd true`. Use `--no-cadd` to skip enrichment for a single run.
|
|
93
|
+
|
|
94
|
+
Two modes:
|
|
95
|
+
|
|
96
|
+
- **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). For genotyping chip data (23andMe, AncestryDNA, MyHappyGenes, etc.), this mode is functionally complete — chip probes overwhelmingly target known, cataloged variants.
|
|
97
|
+
- **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.
|
|
98
|
+
|
|
99
|
+
If your input is a genotyping chip file, cache mode is all you need.
|
|
83
100
|
|
|
84
101
|
### Build coverage asymmetry (GRCh37 vs GRCh38)
|
|
85
102
|
|
|
@@ -177,6 +194,48 @@ gnomAD and AlphaMissense are the largest but add the most interpretive context.
|
|
|
177
194
|
|
|
178
195
|
To skip either during download: `allelix db update --no-gnomad --no-alphamissense`. To disable permanently: `allelix config set sources.gnomad false`.
|
|
179
196
|
|
|
197
|
+
### Managing your data
|
|
198
|
+
|
|
199
|
+
Allelix stores reference database caches at `~/.local/share/allelix/` (Linux/macOS) or the XDG-equivalent on other platforms. Default install (no CADD) is ~16 GB on disk; with the CADD opt-in it's ~22 GB.
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
~/.local/share/allelix/
|
|
203
|
+
├── alphamissense.sqlite ~7.8 GB
|
|
204
|
+
├── gnomad.sqlite ~6.1 GB
|
|
205
|
+
├── cadd.sqlite ~5.8 GB (only if you opted into --cadd)
|
|
206
|
+
├── clinvar.GRCh37.sqlite ~470 MB
|
|
207
|
+
├── clinvar.GRCh38.sqlite ~480 MB
|
|
208
|
+
├── gwas_catalog_associations.tsv ~700 MB
|
|
209
|
+
├── snpedia.sqlite ~390 MB
|
|
210
|
+
├── gwas.sqlite ~190 MB
|
|
211
|
+
└── pharmgkb.sqlite ~14 MB
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**The caches are disposable and re-downloadable.** Everything here was fetched by `allelix db update` and can be re-fetched at any time. There's no per-user state in the cache — your genotype files never enter this directory. Safe to delete to reclaim space (or to force a full refresh if you suspect a cache went stale):
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
# Reclaim all ~16-22 GB
|
|
218
|
+
rm -rf ~/.local/share/allelix/
|
|
219
|
+
|
|
220
|
+
# Reclaim everything except CADD (avoids re-downloading the slowest one)
|
|
221
|
+
find ~/.local/share/allelix/ -mindepth 1 ! -name 'cadd*.sqlite*' -delete
|
|
222
|
+
|
|
223
|
+
# Re-populate from scratch next time you analyze a file
|
|
224
|
+
allelix db update
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**The one thing worth backing up: `config.toml`.** It lives separately (XDG config dir, typically `~/.config/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.
|
|
228
|
+
|
|
229
|
+
To fully uninstall allelix and reclaim everything:
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
pip uninstall allelix
|
|
233
|
+
rm -rf ~/.local/share/allelix/ # reference database caches
|
|
234
|
+
rm -rf ~/.config/allelix/ # license + source-toggle config
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
A `allelix db clean` subcommand to automate the cache-clear step (with confirmation prompt and size report) is planned for v2.2 alongside `allelix db path` (prints the resolved data directory for scripting / backup integration).
|
|
238
|
+
|
|
180
239
|
## Data Sources & Licensing
|
|
181
240
|
|
|
182
241
|
Allelix source code is licensed under the **GNU Affero General Public License v3.0 or later** (AGPL-3.0-or-later). Allelix ships with **zero third-party data**. All reference databases are downloaded by the user at runtime via `allelix db update`. Each database retains its original license on the user's machine:
|
|
@@ -219,6 +278,42 @@ Of the 104,806 genotype pages in the archive:
|
|
|
219
278
|
|
|
220
279
|
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.
|
|
221
280
|
|
|
281
|
+
## Troubleshooting
|
|
282
|
+
|
|
283
|
+
### `ImportError: cannot import name 'UTC' from 'datetime'`
|
|
284
|
+
|
|
285
|
+
You're on Python 3.10 or older. Allelix requires 3.11+. `python --version` to check; upgrade and reinstall.
|
|
286
|
+
|
|
287
|
+
### `allelix db update` failed partway through
|
|
288
|
+
|
|
289
|
+
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, you can isolate it: `allelix db update --no-gnomad` (or `--no-alphamissense` etc.) to skip the failing source for now, then retry that source standalone later.
|
|
290
|
+
|
|
291
|
+
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.
|
|
292
|
+
|
|
293
|
+
### `db status` shows an annotator as "not ready" but the cache files exist on disk
|
|
294
|
+
|
|
295
|
+
Almost always a schema or interpreter version bump in a recent allelix release that invalidates the pre-bump cache. The fix is `allelix db update` — it'll re-ingest only the affected annotators (everything else signal-skips). See the relevant `CHANGELOG.md` entry for "Cache invalidation" notes per release.
|
|
296
|
+
|
|
297
|
+
### Build mismatch warning when analyzing a known-good file
|
|
298
|
+
|
|
299
|
+
Either: (a) the file's header claims one build and the position data is actually a different build (real-world MHG / Tempus exports do this — header says 37, positions are 38; ADR-0021 documents the auto-detection), or (b) the file is a GRCh36-era export (pre-2012), which allelix detects accurately but doesn't ship a ClinVar cache for (see [`docs/grch36-liftover.md`](https://github.com/allelix/allelix/blob/main/docs/grch36-liftover.md) for the external-liftover path).
|
|
300
|
+
|
|
301
|
+
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.
|
|
302
|
+
|
|
303
|
+
### Is my database stale? How fresh is the data?
|
|
304
|
+
|
|
305
|
+
`allelix db status` shows the ingestion date of each cache. The freshness model is signal-driven: `allelix db update` queries an upstream freshness signal (md5 / etag) per source and re-ingests only when the signal changed. There's no time-based staleness — a 6-month-old cache against an unchanged source IS current.
|
|
306
|
+
|
|
307
|
+
If you want to force a refresh: `allelix db update --force` re-downloads every cache regardless of freshness signal.
|
|
308
|
+
|
|
309
|
+
### Output reports contain real genome annotations
|
|
310
|
+
|
|
311
|
+
Anything `allelix analyze` writes to disk contains real annotations of your genome. Treat the output files (HTML, JSON, terminal redirects) as sensitive — they're as private as the input genotype file. Allelix does not transmit them; the lifecycle is local.
|
|
312
|
+
|
|
313
|
+
### Where does allelix store its data?
|
|
314
|
+
|
|
315
|
+
See [Managing your data](#managing-your-data) above for cache locations, the disposability rule, what to back up, and the uninstall procedure.
|
|
316
|
+
|
|
222
317
|
## Architecture & Design Decisions
|
|
223
318
|
|
|
224
319
|
The "why" behind major design choices lives in [`docs/adr/`](https://github.com/allelix/allelix/blob/main/docs/adr/README.md) as Architecture Decision Records. Read these before proposing changes that touch the parser/annotator interfaces, the regulatory posture, or the data-handling model.
|
|
@@ -57,18 +57,16 @@ def get_annotators(
|
|
|
57
57
|
return [clinvar, pharmgkb, gwas, snpedia, gnomad, alphamissense, cadd]
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
]
|
|
71
|
-
}
|
|
60
|
+
_ANNOTATOR_CLASS_LIST: list[type[Annotator]] = [
|
|
61
|
+
ClinVarAnnotator,
|
|
62
|
+
PharmGKBAnnotator,
|
|
63
|
+
GWASCatalogAnnotator,
|
|
64
|
+
SNPediaAnnotator,
|
|
65
|
+
GnomadAnnotator,
|
|
66
|
+
AlphaMissenseAnnotator,
|
|
67
|
+
CaddAnnotator,
|
|
68
|
+
]
|
|
69
|
+
_ANNOTATOR_CLASSES: dict[str, type[Annotator]] = {cls.name: cls for cls in _ANNOTATOR_CLASS_LIST}
|
|
72
70
|
|
|
73
71
|
|
|
74
72
|
def get_annotator_class(name: str) -> type[Annotator] | None:
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
-
import contextlib
|
|
8
7
|
from abc import ABC, abstractmethod
|
|
9
8
|
from dataclasses import dataclass
|
|
10
9
|
from enum import Enum, auto
|
|
@@ -141,34 +140,6 @@ class Annotator(ABC):
|
|
|
141
140
|
"""Bind the annotator to a data directory (created elsewhere)."""
|
|
142
141
|
self.data_dir = data_dir
|
|
143
142
|
|
|
144
|
-
def __del__(self) -> None:
|
|
145
|
-
"""Safety-net resource release on GC. Deliberately retained.
|
|
146
|
-
|
|
147
|
-
GH #36 (audit second pass) flagged ``__del__`` as a Python
|
|
148
|
-
antipattern — GC timing is nondeterministic and raised exceptions
|
|
149
|
-
are silently swallowed. The correct usage pattern is the
|
|
150
|
-
``__enter__`` / ``__exit__`` context manager pair below, wired
|
|
151
|
-
through ``contextlib.ExitStack`` in ``reports/_pipeline.py``.
|
|
152
|
-
|
|
153
|
-
However: removing ``__del__`` exposes residual SQLite connection
|
|
154
|
-
leaks in code paths that construct an annotator outside a
|
|
155
|
-
context manager. ``ResourceWarning`` is elevated to error by
|
|
156
|
-
``pytest`` config, so leaks fail the suite as
|
|
157
|
-
``PytestUnraisableExceptionWarning`` — caught in the v2.0.2
|
|
158
|
-
ship gate when ``__del__`` was first removed. Until every call
|
|
159
|
-
site is verified to use ``with`` / ``ExitStack`` / explicit
|
|
160
|
-
``close()``, this safety net stays. v2.1 task: audit and
|
|
161
|
-
remove.
|
|
162
|
-
|
|
163
|
-
``contextlib.suppress(Exception)`` is deliberate — ``__del__``
|
|
164
|
-
must never raise. The GC timing and shutdown-ordering edges
|
|
165
|
-
are explicitly silenced; this is exactly the
|
|
166
|
-
"if you must keep ``__del__``, make absolutely sure it can
|
|
167
|
-
never raise" mitigation the audit recommended.
|
|
168
|
-
"""
|
|
169
|
-
with contextlib.suppress(Exception):
|
|
170
|
-
self.close()
|
|
171
|
-
|
|
172
143
|
def __enter__(self) -> Annotator:
|
|
173
144
|
"""Return self for `with` usage."""
|
|
174
145
|
return self
|
|
@@ -24,7 +24,7 @@ from __future__ import annotations
|
|
|
24
24
|
|
|
25
25
|
import logging
|
|
26
26
|
import sqlite3
|
|
27
|
-
from typing import TYPE_CHECKING, ClassVar
|
|
27
|
+
from typing import TYPE_CHECKING, Any, ClassVar
|
|
28
28
|
|
|
29
29
|
from allelix.annotators.base import Annotator, LicenseDescriptor
|
|
30
30
|
from allelix.databases._versions import CADD_SCHEMA_VERSION
|
|
@@ -90,9 +90,11 @@ class CaddAnnotator(Annotator):
|
|
|
90
90
|
self._conn: sqlite3.Connection | None = None
|
|
91
91
|
self._full_mode = full_mode
|
|
92
92
|
self._tabix_path = data_dir / CADD_FULL_FILENAME
|
|
93
|
-
|
|
93
|
+
# pysam ships no type stubs (see [tool.mypy.overrides]); the tabix
|
|
94
|
+
# handle is held as Any so call sites can use `.fetch()` / `.close()`.
|
|
95
|
+
self._tabix: Any = None
|
|
94
96
|
self._indel_tabix_path = data_dir / CADD_INDEL_FILENAME
|
|
95
|
-
self._indel_tabix:
|
|
97
|
+
self._indel_tabix: Any = None
|
|
96
98
|
|
|
97
99
|
def _connection(self) -> sqlite3.Connection:
|
|
98
100
|
if self._conn is None:
|
|
@@ -104,11 +106,11 @@ class CaddAnnotator(Annotator):
|
|
|
104
106
|
self._conn = sqlite3.connect(self._db_path)
|
|
105
107
|
return self._conn
|
|
106
108
|
|
|
107
|
-
def _open_tabix(self) ->
|
|
109
|
+
def _open_tabix(self) -> Any: # noqa: ANN401 — pysam ships no type stubs
|
|
108
110
|
"""Open the tabix file for full-mode queries."""
|
|
109
111
|
if self._tabix is None:
|
|
110
112
|
try:
|
|
111
|
-
import pysam
|
|
113
|
+
import pysam
|
|
112
114
|
except ImportError:
|
|
113
115
|
raise ImportError(
|
|
114
116
|
"Full CADD mode requires pysam. Install with: pip install 'allelix[cadd]'"
|
|
@@ -122,7 +124,7 @@ class CaddAnnotator(Annotator):
|
|
|
122
124
|
self._tabix = pysam.TabixFile(str(self._tabix_path))
|
|
123
125
|
return self._tabix
|
|
124
126
|
|
|
125
|
-
def _open_indel_tabix(self) ->
|
|
127
|
+
def _open_indel_tabix(self) -> Any: # noqa: ANN401 — pysam ships no type stubs
|
|
126
128
|
"""Open the indel tabix file. Returns None if file doesn't exist."""
|
|
127
129
|
if self._indel_tabix is None:
|
|
128
130
|
if not self._indel_tabix_path.exists():
|
|
@@ -131,7 +133,7 @@ class CaddAnnotator(Annotator):
|
|
|
131
133
|
if not tbi.exists():
|
|
132
134
|
return None
|
|
133
135
|
try:
|
|
134
|
-
import pysam
|
|
136
|
+
import pysam
|
|
135
137
|
except ImportError:
|
|
136
138
|
return None
|
|
137
139
|
self._indel_tabix = pysam.TabixFile(str(self._indel_tabix_path))
|
|
@@ -500,9 +500,10 @@ class ClinVarAnnotator(Annotator):
|
|
|
500
500
|
for rows in clinvar_rows.values():
|
|
501
501
|
rows.sort()
|
|
502
502
|
for v in build_variants:
|
|
503
|
-
|
|
504
|
-
if not
|
|
503
|
+
pos_rows = clinvar_rows.get((v.chromosome, v.position))
|
|
504
|
+
if not pos_rows:
|
|
505
505
|
continue
|
|
506
|
+
rows = pos_rows
|
|
506
507
|
user_alleles = {v.allele1, v.allele2}
|
|
507
508
|
# Stamp only on a UNIQUE consistent match. Multiple matches
|
|
508
509
|
# mean the Variant model can't distinguish them (the 1/1
|
|
@@ -16,7 +16,7 @@ import logging
|
|
|
16
16
|
import re
|
|
17
17
|
import sys
|
|
18
18
|
import time
|
|
19
|
-
from typing import TYPE_CHECKING, NamedTuple
|
|
19
|
+
from typing import TYPE_CHECKING, NamedTuple, cast
|
|
20
20
|
|
|
21
21
|
import click
|
|
22
22
|
from rich.console import Console
|
|
@@ -34,7 +34,10 @@ from allelix.reports.terminal import render_terminal, render_terminal_diff
|
|
|
34
34
|
if TYPE_CHECKING:
|
|
35
35
|
from pathlib import Path
|
|
36
36
|
|
|
37
|
+
from allelix.annotators.alphamissense import AlphaMissenseAnnotator
|
|
37
38
|
from allelix.annotators.base import Annotator
|
|
39
|
+
from allelix.annotators.cadd import CaddAnnotator
|
|
40
|
+
from allelix.annotators.gnomad import GnomadAnnotator
|
|
38
41
|
from allelix.parsers.base import GenotypeParser
|
|
39
42
|
|
|
40
43
|
console = Console()
|
|
@@ -489,9 +492,9 @@ def _run_analysis_command(
|
|
|
489
492
|
ready,
|
|
490
493
|
skipped_count_provider=lambda: counter.count,
|
|
491
494
|
build_override=build,
|
|
492
|
-
gnomad=gnomad_annotator,
|
|
493
|
-
alphamissense=am_annotator,
|
|
494
|
-
cadd=cadd_annotator,
|
|
495
|
+
gnomad=cast("GnomadAnnotator | None", gnomad_annotator),
|
|
496
|
+
alphamissense=cast("AlphaMissenseAnnotator | None", am_annotator),
|
|
497
|
+
cadd=cast("CaddAnnotator | None", cadd_annotator),
|
|
495
498
|
high_value_rsids=hv_rsids,
|
|
496
499
|
)
|
|
497
500
|
finally:
|