Skip to content

Commit

Permalink
Moves the reference range logic onto the model
Browse files Browse the repository at this point in the history
  • Loading branch information
fredkingham committed Dec 19, 2019
1 parent ff580d9 commit 975fec6
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 71 deletions.
36 changes: 2 additions & 34 deletions elcid/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,20 +78,6 @@
LAB_TEST_TAGS[test_name].append(tag)


def clean_ref_range(ref_range):
return ref_range.replace("]", "").replace("[", "").strip()


def get_reference_range(observation_reference_range):
ref_range = clean_ref_range(observation_reference_range)
if not len(ref_range.replace("-", "").strip()):
return None
range_min_max = ref_range.split("-")
if len(range_min_max) > 2:
return None
return {"min": range_min_max[0].strip(), "max": range_min_max[1].strip()}


AEROBIC = "aerobic"
ANAEROBIC = "anaerobic"

Expand All @@ -108,6 +94,7 @@ def serialize_observation(self, observation):
"observation_name": observation.observation_name,
"observation_datetime": observation.observation_datetime,
"observation_number": observation.observation_number,
"reference_range": observation.cleaned_reference_range,
"units": observation.units,
"last_updated": serialization.serialize_datetime(observation.last_updated),
}
Expand All @@ -117,23 +104,6 @@ def serialize_observation(self, observation):
else:
obs_dict["observation_value"] = observation.observation_value

obs_dict["reference_range"] = observation.reference_range.replace("]", "").replace("[", "")

if not len(obs_dict["reference_range"].replace("-", "").strip()):
obs_dict["reference_range"] = None
else:
range_min_max = obs_dict["reference_range"].split("-")
if not range_min_max[0].strip():
obs_dict["reference_range"] = None
else:
if not len(range_min_max) == 2:
obs_dict["reference_range"] = None
# raise ValueError("unable to properly judge the range")
else:
obs_dict["reference_range"] = dict(
min=float(range_min_max[0].strip()),
max=float(range_min_max[1].strip())
)
return obs_dict

def get_observations_by_lab_test(self, lab_tests):
Expand Down Expand Up @@ -337,9 +307,7 @@ def serialize_observations(self, observations):
return dict(
name=observations[0].observation_name,
units=observations[0].units,
reference_range=get_reference_range(
observations[0].reference_range
),
reference_range=observations[0].cleaned_reference_range,
latest_results=latest_results
)

Expand Down
40 changes: 8 additions & 32 deletions elcid/test/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,30 +420,6 @@ def test_patient_found_with_hash(self):
)


class GetReferenceRangeTestCase(OpalTestCase):
def test_clean_ref_range(self):
self.assertEqual(
api.get_reference_range("[ 2 - 3 ]"),
dict(min="2", max="3")
)

def test_return_none_if_only_dash(self):
self.assertIsNone(
api.get_reference_range(" - ")
)

def test_return_none_if_more_than_one_dash(self):
self.assertIsNone(
api.get_reference_range("else -something - or")
)

def test_return_stripped_max_min(self):
self.assertEqual(
api.get_reference_range("2-3"),
dict(min="2", max="3")
)


class BloodCultureSetTestCase(OpalTestCase):
def setUp(self):
positive = datetime.date(2019, 5, 9)
Expand Down Expand Up @@ -908,31 +884,31 @@ def test_vanilla_check(self):
{
'latest_results': {'04/06/2019': 1.8, '05/06/2019': 1.8},
'name': 'WBC',
'reference_range': {'max': '7.5', 'min': '1.7'},
'reference_range': {'max': 7.5, 'min': 1.7},
'units': 'g/l'
},
{
'latest_results': {'04/06/2019': 1.0, '05/06/2019': 1.0},
'name': 'Lymphocytes',
'reference_range': {'max': '4', 'min': '1'},
'reference_range': {'max': 4, 'min': 1},
'units': '10'
},
{
'latest_results': {'04/06/2019': 2.0, '05/06/2019': 2.0},
'name': 'Neutrophils',
'reference_range': {'max': '7.5', 'min': '1.7'},
'reference_range': {'max': 7.5, 'min': 1.7},
'units': '10'
},
{
'latest_results': {'04/06/2019': 1.2, '05/06/2019': 1.2},
'name': 'INR',
'reference_range': {'max': '1.12', 'min': '0.9'},
'reference_range': {'max': 1.12, 'min': 0.9},
'units': 'Ratio'
},
{
'latest_results': {'04/06/2019': 1.0, '05/06/2019': 1.0},
'name': 'C Reactive Protein',
'reference_range': {'max': '5', 'min': '0'},
'reference_range': {'max': 5, 'min': 0},
'units': 'mg/L'
}
],
Expand Down Expand Up @@ -962,7 +938,7 @@ def test_multiple_results_on_the_same_day(self):
{
'latest_results': {'04/06/2019': 1.3},
'name': 'INR',
'reference_range': {'max': '1.12', 'min': '0.9'},
'reference_range': {'max': 1.12, 'min': 0.9},
'units': 'Ratio'
}
],
Expand Down Expand Up @@ -1011,7 +987,7 @@ def test_results_date_crunching(self):
},
'name': 'INR',
'reference_range': {
'max': '1.12', 'min': '0.9'
'max': 1.12, 'min': 0.9
},
'units': 'Ratio'
},
Expand All @@ -1025,7 +1001,7 @@ def test_results_date_crunching(self):
},
'name': 'C Reactive Protein',
'reference_range': {
'max': '5', 'min': '0'
'max': 5, 'min': 0
},
'units': 'mg/L'
}
Expand Down
42 changes: 38 additions & 4 deletions plugins/labtests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,21 +136,55 @@ class Observation(models.Model):
# as defined by us
created_at = models.DateTimeField(auto_now_add=True)

def to_float(self, some_val):
regex = r'^[-+]?[0-9]+(\.[0-9]+)?$'
if re.match(regex, some_val):
return round(float(some_val), 3)

@property
def value_numeric(self):
"""
if an observation is numeric, return it as a float
if an observation is , return it as a float
some of the inputted values are messy, but essentially
integers for example
' 12 ~ using new systyem as of Sep 2014
If possible we clean this up and return a number
otherwise return None
"""
regex = r'^[-+]?[0-9]+(\.[0-9]+)?$'
obs_result = self.observation_value.strip()
obs_result = obs_result.split("~")[0].strip("<").strip(">").strip()
if re.match(regex, obs_result):
return round(float(obs_result), 3)
return self.to_float(obs_result)

@property
def cleaned_reference_range(self):
"""
reference ranges appear of the form
1.5 - 4
[ < 17 ]
1-6
-
Clean these and handle them appropriately
For the moment we will now pass < 17
"""
reference_range = self.reference_range.replace("]", "").replace("[", "")
reference_range = reference_range.strip()
if reference_range == "" or reference_range == "-":
return

min_max_range = [
self.to_float(i.strip()) for i in reference_range.split("-")
]
# remove Nones
min_max_range = [i for i in min_max_range if i is not None]

if not len(min_max_range) == 2:
return

return {
"min": min_max_range[0],
"max": min_max_range[1]
}

def create(self, observation_dict):
self.last_updated = serialization.deserialize_datetime(
Expand Down
20 changes: 19 additions & 1 deletion plugins/labtests/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,22 @@ def test_value_numeric(self):
)
for input_value, expected in inputs_to_expected_results:
observation.observation_value = input_value
self.assertEqual(observation.value_numeric, expected)
self.assertEqual(observation.value_numeric, expected)

def test_cleaned_reference_range(self):
patient, _ = self.new_patient_and_episode_please()
observation = models.Observation()

inputs_to_expected_results = (
("1.5 - 4", (1.5, 4,)),
('0 - 129', (0, 129,)),
("[ < 17 ]", None),
("1-6", (1, 6)),
(" - ", None),
(" ", None),
)
for input_value, expected in inputs_to_expected_results:
observation.reference_range = input_value
if expected:
expected = {"min": expected[0], "max": expected[1]}
self.assertEqual(observation.cleaned_reference_range, expected)

0 comments on commit 975fec6

Please sign in to comment.