haplohub-cli 2.2.0__tar.gz → 2.4.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.
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/.github/workflows/on_pr.yml +5 -5
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/.github/workflows/on_push_main.yml +5 -5
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/PKG-INFO +2 -2
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/_version.py +3 -3
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/commands/algorithm/result/__init__.py +20 -7
- haplohub_cli-2.4.0/haplohub_cli/commands/variant.py +124 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/formatters/algorithm.py +12 -6
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/formatters/sample.py +6 -4
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/formatters/variant.py +20 -3
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli.egg-info/PKG-INFO +2 -2
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli.egg-info/SOURCES.txt +2 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli.egg-info/requires.txt +1 -1
- haplohub_cli-2.4.0/haplohub_cli.egg-info/scm_file_list.json +69 -0
- haplohub_cli-2.4.0/haplohub_cli.egg-info/scm_version.json +8 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/pyproject.toml +1 -1
- haplohub_cli-2.2.0/haplohub_cli/commands/variant.py +0 -66
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/.github/dependabot.yml +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/.gitignore +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/.pre-commit-config.yaml +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/README.md +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/__init__.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/auth/__init__.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/auth/auth.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/auth/auth_web_server.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/auth/oauth_client.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/auth/tests/__init__.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/auth/tests/test_auth_web_server.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/auth/tests/test_token_storage.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/auth/token_storage.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/cli.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/commands/__init__.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/commands/algorithm/__init__.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/commands/cohort/__init__.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/commands/cohort/biomarker.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/commands/cohort/member/__init__.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/commands/cohort/member/report.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/commands/cohort/sample.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/commands/config.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/commands/file.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/commands/login.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/commands/metadata/__init__.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/commands/version.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/config/__init__.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/config/config.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/config/config_manager.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/core/__init__.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/core/api/__init__.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/core/api/client.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/core/checksum.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/core/network.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/core/slug.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/core/tests/__init__.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/core/tests/test_checksum.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/core/tests/test_network.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/core/tests/test_slug.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/core/types.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/core/upload.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/formatters/__init__.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/formatters/algorithm_result.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/formatters/biomarker.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/formatters/cohort.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/formatters/config.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/formatters/decorators.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/formatters/file.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/formatters/formatter_registry.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/formatters/generic.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/formatters/member.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/formatters/metadata.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/formatters/utils.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/settings.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/types/__init__.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/types/variant_range.py +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli.egg-info/dependency_links.txt +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli.egg-info/entry_points.txt +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli.egg-info/top_level.txt +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/setup.cfg +0 -0
- {haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/uv.lock +0 -0
|
@@ -13,15 +13,15 @@ jobs:
|
|
|
13
13
|
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
|
|
14
14
|
|
|
15
15
|
steps:
|
|
16
|
-
- uses: actions/checkout@
|
|
17
|
-
- uses: astral-sh/setup-uv@
|
|
16
|
+
- uses: actions/checkout@v6
|
|
17
|
+
- uses: astral-sh/setup-uv@v7
|
|
18
18
|
with:
|
|
19
19
|
python-version: ${{ matrix.python-version }}
|
|
20
20
|
- name: Install dependencies
|
|
21
21
|
run: uv sync --dev --no-sources
|
|
22
22
|
- name: Lint and format with ruff
|
|
23
23
|
run: |
|
|
24
|
-
ruff format --check .
|
|
25
|
-
ruff check .
|
|
24
|
+
uv run --no-sync ruff format --check .
|
|
25
|
+
uv run --no-sync ruff check .
|
|
26
26
|
- name: Run tests
|
|
27
|
-
run: uv run pytest -v
|
|
27
|
+
run: uv run --no-sync pytest -v
|
|
@@ -15,7 +15,7 @@ jobs:
|
|
|
15
15
|
name: Build python package
|
|
16
16
|
runs-on: ubuntu-latest
|
|
17
17
|
steps:
|
|
18
|
-
- uses: actions/checkout@
|
|
18
|
+
- uses: actions/checkout@v6
|
|
19
19
|
with:
|
|
20
20
|
fetch-depth: 0
|
|
21
21
|
- uses: hynek/build-and-inspect-python-package@v2
|
|
@@ -29,7 +29,7 @@ jobs:
|
|
|
29
29
|
needs: build
|
|
30
30
|
environment: testpypi
|
|
31
31
|
steps:
|
|
32
|
-
- uses: actions/download-artifact@
|
|
32
|
+
- uses: actions/download-artifact@v8
|
|
33
33
|
with:
|
|
34
34
|
name: Packages
|
|
35
35
|
path: dist
|
|
@@ -46,7 +46,7 @@ jobs:
|
|
|
46
46
|
needs: build
|
|
47
47
|
environment: pypi
|
|
48
48
|
steps:
|
|
49
|
-
- uses: actions/download-artifact@
|
|
49
|
+
- uses: actions/download-artifact@v8
|
|
50
50
|
with:
|
|
51
51
|
name: Packages
|
|
52
52
|
path: dist
|
|
@@ -60,12 +60,12 @@ jobs:
|
|
|
60
60
|
runs-on: ubuntu-latest
|
|
61
61
|
needs: publish-pypi
|
|
62
62
|
steps:
|
|
63
|
-
- uses: actions/download-artifact@
|
|
63
|
+
- uses: actions/download-artifact@v8
|
|
64
64
|
with:
|
|
65
65
|
name: Packages
|
|
66
66
|
path: dist
|
|
67
67
|
- name: Sign the dists with Sigstore
|
|
68
|
-
uses: sigstore/gh-action-sigstore-python@v3.
|
|
68
|
+
uses: sigstore/gh-action-sigstore-python@v3.3.0
|
|
69
69
|
with:
|
|
70
70
|
inputs: >-
|
|
71
71
|
./dist/*.tar.gz
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: haplohub-cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: HaploHub Command Line Interface
|
|
5
5
|
Author-email: Mike Polcari <mike@haplotype-labs.com>, Ilya Khrustalev <ilya@haplotype-labs.com>
|
|
6
6
|
Requires-Python: >=3.8
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
Requires-Dist: click>=8.1.8
|
|
9
|
-
Requires-Dist: haplohub
|
|
9
|
+
Requires-Dist: haplohub<3,>=2.2.0
|
|
10
10
|
Requires-Dist: pendulum>=3.0.0
|
|
11
11
|
Requires-Dist: requests>=2.32.0
|
|
12
12
|
Requires-Dist: rich>=13.9.4
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '2.
|
|
22
|
-
__version_tuple__ = version_tuple = (2,
|
|
21
|
+
__version__ = version = '2.4.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 4, 0)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'gc36ea6d15'
|
{haplohub_cli-2.2.0 → haplohub_cli-2.4.0}/haplohub_cli/commands/algorithm/result/__init__.py
RENAMED
|
@@ -31,26 +31,39 @@ def get(id):
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
@result.command()
|
|
34
|
-
@click.option("--algorithm
|
|
34
|
+
@click.option("--algorithm", "-a", type=str, required=True, help="The algorithm name (e.g. pgsc_calc)")
|
|
35
|
+
@click.option("--version", "-v", type=str, required=False, help="The algorithm version (defaults to the latest)")
|
|
35
36
|
@click.option("--cohort", "-c", type=types.HAPLOHUB_ID, required=True, help="The ID of the cohort")
|
|
37
|
+
@click.option("--member", "-m", type=types.HAPLOHUB_ID, required=False, help="The member id (its latest sample is scored)")
|
|
38
|
+
@click.option("--sample", "-s", type=types.HAPLOHUB_ID, required=False, help="The sample id to run on")
|
|
36
39
|
@click.option("--input-json", "-i", type=types.FILE_PATH, required=False, help="The input JSON")
|
|
37
40
|
@click.option("--input-file", "-f", type=types.FILE_PATH, required=False, help="The input file")
|
|
38
|
-
def create(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
def create(
|
|
42
|
+
algorithm: str,
|
|
43
|
+
cohort: str,
|
|
44
|
+
version: Optional[str] = None,
|
|
45
|
+
member: Optional[str] = None,
|
|
46
|
+
sample: Optional[str] = None,
|
|
47
|
+
input_json: Optional[str] = None,
|
|
48
|
+
input_file: Optional[str] = None,
|
|
49
|
+
):
|
|
42
50
|
if input_json is not None and input_file is not None:
|
|
43
51
|
raise click.ClickException("Only one of --input-json or --input-file can be provided")
|
|
44
52
|
|
|
45
53
|
if input_json is not None:
|
|
46
54
|
input_data = json.loads(input_json)
|
|
47
|
-
|
|
55
|
+
elif input_file is not None:
|
|
48
56
|
with open(input_file, "r") as f:
|
|
49
57
|
input_data = json.load(f)
|
|
58
|
+
else:
|
|
59
|
+
input_data = {}
|
|
50
60
|
|
|
51
61
|
request = CreateAlgorithmResultRequest(
|
|
52
|
-
|
|
62
|
+
algorithm=algorithm,
|
|
63
|
+
version=version,
|
|
53
64
|
cohort_id=cohort,
|
|
65
|
+
member_id=member,
|
|
66
|
+
sample_id=sample,
|
|
54
67
|
input=input_data,
|
|
55
68
|
)
|
|
56
69
|
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from haplohub import (
|
|
3
|
+
GetVariantRequest,
|
|
4
|
+
GwasTargetSchema,
|
|
5
|
+
HgvsTargetSchema,
|
|
6
|
+
RegionTargetSchema,
|
|
7
|
+
TargetsInner,
|
|
8
|
+
VariantFilterSchema,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
from haplohub_cli.core.api.client import client
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _selectors(clinvar: bool, gwas: bool) -> list[str] | None:
|
|
15
|
+
"""Build the selector list; None when no annotations were requested."""
|
|
16
|
+
selectors = []
|
|
17
|
+
if clinvar:
|
|
18
|
+
selectors.append("clinvar")
|
|
19
|
+
if gwas:
|
|
20
|
+
selectors.append("gwas")
|
|
21
|
+
return selectors or None
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@click.group()
|
|
25
|
+
def variant():
|
|
26
|
+
"""
|
|
27
|
+
Work with variants
|
|
28
|
+
"""
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@variant.command()
|
|
33
|
+
@click.argument("cohort_id", type=str)
|
|
34
|
+
@click.option("--sample", "-s", "sample_ids", type=str, multiple=True, required=True, help="Sample ID (repeatable)")
|
|
35
|
+
@click.option("--accession", "-a", type=str, required=True, help="Chromosome accession (e.g. NC_000001.11)")
|
|
36
|
+
@click.option("--start", type=int, required=True, help="Genomic start position")
|
|
37
|
+
@click.option("--end", type=int, required=True, help="Genomic end position")
|
|
38
|
+
@click.option("--reference", type=str, default=None, help="Reference allele")
|
|
39
|
+
@click.option("--alternate", type=str, default=None, help="Alternate allele")
|
|
40
|
+
@click.option("--call-state", type=click.Choice(["called", "all"]), default="called", help="Filter by call state")
|
|
41
|
+
@click.option("--clinvar", is_flag=True, default=False, help="Include ClinVar annotations")
|
|
42
|
+
@click.option("--gwas", is_flag=True, default=False, help="Include GWAS Catalog annotations")
|
|
43
|
+
def region(sample_ids, cohort_id, accession, start, end, reference, alternate, call_state, clinvar, gwas):
|
|
44
|
+
"""
|
|
45
|
+
Query variants by genomic region
|
|
46
|
+
"""
|
|
47
|
+
target = RegionTargetSchema(
|
|
48
|
+
accession=accession,
|
|
49
|
+
start=start,
|
|
50
|
+
end=end,
|
|
51
|
+
reference=reference,
|
|
52
|
+
alternate=alternate,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
request = GetVariantRequest(
|
|
56
|
+
sample_ids=list(sample_ids),
|
|
57
|
+
targets=[TargetsInner(target)],
|
|
58
|
+
filters=VariantFilterSchema(call_state=call_state),
|
|
59
|
+
selectors=_selectors(clinvar, gwas),
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
return client.variant.get_variant(cohort_id, request)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@variant.command()
|
|
66
|
+
@click.argument("cohort_id", type=str)
|
|
67
|
+
@click.option("--sample", "-s", "sample_ids", type=str, multiple=True, required=True, help="Sample ID (repeatable)")
|
|
68
|
+
@click.option("--hgvs", "-h", type=str, multiple=True, required=True, help="HGVS notation (repeatable)")
|
|
69
|
+
@click.option("--call-state", type=click.Choice(["called", "all"]), default="called", help="Filter by call state")
|
|
70
|
+
@click.option("--clinvar", is_flag=True, default=False, help="Include ClinVar annotations")
|
|
71
|
+
@click.option("--gwas", is_flag=True, default=False, help="Include GWAS Catalog annotations")
|
|
72
|
+
def hgvs(sample_ids, cohort_id, hgvs, call_state, clinvar, gwas):
|
|
73
|
+
"""
|
|
74
|
+
Query variants by HGVS notation
|
|
75
|
+
"""
|
|
76
|
+
targets = [TargetsInner(HgvsTargetSchema(value=v)) for v in hgvs]
|
|
77
|
+
|
|
78
|
+
request = GetVariantRequest(
|
|
79
|
+
sample_ids=list(sample_ids),
|
|
80
|
+
targets=targets,
|
|
81
|
+
filters=VariantFilterSchema(call_state=call_state),
|
|
82
|
+
selectors=_selectors(clinvar, gwas),
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
return client.variant.get_variant(cohort_id, request)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@variant.command()
|
|
89
|
+
@click.argument("cohort_id", type=str)
|
|
90
|
+
@click.option("--sample", "-s", "sample_ids", type=str, multiple=True, required=True, help="Sample ID (repeatable)")
|
|
91
|
+
@click.option("--gene", type=str, default=None, help="Mapped gene symbol (e.g. TCF7L2)")
|
|
92
|
+
@click.option("--trait-id", type=str, default=None, help="EFO trait id (e.g. EFO_0001360)")
|
|
93
|
+
@click.option("--rs", "rs_ids", type=str, multiple=True, help="rsID to genotype (repeatable)")
|
|
94
|
+
@click.option("--p-value-max", type=float, default=None, help="Keep only associations with p-value <= this")
|
|
95
|
+
@click.option("--limit", type=int, default=100, help="Max associations to resolve (most significant first)")
|
|
96
|
+
@click.option("--call-state", type=click.Choice(["called", "all"]), default="called", help="Filter by call state")
|
|
97
|
+
@click.option("--clinvar", is_flag=True, default=False, help="Also include ClinVar annotations")
|
|
98
|
+
def gwas(sample_ids, cohort_id, gene, trait_id, rs_ids, p_value_max, limit, call_state, clinvar):
|
|
99
|
+
"""
|
|
100
|
+
Genotype the SNPs of GWAS Catalog associations in a sample.
|
|
101
|
+
|
|
102
|
+
Selects associations by --gene, --trait-id and/or --rs (at least one required),
|
|
103
|
+
genotypes their SNP positions in the sample, and attaches the matching GWAS
|
|
104
|
+
associations to each result. Combine with --clinvar to also attach ClinVar.
|
|
105
|
+
"""
|
|
106
|
+
if not (gene or trait_id or rs_ids):
|
|
107
|
+
raise click.UsageError("Provide at least one of --gene, --trait-id or --rs.")
|
|
108
|
+
|
|
109
|
+
target = GwasTargetSchema(
|
|
110
|
+
gene=gene,
|
|
111
|
+
trait_id=trait_id,
|
|
112
|
+
rs_ids=list(rs_ids),
|
|
113
|
+
p_value_max=p_value_max,
|
|
114
|
+
limit=limit,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
request = GetVariantRequest(
|
|
118
|
+
sample_ids=list(sample_ids),
|
|
119
|
+
targets=[TargetsInner(target)],
|
|
120
|
+
filters=VariantFilterSchema(call_state=call_state),
|
|
121
|
+
selectors=_selectors(clinvar, gwas=True),
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
return client.variant.get_variant(cohort_id, request)
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
1
3
|
from haplohub import (
|
|
2
4
|
AlgorithmSchema,
|
|
5
|
+
AlgorithmVersionSchema,
|
|
3
6
|
PaginatedResponseAlgorithmSchema,
|
|
4
7
|
ResultResponseAlgorithmSchema,
|
|
5
8
|
)
|
|
@@ -9,14 +12,19 @@ from haplohub_cli.formatters import utils
|
|
|
9
12
|
from haplohub_cli.formatters.decorators import register
|
|
10
13
|
|
|
11
14
|
|
|
15
|
+
def _latest_version(version: Optional[AlgorithmVersionSchema]) -> str:
|
|
16
|
+
# Algorithms are identified by name now; a version is identified by its version string.
|
|
17
|
+
return version.version if version else "N/A"
|
|
18
|
+
|
|
19
|
+
|
|
12
20
|
@register(AlgorithmSchema)
|
|
13
21
|
def format_algorithm(data: AlgorithmSchema):
|
|
14
|
-
table = Table(title="Algorithm", caption=f"
|
|
15
|
-
table.add_column("Id")
|
|
22
|
+
table = Table(title="Algorithm", caption=f"Name: {data.name}")
|
|
16
23
|
table.add_column("Name")
|
|
17
24
|
table.add_column("Description")
|
|
18
25
|
table.add_column("Latest Version")
|
|
19
|
-
table.
|
|
26
|
+
table.add_column("Owner")
|
|
27
|
+
table.add_row(data.name, data.description, _latest_version(data.latest_version), data.owner)
|
|
20
28
|
return table
|
|
21
29
|
|
|
22
30
|
|
|
@@ -28,7 +36,6 @@ def format_single_algorithm(data: ResultResponseAlgorithmSchema):
|
|
|
28
36
|
@register(PaginatedResponseAlgorithmSchema)
|
|
29
37
|
def format_algorithms(data: PaginatedResponseAlgorithmSchema):
|
|
30
38
|
table = Table(title="Algorithms", caption=f"Total: {data.total_count}")
|
|
31
|
-
table.add_column("Id")
|
|
32
39
|
table.add_column("Name")
|
|
33
40
|
table.add_column("Description")
|
|
34
41
|
table.add_column("Latest Version")
|
|
@@ -36,10 +43,9 @@ def format_algorithms(data: PaginatedResponseAlgorithmSchema):
|
|
|
36
43
|
|
|
37
44
|
for item in data.items:
|
|
38
45
|
table.add_row(
|
|
39
|
-
utils.format_id(item.id),
|
|
40
46
|
item.name,
|
|
41
47
|
utils.truncate(item.description, 50),
|
|
42
|
-
|
|
48
|
+
_latest_version(item.latest_version),
|
|
43
49
|
utils.format_dt(item.created),
|
|
44
50
|
)
|
|
45
51
|
|
|
@@ -13,10 +13,10 @@ from haplohub_cli.formatters.decorators import register
|
|
|
13
13
|
def format_sample(data: SampleSchema):
|
|
14
14
|
table = Table(title="Sample", caption=f"Id: {utils.format_id(data.id)}")
|
|
15
15
|
table.add_column("Id")
|
|
16
|
-
table.add_column("
|
|
16
|
+
table.add_column("External ID")
|
|
17
17
|
table.add_column("Member ID")
|
|
18
18
|
table.add_column("Created")
|
|
19
|
-
table.add_row(utils.format_id(data.id), data.
|
|
19
|
+
table.add_row(utils.format_id(data.id), data.external_id, utils.format_id(data.member_id), utils.format_dt(data.created))
|
|
20
20
|
return table
|
|
21
21
|
|
|
22
22
|
|
|
@@ -24,12 +24,14 @@ def format_sample(data: SampleSchema):
|
|
|
24
24
|
def format_samples(data: PaginatedResponseSampleSchema):
|
|
25
25
|
table = Table(title="Samples", caption=f"Total: {data.total_count}")
|
|
26
26
|
table.add_column("Id")
|
|
27
|
-
table.add_column("
|
|
27
|
+
table.add_column("External ID")
|
|
28
28
|
table.add_column("Member ID")
|
|
29
29
|
table.add_column("Created")
|
|
30
30
|
|
|
31
31
|
for item in data.items:
|
|
32
|
-
table.add_row(
|
|
32
|
+
table.add_row(
|
|
33
|
+
utils.format_id(item.id), item.external_id, utils.format_id(item.member_id), utils.format_dt(item.created)
|
|
34
|
+
)
|
|
33
35
|
|
|
34
36
|
return table
|
|
35
37
|
|
|
@@ -16,10 +16,11 @@ def format_variant_results(data: ResultListResponseVariantResultSchema):
|
|
|
16
16
|
table.add_column("Sample")
|
|
17
17
|
table.add_column("Called")
|
|
18
18
|
table.add_column("Dosage")
|
|
19
|
+
table.add_column("Annotations")
|
|
19
20
|
|
|
20
21
|
for item in data.items:
|
|
21
22
|
if item.error_message:
|
|
22
|
-
table.add_row(item.target.input, f"[red]{item.error_message}[/red]", "", "", "", "", "", "", "")
|
|
23
|
+
table.add_row(item.target.input, f"[red]{item.error_message}[/red]", "", "", "", "", "", "", "", "")
|
|
23
24
|
continue
|
|
24
25
|
|
|
25
26
|
variant = item.variant
|
|
@@ -30,9 +31,10 @@ def format_variant_results(data: ResultListResponseVariantResultSchema):
|
|
|
30
31
|
reference = variant.reference or "" if variant else ""
|
|
31
32
|
alternate = ", ".join(variant.alternate) if variant and variant.alternate else ""
|
|
32
33
|
quality = f"{variant.quality:.4f}" if variant and variant.quality is not None else ""
|
|
34
|
+
annotations = _format_annotations(item.attachments)
|
|
33
35
|
|
|
34
36
|
if not samples:
|
|
35
|
-
table.add_row(item.target.input, accession, position, reference, alternate, quality, "", "", "")
|
|
37
|
+
table.add_row(item.target.input, accession, position, reference, alternate, quality, "", "", "", annotations)
|
|
36
38
|
else:
|
|
37
39
|
for i, sample in enumerate(samples):
|
|
38
40
|
target_col = item.target.input if i == 0 else ""
|
|
@@ -41,10 +43,25 @@ def format_variant_results(data: ResultListResponseVariantResultSchema):
|
|
|
41
43
|
ref_col = reference if i == 0 else ""
|
|
42
44
|
alt_col = alternate if i == 0 else ""
|
|
43
45
|
qual_col = quality if i == 0 else ""
|
|
46
|
+
ann_col = annotations if i == 0 else ""
|
|
44
47
|
|
|
45
48
|
is_called = f"[green]{sample.is_called}[/green]" if sample.is_called else f"[red]{sample.is_called}[/red]"
|
|
46
49
|
dosage = str(sample.dosage) if sample.dosage is not None else ""
|
|
47
50
|
|
|
48
|
-
table.add_row(
|
|
51
|
+
table.add_row(
|
|
52
|
+
target_col, acc_col, pos_col, ref_col, alt_col, qual_col, sample.sample_id, is_called, dosage, ann_col
|
|
53
|
+
)
|
|
49
54
|
|
|
50
55
|
return table
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _format_annotations(attachments) -> str:
|
|
59
|
+
"""Summarize per-source attachment counts, e.g. "clinvar:1 gwas:5"."""
|
|
60
|
+
if attachments is None:
|
|
61
|
+
return ""
|
|
62
|
+
parts = []
|
|
63
|
+
for source in ("clinvar", "gwas"):
|
|
64
|
+
rows = getattr(attachments, source, None) or []
|
|
65
|
+
if rows:
|
|
66
|
+
parts.append(f"{source}:{len(rows)}")
|
|
67
|
+
return " ".join(parts)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: haplohub-cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: HaploHub Command Line Interface
|
|
5
5
|
Author-email: Mike Polcari <mike@haplotype-labs.com>, Ilya Khrustalev <ilya@haplotype-labs.com>
|
|
6
6
|
Requires-Python: >=3.8
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
Requires-Dist: click>=8.1.8
|
|
9
|
-
Requires-Dist: haplohub
|
|
9
|
+
Requires-Dist: haplohub<3,>=2.2.0
|
|
10
10
|
Requires-Dist: pendulum>=3.0.0
|
|
11
11
|
Requires-Dist: requests>=2.32.0
|
|
12
12
|
Requires-Dist: rich>=13.9.4
|
|
@@ -15,6 +15,8 @@ haplohub_cli.egg-info/SOURCES.txt
|
|
|
15
15
|
haplohub_cli.egg-info/dependency_links.txt
|
|
16
16
|
haplohub_cli.egg-info/entry_points.txt
|
|
17
17
|
haplohub_cli.egg-info/requires.txt
|
|
18
|
+
haplohub_cli.egg-info/scm_file_list.json
|
|
19
|
+
haplohub_cli.egg-info/scm_version.json
|
|
18
20
|
haplohub_cli.egg-info/top_level.txt
|
|
19
21
|
haplohub_cli/auth/__init__.py
|
|
20
22
|
haplohub_cli/auth/auth.py
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"files": [
|
|
3
|
+
".pre-commit-config.yaml",
|
|
4
|
+
"README.md",
|
|
5
|
+
"uv.lock",
|
|
6
|
+
"pyproject.toml",
|
|
7
|
+
".gitignore",
|
|
8
|
+
"haplohub_cli/__init__.py",
|
|
9
|
+
"haplohub_cli/settings.py",
|
|
10
|
+
"haplohub_cli/cli.py",
|
|
11
|
+
"haplohub_cli/commands/__init__.py",
|
|
12
|
+
"haplohub_cli/commands/version.py",
|
|
13
|
+
"haplohub_cli/commands/config.py",
|
|
14
|
+
"haplohub_cli/commands/file.py",
|
|
15
|
+
"haplohub_cli/commands/variant.py",
|
|
16
|
+
"haplohub_cli/commands/login.py",
|
|
17
|
+
"haplohub_cli/commands/cohort/biomarker.py",
|
|
18
|
+
"haplohub_cli/commands/cohort/__init__.py",
|
|
19
|
+
"haplohub_cli/commands/cohort/sample.py",
|
|
20
|
+
"haplohub_cli/commands/cohort/member/__init__.py",
|
|
21
|
+
"haplohub_cli/commands/cohort/member/report.py",
|
|
22
|
+
"haplohub_cli/commands/metadata/__init__.py",
|
|
23
|
+
"haplohub_cli/commands/algorithm/__init__.py",
|
|
24
|
+
"haplohub_cli/commands/algorithm/result/__init__.py",
|
|
25
|
+
"haplohub_cli/core/network.py",
|
|
26
|
+
"haplohub_cli/core/__init__.py",
|
|
27
|
+
"haplohub_cli/core/checksum.py",
|
|
28
|
+
"haplohub_cli/core/slug.py",
|
|
29
|
+
"haplohub_cli/core/upload.py",
|
|
30
|
+
"haplohub_cli/core/types.py",
|
|
31
|
+
"haplohub_cli/core/api/__init__.py",
|
|
32
|
+
"haplohub_cli/core/api/client.py",
|
|
33
|
+
"haplohub_cli/core/tests/test_checksum.py",
|
|
34
|
+
"haplohub_cli/core/tests/__init__.py",
|
|
35
|
+
"haplohub_cli/core/tests/test_slug.py",
|
|
36
|
+
"haplohub_cli/core/tests/test_network.py",
|
|
37
|
+
"haplohub_cli/auth/__init__.py",
|
|
38
|
+
"haplohub_cli/auth/token_storage.py",
|
|
39
|
+
"haplohub_cli/auth/auth.py",
|
|
40
|
+
"haplohub_cli/auth/oauth_client.py",
|
|
41
|
+
"haplohub_cli/auth/auth_web_server.py",
|
|
42
|
+
"haplohub_cli/auth/tests/test_token_storage.py",
|
|
43
|
+
"haplohub_cli/auth/tests/__init__.py",
|
|
44
|
+
"haplohub_cli/auth/tests/test_auth_web_server.py",
|
|
45
|
+
"haplohub_cli/config/__init__.py",
|
|
46
|
+
"haplohub_cli/config/config_manager.py",
|
|
47
|
+
"haplohub_cli/config/config.py",
|
|
48
|
+
"haplohub_cli/formatters/biomarker.py",
|
|
49
|
+
"haplohub_cli/formatters/__init__.py",
|
|
50
|
+
"haplohub_cli/formatters/algorithm.py",
|
|
51
|
+
"haplohub_cli/formatters/config.py",
|
|
52
|
+
"haplohub_cli/formatters/file.py",
|
|
53
|
+
"haplohub_cli/formatters/utils.py",
|
|
54
|
+
"haplohub_cli/formatters/member.py",
|
|
55
|
+
"haplohub_cli/formatters/cohort.py",
|
|
56
|
+
"haplohub_cli/formatters/decorators.py",
|
|
57
|
+
"haplohub_cli/formatters/formatter_registry.py",
|
|
58
|
+
"haplohub_cli/formatters/metadata.py",
|
|
59
|
+
"haplohub_cli/formatters/variant.py",
|
|
60
|
+
"haplohub_cli/formatters/algorithm_result.py",
|
|
61
|
+
"haplohub_cli/formatters/sample.py",
|
|
62
|
+
"haplohub_cli/formatters/generic.py",
|
|
63
|
+
"haplohub_cli/types/__init__.py",
|
|
64
|
+
"haplohub_cli/types/variant_range.py",
|
|
65
|
+
".github/dependabot.yml",
|
|
66
|
+
".github/workflows/on_pr.yml",
|
|
67
|
+
".github/workflows/on_push_main.yml"
|
|
68
|
+
]
|
|
69
|
+
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import click
|
|
2
|
-
from haplohub import GetVariantRequest, HgvsTargetSchema, RegionTargetSchema, TargetsInner, VariantFilterSchema
|
|
3
|
-
|
|
4
|
-
from haplohub_cli.core.api.client import client
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@click.group()
|
|
8
|
-
def variant():
|
|
9
|
-
"""
|
|
10
|
-
Work with variants
|
|
11
|
-
"""
|
|
12
|
-
pass
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@variant.command()
|
|
16
|
-
@click.argument("cohort_id", type=str)
|
|
17
|
-
@click.option("--sample", "-s", "sample_ids", type=str, multiple=True, required=True, help="Sample ID (repeatable)")
|
|
18
|
-
@click.option("--accession", "-a", type=str, required=True, help="Chromosome accession (e.g. NC_000001.11)")
|
|
19
|
-
@click.option("--start", type=int, required=True, help="Genomic start position")
|
|
20
|
-
@click.option("--end", type=int, required=True, help="Genomic end position")
|
|
21
|
-
@click.option("--reference", type=str, default=None, help="Reference allele")
|
|
22
|
-
@click.option("--alternate", type=str, default=None, help="Alternate allele")
|
|
23
|
-
@click.option("--call-state", type=click.Choice(["called", "all"]), default="called", help="Filter by call state")
|
|
24
|
-
@click.option("--clinvar", is_flag=True, default=False, help="Include ClinVar annotations")
|
|
25
|
-
def region(sample_ids, cohort_id, accession, start, end, reference, alternate, call_state, clinvar):
|
|
26
|
-
"""
|
|
27
|
-
Query variants by genomic region
|
|
28
|
-
"""
|
|
29
|
-
target = RegionTargetSchema(
|
|
30
|
-
accession=accession,
|
|
31
|
-
start=start,
|
|
32
|
-
end=end,
|
|
33
|
-
reference=reference,
|
|
34
|
-
alternate=alternate,
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
request = GetVariantRequest(
|
|
38
|
-
sample_ids=list(sample_ids),
|
|
39
|
-
targets=[TargetsInner(target)],
|
|
40
|
-
filters=VariantFilterSchema(call_state=call_state),
|
|
41
|
-
selectors=["clinvar"] if clinvar else None,
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
return client.variant.get_variant(cohort_id, request)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
@variant.command()
|
|
48
|
-
@click.argument("cohort_id", type=str)
|
|
49
|
-
@click.option("--sample", "-s", "sample_ids", type=str, multiple=True, required=True, help="Sample ID (repeatable)")
|
|
50
|
-
@click.option("--hgvs", "-h", type=str, multiple=True, required=True, help="HGVS notation (repeatable)")
|
|
51
|
-
@click.option("--call-state", type=click.Choice(["called", "all"]), default="called", help="Filter by call state")
|
|
52
|
-
@click.option("--clinvar", is_flag=True, default=False, help="Include ClinVar annotations")
|
|
53
|
-
def hgvs(sample_ids, cohort_id, hgvs, call_state, clinvar):
|
|
54
|
-
"""
|
|
55
|
-
Query variants by HGVS notation
|
|
56
|
-
"""
|
|
57
|
-
targets = [TargetsInner(HgvsTargetSchema(value=v)) for v in hgvs]
|
|
58
|
-
|
|
59
|
-
request = GetVariantRequest(
|
|
60
|
-
sample_ids=list(sample_ids),
|
|
61
|
-
targets=targets,
|
|
62
|
-
filters=VariantFilterSchema(call_state=call_state),
|
|
63
|
-
selectors=["clinvar"] if clinvar else None,
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
return client.variant.get_variant(cohort_id, request)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|