Skip to content

Pathways on FHIR

Dylan Hall edited this page Jul 31, 2020 · 16 revisions

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

Background

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.

FHIR Clinical Guidelines

(Put a brief summary of the CPG IG and FHIR clinical reasoning module here. Copious links encouraged)

Note: the hierarchy of profiles within the CPG IG is Shareable < Computable < Shareable < Executable. We should always aim to implement the highest level (i.e., Executable) whenever possible, unless there is a compelling reason not to.

Approach

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 for a patient's cancer

These can both be created using two 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 or their condition drives the path of care in one of multiple directions

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.

Resources/Profiles

The central resource in all of this is the PlanDefinition, with ActivityDefinition, Library, and CarePlan resources also involved.

PlanDefinition

Profiles

Name Description
CPGPublishablePathwayDefinition ...
CPGPathwayDefinition ...
CPGStrategyDefinition ...
CPGRecommendationDefinition ...

ActivityDefinition

The ActivityDefinition resources represent the detailed definition of "actions" as described above. If an activity is determined to be applicable, then the code and/or product[x] fields will be used to populate a corresponding Request resource.

Library

CarePlan

The CarePlan resource is the result of applying a Patient resource against a PlanDefinition.

Examples

Minimal/Modularized Example

Complete/Longitudinal Example

Notes on CQF Ruler

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 or dynamicValue
            • dosage and product not allowed
          • MedicationRequest
            • requires product
            • bodySite, code, and quantity not allowed
          • SupplyRequest
          • Procedure*
          • DiagnosticReport*
          • Communication*
          • CommunicationRequest
            • sets ActivityDefinition.code.text as CommunicationRequest.payload.content
          • ( * = 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
        • apply any dynamicValues from the ActivityDefinition, if any, to the activity result
        • return the activity result
      • apply any dynamicValues 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...

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, and this comment on an issue in the repo confirms that: https://github.com/DBCG/cqf-ruler/issues/45#issuecomment-389242647

Clone this wiki locally