-
Notifications
You must be signed in to change notification settings - Fork 1
Pathways on FHIR
This page serves as documentation of our approach to representing oncology clinical pathways with mCODE, using the Clinical Practice Guidelines Implementation Guide (CPG IG) and related FHIR Clinical Reasoning resources
The fundamental goal of this project is to bring the mCODE data standard into the world of oncology clinical pathways. Camino is a mature prototype intended to demonstrate the art of the possible with mCODE - automatically reading a patient's record and applying a pathway to see what's already been completed, and highlight the next recommendation for action from the user. But Camino's data model is not a standard - it's a very simple JSON structure, inspired heavily by Synthea's generic modules, and designed purely to support the features of the prototype. In order to drive true interoperability we need to work within existing standards where possible.
The Clinical Reasoning module provides resources and operations to enable the representation, distribution, and evaluation of clinical knowledge artifacts such as clinical decision support rules, quality measures, public health indicators, order sets, and clinical protocols. In addition, the module describes how expression languages can be used throughout the specification to provide dynamic capabilities.
Clinical Reasoning involves the ability to represent and encode clinical knowledge in a very broad sense so that it can be integrated into clinical systems. This encoding may be as simple as controlling whether or not a particular section of an order set appears based on the conditions that a patient has, or it may be as complex as representing the care pathway for a patient with multiple conditions.
ref: http://www.hl7.org/fhir/clinicalreasoning-module.html
FHIR Clinical Reasoning provides the baseline resources that we will be using to represent pathways on FHIR, including but not limited to PlanDefinition, ActivityDefinition, and Library.
[The CPG IG] supports the development of standards-based computable representations of the content of clinical care guidelines. Its content pertains to technical aspects of digital guidelines implementation and is intended to be usable across multiple use cases across clinical domains as well as in the International Realm.
The CPG IG builds profiles on top of the Clinical Reasoning resources to ensure that clinical decision support artifacts are shareable, computable, and executable.
The IG's goals are:
- Direct:
- Reduce duplicate development effort involved in the implementation of clinical practice guideline recommendations in clinical systems
- Reduce unnecessary and/or unintentional variability in clinical practice guideline implementation
- Indirect:
- Minimize the time needed to implement clinical practice guideline recommendations in clinical systems
By translating the recommendations in clinical practice guidelines at the source, and disseminating a computable version along with the narrative version of the guidelines, the effort of translation would not be repeated across every organization that intends to apply the recommendations. Likewise, unnecessary or unintentional variations as a result of duplicative translation efforts could be prevented with a standard, computable version that is ready to be implemented.
The CPG IG is currently under active development, but has contributors from leading organizations, most notably the CDC: http://build.fhir.org/ig/HL7/cqf-recommendations/index.html#acknowledgements
Note: the hierarchy of profiles within the CPG IG is Shareable < Computable < Publishable < Executable. We should generally aim to implement the highest level (i.e., Executable) whenever possible, unless there is a compelling reason not to.
We want to support two basic paradigms for pathway creation:
- Small, modularized pathways, which represent a single phase of "action" and can be linked together in various ways
- Large, longitudinal pathways, which represent an entire sequence of care, with branching options, for a certain kind of cancer
These can both be created using three basic concepts:
- "actions", where a clinical activity, such as a prescription, procedure, or chemo regimen may be requested
- "branches", where some aspect of the patient's demographics or their condition drives the path of care in one of multiple directions
- "references" to other pathways or pathway pieces
Because the FHIR resources depend on boolean-valued expressions as well as allow for more complex logic to drive dynamic values, there are multiple approaches that pathways could be represented using FHIR and CQL.
One extreme is to include all branching and evaluation logic within the CQL itself, and the FHIR only represents a single action of "do whatever the CQL says to do next". That's generally against the spirit of the CPG data model though, and probably not easy to maintain either. The ideal approach would logically split out the FHIR and CQL to leverage each one's strengths.
The central resource in all of this is the PlanDefinition
, with ActivityDefinition
, Library
, and CarePlan
resources also involved.
A plan definition is a pre-defined group of actions to be taken in particular circumstances, often including conditional elements, options, and other decision points.
In short, a PlanDefinition is a very generic resource type that allows for a lot of flexibility in what it represents. We will be using PlanDefinition as the foundation of our guidelines, in a few different ways.
The basic concept of a PlanDefinition is that it links together actions
. An action is a single "step", which includes the specific "thing" to do as well as applicability statement that evaluates whether or not that "thing" is appropriate. Actions may represent sequential steps, as determined by action.relatedAction.relationship
, or all actions may be concurrent if no links are provided. Actions can refer to specific activities which generate Request-type resources via an ActivityDefinition, or to other PlanDefinitions. Actions can also have nested sub-actions.
The "publishable" level profile for PlanDefinition, which is the minimal level we should aim for.
Required fields:
- title, date
- url, version, name, experimental, publisher, description
- extension
cpg-knowledgeCapability
= shareable | computable | publishable | executable
Further profiles (below) build on this one, to define a "Pathway", a "Strategy", and a "Recommendation".
In short, a "Pathway" groups together "Strategies", and a "Strategy" groups together "Recommendations". One "Recommendation" would align with one or more actions and the direct preconditions for whether those actions were applicable. The "Strategy" would link together those recommendations sequentially, and then the "Pathway" would represent a comprehensive grouping of all strategies. For example, one might imagine a "Pathway" for Breast Cancer, a "Strategy" for "Neoadjuvant Therapy for HER2 Positive" (aligning with how we currently define a "pathway" within Camino), and a "Recommendation" for a chemotherapy regimen (aligns with a single action node or multiple sequential action nodes within Camino).
The most complete resource for explaining the relationship between the "Pathway", "Strategy", and "Recommendation" is at http://build.fhir.org/ig/HL7/cqf-recommendations/documentation-approach-12-03-cpg-plan.html
"A pathway provides groupings of strategies to provide a longitudinal view of the guideline"
Profile diff:
-
type
=- system: "http://terminology.hl7.org/CodeSystem/plan-definition-type"
- code: "clinical-protocol"
- display: "Clinical Protocol"
- each
action
:- definition[x] fixed to
canonical(PlanDefinition)
, not ActivityDefinition. So a Pathway only groups together other PlanDefinitions, it doesn't define specific actions by itself - title, description, code required
- some other fields disallowed: input, output, relatedAction, type, *Behavior, transform, dynamicValue
- definition[x] fixed to
"Strategies are used to group recommendations together, typically focused on a particular condition or state within the overall guideline or pathway"
Profile diff:
-
type
=- system: "http://terminology.hl7.org/CodeSystem/plan-definition-type"
- code: "workflow-definition"
- display: "workflow-definition"
- each
action
:- definition[x] fixed to
canonical(PlanDefinition)
, not ActivityDefinition. So a Strategy also only groups together other PlanDefinitions, it doesn't define specific actions by itself - title, description, code required
- some other fields disallowed: type, *Behavior (except selectionBehavior), transform, dynamicValue
- definition[x] fixed to
Mapping Camino Pathways into Strategies
Camino "transitions" map into PlanDefinition as well, as the "applicability"-type conditions on actions. This is where the CQL determining whether an action is appropriate will be placed.
Note: Camino includes additional CQL on each action to determine when the action has been performed, to move execution onto the next node in the pathway. We can include that here, but it doesn't align super well with a one-time execution philosophy. My suggestion is we leave that "is X done?" and "is X in progress?" CQL out, and it will be an implementation detail of whatever system processes the RequestGroup within the CarePlan.
Profile diff:
-
type
=- system: "http://terminology.hl7.org/CodeSystem/plan-definition-type"
- code: "workflow-definition"
- display: "workflow-definition"
- each
action
:- definition[x] fixed to
canonical(ActivityDefinition)
, not PlanDefinition. So a Recommendation must be self-contained, and does not link to others (Any links to "subsequent" actions must be represented in a parent Strategy or Pathway definition)
- definition[x] fixed to
The operation that makes the PlanDefinition useful is the $apply operation. This operation takes a PlanDefinition, a Patient, and optionally a few other fields as context, and evaluates the PlanDefinition against the Patient to return a CarePlan. (Note the CarePlan is only returned as the result of the operaition, not automatically saved to the Patient's record.) The resulting CarePlan will contain one single RequestGroup, with nested requests for applicable actions within the PlanDefinition.
The CPG IG does not constrain or affect the PlanDefinition$apply operation in any way. The core FHIR specification on the operation is here: https://www.hl7.org/fhir/plandefinition-operation-apply.html
The ActivityDefinition
resources represent the detailed definition of "actions" as described above. If an activity is determined to be applicable, then the fields will be used to populate a corresponding Request resource, such as a ServiceRequest or MedicationRequest.
ActivityDefinition
maps fairly cleanly to the details within "Action Nodes" in Camino today.
ActivityDefinition
allows for a "statically" defined resource to be produced, using the code
, product
, and supporting fields to define a template for a resource of the right kind
, but also allows for dynamic values and transformations, using the dynamicValue
and transform
fields. My recommendation is we stick to "static" resources for simplicity.
The IG also defines "kind"-based profiles for the specific types of requests that can be produced with an ActivityDefinition. The two key ones for us are for MedicationRequest
s and ServiceRequests
, highlighted below.
Defines the minimum expectations and behavior for the definition of a medication request activity for use with content conforming to the CPG implementation guide
- sets
kind
= "MedicationRequest" - sets
profile
= "http://hl7.org/fhir/uv/cpg/StructureDefinition/cpg-medicationrequest"- note:
profile
is 1..1, but there is no mCODE profile for MedicationRequest so this should be fine
- note:
- sets
intent
= "proposal" - note:
product[x]
is not required (still 0..1) but we should expect to always include a productCodeableConcept with the appropriate RxNorm code here
Defines the minimum expectations and behavior for the definition of a service request activity for use with content conforming to the CPG implementation guide
- sets
kind
= "ServiceRequest" - sets
profile
= "http://hl7.org/fhir/uv/cpg/StructureDefinition/cpg-servicerequest"- note:
profile
is 1..1, but there is no mCODE profile for ServiceRequest so this should be fine
- note:
- sets
intent
= "proposal" - note:
code
is not required (still 0..1) but we should expect to always include a procedure code with an appropriate SNOMED code here
TODO: how do we want to represent "start a chemo regimen"? or do we want to represent the chemo regimen directly within CPG? Technically we can continue to represent a chemo regimen as a CarePlan, as CarePlan is a supported "kind" within ActivityDefinition.
The Library
resource is referenced from PlanDefinition
resources to include the executable logic that drives the plan.
Key fields:
-
content
: Attachment - where the actual CQL containing expressions that drive the pathway will be contained, in base64.- note that
content
is cardinality0..*
so we can probably include both the CQL as well as the compiled ELM here
- note that
We should aim for CPGExecutableLibrary
which expects:
- title, type, and date
-
content
to include- one attachment for CQL (i.e., the "computable" level)
- one for ELM JSON or XML (i.e., the "executable" level)
- extension
cpg-knowledgeCapability
= "executable"
The CarePlan
resource is the result of applying a Patient resource against a PlanDefinition. According to the FHIR spec:
The result of [the PlanDefinition$apply] operation is a CarePlan resource with a single activity represented by a RequestGroup. The RequestGroup will have actions for each of the applicable actions in the plan based on evaluating the applicability condition in context.
(ref: https://www.hl7.org/fhir/operation-plandefinition-apply.html , at the bottom)
Note there is a profile CPGCarePlan
however since we don't expect to generate the CarePlan ourselves, we'll use cqf-ruler or another library, the details of that profile are omitted here. Similarly there are profiles on other activities which will come out of the CarePlan: http://build.fhir.org/ig/HL7/cqf-recommendations/profiles.html#activity-profiles which we may have to review if we build a system that directly uses CPG pathways.
Note there are currently no profiles on RequestGroup
.
cqf-ruler "is an implementation of FHIR's Clinical Reasoning Module and serves as a knowledge artifact repository and clinical decision support service." In practical terms, cqf-ruler is the only* FHIR server that will allow us to use the PlanDefinition$apply operation with a Patient and get back a CarePlan resource with appropriate actions.
( * = the IBM FHIR server may also support some of what we want to do based on this discussion and linked PR, but the docker image doesn't seem to work out of the box)
The implementation of the PlanDefinition$apply operation is here: https://github.com/DBCG/cqf-ruler/blob/master/r4/src/main/java/org/opencds/cqf/r4/providers/PlanDefinitionApplyProvider.java and the implementation of ActivityDefinition$apply, which PlanDefinition$apply calls for each action, is here: https://github.com/DBCG/cqf-ruler/blob/master/r4/src/main/java/org/opencds/cqf/r4/providers/ActivityDefinitionApplyProvider.java
The basic flow of PlanDefinition$apply
is as follows:
- for each
action
in PlanDefinition:- if all "applicability" conditions with type "text/cql" in
condition
are met:- note it only appears to support CQL, not ELM
- note that nested sub-actions are evaluated, presumably to for exceptions, but their applicability is not used anywhere, nor are nested sub-actions ever "applied"
- find the referenced ActivityDefinition from
definitionCanonical
- note: the spec allows this to be a PlanDefinition, but only ActivityDefinitions are currently supported
- call
ActivityDefinition$apply
:- note at this point the ActivityDefinition is completely standalone, it has no link back to the PlanDefinition
- depending on
kind
, one of the following resource types will be populated:- ServiceRequest
- requires
code
ordynamicValue
-
dosage
andproduct
not allowed
- requires
- MedicationRequest
- requires
product
-
bodySite
,code
, andquantity
not allowed
- requires
- SupplyRequest
- Procedure*
- DiagnosticReport*
- Communication*
- CommunicationRequest
- sets
ActivityDefinition.code.text
asCommunicationRequest.payload.content
- sets
- ( * = not actually allowed by the spec? see https://www.hl7.org/fhir/activitydefinition-definitions.html#ActivityDefinition.kind)
- note: the FHIR spec allows additional types, noted below, but the above are the only types supported in cqf-ruler
- Appointment
- AppointmentResponse
- CarePlan
- Claim
- Contract
- DeviceRequest
- EnrollmentRequest
- ImmunizationRecommendation
- NutritionOrder
- Task
- VisionPrescription
- ServiceRequest
- apply any
dynamicValue
s from the ActivityDefinition, if any, to the activity result - return the activity result
- apply any
dynamicValue
s from the PlanDefinition.action, if any, to the result - note it does not use any other fields on PlanDefinition.action, such as
relatedAction
,trigger
,input
/'output`, etc...
- if all "applicability" conditions with type "text/cql" in
There is also a resolveCdsHooksPlanDefinition
function, which is never actually directly called in the code that I can see, and it has the comment "For library use". At a glance it seems much more robust, including for example generating RequestGroups which the $apply version does not, and this comment on an issue in the repo confirms that: https://github.com/DBCG/cqf-ruler/issues/45#issuecomment-389242647