From 98764b024e80876aa75f884abcecabf96357093f Mon Sep 17 00:00:00 2001 From: VarenyaJ Date: Mon, 20 Jul 2026 09:44:48 -0400 Subject: [PATCH] fix: respect SimpleTerm.excluded in gyn_phenopacket's narrative feature Same bug already fixed in observer_phenopacket.py and viewpoint_phenopacket.py (PR6/#111), present here too since gyn_phenopacket.py was copied from the same original code before that fix existed. _narrative_feature() never read term.excluded, so fenominal's negation detection was silently dropped. Real fixture (Gwen_Sally_pretty.json) already has a negated finding ("No evidence of hydronephrosis"), so no new fixture needed. Verified the new regression test fails without the fix and passes with it. --- src/prenatalppkt/builders/gyn_phenopacket.py | 1 + tests/builders/test_gyn_phenopacket.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/prenatalppkt/builders/gyn_phenopacket.py b/src/prenatalppkt/builders/gyn_phenopacket.py index 2afda1d..ec323bb 100644 --- a/src/prenatalppkt/builders/gyn_phenopacket.py +++ b/src/prenatalppkt/builders/gyn_phenopacket.py @@ -44,6 +44,7 @@ def _hpo_resource(hpo_parser: HpoParser) -> pps2.Resource: def _narrative_feature(term) -> pps2.PhenotypicFeature: return pps2.PhenotypicFeature( type=pps2.OntologyClass(id=term.hpo_id, label=term.hpo_label), + excluded=term.excluded, description="Gyn exam impression", ) diff --git a/tests/builders/test_gyn_phenopacket.py b/tests/builders/test_gyn_phenopacket.py index d948991..5bf99d9 100644 --- a/tests/builders/test_gyn_phenopacket.py +++ b/tests/builders/test_gyn_phenopacket.py @@ -49,3 +49,21 @@ def test_gyn_phenopacket_no_accession_falls_back(hpo_parser, now_ts): assert pp.subject.id == "patient" assert pp.id == "gyn-exam" + + +def test_negated_narrative_finding_marked_excluded(hpo_parser, now_ts): + """Gwen Sally's impression explicitly documents an ABSENT finding + ("No evidence of hydronephrosis"). fenominal correctly flags this + SimpleTerm as excluded=True; the resulting PhenotypicFeature must + carry that same excluded=True rather than silently defaulting to + "observed/present" - same fix as observer_phenopacket.py's and + viewpoint_phenopacket.py's identical bug.""" + raw = json.loads((DATA_DIR / "Gwen_Sally_pretty.json").read_text()) + + pp = build_gyn_phenopacket(raw, hpo_parser, now_ts) + + hydronephrosis_features = [ + pf for pf in pp.phenotypic_features if pf.type.id == "HP:0000126" + ] + assert len(hydronephrosis_features) == 1 + assert hydronephrosis_features[0].excluded is True