Skip to main content

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:

  1. Defining a reference range.
  2. Establishing age and gender-dependent ranges.
  3. Understanding the types of ranges that FHIR supports.
  4. Editing reference ranges in the medplum UI.
  5. 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 mulitple ranges of interest for a single Observation.

A range is defined by the following properties:

ElementDescriptionExample
qualifiedInterval.range.lowLower bound for the reference range, inclusive.
(Empty value denotes no lower bound)
10 mg/dL
qualifiedInterval.range.highUpper bound for the reference range, inclusive.
(Empty value denotes no upper bound)
100 mg/dL
qualifiedInterval.range.conditionHow to interpret observation values in this interval"High"
Example: 10 - 100 mg/dL
  {
resourceType: 'ObservationDefinition',
code: {
coding: [
{
system: 'http://loinc.org',
code: '38483-4',
display: 'Creatinine [Mass/volume] in Blood',
},
],
},
qualifiedInterval: [
{
condition: 'Normal',
range: {
low: {
value: 10,
unit: 'mg/dL',
system: 'http://unitsofmeasure.org',
},
high: {
value: 100,
unit: 'mg/dL',
system: 'http://unitsofmeasure.org',
},
},
},
],
}
Example: Less or equal to than 5 mg/dL
  {
resourceType: 'ObservationDefinition',
code: {
coding: [
{
system: 'http://loinc.org',
code: '38483-4',
display: 'Creatinine [Mass/volume] in Blood',
},
],
},
qualifiedInterval: [
{
condition: 'Normal',
range: {
high: {
value: 5,
unit: 'mg/dL',
system: 'http://unitsofmeasure.org',
},
},
},
],
}
Example: Greater than or equal to 20 mg/dL
  {
resourceType: 'ObservationDefinition',
code: {
coding: [
{
system: 'http://loinc.org',
code: '38483-4',
display: 'Creatinine [Mass/volume] in Blood',
},
],
},
qualifiedInterval: [
{
condition: 'Normal',
range: {
low: {
value: 20,
unit: 'mg/dL',
system: 'http://unitsofmeasure.org',
},
},
},
],
}

In practice, multiple an ObservationDefinition will define multiple reference ranges for a given patient population, to provide interpretations for each value of the Observation.

Example: Multiple Ranges
The example below defines three reference ranges, to be interpreted as "Low", "Normal", and "High".
  {
resourceType: 'ObservationDefinition',
code: {
coding: [
{
system: 'http://loinc.org',
code: '38483-4',
display: 'Creatinine [Mass/volume] in Blood',
},
],
},
qualifiedInterval: [
{
context: {
text: 'Low',
},
range: {
high: {
value: 9,
unit: 'mg/dL',
system: 'http://unitsofmeasure.org',
code: 'mg/dL',
},
},
},
{
context: {
text: 'Normal',
},
range: {
low: {
value: 10,
unit: 'mg/dL',
system: 'http://unitsofmeasure.org',
code: 'mg/dL',
},
high: {
value: 99,
unit: 'mg/dL',
system: 'http://unitsofmeasure.org',
code: 'mg/dL',
},
},
},
{
context: {
text: 'High',
},
range: {
low: {
value: 100,
unit: 'mg/dL',
system: 'http://unitsofmeasure.org',
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:

AttributeElementTypeCode SystemExample
AgequalifiedInterval.ageRange
GenderqualifiedInterval.gendercodeAdministrativeGenderfemale
Gestational AgequalifiedInterval.gestationalAgeRange
Racial/Ethnic GroupqualifiedInterval.appliesToCodeableConcept(Example) OMB Race CategoriesAsian
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: 'http://loinc.org',
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',
},
},
},
],
}
note

For any range, if these demographic qualifiers are left unspecified, the system interprets it as a universal range applicable to all patients.

Matching Patients to reference ranges

The 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',
code: {
coding: [
{
system: 'http://loinc.org',
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:

FieldDescription
referenceDefines the normal ranges for a given observation type.
criticalDefines the critical values for the observation, also known as "panic" values. Observing values in these ranges often require special handling to notify patients.
absoluteThe 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: 'http://loinc.org',
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:

  1. Navigate to the Medplum App's ObservationDefinition page at https://app.medplum.com/ObservationDefinition.
  2. Select the specific ObservationDefinition resource you wish to edit.
  3. Click on the "Ranges" tab.

Examples

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 NameSimilar toDescription
validCodedValueSetabsoluteEnumerates of all valid qualitative values for this Observation type.
normalCodedValueSetreferenceEnumerates all codes that signify a normal result for this Observation. It should be a subset of the validCodedValueSet.
abnormalCodedValueSetreferenceEnumerates all of codes that signify an abnormal result for this Observation. It should be a subset of the validCodedValueSet.
criticalCodedValueSetcriticalEnumerates all the qualitative values that are considered critical or cause for "panic". Typically a subset of the abnormalCodedValueSet.

See Also