vartriage 0.1.0__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.
- vartriage-0.1.0/.github/workflows/ci.yml +35 -0
- vartriage-0.1.0/.github/workflows/publish.yml +29 -0
- vartriage-0.1.0/.gitignore +47 -0
- vartriage-0.1.0/CONTRIBUTING.md +120 -0
- vartriage-0.1.0/LICENSE +21 -0
- vartriage-0.1.0/PKG-INFO +343 -0
- vartriage-0.1.0/README.md +296 -0
- vartriage-0.1.0/docs/api/annotation.md +3 -0
- vartriage-0.1.0/docs/api/classification.md +3 -0
- vartriage-0.1.0/docs/api/config.md +13 -0
- vartriage-0.1.0/docs/api/exceptions.md +9 -0
- vartriage-0.1.0/docs/api/filter.md +3 -0
- vartriage-0.1.0/docs/api/index.md +22 -0
- vartriage-0.1.0/docs/api/models.md +23 -0
- vartriage-0.1.0/docs/api/parser.md +3 -0
- vartriage-0.1.0/docs/api/pipeline.md +3 -0
- vartriage-0.1.0/docs/api/prioritization.md +3 -0
- vartriage-0.1.0/docs/api/reporting.md +3 -0
- vartriage-0.1.0/docs/architecture.md +109 -0
- vartriage-0.1.0/docs/changelog.md +17 -0
- vartriage-0.1.0/docs/configuration.md +175 -0
- vartriage-0.1.0/docs/getting-started.md +78 -0
- vartriage-0.1.0/docs/index.md +32 -0
- vartriage-0.1.0/docs/pipeline-stages.md +162 -0
- vartriage-0.1.0/docs/reference-files.md +160 -0
- vartriage-0.1.0/docs/tutorial.md +129 -0
- vartriage-0.1.0/mkdocs.yml +68 -0
- vartriage-0.1.0/pyproject.toml +101 -0
- vartriage-0.1.0/tests/__init__.py +0 -0
- vartriage-0.1.0/tests/conftest.py +40 -0
- vartriage-0.1.0/tests/generators/__init__.py +1 -0
- vartriage-0.1.0/tests/generators/variants.py +258 -0
- vartriage-0.1.0/tests/generators/vcf.py +217 -0
- vartriage-0.1.0/tests/integration/__init__.py +0 -0
- vartriage-0.1.0/tests/integration/test_performance.py +290 -0
- vartriage-0.1.0/tests/integration/test_pipeline_e2e.py +861 -0
- vartriage-0.1.0/tests/invariants/__init__.py +0 -0
- vartriage-0.1.0/tests/invariants/test_annotation.py +366 -0
- vartriage-0.1.0/tests/invariants/test_classification.py +421 -0
- vartriage-0.1.0/tests/invariants/test_filtering.py +254 -0
- vartriage-0.1.0/tests/invariants/test_parsing.py +161 -0
- vartriage-0.1.0/tests/invariants/test_prioritization.py +430 -0
- vartriage-0.1.0/tests/invariants/test_serialization.py +245 -0
- vartriage-0.1.0/tests/invariants/test_streaming_properties.py +352 -0
- vartriage-0.1.0/tests/invariants/test_warnings.py +672 -0
- vartriage-0.1.0/tests/test_annotation_engine_smoke.py +279 -0
- vartriage-0.1.0/tests/test_consequence_smoke.py +180 -0
- vartriage-0.1.0/tests/test_frequency_smoke.py +178 -0
- vartriage-0.1.0/tests/test_pipeline_smoke.py +377 -0
- vartriage-0.1.0/tests/unit/__init__.py +0 -0
- vartriage-0.1.0/tests/unit/test_acmg_classify_wiring.py +173 -0
- vartriage-0.1.0/tests/unit/test_acmg_evidence_tags.py +273 -0
- vartriage-0.1.0/tests/unit/test_batch.py +118 -0
- vartriage-0.1.0/tests/unit/test_combining.py +93 -0
- vartriage-0.1.0/tests/unit/test_csv_writer.py +201 -0
- vartriage-0.1.0/tests/unit/test_edge_cases.py +552 -0
- vartriage-0.1.0/tests/unit/test_frequency_filter.py +157 -0
- vartriage-0.1.0/tests/unit/test_pdf_writer.py +179 -0
- vartriage-0.1.0/tests/unit/test_pypi_readiness.py +492 -0
- vartriage-0.1.0/tests/unit/test_quality_filter.py +138 -0
- vartriage-0.1.0/tests/unit/test_report_generator.py +208 -0
- vartriage-0.1.0/tests/unit/test_scoring.py +265 -0
- vartriage-0.1.0/tests/unit/test_vcf_parser.py +176 -0
- vartriage-0.1.0/tests/unit/test_vectorized.py +338 -0
- vartriage-0.1.0/tests/unit/test_warning_accumulator.py +263 -0
- vartriage-0.1.0/uv.lock +1813 -0
- vartriage-0.1.0/vartriage/__init__.py +95 -0
- vartriage-0.1.0/vartriage/_internal/__init__.py +4 -0
- vartriage-0.1.0/vartriage/_internal/batch.py +131 -0
- vartriage-0.1.0/vartriage/_internal/interval_tree.py +466 -0
- vartriage-0.1.0/vartriage/_internal/vectorized.py +502 -0
- vartriage-0.1.0/vartriage/_internal/warning_accumulator.py +280 -0
- vartriage-0.1.0/vartriage/annotation/__init__.py +1 -0
- vartriage-0.1.0/vartriage/annotation/clinvar.py +176 -0
- vartriage-0.1.0/vartriage/annotation/clinvar_polars.py +192 -0
- vartriage-0.1.0/vartriage/annotation/consequence.py +161 -0
- vartriage-0.1.0/vartriage/annotation/consequence_pyranges.py +388 -0
- vartriage-0.1.0/vartriage/annotation/engine.py +349 -0
- vartriage-0.1.0/vartriage/annotation/frequency.py +162 -0
- vartriage-0.1.0/vartriage/annotation/frequency_polars.py +206 -0
- vartriage-0.1.0/vartriage/classification/__init__.py +1 -0
- vartriage-0.1.0/vartriage/classification/acmg.py +230 -0
- vartriage-0.1.0/vartriage/classification/combining.py +105 -0
- vartriage-0.1.0/vartriage/cli.py +188 -0
- vartriage-0.1.0/vartriage/exceptions.py +10 -0
- vartriage-0.1.0/vartriage/filter/__init__.py +5 -0
- vartriage-0.1.0/vartriage/filter/quality_filter.py +113 -0
- vartriage-0.1.0/vartriage/io/__init__.py +1 -0
- vartriage-0.1.0/vartriage/io/exceptions.py +124 -0
- vartriage-0.1.0/vartriage/io/vcf_parser.py +349 -0
- vartriage-0.1.0/vartriage/models/__init__.py +29 -0
- vartriage-0.1.0/vartriage/models/config.py +184 -0
- vartriage-0.1.0/vartriage/models/variant.py +268 -0
- vartriage-0.1.0/vartriage/models/warnings.py +54 -0
- vartriage-0.1.0/vartriage/pipeline.py +244 -0
- vartriage-0.1.0/vartriage/prioritization/__init__.py +1 -0
- vartriage-0.1.0/vartriage/prioritization/engine.py +223 -0
- vartriage-0.1.0/vartriage/prioritization/frequency_filter.py +93 -0
- vartriage-0.1.0/vartriage/prioritization/score_loader.py +176 -0
- vartriage-0.1.0/vartriage/prioritization/scoring.py +290 -0
- vartriage-0.1.0/vartriage/protocols.py +211 -0
- vartriage-0.1.0/vartriage/py.typed +0 -0
- vartriage-0.1.0/vartriage/reporting/__init__.py +1 -0
- vartriage-0.1.0/vartriage/reporting/csv_writer.py +139 -0
- vartriage-0.1.0/vartriage/reporting/generator.py +155 -0
- vartriage-0.1.0/vartriage/reporting/json_writer.py +118 -0
- vartriage-0.1.0/vartriage/reporting/pdf_fallback.py +48 -0
- vartriage-0.1.0/vartriage/reporting/pdf_writer.py +256 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, "feature/**", "fix/**", "docs/**"]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
19
|
+
uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: ${{ matrix.python-version }}
|
|
22
|
+
|
|
23
|
+
- name: Install dependencies
|
|
24
|
+
run: pip install -e ".[dev]"
|
|
25
|
+
|
|
26
|
+
- name: Run tests
|
|
27
|
+
run: pytest
|
|
28
|
+
|
|
29
|
+
- name: Run mypy
|
|
30
|
+
run: mypy --strict --python-version=${{ matrix.python-version }} vartriage/
|
|
31
|
+
|
|
32
|
+
- name: Build package
|
|
33
|
+
run: |
|
|
34
|
+
pip install build
|
|
35
|
+
python -m build
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
environment: pypi
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Set up Python
|
|
18
|
+
uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.12"
|
|
21
|
+
|
|
22
|
+
- name: Install build tools
|
|
23
|
+
run: pip install build
|
|
24
|
+
|
|
25
|
+
- name: Build package
|
|
26
|
+
run: python -m build
|
|
27
|
+
|
|
28
|
+
- name: Publish to PyPI
|
|
29
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Python bytecode
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.pyc
|
|
4
|
+
*.pyo
|
|
5
|
+
|
|
6
|
+
# Virtual environments
|
|
7
|
+
.venv/
|
|
8
|
+
venv/
|
|
9
|
+
env/
|
|
10
|
+
|
|
11
|
+
# Build and distribution
|
|
12
|
+
*.egg-info/
|
|
13
|
+
dist/
|
|
14
|
+
build/
|
|
15
|
+
|
|
16
|
+
# Tool caches
|
|
17
|
+
.mypy_cache/
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.ruff_cache/
|
|
20
|
+
.hypothesis/
|
|
21
|
+
|
|
22
|
+
# Coverage
|
|
23
|
+
.coverage
|
|
24
|
+
htmlcov/
|
|
25
|
+
|
|
26
|
+
# MkDocs build output
|
|
27
|
+
site/
|
|
28
|
+
|
|
29
|
+
# Environment variables
|
|
30
|
+
.env
|
|
31
|
+
|
|
32
|
+
# macOS
|
|
33
|
+
.DS_Store
|
|
34
|
+
|
|
35
|
+
# Archives
|
|
36
|
+
archives/
|
|
37
|
+
|
|
38
|
+
# Temp test files
|
|
39
|
+
test_*.tmp.py
|
|
40
|
+
|
|
41
|
+
# UV lock (optional, remove this line if you want to track it)
|
|
42
|
+
# uv.lock
|
|
43
|
+
|
|
44
|
+
.history
|
|
45
|
+
.qodo
|
|
46
|
+
.kiro
|
|
47
|
+
.vscode
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Contributing to vartriage
|
|
2
|
+
|
|
3
|
+
Thanks for considering a contribution. Here's how to get set up, run tests, and open a PR.
|
|
4
|
+
|
|
5
|
+
## Development Setup
|
|
6
|
+
|
|
7
|
+
Clone the repository and install in editable mode with development dependencies:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
git clone https://github.com/Behordeun/vartriage.git
|
|
11
|
+
cd vartriage
|
|
12
|
+
pip install -e ".[dev]"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
This installs pytest, hypothesis, pytest-cov, and mypy alongside the core package.
|
|
16
|
+
|
|
17
|
+
### Accelerated Backends
|
|
18
|
+
|
|
19
|
+
For the optional fast backends (polars, pyranges) and PDF support:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install -e ".[all]"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This pulls in polars, pyranges, and reportlab.
|
|
26
|
+
|
|
27
|
+
## Running Tests
|
|
28
|
+
|
|
29
|
+
Run the full test suite with:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pytest
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
A passing run looks like:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
tests/ ... 383 passed in Xs
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The project uses [Hypothesis](https://hypothesis.readthedocs.io/) for property-based testing with three profiles:
|
|
42
|
+
|
|
43
|
+
| Profile | Max Examples | Usage |
|
|
44
|
+
| --------- | ------------ | ------------------------------ |
|
|
45
|
+
| `dev` | 50 | Default for local development |
|
|
46
|
+
| `ci` | 500 | Used in CI pipelines |
|
|
47
|
+
| `debug` | 10 | Quick iteration when debugging |
|
|
48
|
+
|
|
49
|
+
Switch profiles via the `HYPOTHESIS_PROFILE` environment variable:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
HYPOTHESIS_PROFILE=ci pytest
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
To skip slow performance benchmarks during local development:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pytest -m "not slow"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Type Checking
|
|
62
|
+
|
|
63
|
+
Strict mypy is enforced:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
mypy --strict
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
This uses the config in `pyproject.toml` (Python 3.10 target, strict mode). A clean run means zero errors.
|
|
70
|
+
|
|
71
|
+
## Code Style
|
|
72
|
+
|
|
73
|
+
We use **Black** for formatting and **ruff** for linting. Before opening a PR:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
black .
|
|
77
|
+
ruff check .
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Fix any auto-fixable lint issues with:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
ruff check --fix .
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Branch Naming
|
|
87
|
+
|
|
88
|
+
Use the following prefixes for your branches:
|
|
89
|
+
|
|
90
|
+
- `feature/` — new functionality (e.g., `feature/streaming-reports`)
|
|
91
|
+
- `fix/` — bug fixes (e.g., `fix/score-loader-nan-handling`)
|
|
92
|
+
- `docs/` — documentation changes (e.g., `docs/update-api-reference`)
|
|
93
|
+
|
|
94
|
+
## Pull Request Process
|
|
95
|
+
|
|
96
|
+
1. Create a branch from `main` using the naming convention above.
|
|
97
|
+
2. Make your changes, keeping commits focused on a single logical change.
|
|
98
|
+
3. Make sure CI passes:
|
|
99
|
+
- `pytest` (full suite)
|
|
100
|
+
- `mypy --strict` (zero errors)
|
|
101
|
+
- Black + ruff (formatting/lint)
|
|
102
|
+
4. Open a pull request against `main`.
|
|
103
|
+
5. PRs require at least one approval before merging.
|
|
104
|
+
6. Keep the PR description short: what changed, what you tested, open questions if any.
|
|
105
|
+
|
|
106
|
+
## Project Structure
|
|
107
|
+
|
|
108
|
+
```text
|
|
109
|
+
vartriage/
|
|
110
|
+
├── annotation/ # Variant annotation engine
|
|
111
|
+
├── classification/ # ACMG classification and combining rules
|
|
112
|
+
├── models/ # Data models (Variant, AnnotatedVariant, etc.)
|
|
113
|
+
├── prioritization/ # Scoring and prioritization engine
|
|
114
|
+
├── reporting/ # Report generation (JSON, CSV, PDF)
|
|
115
|
+
├── _internal/ # Internal utilities
|
|
116
|
+
├── protocols.py # Protocol interfaces
|
|
117
|
+
├── exceptions.py # Warning and exception hierarchy
|
|
118
|
+
├── cli.py # Command-line interface
|
|
119
|
+
└── py.typed # PEP 561 marker
|
|
120
|
+
```
|
vartriage-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Muhammad Abiodun SULAIMAN, Bolaji Fatai OYEYEMI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
vartriage-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vartriage
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A streaming pipeline library for identifying and classifying pathogenic genetic variants from VCF data
|
|
5
|
+
Project-URL: Homepage, https://github.com/Behordeun/vartriage
|
|
6
|
+
Project-URL: Documentation, https://github.com/Behordeun/vartriage#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/Behordeun/vartriage
|
|
8
|
+
Project-URL: Issues, https://github.com/Behordeun/vartriage/issues
|
|
9
|
+
Author: Muhammad Abiodun SULAIMAN, Bolaji Fatai OYEYEMI
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: acmg,bioinformatics,genomics,pathogenicity,variants,vcf
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: numpy<3.0,>=1.24.0
|
|
23
|
+
Requires-Dist: pysam<1.0,>=0.22.0
|
|
24
|
+
Provides-Extra: accelerated
|
|
25
|
+
Requires-Dist: polars<2.0,>=0.20.0; extra == 'accelerated'
|
|
26
|
+
Requires-Dist: pyranges<1.0,>=0.1.0; extra == 'accelerated'
|
|
27
|
+
Provides-Extra: all
|
|
28
|
+
Requires-Dist: polars<2.0,>=0.20.0; extra == 'all'
|
|
29
|
+
Requires-Dist: pyranges<1.0,>=0.1.0; extra == 'all'
|
|
30
|
+
Requires-Dist: reportlab<5.0,>=4.0; extra == 'all'
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: hypothesis<7.0,>=6.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: mypy<2.0,>=1.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest-cov<6.0,>=4.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: pytest<9.0,>=7.0; extra == 'dev'
|
|
36
|
+
Provides-Extra: docs
|
|
37
|
+
Requires-Dist: mkdocs-material<10.0,>=9.0; extra == 'docs'
|
|
38
|
+
Requires-Dist: mkdocs<2.0,>=1.5; extra == 'docs'
|
|
39
|
+
Requires-Dist: mkdocstrings[python]<1.0,>=0.24; extra == 'docs'
|
|
40
|
+
Provides-Extra: pdf
|
|
41
|
+
Requires-Dist: reportlab<5.0,>=4.0; extra == 'pdf'
|
|
42
|
+
Provides-Extra: test
|
|
43
|
+
Requires-Dist: hypothesis<7.0,>=6.0; extra == 'test'
|
|
44
|
+
Requires-Dist: pytest-cov<6.0,>=4.0; extra == 'test'
|
|
45
|
+
Requires-Dist: pytest<9.0,>=7.0; extra == 'test'
|
|
46
|
+
Description-Content-Type: text/markdown
|
|
47
|
+
|
|
48
|
+
# vartriage
|
|
49
|
+
|
|
50
|
+
Variant prioritization pipeline for whole-genome sequencing data. Reads a VCF, applies quality filters, annotates functional consequence and population frequency, computes pathogenicity scores, runs ACMG/AMP evidence classification, and writes a ranked candidate list in JSON, CSV, or PDF.
|
|
51
|
+
|
|
52
|
+
Processes 4M+ variant WGS files under 2GB memory via batched iterators.
|
|
53
|
+
|
|
54
|
+
## Install
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install vartriage
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
With faster annotation backends (polars + pyranges):
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install vartriage[accelerated]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
With PDF report support:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install vartriage[pdf]
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
All optional extras:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install vartriage[all]
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Usage
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
from pathlib import Path
|
|
82
|
+
from vartriage import (
|
|
83
|
+
Pipeline, PipelineConfig, AnnotationConfig,
|
|
84
|
+
PrioritizationConfig, QualityFilterConfig, ReportConfig,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
config = PipelineConfig(
|
|
88
|
+
vcf_path=Path("sample.vcf.gz"),
|
|
89
|
+
output_path=Path("candidates.json"),
|
|
90
|
+
quality_filter=QualityFilterConfig(min_qual=30.0),
|
|
91
|
+
annotation=AnnotationConfig(
|
|
92
|
+
gene_annotation_path=Path("gencode.v44.gtf"),
|
|
93
|
+
gnomad_path=Path("gnomad.v4.sites.tsv"),
|
|
94
|
+
clinvar_path=Path("clinvar_20240101.tsv"),
|
|
95
|
+
),
|
|
96
|
+
prioritization=PrioritizationConfig(
|
|
97
|
+
max_allele_frequency=0.01,
|
|
98
|
+
cadd_scores_path=Path("cadd_scores.tsv"),
|
|
99
|
+
revel_scores_path=Path("revel_scores.tsv"),
|
|
100
|
+
),
|
|
101
|
+
report=ReportConfig(output_format="json"),
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
pipeline = Pipeline(config)
|
|
105
|
+
pipeline.run()
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Individual stages work on their own:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from vartriage import VCFParser, QualityFilter, QualityFilterConfig
|
|
112
|
+
|
|
113
|
+
with VCFParser(Path("input.vcf.gz")) as parser:
|
|
114
|
+
qf = QualityFilter(QualityFilterConfig(min_qual=30.0))
|
|
115
|
+
for variant in qf.apply(iter(parser)):
|
|
116
|
+
print(f"{variant.chrom}:{variant.pos} {variant.ref}>{variant.alt}")
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Command Line
|
|
120
|
+
|
|
121
|
+
After installation, the `vartriage` command is available:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
vartriage --vcf sample.vcf.gz --output candidates.json
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
With annotation and scoring references:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
vartriage \
|
|
131
|
+
--vcf sample.vcf.gz \
|
|
132
|
+
--output report.json \
|
|
133
|
+
--output-format json \
|
|
134
|
+
--gene-annotation gencode.v44.gtf \
|
|
135
|
+
--gnomad gnomad.v4.sites.tsv \
|
|
136
|
+
--clinvar clinvar_20240101.tsv \
|
|
137
|
+
--cadd-scores cadd_scores.tsv \
|
|
138
|
+
--revel-scores revel_scores.tsv
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Run `vartriage --help` for all options.
|
|
142
|
+
|
|
143
|
+
## Pipeline stages
|
|
144
|
+
|
|
145
|
+
```text
|
|
146
|
+
VCFParser > QualityFilter > AnnotationEngine > PrioritizationEngine > ACMGClassifier > ReportGenerator
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Quality filtering
|
|
150
|
+
|
|
151
|
+
Drops variants where:
|
|
152
|
+
|
|
153
|
+
- `FILTER` is not `PASS` or `.`
|
|
154
|
+
- `QUAL` is below the threshold (default 20)
|
|
155
|
+
- `QUAL` field is missing (emits a warning)
|
|
156
|
+
|
|
157
|
+
Passing variants keep their original order.
|
|
158
|
+
|
|
159
|
+
### Annotation
|
|
160
|
+
|
|
161
|
+
Adds three annotations to each surviving variant:
|
|
162
|
+
|
|
163
|
+
**Functional consequence:** Looked up against gene models (GTF/GFF). Splice_Site applies within 2bp of an exon-intron boundary. When multiple transcripts disagree, the most damaging consequence wins. Severity ranking (highest first): Frameshift, Nonsense, Splice_Site, Missense, In_Frame_Insertion, In_Frame_Deletion, Synonymous, Intergenic.
|
|
164
|
+
|
|
165
|
+
**Population frequency:** Matched against gnomAD by (chrom, pos, ref, alt). Variants not found get `frequency_unknown=True` and a `MissingDataWarning`.
|
|
166
|
+
|
|
167
|
+
**ClinVar assertion:** Pathogenic, Likely_Pathogenic, VUS, Likely_Benign, or Benign when available.
|
|
168
|
+
|
|
169
|
+
### Prioritization
|
|
170
|
+
|
|
171
|
+
Two phases:
|
|
172
|
+
|
|
173
|
+
1. Frequency gate: drops variants with AF above the threshold (default 0.01). Variants marked `frequency_unknown` always pass.
|
|
174
|
+
2. Composite scoring: normalizes CADD Phred (divide by 99, cap at 1.0) and REVEL (already 0-1), then computes:
|
|
175
|
+
|
|
176
|
+
```text
|
|
177
|
+
composite = (REVEL x 0.6) + (CADD_normalized x 0.4)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Falls back to the single available score when only one source exists. Output sorted descending by composite rank; variants without scores go last.
|
|
181
|
+
|
|
182
|
+
### ACMG classification
|
|
183
|
+
|
|
184
|
+
Evidence tagging per ACMG/AMP 2015:
|
|
185
|
+
|
|
186
|
+
| Tag | Strength | Condition |
|
|
187
|
+
| ---- | ----------- | ----------------------------------------- |
|
|
188
|
+
| PVS1 | Very Strong | Nonsense or Frameshift |
|
|
189
|
+
| PM2 | Moderate | gnomAD AF < 0.0001 |
|
|
190
|
+
| PP3 | Supporting | REVEL > 0.7 |
|
|
191
|
+
| PP5 | Supporting | ClinVar Pathogenic, no conflicting Benign |
|
|
192
|
+
|
|
193
|
+
Tags combine per standard rules into: Pathogenic, Likely_Pathogenic, or VUS. If a data source is unavailable, the corresponding tag is omitted.
|
|
194
|
+
|
|
195
|
+
### Report output
|
|
196
|
+
|
|
197
|
+
Fields in all formats:
|
|
198
|
+
|
|
199
|
+
| Field | Description |
|
|
200
|
+
| -------------------------- | --------------------------- |
|
|
201
|
+
| `chromosome` | Chromosome name |
|
|
202
|
+
| `position` | 1-based position |
|
|
203
|
+
| `ref_allele` | Reference allele |
|
|
204
|
+
| `alt_allele` | Alternate allele |
|
|
205
|
+
| `functional_consequence` | Most severe consequence |
|
|
206
|
+
| `allele_frequency` | gnomAD AF (null if unknown) |
|
|
207
|
+
| `composite_rank` | Pathogenicity score 0-1 |
|
|
208
|
+
| `clinvar_assertion` | ClinVar significance |
|
|
209
|
+
| `acmg_classification` | Final classification |
|
|
210
|
+
| `evidence_tags` | Applied evidence codes |
|
|
211
|
+
|
|
212
|
+
Null values: `null` in JSON, empty in CSV, `N/A` in PDF.
|
|
213
|
+
|
|
214
|
+
## Configuration
|
|
215
|
+
|
|
216
|
+
### QualityFilterConfig
|
|
217
|
+
|
|
218
|
+
| Field | Type | Default | Range |
|
|
219
|
+
| ------------ | ----- | ------- | -------------- |
|
|
220
|
+
| `min_qual` | float | 20.0 | 0 to 1,000,000 |
|
|
221
|
+
|
|
222
|
+
### AnnotationConfig
|
|
223
|
+
|
|
224
|
+
| Field | Type | Default | Notes |
|
|
225
|
+
| ------------------------ | ---- | -------- | ---------------------- |
|
|
226
|
+
| `gene_annotation_path` | Path | required | GTF/GFF |
|
|
227
|
+
| `gnomad_path` | Path | required | TSV (see format below) |
|
|
228
|
+
| `clinvar_path` | Path | None | TSV (see format below) |
|
|
229
|
+
| `batch_size` | int | 10,000 | 1,000 to 100,000 |
|
|
230
|
+
|
|
231
|
+
### PrioritizationConfig
|
|
232
|
+
|
|
233
|
+
| Field | Type | Default | Range |
|
|
234
|
+
| ------------------------ | ----- | ------- | ---------------- |
|
|
235
|
+
| `max_allele_frequency` | float | 0.01 | 0.0 to 1.0 |
|
|
236
|
+
| `cadd_scores_path` | Path | None | CADD Phred TSV |
|
|
237
|
+
| `revel_scores_path` | Path | None | REVEL scores TSV |
|
|
238
|
+
| `batch_size` | int | 10,000 | 1,000 to 100,000 |
|
|
239
|
+
|
|
240
|
+
### ReportConfig
|
|
241
|
+
|
|
242
|
+
| Field | Type | Default | Options |
|
|
243
|
+
| ----------------- | ---- | ---------- | -------------------------------- |
|
|
244
|
+
| `output_format` | str | `"json"` | `"json"`, `"csv"`, `"pdf"` |
|
|
245
|
+
|
|
246
|
+
### MissingDataConfig
|
|
247
|
+
|
|
248
|
+
| Field | Type | Default | Notes |
|
|
249
|
+
| --------------------- | ---- | ------- | ----------------------------- |
|
|
250
|
+
| `warning_threshold` | int | 1000 | Summary warning when exceeded |
|
|
251
|
+
|
|
252
|
+
## Reference file formats
|
|
253
|
+
|
|
254
|
+
All reference files are tab-separated with a header row.
|
|
255
|
+
|
|
256
|
+
**gnomAD:**
|
|
257
|
+
|
|
258
|
+
```tsv
|
|
259
|
+
chrom pos ref alt af
|
|
260
|
+
chr1 12345 A G 0.00032
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**ClinVar:**
|
|
264
|
+
|
|
265
|
+
```tsv
|
|
266
|
+
chrom pos ref alt clinical_significance
|
|
267
|
+
chr1 12345 A G Pathogenic
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Recognized values: `Pathogenic`, `Likely pathogenic`, `Uncertain significance`, `Likely benign`, `Benign`.
|
|
271
|
+
|
|
272
|
+
**CADD / REVEL:**
|
|
273
|
+
|
|
274
|
+
```tsv
|
|
275
|
+
chrom pos ref alt score
|
|
276
|
+
chr1 12345 A G 28.5
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## Missing data handling
|
|
280
|
+
|
|
281
|
+
Variants absent from gnomAD are never dropped. They get `frequency_unknown=True` and pass the frequency filter. Same for ClinVar: no match means `clinvar_unknown=True`.
|
|
282
|
+
|
|
283
|
+
A `MissingDataWarning` is emitted per lookup miss. Once the total exceeds `warning_threshold`, a summary fires with the count and contributing sources.
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
pipeline.run()
|
|
287
|
+
acc = pipeline.warning_accumulator
|
|
288
|
+
print(f"{acc.total_count} missing data events across {acc.sources}")
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Dependencies
|
|
292
|
+
|
|
293
|
+
| Package | Required | Extra | Purpose |
|
|
294
|
+
| --------- | -------- | ----------------- | ----------------------------- |
|
|
295
|
+
| pysam | yes | n/a | VCF streaming (htslib) |
|
|
296
|
+
| numpy | yes | n/a | Score normalization |
|
|
297
|
+
| polars | no | `[accelerated]` | Batch frequency/ClinVar joins |
|
|
298
|
+
| pyranges | no | `[accelerated]` | Interval overlap queries |
|
|
299
|
+
| reportlab | no | `[pdf]` | PDF report generation |
|
|
300
|
+
|
|
301
|
+
Without optional extras, the library uses pure-Python fallbacks (dict-based lookups, bisect-based interval tree). Correct output either way; the accelerated path runs faster on large reference files.
|
|
302
|
+
|
|
303
|
+
## Error handling
|
|
304
|
+
|
|
305
|
+
Invalid configuration raises `ValueError` or `FileNotFoundError` at construction time, before any variants are processed.
|
|
306
|
+
|
|
307
|
+
During processing, missing reference data does not crash. The library assigns null values, sets flags, and continues. After a run, inspect `pipeline.warning_accumulator` to see how many lookup misses occurred and which sources were affected.
|
|
308
|
+
|
|
309
|
+
## Tests
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
pytest tests/ # full suite
|
|
313
|
+
pytest tests/ -m "not slow" # skip performance benchmarks
|
|
314
|
+
mypy --strict vartriage/ # type checking
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
Tests pass. mypy strict, 0 errors.
|
|
318
|
+
|
|
319
|
+
## Project layout
|
|
320
|
+
|
|
321
|
+
```text
|
|
322
|
+
vartriage/
|
|
323
|
+
pipeline.py # Top-level orchestrator
|
|
324
|
+
protocols.py # Protocol interfaces for swappable backends
|
|
325
|
+
io/ # VCF parsing, exceptions
|
|
326
|
+
filter/ # Quality-based exclusion
|
|
327
|
+
annotation/ # Consequence, frequency, ClinVar lookups
|
|
328
|
+
prioritization/ # AF gating + pathogenicity scoring
|
|
329
|
+
classification/ # ACMG evidence tagging + combining
|
|
330
|
+
reporting/ # JSON, CSV, PDF output
|
|
331
|
+
models/ # Dataclasses, enums, configs, warnings
|
|
332
|
+
_internal/ # Batch utils, interval tree, vectorized ops
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Requirements
|
|
336
|
+
|
|
337
|
+
- Python >= 3.10
|
|
338
|
+
- pysam >= 0.22.0
|
|
339
|
+
- numpy >= 1.24.0
|
|
340
|
+
|
|
341
|
+
## License
|
|
342
|
+
|
|
343
|
+
MIT
|