quality-measure-engine 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,9 +11,10 @@ module QME
11
11
  # Utility class used to supply a binding to Erb
12
12
  class Context < OpenStruct
13
13
  # Create a new context
14
- # @param [Hash] vars a hash of parameter names (String) and values (Object). Each entry is added as an accessor of the new Context
14
+ # @param [Hash] vars a hash of parameter names (String) and values (Object). Each
15
+ # entry is added as an accessor of the new Context
15
16
  def initialize(db, vars)
16
- super(vars)
17
+ super(Context.add_defaults(vars))
17
18
  @db = db
18
19
  end
19
20
 
@@ -23,6 +24,17 @@ module QME
23
24
  binding
24
25
  end
25
26
 
27
+ # Add default parameter values if not specified
28
+ def self.add_defaults(vars)
29
+ if !vars.has_key?('enable_logging')
30
+ vars['enable_logging'] = false
31
+ end
32
+ if !vars.has_key?('enable_rationale')
33
+ vars['enable_rationale'] = false
34
+ end
35
+ vars
36
+ end
37
+
26
38
  # Inserts any library code into the measure JS. JS library code is loaded from
27
39
  # three locations: the js directory of the quality-measure-engine project, the
28
40
  # js sub-directory of the current directory (e.g. measures/js), and the bundles
@@ -7,7 +7,10 @@ module QME
7
7
  class Executor
8
8
 
9
9
  include DatabaseAccess
10
-
10
+ SUPPLEMENTAL_DATA_ELEMENTS = {QME::QualityReport::RACE => "$value.race.code",
11
+ QME::QualityReport::ETHNICITY => "$value.ethnicity.code",
12
+ QME::QualityReport::SEX => "$value.gender",
13
+ QME::QualityReport::PAYER => "$value.payer"}
11
14
  # Create a new Executor for a specific measure, effective date and patient population.
12
15
  # @param [String] measure_id the measure identifier
13
16
  # @param [String] sub_id the measure sub-identifier or null if the measure is single numerator
@@ -64,6 +67,44 @@ module QME
64
67
  pipeline
65
68
  end
66
69
 
70
+
71
+ #Calculate all of the supoplemental data elements
72
+ def calculate_supplemental_data_elements
73
+
74
+ match = {'value.measure_id' => @measure_id,
75
+ 'value.sub_id' => @sub_id,
76
+ 'value.effective_date' => @parameter_values['effective_date'],
77
+ 'value.test_id' => @parameter_values['test_id'],
78
+ 'value.manual_exclusion' => {'$in' => [nil, false]}}
79
+
80
+ keys = @measure_def["population_ids"].keys - [QME::QualityReport::OBSERVATION, "stratification"]
81
+ supplemental_data = Hash[*keys.map{|k| [k,{QME::QualityReport::RACE => {},
82
+ QME::QualityReport::ETHNICITY => {},
83
+ QME::QualityReport::SEX => {},
84
+ QME::QualityReport::PAYER => {}}]}.flatten]
85
+
86
+ keys.each do |pop_id|
87
+ _match = match.clone
88
+ _match["value.#{pop_id}"] = {"$gt" => 0}
89
+ SUPPLEMENTAL_DATA_ELEMENTS.each_pair do |supp_element,location|
90
+ group1 = {"$group" => { "_id" => { "id" => "$_id", "val" => location}}}
91
+ group2 = {"$group" => {"_id" => "$_id.val", "val" =>{"$sum" => 1} }}
92
+ pipeline = [{"$match" =>_match},group1,group2]
93
+ aggregate = get_db.command(:aggregate => 'patient_cache', :pipeline => pipeline)
94
+
95
+ v = {}
96
+ (aggregate["result"] || []).each do |entry|
97
+ code = entry["_id"].nil? ? "UNK" : entry["_id"]
98
+ v[code] = entry["val"]
99
+ end
100
+ supplemental_data[pop_id] ||= {}
101
+ supplemental_data[pop_id][supp_element] = v
102
+ end
103
+ end
104
+ supplemental_data
105
+ end
106
+
107
+
67
108
  # Examines the patient_cache collection and generates a total of all groups
68
109
  # for the measure. The totals are placed in a document in the query_cache
69
110
  # collection.
@@ -104,6 +145,7 @@ module QME
104
145
  result.reject! {|k, v| k == '_id'} # get rid of the group id the Mongo forced us to use
105
146
  # result['exclusions'] += get_db['patient_cache'].find(base_query.merge({'value.manual_exclusion'=>true})).count
106
147
  result.merge!(execution_time: (Time.now.to_i - @parameter_values['start_time'].to_i)) if @parameter_values['start_time']
148
+ result[:supplemental_data] = self.calculate_supplemental_data_elements
107
149
  get_db()["query_cache"].insert(result)
108
150
  get_db().command({:getLastError => 1}) # make sure last insert finished before we continue
109
151
  result
@@ -18,6 +18,12 @@ module QME
18
18
  ANTINUMERATOR = 'antinumerator'
19
19
  CONSIDERED = 'considered'
20
20
 
21
+ RACE = 'RACE'
22
+ ETHNICITY = 'ETHNICITY'
23
+ SEX ='SEX'
24
+ POSTAL_CODE = 'POSTAL_CODE'
25
+ PAYER = 'PAYER'
26
+
21
27
  # Gets rid of all calculated QualityReports by dropping the patient_cache
22
28
  # and query_cache collections
23
29
  def self.destroy_all
@@ -144,11 +150,14 @@ module QME
144
150
  filters.each {|key, value| value.sort_by! {|v| (v.is_a? Hash) ? "#{v}" : v} if value.is_a? Array} unless filters.nil?
145
151
  end
146
152
 
147
- def patient_result
153
+ def patient_result(patient_id = nil)
148
154
  cache = get_db()["patient_cache"]
149
155
  query = {'value.measure_id' => @measure_id, 'value.sub_id' => @sub_id,
150
156
  'value.effective_date' => @parameter_values['effective_date'],
151
157
  'value.test_id' => @parameter_values['test_id']}
158
+ if patient_id
159
+ query['value.medical_record_id'] = patient_id
160
+ end
152
161
  cache.find(query).first()
153
162
  end
154
163
 
data/lib/qme/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module QME
2
- VERSION = "2.3.0"
2
+ VERSION = "2.4.0"
3
3
  end
@@ -8,13 +8,14 @@ require 'rubyXL'
8
8
  require "qme/version"
9
9
  require 'qme/database_access'
10
10
  require 'qme/quality_measure'
11
+ require 'qme/quality_report'
11
12
 
12
13
  require 'qme/map/map_reduce_builder'
13
14
  require 'qme/map/map_reduce_executor'
14
15
  require 'qme/map/measure_calculation_job'
15
16
  require 'qme/map/cv_aggregator'
16
17
 
17
- require 'qme/quality_report'
18
+
18
19
 
19
20
  require 'qme/bundle/eh_measure_sheet'
20
21
  require 'qme/bundle/eh_patient_importer'
@@ -2,6 +2,9 @@
2
2
  "_id": "507ec2077042f9362c00001b",
3
3
  "birthdate": 946715400,
4
4
  "medical_record_number": "12345",
5
+ "ethnicity" : { "code" : "2186-5",
6
+ "name" : "Not Hispanic or Latino",
7
+ "codeSystem" : "CDC Race" },
5
8
  "conditions": [
6
9
  {
7
10
  "codes": {
@@ -2,6 +2,12 @@
2
2
  "_id": "507ec1407042f9362c000017",
3
3
  "birthdate": 946715400,
4
4
  "medical_record_number" : "1236",
5
+ "race" : { "code" : "1002-5",
6
+ "name" : "American Indian or Alaska Native",
7
+ "codeSystem" : "CDC Race" },
8
+ "ethnicity" : { "code" : "2186-5",
9
+ "name" : "Not Hispanic or Latino",
10
+ "codeSystem" : "CDC Race" },
5
11
  "conditions": [
6
12
  {
7
13
  "codes": {
@@ -35,5 +35,14 @@ class MapReduceBuilderTest < MiniTest::Unit::TestCase
35
35
  binding = context.get_binding
36
36
  assert_equal 10, eval("a",binding)
37
37
  assert_equal 20, eval("b",binding)
38
+ assert_equal false, eval("enable_logging",binding)
39
+ vars = {'enable_logging'=>true}
40
+ context = QME::MapReduce::Builder::Context.new(get_db(), vars)
41
+ binding = context.get_binding
42
+ assert_equal true, eval("enable_logging",binding)
43
+ vars = {'enable_logging'=>false}
44
+ context = QME::MapReduce::Builder::Context.new(get_db(), vars)
45
+ binding = context.get_binding
46
+ assert_equal false, eval("enable_logging",binding)
38
47
  end
39
48
  end
@@ -18,6 +18,7 @@ class MapReduceExecutorTest < MiniTest::Unit::TestCase
18
18
  'effective_date' => Time.gm(2011, 1, 15).to_i)
19
19
 
20
20
  executor.map_records_into_measure_groups
21
+
21
22
 
22
23
  assert_equal 4, get_db['patient_cache'].find().count
23
24
  assert_equal 3, get_db['patient_cache'].find("value.#{QME::QualityReport::POPULATION}" => 1).count
@@ -26,6 +27,44 @@ class MapReduceExecutorTest < MiniTest::Unit::TestCase
26
27
  assert_equal 1, get_db['patient_cache'].find("value.#{QME::QualityReport::NUMERATOR}" => 1).count
27
28
  end
28
29
 
30
+
31
+ def test_calculate_supplemental_data_elements
32
+ executor = QME::MapReduce::Executor.new("2E679CD2-3FEC-4A75-A75A-61403E5EFEE8", nil,
33
+ 'effective_date' => Time.gm(2011, 1, 15).to_i)
34
+
35
+ executor.map_records_into_measure_groups
36
+ executor.count_records_in_measure_groups
37
+ assert_equal 1, get_db['query_cache'].find().count
38
+ doc = get_db['query_cache'].find().first
39
+ suppl = doc["supplemental_data"]
40
+ assert !suppl.empty?, "should contain supplemental data entries"
41
+ ipp = {QME::QualityReport::RACE =>{"UNK"=>2, "1002-5"=>1},
42
+ QME::QualityReport::ETHNICITY => {"UNK"=>1, "2186-5"=>2},
43
+ QME::QualityReport::PAYER => {"UNK"=>3},
44
+ QME::QualityReport::SEX => {"F"=>2,"M"=>1}
45
+ }
46
+
47
+ denom = {QME::QualityReport::RACE =>{"UNK"=>1, "1002-5"=>1},
48
+ QME::QualityReport::ETHNICITY => { "2186-5"=>2},
49
+ QME::QualityReport::PAYER => {"UNK"=>2},
50
+ QME::QualityReport::SEX => {"F"=>2}
51
+ }
52
+
53
+ numer = {QME::QualityReport::RACE =>{"UNK"=>1},
54
+ QME::QualityReport::ETHNICITY => {"2186-5"=>1},
55
+ QME::QualityReport::PAYER => {"UNK"=>1},
56
+ QME::QualityReport::SEX => {"F"=>1}
57
+ }
58
+
59
+
60
+
61
+ assert_equal ipp, suppl[QME::QualityReport::POPULATION]
62
+ assert_equal denom, suppl[QME::QualityReport::DENOMINATOR]
63
+ assert_equal numer, suppl[QME::QualityReport::NUMERATOR]
64
+
65
+
66
+ end
67
+
29
68
  def test_count_records_in_measure_groups
30
69
  executor = QME::MapReduce::Executor.new("2E679CD2-3FEC-4A75-A75A-61403E5EFEE8", nil,
31
70
  'effective_date' => Time.gm(2011, 1, 15).to_i)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quality-measure-engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2013-02-27 00:00:00.000000000 Z
16
+ date: 2013-04-22 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: moped
@@ -232,7 +232,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
232
232
  version: '0'
233
233
  requirements: []
234
234
  rubyforge_project:
235
- rubygems_version: 1.8.24
235
+ rubygems_version: 1.8.25
236
236
  signing_key:
237
237
  specification_version: 3
238
238
  summary: This library can run JavaScript based clinical quality measures on a repository
@@ -264,4 +264,3 @@ test_files:
264
264
  - test/unit/qme/map/measure_calculation_job_test.rb
265
265
  - test/unit/qme/quality_measure_test.rb
266
266
  - test/unit/qme/quality_report_test.rb
267
- has_rdoc: