Code Monkey home page Code Monkey logo

cqframework / clinical_quality_language Goto Github PK

View Code? Open in Web Editor NEW
245.0 53.0 119.0 26.09 MB

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.

Home Page: https://confluence.hl7.org/display/CDS/Clinical+Quality+Language

License: Apache License 2.0

C# 5.80% Java 93.26% ANTLR 0.89% Batchfile 0.02% TSQL 0.03%
cql clinical-quality-language cds java cqm fhir fhir-path clinical-decision-support clinical-quality-measurement clinical-data

clinical_quality_language's Introduction

Maven Central project chatContributor Covenant

Clinical Quality Language

Clinical Quality Language (CQL) is a Health Level 7 (HL7) standard for the expression of clinical knowledge that can be used within a broad range of clinical domains, including Clinical Decision Support (CDS), and Clinical Quality Measurement (CQM).

This repository contains documentation, examples, and tooling in support of the CQL specification, including a CQL compiler and ELM runtime.

Background

CQL was developed as part of the Clinical Quality Framework (CQF) initiative, a public-private partnership sponsored by the Centers for Medicare & Medicaid Services (CMS) and the U.S. Office of the National Coordinator for Health Information Technology (ONC) to identify, develop, and harmonize standards for clinical decision support and electronic clinical quality measurement.

The Clinical Quality Language specification is maintained by the HL7 Clinical Decision Support (CDS) Work Group with co-sponsorship from the HL7 Clinical Quality Information (CQI) Work Group.

Scope

The primary focus of the tooling in this repository is to support and enable adoption and implementation of the Clinical Quality Language specification. In particular, the CQL-to-ELM translator provides a reference implementation for syntactic and semantic validation of Clinical Quality Language. As such, the features and functionality provided by these tools are ultimately defined by the CQL specification, and that specification is the source-of-truth for those requirements. This relationship to the CQL standard heavily informs and shapes the change management policies for maintenance of these tools.

Community

The CQL community consists of multiple stakeholders including EHR vendors, clinical knowledge content vendors, knowledge artifact authors, and clinical quality content tool vendors. We encourage participation from these and other relevant stakeholders, and the processes and policies described here are intended to enable participation and support of the CQL tooling. Because this community of stakeholders both depends on and provides feedback to these tools, their participation in these processes is vital.

Change Management

Changes to the tooling maintained within this repository are managed using as lightweight a process as possible, while still ensuring stable, viable, production quality software. These processes are described in the Change Management topic.

Contents

Cloning This Repository

Some of the tests in this repository have long paths which require this setting for git on Windows:

git config --system core.longpaths true

License

All code in this repository is licensed under the Apache License 2.0. All documentation is licensed under the Creative Common Attribution 4.0 International license (CC BY 4.0).

CQL compiler/translator, grammar, and associated tooling: Copyright 2014 The MITRE Corporation

ELM runtime and associated components (specifically the java/engine and java/engine-fhir modules): Copyright 2016 University of Utah

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

clinical_quality_language's People

Contributors

athenaecascketta avatar barhodes avatar bryantaustin13 avatar brynrhodes avatar c-monkey avatar c-schuler avatar chris0296 avatar cmoesel avatar csandersdev avatar duncand avatar erichbschulz avatar hadleynet avatar holmesie avatar hossenlopp avatar iasmile avatar jamesagnew avatar jawalonoski avatar jbradl11 avatar jpercival avatar jreyno77 avatar jsrankins avatar lukedegruchy avatar mdnazmulkarim avatar msargentibm avatar mulcahyk avatar pkmitre avatar rdingwell avatar sliver007 avatar tangiblezero avatar vitorpamplona avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

clinical_quality_language's Issues

CQL-to-ELM DSTU2 translator fails with choice properties

CQL-to-ELM translator for DSTU2 Observation “Obs.effectiveDateTime” does not work, error is "Member effectiveDateTime not found for type FHIR.Observation". The parent choice element “Obs.effective" does not cause errors. The effectiveDateTime property exists in DSTU2 Observation and the equivalent path works in ELM.

FunctionRefs to Overloaded Functions

CQL/ELM allows for the overloading of functions. For example:

define function MostRecent(ObsList List<Observation>):
  Last(ObsList O sort by O.issued)

define function MostRecent(CondList List<Condition>):
  Last(CondList C sort by C.effectiveDateTime)

This is a great feature, but can be difficult to implement in an execution environment because when it is used, the FunctionRef in ELM does not indicate which of the overloaded functions to use:

{
  "name" : "MostRecent",
  "type" : "FunctionRef",
  "operand" : [ {
    "name" : "LDLTests",
    "type" : "ExpressionRef"
  } ]
}

Implementors need to analyze the chain of expressions behind each operand to infer the return types of each before they can choose the correct version of the function to invoke. Given that the CQL-to-ELM already has to do this inference when validating the CQL, it would be helpful if it used that information to generate more specific ELM function invocations. Perhaps something like:

{
  "name" : "MostRecent",
  "type" : "FunctionRef",
  "operandTypeSpecifiers" : [ {
    "type" : "ListTypeSpecifier",
    "elementType" : {
      "name" : "{http://hl7.org/fhir}Observation",
      "type" : "NamedTypeSpecifier"
    }
  } ]
  "operand" : [ {
    "name" : "LDLTests",
    "type" : "ExpressionRef"
  } ]
}

Or when you define a FunctionDef in ELM, give it a unique local identifier that is a hash of the argument types, and then reference that in the FunctionRef as well. In this way, the FunctionRef might look more like:

{
  "name" : "MostRecent",
  "type" : "FunctionRef",
  "functionIdentifier": "2f68523b6f0738c8194d6d76e9ffdb30",
  "operand" : [ {
    "name" : "LDLTests",
    "type" : "ExpressionRef"
  } ]
}

installApp task has been deprecated

not sure if this is a problem for you - but just an fyi that my successful (yay!) build complained thusly:

The installApp task has been deprecated and is scheduled to be removed in Gradle 3.0. Please use       
the installDist task instead.

Add support for FHIR STU3

Now that FHIR STU3 is published, update the FHIR model info provider to reference the new version.

Add line information to the annotation output of the translator.

Per the following issue logged at the CQL Issues Tracker, we will add line information to the annotation output of the translator:

https://oncprojectracking.healthit.gov/support/browse/CQLIT-8

The approach involves adding an "li" element to the annotation that contains a string with the line information ":".

Because it's part of the annotations, it will not be part of the core ELM output.

We could also consider adding the li element to the base expression, and controlling output with a "debug" flag.

Library Alias being treated as an expression identifier

The following cql files pass validation:

Parent CQL Library

library parent version '0.0.000'

using QDM version '5.0.2'

include child version '1.0.000' called Alias1

context Patient

define "Def1": "Alias1"

Child CQL Library

library child version '1.0.000'

using QDM version '5.0.2'

context Patient

Notice, in the parent library, def1 is referencing Alias1 which is an included library.

The following ELM is generated:
Parent ELM

<?xml version="1.0" encoding="UTF-8"?>
<library xmlns="urn:hl7-org:elm:r1" xmlns:t="urn:hl7-org:elm-types:r1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:fhir="http://hl7.org/fhir" xmlns:a="urn:hl7-org:cql-annotations:r1">
   <identifier id="parent" version="0.0.000"/>
   <schemaIdentifier id="urn:hl7-org:elm" version="r1"/>
   <usings>
      <def localIdentifier="System" uri="urn:hl7-org:elm-types:r1"/>
      <def localIdentifier="QDM" uri="urn:healthit-gov:qdm:v5_0_1_draft" version="5.0.2"/>
   </usings>
   <includes>
      <def localIdentifier="Alias1" path="child" version="1.0.000"/>
   </includes>
   <statements>
      <def name="Patient" context="Patient">
         <expression xsi:type="SingletonFrom">
            <operand xmlns:ns0="urn:healthit-gov:qdm:v5_0_1_draft" dataType="ns0:Patient" templateId="Patient" xsi:type="Retrieve"/>
         </expression>
      </def>
      <def name="Def1" context="Patient" accessLevel="Public">
         <expression/>
      </def>
   </statements>
</library>

Child ELM

<?xml version="1.0" encoding="UTF-8"?>
<library xmlns="urn:hl7-org:elm:r1" xmlns:t="urn:hl7-org:elm-types:r1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:fhir="http://hl7.org/fhir" xmlns:a="urn:hl7-org:cql-annotations:r1">
   <identifier id="child" version="1.0.000"/>
   <schemaIdentifier id="urn:hl7-org:elm" version="r1"/>
   <usings>
      <def localIdentifier="System" uri="urn:hl7-org:elm-types:r1"/>
      <def localId="1" locator="3:1-3:25" localIdentifier="QDM" uri="urn:healthit-gov:qdm:v5_0_1_draft" version="5.0.2"/>
   </usings>
   <statements>
      <def name="Patient" context="Patient">
         <expression xsi:type="SingletonFrom">
            <operand xmlns:ns0="urn:healthit-gov:qdm:v5_0_1_draft" dataType="ns0:Patient" templateId="Patient" xsi:type="Retrieve"/>
         </expression>
      </def>
   </statements>
</library>

CQL-to-ELM Validation Issue Related to Undeclared Definitions

The following passes CQL-to-ELM validation:

library Hello

using QDM versino '5.0'

context Patient 

define "Initial Population":
    exists(Encounter) //note: the reference to the Encounter definition does not include quotes

Note that Encounter is not declared anywhere - just "Encounter". Is there a plan to update CQL-to-ELM to provide validation around use of non-declared items in CQL? If so, when?

No-Op Conversions

Previous versions of the cql-to-elm translator allowed CQL such as this:

define quantityToQuantity: convert 10 'g' to Quantity

The newest version (1.2) now creates an error:

Could not resolve conversion from type System.Quantity to type System.Quantity.

Is this a regression or does cql-to-elm now intentionally disallow conversions that are essentially no-ops (when source and target have the same type)?

Type name DateTime is ambiguous between DateTime and System.DateTime.

Found an issue while running the following through the updated CQL-to-ELM translator:

parameter "Measurement Period" Interval<DateTime>

The following errors occur:
[13:41, 13:48] Type name DateTime is ambiguous between DateTime and System.DateTime. [13:32, 13:49] org.hl7.elm.r1.Null cannot be cast to org.hl7.elm.r1.TypeSpecifier [13:1, 13:49] org.hl7.elm.r1.Null cannot be cast to org.hl7.elm.r1.TypeSpecifier

Per spec, this should be allowed. If I update to the following, the translator does not error:

parameter "Measurement Period" Interval<System.DateTime>

Thoughts?

SNAPSHOT-1.1.0 mistranslation of Exp and removal of Implies operator

I am experiencing a similar issue as the Time(x.x.x...) issue I posted back in June. The Exp operation is being translated as a function reference instead of a Exp expression. This is not an issue with the 1.2.0 SNAPSHOT. Also, has the implies operation been removed from the language? I do not see it in the expression.xsd...

Refactor error messages and improve message output

Although the translator defines exception classes, most of the errors thrown are Java base classes. Refactor those to use the appropriate exception class, add codes to enable lookup of error messages, and add reason and solution hint information support to error message output.

Name hiding error when using the same alias in different expressions

Attempting to use definitions that have the same alias names resolves incorrectly.

Specifically, from this example:

define "Numerator": 
  "Encounter Inpatient" Encounter
    where exists "Left Screen or Medical Reason" 
      and exists "Right Screen or Medical Reason"

define "Left Screen or Medical Reason": 
  from 
    ["Encounter, Performed": "Encounter Inpatient"] Encounter,
    "Newborn Hearing Screening Left" ScreenLeft,
    "Medical Reason Left" MedicalLeft
  where ScreenLeft.relevantPeriod during Encounter.relevantPeriod
    or MedicalLeft.relevantPeriod during Encounter.relevantPeriod

define "Right Screen or Medical Reason": 
  from 
    ["Encounter, Performed": "Encounter Inpatient"] Encounter,
    "Newborn Hearing Screening Right" ScreenRight,
    "Medical Reason Right" MedicalRight
  where ScreenRight.relevantPeriod during Encounter.relevantPeriod 
    or MedicalRight.relevantPeriod during Encounter.relevantPeriod

Using E as the alias instead of Encounter in the Left Screen or Medical Reason and Right Screen or Medical Reason expressions fixes the issue. With Encounter as the alias, the translator incorrectly resolves the type of the alias reference as a System.Code.

CQL File passes validation when referencing an undefined function

The cql file below is passing CQL validations:

library TEST version '1.0'

using QDM version '5.0.2'

parameter "Measurement Period" Interval<DateTime>

context Patient

define "TestDef": "TestFuncNotARealFunction"()

define function "TestFunc"(): true

When translated through the CQLtoELM parser, it produces the following ELM File:

<?xml version="1.0" encoding="UTF-8"?>
<library xmlns="urn:hl7-org:elm:r1" xmlns:t="urn:hl7-org:elm-types:r1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:fhir="http://hl7.org/fhir" xmlns:a="urn:hl7-org:cql-annotations:r1">
   <identifier id="TEST" version="1.0"/>
   <schemaIdentifier id="urn:hl7-org:elm" version="r1"/>
   <usings>
      <def localIdentifier="System" uri="urn:hl7-org:elm-types:r1"/>
      <def localIdentifier="QDM" uri="urn:healthit-gov:qdm:v5_0_1_draft" version="5.0.2"/>
   </usings>
   <parameters>
      <def name="Measurement Period" accessLevel="Public">
         <parameterTypeSpecifier xsi:type="IntervalTypeSpecifier">
            <pointType name="t:DateTime" xsi:type="NamedTypeSpecifier"/>
         </parameterTypeSpecifier>
      </def>
   </parameters>
   <statements>
      <def name="Patient" context="Patient">
         <expression xsi:type="SingletonFrom">
            <operand xmlns:ns0="urn:healthit-gov:qdm:v5_0_1_draft" dataType="ns0:Patient" templateId="Patient" xsi:type="Retrieve"/>
         </expression>
      </def>
      <def name="TestDef" context="Patient" accessLevel="Public">
         <expression name="TestFuncNotARealFunction" xsi:type="FunctionRef"/>
      </def>
      <def name="TestFunc" context="Patient" accessLevel="Public" xsi:type="FunctionDef">
         <expression valueType="t:Boolean" value="true" xsi:type="Literal"/>
      </def>
   </statements>
</library>

Should the "TestDef" definition have an error because it is referencing a function that does not exist?

Add the ability to detect references to elements that are not marked "mustSupport"

When logic is written against data models that include a "mustSupport" indicator, it would be useful to be able to issue warnings when that logic references elements of the model that are not marked "mustSupport". This would be a flag to consumers of an artifact using the logic to be sure that the behavior is not negatively impacted if the data is not present as expected.

ELM Annotations Data Duplication

I'm on the MITRE Bonnie team. I'm currently trying to create an html representation of the CQL that will have the appropriate data to enable logic highlighting.
My current attempts to derive cql from the XML ELM's annotations run into issues with duplicated information.

Does a strategy currently exist for re-creating CQL from the XML annotations and ignoring the duplication? If not, is this something that can be resolved during CQL-to-ELM generation?

Examples from CMS177:

  1. Element references duplicated in full.
    This snippet from the MDD Diagnosis annotation fully reproduces the contents of the MDD Encounter element. See references 58 and 48 below.

    In addition, reference 48 contains the following:
    "MDD Encounter" Encounter such that Diagnosis.prevalencePeriod overlaps Encounter.relevantPerioddefine "MDD Encounter":

    See bolded portion. This line seems incorrectly formatted, with the define statement being appended where it shouldn't be.

  <annotation xsi:type="a:Annotation">
    <a:s r="58">define "MDD Encounter": distinct (["Encounter, Performed": "Office Visit"] union ["Encounter, Performed": "Outpatient Consultation"] union ["Encounter, Performed": "Face-to-Face Interaction"] union ["Encounter, Performed": "Psych Visit - Diagnostic Evaluation"] union ["Encounter, Performed": "Psych Visit - Family Psychotherapy"] union ["Encounter, Performed": "Psych Visit - Psychotherapy"] union ["Encounter, Performed": "Psychoanalysis"]) Encounter    where Encounter.relevantPeriod during "Measurement Period"</a:s>
  </annotation>
<a:s r="49">                       
  <a:s r="48">"MDD Encounter" Encounter     such that Diagnosis.prevalencePeriod overlaps Encounter.relevantPerioddefine "MDD Encounter":
    <a:s r="47">distinct
      <a:s r="46">                                
        <a:s r="41">(
          <a:s r="40">                                      
            <a:s r="38">                                         
              <a:s r="36">                                            
                <a:s r="34">                                                
                  <a:s r="32">                                                  
                    <a:s r="30">                                                     
                      <a:s r="28">["Encounter, Performed": "Office Visit"]
                      </a:s> union
                    <a:s r="29">["Encounter, Performed": "Outpatient Consultation"]
                  </a:s>                                                  
                </a:s> union
              <a:s r="31">["Encounter, Performed": "Face-to-Face Interaction"]
            </a:s>                                               
          </a:s> union
        <a:s r="33">["Encounter, Performed": "Psych Visit - Diagnostic Evaluation"]
      </a:s>                                            
    </a:s> union
  <a:s r="35">["Encounter, Performed": "Psych Visit - Family Psychotherapy"]
</a:s>
  1. Annotations associated with certain clauses will contain summary lines either before or after the relevant child elements.
<annotation xsi:type="a:Annotation">
               <a:s r="70">
                 define "Age Demographic":
                 <a:s r="69">
                   <a:s r="63">
                     AgeInYearsAt(start of "Measurement Period") &gt;=
                     <a:s r="61">AgeInYearsAt(
                       <a:s r="60">start of
                         <a:s r="59">"Measurement Period"</a:s>
                       </a:s>
                       )
                     </a:s>
                      &gt;=
                     <a:s r="62">6</a:s>
                   </a:s>
                       and
                   <a:s r="68">
                     AgeInYearsAt(start of "Measurement Period") &lt;
                     <a:s r="66">
                       AgeInYearsAt(
                       <a:s r="65">
                         start of
                         <a:s r="64">"Measurement Period"</a:s>
                       </a:s>)
                     </a:s>
                      &lt;
                     <a:s r="67">17</a:s>
                   </a:s>
                 </a:s>
               </a:s>
             </annotation>

So you have AgeInYearsAt(start of "Measurement Period") which is then duplicated. This is also seen with less, lessorequal, equal, greaterorequal and equal type elements.

<a:s r="82">define "Suicide Risk":
  <a:s r="81">
    <a:s r="72">
      <a:s r="71">["Intervention, Performed": "Suicide Risk Assessment"]</a:s>
      Intervention
    </a:s>
                <a:s r="80">with
                  <a:s r="74">
                    <a:s r="73">"MDD Encounter"</a:s>
                    Encounter
                  </a:s>
                       such that
                  <a:s r="76">
                    <a:s r="75">Intervention</a:s>
                    .relevantPeriod
                  </a:s>
                   during
                  <a:s r="78">
                    <a:s r="77">Encounter</a:s>
                    .relevantPeriod
                  </a:s>
                  <a:s r="79">during</a:s>
                   Encounter.relevantPeriod
                </a:s>
              </a:s>
            </a:s>

Here we see the “during Encounter.relevantPeriod” clause duplicated in two different ways.

Thank you for your help.

Compiler errors for age functions

CQLIT-16

compiling this:

265 // @test: CalculateAge
266 define Years: AgeInYears()
267 define Months: AgeInMonths()
268 define Days: AgeInDays()
269 define Hours: AgeInHours()
270 define Minutes: AgeInMinutes()
271 define Seconds: AgeInSeconds()
272
273 define Age:
274 AgeInYearsAt(start of age_MeasurementPeriod)
275
276 // @test: CalculateAgeAt
277 define AgeAt2012: AgeInYearsAt(DateTime(2012))
278 define AgeAt19810216: AgeInYearsAt(DateTime(1981, 2, 16))
279 define AgeAt1975: AgeInYearsAt(DateTime(1975))

i get:

[266:15, 266:26] Internal translator error.
[267:16, 267:28] Internal translator error.
[268:14, 268:24] Internal translator error.
[269:15, 269:26] Internal translator error.
[270:17, 270:30] Internal translator error.
[271:17, 271:30] Internal translator error.
[274:3, 274:46] Internal translator error.
[277:19, 277:46] Internal translator error.
[278:23, 278:57] Internal translator error.
[279:19, 279:46] Internal translator error.

is this known?

and this on too...

define List_MixedList: List
{ 1, 'two', Three }

Execution Engine: Cannot Sort By Function

The execution engine fails when attempting to sort queries using a function. For example:

define function square (a System.Integer) :
  a * a

define SortBySquareFunction:
  ({1, 3, 2, 5, 4}) N sort by square(N)

When attempting to execute SortBySquareFunction, the execution engine throws an error like the following:

TypeError: Cannot read property 'parameters' of undefined
      at FunctionRef.module.exports.FunctionRef.FunctionRef.exec (lib/elm/reusable.js:87:38)
      at ByExpression.module.exports.ByExpression.ByExpression.exec (lib/elm/query.js:135:31)
      at lib/elm/query.js:191:28
      at Array.sort (native)
      at SortClause.module.exports.SortClause.SortClause.sort (lib/elm/query.js:184:23)
      at Query.module.exports.Query.Query.exec (lib/elm/query.js:301:14)
      at Context.<anonymous> (test/elm/reusable/test.coffee:52:27)

(NOTE: I previously thought this was an error related to using included libraries, but that is not the case, so I have edited the issue to reflect the real problem.)

QDM 5.0 Model Info

Questions about the following file: https://github.com/cqframework/clinical_quality_language/tree/modelinfo-profiles/Src/java/qdm/src/main/resources/gov/healthit/qdm/qdm-modelinfo-5.0.xml

First: The file contains the following label values for the patient characteristic datatypes:

  • Patient Characteristic: Birthdate
  • Patient Characteristic: Clinical Trial Participant
  • Patient Characteristic: Ethnicity
  • Patient Characteristic: Expired
  • Patient Characteristic: Payer
  • Patient Characteristic: Race
  • Patient Characteristic: Sex

Based on the draft QDM 5.0 document (https://ecqi.healthit.gov/system/files/qdm_5_0_draft_.pdf), none of these datatypes contain colons.

Second: It appears that the generic "Patient Characteristic" datatype is missing from the model info file. Since this datatype is part of QDM 5.0, how is this datatype being handled?

Third: There is a typo for the DeviceApplied element anatomialLocationSite - should be anatomicalLocationSite

List-valued expression was demoted to a singleton

Given the following CQL:

library Test version '1'
using QUICK
valueset "Ambulatory/ED Visit": '2.16.840.1.113883.3.464.1003.101.12.1061'
context Patient
define Visits: [Encounter: "Ambulatory/ED Visit"]

The CQL-to-ELM translator produces this warning:

Warning:[n/a] List-valued expression was demoted to a singleton.

Or in the generated XML:

<annotation message="List-valued expression was demoted to a singleton."
            errorType="semantic" 
            errorSeverity="warning" 
            xsi:type="a:CqlToElmError"/>

I don't see anything in the CQL that would necessitate a demotion to a singleton. The ELM XML does ensure Patient is a singleton, but this is normal and expected behavior. In addition, if I make the Foo expression evaluate to a literal (e.g., true) instead of the Retrieve, the warning goes away.

Escaped chars not translated to ELM correctly?

Given the following CQL:

define EscapeExample: 'Hello \'World\''

the CQL-to-ELM translator produces:

{
  "name" : "EscapeExample",
  "context" : "Patient",
  "accessLevel" : "Public",
  "expression" : {
    "valueType" : "{urn:hl7-org:elm-types:r1}String",
    "value" : "Hello \\'World\\'",
    "type" : "Literal"
  }
}

Is this intentional? I would have expected the ELM to remove the escape characters since they're no longer necessary (rather than double-escaping them). In other words, I expected "value" : "Hello 'World'", not "value" : "Hello \\'World\\'".

Minimum date test case

Minimum Date Test Case CQLIT-17

i note the spec says (p154):

Description:
The DateTime type represents date and time values with potential uncertainty within CQL.
CQL supports date and time values in the range @0001-01-01T00:00:00.0 to @9999-12-
31T23:59:59.999 with a 1 millisecond step size.

however there there is a test case defined which suggest this should throw:

define Predecessor_min_date: predecessor of DateTime(1900,01,01,0,0,0,0)

https://github.com/cqframework/clinical_quality_language/blob/master/Src/coffeescript/cql-execution/test/elm/arithmetic/test.coffee#L344

Unintuitive interpretation of some interval operator phrases

There is an ambiguity in the specification related to the interpretation of timing relationships. Specifically, given this example:

define Interval1: Interval[@2012-01-01T09:00:00.0, @2012-01-01T10:30:00.0]
define Interval2: Interval[@2012-01-01T11:00:00.0, @2012-01-01T18:00:00.0]
define Within1: Interval1 ends 1 hour or less before start of Interval2

The specification implies in the definition of timing relationships (2.5.5.3) that this should return true, but then describes in 5.5.3.2 that it should be interpreted as a duration between that would return false.

The problem is that there are two boundaries involved in the comparison "X 1 hour or less before Y":

  1. The boundary specified by the "before", which is exclusive by the definition of the "before" operator.
  2. The boundary specified by the relative qualifier, "1 hour or less", which is clearly inclusive.

In this particular case, those boundaries meet and so the interpretation is ambiguous. (In the case of "1 hour or more" the boundaries don't meet, so there is no ambiguity and you get the intuitive behavior).

The translator should be updated to provide the intuitively correct behavior by having the inclusive boundary of the relative qualifier override the exclusive boundary of the comparison operator.

An STU comment has been submitted to the specification to clarify the ambiguity:
http://www.hl7.org/dstucomments/showdetail_comment.cfm?commentid=1336

Lets should be referenceable in subsequent lets

Because of the way the translator pushes lets, a let is not available in the query scope until after all lets have been defined. There's no good reason to disallow this, and section 4.15 Queries implies that once defined, a let can be accessed by name within the query context.

As an example, this fails:

define NestedLet:
  ({ { id: 1, value: 10 }, { id: 2, value: 20 } }) X
    let
      A: (X.value * 10),
      B: A * 10
    return {
      id: X.id,
      value: X.value,
      a: A,
      b: B
    }

But it shouldn't.

The ability to use an expression reference, which returns a retrieve, inside of another retrieve

The following CQL passes validation:

library test version '0.0.000'

using QDM version '5.0.2'

valueset "Ethnicity": 'urn:oid:2.16.840.1.114222.4.11.837'

context Patient

define "SDE Ethnicity": ["Patient Characteristic Ethnicity": "Ethnicity"]

define "def": ["Encounter, Performed": "SDE Ethnicity"]

The following is the outputted ELM:

<?xml version="1.0" encoding="UTF-8"?>
<library xmlns="urn:hl7-org:elm:r1" xmlns:t="urn:hl7-org:elm-types:r1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:fhir="http://hl7.org/fhir" xmlns:a="urn:hl7-org:cql-annotations:r1">
   <identifier id="test" version="0.0.000"/>
   <schemaIdentifier id="urn:hl7-org:elm" version="r1"/>
   <usings>
      <def localIdentifier="System" uri="urn:hl7-org:elm-types:r1"/>
      <def localIdentifier="QDM" uri="urn:healthit-gov:qdm:v5_0_1_draft" version="5.0.2"/>
   </usings>
   <valueSets>
      <def name="Ethnicity" id="urn:oid:2.16.840.1.114222.4.11.837" accessLevel="Public"/>
   </valueSets>
   <statements>
      <def name="Patient" context="Patient">
         <expression xsi:type="SingletonFrom">
            <operand xmlns:ns0="urn:healthit-gov:qdm:v5_0_1_draft" dataType="ns0:Patient" templateId="Patient" xsi:type="Retrieve"/>
         </expression>
      </def>
      <def name="SDE Ethnicity" context="Patient" accessLevel="Public">
         <expression xmlns:ns1="urn:healthit-gov:qdm:v5_0_1_draft" dataType="ns1:PatientCharacteristicEthnicity" xsi:type="Retrieve">
            <codes name="Ethnicity" xsi:type="ValueSetRef"/>
         </expression>
      </def>
      <def name="def" context="Patient" accessLevel="Public">
         <expression xmlns:ns2="urn:healthit-gov:qdm:v5_0_1_draft" dataType="ns2:EncounterPerformed" templateId="PositiveEncounterPerformed" codeProperty="code" xsi:type="Retrieve">
            <codes name="SDE Ethnicity" xsi:type="ExpressionRef"/>
         </expression>
      </def>
   </statements>
</library>

Thoughts?

Translator is ignoring date/time precision specified as part of an interval operator phrase

The translator is ignoring the date/time precision specified as part of an interval operator phrase:

define Interval1: Interval[@2012-01-01T09:00:00.0, @2012-01-01T10:30:00.0]
define Interval2: Interval[@2012-01-01T11:00:00.0, @2012-01-01T18:00:00.0]
define Within: Interval1 ends 1 hour or less before minute of start of Interval2

This should translate to:

define Within: minutes between end of Interval1 and start of Interval2 in Interval(0, 1 * 60]

NOTE: The "* 60" here represents the translator actually performing date/time arithmetic, and should probably be performed with an operation rather than embedding a literal like that. Something like HoursToMinutes(1).

QDM Datatype "Encounter, Active" Retrievable Set to False

In the QDM 5.0 and QDM 5.0.1 Model Info Files, the retrievable is set to "false" for "Encounter, Active":

<ns4:typeInfo xsi:type="ns4:ClassInfo" name="QDM.EncounterActive" retrievable="false" baseType="QDM.QDMBaseType" label="Encounter, Active">

"Encounter, Active" is a datatype in QDM 5.0. Shouldn't this be set to "true"?

Also noticed that the reason attribute was not available for the Patient Characteristic Clinical Trial Participant in the qdm-modelinfo-5.0.xml and qdm-modelinfo-5.0.1.xml files. This attribute is in QDM for this datatype.

Also noticed that the type attribute was not available for the Adverse Event in the qdm-modelinfo-5.0.xml and qdm-modelinfo-5.0.1.xml files. This attribute is in QDM for this datatype.

Annotations in JSON

Annotations in XML work as expected because the content of the annotation is an html fragment. However, when the ELM is output as JSON, the rendering is very difficult to reconstruct. There needs to be a better way to communicate the content of the annotation when the output is formatted using JSON.

Sort Expressions Using Query Aliases

I’m chasing down an issue in the coffeescript execution engine, but it’s led me to question some things regarding sort.

The Problem

In the R1.1 spec, we introduce sort with this example:

[Encounter: “Inpatient”] E sort by start of period

I think this is the way sort by is intended to be used – directly referencing a property in each of the returned items.

That said, we also have some examples further on that do things like this:

First([Condition: "Acute Pharyngitis"] C sort by C.onsetDateTime desc)

Note the use of the C alias in the sort expression. I’m not sure this is actually valid and it raises the question: Can a query alias be referenced in a sort clause?

At first glance, this seems OK – but when you really think about it, C is an alias used during the query execution. The sort is defined to operate on the results of the query – after the execution has occurred – at which point C doesn’t really have meaning.

Looking at the CQL 1.1 spec, section 5.3.3 states:

After the iterative clauses are executed for each element of the query source, the sort clause, if present, specifies a sort order for the final output. This step simply involves sorting the output of the iterative steps…

Since the alias only holds meaning during the iterative clauses (and changes during each iteration), then if sort comes after iteration, the alias has no meaning. Section 5.3.4 makes this ordering even more clear when it lists out the steps to implementing a query: ForEach, Times, Filter, Distinct, Sort. It seems that by the time you get to Sort, the alias shouldn't be in scope anymore.

Another reason it likely doesn’t make sense to reference an alias in the sort clause is that it introduces a possibility for ambiguity when the thing you’re sorting has a property with the same name as your alias. Consider this:

({Tuple{E: 1}, Tuple{E: 3}, Tuple{E: 2}}) N sort by E

Like the first example above, this shows how sort is intended to work -- by referencing a property in the returned items. This is fine, but what happens when we do this instead:

({Tuple{E: 1}, Tuple{E: 3}, Tuple{E: 2}}) E sort by E

If we allow aliases in the sort expression, what does the E in the sort mean? Is it the property E or is it the item E? It’s unclear.

Where It's Currently Allowed

Despite the above, there are a few things that hint that using aliases in a sort clause is allowed:

  • the spec has a number of examples where an alias is used in a sort clause
  • the cql-to-elm translator allows aliases in sort clauses (they become AliasRef instances)

If it's not really allowed, these will have to be fixed.

A Further Issue / Limitation

That said, there are a few cases where we do want to reference the returned item in the sort clause rather than a property of the item. The use case that led me here is that I want to sort items by the result of a function that takes the item as a parameter. A trivial example is:

({1,-3,2,-5,4}) N sort by Abs(N)

Now... if referencing an alias is not allowed, then what do I pass into the Abs function? It seems we would need to have some sort of inferred variable, such as:

({1,-3,2,-5,4}) N sort by Abs($result)

Right now, I can use a workaround, but it is ugly:

(({1,-3,2,-5,4}) N return Tuple{num: N} sort by Abs(num)) N2 return N2.num

So...

I guess that leaves the following questions:

  • Should aliases be allowed in sort expressions?
    • If yes...
      • How do we reconcile that with the implementation guidance in the spec?
      • How do we specify the expected behavior in the ambiguous example I provided?
    • If no...
      • How do we support sort expressions that want to operate directly on the result?

Include highest supported QDM version in CQL-to-ELM translator package name

The CQL-to-ELM translator is dependent on two versioned artifacts, CQL and QDM. Currently, the package for the translator includes the CQL version but does not include the QDM version. My understanding is that the translator will be able to handle at least QDM v 5 to the latest QDM version that it supports. It would be good to have the latest supported QDM version noted in the package name to make this explicit to the user.

Lizzie

cql-execution port to ES6...

I have nothing against Coffeescript, but its future as a language has been debated as of late (due to ES6, ES7, babel, etc)... I have ported the cql-execution engine (and all tests) to ES6, which even with decaffeinate was more work than one might think! Not sure if you are interested, but I am willing to contribute it if you want it.. If not, no big deal, just thought I would offer it up... I currently have it in a private repo, but will open it up if there is any interest. Cheers!

Jeff

Unable to Union different QDM Types

Several eCQMs published in 2015 and 2016 have used "union" to group events that are of different types (CMS 100 v5, CMS 102 v5, CMS 107 v5, etc.). However, something like the following is causing an error to be thrown in the CQL-to-ELM validation:

define "Interventions":
["Intervention, Order"] union ["Intervention, Performed"]

The following error is being thrown:
Could not resolve call to operator Union with signature (list<QDM.InterventionOrder>,list<QDM.InterventionPerformed>).

Is this by design, or is this an issue in the current code?

Issue with code declarations

@brynrhodes When running the following file through the updated CQL-to-ELM translator, I get the following errors:

Translation failed due to errors:
[23:1, 23:63] Type name Code is ambiguous between Code and System.Code.
[25:1, 25:65] Type name Code is ambiguous between Code and System.Code.
[39:19, 39:60] Could not resolve identifier Dead in the current library.
[41:20, 41:68] Could not resolve identifier Birthdate in the current library.
library Test0709282016 version '0.0.000'

using QDM version '5.0'

codesystem "CDCREC:1.0": 'urn:oid:2.16.840.1.113883.6.238' version 'urn:hl7:version:1.0'

codesystem "AdministrativeGender:HL7V3.0_2014-08": 'urn:oid:2.16.840.1.113883.5.1' version 'urn:hl7:version:HL7V3.0_2014-08'

codesystem "SOP:5.0": 'urn:oid:2.16.840.1.113883.3.221.5' version 'urn:hl7:version:5.0'

codesystem "LOINC:2.46": 'urn:oid:2.16.840.1.113883.6.1' version 'urn:hl7:version:2.46'

codesystem "SNOMEDCT:2016-03": 'urn:oid:2.16.840.1.113883.6.96' version 'urn:hl7:version:2016-03'

valueset "ONC Administrative Sex": 'urn:oid:2.16.840.1.113762.1.4.1' codesystems {"AdministrativeGender:HL7V3.0_2014-08"}

valueset "Race": 'urn:oid:2.16.840.1.114222.4.11.836' codesystems {"CDCREC:1.0"}

valueset "Ethnicity": 'urn:oid:2.16.840.1.114222.4.11.837' codesystems {"CDCREC:1.0"}

valueset "Payer": 'urn:oid:2.16.840.1.114222.4.11.3591' codesystems {"SOP:5.0"}

code "Dead": '419099009' from "SNOMEDCT:2016-03" display 'Dead'

code "Birthdate": '21112-8' from "LOINC:2.46" display 'Birthdate'

parameter "Measurement Period" Interval<DateTime>

context Patient

define "SDE Ethnicity": ["Patient Characteristic Ethnicity": "Ethnicity"]

define "SDE Payer": ["Patient Characteristic Payer": "Payer"]

define "SDE Race": ["Patient Characteristic Race": "Race"]

define "SDE Sex": ["Patient Characteristic Sex": "ONC Administrative Sex"]

define "TestDef": ["Patient Characteristic Expired": "Dead"]

define "TestDef2": ["Patient Characteristic Birthdate": "Birthdate"]

Thoughts?

unable to cql-to-elm in json format

following instruction here https://github.com/cqframework/clinical_quality_language/blob/master/Src/java/README.md

the -f option breaks it:

root@a4257a35358c:/usr/src/myapp/Src/java# ./cql-to-elm/build/install/cql-to-elm/bin/cql-to-elm --input ../../Examples/ChlamydiaScreening_CQM.cql --output temp.json -f=json

Exception in thread "main" joptsimple.OptionArgumentConversionException: Cannot parse argument 'json' of option ['format']
    at joptsimple.AbstractOptionSpec.convertWith(AbstractOptionSpec.java:94)
    at joptsimple.ArgumentAcceptingOptionSpec.convert(ArgumentAcceptingOptionSpec.java:276)
    at joptsimple.OptionSet.valuesOf(OptionSet.java:223)
    at joptsimple.OptionSet.valueOf(OptionSet.java:172)
    at joptsimple.AbstractOptionSpec.value(AbstractOptionSpec.java:67)
    at org.cqframework.cql.cql2elm.CqlTranslator.main(CqlTranslator.java:234)
Caused by: joptsimple.internal.ReflectionException: java.lang.IllegalArgumentException: No enum constant org.cqframework.cql.cql2elm.Cq
lTranslator.Format.json
    at joptsimple.internal.Reflection.reflectionException(Reflection.java:140)
    at joptsimple.internal.Reflection.invoke(Reflection.java:122)
    at joptsimple.internal.MethodInvokingValueConverter.convert(MethodInvokingValueConverter.java:48)
    at joptsimple.internal.Reflection.convertWith(Reflection.java:128)
    at joptsimple.AbstractOptionSpec.convertWith(AbstractOptionSpec.java:91)
    ... 5 more
Caused by: java.lang.IllegalArgumentException: No enum constant org.cqframework.cql.cql2elm.CqlTranslator.Format.json
    at java.lang.Enum.valueOf(Enum.java:238)
    at org.cqframework.cql.cql2elm.CqlTranslator$Format.valueOf(CqlTranslator.java:35)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at joptsimple.internal.Reflection.invoke(Reflection.java:119)
    ... 8 more

this works (but makes xml):

root@a4257a35358c:/usr/src/myapp/Src/java# ./cql-to-elm/build/install/cql-to-elm/bin/cql-to-elm --input ../../Examples/ChlamydiaScreening_CQM.cql --output temp.json        

Improve error messages

To improve usability of the output of error messages from the translator, error messages should be made more author-friendly (i.e. use less programmer-ese).

In addition, the translator often outputs secondary errors (e.g. errors that are caused by a root error that prevents the translator from correctly determining the type of an expression result in subsequent errors in resolution). These types of errors should be reduced as much as possible.

In addition, the parser often produces errors that are very unfriendly, especially token recognition errors that result in "expected:... (a long string of unrelated tokens that cannot reasonably be interpreted by mortals)."

Test cases for variance and population variance are reversed

CQLIT-18

CQL > variance and pop variance

Erich Schulz: i think the 2 test case values are reversed...

Erich Schulz:
// PopulationVariance
// should be able to find PopulationVariance of a list
PopulationVariance_v: 2.5,

// Variance
// should be able to find Variance of a list
Variance_v: 2,
Erich Schulz: i have a test spreadsheet here

Erich Schulz:
// @test: Variance
define Variance_v: Variance(
{1,2,3,4,5}

)
// @test: PopulationVariance
define PopulationVariance_v: PopulationVariance(
{1.0,2.0,3.0,4.0,5.0}

)

build failing

I just tried to build in java 6, 7, 8 and 9 (using vanilla java dockers as specified here: https://hub.docker.com/_/java/)

6 and 7 both seemed to go furtherest but failed with

:cql:test FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':cql:test'.
> There were failing tests. See the report at: file:///usr/src/myapp/cql/build/repor
ts/tests/index.html

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug opti
on to get more log output.

BUILD FAILED

java8 failed with

FAILURE: Build failed with an exception.

* Where:
Build file '/usr/src/myapp/elm/build.gradle' line: 12

* What went wrong:
Execution failed for task ':elm:generateSources'.
> unable to parse the schema. Error messages should have been provided

Incorrect translation of Time(x,x,x,x,x) operator

The cql-to-elm translator is not recognizing the Time(x,x,x,x,x) operator properly.

For example:
define TimeTest: Time(23, 59, 59, 999)
This expression should result in a Time object populated with the corresponding hour, minute, second, and millisecond values, but it is not. This is causing problems with implementation as the Time(x,x,x,x,x) operator is being evaluated as a function, which leads to errors as the corresponding evaluator never gets called.

*I am using the @txx:xx:xx.xxxZ Time format as a workaround for now.

CQL File passing validation with reference to function with incorrect signature

The following cql file is passing validation:

library TEST version '1.0'

using QDM version '5.0.2'

parameter "Measurement Period" Interval<DateTime>

context Patient

define "TestDef": "TestFunc"()

define function "TestFunc"(Test String): true

It produces the following EML file:

<?xml version="1.0" encoding="UTF-8"?>
<library xmlns="urn:hl7-org:elm:r1" xmlns:t="urn:hl7-org:elm-types:r1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:fhir="http://hl7.org/fhir" xmlns:a="urn:hl7-org:cql-annotations:r1">
   <identifier id="TEST" version="1.0"/>
   <schemaIdentifier id="urn:hl7-org:elm" version="r1"/>
   <usings>
      <def localIdentifier="System" uri="urn:hl7-org:elm-types:r1"/>
      <def localIdentifier="QDM" uri="urn:healthit-gov:qdm:v5_0_1_draft" version="5.0.2"/>
   </usings>
   <parameters>
      <def name="Measurement Period" accessLevel="Public">
         <parameterTypeSpecifier xsi:type="IntervalTypeSpecifier">
            <pointType name="t:DateTime" xsi:type="NamedTypeSpecifier"/>
         </parameterTypeSpecifier>
      </def>
   </parameters>
   <statements>
      <def name="Patient" context="Patient">
         <expression xsi:type="SingletonFrom">
            <operand xmlns:ns0="urn:healthit-gov:qdm:v5_0_1_draft" dataType="ns0:Patient" templateId="Patient" xsi:type="Retrieve"/>
         </expression>
      </def>
      <def name="TestDef" context="Patient" accessLevel="Public">
         <expression name="TestFunc" xsi:type="FunctionRef"/>
      </def>
      <def name="TestFunc" context="Patient" accessLevel="Public" xsi:type="FunctionDef">
         <expression valueType="t:Boolean" value="true" xsi:type="Literal"/>
         <operand name="Test">
            <operandTypeSpecifier name="t:String" xsi:type="NamedTypeSpecifier"/>
         </operand>
      </def>
   </statements>
</library>

Should the CQL to ELM parser catch the reference to a function with an invalid signature?

Operand result type is returning as the negated QDM type

When using the following function in CQL, the operand for the function argument has a result type of the negated version of the QDM.

define function "func1"(AP "Assessment, Not Performed" ):
             true

This is inconsistent with other result type functionality. For example, the following CQL definition returns the positive version of the QDM type

define "def1": 
              ["Assessment, Not Performed"]

Thoughts?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.