qpp-measures-data
Advanced tools
Comparing version 0.0.41 to 1.0.0-alpha.1
@@ -1,3 +0,5 @@ | ||
## Develop | ||
# Contribution Guidelines | ||
## Getting Started | ||
Install the following homebrew dependencies: | ||
@@ -15,38 +17,23 @@ ``` | ||
### Generating measures-data.json | ||
To regenerate and validate the `measures-data.json` and `measures-data.xml` files, which contain additional metadata and conform to | ||
the measures schema, do the following: | ||
### Generating data | ||
To regenerate and validate data, do the following: | ||
``` | ||
npm run build:measures | ||
npm run build:measures # generates measures/measures-data.json and measures/measures-data.xml | ||
npm run build:benchmarks # generates benchmarks/2017.json | ||
npm run build:clinical-clusters # generates clinical-clusters/clinical-clusters.json | ||
``` | ||
### Generating benchmarks data | ||
To regenerate and validate benchmarks data from historical data: | ||
``` | ||
npm run build:benchmarks | ||
``` | ||
### Validation | ||
We've provided a simple tool to validate JSON against our JSON schema. | ||
For example, running | ||
We've provided a simple tool to validate JSON against our JSON schemas. By providing an argument to indicate the schema against which to validate, it can be used as follows: | ||
``` | ||
cat measures/measures-data.json | node scripts/validate-data.js measures | ||
cat [path to JSON] | node scripts/validate-data.js [measures | benchmarks | clinical-clusters] | ||
``` | ||
validates the latest version of `measures-data.json` against the latest `measures-schema.yaml`. | ||
To validate measures against `measures-schema.yaml`, run: | ||
``` | ||
cat [path to measures JSON] | node scripts/validate-data.js measures | ||
``` | ||
To validate benchmarks against `benchmarks-schema.yaml`, run: | ||
``` | ||
cat [path to benchmarks JSON] | node scripts/validate-data.js benchmarks | ||
``` | ||
### Additional measures or benchmarks | ||
### Additional measures | ||
`util/measures/additional-measures.json` includes data objects which are necessary for scoring but are not MIPS measures. Any additional measures should be added to this file, followed by a re-generation of measures data using the command described in the "Generating Data" section. | ||
`util/additional-measures.json` includes data objects which are necessary for scoring but are not MIPS measures. At this time `util/additional-measures.json` includes: | ||
At this time `util/measures/additional-measures.json` includes: | ||
@@ -56,2 +43,4 @@ 1. **Attestations:** Attestations are pre-requisites of submitting additional measurements for a given category. | ||
Similarly, `util/benchmarks/additional-benchmarks-2017.json` contains benchmark data that is necessary for scoring but not included in the historical CSV file. Any additional benchmarks should be added to this file, followed by a re-generation of benchmarks data. | ||
## Testing | ||
@@ -74,1 +63,7 @@ | ||
``` | ||
## Licenses | ||
This project is in the public domain within the United States, and copyright and related rights in the work worldwide are waived through the [CC0 1.0 Universal public domain dedication](https://creativecommons.org/publicdomain/zero/1.0/). | ||
All contributions to this project will be released under the CC0 dedication. By submitting a pull request, you are agreeing to comply with this waiver of copyright interest. |
@@ -49,3 +49,2 @@ // Libraries | ||
/** | ||
@@ -55,7 +54,6 @@ * @return {Array<ClinicalCluster>} | ||
exports.getClinicalClusterData = function() { | ||
return JSON.parse( | ||
fs.readFileSync(path.join(__dirname, 'clinical-clusters', 'clinical-clusters.json'))); | ||
return JSON.parse( | ||
fs.readFileSync(path.join(__dirname, 'clinical-clusters', 'clinical-clusters.json'))); | ||
}; | ||
/** | ||
@@ -62,0 +60,0 @@ * @return {{}} - Object representation of the Clinical Cluster Schema |
{ | ||
"name": "qpp-measures-data", | ||
"version": "0.0.41", | ||
"version": "1.0.0-alpha.1", | ||
"description": "Quality Payment Program Measures Data Repository", | ||
@@ -11,5 +11,7 @@ "repository": { | ||
"scripts": { | ||
"test": "node_modules/.bin/_mocha --colors", | ||
"build:measures": "scripts/build-measures", | ||
"build:benchmarks": "scripts/build-benchmarks", | ||
"test": "mocha --recursive", | ||
"build:measures": "scripts/measures/build-measures", | ||
"build:benchmarks": "scripts/benchmarks/build-benchmarks", | ||
"build:clinical-clusters": "scripts/clinical-clusters/build-clinical-clusters", | ||
"pretest": "eslint test util scripts index.js", | ||
"pre-commit": "tools/pre-commit.sh" | ||
@@ -25,2 +27,6 @@ }, | ||
"csv-parse": "^1.2.0", | ||
"eslint": "^4.2.0", | ||
"eslint-config-nava": "^1.0.0", | ||
"eslint-plugin-react": "^7.1.0", | ||
"eslint-plugin-standard": "^3.0.1", | ||
"lodash": "^4.16.4", | ||
@@ -27,0 +33,0 @@ "mocha": "^3.2.0", |
@@ -14,3 +14,3 @@ # qpp-measures-data | ||
This data (qpp-measures-data) reformats some of the data from the v1 measures | ||
API and adds some additional information (see `util/convert-qpp-to-measures.js` | ||
API and adds some additional information (see `util/measures/convert-qpp-to-measures.js` | ||
for the exact transformations). The transition to using qpp-measures-data as a | ||
@@ -41,8 +41,8 @@ source of truth for CMS is ongoing and this data may be subject to | ||
```javascript | ||
var qppMeasuresData = require('qpp-measures-data'); | ||
var measuresData = qppMeasuresData.getMeasuresData(); | ||
var measuresSchema = qppMeasuresData.getMeasuresSchema(); | ||
var benchmarksData = qppMeasuresData.getBenchmarksData(); | ||
var benchmark2017Data = benchmarksData[2017]; | ||
var benchmarksSchema = qppMeasuresData.getBenchmarksSchema(); | ||
const qppMeasuresData = require('qpp-measures-data'); | ||
const measuresData = qppMeasuresData.getMeasuresData(); | ||
const measuresSchema = qppMeasuresData.getMeasuresSchema(); | ||
const benchmarksData = qppMeasuresData.getBenchmarksData(); | ||
const benchmark2017Data = benchmarksData[2017]; | ||
const benchmarksSchema = qppMeasuresData.getBenchmarksSchema(); | ||
``` | ||
@@ -49,0 +49,0 @@ |
@@ -35,6 +35,6 @@ /** | ||
xml | ||
.replace(/(<\/)?substitutes(>)/g,'$1substitute$2') | ||
.replace(/(<\/)?measureSets(>)/g,'$1measureSet$2') | ||
.replace(/(<\/)?submissionMethods(>)/g,'$1submissionMethod$2') | ||
.replace(/(<\/)?[0-9]{1,}(>)/g,'$1measure$2') | ||
.replace(/(<\/)?substitutes(>)/g, '$1substitute$2') | ||
.replace(/(<\/)?measureSets(>)/g, '$1measureSet$2') | ||
.replace(/(<\/)?submissionMethods(>)/g, '$1submissionMethod$2') | ||
.replace(/(<\/)?[0-9]{1,}(>)/g, '$1measure$2') | ||
); | ||
@@ -46,10 +46,10 @@ } | ||
process.stdin.on('readable', function() { | ||
var chunk = this.read(); | ||
if (chunk !== null) { | ||
json += chunk; | ||
} | ||
var chunk = this.read(); | ||
if (chunk !== null) { | ||
json += chunk; | ||
} | ||
}); | ||
process.stdin.on('end', function() { | ||
convertToXml(json); | ||
convertToXml(json); | ||
}); |
@@ -29,4 +29,3 @@ /** | ||
console.log('Valid!'); | ||
} | ||
else { | ||
} else { | ||
console.log('Invalid: ' + ajv.errorsText(ajv.errors)); | ||
@@ -52,3 +51,1 @@ } | ||
} | ||
// Libraries | ||
var chai = require('chai'); | ||
var chai = require('chai'); | ||
var assert = chai.assert; | ||
// functions being tested | ||
var main = require('./../../index'); | ||
var getBenchmarksData = main.getBenchmarksData; | ||
var getBenchmarksData = main.getBenchmarksData; | ||
var getBenchmarksSchema = main.getBenchmarksSchema; | ||
@@ -19,3 +19,3 @@ | ||
it('should return undefined if benchmarks do not exist for that performance year', function(){ | ||
it('should return undefined if benchmarks do not exist for that performance year', function() { | ||
assert.isUndefined(getBenchmarksData()[2016]); | ||
@@ -22,0 +22,0 @@ }); |
@@ -1,2 +0,2 @@ | ||
var chai = require('chai'); | ||
var chai = require('chai'); | ||
var assert = chai.assert; | ||
@@ -6,38 +6,35 @@ var main = require('./../../index'); | ||
describe('benchmarks getter functions', () => { | ||
it('should load clinical cluster data', () => { | ||
var data = main.getClinicalClusterData(); | ||
assert.isArray(data); | ||
assert.isTrue(data.length > 0); | ||
}); | ||
it('should load clinical cluster data', () => { | ||
var data = main.getClinicalClusterData(); | ||
assert.isArray(data); | ||
assert.isTrue(data.length > 0); | ||
}); | ||
it('should load clinical cluster schema', () => { | ||
var schema = main.getClinicalClusterSchema(); | ||
assert.isObject(schema); | ||
}); | ||
it('should load clinical cluster schema', () => { | ||
var schema = main.getClinicalClusterSchema(); | ||
assert.isObject(schema); | ||
}); | ||
it('should not have registry 130, but claims', () => { | ||
var data = main.getClinicalClusterData(); | ||
var clusters = data.filter(c => c.measureId === '130' && c.submissionMethod === 'registry'); | ||
assert.isArray(clusters); | ||
assert.equal(0, clusters.length); | ||
clusters = data.filter(c => c.measureId === '130' && c.submissionMethod === 'claims'); | ||
assert.isArray(clusters); | ||
assert.equal(1, clusters.length); | ||
}); | ||
it('should not have registry 130, but claims', () => { | ||
var data = main.getClinicalClusterData(); | ||
var clusters = data.filter(c => c.measureId === '130' && c.submissionMethod === 'registry'); | ||
assert.isArray(clusters); | ||
assert.equal(0, clusters.length); | ||
clusters = data.filter(c => c.measureId === '130' && c.submissionMethod === 'claims'); | ||
assert.isArray(clusters); | ||
assert.equal(1, clusters.length); | ||
}) | ||
it('registry 051 and 052 should only have 130 in their clinicalCluster for registry', () => { | ||
var data = main.getClinicalClusterData(); | ||
var clusters = data.filter(c => c.measureId === '051' && c.submissionMethod === 'registry'); | ||
assert.equal(1, clusters.length); | ||
var cluster051 = clusters[0]; | ||
assert.deepEqual(['130'], cluster051.clinicalClusters[0].measureIds); | ||
it('registry 051 and 052 should only have 130 in their clinicalCluster for registry', () => { | ||
var data = main.getClinicalClusterData(); | ||
var clusters = data.filter(c => c.measureId === '051' && c.submissionMethod === 'registry'); | ||
assert.equal(1, clusters.length); | ||
var cluster051 = clusters[0]; | ||
assert.deepEqual(['130'], cluster051.clinicalClusters[0].measureIds); | ||
clusters = data.filter(c => c.measureId === '052' && c.submissionMethod === 'registry'); | ||
assert.equal(1, clusters.length); | ||
var cluster052 = clusters[0]; | ||
assert.deepEqual(['130'], cluster052.clinicalClusters[0].measureIds); | ||
}) | ||
clusters = data.filter(c => c.measureId === '052' && c.submissionMethod === 'registry'); | ||
assert.equal(1, clusters.length); | ||
var cluster052 = clusters[0]; | ||
assert.deepEqual(['130'], cluster052.clinicalClusters[0].measureIds); | ||
}); | ||
}); |
@@ -1,11 +0,11 @@ | ||
var chai = require('chai'); | ||
var assert = chai.assert; | ||
var _ = require('lodash'); | ||
const chai = require('chai'); | ||
const assert = chai.assert; | ||
const _ = require('lodash'); | ||
var mipsDataFormat = require('../../index.js'); | ||
var measuresData = mipsDataFormat.getMeasuresData(); | ||
var actualAciRelation = require('../../util/aci-measure-relations.json'); | ||
const mipsDataFormat = require('../../index.js'); | ||
const measuresData = mipsDataFormat.getMeasuresData(); | ||
const actualAciRelation = require('../../util/measures/aci-measure-relations.json'); | ||
describe('measures data json', function() { | ||
var measureIds = _.map(measuresData, 'measureId'); | ||
const measureIds = _.map(measuresData, 'measureId'); | ||
@@ -17,15 +17,16 @@ it('should not have any duplicate measureIds', function() { | ||
describe('pre-aci attestations', function() { | ||
var measureIdsSet = new Set(measureIds); | ||
var requiredAttestationIdsSet = new Set(['ACI_INFBLO_1', 'ACI_ONCDIR_1', 'ACI_ONCACB_1', 'ACI_IACEHRT_1']); | ||
const measureIdsSet = new Set(measureIds); | ||
const requiredAttestationIdsSet = new Set(['ACI_INFBLO_1', 'ACI_ONCDIR_1', 'ACI_ONCACB_1', 'ACI_IACEHRT_1']); | ||
it('includes all the pre-aci attestations', function() { | ||
var intersection = new Set([...measureIdsSet] | ||
const intersection = new Set([...measureIdsSet] | ||
.filter(x => requiredAttestationIdsSet.has(x))); | ||
assert.equal(intersection.size, requiredAttestationIdsSet.size); | ||
}); | ||
it('does not have substitutes', () => { | ||
requiredAttestationIdsSet.forEach(measureId => { | ||
var measure = measuresData.find(m => m.measureId == 'ACI_INFBLO_1'); | ||
const measure = measuresData.find(m => m.measureId === 'ACI_INFBLO_1'); | ||
assert.isTrue(_.isEmpty(measure.substitutes)); | ||
}) | ||
}); | ||
}); | ||
@@ -35,17 +36,18 @@ }); | ||
describe('ACI measures have proper substitutions', () => { | ||
it('ACI_PHCDRR_1 should be in performanceBonus reporting category', () => { | ||
var measure = measuresData.find(m => m.measureId == 'ACI_PHCDRR_1'); | ||
const measure = measuresData.find(m => m.measureId === 'ACI_PHCDRR_1'); | ||
assert.equal(measure.reportingCategory, 'performanceBonus'); | ||
}); | ||
it('ACI_TRANS_PHCDRR_2 should contain correct substitutes', () => { | ||
var measure = measuresData.find(m => m.measureId == 'ACI_TRANS_PHCDRR_2'); | ||
const measure = measuresData.find(m => m.measureId === 'ACI_TRANS_PHCDRR_2'); | ||
assert.deepEqual(measure.substitutes, ['ACI_PHCDRR_2']); | ||
}); | ||
it('dose contain proper metadata on all measures', () => { | ||
var generated = {}; | ||
it('contains proper metadata on all measures', () => { | ||
const generated = {}; | ||
measuresData | ||
.filter(m => m.category === 'aci') | ||
.forEach(m => { | ||
generated[m.measureId] = {reportingCategory: m.reportingCategory, substitutes: m.substitutes}; | ||
.forEach(m => { | ||
generated[m.measureId] = {reportingCategory: m.reportingCategory, substitutes: m.substitutes}; | ||
}); | ||
@@ -57,6 +59,6 @@ assert.deepEqual(generated, actualAciRelation); | ||
describe('quality measures', function() { | ||
it('includes all quality measures with mutli-performance strata', function() { | ||
var multiPerformanceIds = new Set(['007', '046', '122', '238', '348', '391', '392', '394', '398']); | ||
var qualityMeasureIds = _.map(_.filter(measuresData, {category: 'quality'}), 'measureId'); | ||
var intersection = new Set([...qualityMeasureIds].filter(x => multiPerformanceIds.has(x))); | ||
it('includes all quality measures with multi-performance strata', function() { | ||
const multiPerformanceIds = new Set(['007', '046', '122', '238', '348', '391', '392', '394', '398']); | ||
const qualityMeasureIds = _.map(_.filter(measuresData, {category: 'quality'}), 'measureId'); | ||
const intersection = new Set([...qualityMeasureIds].filter(x => multiPerformanceIds.has(x))); | ||
@@ -66,7 +68,12 @@ assert.equal(intersection.size, multiPerformanceIds.size); | ||
describe('CAHPS measures', function() { | ||
const cahpsMeasures = measuresData.filter(function(measure) { | ||
return measure.measureId.match(/CAHPS_\d+/); | ||
it('properly handles the exclusion of certain submission methods', () => { | ||
const shouldNotAcceptCmsWebInterface = measuresData.filter( | ||
measure => ['001', '117'].includes(measure.measureId) | ||
); | ||
shouldNotAcceptCmsWebInterface.forEach(measure => { | ||
assert.isFalse(measure.submissionMethods.includes('cmsWebInterface')); | ||
}); | ||
}); | ||
describe('CAHPS measures', function() { | ||
it('contains 12 correct CAHPS measures', function() { | ||
@@ -90,3 +97,3 @@ const cahpsMeasures = measuresData.filter(measure => measure.measureId.match(/CAHPS_\d+/)); | ||
'CAHPS for MIPS SSM: Courteous and Helpful Office Staff': '0005' | ||
} | ||
}; | ||
assert.equal(cahpsMeasures.length, 12); | ||
@@ -93,0 +100,0 @@ cahpsMeasures.forEach(cahpsMeasure => { |
@@ -6,5 +6,4 @@ const chai = require('chai'); | ||
const testFilesFolder = 'test/examples/quality/'; | ||
const testFilesFolder = 'test/measures/examples/quality/'; | ||
const qualityMeasureExampleFilenames = fs.readdirSync(testFilesFolder); | ||
const numExamples = qualityMeasureExampleFilenames.length; | ||
@@ -18,2 +17,3 @@ describe('measures schema validates json', function() { | ||
exec(command, function(error, stdout, stderr) { | ||
if (error) console.log(error.stack); | ||
capturedStdout = stdout; | ||
@@ -35,5 +35,6 @@ done(); | ||
before(function(done) { | ||
var command = 'cat ' + testFilesFolder + qualityMeasureExampleFilename + | ||
var command = 'cat ' + testFilesFolder + qualityMeasureExampleFilename + | ||
' | node scripts/validate-data.js measures'; | ||
exec(command, function(error, stdout, stderr) { | ||
if (error) console.log(error.stack); | ||
capturedStdoutExamples = stdout; | ||
@@ -40,0 +41,0 @@ done(); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1578139
27076
11
15