cqframework / clinical_quality_language

Clinical Quality Language (CQL) is an HL7 specification for the expression of clinical knowledge that can be used within both the Clinical Decision Support (CDS) and Clinical Quality Measurement (CQM) domains. This repository contains complementary tooling in support of that specification.
https://confluence.hl7.org/display/CDS/Clinical+Quality+Language
Apache License 2.0
251 stars 121 forks source link

FHIR/QICore MedicationRequest strange translation output #1363

Open hossenlopp opened 1 month ago

hossenlopp commented 1 month ago

While looking at the ELM of CMS130FHIR-v0.1.000 from the January 2024 Connectathon bundles, we noticed a peculiar translation of a retrieve on MedicationRequest.

The AdvancedIllnessandFrailty 1.8.000 CQL Library has the following define statement:

define "Has Dementia Medications in Year Before or During Measurement Period":
  exists (( ([MedicationRequest: "Dementia Medications"]).isMedicationActive()) DementiaMedication
      where DementiaMedication.doNotPerform is not true and
      CMD."MedicationRequestPeriod" ( DementiaMedication ) overlaps day of Interval[start of "Measurement Period" - 1 year, 
        end of "Measurement Period"]

In this define statement the [MedicationRequest: "Dementia Medications"] appears to be translated into ELM with extra logic to handle MedicationRequests which reference a Medication resource to grab the actual code for the medication.

{
  "localId": "180",
  "locator": "99:13-99:57",
  "type": "Union",
  "resultTypeSpecifier": {
    "type": "ListTypeSpecifier",
    "elementType": {
      "name": "{http://hl7.org/fhir}MedicationRequest",
      "type": "NamedTypeSpecifier"
    }
  },
  "operand": [
    {
      "dataType": "{http://hl7.org/fhir}MedicationRequest",
      "templateId": "http://hl7.org/fhir/us/qicore/StructureDefinition/qicore-medicationrequest",
      "codeProperty": "medication",
      "codeComparator": "in",
      "type": "Retrieve",
      "codes": {
        "locator": "99:34-99:55",
        "resultTypeName": "{urn:hl7-org:elm-types:r1}ValueSet",
        "name": "Dementia Medications",
        "preserve": true,
        "type": "ValueSetRef"
      }
    },
    {
      "locator": "99:14-99:56",
      "type": "Query",
      "resultTypeSpecifier": {
        "type": "ListTypeSpecifier",
        "elementType": {
          "name": "{http://hl7.org/fhir}MedicationRequest",
          "type": "NamedTypeSpecifier"
        }
      },
      "source": [
        {
          "locator": "99:14-99:56",
          "alias": "MR",
          "expression": {
            "dataType": "{http://hl7.org/fhir}MedicationRequest",
            "templateId": "http://hl7.org/fhir/us/qicore/StructureDefinition/qicore-medicationrequest",
            "type": "Retrieve"
          }
        }
      ],
      "relationship": [
        {
          "locator": "99:14-99:56",
          "alias": "M",
          "type": "With",
          "expression": {
            "dataType": "{http://hl7.org/fhir}Medication",
            "templateId": "http://hl7.org/fhir/us/qicore/StructureDefinition/qicore-medication",
            "type": "Retrieve"
          },
          "suchThat": {
            "type": "And",
            "operand": [
              {
                "type": "Equal",
                "operand": [
                  {
                    "path": "id",
                    "scope": "M",
                    "type": "Property"
                  },
                  {
                    "type": "Last",
                    "source": {
                      "type": "Split",
                      "stringToSplit": {
                        "path": "medication.reference",
                        "scope": "MR",
                        "type": "Property"
                      },
                      "separator": {
                        "valueType": "{urn:hl7-org:elm-types:r1}String",
                        "value": "/",
                        "type": "Literal"
                      }
                    }
                  }
                ]
              },
              {
                "type": "InValueSet",
                "code": {
                  "path": "code",
                  "type": "Property"
                },
                "valueset": {
                  "locator": "99:34-99:55",
                  "resultTypeName": "{urn:hl7-org:elm-types:r1}ValueSet",
                  "name": "Dementia Medications",
                  "preserve": true
                }
              }
            ]
          }
        }
      ]
    }
  ]
}

In CQL this looks like:

[MedicationRequest: "Dementia Medications"] 
  union ([MedicationRequest] MR
    with [Medication] M
      such that M.id = Last(Split(MR.medication.reference, '/')) and code in "Dementia Medications")

There is a bit of a bug here that would prevent it from working in the case of referencing a Medication. The InValueSet expression seen towards the end of the ELM snippet compares against a Property expression that does not have a scope or source defined. This would not return any value or error out and will not be able to compare the Medication type. This should have a scope of M. Making the equivalent CQL M.code in "Dementia Medication"

There is also a concern with the efficiency of this logic. It currently is asking for EVERY MedicationRequest and with each MedicationRequest it is asking for EVERY Medication and then looking for the one with the matching id. Since we know the referenced id it could be used to directly fetch the Medication resource with the id field of the Retrieve expression. There doesn't appear to be a way do do this in CQL at the moment.