Observation Reference Ranges
In on our previous guide about creating diagnostic services catalog, we described the importance of the ObservationDefinition
resource for storing metadata about the Observations
produced by the test. This metadata is not just for ensuring data correctness, but also a key component in assisting providers with data interpretation.
A core part of interpreting results of this metadata is the definition of reference ranges, sets of Observation
values that share a diagnostic interpretation. While medical directors will always have the final say on any interpretation, incorporating reference ranges into your catalog can streamline their workflow.
In this guide, we'll take a closer look at how administrators can use the ObservationDefinition
resource to define these ranges of interest. We'll cover the following key areas:
- Defining a reference range.
- Establishing age and gender-dependent ranges.
- Understanding the types of ranges that FHIR supports.
- Editing reference ranges in the medplum UI.
- Defining ranges for non-numerical Observations.
Defining a Reference Range
A reference range is defined using the ObservationDefinition.qualifiedInterval
element. This is an array field, which allows administrators to define multiple ranges of interest for a single Observation
.
A range is defined by the following properties:
Element | Description | Example |
---|---|---|
qualifiedInterval.range.low | Lower bound for the reference range, inclusive. (Empty value denotes no lower bound) | 10 mg/dL |
qualifiedInterval.range.high | Upper bound for the reference range, inclusive. (Empty value denotes no upper bound) | 100 mg/dL |
qualifiedInterval.range.condition | How to interpret observation values in this interval | "High" |
Example: 10 - 100 mg/dL
{
resourceType: 'ObservationDefinition',
code: {
coding: [
{
system: LOINC,
code: '38483-4',
display: 'Creatinine [Mass/volume] in Blood',
},
],
},
qualifiedInterval: [
{
condition: 'Normal',
range: {
low: {
value: 10,
unit: 'mg/dL',
system: UCUM,
},
high: {
value: 100,
unit: 'mg/dL',
system: UCUM,
},
},
},
],
}
Example: Less or equal to than 5 mg/dL
{
resourceType: 'ObservationDefinition',
code: {
coding: [
{
system: LOINC,
code: '38483-4',
display: 'Creatinine [Mass/volume] in Blood',
},
],
},
qualifiedInterval: [
{
condition: 'Normal',
range: {
high: {
value: 5,
unit: 'mg/dL',
system: UCUM,
},
},
},
],
}
Example: Greater than or equal to 20 mg/dL
{
resourceType: 'ObservationDefinition',
code: {
coding: [
{
system: LOINC,
code: '38483-4',
display: 'Creatinine [Mass/volume] in Blood',
},
],
},
qualifiedInterval: [
{
condition: 'Normal',
range: {
low: {
value: 20,
unit: 'mg/dL',
system: UCUM,
},
},
},
],
}
In practice, multiple an ObservationDefinition
will define multiple reference ranges for a given patient population, to provide interpretations for each value of the Observation
.
Details
Example: Multiple Ranges
The example below defines three reference ranges, to be interpreted as "Low", "Normal", and "High". {
resourceType: 'ObservationDefinition',
code: {
coding: [
{
system: LOINC,
code: '38483-4',
display: 'Creatinine [Mass/volume] in Blood',
},
],
},
qualifiedInterval: [
{
context: {
text: 'Low',
},
range: {
high: {
value: 9,
unit: 'mg/dL',
system: UCUM,
code: 'mg/dL',
},
},
},
{
context: {
text: 'Normal',
},
range: {
low: {
value: 10,
unit: 'mg/dL',
system: UCUM,
code: 'mg/dL',
},
high: {
value: 99,
unit: 'mg/dL',
system: UCUM,
code: 'mg/dL',
},
},
},
{
context: {
text: 'High',
},
range: {
low: {
value: 100,
unit: 'mg/dL',
system: UCUM,
code: 'mg/dL',
},
},
},
],
}
Patient-dependent reference ranges
Patient demographics can influence the interpretation of some diagnostic test results.
To handle this, the ObservationDefinition
resource allows for defining reference ranges that can be either tailored to specific patient demographics or universally applied.
The table below describes which patient attributes can be used to target reference ranges:
Attribute | Element | Type | Code System | Example |
---|---|---|---|---|
Age | qualifiedInterval.age | Range | ||
Gender | qualifiedInterval.gender | code | AdministrativeGender | female |
Gestational Age | qualifiedInterval.gestationalAge | Range | ||
Racial/Ethnic Group | qualifiedInterval.appliesTo | CodeableConcept | (Example) OMB Race Categories | Asian |
Details
Example: Age and gender dependent reference ranges
The example below demonstrates how to represent different normal ranges for a testosterone test, for both adults and children. {
resourceType: 'ObservationDefinition',
code: {
coding: [
{
system: LOINC,
code: '2990-0',
display: 'Testosterone.free+weakly bound [Mass/volume] in Serum or Plasma',
},
],
text: 'Testosterone',
},
qualifiedInterval: [
{
gender: 'male',
age: {
low: {
value: 11,
unit: 'years',
},
high: {
value: 29,
unit: 'years',
},
},
condition: 'Normal',
range: {
low: {
value: 200,
unit: 'ng/dL',
},
high: {
value: 900,
unit: 'ng/dL',
},
},
},
{
gender: 'male',
age: {
low: {
value: 30,
unit: 'years',
},
},
condition: 'High',
range: {
low: {
value: 300,
unit: 'ng/dL',
},
high: {
value: 1000,
unit: 'ng/dL',
},
},
},
{
gender: 'female',
age: {
low: {
value: 11,
unit: 'years',
},
high: {
value: 14,
unit: 'years',
},
},
condition: 'Normal',
range: {
low: {
value: 15,
unit: 'ng/dL',
},
high: {
value: 70,
unit: 'ng/dL',
},
},
},
{
gender: 'female',
age: {
low: {
value: 15,
unit: 'years',
},
},
condition: 'High',
range: {
low: {
value: 30,
unit: 'ng/dL',
},
high: {
value: 95,
unit: 'ng/dL',
},
},
},
],
}
For any range, if these demographic qualifiers are left unspecified, the system interprets it as a universal range applicable to all patients.
Patients
to reference rangesThe Medplum SDK provides helper functions, findObservationInterval
, findObservationReferenceRange
, and matchesRange
to find reference ranges that match a particular patient.
Example
const jane: Patient = {
resourceType: 'Patient',
name: [{ given: ['Jane'], family: 'Doe' }],
gender: 'female',
birthDate: '1970-01-01',
};
const janeTestosterone: Observation = {
resourceType: 'Observation',
status: 'final',
code: {
coding: [
{
system: LOINC,
code: '2990-0',
display: 'Testosterone.free+weakly bound [Mass/volume] in Serum or Plasma',
},
],
text: 'Testosterone',
},
subject: createReference(jane),
valueQuantity: {
value: 32,
unit: 'ng/dL',
},
};
findObservationInterval(testosteroneDefinition, jane, janeTestosterone.valueQuantity?.value as number);
// Returns
// {
// gender: 'female',
// age: {
// low: {
// value: 15,
// unit: 'years',
// },
// },
// condition: 'High',
// range: {
// low: {
// value: 30,
// unit: 'ng/dL',
// },
// high: {
// value: 95,
// unit: 'ng/dL',
// },
// },
// },
Types of reference ranges
Reference ranges can be categorized into three different types:
Field | Description |
---|---|
reference | Defines the normal ranges for a given observation type. |
critical | Defines the critical values for the observation, also known as "panic" values. Observing values in these ranges often require special handling to notify patients. |
absolute | The absolute allowable range for this value (i.e. the measurable range). Values outside of this range are not possible / sensible. |
The type of reference range is specified in the qualifiedInterval.category
field.
Example
{
resourceType: 'ObservationDefinition',
code: {
coding: [
{
system: LOINC,
code: '2093-3',
display: 'Cholesterol in HDL [Mass/volume] in Serum or Plasma',
},
],
text: 'HDL Cholesterol',
},
qualifiedInterval: [
// Reference ranges
{
category: 'reference',
range: {
low: {
value: 21,
unit: 'mg/dL',
},
high: {
value: 39,
unit: 'mg/dL',
},
},
condition: 'Low',
},
{
category: 'reference',
range: {
low: {
value: 40,
unit: 'mg/dL',
},
high: {
value: 60,
unit: 'mg/dL',
},
},
condition: 'Normal',
},
{
category: 'reference',
range: {
low: {
value: 61,
unit: 'mg/dL',
},
high: {
value: 99,
unit: 'mg/dL',
},
},
condition: 'High',
},
// Critical Ranges
{
category: 'critical',
range: {
high: {
value: 20,
unit: 'mg/dL',
},
},
condition: 'Critical Low',
},
{
category: 'critical',
range: {
low: {
value: 100,
unit: 'mg/dL',
},
},
condition: 'Critical High',
},
// Absolute Range
{
category: 'absolute',
range: {
low: {
value: 0,
unit: 'mg/dL',
},
high: {
value: 120,
unit: 'mg/dL',
},
},
condition: 'Absolute Range',
},
],
}
Editing reference ranges in the Medplum App
Medplum has developed user interface tools to simplify the process of editing ObservationDefinition
reference ranges.
The ReferenceRangeEditor component enables you to define groups of reference ranges for each set of patient attributes.
You can integrate this component into your custom application, or you can use it directly within the Medplum App.
To edit reference ranges in the Medplum App:
- Navigate to the Medplum App's ObservationDefinition page at https://app.medplum.com/ObservationDefinition.
- Select the specific
ObservationDefinition
resource you wish to edit. - Click on the "Ranges" tab.
Examples
- HDL Reference Ranges - no dependence on patient attributes.
- Testosterone Reference Ranges - dependent on patient gender and age.
Non-numeric reference ranges
For qualitative observations, defining interpretations in the ObservationDefinition
is slightly different. Rather than defining numerical ranges, the administrator defines ValueSet
resources that enumerate sets of codes.
The validCodedValueSet
, normalCodedValueSet
, abnormalCodedValueSet
, and criticalCodedValueSet
fields mirror the functionality of absolute
, reference
, and critical
reference ranges, are used to define the interpretation of a qualitative observation.
Each one of these fields refers to a ValueSet
resource, which enumerates the codes assigned to each category of interpretation:
Field Name | Similar to | Description |
---|---|---|
validCodedValueSet | absolute | Enumerates of all valid qualitative values for this Observation type. |
normalCodedValueSet | reference | Enumerates all codes that signify a normal result for this Observation. It should be a subset of the validCodedValueSet . |
abnormalCodedValueSet | reference | Enumerates all of codes that signify an abnormal result for this Observation. It should be a subset of the validCodedValueSet . |
criticalCodedValueSet | critical | Enumerates all the qualitative values that are considered critical or cause for "panic". Typically a subset of the abnormalCodedValueSet . |