-
Notifications
You must be signed in to change notification settings - Fork 0
Gaps in Care Tutorial
This tutorial will give an in-depth guide for calculating the "gaps in care" for a specific FHIR-based eCQM using the $care-gaps operation.
- Basic understanding of eCQM populations ("Numerator", "Denominator", etc.) and CQL
- Test server is running locally. Follow the installation instructions for running locally
-
NOTE: This tutorial will use
http://localhost:3000
as the server location. If your location differs, replace with your proper host and port
-
NOTE: This tutorial will use
- Measure exists on the test server. See Measure-Bundle-Upload for how to upload a Measure Bundle
The $care-gaps
operation seeks to provide detailed information about why a patient might not be calculating into the desired population criteria for a given eCQM. A good example to conceptualize this is the Colorectal Cancer Screening eCQM.
For this measure, patients calculating into the "Numerator" population increase the measure score. The following snippet from the measure logic shows one of the ways a patient could calculate into the "Numerator":
define "Colonoscopy Performed":
[Procedure: "Colonoscopy"] Colonoscopy
where Colonoscopy.status = 'completed'
and Global."Normalize Interval"(Colonoscopy.performed) ends
10 years or less on or before end of "Measurement Period"
define "Numerator":
exists "Colonoscopy Performed"
// ...
// other clauses snipped for brevity
// ...
Any of the following scenarios constitutes a gap in care for this specific example:
- The patient has not had a colonoscopy at all
- The patient did have a colonoscopy, but it was longer than 10 years ago relative to the measurement period
- The patient did have a colonoscopy, but it was incorrectly modeled in FHIR (i.e.
status
was not'completed'
)
$care-gaps
will use a FHIR GuidanceResponse resource to convey detailed information about which data elements the measure logic queried for, along with why the given patient
did not satisfy that criteria.
$care-gaps
may be invoked using an HTTP GET
or POST
(GET
is recommended for simplicity, but they behave exactly the same server-side). Send an HTTP GET
request to the following URL:
http://localhost:3000/4_0_1/Measure/$care-gaps?status=open-gap&periodStart=<your-period-start>&periodEnd=<your-period-end>&measureId=<your-measure-id>&subject=Patient/<your-patient-id>
- Replace
<your-period-start>
and<your-period-end>
with the desired measurement period. Use theyyyy-mm-dd
format - Replace
<your-measure-id>
with theid
of the FHIR Measure resource to calculate gaps for- If you are unsure what the
id
is, send aGET
request tohttp://localhost:3000/4_0_1/Measure
to see a list of all Measure resources available on the server
- If you are unsure what the
- Replace
<your-patient-id>
with theid
of the FHIR Patient resource to calculate gaps for- If you are unsure what the
id
is, send aGET
request tohttp://localhost:3000/4_0_1/Patient
to see a list of all Patient resources available on the server
- If you are unsure what the
For a full list of allowed parameters, refer to the OperationDefinition. Note that the $care-gaps
implementation on deqm-test-server
is a work in progress, and not all parameters may be supported.
The response for an invocation of $care-gaps
is a FHIR Parameters Resource.
If no gaps in care are found, the parameter
array of the response will be empty:
{
"resourceType": "Parameters",
"parameter": []
}
NOTE: Defining the spec for what should be returned in cases of "no gaps" is under active development, and may change in the future
If there are gaps in care found for the patient, the parameter
array of the response will contain a Gaps in Care Bundle. This bundle contains some metadata about the gap(s),
along with references to DEQM DetectedIssue resource(s) which contain the information about the found gap.
The locations of the DetectedIssue resources within the gaps bundle can be found in the section[0].entry
list of the Composition resource within the gaps bundle:
{
"resourceType": "Composition",
"type": {
"coding": [
{
"system": "http://hl7.org/fhir/us/davinci-deqm/CodeSystem/gaps-doc-type",
"code": "gaps-doc",
"display": "Gaps in Care Report"
}
]
},
"author": [
{
"reference": "Patient/<your-patient-id>"
}
],
"subject": {
"reference": "Patient/<your-patient-id>"
},
"date": "<a datetime for when the report was generated>",
"title": "Gaps in Care Report",
"status": "preliminary",
"section": [
{
"title": "<canonical url of measure resource>",
"focus": {
"reference": "MeasureReport/<measurereport-unique-id>"
},
"entry": [
{
"reference": "DetectedIssue/<detectedissue-unique-id>"
}
]
}
]
}
We can see in Composition.section[0].entry[0]
, there is a reference to a DetectedIssue resource with id <detectedissue-unique-id>
. This resource will exist within the entry
array of the gaps bundle returned by the operation (many details snipped for brevity indicated by ...
):
{
"resourceType": "DetectedIssue",
"id": "<detectedissue-unique-id>",
"status": "final",
"code": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/detectedissue-category",
"code": "care-gap",
"display": "Gap in Care Detected"
}
]
},
"evidence": [
{
"detail": [
{
"reference": "#<contained-guidanceresponse-id>"
}
]
}
...
],
"contained": [
{
"resourceType": "GuidanceResponse",
"id": "<contained-guidanceresponse-id>",
"status": "data-required",
"moduleUri": "<canonical url of measure resource>"
...
}
]
}
NOTE: A formal proposal for a DEQM GuidanceResponse profile is under active development.
A gaps in care GuidanceResponse contains two important sections of information
- Detailed information about the FHIR data element queried for by the measure logic that contributed to this gap (E.g. Procedure, Observation, etc.). This lives within the
dataRequirement
of the GuidanceResponse - Detailed information about why the query for this data element contributed to the gap. This lives within the
reasonCode
of the GuidanceResponse
The key pieces of information that may be present in dataRequirement
are type
, codeFilter
, dateFilter
, and a custom value filter extension.
The following is an example dataRequirement
that could be present on one of these GuidanceResponse resources:
{
"type": "Observation",
"codeFilter": [
{
"path": "code",
"valueSet": "http://example.com/example-valueset"
},
{
"path": "status",
"code": [
{
"code": "final",
"system": "http://hl7.org/fhir/observation-status"
}
]
}
],
"dateFilter": [
{
"path": "effective",
"valuePeriod": {
"start": "2019-01-01T00:00:00.000Z",
"end": "2019-12-31T00:00:00.000Z"
}
}
],
"extension": [
{
"url": "http://hl7.org/fhir/us/cqfmeasures/StructureDefinition/cqfm-valueFilter",
"extension": [
{
"url": "path",
"valueString": "value"
},
{
"url": "comparator",
"valueCode": "eq"
},
{
"url": "value",
"valueRange": {
"high": {
"value": 9,
"unit": "%"
}
}
}
]
}
]
}
In English, this data requirement is asking for all of the following:
- FHIR Observation resources whose
.code
property comes from the"http://example.com/example-valueset"
AND - whose
.status
property isfinal
AND - whose
.effective[x]
property lies within the range2019-01-01 - 2019-12-31
AND - whose
.value[x]
property is less than9%
Importantly, dataRequirement
is only conveying what the measure was looking for, not any detailed information about why the specific gap occurred.
The information for why a gap occurred lives within the reasonCode
property of the GuidanceResponse. For the current list of reasonCode
codes and displays used,
see these definitions in the gaps in care calculation engine.
Basic reason codes convey whether a gap occurred because of data being absent or present from a patient's record. This is the simplest representation of reasonCode
, and will be commonly seen
when there is no existing data on the patient record to interpret, or the gaps in care engine reaches complicated measure logic that it does not now how to process.
{
"coding": [
{
"system": "http://hl7.org/fhir/us/davinci-deqm/CodeSystem/care-gap-reason",
"code": "NotFound",
"display": "Data Element Not Found"
}
]
}
{
"coding": [
{
"system": "http://hl7.org/fhir/us/davinci-deqm/CodeSystem/care-gap-reason",
"code": "Present",
"display": "Data Element is Present"
}
]
}
A reasonCode
can have a ReasonDetail
extension on it when the gaps in care engine is able to process additional information about why a specific data element contributed to a gap.
The ReasonDetail
extension provides information on:
- What specific resource on the patient record contributed to the gap for this GuidanceResponse
- What property on that resource is related to the
reasonCode
that we're seeing
An example of this concept is if a data element was out of the desired date range for the measure logic:
{
"coding": [
{
"system": "http://hl7.org/fhir/us/davinci-deqm/CodeSystem/care-gap-reason",
"code": "DateOutOfRange",
"display": "Date is out of specified range",
"extension": [
{
"url": "http://hl7.org/fhir/us/davinci-deqm/StructureDefinition/reasonDetail",
"extension": [
{
"url": "reference",
"valueReference": {
"reference": "Observation/<some-observation-id>"
}
},
{
"url": "path",
"valueString": "effective.end"
}
]
}
]
}
]
}
This reasonCode
is indicating that a gap was caused by the effective.end
property on the Observation with id <some-observation-id>
being out of the proper range defined by the dateFilter
on the dataRequirement
In practice, a lot of measures have population criteria that can be satisfied in multiple different ways. For a good example of this, we can again return to the Colorectal Cancer Screening eCQM:
define "Numerator":
exists "Colonoscopy Performed"
or exists "Fecal Occult Blood Test Performed"
or exists "Flexible Sigmoidoscopy Performed"
or exists "Fecal Immunochemical Test DNA"
or exists "CT Colonography Performed"
A patient can land in the Numerator population if any of the above data element definitions are satisfied. Therefore, a potential gap for this eCQM can be closed via any combination of five different data elements. To represent this, we use multiple GuidanceResponse resources contained within the same DetectedIssue resource.
In short, resolving any of the GuidanceResponses within one DetectedIssue resource will resolve the gap indicated by that DetectedIssue resource.
The following is a full example of the $care-gaps
return result for a patient with a gap for the Colorectal Cancer Screening eCQM.
In this example, the patient did have a colonoscopy, but it was performed outside of the 10 year range defined by the measurement period.
http://localhost:3000/4_0_1/Measure/$care-gaps?status=open-gap&periodStart=2019-01-01&periodEnd=2019-12-31&measureId=measure-EXM130-7.3.000&subject=Patient/denom-EXM130
{
"resourceType": "Parameters",
"parameter": [
{
"name": "return",
"resource": {
"resourceType": "Bundle",
"type": "document",
"entry": [
{
"resource": {
"resourceType": "Composition",
"type": {
"coding": [
{
"system": "http://hl7.org/fhir/us/davinci-deqm/CodeSystem/gaps-doc-type",
"code": "gaps-doc",
"display": "Gaps in Care Report"
}
]
},
"author": [
{
"reference": "Patient/denom-EXM130"
}
],
"subject": {
"reference": "Patient/denom-EXM130"
},
"date": "2022-04-04T18:14:57.132Z",
"title": "Gaps in Care Report",
"status": "preliminary",
"section": [
{
"title": "http://hl7.org/fhir/us/cqfmeasures/Measure/EXM130",
"focus": {
"reference": "MeasureReport/eddf30ae-a237-4e13-8991-4bcfc0297af9"
},
"entry": [
{
"reference": "DetectedIssue/a784d0d8-144d-4781-9d99-33b917409e3a"
}
]
}
]
}
},
{
"resource": {
"id": "eddf30ae-a237-4e13-8991-4bcfc0297af9",
"resourceType": "MeasureReport",
"period": {
"start": "2019-01-01",
"end": "2019-12-31"
},
"status": "complete",
"type": "individual",
"measure": "http://hl7.org/fhir/us/cqfmeasures/Measure/EXM130",
"contained": [
{
"resourceType": "Observation",
"code": {
"text": "sde-ethnicity"
},
"id": "d5740f53-dddc-4643-8764-d2a2f46c7e13",
"status": "final",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/cqf-measureInfo",
"extension": [
{
"url": "measure",
"valueCanonical": "http://hl7.org/fhir/us/cqfmeasures/Measure/EXM130"
},
{
"url": "populationId",
"valueString": "sde-ethnicity"
}
]
}
],
"valueCodeableConcept": {
"coding": [
{
"system": "urn:oid:2.16.840.1.113883.6.238",
"code": "2135-2",
"display": "Hispanic or Latino"
}
]
}
},
{
"resourceType": "Observation",
"code": {
"text": "sde-payer"
},
"id": "cbbfb999-6b10-4aa7-b264-16d8190df477",
"status": "final",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/cqf-measureInfo",
"extension": [
{
"url": "measure",
"valueCanonical": "http://hl7.org/fhir/us/cqfmeasures/Measure/EXM130"
},
{
"url": "populationId",
"valueString": "sde-payer"
}
]
}
],
"valueCodeableConcept": {
"coding": []
}
},
{
"resourceType": "Observation",
"code": {
"text": "sde-race"
},
"id": "291c373a-56c6-4689-bc8a-ec13545a6a73",
"status": "final",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/cqf-measureInfo",
"extension": [
{
"url": "measure",
"valueCanonical": "http://hl7.org/fhir/us/cqfmeasures/Measure/EXM130"
},
{
"url": "populationId",
"valueString": "sde-race"
}
]
}
],
"valueCodeableConcept": {
"coding": [
{
"system": "urn:oid:2.16.840.1.113883.6.238",
"code": "2028-9",
"display": "Asian"
}
]
}
},
{
"resourceType": "Observation",
"code": {
"text": "sde-sex"
},
"id": "bb831359-7d05-41f3-a723-1a17455c3569",
"status": "final",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/cqf-measureInfo",
"extension": [
{
"url": "measure",
"valueCanonical": "http://hl7.org/fhir/us/cqfmeasures/Measure/EXM130"
},
{
"url": "populationId",
"valueString": "sde-sex"
}
]
}
],
"valueCodeableConcept": {
"coding": [
{
"system": "http://hl7.org/fhir/v3/AdministrativeGender",
"code": "M",
"display": "Male"
}
]
}
}
],
"text": {
"status": "generated",
"div": "<!-- snipped for brevity -->"
},
"group": [
{
"id": "group-1",
"population": [
{
"count": 1,
"code": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/measure-population",
"code": "initial-population",
"display": "Initial Population"
}
]
}
},
{
"count": 0,
"code": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/measure-population",
"code": "numerator",
"display": "Numerator"
}
]
}
},
{
"count": 1,
"code": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/measure-population",
"code": "denominator",
"display": "Denominator"
}
]
}
},
{
"count": 0,
"code": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/measure-population",
"code": "denominator-exclusion",
"display": "Denominator Exclusion"
}
]
}
}
],
"measureScore": {
"value": 0
}
}
],
"evaluatedResource": [
{
"reference": "#d5740f53-dddc-4643-8764-d2a2f46c7e13"
},
{
"reference": "#cbbfb999-6b10-4aa7-b264-16d8190df477"
},
{
"reference": "#291c373a-56c6-4689-bc8a-ec13545a6a73"
},
{
"reference": "#bb831359-7d05-41f3-a723-1a17455c3569"
},
{
"reference": "Patient/denom-EXM130"
},
{
"reference": "Procedure/denom-EXM130-2"
},
{
"reference": "Encounter/denom-EXM130-1"
}
],
"subject": {
"reference": "Patient/denom-EXM130"
}
}
},
{
"resource": {
"id": "denom-EXM130",
"birthDate": "1965-01-01",
"extension": [
{
"url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race",
"extension": [
{
"url": "ombCategory",
"valueCoding": {
"system": "urn:oid:2.16.840.1.113883.6.238",
"code": "2028-9",
"display": "Asian"
}
}
]
},
{
"url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity",
"extension": [
{
"url": "ombCategory",
"valueCoding": {
"system": "urn:oid:2.16.840.1.113883.6.238",
"code": "2135-2",
"display": "Hispanic or Latino"
}
}
]
}
],
"gender": "male",
"identifier": [
{
"use": "usual",
"type": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "MR",
"display": "Medical Record Number"
}
]
},
"system": "http://hospital.smarthealthit.org",
"value": "999999992"
}
],
"meta": {
"profile": ["http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient"]
},
"name": [
{
"family": "Dere",
"given": ["Ben"]
}
],
"resourceType": "Patient"
}
},
{
"resource": {
"resourceType": "DetectedIssue",
"id": "a784d0d8-144d-4781-9d99-33b917409e3a",
"status": "final",
"code": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/detectedissue-category",
"code": "care-gap",
"display": "Gap in Care Detected"
}
]
},
"evidence": [
{
"detail": [
{
"reference": "#07eb93fc-5254-49e2-a38a-fcbfd9d57060"
}
]
},
{
"detail": [
{
"reference": "#8d347b16-e035-49b4-8c6e-a06f1fe689fb"
}
]
},
{
"detail": [
{
"reference": "#50fdd9bf-1831-4013-9903-893a5b1fac56"
}
]
},
{
"detail": [
{
"reference": "#5ce79052-da15-49b1-8b09-a5f4992fbc09"
}
]
},
{
"detail": [
{
"reference": "#9e89d798-098c-45e4-a87e-e2eea68cc414"
}
]
}
],
"contained": [
{
"resourceType": "GuidanceResponse",
"id": "07eb93fc-5254-49e2-a38a-fcbfd9d57060",
"dataRequirement": [
{
"type": "Procedure",
"codeFilter": [
{
"path": "code",
"valueSet": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.3.464.1003.108.12.1020"
},
{
"path": "status",
"code": [
{
"code": "completed",
"system": "http://hl7.org/fhir/event-status"
}
]
}
],
"dateFilter": [
{
"path": "performed.end",
"valuePeriod": {
"start": "2009-12-31T00:00:00.000Z",
"end": "2019-12-31T00:00:00.000Z"
}
}
]
}
],
"reasonCode": [
{
"coding": [
{
"system": "http://hl7.org/fhir/us/davinci-deqm/CodeSystem/care-gap-reason",
"code": "DateOutOfRange",
"display": "Date is out of specified range",
"extension": [
{
"url": "http://hl7.org/fhir/us/davinci-deqm/StructureDefinition/reasonDetail",
"extension": [
{
"url": "reference",
"valueReference": {
"reference": "Procedure/denom-EXM130-2"
}
},
{
"url": "path",
"valueString": "performed.end"
}
]
}
]
}
]
}
],
"status": "data-required",
"moduleUri": "http://hl7.org/fhir/us/cqfmeasures/Measure/EXM130"
},
{
"resourceType": "GuidanceResponse",
"id": "8d347b16-e035-49b4-8c6e-a06f1fe689fb",
"dataRequirement": [
{
"type": "Observation",
"codeFilter": [
{
"path": "code",
"valueSet": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.3.464.1003.198.12.1011"
},
{
"path": "status",
"code": [
{
"code": "final",
"system": "http://hl7.org/fhir/observation-status"
},
{
"code": "amended",
"system": "http://hl7.org/fhir/observation-status"
},
{
"code": "corrected",
"system": "http://hl7.org/fhir/observation-status"
},
{
"code": "preliminary",
"system": "http://hl7.org/fhir/observation-status"
}
]
}
],
"extension": [
{
"url": "http://hl7.org/fhir/us/cqfmeasures/StructureDefinition/cqfm-valueFilter",
"extension": [
{
"url": "path",
"valueString": "value"
},
{
"url": "comparator",
"valueCode": "eq"
},
{
"url": "value",
"valueString": "not null"
}
]
}
],
"dateFilter": [
{
"path": "effective",
"valuePeriod": {
"start": "2019-01-01T00:00:00.000Z",
"end": "2019-12-31T00:00:00.000Z"
}
}
]
}
],
"reasonCode": [
{
"coding": [
{
"system": "http://hl7.org/fhir/us/davinci-deqm/CodeSystem/care-gap-reason",
"code": "NotFound",
"display": "Data Element Not Found"
}
]
}
],
"status": "data-required",
"moduleUri": "http://hl7.org/fhir/us/cqfmeasures/Measure/EXM130"
},
{
"resourceType": "GuidanceResponse",
"id": "50fdd9bf-1831-4013-9903-893a5b1fac56",
"dataRequirement": [
{
"type": "Procedure",
"codeFilter": [
{
"path": "code",
"valueSet": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.3.464.1003.198.12.1010"
},
{
"path": "status",
"code": [
{
"code": "completed",
"system": "http://hl7.org/fhir/event-status"
}
]
}
],
"dateFilter": [
{
"path": "performed.end",
"valuePeriod": {
"start": "2014-12-31T00:00:00.000Z",
"end": "2019-12-31T00:00:00.000Z"
}
}
]
}
],
"reasonCode": [
{
"coding": [
{
"system": "http://hl7.org/fhir/us/davinci-deqm/CodeSystem/care-gap-reason",
"code": "NotFound",
"display": "Data Element Not Found"
}
]
}
],
"status": "data-required",
"moduleUri": "http://hl7.org/fhir/us/cqfmeasures/Measure/EXM130"
},
{
"resourceType": "GuidanceResponse",
"id": "5ce79052-da15-49b1-8b09-a5f4992fbc09",
"dataRequirement": [
{
"type": "Observation",
"codeFilter": [
{
"path": "code",
"valueSet": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.3.464.1003.108.12.1039"
},
{
"path": "status",
"code": [
{
"code": "final",
"system": "http://hl7.org/fhir/observation-status"
},
{
"code": "amended",
"system": "http://hl7.org/fhir/observation-status"
},
{
"code": "corrected",
"system": "http://hl7.org/fhir/observation-status"
},
{
"code": "preliminary",
"system": "http://hl7.org/fhir/observation-status"
}
]
}
],
"extension": [
{
"url": "http://hl7.org/fhir/us/cqfmeasures/StructureDefinition/cqfm-valueFilter",
"extension": [
{
"url": "path",
"valueString": "value"
},
{
"url": "comparator",
"valueCode": "eq"
},
{
"url": "value",
"valueString": "not null"
}
]
}
],
"dateFilter": [
{
"path": "effective.end",
"valuePeriod": {
"start": "2016-12-31T00:00:00.000Z",
"end": "2019-12-31T00:00:00.000Z"
}
}
]
}
],
"reasonCode": [
{
"coding": [
{
"system": "http://hl7.org/fhir/us/davinci-deqm/CodeSystem/care-gap-reason",
"code": "NotFound",
"display": "Data Element Not Found"
}
]
}
],
"status": "data-required",
"moduleUri": "http://hl7.org/fhir/us/cqfmeasures/Measure/EXM130"
},
{
"resourceType": "GuidanceResponse",
"id": "9e89d798-098c-45e4-a87e-e2eea68cc414",
"dataRequirement": [
{
"type": "Procedure",
"codeFilter": [
{
"path": "code",
"valueSet": "http://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.3.464.1003.108.12.1038"
},
{
"path": "status",
"code": [
{
"code": "completed",
"system": "http://hl7.org/fhir/event-status"
}
]
}
],
"dateFilter": [
{
"path": "performed.end",
"valuePeriod": {
"start": "2014-12-31T00:00:00.000Z",
"end": "2019-12-31T00:00:00.000Z"
}
}
]
}
],
"reasonCode": [
{
"coding": [
{
"system": "http://hl7.org/fhir/us/davinci-deqm/CodeSystem/care-gap-reason",
"code": "NotFound",
"display": "Data Element Not Found"
}
]
}
],
"status": "data-required",
"moduleUri": "http://hl7.org/fhir/us/cqfmeasures/Measure/EXM130"
}
]
}
}
]
}
}
]
}