quality-measure-engine 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: