CMS FHIR Quality Measure Development IG
0.8.0-cibuild - CI Build International flag

CMS FHIR Quality Measure Development IG, published by Centers for Medicare & Medicaid Services (CMS). This guide is not an authorized publication; it is the continuous build for version 0.8.0-cibuild built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/cqframework/cms-qmd/ and changes regularly. See the Directory of published versions

FHIR Patterns

Whether logic should make use of a particular element of a profile depends wholly on the intent of the measure or rule. Nonetheless, some general guidelines should be followed to ensure correct expression and evaluation of CQL. The considerations most often encountered in these patterns are summarized here; see Element Considerations in the Using CQL With FHIR IG for the complete treatment. The guidance in that IG is informative. Where a requirement is normative for quality measures, it is stated in the Using CQL topic of the Quality Measure IG, which carries the conformance requirements; those are called out below where they apply.

Element cardinality

Every element in a FHIR resource or profile has a cardinality that determines whether and how many values may appear in that element. Cardinality is expressed as a range, typically from 0 or 1 to 1 or *. A cardinality of 0..1 means the element is optional, 1..1 means the element is required, 0..* means it may appear any number of times, and 1..* means it must appear at least once, but may appear multiple times. Although other cardinalities are possible, those described above are the most common.

NOTE: Cardinality determines whether and how many values may appear for a given element, but the fact that an element is required (e.g. 1..1) does not mean that expressions using that profile must reference that element.

Must support elements

Elements in FHIR profiles may be marked must support, meaning that implementations are required to provide a value for the element if one is present in the system. Expressions should only make use of elements that are marked must support, or that otherwise have a reasonable expectation of being present. The specific meaning of must support is established by each implementation guide — see the MustSupport Flag topic in US Core and Must Support in US Quality Core.

Modifier elements

Some elements in FHIR profiles are designated as modifier elements, meaning that the value of the element may change the overall meaning of the resource. For example, the clinicalStatus element of a Condition is a modifier element because its value determines whether the Condition represents the presence or absence of a condition. As a result, authors must carefully consider, for each modifier element, whether its possible values could affect the intended meaning of the expression.

The status element of an event or request is the modifier element most often encountered in these patterns. Where a profile does not constrain status, the expression must account for every value it may take. US Quality Core provides value sets for this purpose, such as Non-Negative Event Status and its per-resource counterparts, which exclude the statuses used by the negation profiles.

Extensions may likewise be modifier extensions, and a resource carrying a modifier extension that is not understood cannot be processed. The implicitRules element is a modifier element that applies to every FHIR resource. These checks may be handled by the evaluation environment, or performed in CQL using the checkModifiers() function defined in FHIRHelpers.

To summarize,

  • Cardinality determines whether data will be present at all.
  • Must support determines whether the element can reasonably be expected to be present.
  • Modifier elements must always be evaluated for how their possible values might influence the meaning or outcome of an expression.

Authoring against the US Quality Core model

US Quality Core publishes derived ModelInfo, so profiles are presented as types derived from their US Core and FHIR base definitions:

using USQualityCore version '0.5.0'

The version is not optional. For quality measures, all CQL SHALL use FHIR-based data models, and the model declaration SHALL include a version — see CQL Data Model in the Quality Measure IG.

This differs from the profile-informed authoring approach used by QI-Core, which flattened profiles so that slices and extensions appeared as ordinary elements. Under derived ModelInfo, extension-backed data is reached through fluent functions rather than named elements — Patient.race() rather than Patient.race. For the full list of affected elements and the function to use for each, see the Extension Index in the Refactored Index.

NOTE: The Patterns page published in US Quality Core 0.5.0 describes primitives, extensions, and choice types in terms of profile-informed authoring, which does not match the derived ModelInfo that guide ships. It should not be referenced; use the guidance referred to here instead. That page has been removed for the next ballot publication of US Quality Core, and no further publication of the 0.5.0 branch is expected.

Accessing data

Data is accessed with the CQL Retrieve expression, naming the type to be retrieved and, optionally, a terminology filter:

define "All Allergies and Intolerances":
  [USQualityCore.AllergyIntolerance]

define "Antithrombotics Administered":
  [USQualityCore.MedicationAdministration: "Antithrombotic Therapy"]

Under derived ModelInfo, the retrievable type name is the computable name of the profile with the model prefix removed, so the USQualityCoreMedicationAdministration profile is retrieved as MedicationAdministration. US Quality Core 0.5.0 defines 57 retrievable types on this basis. Qualifying the type with the model name is optional but recommended, both because it makes the source of the type explicit and because some patterns need to reach types the guide does not profile, such as [USCore.SmokingStatusProfile].

As described under Modifier elements, status elements must be considered whenever data is accessed. FHIRCommon provides fluent functions for the common cases, in both a singleton predicate form (e.g. Allergy.isActive()) and a list-filtering form (e.g. Allergies.active()):

define "Active Confirmed Allergies and Intolerances":
  "All Allergies and Intolerances".active().confirmed()

See Accessing Data for further discussion.

References

See References in FHIR

Many elements of FHIR resources are references to other resources. A reference is always represented in one direction, from a source to a target.

References target a resource based on its identity, and there are several types of resource identities in FHIR.

The FHIRHelpers and FHIRCommon libraries include several functions for dealing with references in FHIR:

  • reference(String): Reference - Returns a FHIR.Reference with the given value as the reference target
  • reference(Resource): Reference - Returns a FHIR.Reference with the logical id of the given Resource as the reference target
  • references(Resource): Boolean - Returns true if the reference is to the given Resource
  • references(String): Boolean - Returns true if the reference is to the given id

For example, to determine whether an Observation is referencing an Encounter:

define "Encounter With Blood Pressure Observation":
  [USQualityCore.Encounter] E
    with [USCore.BloodPressureProfile] BP
      such that BP.encounter.references(E)

These reference functions are used throughout the patterns in this guide to establish relationships. Note however that references are not always populated in the source data, and establishing a temporal relationship can often be more robust:

define "Encounter With Blood Pressure Observation":
  [USQualityCore.Encounter] E
    with [USCore.BloodPressureProfile] BP
      such that BP.effective.toInterval() during E.period

NOTE: Although FHIR does provide a mechansim for business identifiers to be used for both the source and target of a reference, this is not a common practice and should typically be avoided. US Core in particular specifies that when referencing data in US Core profiles, references should include a logical id and not a business identifier.

NOTE: Although FHIRHelpers provides a resolve() function that can be used to retrieve the resource targeted by a reference, this approach is not recommended in CQL, because CQL already has a retrieve mechanism. Using resolve() means that implementing systems need to support multiple ways of accomplishing the same underlying task; as well, CQL data access layers use the retrieve syntax in CQL as a primary optimization strategy, and the resolve() function is not likely to be understood or used by those optimization strategies.

NOTE: This topic is proposed for inclusion in the FHIR Patterns page of the Using CQL With FHIR implementation guide: https://jira.hl7.org/browse/FHIR-58895

Use of terminologies

FHIR terminology-valued elements are compared in CQL using the equal (=), equivalent (~), and in operators. As a general rule,

  • Use the equivalent operator (~) when comparing to a direct-reference code.
  • Use the in operator when comparing to a value set.
  • Use the equal operator (=) only with code-valued elements that have a required binding.

Note that contains has no terminological overload in the current version of CQL and should not be used with terminology-valued elements; use includesCode() from FHIRCommon instead.

For quality measures, the first two rules above are backed by conformance requirements rather than style preferences:

  • Value set membership testing SHOULD use the CQL terminology membership operator (in), rather than computing over the list of codes a value set expands to — see Value Set Expansion.
  • String-based membership testing SHOULD NOT be used — see String-based Membership Testing. Given a value set named “Administrative Gender”, the expression 'female' in "Administrative Gender" is not conformant, because no code system is associated with the string 'female'.

Direct-reference codes are declared with the code’s logical identifier from the code system. That identifier SHALL NOT be a URI, and SHOULD be a code drawn from the code system — see Codes:

code "Venous foot pump, device (physical object)": '442023007' from "SNOMED CT"

Further considerations

The following topics in the Using CQL With FHIR IG apply throughout these patterns and are not repeated here:

Topic Applies to
Primitives Whether a .value accessor is required; under derived ModelInfo elements carry FHIR types (Patient.birthDate is FHIR.date), with FHIRHelpers supplying the conversions
Choices Elements that may take several types, such as Condition.onset; the toInterval(), abatementInterval(), prevalenceInterval(), earliest(), and latest() helpers in FHIRCommon
Slices Accessing sliced elements, such as blood pressure components via the systolic() and diastolic() fluent functions in USCoreCommon
Extensions Reading extension values where no fluent accessor is defined; see also the Extension Index in the Refactored Index
Missing Information Null propagation, the is true/is not true predicates, and the treatment of unknown status codes
Date, Time, and DateTime Values Being explicit about comparison precision, typically day of
Timezone and Timezone Offset Handling Day-boundary calculations such as “on hospital day 2”
Time-Valued Quantities Calendar durations (year, month) versus UCUM definite durations ('a', 'mo')
Use of Terminologies Comparing code, Coding, and CodeableConcept elements, including multi-cardinality and direct-reference code cases