OHSU Hypertension Implementation Guide
0.1.0 - CI Build Unknown region code '840'

OHSU Hypertension Implementation Guide, published by Oregon Health and Science University. This is not an authorized publication; it is the continuous build for version 0.1.0). This version is based on the current content of https://github.com/OHSUCMP/htnu18ig/ and changes regularly. See the Directory of published versions

Using CQF Ruler

Overview

CQF Ruler is a HAPI FHIR Server implementation with extensions built-in to implement FHIR's Clinical Reasoning Module, allowing it to execute CQL.

In this system, CQL is used to encode the workflows associated with evaluating different hypertension-related recommendations for a given Patient record. These workflows are triggered via CQF Ruler's CDS Hooks execution framework, each of which incorporates clinical data about the Patient (Observations, Conditions, etc.) obtained either via "prefetch" block attached to the request itself, or by way of direct FHIR queries executed by CQF Ruler in response to required resources that are missing from the prefetch.

When a CDS Hook is executed, the associated PlanDefinition resource is processed, which in turn executes CQL that represents the Recommendation logic. Once completed, resultant Cards are returned, which are then parsed by the client application, and is used to drive how the user-interface is rendered to the user.

See the Detailed Specification for more information on how this process occurs.

Installation

To install CQF Ruler, use git to execute the following:

/git $ git clone https://github.com/DBCG/cqf-ruler.git
This will clone the current version of CQF Ruler to the folder in which the above command was executed.

Running the Service

To run CQF Ruler, use Apache Maven to execute the following:

/git/cqf-ruler $ mvn -Djetty.port=8080 jetty:run -am --projects cqf-ruler-r4
This will execute the CQF Ruler service, using its FHIR R4 configuration, on localhost port 8080.

Note that at the time of this writing, CQF Ruler must be run on port 8080 in order for CDS Services to operate correctly. See this issue documented on CQF Ruler's bug tracker for details.

Configuration

To configure CQF Ruler with artifacts in this Implementation Guide, use the PopulateCQFRuler.py script found in this IG's input/ folder:

/git/htnu18ig/input $ python PopulateCQFRuler.py
CQF Ruler URL = http://localhost:8080/cqf-ruler-r4/fhir/
processing valueset-2.16.840.1.113762.1.4.1032.10.json
processing valueset-2.16.840.1.113762.1.4.1032.124.json
processing valueset-2.16.840.1.113762.1.4.1047.511.json
processing valueset-2.16.840.1.113762.1.4.1104.2.json
processing valueset-2.16.840.1.113762.1.4.1108.15.json
processing valueset-2.16.840.1.113762.1.4.1116.418.json
processing valueset-2.16.840.1.113762.1.4.1116.420.json
processing valueset-2.16.840.1.113762.1.4.1146.1330.json
processing valueset-2.16.840.1.113762.1.4.1178.10.json
processing valueset-2.16.840.1.113762.1.4.1195.111.json
processing valueset-2.16.840.1.113762.1.4.1222.24.json
processing valueset-2.16.840.1.113883.3.3157.4012.json
processing valueset-2.16.840.1.113883.3.464.1003.106.11.1030.json
processing valueset-2.16.840.1.113883.3.464.1003.195.12.1003.json
processing valueset-2.16.840.1.113883.3.526.2.1045.json
processing valueset-2.16.840.1.113883.3.526.2.422.json
processing valueset-2.16.840.1.113883.3.526.2.590.json
processing valueset-2.16.840.1.113883.3.526.3.378.json
processing valueset-2.16.840.1.113883.3.526.3.509.json
processing valueset-2.16.840.1.113883.3.600.1.1490.json
processing valueset-2.16.840.1.113883.3.600.2012.json
processing library-AdverseEvents.json
processing library-FHIR-ModelInfo.json
processing library-FHIRHelpers.json
processing library-Hypertension.json
processing library-HypertensiveEmergency.json
processing library-Monitoring.json
processing library-NonPharmacologicIntervention.json
processing library-OHSUHTNCommon.json
processing library-Pharma.json
processing plandefinition-AdverseEvents.json
processing plandefinition-Hypertension.json
processing plandefinition-HypertensiveEmergency.json
processing plandefinition-Monitoring.json
processing plandefinition-NonPharmacologicIntervention.json
processing plandefinition-Pharma.json
processing cqf-tooling.json

/git/htnu18ig/input $

Retrieving Available CDS Hooks to Request

To retrieve a list of executable CDS Hooks available on a running instance of CQF Ruler, perform an HTTP GET to http://localhost:8080/cqf-ruler-r4/cds-services, which will return a JSON array of services, with each object in the list representing a CDS Hook, e.g.:

~ $ wget -qO- http://localhost:8080/cqf-ruler-r4/cds-services
{
  "services": [
    {
      "hook": "patient-view",
      "name": "Hypertension",
      "title": "Hypertension Diagnosis",
      "description": "This PlanDefinition identifies hypertension",
      "id": "plandefinition-Hypertension",
      "prefetch": {
        "item1": "Patient?_id\u003d",
        "item2": "Patient?_id\u003dPatient/",
        "item3": "Condition?patient\u003dPatient/\u0026category\u003dhttp://terminology.hl7.org/CodeSystem/condition-category|problem-list-item",
        "item4": "Condition?patient\u003dPatient/\u0026category\u003dhttp://terminology.hl7.org/CodeSystem/condition-category|encounter-diagnosis",
        "item5": "Observation?subject\u003dPatient/\u0026code\u003dhttp://loinc.org|55284-4"
      }
    },
    <!-- cut -->
  ]
}
~ $
See CDS Hooks HTTP Request for details.

Executing CDS Hook Requests

To execute a CDS Hook, collect any FHIR resources to include in the prefetch per these instructions, and execute an HTTP POST to the appropriate CDS Services Hook endpoint, per these instructions.

HACK : Adverse Events

Adverse Events are processed a little differently in this system. They are conceived to originate as a collection of Conditions that map to a specific, curated set of CodeSystems represented in this ValueSet. Matching Condition resources are queried and converted by the client application into AdverseEvent resources, each of which must contain the following event CodeSystem in order to be recognized and processed by the Recommendation logic:

"event": {
  "coding": [
    {
      "system": "https://coach.ohsu.edu",
      "code": "coach-adverse-event",
    }
  ]
}
These constructed AdverseEvent resources must be included in the prefetch block on calls to CQF Ruler via CDS Services when processing Recommendations.

This is done in large part due to the environment in which this system was developed, which employs a FHIR server backed by an Epic system. At the time of development, Epic requires a ResearchStudy FHIR ID to be included in any AdverseEvent searches, which in the context of our usage both doesn't make sense, and we don't have any such FHIR IDs to reference, making searching for all AdverseEvent resources for a given Patient impossible. In fact, an error is thrown by the FHIR server if a study FHIR ID isn't included on an AdverseEvent search, which cascades through CQF Ruler causing the Recommendation execution to crash. See Epic's FHIR API Specification for AdverseEvent.Search (R4) for details.

Because of this limitation, at least one AdverseEvent resource must be included in the prefetch block, even if logically none exist. To account for this edge case, a dummy AdverseEvent must be crafted and included in the prefetch block, such as the following:

{
  "fullUrl": "adverseevent-FAKE-HACK",
  "resource": {
    "resourceType": "AdverseEvent",
    "id": "adverseevent-FAKE-HACK",
    "event": {
      "coding": [
        {
          "system": "https://coach.ohsu.edu",
          "code": "coach-fake-adverse-event",
          "display": "***FAKE*** Adverse Event generated by COACH to prevent CQF-Ruler from querying the FHIR server"
        }
      ]
    },
    "subject": {
      "reference": "https://example.com/fhir/Patient/SomeTestPatientID"
    },
    "date": "2021-11-24T14:40:54-08:00"
  }
}
Note that almost anything will do when populating the dummy AdverseEvent resource, just so long as it does not have a valid event CodeSystem (as defined above).

Processing Cards into POJOs using Google GSON

The client application developed alongside this Implementation Guide (COACH) uses Google Gson to deserialize JSON objects produced by CQF Ruler into Java Objects for further processing. See this code fragment for technical details relating to how the JSON is deserialized and processed.

Note: There is limited functionality at this time by CQF Ruler allowing CQL to populate CDS Hook Card attributes. The attributes that may be populated in this manner are limited to summary, detail, and indicator. As such, in order to pass back the kind of structured data required by the system against which this IG has been developed, these additional data are serialized and transmitted via the Card's detail attribute (i.e. "rationale").

Note: All data serialized into the Card response is processed by the client application through the Mustache templating engine, in order to tailor the displayed text to the appropriate Audience, either patient or careTeam. That is, when a user logs into the client application via a patient context, any text enclosed within {{#careTeam}}...{{/careTeam}} will be discarded, prior to display. Similarly, when a user logs into the client application via an EHR context, any text enclosed within {{#patient}}...{{/patient}} will be discarded, prior to display.