From 746f49d4a3284d3d373d1d8309d8260c7e68624a Mon Sep 17 00:00:00 2001 From: John Mazella Date: Wed, 29 Aug 2012 15:07:09 -0400 Subject: [PATCH 1/2] Fixing regex in measure loader --- lib/measures/importer.rb | 8 ++++---- lib/tasks/measures.rake | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/measures/importer.rb b/lib/measures/importer.rb index ffc19872a..fb5e79f5b 100644 --- a/lib/measures/importer.rb +++ b/lib/measures/importer.rb @@ -18,10 +18,10 @@ def import(zip) Zip::ZipFile.open(zip.path) do |zipfile| zipfile.entries.each do |entry| - next if entry.directory? - entries_by_type[:libraries][entry_key(entry.name,"js")] = zipfile.read(entry.name) if entry.name.match /libraries/ - entries_by_type[:json][entry_key(entry.name,"json")] = zipfile.read(entry.name) if entry.name.match /\/json\// - entries_by_type[:bundle] = zipfile.read(entry.name) if entry.name.match /bundle/ + next if entry.directory? + entries_by_type[:libraries][entry_key(entry.name,"js")] = zipfile.read(entry.name) if entry.name.match /libraries\// + entries_by_type[:json][entry_key(entry.name,"json")] = zipfile.read(entry.name) if entry.name.match /json\// + entries_by_type[:bundle] = zipfile.read(entry.name) if entry.name.match /bundle/ end end diff --git a/lib/tasks/measures.rake b/lib/tasks/measures.rake index 8354bec33..dfe08e94a 100644 --- a/lib/tasks/measures.rake +++ b/lib/tasks/measures.rake @@ -66,8 +66,7 @@ namespace :measures do puts "ERROR: Unable to find measures #{@measures_version} for installation" next end - puts "Installing measures from #{measures_file} to database" - + puts "Installing measures from #{measures_file} to database #{@loader.get_db.name}" # Clear out all current measure data @loader.get_db['bundles'].remove("name" => "Meaningful Use Stage 1 Clinical Quality Measures") From 74b1d2c5e81d39bc8951a1f02d449968816c7154 Mon Sep 17 00:00:00 2001 From: John Mazella Date: Thu, 30 Aug 2012 13:38:50 -0400 Subject: [PATCH 2/2] Adding QRDA CATIII utility --- lib/cypress/qrda_utility.rb | 50 + test/fixtures/qrda/QRDA_CATIII_RI_AUG.xml | 2707 +++++++++++++++++++++ test/unit/lib/qrda_utility_test.rb | 42 + 3 files changed, 2799 insertions(+) create mode 100644 lib/cypress/qrda_utility.rb create mode 100644 test/fixtures/qrda/QRDA_CATIII_RI_AUG.xml create mode 100644 test/unit/lib/qrda_utility_test.rb diff --git a/lib/cypress/qrda_utility.rb b/lib/cypress/qrda_utility.rb new file mode 100644 index 000000000..c6f9e2430 --- /dev/null +++ b/lib/cypress/qrda_utility.rb @@ -0,0 +1,50 @@ +module Cypress + class QrdaUtility + + + # Extract and return measure results from a PQRI document and add to the reported results + # for this test. + def self.extract_results(doc, id_map) + # the measure IDs in the report must be a subset of what the product is + # allowed to test (in the measure_map) + # reverse the hash of nqf#=>product-specific-measure-id + measure_map = id_map.invert if id_map + doc = (doc.kind_of? String )? Nokogiri::XML::Document.new(doc) : doc + + #the nodes we want will have a child "templateId" with root = 2.16.840.1.113883.10.20.27.3.1 + result_nodes = doc.xpath('/xmlns:ClinicalDocument/xmlns:component/xmlns:structuredBody/xmlns:component/xmlns:section/xmlns:entry/xmlns:organizer/xmlns:templateId[@root = "2.16.840.1.113883.10.20.27.3.1"]/parent::*') + results ||= {} + result_nodes.each do |result_node| + key = result_node.at_xpath('xmlns:reference/xmlns:externalDocument/xmlns:id[@root = "2.16.840.1.113883.3.560.1"]')['extension'] + key = measure_map[key] if id_map + + numerator = get_measure_attr(result_node,'NUMER') + denominator = get_measure_attr(result_node,'DENOM') + initial_population = get_measure_attr(result_node,'IPP') + measure_population = get_measure_attr(result_node,'MSRPOPL') + numerator_exclusions = get_measure_attr(result_node,'NUMEX') + denominator_exclusions = get_measure_attr(result_node,'DENEX') + denominator_exceptions = get_measure_attr(result_node,'EXCEP') + + results[key] = {'measure_population' => measure_population, 'initial_population' => initial_population, \ + 'numerator' => numerator , 'numerator_exclusions' => numerator_exclusions, \ + 'denominator' => denominator, 'denominator_exclusions' => denominator_exclusions, 'denominator_exceptions' => denominator_exceptions \ + } if key + end + + return results + end + + private + def self.get_measure_attr(node, name) + xpath = 'xmlns:component/xmlns:observation/xmlns:value[@code = "'+ name +'"]/following::xmlns:entryRelationship/xmlns:observation/xmlns:value' + result = node.at_xpath(xpath) + if !result.nil? + return result['value'].to_i + else + return '-' + end + end + + end +end \ No newline at end of file diff --git a/test/fixtures/qrda/QRDA_CATIII_RI_AUG.xml b/test/fixtures/qrda/QRDA_CATIII_RI_AUG.xml new file mode 100644 index 000000000..d75e3709c --- /dev/null +++ b/test/fixtures/qrda/QRDA_CATIII_RI_AUG.xml @@ -0,0 +1,2707 @@ + + + + + + + + + + + + + + QRDA Calculated Summary Report + + + + + + + + + + + + + + + + + + + + + + + + Good Health Hospital + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + Reporting Parameters + + + Reporting period: 01 January 2012 - 31 March 2012 + First encounter: 05 January 2012 + Last encounter: 24 March 2012 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ + + + + + + QRDA Category III Measure Section + + + + + + + + + + + + + + + + + + + + + + + +
eMeasure TitleVersion neutral identifiereMeasure Version NumberNQF eMeasure NumbereMeasure Identifier (MAT)Version specific identifier
Anticoagulation Therapy for Atrial Fibrillation/Flutter03876d69-085b-415c-ae9d-9924171040c210436718a4d92b2-36af-5758-0136-ea8c43244986
+ Member of Measure Set: Clinical Quality Measure + Set 2011-2012 - b6ac13e2-beb8-4e4f-94ed-fcc397406cd8 + + Performance Rate: 83% (Predicted = 62%) + Reporting Rate: 84% + Initial Patient Population: + 1000 + Male: 400 + Female: 600 + Not Hispanic or + Latino: 350 + Hispanic or Latino: + 650 + Black: 300 + White: 350 + Asian: 350 + Payer - Medicare: + 250 + Payer - Medicaid: + 550 + Zipcode 92543: + 15 + + + Denominator: 500 + Male: 200 + Female: 300 + Not Hispanic or + Latino: 175 + Hispanic or Latino: + 325 + Black: 150 + White: 175 + Asian: 175 + Payer - Medicare: + 125 + Payer - Medicaid: + 275 + Zipcode 92543: + 15 + + + Numerator: 400 (predicted=300) + Male: 100 + Female: 300 + Not Hispanic or + Latino: 140 + Hispanic or Latino: + 260 + Black: 120 + White: 140 + Asian: 140 + Payer - Medicare: + 100 + Payer - Medicaid: + 220 + Zipcode 92543: + 6 + + + Denominator Exclusions: 20 + Male: 8 + Female: 12 + Not Hispanic or + Latino: 7 + Hispanic or Latino: + 13 + Black: 6 + White: 7 + Asian: 7 + Payer - Medicare: + 5 + Payer - Medicaid: + 11 + Zipcode 92543: + 0 + + + + + + + + + + + + + + + + + + + + + + + + + +
eMeasure TitleVersion neutral identifiereMeasure Version NumberNQF eMeasure NumbereMeasure Identifier (MAT)Version specific identifier
Median Time from ED Arrival to ED Departure for Discharged + ED Patients3fd13096-2c8f-40b5-9297-b714e8de913310496328a4d92b2-37d1-f95b-0137-dd4b0eb62de6
+ + Initial Patient Population: + 1000 + Reporting Stratum 1: + 200 + Reporting Stratum 2: + 250 + Reporting Stratum 3: + 250 + Reporting Stratum 4: + 150 + Reporting Stratum 5: + 150 + Male: 400 + Female: 600 + Not Hispanic or + Latino: 350 + Hispanic or Latino: + 650 + Black: 300 + White: 350 + Asian: 350 + Payer - Medicare: + 250 + Payer - Medicaid: + 550 + Zipcode 92543: + 15 + + + Measure Population: 500 + Reporting Stratum 1: + 150 + Reporting Stratum 2: + 150 + Reporting Stratum 3: + 100 + Reporting Stratum 4: + 50 + Reporting Stratum 5: + 50 + Male: 200 + Female: 300 + Not Hispanic or + Latino: 350 + Hispanic or Latino: + 150 + Black: 300 + White: 100 + Asian: 100 + Payer - Medicare: + 250 + Payer - Medicaid: + 250 + Zipcode 92543: + 1 + Median Admit Decision Time to ED + Departure Time for Admitted Patients: 55 min (Predicted = 60 min) + + + +
+ + + + + + + + + + + + + + + + + + + Anticoagulation Therapy for Atrial + Fibrillation/Flutter + + + + + + + + + + + + + + + Clinical Quality Measure Set 2011-2012 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 92543 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 92543 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 92543 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 92543 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Median Admit Decision Time to ED Departure Time for + Admitted Patients + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Stratum + + + + + + + + + + + + + + + + + + + + + + + + + + Stratum + + + + + + + + + + + + + + + + + + + + + + + + + + Stratum + + + + + + + + + + + + + + + + + + + + + + + + + + Stratum + + + + + + + + + + + + + + + + + + + + + + + + + + Stratum + + + + + + + + + + + + + + + + + + + + + + + + + + + + 92543 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Time Difference + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Stratum + + + + + + + + + + + + + + + + + + + + + + + + + + Stratum + + + + + + + + + + + + + + + + + + + + + + + + + + Stratum + + + + + + + + + + + + + + + + + + + + + + + + + + Stratum + + + + + + + + + + + + + + + + + + + + + + + + + + Stratum + + + + + + + + + + + + + + + + + + + + + + + + + + + + 92543 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
diff --git a/test/unit/lib/qrda_utility_test.rb b/test/unit/lib/qrda_utility_test.rb new file mode 100644 index 000000000..c8c2c6e8c --- /dev/null +++ b/test/unit/lib/qrda_utility_test.rb @@ -0,0 +1,42 @@ +require 'test_helper' +require 'fileutils' + +class QRDATest < ActiveSupport::TestCase + + + test "Should import a QRDA file" do + xml_file = File.new(File.join(Rails.root, 'test/fixtures/qrda/QRDA_CATIII_RI_AUG.xml')) + doc = Nokogiri::XML(xml_file) + results = Cypress::QrdaUtility.extract_results(doc, nil) + measure1 = results['0436'] + measure2 = results['0496'] + + assert measure1['measure_population'] == '-' + assert measure1['initial_population'] == 1000 + assert measure1['numerator'] == 400 + assert measure1['numerator_exclusions'] == '-' + assert measure1['denominator'] == 500 + assert measure1['denominator_exclusions'] == 20 + assert measure1['denominator_exceptions'] == '-' + + assert measure2['measure_population'] == 500 + assert measure2['initial_population'] == 1000 + assert measure2['numerator'] == '-' + assert measure2['numerator_exclusions'] == '-' + assert measure2['denominator'] == '-' + assert measure2['denominator_exclusions'] == '-' + assert measure2['denominator_exceptions'] == '-' + + end + + + + # test "should validate QRDA " do + # xml_file = File.new(File.join(Rails.root, 'test/fixtures/pqri/pqri_2010_1.xml')) + # doc = Nokogiri::XML(xml_file) + # errors = Cypress::PqriUtility.validate(doc) + # assert errors.size == 0, "Should be 0 errors but there were #{errors}" + + # end + +end