Introduction
In order to make concepts ranges effective, it is crucial to implement factor-based reference ranges for key metrics like vital signs and laboratory results. For instance, if we consider a factor like age; patients of any age, from newborns to centenarians, may require care, and the normal versus abnormal ranges for this factor may vary significantly based on age.
Another example is blood pressure, which has distinct ranges depending on the age of the patient. A range that is normal for an adult could be life-threatening for a newborn. The following are details of blood glucose and blood pressure ranges:
Fasting Blood Glucose Ranges:
Infants:
Normal: 40-90 mg/dL
Critical: < 40 mg/dL or > 300 mg/dL
Patients > 2 years:
Normal: 70-110 mg/dL
Critical: < 54 mg/dL or > 400 mg/dL
Blood Pressure Ranges:
Newborn: 80/40 mmHg
1-3 years: 94/64 mmHg
10 years: 110/58 mmHg
Adult: 120/80 mmHg
In addition to age, other factors can influence what is considered a "normal" range for a given patient. These factors include:
sex/gender
ethnicity
renal function
pregnancy status
weight/BMI
time of day
OpenMRS Platform version
2.7.0
Absolute values
When evaluating with concept reference ranges, only absolute values are used. i.e. absolute low and absolute high values are the ones used for validation. The rest such as critical high/low, etc are only used for flagging values displayed in the user interface.
Creating Criteria Expressions
The criteria can be based on one or many factor combinations of the following :
Age (in years, months, weeks, or days)
Gender
Time of day
Observation boolean/text/numeric/coded values
The criteria enable precise and tailored validation of patient data, ensuring that the appropriate reference ranges are applied for each unique case.
Relational operations (used in criteria expressions)
<
: Less than>
: Greater than<=
: Less than or equal to>=
: Greater than or equal to==
: Equal to!=
: Not equal to&&
: Logical AND. This operator returnstrue
if both of the conditions or expressions it combines are true. If either condition is false, the overall result is false.||
: Logical OR. This operator returnstrue
if at least one of the conditions or expressions it combines is true. If both conditions are false, the overall result is false.
Examples of Criteria Expressions
Age:
$patient.getAge() > 5
checks if the patient is older than 5 years.$patient.getAgeInMonths() < 3
checks if the patient is less than 3 months.$patient.getAgeInWeeks() < 12
checks if the patient is less than 12 weeks.$patient.getAgeInDays() < 10
checks if the patient is less than 10 days.$patient.getAge() > 18 && $patient.getAge() < 70
checks if the patient is between the age of 18 and 70 years.
Gender:
$patient.getGender().equals("M")
checks if the patient is male.$patient.getGender().equals("M") || $patient.getGender().equals("F")
checks if the patient is male OR female.
Age & Gender:
$patient.getGender().equals("F") && $patient.getAge() > 18
checks if the patient is a female older than 18 years.$patient.getGender().equals("M") || $patient.getAge() > 20
checks if the patient is either a male or is older than 20 years.
Observation Value:
$fn.getLatestObs("CIEL:1234").getValueText().equals("PREGNANT")
checks if the patient has a recent observation indicating pregnancy.$fn.getLatestObs("2a86e48c-76ef-479f-815f-d7c1701e8fb7").getValueBoolean() == true
checks if the patient
Note:CIEL:1234
used in example a) is concept mapping while2a86e48c-76ef-479f-815f-d7c1701e8fb7
used in example b) is concept’s uuid.The method called after
getLatestObs()
expression depends on the data type of the concept passed in the parameter. For instance in example a) above, the concepts data type is text while in example b) the data type is boolean.
-$fn.getLatestObs("CIEL:1234").getValueNumeric()
for value numeric
-$fn.getLatestObs("CIEL:1234").getValueCoded()
for value coded
Time of the day:
$fn.getCurrentHour() == 14
checks if the (current) time of the the day at the time of creating the Observation is the specified time in the criteria. In our example, the expression checks if the time of the day is 2pm. Note thatgetCurrentHour()
returns the hour of the day in 24hr format.
Person Attributes:
Note that you person attributes need to be set. Therefore make sure that person attributes are set for the attribute expressions to work. Find more on how to manage person attributes here.$patient.getAttribute("Ethnicity").getValue() == "Maasai"
check if there is the person is ofMaasai
ethnicity. The ‘Maasai’ in this example is the attribute value while the ‘Ethnicity’ is attribute type.
Complex Criteria reference:
($patient.getGender().equals("F") && $patient.getAge() > 18) || ($patient.getGender().equals("M") && $patient.getAge() < 18)
checks the patient is either a female older than 18 years or a male who is less than 18 years of age.$patient.getAge() >= 1 && $patient.getAge() <= 3
evaluates to true if the patient is one, two or 3 years old.You can come up with criteria expressions using the values of the current Obs. For example:-
BMI - criteria expression would require the use of formula. If person’s weight and height are in kg and cm, then the formula would be weight/ ((1/100 x height) power 2) or weight/ ((1/100 x height) x (1/100 x height)). Here is an example of an expression that will return true if BMI is greater than 25.
"($fn.getCurrentObs("c607c80f-1ea9-4da3-bb88-6276ce8868dd", $obs).getValueNumeric() / (($fn.getCurrentObs("a09ab2c5-878e-4905-b25d-5784167d0216", $obs).getValueNumeric() / 100) * ($fn.getCurrentObs("a09ab2c5-878e-4905-b25d-5784167d0216", $obs).getValueNumeric() / 100))) > 25"
Note:c607c80f-1ea9-4da3-bb88-6276ce8868dd
is the uuid(conceptRef) for weight concept anda09ab2c5-878e-4905-b25d-5784167d0216
is the uuid(conceptRef) for height concept.
Strict Ranges
In the case where multiple concept reference ranges are evaluated to true, then we use the strictest range.
For example:-
ConceptReferenceRange1 has absolute ranges of
60-140
and criteria$patient.getAge() > 5
ConceptReferenceRange2 has absolute ranges of
80-150
and criteria$patient.getAge() > 3
-> Assuming the patient is
10
years old, then the criteria will evaluate to true for both reference ranges. Therefore, the highest lower bound and lowest higher bound is picked. Hence,ObsReferenceRange
will be saved with ranges80-140
.
Current & Latest Obs Functions
getCurrentObs()
getCurrentObs(String conceptRef, Obs currentObs)
This function returns the most relevant observation (Obs
) based on the provided concept reference (conceptRef
) and the current observation (currentObs
). If the currentObs
has a valid value—such as coded, numeric, date, or text and the concept in the currentObs
matches the supplied concept reference, it returns the currentObs
. Otherwise, it fetches the most recent Obs
that matches the supplied concept reference and the patient associated with the currentObs
.
Key Points:
Current Obs Check: If
currentObs
has a valid value and its concept matches the providedconceptRef
, the method directly returns thiscurrentObs
.Fallback to Latest Obs: If the
currentObs
does not have a valid value or the concept does not match, the method retrieves the latest Obs for the providedconceptRef
and patient.
For a practical example, refer to the criteria expressions for calculating BMI above.
getLatestObs()
This function returns the most recent obs, for the patient in subject & the provided concept, that was saved.
getLatestObs(String conceptRef, Person person)
This function retrieves the latest observation for a specified concept reference (conceptRef
) and person (person
). The conceptRef
can be a concept UUID or a concept map's code and source name (e.g., "CIEL:1434"
). The method returns the most recently saved Obs matching the provided criteria.
Key Points:
Concept Reference: The method accepts a concept UUID or a concept map's code and source name to identify the relevant concept.
Person: The latest Obs is retrieved for the current person/patient.
Example:
You can use getLatestObs
to fetch the most recent weight observation like this:
$fn.getLatestObs('c607c80f-1ea9-4da3-bb88-6276ce8868dd', $patient).getValueNumeric()
This retrieves the most recent weight observation for the current patient.
For more examples, refer to the criteria expressions mentioned above.
Concept Numeric Ranges
If concept numeric ranges are still present (e.g., for legacy or historical reasons), the system will prioritize evaluating the concept reference ranges first before validating against the concept numeric ranges. This approach is adopted because concept reference ranges provide stricter validation criteria, ensuring that observations are assessed against the most precise and relevant standards first.
Why save new Obs Reference Ranges?
Saving new observation reference ranges is crucial for maintaining the integrity and relevance of historical data. By storing these ranges, clinicians can easily review the specific criteria used during each patient encounter. For example, if a patient receives prenatal care and later returns for postnatal care, the practitioner can quickly identify which reference ranges were applied during the pregnancy. This historical context enhances clinical decision-making by providing insights into the factors considered during past evaluations.
Another example might involve a pediatric patient whose reference range for a particular vital sign was set based on their age at the time of the encounter. As the patient grows older, the will change, rendering the criteria no longer evaluating to true. By saving the Obs reference ranges, it is possible to track these ranges and ensure that the patient’s historical data is accurately interpreted.
This approach also brings us closer to alignment with FHIR (Fast Healthcare Interoperability Resources), which already supports the inclusion of reference ranges in clinical observations.
Conclusion
The implementation of factor-based reference ranges in OpenMRS is a critical enhancement that ensures the applicability of ranges across various patient factors. By leveraging a flexible architecture that incorporates dynamic criteria expressions, OpenMRS can now provide accurate and relevant reference ranges for vital signs and lab results based on patient-specific factors.