Diff of /tests/test_ontology.py [000000] .. [f54d94]

Switch to side-by-side view

--- a
+++ b/tests/test_ontology.py
@@ -0,0 +1,156 @@
+# flake8: noqa: E501
+
+import pathlib
+
+import femr.ontology
+
+
+def create_fake_athena(tmp_path: pathlib.Path) -> pathlib.Path:
+    athena = tmp_path / "athena"
+    athena.mkdir()
+
+    concept = athena / "CONCEPT.csv"
+    concept.write_text(
+        """concept_id	concept_name	domain_id	vocabulary_id	concept_class_id	standard_concept	concept_code	valid_start_date	valid_end_date	invalid_reason
+37200198\tType 2 diabetes mellitus with mild nonproliferative diabetic retinopathy with macular edema, right eye\tCondition\tICD10CM\t7-char billing code\t\tE11.3211\t19700101\t20991231\t
+380097\tMacular edema due to diabetes mellitus\tCondition\tSNOMED\tClinical Finding\tS\t312912001\t20020131\t20991231
+4334884	Disorder of macula due to diabetes mellitus	Condition	SNOMED	Clinical Finding	S	232020009	20020131	20991231
+4174977	Retinopathy due to diabetes mellitus	Condition	SNOMED	Clinical Finding	S	4855003	20020131	20991231
+4208223	Disorder of macula of retina	Condition	SNOMED	Clinical Finding	S	312999006	20020131	20991231
+4290333	Macular retinal edema	Condition	SNOMED	Clinical Finding	S	37231002	20020131	20991231
+35626904	Retinal edema due to diabetes mellitus	Condition	SNOMED	Clinical Finding	S	770323005	20180731	20991231
+45757435	Mild nonproliferative retinopathy due to type 2 diabetes mellitus	Condition	SNOMED	Clinical Finding	S	138911000119106	20150131	20991231
+"""
+    )
+    relationship = athena / "CONCEPT_RELATIONSHIP.csv"
+    relationship.write_text(
+        """concept_id_1	concept_id_2	relationship_id	valid_start_date	valid_end_date	invalid_reason
+37200198	380097	Maps to	20171001	20991231
+37200198	1567956	Is a	20170428	20991231
+37200198	1567959	Is a	20170428	20991231
+37200198	45757435	Maps to	20171001	20991231
+37200198	1567961	Is a	20170428	20991231
+37200198	45552385	Is a	20170428	20991231
+35977781	35977781	Mapped from	20200913	20991231
+46135811	40642538	Has status	20220128	20991231
+46135811	35631990	Has Module	20220128	20991231"""
+    )
+
+    ancestor = athena / "CONCEPT_ANCESTOR.csv"
+    ancestor.write_text(
+        """ancestor_concept_id\tdescendant_concept_id\tmin_levels_of_separation\tmax_levels_of_separation
+373499	4334884	4	6
+442793	4334884	3	3
+255919	4334884	6	9
+433128	4334884	4	4
+4180628	4334884	6	8
+4209989	4334884	3	3
+441840	4334884	6	10
+4274025	4334884	5	9
+4082284	4334884	2	2
+4042836	4334884	5	7
+443767	4334884	2	2
+4038502	4334884	5	8
+4174977	4334884	1	1
+4334884	4334884	0	0
+4134440	4334884	5	7
+4247371	4334884	5	8
+375252	4334884	3	5
+4027883	4334884	4	4
+4208223	4334884	1	1
+378416	4334884	2	2
+4080992	4334884	4	6
+4162092	4334884	3	3
+255919	380097	7	10
+433128	380097	5	5
+442793	380097	4	4
+373499	380097	5	7
+4180628	380097	7	9
+4209989	380097	4	4
+37018677	380097	3	3
+441840	380097	5	11
+380097	380097	0	0
+4274025	380097	4	10
+372903	380097	2	2
+433595	380097	4	4
+4042836	380097	6	8
+4082284	380097	3	3
+443767	380097	3	3
+4038502	380097	6	9
+4174977	380097	2	2
+4334884	380097	1	1
+4134440	380097	6	8
+4247371	380097	6	9
+4290333	380097	1	1
+375252	380097	4	6
+4027883	380097	5	5
+4040388	380097	3	3
+4208223	380097	2	2
+35626904	380097	1	1
+378416	380097	3	3
+4080992	380097	5	7
+4162092	380097	4	4
+"""
+    )
+
+    return athena
+
+
+def test_only_athena(tmp_path: pathlib.Path) -> None:
+    fake_athena = create_fake_athena(tmp_path)
+
+    ontology = femr.ontology.Ontology(str(fake_athena))
+
+    assert (
+        ontology.get_description("ICD10CM/E11.3211")
+        == "Type 2 diabetes mellitus with mild nonproliferative diabetic retinopathy with macular edema, right eye"
+    )
+
+    assert ontology.get_parents("ICD10CM/E11.3211") == {"SNOMED/312912001", "SNOMED/138911000119106"}
+    assert ontology.get_parents("SNOMED/312912001") == {"SNOMED/37231002", "SNOMED/232020009", "SNOMED/770323005"}
+
+    assert ontology.get_all_parents("ICD10CM/E11.3211") == {
+        "SNOMED/37231002",
+        "SNOMED/138911000119106",
+        "SNOMED/4855003",
+        "SNOMED/312999006",
+        "SNOMED/312912001",
+        "ICD10CM/E11.3211",
+        "SNOMED/770323005",
+        "SNOMED/232020009",
+    }
+
+    assert ontology.get_children("SNOMED/312912001") == {"ICD10CM/E11.3211"}
+    assert ontology.get_children("SNOMED/37231002") == {"SNOMED/312912001"}
+
+    assert ontology.get_all_children("SNOMED/37231002") == {"ICD10CM/E11.3211", "SNOMED/312912001", "SNOMED/37231002"}
+
+
+def test_athena_and_custom(tmp_path: pathlib.Path) -> None:
+    fake_athena = create_fake_athena(tmp_path)
+
+    code_metadata = {
+        "CUSTOM/CustomDiabetes": {"description": "A nice diabetes code", "parent_codes": ["ICD10CM/E11.3211"]}
+    }
+
+    ontology = femr.ontology.Ontology(str(fake_athena), code_metadata)
+
+    assert ontology.get_description("CUSTOM/CustomDiabetes") == "A nice diabetes code"
+    assert ontology.get_all_parents("CUSTOM/CustomDiabetes") == {
+        "CUSTOM/CustomDiabetes",
+        "SNOMED/37231002",
+        "SNOMED/138911000119106",
+        "SNOMED/4855003",
+        "SNOMED/312999006",
+        "SNOMED/312912001",
+        "ICD10CM/E11.3211",
+        "SNOMED/770323005",
+        "SNOMED/232020009",
+    }
+
+    assert ontology.get_all_children("SNOMED/37231002") == {
+        "CUSTOM/CustomDiabetes",
+        "ICD10CM/E11.3211",
+        "SNOMED/312912001",
+        "SNOMED/37231002",
+    }