SMART Guidelines Starter Kit
2.1.0 - ci-build
SMART Guidelines Starter Kit, published by WHO. This guide is not an authorized publication; it is the continuous build for version 2.1.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/WorldHealthOrganization/smart-ig-starter-kit/tree/main and changes regularly. See the Directory of published versions
CQL - Clinical Query Language is a way to computably express queries and logic for the inputs and outputs of decision support - decision logic - as well as indicators.
For background and introduction to CQL, refer to the Getting Started page of the CQFramework wiki.
CQL expressions are defined in CQL libraries; Common CQL libraries are available, containing commonly usable expressions for accessing data represented as FHIR resources.
Upon authoring, CQL libraries are encoded (base64) and included in FHIR Library resources.
The L3 author must ensure that there are CQL expressions in each Measure or Decision/Scheduling artifact, including their dependencies. CQL Library dependencies are common definitions intended to be reused among multiple artifacts, and potentially multiple SMART Guidelines.
The L3 author creates CQL libraries for:
In general, follow the conventions and conformance requirements established in the Using CQL With FHIR implementation guide. In addition, the Patterns page provides best-practices for writing CQL with FHIR resources.
To enable the CQL to refer to concepts defined in the SMART Guideline, create a Concepts
library that includes CQL declarations for each CodeSystem and ValueSet defined in the SMART Guideline. For example:
library IMMZConcepts
// Immunization Measles Concepts
codesystem "IMMZConcepts": 'https://worldhealthorganization.github.io/smart-example-immz/CodeSystem-IMMZConcepts.html'
//WHO ATC IPS Valueset
valueset "WHO ATC": 'http://hl7.org/fhir/uv/ips/ValueSet/whoatc-uv-ips'
// General use ValueSets
valueset "Negative Result": 'https://worldhealthorganization.github.io/smart-example-immz/ValueSet-Negativetestresult-values.html'
valueset "Positive Result": 'https://worldhealthorganization.github.io/smart-example-immz/ValueSet-PositiveTestResult-values.html'
...
This library is then referenced by the other libraries whenever terminology needs to be referenced in CQL. This approach centralizes the management of CQL references to terminology throughout the SMART Guideline.
To provide a space for re-usable CQL declarations within the SMART Guideline, create a Common
library. For example:
library IMMZCommon
using FHIR version '4.0.1'
include FHIRHelpers version '4.0.1'
...
This library is then referenced by the other libraries whenever common logic needs to be shared between the logic libraries for each artifact.
Common libraries typically contain shared function definitions used throughout the various Elements, Logic, and Indicator libraries. For example, a fluent function in the IMMZCommon library:
/**
* @description Fetches a singleton protocol applied from an immunization
* @comment The protocol list from the immunization
*/
define fluent function only(protocols List<FHIR.Immunization.ProtocolApplied>):
singleton from protocols
NOTE: Common libraries are an organizing capability of CQL, and multiple common libraries MAY be created to facilitate sharing as appropriate for organizing the logic defined in the SMART Guideline. For example, logic may be organized around particular topic areas so that logic needed for recommendations related to a particular topic can be shared, without requiring that logic to be shared everywhere. Depending on the size of complexity of a SMART Guideline, multiple common libraries can be used to organized and share the logic. In addition, libraries may be refactored as needed when sharing patterns are recognized as the content develops.
To allow for configuration options to be referenced within CQL logic, define a Config
library. For example:
library IMMZConfig
define "High incidence of TB and/or high leprosy burden": true
define "Polio-endemic country with high risk of spread": true
...
NOTE: This approach supports configuration as part of the definition of the logic. To support more dynamic configuration, consider the CodeSystem supplement approach used in the Opioid MME IG. This approach allows configuration options to be defined within a CodeSystem resource, and then referenced from the CQL (and anywhere else that needs them), rather than establishing configuration values in the CQL directly.
To allow CQL logic to reference data elements defined in the SMART Guideline, create an Elements
library with an expression for each data element defined in the data dictionary. For example:
library IMMZElements
using FHIR version '4.0.1'
include FHIRHelpers version '4.0.1'
include fhir.cqf.common.FHIRCommon called FC
include WHOConcepts
include WHOCommon called WC
include WHOElements called WE
include IMMZConcepts called Concepts
include IMMZCommon called IC
context Patient
/*
* Measles elements
*/
define "MCV Dose":
[Immunization: Concepts."MCV Vaccine"] MCV
where MCV.status = 'completed'
and MCV.isSubpotent is not true
define "MCV Primary Series Dose":
"MCV Dose" MCV
where exists (
MCV.protocolApplied Protocol
where Protocol.series = 'primary'
)
define "MCV Supplementary Dose":
"MCV Dose" MCV
where exists (
MCV.protocolApplied Protocol
where Protocol.series = 'supplementary'
)
define "MCV Dose 0 Dose":
"MCV Dose" MCV
where exists (
MCV.protocolApplied Protocol
where Protocol.series = 'dose 0'
)
Note that these expressions are not tied to any particular timeframe, they are only tied to the Patient
context and provide a basis for sharing the definition of data elements between decision support, scheduling logic, and indicator logic. These expressions are rarely, if ever, used on their own; instead, they are used by inclusion in the EncounterElements and IndicatorElements libraries, as shown in the following sections.
The EncounterElements
library defines data elements from the perspective of an encounter, and allows the data elements to be referenced from decision support logic as part of the evaluation of recommendations at the point of care (i.e. for an Encounter); while the IndicatorElements
library defines the data elements from the perspective of an indicator, and allows the data elements to be referenced as part of the definition of an indicator (i.e. with a Measurement Period). For example:
library IMMZEncounterElements
using FHIR version '4.0.1'
include FHIRHelpers version '4.0.1'
include WHOConcepts
include WHOCommon called WC
include WHOEncounterElements called WE
include IMMZConcepts called Concepts
include IMMZCommon called Common
include IMMZElements called Elements
parameter Today Date default Today()
parameter EncounterId String
context Patient
/*
* Measles elements
*/
define "MCV Dose":
Elements."MCV Dose" MCV
where MCV.occurrence.toInterval() on or before Today
define "MCV Primary Series Dose":
Elements."MCV Primary Series Dose" MCV
where MCV.occurrence.toInterval() on or before Today
define "MCV Supplementary Dose":
Elements."MCV Supplementary Dose" MCV
where MCV.occurrence.toInterval() on or before Today
define "MCV Dose 0 Dose":
Elements."MCV Dose 0 Dose" MCV
where MCV.occurrence.toInterval() on or before Today
Note the inclusion of the IMMZElements
library called Elements
; this allows the definitions in this library to extend the base element definitions from the encounter perspective. Consider the MCV Primary Series Dose
element from the base Elements
library:
define "MCV Primary Series Dose":
"MCV Dose" MCV
where exists (
MCV.protocolApplied Protocol
where Protocol.series = 'primary'
)
An MCV Primary Series Dose
is an MCV Dose
(i.e. Measles Containing Vaccine Dose) where the protocol series has a value of primary
. This definition is then contextualized in the EncounterElements
library to identify only those primary series doses that occurred on or before today:
define "MCV Primary Series Dose":
Elements."MCV Primary Series Dose" MCV
where MCV.occurrence.toInterval() on or before Today
Similarly, the MCV Doses Administered To Patient
expression in the indicator elements contextualizes the MCV Dose
element to only those that occurred during the measurement period:
define "MCV Doses Administered to Patient During Measurement Period":
Elements."MCV Dose" I
where I.occurrence.toInterval() starts during "Measurement Period"
By organizing the data elements in this way, the definitions that are common to both decision support and indicators can be shared.
Each decision support rule, scheduling rule, or measure (indicator), should have its own logic library containing all and only the expressions that are referenced from the FHIR PlanDefinition or Measure resource. This approach allows the logic for each artifact to be organized alongside the artifact. Note that if logic needs to be reorganized so that it can be reused among multiple artifacts, create a common library to support the common definitions.
CQL Libraries are named after the decision/scheduling/measure. For example:
/*
@DecisionID: IMMZ.D2.DT.Measles.Ongoing transmission
@BusinessRule: Determine if the client is due for a measles vaccination according to the national immunization schedule
@Trigger: IMMZ.D2 Determine required vaccination(s) if any
@Description: Countries with ongoing transmission in which the risk of measles mortality remains high (countries that provide first dose of MCV at 9 months and second dose of MCV at 15 months)
*/
library IMMZD2DTMeaslesOTLogic
using FHIR version '4.0.1'
include FHIRHelpers version '4.0.1'
include WHOCommon called WC
include IMMZD2DTMeaslesLogic called Logic
parameter Today default Today()
Note the use of tags:
Create expressions for all input columns with tags:
Input | CQL code |
---|---|
Client's age is less than 9 months Today's date - "Date of birth" < 9 'month' |
/* @input: Client's age is less than 9 months @pseudocode: Today's date - "Date of birth" < 9 'month' */ define "Client's age is less than 9 months": //Code goes here |
NOTE: Expressions in the logic library that are not referenced directly by the artifact MAY be marked with the
private
access modifier to make clear that only the expressions referenced by the artifact are intended to be used from the library. The private expressions are only used within the library.
Create one output CQL file for each Table (e.g., Countries with ongoing transmission in which the risk of measles mortality remains high -> IMMZD2DTMeaslesHighTx.cql)
Create expressions for each output and guidance with tags:
Client is due for MCV1"Immunization recommendation status" = 'Due' |
/* @output: Client is due for MCV1 @pseudocode: "Immunization recommendation status" = 'Due' */ define "Client is due for MCV1": // input expressions that use this output: "No measles primary series doses were administered"; "Client's age is more than or equal to 9 months" ; "No live vaccine was administered in the last four weeks" |
Client is less than 9 months. Check for any vaccines due, and inform the caregiver of when to come back for MCV1 administration. |
/* @output: Client is due for MCV1 Guidance<br>@guidance: Client is less than 9 months. Check for any vaccines due, and inform the caregiver of when to come back for MCV1 administration. */ define: "Client is due for MCV1 Guidance": 'Client is less than 9 months. Check for any vaccines due, and inform the caregiver of when to come back for MCV1 administration.' |
Sometimes the same expression may appear in multiple outputs that have different inputs. For example:
Client is not due for MCV1 can be from
In this case, the author can for example:
Include a single expression called Guidance to return the main Guidance to be sent using the PlanDefintion. This is to avoid proliferation of actions in the PlanDefinition. Tag this as a dynamicValue.
/* @dynamicValue: Guidance<br>*/ define "Guidance": case when "Output 1" then "Output 1 Guidance" when "Output 2" then "Output 2 Guidance" else null end |
Include any other dynamic values that are needed for the PlanDefinition in the output CQL.
Tag any other expressions needed as private
.
Create or reuse ActivityDefinitions depending on what FHIR resources need to be created from the Decision Tables. This will include a CommunicationRequest to alert the Health Worker to the Guidance that will be output.
Create PlanDefintions for each Decision Table that references the output CQL libraries.
Create actions as needed to reference the ActivityDefinitions that are created, including the CommunicationRequest for Guidance.
Include any dynamicValues here to maintain reusability of the ActivityDefinitions.
Create at least enough Test resources for each row in the Decision Tables.
To enable end-to-end testing and better understanding, The test resources should follow the test scenario that is used for the other resources (Questionnaires, etc.)
Append Case # to each (e.g., Case 1, Case 2). Include an overall output that checks all the Cases. Have 1 Guidance expression that checks each case and returns the appropriate guidance.
Include a single expression called Guidance to return the main Guidance to be sent using the PlanDefintion. This is to avoid proliferation of actions in the PlanDefinition. Tag this as a dynamicValue.
It is important to keep the ActivityDefinitions simple and reusable. For example by avoiding dynamicValues in ActivityDefinitions. Since each output CQL is associated with a PlanDefintion, all dynamicValues may go into the PlanDefinition resources. This avoids the many ActivityDefinitions having have an associated Library.
Code should be tagged:
private
for any expressions needed to use for whatever else (like the list of Immunizations)@dynamicValue:
for anything used as a dynamic value in the PlanDefinition.@input:
) for the bolded part, and @pseudocode:
for the code. Also do @output:
for bolded with @pseudocode:
for the rest. Use @guidance:
to include the text to display for the "alert" (CommunicationRequest). Authors should use the same @output:
expression and appended "Guidance" for the guidance expression in cql.Every input in the Decision and Scheduling tables shall have a CQL expression Every input in the Decision and Scheduling tables should have a concept in a CodeSystem
As with all FHIR Conformance resources, change management is critical. Do not set the version element of libraries defined in the SMART Guideline, the version element will be set by the publication process. See the versioning topic for more information on change management.
Tool | Usage | Documentation |
---|---|---|
CQF tooling | Parse and process CQL files into Libraries. | |
VisualStudio plugin | Validate CQL expressions. | |
CQF Ruler | A FHIR server with CQL functionality included |
[SMART Guidelines - Immunizations (Measles): Example ActorDefinition(https://worldhealthorganization.github.io/smart-example-immz/ActorDefinition-CommunityHealthWorker.html) SMART Guidelines - Immunizations (Measles): Rendered set of ActorDefinitions
Each CQL code must have its wrapper FHIR resource. For this, the corresponding Libraries must exist.
The IG Publisher is able to parse CQL libraries