GithubHelp home page GithubHelp logo

cqframework / cql-engine Goto Github PK

View Code? Open in Web Editor NEW
62.0 22.0 45.0 24.27 MB

Clinical Quality Language Evaluation Engine

License: Apache License 2.0

Java 99.85% Batchfile 0.02% Shell 0.13%
clinical-quality-language cql cqlengine cql-evaluation-engine elm java cql-engine hacktoberfest

cql-engine's Introduction

๐Ÿšจ๐Ÿšจ This project has moved! ๐Ÿšจ๐Ÿšจ

The code from the cql-engine project has been merged into the Clinical Quality Language repository. Source Code

CQL Evaluation Engine

Maven Central Build Status project chat

The HL7 Clinical Quality Language specification is designed to enable accurate authoring and automated sharing of computable knowledge artifacts including quality measures, decision support rules, orders sets and documentation templates. The specification is constructed using a layered approach informed by modern programming language and compiler design which facilitates the development of language processing applications including static analysis, translation, and evaluation.

The specification includes informative open source tooling that can be used to verify the semantics of CQL libraries; to produce the sharable format, Expression Logical Model (ELM), of those libraries; and to evaluate the resulting libraries using a prototypical JavaScript-based ELM interpreter.

This project builds on that tooling to provide an open source Java-based evaluation engine capable of evaluating the result of any CQL expression.

Repository

This repository uses stable trunk methodology:

Branch Description Status Version
v12 CQL 1.2 Engine Obsolete 1.2.20
v13 CQL 1.3 Engine Obselete 1.3.12.2
v14 CQL 1.4 Engine Maintenance 1.4.0
v15 CQL 1.5 Engine Maintenance 1.5.7
v20 CQL 2.0 Engine Maintenance 2.0.0
master CQL 2.4.0 Engine Active Development 2.4.0

Commit Policy

All new development takes place on <feature> branches off master. Once feature development on the branch is complete, the feature branch is submitted to master as a PR. The PR is reviewed by maintainers and regression testing by the CI build occurs.

Changes to the master branch must be done through an approved PR. Delete branches after merging to keep the repository clean.

Merges to master trigger a deployment to the Maven Snapshots repositories. Once ready for a release, the master branch is updated with the correct version number and is tagged. Tags trigger a full release to Maven Central and a corresponding release to Github. Releases SHALL NOT have a SNAPSHOT version, nor any SNAPSHOT dependencies.

On release, committers must ensure that:

  1. The major, minor, and patch build properties are incremented appropriately.
  2. Increment the minor build property on the master branch (to be automated by #316)

Release Policy

This project uses Semantic Versioning, with the caveat that we track to the version of CQL the engine supports. Releases are published to Maven snapshot and public directories under the org.opencds.cqf.cql group id. Each release SHALL have a Release in Github. Pre-releases SHALL be marked as such and use the -SNAPSHOT version indicator. For any new release, a SNAPSHOT is released first and must pass integration testing in at least one external system prior to being promoted to a release. SNAPSHOTs may be published from any branch, but SHALL have incremented version numbers consistent with the branch and semantic versioning policies. Releases may only be published from the master or maintenance branches. Only one prior version is maintained at any given time.

Roadmap

  • 1.4 - CQL 1.4 Support
  • 1.5 - CQL 1.5 Support
  • 1.5.0 - Initial release candidate
  • 1.5.1 - Minor maintenance/stability fixes
  • 1.5.2 - PHI Obfuscation, Long data type, performance enhancements, bug fixes
  • 1.5.3 - Performance enhancements, break out of Jaxb dependencies, support for ValueSet and CodeSystem types
  • 1.5.4 - Maintenance/stability fixes
  • 1.5.5 - Maintenance/stability fixes; FHIRPath test suite; improved test coverage
  • 1.5.6 - Burned by Maven
  • 1.5.7 - Critical fix for FHIRPath now() and today() support
  • 1.5.8 - Critical fix for evaluator parameter passing
  • 1.5.9 - Improved support for dynamic model info loading, version manifest usage, improved test coverage, improved testing and debug capabilities
  • 1.5.10 - Enhanced retrieve: profile-retrieve, context-based retrieves, includes, search parameters, inferred expression support, FHIRPath test suite, improved debugging capabilities, code coverage, date filter support for data providers
  • 1.5.N - Support for concept mapping with versioned manifest usage and/or concept map configuration, CQL specification test suite, data provenance propagation, result meta-data tagging
  • 2.0.0 - Start using Translator 2.1.0
  • 2.1.0 - Start using Translator 2.2.0, maintain expression wise evaluated resources state
  • 2.2.0 - Start using Translator 2.3.0, fix Jackson error for Expand ValueSet operators, fix primary context path between Task and Patient to the field for in R4 and DSTU3
  • 2.3.0 - Start using Translator 2.4.0
  • 2.4.0 - Added config queryBatchThreshold in FhirQueryGeneration

Getting Help

Bugs and feature requests can be filed with Github Issues.

The implementers are active on the official FHIR Zulip chat for CQL.

Inquires for commercial support can be directed to [email protected].

Related Projects

Clinical Quality Language - Tooling in support of the CQL specification, including the CQL verifier/translator used in this project.

CQL Evaluator - Integrates the CQL Translator and this CQL Engine into an execution environment, and provides implementations of operations defined by FHIR IGs.

CQL Support for Atom - Open source CQL IDE with syntax highlighting, linting, and local CQL evaluation.

CQF Ruler - Integrates this CQL Engine into the HAPI FHIR server, providing CQL Library evaluation, among other functionality.

License

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.

cql-engine's People

Contributors

bryantaustin13 avatar brynrhodes avatar c-schuler avatar cmoesel avatar coreysandersoh avatar csandersdev avatar dand9959 avatar deekim avatar dependabot[bot] avatar dkwasny-ibm avatar duncand avatar esteban-aliverti avatar hadleynet avatar jawalonoski avatar jpercival avatar jreyno77 avatar jrswenson avatar mdnazmulkarim avatar msargentibm 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

Watchers

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

cql-engine's Issues

Display CQL values to the user as valid CQL expression source code

This might actually be implemented elsewhere but I consider it a generic issue across multiple components, so am putting it as an Engine issue for now.

Currently when evaluating expressions in the CQL Runner, the resulting value displayed for each "define" is a close approximation of, but is not identical to, valid CQL source code. Examples of differences include that strings are not quoted, date times don't have the commercial-at prefix, some lists are not comma-delimited, and so on.

The task of this ticket is make CQL expressions round-trip-able. What you see output in the CQL Runner and other places can be copy-pasted into the input box and be re-run with the same result, and it would parse as valid syntax. A bulk-ready variant is that the output takes the form of a library definition where each expression has the form of a "define" etc. Meta-data such as declared line numbers can appear beside it as a CQL comment, and so on.

Besides being a huge convenience feature, this would also help avoid a lot of interpretation bugs, such that literals which appear the same always are Equivalent()=true and those which appear different in that output are Equivalent()=false.

See also issue #39 which is a bug directly resulting from the imprecision of the output.

Date/time Arithmetic fails adding durations?

The following define:

define Test3: E + 1 day

Fails with the error "Invalid duration day".

I also tried with the UCUM unit 'd', but it gives the same "Invalid duration" error.

Report the same location context info for errors as for successes

When a CQL named expression is evaluated successfully, the output gives the expression name and line number in the source code, for example:

>> Is Colonoscopy In Last Ten Years [304:1] false

However, when there are runtime errors with an expression, that context is not indicated, for example:

>> Error: HTTP 404 Not Found

The task of this ticket is to update the engine such that the expression name / line number context is always reported regardless of whether the evaluation result is successful or an error.

This information is important for tracking down where in many possible places the error may originate in the source code.

cql-engine-fhir FileBasedFhirProvider does not handle interval datePath

According to clinicalexpression.xsd, dateProperty may be a DateTime or Interval. If both dateProperty and dateRange are intervals then resource should be included in results if entire dateProperty interval is included in the date range. FileBasedFhirProvider currently only handles scenario where dateProperty is a datetime, not an interval.

The following code works in my testing.

`
if (temp instanceof DateTime) {
date = (DateTime)temp;
}
else if (temp instanceof DateTimeType) {
date = toDateTime((DateTimeType)temp);
}
else if (temp instanceof Interval) {
dateInterval = (Interval)temp;
}

                if (date != null && InEvaluator.in(date, expanded)) {
                    results.add(res);
                }
                else if(dateInterval != null && (Boolean)IncludesEvaluator.includes(expanded, dateInterval)){                    	
                	results.add(res);
                }
                else {
                    includeRes = false;
                }

`

InEvaluator ignores precision

When translating the following script:

define TestPeriod1: Interval[@2017-12-20T11:00:00, @2017-12-21T21:00:00]
define TestPeriod2: Interval[@2017-12-20T10:30:00, @2017-12-20T12:00:00]
define Test11: TestPeriod2 starts 1 day or less on or after day of start of TestPeriod1

The resulting EML uses an "in" with a precision of "day", but the evaluator is ignoring the "day" precision of the operator.

Translator fails to handle result types of Width()

Run the following CQL:

define x1: width of Interval[DateTime(2012, 1, 5), DateTime(2012, 1, 25)]
define x2: Equivalent(x1, 20 days)
define y1: width of Interval[@T05:59:59.999, @T15:59:59.999]
define y2: Equivalent(x1, 36000000 milliseconds)

Expected result:

x1: 20 days
x2: true
y1: 36000000 milliseconds
y2: true

Actual result:

x1: 20 days
x2: Could not resolve call to operator Equivalent with signature (System.DateTime,System.Quantity)
y1: 36000000 milliseconds
y2: Could not resolve call to operator Equivalent with signature (System.Time,System.Quantity)

This problem is demonstrated by these failing CQL Engine tests:

  • CqlIntervalOperatorsTest.xml -> DateTimeWidth
  • CqlIntervalOperatorsTest.xml -> TimeWidth

Internal Java exception when comparing some Decimal values

The CQL Engine can't reconcile different internal formats for Decimal values.

Run the following CQL:

define x: Power(2, -2)
define y: Equivalent(Power(2, -2), 0.25)

Expected result:

x: 0.25
y: true

Actual result:

x: 0.25
y: java.lang.IllegalArgumentException: Cannot call ToDecimal operator with argument of type 'java.math.BigDecimal'.

These failing CQL Engine tests reflect this bug:

  • CqlArithmeticFunctionsTest -> Power2ToNeg2

BaseFhirDataProvider missing IBaseDatatypeElement in resolveRuntimeDefinition

resolveRuntimeDefinition method of BaseFhirDataProvider should handle IBaseDatatypeElement in addition to IBaseBackboneElement and IBaseElement. This is the interface for several internal "Component" classes in HAPI FHIR model, including org.hl7.fhir.instance.model.Timing$TimingRepeatComponent which is used for MedicationOrder.dosageInstruction.timing.

Multiply/Divide with Quantity gives wrong result

Per CQL spec 9.6.4 Divide: "For division operations involving quantities, the resulting quantity will have the appropriate unit."

Run the following CQL:

define x: 1'g/cm3' / 1'g/cm3'

Actual result:

 1.0 g/cm3

Expected result:

1.0

... or 1.0'' or however you spell some special neutral unit that means no units.

Enhancement to enable trace for evaluator debugging

Currently very difficult to debug ELM scripts when expression result is not as expected, especially with deep nested expressions. Request enhancement for trace level logging within each evaluator that logs 1. entry into the evaluator and 2. exit from the evaluator with string representation of result of execution.

Interval intersect with null throws java null pointer exception

Try to run this CQL:

define x: Interval[1, 10] intersect Interval[5, null)

Expected result is null, but actual result is the CQL Engine dies with a java.lang.NullPointerException.

This bug is demonstrated in a CQL Engine test failure of CqlIntervalOperatorsTest.xml -> TestIntersectNull.

Quantities don't normalize units, giving wrong answers

The CQL Engine does not handle unit normalization properly and so
comparisons of Quantity of meters and centimeters don't give the right answers.
The problem is characterized by that the unit of the left operand is treated
as being the unit of both operands.

Run the following CQL:

define QuantityEqCM1M01    : 1'cm' = 0.01'm'
define GreaterM1CM1        : 1'm' > 1'cm'
define GreaterM1CM10       : 1'm' > 10'cm'
define GreaterOrEqualM1CM1 : 1'm' >= 1'cm'
define GreaterOrEqualM1CM10: 1'm' >= 10'cm'
define LessM1CM1           : 1'm' < 1'cm'
define LessM1CM10          : 1'm' < 10'cm'
define LessOrEqualM1CM1    : 1'm' <= 1'cm'
define LessOrEqualM1CM10   : 1'm' <= 10'cm'
define EquivEqCM1M01       : 1'cm' ~ 0.01'm'
define QuantityNotEqCM1M01 : 1'cm' != 0.01'm'

Expected result:

QuantityEqCM1M01    : true
GreaterM1CM1        : true
GreaterM1CM10       : true
GreaterOrEqualM1CM1 : true
GreaterOrEqualM1CM10: true
LessM1CM1           : false
LessM1CM10          : false
LessOrEqualM1CM1    : false
LessOrEqualM1CM10   : false
EquivEqCM1M01       : true
QuantityNotEqCM1M01 : false

Actual result (only 2 match):

>> QuantityEqCM1M01 [1:1] false
>> GreaterM1CM1 [2:1] false
>> GreaterM1CM10 [3:1] false
>> GreaterOrEqualM1CM1 [4:1] true
>> GreaterOrEqualM1CM10 [5:1] false
>> LessM1CM1 [6:1] false
>> LessM1CM10 [7:1] true
>> LessOrEqualM1CM1 [8:1] true
>> LessOrEqualM1CM10 [9:1] true
>> EquivEqCM1M01 [10:1] false
>> QuantityNotEqCM1M01 [11:1] true

These failing CQL Engine tests reflect this bug:

  • CqlComparisonOperatorsTest.xml -> 9 of the 11 tests listed above

Implement logical operator Implies

The Translator doesn't recognize the SQL-spec defined dyadic logical operator Implies(). So trying to use say true implies true gives a can't-resolve Translator error. There is a block of 9 tests in the CQL Engine test file CqlLogicalOperatorsTest that currently fails due to this operator not being supported.

Validation for CodeRef

Feature request for validation through terminology service when creating CodeRefs. Optimize this feature through the use of a hash table.

IllegalArgumentException

In the cql library I use (col.elm.xml) effectiveDateTime is checked against a certain range to decide whether an Observation should be included in the report while the effectiveDateTime can be null in an Observation, in which case the Observation should theoritically be excluded from the report. However, when I ran the report with certain Observations having null effectiveDateTimes the following runtime exception is thrown and no report is generated:

java.lang.IllegalArgumentException: Errors occurred attempting to invoke the accessor function for property effectiveDateTimeType of type Observation
org.opencds.cqf.cql.data.fhir.BaseFhirDataProvider.resolveProperty(BaseFhirDataProvider.java:238)

I did some digging and found that the exception is caused by an exception thrown in the Observation class (org.hl7.fhir.dstu3.model):

public DateTimeType getEffectiveDateTimeType() throws FHIRException { 
  if (!(this.effective instanceof DateTimeType))
    throw new FHIRException("Type mismatch: the type DateTimeType was expected, but "+this.effective.getClass().getName()+" was encountered");
  return (DateTimeType) this.effective;
}

The above method throws a FHIRException instead of returning null when the target is null. This is not a loner. There're quite a number of accessors in the hapi fhri model classes following this pattern.

Error when evaluating on or after

The following script:

define TestDateTime1: @2017-12-20T11:00:00
define TestDateTime2: @2017-12-20T11:00:00
define Test: TestDateTime1 on or after TestDateTime2

Gives the error "Precision must be specified". However, the SameOrAfter operator in ELM does not require precision (the precision attribute is optional). In addition, the CQL specification in section 2.5.4.2 indicates:

If no precision is specified, these operators are equivalent to the symbolic comparison operators, implying comparison precision to the millisecond.

The engine should be updated to use "millisecond" precision if no precision is specified for the SameOrAfter operator, as well as any other operators that require precision.

Minimum Integer value -2147483648 can not be selected as a literal

The the minimum Integer value -2147483648 can not be selected as a literal.

Run the following CQL:

define x: minimum Integer
define y: -2147483648

Expected result:

x: -2147483648
y: -2147483648

Actual result:

x: -2147483648
y: java.lang.NumberFormatException: For input string: "2147483648"

These failing CQL Engine tests reflect this bug:

  • CqlArithmeticFunctionsTest -> IntegerMinValue

The root of the problem is that the Translator parses -2147483648
not as a single literal but rather as a Negate operator call paired
with a positive Integer literal, and then the CQL Engine has a runtime
numeric overflow exception trying to parse the ELM in question.

      <def name="y" context="Population" accessLevel="Public">
         <expression xsi:type="Negate">
            <operand valueType="t:Integer" value="2147483648" xsi:type="Literal"/>
         </expression>
      </def>

The proper fix for this would be in the Translator.

A kludge fix for this would be in the Engine that special cases any
occurrances in input ELM of a "Negate" operator call paired with a numeric literal
such that it factors them into a negated literal before converting to a number.

Count of Query source returns null if query return one result

I am counting results of a query operation and latest snapshot is causing errors in cases where the query only returns one result. The QueryEvaluator is now returning a single object instead of an iterable object with one member, which is what I was expecting. CountEvaluator is returning null because the source expression result is not iterable.

Is this intended behavior? In that case, how would the Count expression have to be written to handle a source query which may return 0 or more results?

Also, it seems like the code will throw an indexoutofboundsexception if the query returns 0 results, based on lines 122 and 130 of QueryEvaluator.

Add more tests for CQL external functions

This is a follow-up to issue #52.

The CQL external functions feature deserves a more thorough set of unit tests.

An example of such is one that tests a possible use case like libraries that reference a function with the same signature, but have different results, like the following (written by @c-schuler):

library CqlExternalFunctionsTest version '3'

include AnotherLibrary version '1' called AnotherLibrary

context Patient

define function MyStringOperation(x String) returns String : external

define CallCurrentStringOperation: 
    MyStringOperation('Testing') // returns TESTING

define CallAnotherStringOperation: 
    AnotherLibrary.MyStringOperation('Testing') // returns testing

But more than the above should be added so the additions are not arbitrary as a sum.

DateFrom does not extract the Date component correctly

In this CQL:

define DateTime1: @2012-03-10T10:20:00
define DateTime2: @2013-03-10T09:20:00
define DurationInYears: years between (date from DateTime1) and (date from DateTime2)

DurationInYears should return 1, but it returns 0.

Difference calculation issues when DateTimes are in different timezone offsets

DateTime difference calculations do not behave as expected when the values are in different timezone offsets, as illustrated by the following library:

library TestDateTimeDifference

define DateTime1: @2017-03-12T01:00:00-07:00 // March 12, 2017, 1:00 AM MST
define DateTime2: @2017-03-12T03:00:00-06:00 // 3:00 AM MDT
define DateTime3: @2017-11-05T01:30:00-06:00 // November 5, 2017, 1:30 AM MDT
define DateTime4: @2017-11-05T01:15:00-07:00 // November 5, 2017, 1:15 AM MST
define DateTime5: @2017-03-12T00:00:00-07:00 // March 12, 2017
define DateTime6: @2017-03-13T00:00:00-06:00 // March 13, 2017

define DifferenceInHours: difference in hours between DateTime1 and DateTime2 // Should be 1
define DifferenceInMinutes: difference in minutes between DateTime3 and DateTime4 // Should be 45
define DifferenceInDays: difference in days between DateTime5 and DateTime6 // Should be 1

This issue is related to two STU comments, #1441 and #1478

Engine not implemented part of properly-includes/included-in

The CQL Engine throws exceptions for certain "properly includes"
and "properly included in" calls citing that something isn't implemented,
though many other calls to that syntax succeed.

Run the following CQL:

define x: {'s', 'u', 'n'} properly includes null
define y: null properly included in {2}

The seen exceptions are:

x: evaluate not implemented for class ProperContains
y: evaluate not implemented for class ProperIn

This problem is demonstrated by these failing CQL Engine tests:

  • CqlListOperatorsTest.xml -> ProperlyIncludesNulRight
  • CqlListOperatorsTest.xml -> ProperlyIncludedInNullLeft

Docker containerization (for HSPC demo).

I've love to demo automated deployment of this at HSPC this month. Doing so essentially just requires Docker containerization and pushing releases image(s) to a public repo, such Docker Hub. Would it be possible to get a Dockerfile to do this? I can get the server registered and can test deployment.

Errors with IncludedIn implementation

The "included in" evaluator does not take into account precision as stated in the specification. Also, as alluded to in issue #54, it doesn't account for possible null values being returned by DateTime/Time comparisons.

NotImplementedException for CodeRef expression

CodeRef expression defined in clinicalexpression.xsd gives NotImplementedExpression. I think this is still a valid expression in the language, see cqframework repository Examples/Zika/zika-virus-intervention-logic.xml for example.
org.apache.commons.lang3.NotImplementedException: evaluate not implemented for class CodeRef
at org.opencds.cqf.cql.elm.execution.Executable.evaluate(Executable.java:11)

Expect evaluation of CodeRef expression should return org.opencds.cqf.cql.runtime.Code object from named CodeDef element in order to work with RetrieveEvaluator -
Object codesResult = this.getCodes().evaluate(context);
if (codesResult instanceof Code) {...}

The evaluation of TestRangeToInterval CQL function in TestFhirPath test class doesn't transform correctly

If you try to print the evaluation of the result of this statement, context.resolveExpressionRef("TestRangeToInterval").getExpression().evaluate(context);
it would raise an exception because the the evaluation of the expression is null.
I think the culprit is the transformation doesn't set the value and the unit for the SimpleQuantity object being constructed in BaseFhirDataProvider class at line 265
value = ((Quantity) value).castToSimpleQuantity(new SimpleQuantity());
In the castToSimpleQuantity(base obj), if the object being passed is SimpleQuantity it wouldn't set the values for value and unit.

Check the bundle entry resourceType matches requested type in the Retrieve operation results

Open Epic FHIR server returns Operation Outcome with message "Resource request returns no results", rather than empty bundle, when query has 0 results. Causes errors in Query operations due to type mismatch, unless resource type is always explicitly checked.

Suggest enhancement to check the Bundle entry resourceType and only include those that match the requested type in the Retrieve operation results.

Error with a function that returns an Interval

The following script:

define TestDateTime1: @2017-12-20T11:00:00
define function ToDate(Value DateTime):
  DateTime(year from Value, month from Value, day from Value, 0, 0, 0, 0, timezone from Value)

define function CalendarDayOf(Value DateTime):
  Interval[Value, ToDate(Value + 1 day))

define TestCalendarDayOf: CalendarDayOf(TestDateTime1)

Gives the error "Invalid interval, the ending boundary must be greater than or equal to the starting boundary", but when I create an interval with what I expect the result of the above to be:

define TestDateTime1: @2017-12-20T11:00:00
define TestDateTime3: @2017-12-21T00:00:00.0
define TestInterval: Interval[TestDateTime1, TestDateTime3)

I get the correct result.

The same Equivalent() call translates or not based on existence of other Equivalent() etc calls

For many different routines, whether or not the Translator succeeds in parsing
a routine call varies only on whether a separate call to the same routine
exists with different arguments further up in the same library.

The problem exists particularly with the generic equal/equivalent/not-equal
operators; just a few argument examples are given here to demonstrate the
problem, but it potentially happens with any pair of argument types.
The problem might also affect other operators having (Any,Any) signatures,
and it might affect other operators besides those.

Run the following CQL as a single block:

define x: {} = {}
define y: {} ~ {}
define ListEqABC123:          { 'a', 'b', 'c' } = { 1, 2, 3 }
define ListEq123ABC:          { 1, 2, 3 } = { 'a', 'b', 'c' }
define ListEq123String123:    { 1, 2, 3 } = { '1', '2', '3' }
define EquivListABC123:       { 'a', 'b', 'c' } ~ { 1, 2, 3 }
define EquivList123ABC:       { 1, 2, 3 } ~ { 'a', 'b', 'c' }
define EquivList123String123: { 1, 2, 3 } ~ { '1', '2', '3' }
define ListNotEqABC123:       { 'a', 'b', 'c' } != { 1, 2, 3 }
define ListNotEq123ABC:       { 1, 2, 3 } != { 'a', 'b', 'c' }
define ListNotEq123String123: { 1, 2, 3 } != { '1', '2', '3' }

The actual result then is that the Translator succeeds and every statement
outputs a value, which happens to be null except for the first 2.

Next remove either or both of the first 2 lines and then run the CQL again.

If "x" is removed, then 6 of the last lines will fail to Translate,
citing an error like:

Could not resolve call to operator Equal with signature (list<System.Integer>,list<System.String>).

If "y" is removed, then the other 3 of the last lines will fail to Translate,
citing an error like:

Could not resolve call to operator Equivalent with signature (list<System.Integer>,list<System.String>)

Regardless of on what side of the fence one falls in regards to whether
they think Equivalent() etc with distinct argument types should fail to
Translate versus return false etc at runtime, this bug demonstrates a
serious issue in that the Translator isn't even consistent with itself;
the exact same statement having no external references to other expressions
should either Translate or not translate in exactly the same way no matter
what other statements the library contains.

These failing CQL Engine tests reflect this bug:

  • CqlComparisonOperatorsTest.xml -> all 9 tests listed above

Error when getting timezone offset when ID is in form of Country/City

The getTimeZoneOffset() method in BaseTemporal class assumes that the timezone ID will be in the form of (+|-)hh:mm, e.g. +07:00. However, there may be instances when the ID is of the form Country/City, e.g. America/Denver. This invalid assumption may lead to an ArrayIndexOutOfBoundsException with the current logic.

Translation fails on uncertainty-resulting days-between

The Translator fails to translate an uncertainty.

Run the following CQL:

define x: days between DateTime(2015, 2, 10) and DateTime(2015, 3)
define y: Interval [ 19, 49 ]
define z: Equivalent(x,y)

Expected result:

x: Interval [ 19, 49 ]
y: Interval [ 19, 49 ]
z: true

Actual result:

x: Interval [ 19, 49 ]
y: Interval [ 19, 49 ]
z: Could not resolve call to operator Equivalent with signature (System.Integer,interval<System.Integer>).

These failing CQL Engine tests reflect this bug:

  • CqlTypesTest.xml -> DateTimeUncertain

Weeks duration not supported

Weeks duration calculation should be supported:

define WeekExample1: weeks between @2012-03-10T22:05:09 and @2012-03-20T07:19:33

Currently gives "Invalid duration precision"

Wrong answers for properly-included-in operator

The CQL Engine is producing wrong answers for the "properly included in" operator.

Run the following CQL:

define a: {} includes {}
define b: {} included in {}
define c: {} properly includes {}
define d: {} properly included in {}

Expected result:

a: true
b: true
c: false
d: false

Actual result:

>> a [1:1] true
>> b [2:1] true
>> c [3:1] false
>> d [4:1] true

Rhis problem is demonstrated by these failing CQL Engine tests:

  • CqlListOperatorsTest.xml -> ProperIncludedInEmptyAndEmpty

Two DateTime that display the same compare as different

Two DateTime expressions display the same in CQL Runner but compare as different.

Run the following CQL:

define x:
    Interval[
        @2017-12-20T11:00:00,
        DateTime(
            year from (@2017-12-20T11:00:00 + 1 day),
            month from (@2017-12-20T11:00:00 + 1 day),
            day from (@2017-12-20T11:00:00 + 1 day),
            0, 0, 0, 0,
            timezone from (@2017-12-20T11:00:00 + 1 day)
        )
    )
define y: Interval [ @2017-12-20T11:00:00, @2017-12-20T23:59:59.999 ]
define z: Equivalent(x,y)

Expected result:

x: Interval [ @2017-12-20T11:00:00, @2017-12-20T23:59:59.999 ]
y: Interval [ @2017-12-20T11:00:00, @2017-12-20T23:59:59.999 ]
z: true

Actual result:

>> x [ 1:1] Interval [ 2017-12-20T11:00:00, 2017-12-20T23:59:59.999 ]
>> y [12:1] Interval [ 2017-12-20T11:00:00, 2017-12-20T23:59:59.999 ]
>> z [13:1] false

These failing CQL Engine tests reflect this bug:

  • CqlTypesTest.xml -> Issue33

Now and Today Evaluators do not use the Request date/time

Per the CQL specification, the Now and Today functions must evaluate using the Request date/time to ensure they are deterministic functions within any given evaluate call.

This will require that the Engine context be expanded to include the evaluation request date/time, and that the evaluation have a parameter for the request date/time.

NotImplementedException for Filter expression

Using Filter expression (example below) throws not yet implemented exception.

<operand xsi:type="Filter" scope="R">
   <source name="FluTests" xsi:type="ExpressionRef"/>
   <condition xsi:type="InValueSet">
      <code path="code.coding" scope="R" xsi:type="Property" />					
      <valueset name="InfluenzaMolecular" xsi:type="ValueSetRef"/>
   </condition>
</operand>	

Add CQL source code generator

It is well established already that we have the Translator project which converts CQL source code to ELM source code, and that we have the CQL Engine project that takes ELM source code and evaluates it to produce result values or other output.

However, I am not aware of any projects that go the other way, either taking ELM and generating CQL, or in particular, an Engine feature that takes an arbitrary in-memory CQL value and generates valid CQL (or ELM) source code that when executed produces the same CQL value.

The task of this ticket is to do the last of these (generating valid CQL source code for an in-memory value), in particular, or otherwise identifying where the functionality already exists.

See also related ticket #40.

The fundamental deliverable of this ticket is characterized by a Java function that takes any Java Object X as input which can be the result of an Executable.evaluate() call, and produce a Java String value consisting of an anonymous valid CQL expression, the E in "define e: E" in Population context, such that subsequent translation and Executable.evaluate() of E would produce a Java Object Y representing a CQL value for which Equivalent(X,Y) would result in true.

One use of this function is that it can be exposed as a CQL "external" function, thus a CQL expression can result in CQL source code, a demonstration of the "external" feature of the language.

Another, very important, use of this function, is that it can be used by the CQL Runner to generate the results displayed back to users. The current output approximates but doesn't equal valid CQL, so it can't be copy-pasted back into input without manual editing; moreover, the current output may display non-identical values identically. With the new version, if they display the same / different, they are the same / different respectively.

Note that this ticket is not about generating entire CQL libraries, just individual values; the former if desired (and I think it would be) is the task of another ticket, if not already done.

I estimate that this task can be completed within 1 day of work, given similar features already extant.

Add option for ExpressionRefs to be cached within a given Patient context

If an Expression is referenced multiple times, have option to evaluate the expression once and use the computed value for each future reference within the same Patient context. Without this, performance is impacted by expressions with Retrieve operations being run multiple times to extract same data.

Per Bryn, 'CQL is explicitly designed as a functional language so that this type of caching will work with evaluations'.

DMS Denominator CQL

When I run test data on the DMS measure I get denominator values that are greater than the IPP values:

===== In-memory Summary =====
	denominator 1 = 100
	denominator 2 = 100
	denominator 3 = 100
	initial-population = 55
	numerator 1 = 83
	numerator 2 = 55
	numerator 3 = 25

===== Server Summary =====
	denominator 1 = 100
	denominator 2 = 100
	denominator 3 = 100
	initial-population = 55
	numerator 1 = 83
	numerator 2 = 55
	numerator 3 = 25

Looking at the CQL, I believe the Initial-Population needs to be included in the definitions:

define "Denominator 1":
	{First(
		"Depression Encounters" E
			where PeriodToIntervalOfDT(E.period) during "Assessment Period One"
			sort by start of PeriodToIntervalOfDT(period)
	)}

define "Denominator 2":
	{First(
		"Depression Encounters" E
			where PeriodToIntervalOfDT(E.period) during "Assessment Period Two"
			sort by start of PeriodToIntervalOfDT(period)
	)}

define "Denominator 3":
	{First(
		"Depression Encounters" E
			where PeriodToIntervalOfDT(E.period) during "Assessment Period Three"
			sort by start of PeriodToIntervalOfDT(period)
	)}

Issue with Partial date/time values

The following CQL:

define HoursBetween: hours between @T06 and @T07:00:00Z

Will return an error:

Error: ReadablePartial objects must have the same set of fields

But I believe this should return 1, because the precision is known in both date/time values at the level of precision of the comparison (hours).

Engine is failing on Equal(CodeableConcept, CodeableConcept) when grouping

Running this library:

using FHIR version '3.0.0'

context Patient

define ObservationCodes: 
    [Observation] O
        return O.code

define LastNObservations:
    ObservationCodes C
         return { code: C, observations: ([Observation: code in C]).take(5) }

Using Patient-1136, gets the error:

Error: Cannot perform equal operator on types CodeableConcept and CodeableConcept

But CodeableConcept equality should be supported as a generic structure equality.

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.