Skip to content

Commit

Permalink
[QPPA-1607] Add 2018 PI (Promoting Operability, formerly ACI) measures (
Browse files Browse the repository at this point in the history
#124)

This PR:

- adds the 2018 PI file provided by CMS; it's the same as the 2017 ACI json but with ACI renamed to PI and a few content tweaks. 
- adds an simple merge script to combine any number of staging json files into one final measures-data.json (right now it just combines quality and PI)
- updates the build script to use the merge script

Tests: new 2018 scripts have relevant tests

Jira: https://jira.cms.gov/browse/QPPA-1607

Reviewer(s): @samskeller
  • Loading branch information
kalvinwang committed May 29, 2018
1 parent b8448e2 commit 0eae3e7
Show file tree
Hide file tree
Showing 19 changed files with 3,280 additions and 478 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -34,7 +34,7 @@ For example, `benchmarks/2017.json` contains the benchmarks for performance year

$YEAR refers to the performance year. For measures data, providing a $YEAR is optional. If omitted, it defaults to 2017.

Note that only quality measures data has been imported for 2018. Other measures are being added soon.
Note that only quality and PI (Promoting Interoperability, formerly ACI) measures data has been imported for 2018. IA measures are being added soon.

### Importing the qpp-measures-data module
Functions take a string version argument and return the appropriate YAML schema or JSON data.
Expand Down
744 changes: 744 additions & 0 deletions measures/2018/measures-data.json

Large diffs are not rendered by default.

636 changes: 636 additions & 0 deletions measures/2018/measures-data.xml

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions measures/2018/measures-schema.yaml
Expand Up @@ -9,12 +9,12 @@ definitions:
properties:
measureId:
type: string
description: For quality measures, the measureId is the same as the quality number. For an advancing care information (ACI) measure, the measureId is the measure identifier for the ACI measure, and for an improvement activity (IA) measure, the measureId is the measure identifier for the IA measure.
description: For quality measures, the measureId is the same as the quality number. For a Promoting Interoperability (PI, formerly ACI) measure, the measureId is the measure identifier for the PI measure, and for an improvement activity (IA) measure, the measureId is the measure identifier for the IA measure.
title: { type: string }
description: { type: string }
category:
description: QPP scoring category to which the measure belongs: Improvement Activities, Quality, Advancing Care Information, and Cost.
enum: [ia, quality, aci, cost]
description: QPP scoring category to which the measure belongs: Improvement Activities, Quality, Promoting Interoperability (formerly Advancing Care Information), and Cost.
enum: [ia, quality, pi, cost]
metricType:
description: Type of measurement that the measure requires in order to attest.
enum: [boolean, proportion, singlePerformanceRate, multiPerformanceRate, registrySinglePerformanceRate, registryMultiPerformanceRate, nonProportion, cahps, costScore]
Expand All @@ -30,13 +30,13 @@ definitions:
description: URL link for Measure Specification PDF to download by Submission Method.
items: { $ref: #/definitions/measureSpecification }
measureSets:
description: ACI measures can belong to the transition measure set. Quality measures can belong to multiple measure sets that represent different specialties.
description: PI measures can belong to the transition measure set. Quality measures can belong to multiple measure sets that represent different specialties.
type: array
items: { $ref: #/definitions/measureSets }
required: [measureId, title, description, category, metricType, firstPerformanceYear, lastPerformanceYear]
anyOf:
- { $ref: #/definitions/iaMeasure }
- { $ref: #/definitions/aciMeasure }
- { $ref: #/definitions/piMeasure }
- { $ref: #/definitions/qualityMeasure }
- { $ref: #/definitions/aggregateCostMeasure }

Expand All @@ -52,34 +52,34 @@ definitions:
description: IA category which the measure incentivizes.
oneOf: [{ $ref: #/definitions/subcategoryIds }]
cehrtEligible:
description: If true, attesting to the measure will qualify the provider for an ACI CEHRT bonus.
description: If true, attesting to the measure will qualify the provider for an PI CEHRT bonus.
type: boolean
default: false
required: [weight, subcategoryId, cehrtEligible]

aciMeasure:
piMeasure:
type: object
properties:
category: { enum: [aci] }
category: { enum: [pi] }
reportingCategory:
description: The reporting category of the ACI measure.
enum: [preAttestation, base, registryBonus, performanceBonus, cehrtBonus]
description: The reporting category of the PI measure.
enum: [attestation, base, registryBonus, performanceBonus, cehrtBonus]
weight:
description: Determines the performance score points granted for attesting to the measure.
enum: [0, 5, 10, 20]
objective:
description: ACI category which the measure incentivizes.
description: PI category which the measure incentivizes.
oneOf: [{ $ref: #/definitions/objectives }]
isRequired:
description: If true, attesting to the measure is required in order to receive a non-zero ACI score.
description: If true, attesting to the measure is required in order to receive a non-zero PI score.
type: boolean
default: false
isBonus:
description: If true, attesting to the measure will qualify the provider for ACI bonus points.
description: If true, attesting to the measure will qualify the provider for PI bonus points.
type: boolean
default: false
substitutes:
description: Identifiers of other ACI measure that can be used instead of the current meausre.
description: Identifiers of other PI measure that can be used instead of the current meausre.
oneOf: [{ $ref: #/definitions/arrayOfStringIdentifiers}]
required: [weight, objective, isRequired, isBonus, measureSets]

Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "qpp-measures-data",
"version": "1.1.0",
"version": "1.1.1",
"description": "Quality Payment Program Measures Data Repository",
"repository": {
"type": "git",
Expand Down
6 changes: 3 additions & 3 deletions scripts/measures/2018/import-quality-measures.js
Expand Up @@ -182,7 +182,7 @@ function getCheckedColumns(row, columnNumberToNameMap) {

// loop through all the strata in the strata csv and add them to the measure object
// (there exist multiple csv rows of strata for each multiPerformanceRate measure)
const addMultiPerformanceRateStrata = function(measures, strataRows) {
function addMultiPerformanceRateStrata(measures, strataRows) {
_.each(strataRows, row => {
if (!row[0]) {
return; // csv has a blank row, so skip it
Expand Down Expand Up @@ -226,11 +226,11 @@ const addMultiPerformanceRateStrata = function(measures, strataRows) {
* 2. We trim all data sourced from CSVs because people sometimes unintentionally
* include spaces or linebreaks
*/
const convertQualityStrataCsvsToMeasures = function(qualityCsvRows, strataCsvRows) {
function convertQualityStrataCsvsToMeasures(qualityCsvRows, strataCsvRows) {
const sourcedFields = QUALITY_CSV_CONFIG.sourced_fields;
const constantFields = QUALITY_CSV_CONFIG.constant_fields;

const measures = qualityCsvRows.map(function(row) {
const measures = qualityCsvRows.map((row) => {
const measure = {};
_.each(sourcedFields, (columnObject, measureKey) => {
if (typeof columnObject === 'number') {
Expand Down
24 changes: 24 additions & 0 deletions scripts/measures/2018/merge-measures-data.js
@@ -0,0 +1,24 @@
const fs = require('fs');
const path = require('path');

const outputPath = process.argv[4];

function mergeMeasures() {
const allJson = [];
// Iterate through each measures file provided as a command-line argument
// and add it to the allJson array as an array of measure (json) objects.
// The first command-line argument starts at position 2, last argument
// is the output path. everything in between is an input measures file
for (let i = 2; i < process.argv.length - 1; i++) {
const measureStagingPath = path.join(__dirname, process.argv[i]);
const measureJson = JSON.parse(fs.readFileSync(measureStagingPath, 'utf8'));
allJson.push(measureJson);
}

// Merge the nested-array-per-measures-file into a single array of measures
const combinedMeasures = [].concat(...allJson);
const combinedJson = JSON.stringify(combinedMeasures, null, 2);
fs.writeFileSync(path.join(__dirname, outputPath), combinedJson);
}

mergeMeasures();
21 changes: 16 additions & 5 deletions scripts/measures/build-measures
Expand Up @@ -8,21 +8,32 @@ currentPerformanceYear=2018
# 2. use the git history of any necessary import scripts
# 3. revert any changes to directory structures below.

# note these paths are relative to /scripts/measures/$currentPerformanceYear/
quality_csv='../../../util/measures/'$currentPerformanceYear'/quality-measures.csv'
quality_strata='../../../util/measures/'$currentPerformanceYear'/quality-strata.csv'
quality_measures='../../../staging/'$currentPerformanceYear'/measures-data-quality.json'
# final_measures='../../measures/'$currentPerformanceYear'/measures-data.json'
pi_json='../../../util/measures/'$currentPerformanceYear'/pi-measures.json'
pi_measures='../../../staging/'$currentPerformanceYear'/measures-data-pi.json'
final_measures='../../../measures/'$currentPerformanceYear'/measures-data.json'

# 0. Add quality measures to the staging measures-data-quality.json file:
# 0a. Add quality measures to the staging measures-data-quality.json file:
node scripts/measures/$currentPerformanceYear/import-quality-measures.js \
$quality_csv $quality_strata $quality_measures

# 0b. Add PI (formerly ACI) measures to the staging measures-data-pi.json file:
# (For now it's just copying over 2017's with ACI changed to PI, preAttestation
# changed to attestation, and a few content tweaks by CMS)
cat util/measures/$currentPerformanceYear/pi-measures.json > \
staging/$currentPerformanceYear/measures-data-pi.json

# TODO: Enrich `measures-data.json` file, run:
# node scripts/measures/enrich-measures-data.js \
# $staging_measures_with_qcdrs $final_measures
# For now, just copy the staging measures file over.
cat staging/$currentPerformanceYear/measures-data-quality.json > \
measures/$currentPerformanceYear/measures-data.json

# 1. Merge the array/jsonfile-per-measureType into a combined array of all measures
node scripts/measures/$currentPerformanceYear/merge-measures-data.js \
$quality_measures $pi_measures \
$final_measures

# 2. To regenerate the `measures-data.xml` file, run:
echo "generating measures-data.xml from measures-data.json"
Expand Down

0 comments on commit 0eae3e7

Please sign in to comment.