PGx phenotypes: pgx phenotype|annotate (PGX-024..028, CLI-034)
CPIC lookups by allele function counts or activity values (duplications N x activity, *5/*0 = 0, total-score fallback), Indeterminate when feasible solutions disagree or an allele is not in the guideline; per-sample simurg.pgx/1 JSON and diplotype_annotations.tsv with PGX-026 metadata lines. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01814GKVzZVL3FuF3DeiZXhv
This commit is contained in:
1 parent
ef1a608ee8
commit
0215af9c9c
7 files changed
+338
-1
No files matched your search
@@ -0,0 +1,36 @@
|
||||
"""Diplotype → phenotype (spec PGX-024, PGX-025)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
|
||||
from simurg.pgx.phenotype import build_table, gene_phenotype, phenotype
|
||||
|
||||
ACT_ROWS = [(json.dumps({"1.0": 2}), "2.0", "Normal Metabolizer"), (json.dumps({"0.0": 1, "1.0": 1}), "1.0",
|
||||
"Intermediate Metabolizer"), (json.dumps({"0.0": 2}), "0.0", "Poor Metabolizer"),
|
||||
(json.dumps({"1.0": 1, "2.0": 1}), "3.0", "Ultrarapid Metabolizer")] # fmt: skip
|
||||
ACT_ALLELES = [("*1", "Normal function", "1.0"), ("*4", "No function", "0.0"), ("*10", "Decreased function", "0.25")]
|
||||
FUNC_ROWS = [(json.dumps({"Normal function": 2}), "n/a", "Normal Metabolizer"),
|
||||
(json.dumps({"Normal function": 1, "No function": 1}), "n/a", "Intermediate Metabolizer")] # fmt: skip
|
||||
FUNC_ALLELES = [("*1", "Normal function", None), ("*2", "No function", None)]
|
||||
|
||||
|
||||
def test_activity_genes() -> None:
|
||||
t = build_table("CYP2D6", ACT_ROWS, ACT_ALLELES)
|
||||
assert phenotype(t, ("*1", "*4")).phenotype == "Intermediate Metabolizer"
|
||||
r = phenotype(t, ("*1x2", "*1")) # duplication: 2 × activity
|
||||
assert r.phenotype == "Ultrarapid Metabolizer" and r.activity_score == 3.0
|
||||
assert phenotype(t, ("*1", "*5")).phenotype == "Intermediate Metabolizer" # *5 = whole-gene deletion
|
||||
r = phenotype(t, ("*1", "*10")) # key absent → largest tabulated total ≤ 1.25
|
||||
assert r.phenotype == "Intermediate Metabolizer" and r.activity_score == 1.25
|
||||
r = phenotype(t, ("*1", "*99")) # PGX-024: unknown allele never crashes
|
||||
assert r.phenotype == "Indeterminate" and "phenotype_not_in_guideline" in r.flags
|
||||
|
||||
|
||||
def test_function_genes_and_disagreement() -> None: # PGX-025
|
||||
t = build_table("CYP2C19", FUNC_ROWS, FUNC_ALLELES)
|
||||
assert phenotype(t, ("*2", "*1")).phenotype == "Intermediate Metabolizer"
|
||||
res, per = gene_phenotype(t, [("*1", "*1"), ("*1", "*2")])
|
||||
assert res.phenotype == "Indeterminate" and per == ["Normal Metabolizer", "Intermediate Metabolizer"]
|
||||
res, per = gene_phenotype(t, [("*1", "*2"), ("*2", "*1")])
|
||||
assert res.phenotype == "Intermediate Metabolizer" and per == []
|
||||
Reference in new issue
Block a user