quality-measure-engine 2.2.0 → 2.3.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.
@@ -1,4 +1,5 @@
1
1
  {
2
+
2
3
  "id": "8A4D92B2-3887-5DF3-0139-0D01C6626E46",
3
4
  "nqf_id": "0142",
4
5
  "hqmf_id": "8A4D92B2-3887-5DF3-0139-0D01C6626E46",
@@ -1,4 +1,5 @@
1
1
  {
2
+
2
3
  "id": "8A4D92B2-3887-5DF3-0139-0C4E41594C98",
3
4
  "nqf_id": "0495",
4
5
  "hqmf_id": "8A4D92B2-3887-5DF3-0139-0C4E41594C98",
@@ -1,4 +1,5 @@
1
1
  {
2
+
2
3
  "id": "8A4D92B2-3887-5DF3-0139-0C4E41594C98",
3
4
  "nqf_id": "0495",
4
5
  "hqmf_id": "8A4D92B2-3887-5DF3-0139-0C4E41594C98",
@@ -1,4 +1,5 @@
1
1
  {
2
+
2
3
  "id": "0043",
3
4
  "name": "Pneumonia Vaccination Status for Older Adults",
4
5
  "description": "Patients more than 65 years old who received a pneumococcal vaccine.",
data/test/test_helper.rb CHANGED
@@ -9,6 +9,22 @@ Mongoid.configure do |config|
9
9
  end
10
10
 
11
11
  class MiniTest::Unit::TestCase
12
+
13
+ def load_system_js
14
+ Mongoid.default_session['system.js'].drop
15
+ Dir.glob(File.join(File.dirname(__FILE__), 'fixtures', "library_functions", '*.js')).each do |json_fixture_file|
16
+ name = File.basename(json_fixture_file,".*")
17
+ fn = "function () {\n #{File.read(json_fixture_file)} \n }"
18
+ Mongoid.default_session['system.js'].find('_id' => name).upsert(
19
+ {
20
+ "_id" => name,
21
+ "value" => Moped::BSON::Code.new(fn)
22
+ }
23
+ )
24
+ end
25
+
26
+ end
27
+
12
28
  # Add more helper methods to be used by all tests here...
13
29
 
14
30
  def collection_fixtures(db, collection, *id_attributes)
@@ -6,6 +6,7 @@ class MapReduceBuilderTest < MiniTest::Unit::TestCase
6
6
  def setup
7
7
  raw_measure_json = File.read(File.join('test', 'fixtures', 'measures', 'measure_metadata.json'))
8
8
  @measure_json = JSON.parse(raw_measure_json)
9
+ load_system_js
9
10
  end
10
11
 
11
12
  def test_extracting_measure_metadata
@@ -4,10 +4,13 @@ class MapReduceExecutorTest < MiniTest::Unit::TestCase
4
4
  include QME::DatabaseAccess
5
5
 
6
6
  def setup
7
- importer = QME::Bundle::Importer.new
8
- importer.import(File.new('test/fixtures/bundles/just_measure_0002.zip'), true, nil)
9
7
 
8
+ get_db['query_cache'].drop()
9
+ get_db['patient_cache'].drop()
10
+ collection_fixtures(get_db(), 'measures')
10
11
  collection_fixtures(get_db(), 'records', '_id')
12
+ collection_fixtures(get_db(), 'bundles')
13
+ load_system_js
11
14
  end
12
15
 
13
16
  def test_map_records_into_measure_groups
@@ -4,10 +4,12 @@ class MapCalculationJobTest < MiniTest::Unit::TestCase
4
4
  include QME::DatabaseAccess
5
5
 
6
6
  def setup
7
- importer = QME::Bundle::Importer.new
8
- importer.import(File.new('test/fixtures/bundles/just_measure_0002.zip'), true, nil)
9
-
7
+ get_db['query_cache'].drop()
8
+ get_db['patient_cache'].drop()
9
+ collection_fixtures(get_db(), 'measures')
10
10
  collection_fixtures(get_db(), 'records', '_id')
11
+ collection_fixtures(get_db(), 'bundles')
12
+ load_system_js
11
13
 
12
14
  Delayed::Worker.delay_jobs = false
13
15
  end
@@ -1,14 +1,17 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class QualityMeasureTest < MiniTest::Unit::TestCase
4
+ include QME::DatabaseAccess
4
5
  def setup
5
- importer = QME::Bundle::Importer.new
6
- importer.import(File.new('test/fixtures/bundles/just_measure_0002.zip'), true,nil)
6
+
7
+ collection_fixtures(get_db(), 'measures')
8
+ collection_fixtures(get_db(), 'bundles')
9
+ load_system_js
7
10
  end
8
11
 
9
12
  def test_getting_all_measures
10
13
  all_measures = QME::QualityMeasure.all
11
- assert_equal 1, all_measures.size
14
+ assert_equal 5, all_measures.size
12
15
  assert all_measures["2E679CD2-3FEC-4A75-A75A-61403E5EFEE8.json"]
13
16
  end
14
17
  end
@@ -4,6 +4,8 @@ class QualityReportTest < MiniTest::Unit::TestCase
4
4
  include QME::DatabaseAccess
5
5
 
6
6
  def setup
7
+ load_system_js
8
+ collection_fixtures(get_db(), 'bundles')
7
9
  get_db()['query_cache'].drop()
8
10
  get_db()['patient_cache'].drop()
9
11
  get_db()['query_cache'].insert(
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.2.0
4
+ version: 2.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,10 +9,11 @@ authors:
9
9
  - Andy Gregorowicz
10
10
  - Rob Dingwell
11
11
  - Adam Goldstein
12
+ - Andre Quina
12
13
  autorequire:
13
14
  bindir: bin
14
15
  cert_chain: []
15
- date: 2012-12-19 00:00:00.000000000 Z
16
+ date: 2013-02-27 00:00:00.000000000 Z
16
17
  dependencies:
17
18
  - !ruby/object:Gem::Dependency
18
19
  name: moped
@@ -21,7 +22,7 @@ dependencies:
21
22
  requirements:
22
23
  - - ~>
23
24
  - !ruby/object:Gem::Version
24
- version: 1.2.7
25
+ version: 1.4.2
25
26
  type: :runtime
26
27
  prerelease: false
27
28
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +30,7 @@ dependencies:
29
30
  requirements:
30
31
  - - ~>
31
32
  - !ruby/object:Gem::Version
32
- version: 1.2.7
33
+ version: 1.4.2
33
34
  - !ruby/object:Gem::Dependency
34
35
  name: mongoid
35
36
  requirement: !ruby/object:Gem::Requirement
@@ -37,7 +38,7 @@ dependencies:
37
38
  requirements:
38
39
  - - ~>
39
40
  - !ruby/object:Gem::Version
40
- version: 3.0.9
41
+ version: '3.0'
41
42
  type: :runtime
42
43
  prerelease: false
43
44
  version_requirements: !ruby/object:Gem::Requirement
@@ -45,7 +46,7 @@ dependencies:
45
46
  requirements:
46
47
  - - ~>
47
48
  - !ruby/object:Gem::Version
48
- version: 3.0.9
49
+ version: '3.0'
49
50
  - !ruby/object:Gem::Dependency
50
51
  name: rubyzip
51
52
  requirement: !ruby/object:Gem::Requirement
@@ -172,24 +173,28 @@ files:
172
173
  - LICENSE.txt
173
174
  - README.md
174
175
  - Rakefile
175
- - lib/qme/bundle/bundle.rb
176
176
  - lib/qme/bundle/eh_measure_sheet.rb
177
177
  - lib/qme/bundle/eh_patient_importer.rb
178
- - lib/qme/bundle/importer.rb
179
178
  - lib/qme/database_access.rb
179
+ - lib/qme/map/cv_aggregator.rb
180
180
  - lib/qme/map/map_reduce_builder.rb
181
181
  - lib/qme/map/map_reduce_executor.rb
182
182
  - lib/qme/map/measure_calculation_job.rb
183
183
  - lib/qme/quality_measure.rb
184
184
  - lib/qme/quality_report.rb
185
185
  - lib/qme/railtie.rb
186
- - lib/qme/tasks/bundle.rake
187
186
  - lib/qme/version.rb
188
187
  - lib/quality-measure-engine.rb
189
188
  - quality-measure-engine.gemspec
189
+ - test/fixtures/bundles/bundle.json
190
190
  - test/fixtures/bundles/just_measure_0002.zip
191
+ - test/fixtures/bundles/measures_0003_0002.zip
191
192
  - test/fixtures/delayed_backend_mongoid_jobs/queued_job.json
192
193
  - test/fixtures/eh_patient_sheets/results_matrix_eh.xlsx
194
+ - test/fixtures/library_functions/hqmf_utils.js
195
+ - test/fixtures/library_functions/map_reduce_utils.js
196
+ - test/fixtures/library_functions/underscore_min.js
197
+ - test/fixtures/measures/0002.json
193
198
  - test/fixtures/measures/0142.json
194
199
  - test/fixtures/measures/0495a.json
195
200
  - test/fixtures/measures/0495b.json
@@ -233,9 +238,15 @@ specification_version: 3
233
238
  summary: This library can run JavaScript based clinical quality measures on a repository
234
239
  of patients stored in MongoDB
235
240
  test_files:
241
+ - test/fixtures/bundles/bundle.json
236
242
  - test/fixtures/bundles/just_measure_0002.zip
243
+ - test/fixtures/bundles/measures_0003_0002.zip
237
244
  - test/fixtures/delayed_backend_mongoid_jobs/queued_job.json
238
245
  - test/fixtures/eh_patient_sheets/results_matrix_eh.xlsx
246
+ - test/fixtures/library_functions/hqmf_utils.js
247
+ - test/fixtures/library_functions/map_reduce_utils.js
248
+ - test/fixtures/library_functions/underscore_min.js
249
+ - test/fixtures/measures/0002.json
239
250
  - test/fixtures/measures/0142.json
240
251
  - test/fixtures/measures/0495a.json
241
252
  - test/fixtures/measures/0495b.json
@@ -1,51 +0,0 @@
1
- module QME
2
- module Bundle
3
- # Delete a list of collections. By default, this function drops all of collections related to measures and patients.
4
- #
5
- # @param [Array] collection_names Optionally, an array of collection names to be dropped.
6
- def self.drop_collections(db, collection_names=[])
7
- collection_names = ["bundles", "records", "measures", "selected_measures", "patient_cache", "query_cache", "system.js"] if collection_names.empty?
8
- collection_names.each {|collection| db[collection].drop}
9
- end
10
-
11
- # Save a javascript function into Mongo's system.js collection for measure execution.
12
- #
13
- # @param [String] name The name by which the function will be referred.
14
- # @param [String] fn The body of the function being saved.
15
- def self.save_system_js_fn(db, name, fn)
16
- fn = "function () {\n #{fn} \n }"
17
- db['system.js'].find('_id' => name).upsert(
18
- {
19
- "_id" => name,
20
- "value" => Moped::BSON::Code.new(fn)
21
- }
22
- )
23
- end
24
-
25
- # A utility function for finding files in a bundle. Strip a file path of it's extension and just give the filename.
26
- #
27
- # @param [String] original A file path.
28
- # @param [String] extension A file extension.
29
- # @return The filename at the end of the original String path with the extension removed. e.g. "/boo/urns.html" -> "urns"
30
- def self.entry_key(original, extension)
31
- original.split('/').last.gsub(".#{extension}", '')
32
- end
33
-
34
- def self.unpack_bundle_contents(zip, type = nil)
35
- bundle_contents = { bundle: nil, measures: {}, patients: {}, extensions: {}, results: {} }
36
- Zip::ZipFile.open(zip.path) do |zipfile|
37
- zipfile.entries.each do |entry|
38
- bundle_contents[:bundle] = zipfile.read(entry.name) if entry.name.include? "bundle"
39
- if type.nil? || entry.name.match(Regexp.new("/#{type}/"))
40
- bundle_contents[:measures][Bundle.entry_key(entry.name, "json")] = zipfile.read(entry.name) if entry.name.match /^measures.*\.json$/
41
- bundle_contents[:patients][Bundle.entry_key(entry.name, "json")] = zipfile.read(entry.name) if entry.name.match /^patients.*\.json$/ # Only need to import one of the formats
42
- bundle_contents[:results][Bundle.entry_key(entry.name,"json")] = zipfile.read(entry.name) if entry.name.match /^results.*\.json/
43
- end
44
- bundle_contents[:extensions][Bundle.entry_key(entry.name,"js")] = zipfile.read(entry.name) if entry.name.match /^library_functions.*\.js/
45
-
46
- end
47
- end
48
- bundle_contents
49
- end
50
- end
51
- end
@@ -1,63 +0,0 @@
1
- module QME
2
- module Bundle
3
- class Importer
4
- include QME::DatabaseAccess
5
-
6
- # Create a new Importer.
7
- # @param [String] db_name the name of the database to use
8
- def initialize(db_name = nil)
9
- determine_connection_information(db_name)
10
- @db = get_db
11
- end
12
-
13
- # Import a quality bundle into the database. This includes metadata, measures, test patients, supporting JS libraries, and expected results.
14
- #
15
- # @param [File] zip The bundle zip file.
16
- # @param [String] Type of measures to import, either 'ep', 'eh' or nil for all
17
- # @param [Boolean] keep_existing If true, delete all current collections related to patients and measures.
18
- def import(zip, delete_existing, type=nil)
19
- Bundle.drop_collections(@db) if delete_existing
20
-
21
- # Unpack content from the bundle.
22
- bundle_contents = QME::Bundle.unpack_bundle_contents(zip, type)
23
-
24
- # Store all JS libraries.
25
- bundle_contents[:extensions].each do |key, contents|
26
- Bundle.save_system_js_fn(@db, key, contents)
27
- end
28
-
29
- # Store the bundle metadata.
30
- bundle_id = Moped::BSON::ObjectId.new()
31
- bundle = JSON.parse(bundle_contents[:bundle])
32
- bundle["_id"] = bundle_id
33
- @db['bundles'].insert(bundle)
34
-
35
- # Store all measures.
36
- bundle_contents[:measures].each do |key, contents|
37
- measure_id = Moped::BSON::ObjectId.new()
38
- measure = JSON.parse(contents, {:max_nesting => 100})
39
- measure['_id'] = measure_id
40
- measure['bundle'] = bundle_id
41
- @db['measures'].insert(measure)
42
- end
43
-
44
- # Store all patients.
45
- bundle_id = Moped::BSON::ObjectId(bundle_id.to_s)
46
- bundle_contents[:patients].each do |key, contents|
47
- patient = JSON.parse(contents, {:max_nesting => 100})
48
- patient['bundle'] = bundle_id
49
- Record.new(patient).save
50
- end
51
-
52
- # Store the expected results into the query and patient caches.
53
- bundle_contents[:results].each do |name, contents|
54
- collection = name == "by_patient" ? "patient_cache" : "query_cache"
55
- contents = JSON.parse(contents, {:max_nesting => 100})
56
- contents.each {|document| @db[collection].insert(document)}
57
- end
58
-
59
- bundle_contents
60
- end
61
- end
62
- end
63
- end
@@ -1,95 +0,0 @@
1
- require 'quality-measure-engine'
2
-
3
- db_name = ENV['DB_NAME'] || 'test'
4
-
5
- namespace :bundle do
6
- desc 'Import a quality bundle into the database.'
7
- task :import, [:bundle_path, :delete_existing, :type] => [:environment] do |task, args|
8
- raise "The path to the measures zip file must be specified" unless args.bundle_path
9
-
10
- bundle = File.open(args.bundle_path)
11
- importer = QME::Bundle::Importer.new(db_name)
12
- bundle_contents = importer.import(bundle, args.delete_existing == "true", args.type)
13
-
14
- puts "Successfully imported bundle at: #{args.bundle_path}"
15
- puts "\t Imported into environment: #{Rails.env.upcase}" if defined? Rails
16
- puts "\t Loaded #{args.type || "all"} measures"
17
- puts "\t Measures Loaded: #{bundle_contents[:measures].count}"
18
- puts "\t Test Patients Loaded: #{bundle_contents[:patients].count}"
19
- puts "\t Extensions Loaded: #{bundle_contents[:extensions].count}"
20
- end
21
-
22
- # this task is most likely temporary. Once Bonnie can handle both EP and EH measures together, this would no longer be required.
23
- desc 'Merge two bundles into one.'
24
- task :merge, [:bundle_one,:bundle_two] do |t, args|
25
- raise "Two bundle zip file paths to be merged must be specified" unless args.bundle_one && args.bundle_two
26
-
27
- tmpdir = Dir.mktmpdir
28
- ['measures','patients','library_functions','results', 'sources'].each do |dir|
29
-
30
- FileUtils.mkdir_p(File.join(tmpdir, 'output', dir))
31
-
32
- end
33
-
34
- begin
35
-
36
- ({'one'=>args.bundle_one,'two'=>args.bundle_two}).each do |key, source|
37
- Zip::ZipFile.open(source) do |zip_file|
38
- zip_file.each do |f|
39
- f_path=File.join(tmpdir, key, f.name)
40
- FileUtils.mkdir_p(File.dirname(f_path))
41
- zip_file.extract(f, f_path) unless File.exist?(f_path)
42
- end
43
- end
44
- end
45
-
46
-
47
- ['measures','patients','library_functions', 'sources'].each do |dir|
48
- ['one','two'].each do |key|
49
- FileUtils.mv(Dir.glob(File.join(tmpdir,key,dir,'*')), File.join(tmpdir,'output',dir))
50
- end
51
- end
52
-
53
- Dir.glob(File.join(tmpdir,'one','results','*.json')).each do |result_path_one|
54
- json_one = JSON.parse(File.new(result_path_one).read)
55
- result_filename = Pathname.new(result_path_one).basename.to_s
56
- json_two = JSON.parse(File.new(File.join(tmpdir,'two','results',result_filename)).read)
57
- File.open(File.join(tmpdir,'output','results',result_filename), 'w') {|f| f.write(JSON.pretty_generate(json_one + json_two)) }
58
- end
59
-
60
- json_one = JSON.parse(File.new(File.join(tmpdir,'one','bundle.json')).read)
61
- json_two = JSON.parse(File.new(File.join(tmpdir,'two','bundle.json')).read)
62
- json_out = {}
63
-
64
- ['title','effective_date','version','license','exported'].each do |key|
65
- json_out[key] = json_one[key]
66
- end
67
-
68
- ['measures','patients','extensions'].each do |key|
69
- json_out[key] = (json_one[key] + json_two[key]).uniq
70
- end
71
-
72
- version = json_out['version']
73
-
74
- File.open(File.join(tmpdir,'output','bundle.json'), 'w') {|f| f.write(JSON.pretty_generate(json_out)) }
75
- date_string = Time.now.strftime("%Y-%m-%d")
76
-
77
- out_zip = File.join('tmp','bundles',"bundle-merged-#{date_string}-#{version}.zip")
78
- FileUtils.remove_entry_secure out_zip if File.exists?(out_zip)
79
- Zip::ZipFile.open(out_zip, 'w') do |zipfile|
80
- path = File.join(tmpdir,'output')
81
- Dir[File.join(path,'**','**')].each do |file|
82
- zipfile.add(file.sub(path+'/',''),file)
83
- end
84
- end
85
-
86
- puts "wrote merged bundle to: #{out_zip}"
87
-
88
- ensure
89
- FileUtils.remove_entry_secure tmpdir
90
- end
91
-
92
-
93
- end
94
-
95
- end