PGx: ClinPGx variant-based genes (PGX-008) and --guideline dpwg (PGX-025)
- fetch_sources.sh downloads ClinPGx clinicalVariants (CC BY-SA 4.0); pgx db build adds genotype-only variant-based genes (levels 1A-2B, level 3 for the parity list), rsIDs resolved from the manifest's probes: 70 genes in the DB. - pgx phenotype --guideline dpwg: CPIC mappings for CPIC genes (as ClinPGx curates DPWG), no phenotype for DPWG-only genes (flags dpwg_via_cpic_mapping / dpwg_mapping_not_available). K-029 updated.
This commit is contained in:
1 parent
4d9efab2fc
commit
cc89e9b334
8 files changed
+161
-10
No files matched your search
@@ -156,3 +156,46 @@ def test_pharmvar_core_alleles() -> None: # PGX-001 PharmVar source
|
||||
core = pharmvar_core_alleles("CYP2A6", {"CYP2A6-6.2/GRCh38/CYP2A6_9.vcf": vcf,
|
||||
"CYP2A6-6.2/GRCh38/CYP2A6_9.001.vcf": vcf}) # fmt: skip
|
||||
assert core == {"*9": [("chr19", 100, "A", "C", "rs1")]} # sub-alleles (*9.001) are not core definitions
|
||||
|
||||
|
||||
def test_clinpgx_variant_genes() -> None: # PGX-008 variant-based genes from ClinPGx
|
||||
from simurg.pgx.db import clinpgx_variant_genes
|
||||
|
||||
tsv = ("variant\tgene\ttype\tlevel of evidence\tchemicals\tphenotypes\n"
|
||||
"rs1\tOPRM1\tEfficacy\t3\tx\t\nrs2\tFOO\tEfficacy\t3\tx\t\nrs3\tFOO\tEfficacy\t2A\tx\t\n"
|
||||
"CYP2C9*3\tCYP2C9\tPK\t1A\tx\t\nrs4\tCYP2C9\tPK\t1A\tx\t\nrs5\tA,B\tPK\t1A\tx\t\n") # fmt: skip
|
||||
assert clinpgx_variant_genes(tsv, {"CYP2C9"}) == {"OPRM1": {"rs1"}, "FOO": {"rs3"}}
|
||||
|
||||
|
||||
def test_dpwg_mode(tmp_path: Path) -> None: # PGX-025
|
||||
from simurg.core.log import Reporter
|
||||
from simurg.pipeline.pgx_pheno import PhenoOptions, run_phenotype
|
||||
|
||||
src = tmp_path / "sources" / "cpic-20260101"
|
||||
src.mkdir(parents=True)
|
||||
t = _tables()
|
||||
t["gene"][0]["symbol"] = "CYP2D6"
|
||||
for tbl in ("sequence_location", "allele_definition", "allele", "gene_result"):
|
||||
for r in t[tbl]:
|
||||
r["genesymbol"] = "CYP2D6"
|
||||
for k, v in t.items():
|
||||
(src / f"{k}.json").write_text(json.dumps(v))
|
||||
(src / "source.json").write_text(json.dumps({"name": "CPIC", "version": "2026-01-01", "retrieved": "20260101"}))
|
||||
fa = tmp_path / "g.fa"
|
||||
fa.write_text(">chr1\n" + SEQ + "\n")
|
||||
r = CliRunner().invoke(app, ["pgx", "db", "build", "--sources", str(tmp_path / "sources"), "--fasta", str(fa),
|
||||
"--out", str(tmp_path / "db"), "--quiet"]) # fmt: skip
|
||||
assert r.exit_code == 0, r.output
|
||||
db = next((tmp_path / "db").glob("pgx_db-1-*.sqlite"))
|
||||
calls = tmp_path / "calls"
|
||||
calls.mkdir()
|
||||
(calls / "pgx_calls.json").write_text(json.dumps({"samples": [{"sample_id": "s1", "genes": [
|
||||
{"gene": "CYP2D6", "genotype": "*2/*2", "feasible_solutions": ["*2/*2"], "candidates": [
|
||||
{"genotype": "*2/*2", "score": 1.0, "raw_score": 1.0}]},
|
||||
{"gene": "CYP3A4", "genotype": "*1/*22", "feasible_solutions": ["*1/*22"], "candidates": []}]}]})) # fmt: skip
|
||||
rep = Reporter(command="t", quiet=True)
|
||||
assert run_phenotype(PhenoOptions(calls, db, guideline="dpwg"), rep) == 0
|
||||
doc = json.loads((calls / "s1.pgx.json").read_text())
|
||||
by = {g["gene"]: g for g in doc["genes"]}
|
||||
assert by["CYP2D6"]["phenotype"] == "Poor Metabolizer" and "dpwg_via_cpic_mapping" in by["CYP2D6"]["flags"]
|
||||
assert by["CYP3A4"]["phenotype"] is None and "dpwg_mapping_not_available" in by["CYP3A4"]["flags"]
|
||||
Reference in new issue
Block a user