Coder Social home page Coder Social logo

cqframework / cql-execution Goto Github PK

View Code? Open in Web Editor NEW
65.0 17.0 31.0 11.04 MB

A JavaScript framework for executing CQL

License: Apache License 2.0

JavaScript 89.48% Java 0.10% Shell 0.01% TypeScript 10.41%
cql clinical-quality-language clinical-decision-support clinical-quality-measurement fhir

cql-execution's Introduction

CI Checks codecov

CQL Execution Framework

The CQL Execution Framework provides a TypeScript/JavaScript library for executing CQL artifacts expressed as JSON ELM.

For more information, see the CQL Execution Framework Overview.

Data Model and Terminology Service Implementations

This library (cql-execution) focuses on supporting CQL's logical constructs; it does not provide robust support for any particular data model or terminology service. To fully understand the benefit of the CQL Execution Framework, it must be used with more robust data model providers (called PatientSource implementations) and terminology providers (called CodeService implementations).

Implementors interested in executing electronic Clinical Quality Measures (eCQMs) using the QDM data model should consider using the cqm-execution project (which is based on cql-execution).

Implementors interested in executing FHIR-based CQL logic should consider using the cql-exec-fhir PatientSource with cql-execution.

Implementors interested in using the National Library of Medicine's Value Set Authority Center (VSAC) as a terminology service for looking up value sets should consider using the cql-exec-vsac CodeService with cql-execution.

The cql-exec-examples project provides examples of how cql-execution, cql-exec-fhir, and cql-exec-vsac can be used together.

Current Limitations

This library supports operations defined in CQL 1.4 and 1.5, but is not yet a complete implementation. Implementors should be aware of the following limitations and gaps in cql-execution:

  • Direct support for specific data models is not provided by this library (see above for details).
  • PatientSource, CodeService, and Results APIs are still evolving and subject to change.
  • Since this library uses the JavaScript Number class for both CQL Integer and CQL Decimal, it may display the following limitations related to numbers and math:
    • Reduced precision compared to that which is specified by the CQL specification
    • Issues typically associated with floating point arithmetic
    • Decimals without a decimal portion (e.g., 2.0) may be treated as CQL Integers
  • The following STU (non-normative) features introduced in CQL 1.5 are not yet supported:
    • Long datatype
    • Fluent functions
    • Retrieve search paths
    • Retrieve includes
  • In addition the following features defined prior to CQL 1.5 are also not yet supported:
    • Related context retrieves
    • Unfiltered context retrieves
    • Unfiltered context references to other libraries
    • External functions
  • While the source code of cql-execution is in TypeScript, full-fledged typing of the library is not yet implemented
    • Conversion from JavaScript to TypeScript was done in this pull request, with the intent on making incremental type improvements in subsequent pull requests.

The above is a partial list covering the most significant limitations. For more details, see the CQL_Execution_Features.xlsx spreadsheet.

Project Configuration

To use this project, you should perform the following steps:

  1. Install Node.js (Note: npm version 6.x.x recommended)
  2. Execute the following from the root directory: npm install

To Execute Your CQL

Please note that while the CQL Execution library supports many aspects of CQL, it does not support everything in the CQL specification. You should check to see what is implemented (by referencing the unit tests) before expecting it to work! For a working example, see examples.

There are several steps involved to execute CQL. First, you must create a JSON representation of the ELM. For the easiest integration, we will generate a JSON file using cql-to-elm:

  1. Install the Java 11 SDK
  2. Clone the clinical_quality_language repository to a location of your choice
  3. cd ${path_to_clinical_quality_language}/Src/java (replacing ${path_to_clinical_quality_language} with the path to the local clone)
  4. ./gradlew :cql-to-elm-cli:installDist
  5. ./cql-to-elm-cli/build/install/cql-to-elm-cli/bin/cql-to-elm-cli --format=JSON --input ${path_to_cql} --output ${path_to_cql-execution}/customCQL

The above example puts the example CQL into a subfolder of the cql-execution project to make the relative paths to cql-execution libraries easier, but it doesn't have to go there. If you put it elsewhere, you'll need to modify the examples below so that the require statements point to the correct location of the cql export.

In the rest of the examples, we'll assume an age.cql file with the following contents. This follows the example already in the "examples" folder (but of course you can use your own CQL):

library AgeAtMP version '1'

// NOTE: This example uses a custom data model that is very simplistic and suitable only for
// demonstration and testing purposes.  Real-world CQL should use a more appropriate model.
using Simple version '1.0.0'

parameter MeasurementPeriod default Interval[DateTime(2013, 1, 1, 0, 0, 0, 0), DateTime(2014, 1, 1, 0, 0, 0, 0))

context Patient

define InDemographic:
    AgeInYearsAt(start of MeasurementPeriod) >= 2 and AgeInYearsAt(start of MeasurementPeriod) < 18

TypeScript Example

Next, we can create a TypeScript file to execute the above CQL. This file will need to contain (or import) JSON patient representations for testing as well. Our example CQL uses a "Simple" data model developed only for demonstration and testing purposes. In this model, each patient is represented using a simple JSON object. For ease of use, let's put the file in the customCQL directory:

import cql from '../../src/cql';
import * as measure from './age.json'; // Requires the "resolveJsonModule" compiler option to be "true"

const lib = new cql.Library(measure);
const executor = new cql.Executor(lib);
const psource = new cql.PatientSource([
  {
    id: '1',
    recordType: 'Patient',
    name: 'John Smith',
    gender: 'M',
    birthDate: '1980-02-17T06:15'
  },
  {
    id: '2',
    recordType: 'Patient',
    name: 'Sally Smith',
    gender: 'F',
    birthDate: '2007-08-02T11:47'
  }
]);

executor
  .exec(psource)
  .then(result => {
    console.log(JSON.stringify(result, undefined, 2));
  })
  .catch(err => {
    console.error(err);
  });

In the above file, we've assumed the JSON ELM JSON file for the measure is called age.json and is in the same directory as the file that requires is. We've also assumed a couple of very simple patients. Let's call the file we just created exec-age.ts.

Now we can execute the measure using ts-node:

npx ts-node -O '{ "resolveJsonModule": true }' --files ${path_to_cql-execution}/customCQL/exec-age.ts

If all is well, it should print the result object to standard out.

JavaScript Example

For usage in regular JavaScript, we can refer to the compiled JavaScript in the lib directory. Ensure that this JavaScript is present by running npm run build before continuing on to the example. We will follow the same steps as the above TypeScript example, but our JavaScript code must use require instead of import, and will load the cql-execution library from the lib directory. As before, let's put the file in the customCQL directory:

Next, create a JavaScript file to execute the CQL above. This file will need to contain (or require) JSON patient representations for testing as well. Our example CQL uses a "Simple" data model developed only for demonstration and testing purposes. In this model, each patient is represented using a simple JSON object. For ease of use, let's put the file in the customCQL directory:

const cql = require('../lib/cql');
const measure = require('./age.json');

const lib = new cql.Library(measure);
const executor = new cql.Executor(lib);
const psource = new cql.PatientSource([ {
  'id' : '1',
  'recordType' : 'Patient',
  'name': 'John Smith',
  'gender': 'M',
  'birthDate' : '1980-02-17T06:15'
}, {
  'id' : '2',
  'recordType' : 'Patient',
  'name': 'Sally Smith',
  'gender': 'F',
  'birthDate' : '2007-08-02T11:47'
} ]);

executor
  .exec(psource)
  .then(result => {
    console.log(JSON.stringify(result, undefined, 2));
  })
  .catch(err => {
    console.error(err);
  });

The above file has the same assumptions as the TypeScript example above. Let's call the file we just created exec-age.js.

Now we can execute the measure using Node.js:

node ${path_to_cql-execution}/customCQL/exec-age.js

If all is well, it should print the result object to standard out, and the output should be identical to that of the TypeScript example.

To Run the CQL Execution Unit Tests

Execute npm test.

To Develop Tests

Many of the tests require JSON ELM data. It is much easier to write CQL rather than JSON ELM, so test authors should create test data by adding new CQL to test/elm/*/data.cql. Some conventions are followed to make testing easier. The following is an example of some test data:

// @Test: And
define AllTrue: true and true
define SomeTrue: true and false
define AllFalse: false and false

The // @Test: And indicates the name of the test suite it applies to ("And"). The group of statements that follows the # And represents the CQL Library that will be supplied as test data to the "And" test suite.

To convert the CQL to JavaScript containing the JSON ELM representation, execute npm run build:test-data. This will use the java cql-to-elm project to generate the test/elm/*/data.js file containing the following exported variable declaration (NOTE: It's been slimmed down a bit here to make it easier to read, but nothing substantial has been removed):

/* And
library TestSnippet version '1'
using Simple version '1.0.0'
context Patient
define AllTrue: true and true
define SomeTrue: true and false
define AllFalse: false and false
*/

module.exports['And'] = {
   "library" : {
      "identifier" : { "id" : "TestSnippet", "version" : "1" },
      "schemaIdentifier" : { "id" : "urn:hl7-org:elm", "version" : "r1" },
      "usings" : {
         "def" : [
           { "localIdentifier" : "System", "uri" : "urn:hl7-org:elm-types:r1" },
           { "localIdentifier" : "Simple", "uri" : "https://github.com/cqframework/cql-execution/simple", "version" : "1.0.0" }
         ]
      },
      "statements" : {
         "def" : [ {
            "name" : "Patient",
            "context" : "Patient",
            "expression" : {
               "type" : "SingletonFrom",
               "operand" : {
                  "dataType" : "{https://github.com/cqframework/cql-execution/simple}Patient",
                  "type" : "Retrieve"
               }
            }
         }, {
            "name" : "AllTrue",
            "context" : "Patient",
            "accessLevel" : "Public",
            "expression" : {
               "type" : "And",
               "operand" : [
                  { "valueType" : "{urn:hl7-org:elm-types:r1}Boolean", "value" : "true", "type" : "Literal" },
                  { "valueType" : "{urn:hl7-org:elm-types:r1}Boolean", "value" : "true", "type" : "Literal" }
               ]
            }
         }, {
            "name" : "SomeTrue",
            "context" : "Patient",
            "accessLevel" : "Public",
            "expression" : {
               "type" : "And",
               "operand" : [
                  { "valueType" : "{urn:hl7-org:elm-types:r1}Boolean", "value" : "true", "type" : "Literal" },
                  { "valueType" : "{urn:hl7-org:elm-types:r1}Boolean", "value" : "false", "type" : "Literal" }
               ]
            }
         }, {
            "name" : "AllFalse",
            "context" : "Patient",
            "accessLevel" : "Public",
            "expression" : {
               "type" : "And",
               "operand" : [
                  { "valueType" : "{urn:hl7-org:elm-types:r1}Boolean", "value" : "false", "type" : "Literal" },
                  { "valueType" : "{urn:hl7-org:elm-types:r1}Boolean", "value" : "false", "type" : "Literal" }
               ]
            }
         }
      ]}
   }
}

Notice that since the CQL didn't declare a library name/version, a data model, or a context, default values were inserted into the CQL at generation time. Now this CQL can be used in a test defined in test/elm/*/logical-test.ts. For example:

describe('And', () => {
  this.beforeEach(function () {
    setup(this, data);
  });

  it('should execute allTrue as true', async function () {
    should(await this.allTrue.exec(this.ctx)).be.true();
  });

  it('should execute someTrue as false', async function () {
    should(await this.someTrue.exec(this.ctx)).be.false();
  });

  it('should execute allFalse as false', async function () {
    should(await this.allFalse.exec(this.ctx)).be.false();
  });
});

The test suite above uses Mocha and Should.js. The setup function sets up the test case by creating this.lib (representing the CqlLibrary instance of the test data), creating @this.ctx (representing a Context for execution), and creating local variables for each defined concept (in this case, this.allTrue, this.allFalse, and this.someTrue). Note that the local variables use lowercase first letters even though the CQL expression name starts with an uppercase letter.

Watching For Changes

Rather than continually having to run npm run build:test-data and npm test after every modification to the test data text file, you can setup a process to watch for changes and regenerate the data.js files every time it detects changes in the source text file. Simply execute npm run watch:test-data.

Pull Requests

If TypeScript source code is modified, cql4browsers.js needs to be included in the pull request, otherwise GitHub Actions CI will fail. To generate this file, run:

npm run build:browserify

cql-execution's People

Contributors

adongare avatar birick1 avatar bkaney avatar brynrhodes avatar c-monkey avatar cmoesel avatar daco101 avatar dczulada avatar dependabot[bot] avatar edeyoung avatar elsaperelli avatar hadleynet avatar holmesie avatar hossenlopp avatar jawalonoski avatar jbradl11 avatar luis1van avatar mationai avatar mayerm94 avatar mgramigna avatar mulcahyk avatar natjoe4 avatar pkmitre avatar poolis avatar rdingwell avatar sorliog avatar tangiblezero avatar zlister 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

cql-execution's Issues

Is the 'IS' operator going to be implemented soon?

I see the pull request for the 'IS' operator:
#114 (comment).

I am working with the opioid cds services libraries and I am getting an error from the OpioidCDS_Common library:

Error: Unimplemented Expression: Is
at Is.UnimplementedExpression.exec (expression.js:97)

Thanks!

Age functions fail when a patient has a null or undefined birthDate

From @jgibson on July 18, 2017 18:59

If you define a patient with no birthDate and execute the following CQL:

define "MissingAge": AgeInYears() is null

Then it will fail with a stack trace:

TypeError: Cannot read property 'toJSDate' of null
      at CalculateAge.module.exports.CalculateAge.CalculateAge.exec (node_modules/cql-execution/lib/elm/clinical.js:262:33)
      at GreaterOrEqual.module.exports.Expression.Expression.execArgs (node_modules/cql-execution/lib/elm/expression.js:36:30)
      at GreaterOrEqual.module.exports.GreaterOrEqual.GreaterOrEqual.exec (node_modules/cql-execution/lib/elm/comparison.js:77:19)
      at And.module.exports.Expression.Expression.execArgs (node_modules/cql-execution/lib/elm/expression.js:36:30)
      at And.module.exports.And.And.exec (node_modules/cql-execution/lib/elm/logical.js:19:64)
      at ExpressionDef.module.exports.ExpressionDef.ExpressionDef.exec (node_modules/cql-execution/lib/elm/reusable.js:23:53)
      at Executor.module.exports.Executor.Executor.exec_patient_context (node_modules/cql-execution/lib/runtime/executor.js:62:71)
      at Executor.module.exports.Executor.Executor.exec (node_modules/cql-execution/lib/runtime/executor.js:41:24)
      at Context.testFunc (test/loadTestCases/index.js:138:36)

This is in version cql-execution-0.0.6-011abcd0c243d017e47ed82e2c74bd0acc46841f. I haven't test the Age*At functions, but they may have the same problem.

Fortunately this bug may already be fixed on the cql4bonnie branch by the changes to Src/coffeescript/cql-execution/src/elm/clinical.coffee in 0ba67baebf3165f0d0fc2cbd2826d231c9593e9c.

Copied from original issue: cqframework/clinical_quality_language#192

Test cases for variance and population variance are reversed

From @brynrhodes on August 30, 2016 16:35

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}

)

Copied from original issue: cqframework/clinical_quality_language#64

Scoping Issue in CoffeeScript CQL Execution

From @cmoesel on July 7, 2017 17:5

In some cases, it appears there is a scoping issue in CQL execution -- specifically around aliases. For example, if an expression uses an alias C in a query, and that query invokes a function that also uses an alias C for something different, one will overwrite the other.

I don't have a specific test case on hand at the moment, but did run into this on some internal CQL-related work. Will try to create a test case (and maybe even a fix) when I have a moment.

Copied from original issue: cqframework/clinical_quality_language#162

Internet Explorer bug with ucum.js

When the cql-execution engine is used and opened in Internet Explorer, an error occurs due to ES6 syntax being used in the dependency ucum.js. This should be resolved so that Internet Explorer users can reliable use the cql-execution engine.

TypeError: Cannot read property 'operand' of undefined

Hi,

We are trying to setup CQL execution engine in our environment and faced issues during build and execution.
We are trying to build and execute the sample age calculation program given in github.

OS : RHEL7.5

We did see several syntax error issues during cake build and now see following typeerror during executing java script.

[@ lib]$ node age-exec.js
/u13/DigitalMeasures/cql-execution-master/lib/elm/expression.js:12
if (json.operand != null) {
^

TypeError: Cannot read property 'operand' of undefined
at new Expression (/u13/DigitalMeasures/cql-execution-master/lib/elm/expression.js:12:16)
at new ParameterDef (/u13/DigitalMeasures/cql-execution-master/lib/elm/parameters.js:11:7)
at new Library (/u13/DigitalMeasures/cql-execution-master/lib/elm/library.js:24:39)
at Object. (/u13/DigitalMeasures/cql-execution-master/lib/age-exec.js:9:9)
at Object. (/u13/DigitalMeasures/cql-execution-master/lib/age-exec.js:82:4)
at Module._compile (internal/modules/cjs/loader.js:759:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:770:10)
at Module.load (internal/modules/cjs/loader.js:628:32)
at Function.Module._load (internal/modules/cjs/loader.js:555:12)
at Function.Module.runMain (internal/modules/cjs/loader.js:822:10)

From stackoverflow, we see typeError is generally seen if props is not loaded correctly. Could you help us as this is the sample age calculation program given in your example and we are facing issues while executing.

https://stackoverflow.com/questions/53473858/nodejs-typeerror-cannot-read-property-name-of-undefined

FYI. Below are the modules installed globally until now for build

@babel
babelify
browserify
coffeescript
moment
npm
ucum.js

Thanks & Regards,
Ganesh Ramanathan, Venkata Balaji Yadalla.

Functions with the same name in CQL files.

Hi, I'm using the engine to run eCQMs.
I've found a problem when there are different functions with the same name in the CQL file. This happens for instance in the FHIRHelpers.cql file (cql-exec-examples proyect). In these cases the engine is not able to find the correct function because it searches just by name, ignoring the parameters. I think it should be fixed in the file src\elm\reusable.coffee (FunctionRef class, exec function).
Thanks for writing the framework!. I look forward to hearing from you.
Sebastian.

error "Could not resolve call to operator SameAs with signature (FHIR.dateTime,System.DateTime)"

I am just starting with CQL, so I presume I am just doing something wrong ...
I tried to run numerous of the examples, but usually was drowned in error messages.
So I tried with some very extremely simple examples, but also there, I soon get errors...
My java command e.g. is:
set CLASSPATH="..\jar_files_downloaded*"
java -cp %CLASSPATH% org.cqframework.cql.cql2elm.CqlTranslator -input C:\HL7_CQL\cqframework_software\clinical_quality_language-master\clinical_quality_language-master\Examples\EH_CMS9v4_NQF0480_BF_ExclusiveBreastFeed\test_jozef.cql

My CQL is:
library CMS9v4_CDS version '1'

using FHIR version '1.4'

/* valueset definitions */
valueset "Feeding Intention-Breast": '2.16.840.1.113762.1.4.1045.29'
valueset "Feeding Intention-Not-To-Breast": 'TBD' // Code '636111000124114' from "SNOMED-CT" display: 'Mother refuses to breastfeed (situation)'
valueset "Galactosemia": '2.16.840.1.113883.3.117.1.7.1.35'
valueset "Single Live Birth": '2.16.840.1.113883.3.117.1.7.1.25'
valueset "Single Live Born Newborn Born in Hospital": '2.16.840.1.113883.3.117.1.7.1.26'
valueset "Encounter Inpatient": '2.16.840.1.113883.3.666.5.307'
valueset "Estimated Gestational Age at Birth": '2.16.840.1.113762.1.4.1045.47'
valueset "Parenteral Nutrition": '2.16.840.1.113883.3.117.1.7.1.38'
valueset "Breast Milk": '2.16.840.1.113883.3.117.1.7.1.30'
valueset "Dietary Intake Other than Breast Milk": '2.16.840.1.113883.3.117.1.7.1.27'
valueset "Neonatal Intensive Care Unit (NICU)": '2.16.840.1.113883.3.117.1.7.1.75'
valueset "Patient Expired": '2.16.840.1.113883.3.117.1.7.1.309'
valueset "Discharge To Acute Care Facility": '2.16.840.1.113883.3.117.1.7.1.87'

/* check for breastfeeding - exclusions */

/* further definitions /
/
Breastfeeding Exclusion /
/
define "Breastfeeding Exclusions": [Condition: "Galactosemia"] /
/
Breastfeeding intention */

/* Testing */
define "Breastfeeding Exclusions":
[Condition: "Galactosemia"]

define "Intention to Breastfeed":
[RiskAssessment: "Feeding Intention-Breast"] R
where R.date 1 hour or more after "Infant Birth Date"

define "Breastfeeding Intention":
"Intention to Breastfeed"
/* union "Intention not to Breastfeed" */

// the following definition contains errors
/* define "Intention not to Breastfeed":
[RiskAssessment: "Feeding Intention-Not-To-Breastfeed"] R
where R.date 1 hour or more after "Infant Birth Date"
*/

/** taken from file CMS9v4_CQM-cql */
define "Infant Birth Date":
Last("Single Live Birth Condition").abatementDateTime.value

/** taken from file CMS9v4_CQM-cql */
define "Single Live Birth Condition":
([Condition: "Single Live Birth"]
union [Condition: "Single Live Born Newborn Born in Hospital"]) Condition
where Condition.clinicalStatus.value = 'active'
and Condition.verificationStatus.value = 'confirmed'

When I run this with the above Java command, I get:
Translation failed due to errors:
Warning:[31:3, 31:29] Could not resolve membership operator for terminology target of the retrieve.
Warning:[34:3, 34:46] Could not resolve membership operator for terminology target of the retrieve.
Warning:[54:4, 54:35] Could not resolve membership operator for terminology target of the retrieve.
Warning:[55:11, 55:66] Could not resolve membership operator for terminology target of the retrieve.
Error:[35:18, 35:37] Could not resolve call to operator SameOrAfter with signature (FHIR.dateTime,System.DateTime).

2 questions:

  • what do the warnings mean? I could not find any documentation
  • according to the specification, "dateTime" is supported by "SameOrAfter", so I do not understand why I get the error.
    My apologies if this is not the place for posting this, but I could not find any "beginners forum" anywhere. If there is such one, I will be happy to repost there.

Support "point from" operator

The PointFrom operator extracts the point from a unit interval (and throws an error otherwise). It can be invoked via the following syntax:

define PointFromUnit2Interval: point from Interval[2,2]

Question for use with eCQI published eCQMs

Hi, I'm attempting (hoping) to use this project to run the published eCQMs found here: https://ecqi.healthit.gov/system/files/EP_EC_eCQM_2018-05.zip.

I've successfully installed the project, run the examples, translated some CQL files, and have been able to run CMS125v7 albeit with some issues that raise the following questions:

  1. Can this execution engine use the QDM eCQMs referenced above? If so how?
    If I'm understanding things correctly this engine expects to use FHIR-QUICK models as input and as such needs CQL written with using QUICK. Of course the published eCQM CQL measures are written using QDMv5.3, so I imagine there would have to be a translation somewhere for alignment between the data model and the CQL files - either when converting the CQL (QDM) -> ELM (QUICK) or the data model from (QUICK) -> (QDM).
    As an example how should I map QDM fields like "Patient Characteristic Birthdate" in the define "Initial Population" in CMS125v7 so they resolve properly. Per the http://hl7.org/fhir/us/qicore/2018Jan/qdm-to-qicore.html doc it seems this QDM Attribute should map to QI Core patient.birthDate but I don't see how to do it naturally in this framework. Is there a way besides writing QUICK to QDM data model translator?

  2. Do you have plans to implement a LibraryManager to enable include directives? If yes, when?
    I see indication of what looks like the majority of the plumbing necessary to enable CQL includes e.g. include MATGlobalCommonFunctions version '2.0.000' called Global. Just want to avoid writing one if you're going to :) For testing consolidating all the CQL files into a single CQL file, removing the library qualifiers, and translating that to ELM worked.

Any guidance would be appreciated. Apologies for any incorrect use of terminology (still learning).

Thanks for writing the framework, thanks for reading and please let me know if you require any clarification or data.

Need help and few clarification during execution of CMS68v9 measure

I have converted 2020 year measure-CMS68v9 CQL to coffee script. I am learning to create coffee script file for the execution for same measure. I have created exec-68v9.coffee script as under. I have performed cake build and when I try to execute it gives no result.
Following are the contents of required file.
68v9.coffee

module.exports = {
"library" : {
"annotation" : [ {
"translatorOptions" : "",
"type" : "CqlToElmInfo"
} ],
"identifier" : {
"id" : "DocumentationofCurrentMedicationsintheMedicalRecord",
"version" : "9.1.000"
},
"schemaIdentifier" : {
"id" : "urn:hl7-org:elm",
"version" : "r1"
},
"usings" : {
"def" : [ {
"localIdentifier" : "System",
"uri" : "urn:hl7-org:elm-types:r1"
}, {
"localIdentifier" : "QDM",
"uri" : "urn:healthit-gov:qdm:v5_4",
"version" : "5.4"
} ]
},
"parameters" : {
"def" : [ {
"name" : "Measurement Period",
"accessLevel" : "Public",
"parameterTypeSpecifier" : {
"type" : "IntervalTypeSpecifier",
"pointType" : {
"name" : "{urn:hl7-org:elm-types:r1}DateTime",
"type" : "NamedTypeSpecifier"
}
}
} ]
},
"codeSystems" : {
"def" : [ {
"name" : "LOINC",
"id" : "urn:oid:2.16.840.1.113883.6.1",
"accessLevel" : "Public"
}, {
"name" : "SNOMEDCT",
"id" : "urn:oid:2.16.840.1.113883.6.96",
"accessLevel" : "Public"
} ]
},
"valueSets" : {
"def" : [ {
"name" : "Ethnicity",
"id" : "urn:oid:2.16.840.1.114222.4.11.837",
"accessLevel" : "Public"
}, {
"name" : "Medical or Other reason not done",
"id" : "urn:oid:2.16.840.1.113883.3.600.1.1502",
"accessLevel" : "Public"
}, {
"name" : "Medications Encounter Code Set",
"id" : "urn:oid:2.16.840.1.113883.3.600.1.1834",
"accessLevel" : "Public"
}, {
"name" : "ONC Administrative Sex",
"id" : "urn:oid:2.16.840.1.113762.1.4.1",
"accessLevel" : "Public"
}, {
"name" : "Payer",
"id" : "urn:oid:2.16.840.1.114222.4.11.3591",
"accessLevel" : "Public"
}, {
"name" : "Race",
"id" : "urn:oid:2.16.840.1.114222.4.11.836",
"accessLevel" : "Public"
} ]
},
"codes" : {
"def" : [ {
"name" : "Birth date",
"id" : "21112-8",
"display" : "Birth date",
"accessLevel" : "Public",
"codeSystem" : {
"name" : "LOINC"
}
}, {
"name" : "Documentation of current medications (procedure)",
"id" : "428191000124101",
"display" : "Documentation of current medications (procedure)",
"accessLevel" : "Public",
"codeSystem" : {
"name" : "SNOMEDCT"
}
} ]
},
"statements" : {
"def" : [ {
"name" : "Patient",
"context" : "Patient",
"expression" : {
"type" : "SingletonFrom",
"operand" : {
"dataType" : "{urn:healthit-gov:qdm:v5_4}Patient",
"templateId" : "Patient",
"type" : "Retrieve"
}
}
}, {
"name" : "SDE Ethnicity",
"context" : "Patient",
"accessLevel" : "Public",
"expression" : {
"dataType" : "{urn:healthit-gov:qdm:v5_4}PatientCharacteristicEthnicity",
"codeProperty" : "code",
"type" : "Retrieve",
"codes" : {
"name" : "Ethnicity",
"type" : "ValueSetRef"
}
}
}, {
"name" : "SDE Payer",
"context" : "Patient",
"accessLevel" : "Public",
"expression" : {
"dataType" : "{urn:healthit-gov:qdm:v5_4}PatientCharacteristicPayer",
"codeProperty" : "code",
"type" : "Retrieve",
"codes" : {
"name" : "Payer",
"type" : "ValueSetRef"
}
}
}, {
"name" : "SDE Race",
"context" : "Patient",
"accessLevel" : "Public",
"expression" : {
"dataType" : "{urn:healthit-gov:qdm:v5_4}PatientCharacteristicRace",
"codeProperty" : "code",
"type" : "Retrieve",
"codes" : {
"name" : "Race",
"type" : "ValueSetRef"
}
}
}, {
"name" : "SDE Sex",
"context" : "Patient",
"accessLevel" : "Public",
"expression" : {
"dataType" : "{urn:healthit-gov:qdm:v5_4}PatientCharacteristicSex",
"codeProperty" : "code",
"type" : "Retrieve",
"codes" : {
"name" : "ONC Administrative Sex",
"type" : "ValueSetRef"
}
}
}, {
"name" : "Qualifying Encounters During Measurement Period",
"context" : "Patient",
"accessLevel" : "Public",
"expression" : {
"type" : "Query",
"source" : [ {
"alias" : "QualifyingEncounter",
"expression" : {
"dataType" : "{urn:healthit-gov:qdm:v5_4}PositiveEncounterPerformed",
"templateId" : "PositiveEncounterPerformed",
"codeProperty" : "code",
"type" : "Retrieve",
"codes" : {
"name" : "Medications Encounter Code Set",
"type" : "ValueSetRef"
}
}
} ],
"relationship" : [ ],
"where" : {
"type" : "IncludedIn",
"operand" : [ {
"path" : "relevantPeriod",
"scope" : "QualifyingEncounter",
"type" : "Property"
}, {
"name" : "Measurement Period",
"type" : "ParameterRef"
} ]
}
}
}, {
"name" : "CalendarAgeInYearsAt",
"context" : "Patient",
"accessLevel" : "Public",
"type" : "FunctionDef",
"expression" : {
"precision" : "Year",
"type" : "DurationBetween",
"operand" : [ {
"type" : "ToDate",
"operand" : {
"name" : "BirthDateTime",
"type" : "OperandRef"
}
}, {
"type" : "ToDate",
"operand" : {
"name" : "AsOf",
"type" : "OperandRef"
}
} ]
},
"operand" : [ {
"name" : "BirthDateTime",
"operandTypeSpecifier" : {
"name" : "{urn:hl7-org:elm-types:r1}DateTime",
"type" : "NamedTypeSpecifier"
}
}, {
"name" : "AsOf",
"operandTypeSpecifier" : {
"name" : "{urn:hl7-org:elm-types:r1}DateTime",
"type" : "NamedTypeSpecifier"
}
} ]
}, {
"name" : "Patient Age 18 or Older at Start of Measurement Period",
"context" : "Patient",
"accessLevel" : "Public",
"expression" : {
"type" : "Exists",
"operand" : {
"type" : "Query",
"source" : [ {
"alias" : "BirthDate",
"expression" : {
"dataType" : "{urn:healthit-gov:qdm:v5_4}PatientCharacteristicBirthdate",
"codeProperty" : "code",
"type" : "Retrieve",
"codes" : {
"type" : "ToList",
"operand" : {
"name" : "Birth date",
"type" : "CodeRef"
}
}
}
} ],
"relationship" : [ ],
"where" : {
"type" : "GreaterOrEqual",
"operand" : [ {
"name" : "CalendarAgeInYearsAt",
"type" : "FunctionRef",
"operand" : [ {
"path" : "birthDatetime",
"scope" : "BirthDate",
"type" : "Property"
}, {
"type" : "Start",
"operand" : {
"name" : "Measurement Period",
"type" : "ParameterRef"
}
} ]
}, {
"valueType" : "{urn:hl7-org:elm-types:r1}Integer",
"value" : "18",
"type" : "Literal"
} ]
}
}
}
}, {
"name" : "Initial Population",
"context" : "Patient",
"accessLevel" : "Public",
"expression" : {
"type" : "Query",
"source" : [ {
"alias" : "QualifyingEncounter",
"expression" : {
"name" : "Qualifying Encounters During Measurement Period",
"type" : "ExpressionRef"
}
} ],
"relationship" : [ ],
"where" : {
"name" : "Patient Age 18 or Older at Start of Measurement Period",
"type" : "ExpressionRef"
}
}
}, {
"name" : "Denominator",
"context" : "Patient",
"accessLevel" : "Public",
"expression" : {
"name" : "Initial Population",
"type" : "ExpressionRef"
}
}, {
"name" : "Medications Not Documented for Medical Reason",
"context" : "Patient",
"accessLevel" : "Public",
"expression" : {
"type" : "Query",
"source" : [ {
"alias" : "NotPerformed",
"expression" : {
"dataType" : "{urn:healthit-gov:qdm:v5_4}NegativeProcedurePerformed",
"templateId" : "NegativeProcedurePerformed",
"codeProperty" : "code",
"type" : "Retrieve",
"codes" : {
"type" : "ToList",
"operand" : {
"name" : "Documentation of current medications (procedure)",
"type" : "CodeRef"
}
}
}
} ],
"relationship" : [ ],
"where" : {
"type" : "InValueSet",
"code" : {
"path" : "negationRationale",
"scope" : "NotPerformed",
"type" : "Property"
},
"valueset" : {
"name" : "Medical or Other reason not done"
}
}
}
}, {
"name" : "Denominator Exceptions",
"context" : "Patient",
"accessLevel" : "Public",
"expression" : {
"type" : "Query",
"source" : [ {
"alias" : "EncounterDuringMeasurementPeriod",
"expression" : {
"name" : "Qualifying Encounters During Measurement Period",
"type" : "ExpressionRef"
}
} ],
"relationship" : [ {
"alias" : "MedicationsNotDocumented",
"type" : "With",
"expression" : {
"name" : "Medications Not Documented for Medical Reason",
"type" : "ExpressionRef"
},
"suchThat" : {
"type" : "In",
"operand" : [ {
"path" : "authorDatetime",
"scope" : "MedicationsNotDocumented",
"type" : "Property"
}, {
"path" : "relevantPeriod",
"scope" : "EncounterDuringMeasurementPeriod",
"type" : "Property"
} ]
}
} ]
}
}, {
"name" : "Medications Documented During Qualifying Encounter",
"context" : "Patient",
"accessLevel" : "Public",
"expression" : {
"type" : "Query",
"source" : [ {
"alias" : "QualifyingEncounterDuringMeasurementPeriod",
"expression" : {
"name" : "Qualifying Encounters During Measurement Period",
"type" : "ExpressionRef"
}
} ],
"relationship" : [ {
"alias" : "MedicationsDocumented",
"type" : "With",
"expression" : {
"dataType" : "{urn:healthit-gov:qdm:v5_4}PositiveProcedurePerformed",
"templateId" : "PositiveProcedurePerformed",
"codeProperty" : "code",
"type" : "Retrieve",
"codes" : {
"type" : "ToList",
"operand" : {
"name" : "Documentation of current medications (procedure)",
"type" : "CodeRef"
}
}
},
"suchThat" : {
"type" : "IncludedIn",
"operand" : [ {
"path" : "relevantPeriod",
"scope" : "MedicationsDocumented",
"type" : "Property"
}, {
"path" : "relevantPeriod",
"scope" : "QualifyingEncounterDuringMeasurementPeriod",
"type" : "Property"
} ]
}
} ]
}
}, {
"name" : "Numerator",
"context" : "Patient",
"accessLevel" : "Public",
"expression" : {
"name" : "Medications Documented During Qualifying Encounter",
"type" : "ExpressionRef"
}
} ]
}
}
}

exec-68v9.coffee

cql = require '../cql'
codes = require '../cql-code-service'
measure = require './68v9'

cservice = new codes.CodeService {
"1.2.3.4.5": {
"1": [
{
"code": "ABC",
"system": "5.4.3.2.1",
"version": "1"
}, {
"code": "DEF",
"system": "5.4.3.2.1",
"version": "2"
}, {
"code": "GHI",
"system": "5.4.3.4.5",
"version": "3"
}
],
"2": [
{
"code": "ABC",
"system": "5.4.3.2.1",
"version": "1"
}, {
"code": "DEF",
"system": "5.4.3.2.1",
"version": "2"
}, {
"code": "JKL",
"system": "5.4.3.2.1",
"version": "3"
}
]
},
"6.7.8.9.0": {
"A": [
{
"code": "MNO",
"system": "2.4.6.8.0",
"version": "3"
}, {
"code": "PQR",
"system": "2.4.6.8.0",
"version": "2"
}, {
"code": "STU",
"system": "2.4.6.8.0",
"version": "1"
}
]
}
}

lib = new cql.Library(measure)
parameters = {
MeasurementPeriod: new cql.Interval(cql.DateTime.parse('2019-01-01'), cql.DateTime.parse('2020-01-01'), true, false)
}
executor = new cql.Executor(lib, cservice, parameters)
psource = new cql.PatientSource [ {
"resourceType": "Bundle",
"id": "example1",
"meta": {
"versionId": "1",
"lastUpdated": "2014-08-18T01:43:30Z"
},
"base": "http://example.com/base",
"entry" : [{
"resource": {
"id" : "1",
"meta" :{ "profile" : ["patient-qicore-qicore-patient"]},
"resourceType" : "Patient",
"identifier": [{ "value": "1" }],
"name": {"given":["John"], "family": ["Smith"]},
"gender": "M",
"birthDate" : "1980-02-17T06:15"}
}
]
}, {
"resourceType": "Bundle",
"id": "example1",
"meta": {
"versionId": "1",
"lastUpdated": "2014-08-18T01:43:30Z"
},
"base": "http://example.com/base",
"entry" : [{
"resource": {
"id" : "2",
"meta" :{ "profile" : ["patient-qicore-qicore-patient"]},
"resourceType" : "Patient",
"identifier": [{ "value": "2" }],
"name": {"given":["Sally"], "family": ["Smith"]},
"gender": "F",
"birthDate" : "2007-08-02T11:47"}
}
]
} ]

result = executor.exec(psource)
console.log JSON.stringify(result, undefined, 2)

When I perform execution of exec-68v9.coffee script, It gives no result. Everything is empty. I am not able to understand this. Please help to understand.
I have following questions.

  1. How can I give value sets using code service in exec file? Please share existing Ethnicity/Medications Encounter Code Set/Race or similar value sets to put as part of code service.
  2. How can I give SNOWMED data as patient source? In future How can I give required patient's data in JSON format? Please share any sample JSON format.

I am stuck and not able to proceed further. Please help to answer questions or any kind of help will be really appreciated.

Thanks.

Invoking Coalesce with a single argument yields an internal error

From @jgibson on July 25, 2017 14:44

If you accidentally call Coalesce with a single argument then it will crash the executor. Ideally it should provide a useful error message. For example, running this:

Last(ObsList O sort by Coalesce(O.valueQuantity.value))

will cause this error:

TypeError: Cannot read property 'parameters' of undefined
  at FunctionRef.module.exports.FunctionRef.FunctionRef.exec (node_modules/cql-execution/lib/elm/reusable.js:87:38)
  at FunctionRef.module.exports.Expression.Expression.execute (node_modules/cql-execution/lib/elm/expression.js:34:21)
  at ByExpression.module.exports.ByExpression.ByExpression.exec (node_modules/cql-execution/lib/elm/query.js:136:31)
  at node_modules/cql-execution/lib/elm/query.js:192:28
  at Array.sort (native)
  at SortClause.module.exports.SortClause.SortClause.sort (node_modules/cql-execution/lib/elm/query.js:185:23)
  at Query.module.exports.Query.Query.exec (node_modules/cql-execution/lib/elm/query.js:302:14)
  at Last.module.exports.Last.Last.exec (node_modules/cql-execution/lib/elm/list.js:315:25)
  at Last.module.exports.Expression.Expression.execute (node_modules/cql-execution/lib/elm/expression.js:34:21)
  at FunctionRef.module.exports.FunctionRef.FunctionRef.exec (node_modules/cql-execution/lib/elm/reusable.js:95:37)
  at FunctionRef.module.exports.Expression.Expression.execute (node_modules/cql-execution/lib/elm/expression.js:34:21)
  at ExpressionDef.module.exports.ExpressionDef.ExpressionDef.exec (node_modules/cql-execution/lib/elm/reusable.js:23:53)
  at ExpressionDef.module.exports.Expression.Expression.execute (node_modules/cql-execution/lib/elm/expression.js:34:21)
  at Executor.module.exports.Executor.Executor.exec_patient_context (node_modules/cql-execution/lib/runtime/executor.js:62:58)
  at Executor.module.exports.Executor.Executor.exec (node_modules/cql-execution/lib/runtime/executor.js:41:24)

This stacktrace is from the cql4bonnie branch, commit f0841f35.

Copied from original issue: cqframework/clinical_quality_language#198

cql-execution port to ES6...

From @turp1twin on November 17, 2016 4:47

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

Copied from original issue: cqframework/clinical_quality_language#80

Error raised because FHIR Helpers Library not in ctx

Description

Hi! First off, thanks for all of your work on this repo - I really appreciate it, especially porting it from coffeescript to JS!

I'm using V2 (the JS version of cql-execution) along with cql-exec-fhir to execute the JSON-ELM produced version of this CQL file, but when running the exec JS file, I get the following error:

.../cql-execution/src/elm/reusable.js:66
    functionDefs = functionDefs.filter(f => f.parameters.length === args.length);
                                ^
TypeError: Cannot read property 'filter' of undefined

This error occurs in src/elm/reusable.js. When debugging, I found that this.Library is "FHIRHelpers" and lib returns undefined. The ctx object's attributes are all undefined, or are empty arrays or objects (see the entire ctx object here), except for context_values, which you can view here, and parent, which you can view here. I've also included a branch that has all of the necessary files to reproduce this issue (see below in the "To Reproduce" section) and have had a teammate confirm he is getting the same error.

class FunctionRef extends Expression {
  constructor(json) {
    super(json);
    this.name = json.name;
    this.library = json.libraryName;
  }
  exec(ctx) {
    let functionDefs, child_ctx;
    if (this.library) {
      const lib = ctx.get(this.library);
      functionDefs = lib ? lib.getFunction(this.name) : undefined;
      const libCtx = ctx.getLibraryContext(this.library);
      child_ctx = libCtx ? libCtx.childContext() : undefined;
    } else {
      functionDefs = ctx.get(this.name);
      child_ctx = ctx.childContext();
    }
    const args = this.execArgs(ctx);

    // Filter out functions w/ wrong number of arguments.
    functionDefs = functionDefs.filter(f => f.parameters.length === args.length);
...

The error seems to occur any time that an attribute of BloodPressure is referenced - where BloodPressure.status in {'final', 'amended'} is the first line in which this occurs, but subsequent lines referencing other BloodPressure attributes also cause this error.

Interestingly enough, when checking to see if an attribute exists (i.e. where exists(BloodPressure.status)), no error occurs, and I'm guessing this is because a FHIR helper isn't needed to convert the attribute, since we're just checking to see if it exists.

Additionally, there's a strong chance this could be user error - I am new to FHIR and haven't personally dealt yet with LOINC codes until this point, and there could be something incorrect in my patient data as well (though I replaced my patient data with this and got the same error).

Screenshots

Screen Shot 2020-12-16 at 3 57 50 PM

To Reproduce

Clone my fork of cql-execution
Check out branch fhir-helpers-issue, then:
runyarn
cd exec-files
node exec-test.js

unable to implement string comparison

I have created a simple test case to check for the patient gender = 'female' using the following cql:

library MyTest version '1'
using FHIR version '4.0.1'
include FHIRHelpers version '4.0.1' called FHIRHelpers

context Patient

define "Is Female":
  Patient.gender in 'female'
  
define "Is Female2":
  Patient.gender = 'female'
  
define "Is Female3":
  Patient.gender.value = 'female'

Using the resulting elm/json, as well as several patients, the results are always null. I have tried the current cql-execution as well as the V2 beta. The problem seems to be in the method:
function getPropertyFromObject(obj, path)
in \src\elm\structured.js

The 'obj' passed in is the actual string 'female', the 'path' is a string: 'value'. Since the string 'female' is not an object, the property called 'value' is not found so a null is returned. Since gender is actually a 'code' and not a string according to FHIR, I tried using gender.value above but got the same result.

I can confirm the librarys are getting loaded properly and the Patient is loaded properly as well.

Check Decimal Min/Max Values for Correctness

The spec-tests are failing. Check implementation for correctness (may be related to limitations of JavaScript number:

  • CqlArithmeticFunctionsTest.MinValue.DecimalMinValue
  • CqlArithmeticFunctionsTest.MaxValue.DecimalMaxValue

Yarn command fails while execution of cake build command

I want to use this cql-execution application for eCQM 2020 measures. Based on the guideline, I have configured application in my Windows 10-64 bit PC. I am facing below error during "yarn install" command.

D:\git_workspace\cql-execution-coffee>yarn install
yarn install v1.22.4
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
$ ./node_modules/.bin/cake build && ./node_modules/.bin/cake build-cql4browsers
events.js:282
throw er; // Unhandled 'error' event
^

Error: spawn coffee ENOENT
at Process.ChildProcess._handle.onexit (internal/child_process.js:267:19)
at onErrorNT (internal/child_process.js:469:16)
at processTicksAndRejections (internal/process/task_queues.js:84:21)

Emitted 'error' event on ChildProcess instance at:
at Process.ChildProcess._handle.onexit (internal/child_process.js:273:12)
at onErrorNT (internal/child_process.js:469:16)
at processTicksAndRejections (internal/process/task_queues.js:84:21)
{
errno: -4058,
code: 'ENOENT',
syscall: 'spawn coffee',
path: 'coffee',
spawnargs: [ '-c', '-m', '-o', 'lib', 'src' ]
}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

I have installed and added "coffee" as part of system environment variables and added as part of path so that it is available from any location.

Below is the required versions installed.

D:\git_workspace\cql-execution-coffee>coffee -v
CoffeeScript version 1.12.7

D:\git_workspace\cql-execution-coffee>yarn -v
1.22.4

D:\git_workspace\cql-execution-coffee>npm -v
6.13.4

D:\git_workspace\cql-execution-coffee>node -v
v13.5.0

I am stuck and not able to proceed further. I don't have knowledge on coffee script. Based on some of google references, I found that "spawn" gives the error and change to "exec" Is there any way I can change from spawn to exec?

Any kind of help is really appreciated. Thanks.

Does where clause work?

We have a simple rule that checks for the existence of a resource within a ValueSet and then uses a where clause to make sure that resource has status='draft'. When we run this rule against our FHIR resource bundle it doesn't return true as expected. Is this a known bug or limitation? If I remove the where clause the rule fires so I know the resource is being found in the ValueSet.


valueset "MRIHeartStressTestVS": 'http://hook.md/ValueSet/MRIHeartStressTest'

...
define "New order for MRI Heart with stress":
exists ([ServiceRequest: "MRIHeartStressTestVS"] S
where S.status = 'draft'
)

Certificate Error when running installDist

When I run (...\CQL\clinical_quality_language\Src\java>.\gradlew :cql-to-elm:installDist) I get a certificate error. Have you guys run into this issue before? If so, what did you do to fix it?
certificate error

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.