Skip to content

Commit 1ced119

Browse files
committed
Added DiagnosticTestType mapping class for resolving test type descriptions to valid value IDs
1 parent 33f911c commit 1ced119

File tree

4 files changed

+96
-117
lines changed

4 files changed

+96
-117
lines changed

classes/diagnostic_test_type.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
class DiagnosticTestType:
2+
"""
3+
Maps descriptive diagnostic test types to valid value IDs.
4+
Extend or replace these with values pulled from the actual codebook or database.
5+
"""
6+
7+
_mapping = {
8+
"pcr": 3001,
9+
"antigen": 3002,
10+
"lateral flow": 3003,
11+
# Add more mappings as needed
12+
}
13+
14+
@classmethod
15+
def get_valid_value_id(cls, description: str) -> int:
16+
key = description.strip().lower()
17+
if key not in cls._mapping:
18+
raise ValueError(f"Unknown diagnostic test type: '{description}'")
19+
return cls._mapping[key]

utils/oracle/mock_selection_builder.py

Lines changed: 31 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,19 @@
77

88

99
# Add helper class stubs below
10-
class WhichDiagnosticTest:
10+
class DiagnosticTestType:
1111
"""
12-
Test stub that maps criteria values to normalized diagnostic test selection keys.
13-
Used by _add_join_to_diagnostic_tests for test harness evaluation.
12+
Mock mapping of diagnostic test type names to valid value IDs.
1413
"""
1514

16-
ANY_TEST_IN_ANY_EPISODE = "any_test_in_any_episode"
17-
ANY_TEST_IN_LATEST_EPISODE = "any_test_in_latest_episode"
18-
ONLY_TEST_IN_LATEST_EPISODE = "only_test_in_latest_episode"
19-
ONLY_NOT_VOID_TEST_IN_LATEST_EPISODE = "only_not_void_test_in_latest_episode"
20-
LATEST_TEST_IN_LATEST_EPISODE = "latest_test_in_latest_episode"
21-
LATEST_NOT_VOID_TEST_IN_LATEST_EPISODE = "latest_not_void_test_in_latest_episode"
22-
EARLIEST_NOT_VOID_TEST_IN_LATEST_EPISODE = (
23-
"earliest_not_void_test_in_latest_episode"
24-
)
25-
EARLIER_TEST_IN_LATEST_EPISODE = "earlier_test_in_latest_episode"
26-
LATER_TEST_IN_LATEST_EPISODE = "later_test_in_latest_episode"
27-
2815
_mapping = {
29-
"any_test_in_any_episode": ANY_TEST_IN_ANY_EPISODE,
30-
"any_test_in_latest_episode": ANY_TEST_IN_LATEST_EPISODE,
31-
"only_test_in_latest_episode": ONLY_TEST_IN_LATEST_EPISODE,
32-
"only_not_void_test_in_latest_episode": ONLY_NOT_VOID_TEST_IN_LATEST_EPISODE,
33-
"latest_test_in_latest_episode": LATEST_TEST_IN_LATEST_EPISODE,
34-
"latest_not_void_test_in_latest_episode": LATEST_NOT_VOID_TEST_IN_LATEST_EPISODE,
35-
"earliest_not_void_test_in_latest_episode": EARLIEST_NOT_VOID_TEST_IN_LATEST_EPISODE,
36-
"earlier_test_in_latest_episode": EARLIER_TEST_IN_LATEST_EPISODE,
37-
"later_test_in_latest_episode": LATER_TEST_IN_LATEST_EPISODE,
16+
"pcr": 3001,
17+
"antigen": 3002,
18+
"lateral flow": 3003,
3819
}
3920

4021
@classmethod
41-
def from_description(cls, description: str) -> str:
22+
def get_valid_value_id(cls, description: str) -> int:
4223
key = description.strip().lower()
4324
if key not in cls._mapping:
4425
raise ValueError(f"Unknown diagnostic test type: {description}")
@@ -92,79 +73,35 @@ def _add_join_to_latest_episode(self) -> None:
9273
# Replace this with the one you want to test,
9374
# then use utils/oracle/test_subject_criteria_dev.py to run your scenarios
9475

95-
def _add_join_to_diagnostic_tests(self) -> None:
76+
def _add_criteria_diagnostic_test_type(self, proposed_or_confirmed: str) -> None:
77+
"""
78+
Filters diagnostic tests by type—proposed or confirmed.
79+
Requires prior join to external_tests_t (xt aliasing assumed).
80+
"""
9681
try:
97-
which = WhichDiagnosticTest.from_description(self.criteria_value)
9882
idx = getattr(self, "criteria_index", 0)
9983
xt = f"xt{idx}"
100-
xtp = f"xt{idx - 1}"
101-
102-
self.sql_from.append(
103-
f"INNER JOIN external_tests_t {xt} ON {xt}.screening_subject_id = ss.screening_subject_id"
104-
)
105-
106-
if which == WhichDiagnosticTest.ANY_TEST_IN_ANY_EPISODE:
107-
return
108-
109-
self._add_join_to_latest_episode()
110-
111-
handlers = {
112-
WhichDiagnosticTest.ANY_TEST_IN_LATEST_EPISODE: self._handle_any_test_in_latest_episode,
113-
WhichDiagnosticTest.ONLY_TEST_IN_LATEST_EPISODE: self._handle_only_test_in_latest_episode,
114-
WhichDiagnosticTest.ONLY_NOT_VOID_TEST_IN_LATEST_EPISODE: self._handle_only_test_in_latest_episode,
115-
WhichDiagnosticTest.LATEST_TEST_IN_LATEST_EPISODE: self._handle_latest_test_in_latest_episode,
116-
WhichDiagnosticTest.LATEST_NOT_VOID_TEST_IN_LATEST_EPISODE: self._handle_latest_test_in_latest_episode,
117-
WhichDiagnosticTest.EARLIEST_NOT_VOID_TEST_IN_LATEST_EPISODE: self._handle_earliest_test_in_latest_episode,
118-
WhichDiagnosticTest.EARLIER_TEST_IN_LATEST_EPISODE: self._handle_earlier_or_later_test,
119-
WhichDiagnosticTest.LATER_TEST_IN_LATEST_EPISODE: self._handle_earlier_or_later_test,
120-
}
121-
122-
if which in handlers:
123-
handlers[which](which, xt, xtp)
84+
85+
if proposed_or_confirmed == "proposed":
86+
column = f"{xt}.proposed_type_id"
87+
elif proposed_or_confirmed == "confirmed":
88+
column = f"{xt}.confirmed_type_id"
12489
else:
125-
raise ValueError(f"Unsupported diagnostic test type: {which}")
90+
raise SelectionBuilderException(
91+
self.criteria_key_name, self.criteria_value
92+
)
12693

127-
except Exception:
128-
raise SelectionBuilderException(self.criteria_key_name, self.criteria_value)
94+
self.sql_where.append(f"AND {column} ")
95+
96+
value = self.criteria_value.strip().lower()
97+
if value == "null":
98+
self.sql_where.append("IS NULL")
99+
elif value == "not null":
100+
self.sql_where.append("IS NOT NULL")
101+
else:
102+
comparator = self.criteria_comparator
103+
type_id = DiagnosticTestType.get_valid_value_id(self.criteria_value)
104+
self.sql_where.append(f"{comparator} {type_id}")
129105

130-
def _handle_any_test_in_latest_episode(self, which, xt, _):
131-
self.sql_from.append(f"AND {xt}.subject_epis_id = ep.subject_epis_id")
132-
133-
def _handle_only_test_in_latest_episode(self, which, xt, _):
134-
self.sql_from.append(f"AND {xt}.subject_epis_id = ep.subject_epis_id")
135-
if which == WhichDiagnosticTest.ONLY_NOT_VOID_TEST_IN_LATEST_EPISODE:
136-
self.sql_from.append(f"AND {xt}.void = 'N'")
137-
self.sql_from.append(
138-
f"""AND NOT EXISTS (
139-
SELECT 'xto' FROM external_tests_t xto
140-
WHERE xto.screening_subject_id = ss.screening_subject_id
141-
{'AND xto.void = \'N\'' if which == WhichDiagnosticTest.ONLY_NOT_VOID_TEST_IN_LATEST_EPISODE else ''}
142-
AND xto.subject_epis_id = ep.subject_epis_id
143-
AND xto.ext_test_id != {xt}.ext_test_id )"""
144-
)
145-
146-
def _handle_latest_test_in_latest_episode(self, which, xt, _):
147-
self.sql_from.append(
148-
f"""AND {xt}.ext_test_id = (
149-
SELECT MAX(xtx.ext_test_id) FROM external_tests_t xtx
150-
WHERE xtx.screening_subject_id = ss.screening_subject_id
151-
{'AND xtx.void = \'N\'' if which == WhichDiagnosticTest.LATEST_NOT_VOID_TEST_IN_LATEST_EPISODE else ''}
152-
AND xtx.subject_epis_id = ep.subject_epis_id )"""
153-
)
154-
155-
def _handle_earliest_test_in_latest_episode(self, which, xt, _):
156-
self.sql_from.append(
157-
f"""AND {xt}.ext_test_id = (
158-
SELECT MIN(xtn.ext_test_id) FROM external_tests_t xtn
159-
WHERE xtn.screening_subject_id = ss.screening_subject_id
160-
AND xtn.void = 'N'
161-
AND xtn.subject_epis_id = ep.subject_epis_id )"""
162-
)
163-
164-
def _handle_earlier_or_later_test(self, which, xt, xtp):
165-
if getattr(self, "criteria_index", 0) == 0:
106+
except Exception:
166107
raise SelectionBuilderException(self.criteria_key_name, self.criteria_value)
167-
comparator = (
168-
"<" if which == WhichDiagnosticTest.EARLIER_TEST_IN_LATEST_EPISODE else ">"
169-
)
170-
self.sql_from.append(f"AND {xt}.ext_test_id {comparator} {xtp}.ext_test_id")

utils/oracle/subject_selection_query_builder.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from classes.appointments_slot_type import AppointmentSlotType
2929
from classes.appointment_status_type import AppointmentStatusType
3030
from classes.which_diagnostic_test import WhichDiagnosticTest
31+
from classes.diagnostic_test_type import DiagnosticTestType
3132

3233

3334
class SubjectSelectionQueryBuilder:
@@ -1690,6 +1691,39 @@ def _handle_earlier_or_later_test(self, which, xt, xtp):
16901691
)
16911692
self.sql_from.append(f"AND {xt}.ext_test_id {comparator} {xtp}.ext_test_id")
16921693

1694+
def _add_criteria_diagnostic_test_type(self, proposed_or_confirmed: str) -> None:
1695+
"""
1696+
Filters diagnostic tests by type—proposed or confirmed.
1697+
Requires prior join to external_tests_t (xt aliasing assumed).
1698+
"""
1699+
try:
1700+
idx = getattr(self, "criteria_index", 0)
1701+
xt = f"xt{idx}"
1702+
1703+
if proposed_or_confirmed == "proposed":
1704+
column = f"{xt}.proposed_type_id"
1705+
elif proposed_or_confirmed == "confirmed":
1706+
column = f"{xt}.confirmed_type_id"
1707+
else:
1708+
raise SelectionBuilderException(
1709+
self.criteria_key_name, self.criteria_value
1710+
)
1711+
1712+
self.sql_where.append(f"AND {column} ")
1713+
1714+
value = self.criteria_value.strip().lower()
1715+
if value == "null":
1716+
self.sql_where.append("IS NULL")
1717+
elif value == "not null":
1718+
self.sql_where.append("IS NOT NULL")
1719+
else:
1720+
comparator = self.criteria_comparator
1721+
type_id = DiagnosticTestType.get_valid_value_id(self.criteria_value)
1722+
self.sql_where.append(f"{comparator} {type_id}")
1723+
1724+
except Exception:
1725+
raise SelectionBuilderException(self.criteria_key_name, self.criteria_value)
1726+
16931727
# ------------------------------------------------------------------------
16941728
# 🧬 CADS Clinical Dataset Filters
16951729
# ------------------------------------------------------------------------

utils/oracle/test_subject_criteria_dev.py

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -37,31 +37,20 @@ def make_builder(key, value, index=0):
3737
return b
3838

3939

40-
# === Test: ANY_TEST_IN_ANY_EPISODE ===
41-
b = make_builder(
42-
SubjectSelectionCriteriaKey.WHICH_DIAGNOSTIC_TEST, "any_test_in_any_episode"
43-
)
44-
b._add_join_to_diagnostic_tests()
45-
print("=== ANY_TEST_IN_ANY_EPISODE ===")
40+
# === Test: DIAGNOSTIC_TEST_CONFIRMED_TYPE (valid value) ===
41+
b = make_builder(SubjectSelectionCriteriaKey.DIAGNOSTIC_TEST_CONFIRMED_TYPE, "PCR")
42+
b._add_criteria_diagnostic_test_type("confirmed")
43+
print("=== DIAGNOSTIC_TEST_CONFIRMED_TYPE (valid value) ===")
4644
print(b.dump_sql(), end="\n\n")
4745

48-
# === Test: EARLIER_TEST_IN_LATEST_EPISODE ===
49-
b = make_builder(
50-
SubjectSelectionCriteriaKey.WHICH_DIAGNOSTIC_TEST,
51-
"earlier_test_in_latest_episode",
52-
index=1,
53-
)
54-
b._add_join_to_diagnostic_tests()
55-
print("=== EARLIER_TEST_IN_LATEST_EPISODE ===")
46+
# === Test: DIAGNOSTIC_TEST_PROPOSED_TYPE (null) ===
47+
b = make_builder(SubjectSelectionCriteriaKey.DIAGNOSTIC_TEST_PROPOSED_TYPE, "null")
48+
b._add_criteria_diagnostic_test_type("proposed")
49+
print("=== DIAGNOSTIC_TEST_PROPOSED_TYPE (null) ===")
5650
print(b.dump_sql(), end="\n\n")
5751

58-
# === Test: ONLY_NOT_VOID_TEST_IN_LATEST_EPISODE ===
59-
b = make_builder(
60-
SubjectSelectionCriteriaKey.WHICH_DIAGNOSTIC_TEST,
61-
"only_not_void_test_in_latest_episode",
62-
)
63-
b._add_join_to_diagnostic_tests()
64-
print("=== ONLY_NOT_VOID_TEST_IN_LATEST_EPISODE ===")
52+
# === Test: DIAGNOSTIC_TEST_PROPOSED_TYPE (not null) ===
53+
b = make_builder(SubjectSelectionCriteriaKey.DIAGNOSTIC_TEST_PROPOSED_TYPE, "not null")
54+
b._add_criteria_diagnostic_test_type("proposed")
55+
print("=== DIAGNOSTIC_TEST_PROPOSED_TYPE (not null) ===")
6556
print(b.dump_sql(), end="\n\n")
66-
67-
# Add more as needed for full coverage

0 commit comments

Comments
 (0)