quality-measure-engine 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/Gemfile +9 -9
  2. data/README.md +39 -2
  3. data/Rakefile +25 -44
  4. data/js/map-reduce-utils.js +174 -0
  5. data/js/underscore-min.js +24 -0
  6. data/lib/qme/importer/code_system_helper.rb +26 -0
  7. data/lib/qme/importer/entry.rb +89 -0
  8. data/lib/qme/importer/generic_importer.rb +71 -0
  9. data/lib/qme/importer/hl7_helper.rb +27 -0
  10. data/lib/qme/importer/patient_importer.rb +150 -0
  11. data/lib/qme/importer/property_matcher.rb +103 -0
  12. data/lib/qme/importer/section_importer.rb +82 -0
  13. data/lib/qme/map/map_reduce_builder.rb +77 -147
  14. data/lib/qme/map/map_reduce_executor.rb +97 -13
  15. data/lib/qme/measure/database_loader.rb +90 -0
  16. data/lib/qme/measure/measure_loader.rb +141 -0
  17. data/lib/qme/mongo_helpers.rb +15 -0
  18. data/lib/qme/randomizer/patient_randomizer.rb +95 -0
  19. data/lib/qme_test.rb +13 -0
  20. data/lib/quality-measure-engine.rb +20 -4
  21. data/lib/tasks/measure.rake +76 -0
  22. data/lib/tasks/mongo.rake +74 -0
  23. data/lib/tasks/patient_random.rake +46 -0
  24. metadata +110 -156
  25. data/.gitignore +0 -6
  26. data/Gemfile.lock +0 -44
  27. data/fixtures/complex_measure.json +0 -36
  28. data/fixtures/result_example.json +0 -6
  29. data/lib/patches/v8.rb +0 -20
  30. data/lib/qme/query/json_document_builder.rb +0 -130
  31. data/lib/qme/query/json_query_executor.rb +0 -44
  32. data/measures/0032/0032_NQF_Cervical_Cancer_Screening.json +0 -171
  33. data/measures/0032/patients/denominator1.json +0 -10
  34. data/measures/0032/patients/denominator2.json +0 -10
  35. data/measures/0032/patients/numerator1.json +0 -11
  36. data/measures/0032/patients/population1.json +0 -9
  37. data/measures/0032/patients/population2.json +0 -11
  38. data/measures/0032/result/result.json +0 -6
  39. data/measures/0043/0043_NQF_PneumoniaVaccinationStatusForOlderAdults.json +0 -71
  40. data/measures/0043/patients/denominator.json +0 -11
  41. data/measures/0043/patients/numerator.json +0 -11
  42. data/measures/0043/patients/population.json +0 -10
  43. data/measures/0043/result/result.json +0 -6
  44. data/quality-measure-engine.gemspec +0 -97
  45. data/schema/result.json +0 -28
  46. data/schema/schema.json +0 -143
  47. data/spec/qme/map/map_reduce_builder_spec.rb +0 -64
  48. data/spec/qme/measures_spec.rb +0 -50
  49. data/spec/qme/query/json_document_builder_spec.rb +0 -56
  50. data/spec/schema_spec.rb +0 -21
  51. data/spec/spec_helper.rb +0 -7
  52. data/spec/validate_measures_spec.rb +0 -21
@@ -1,64 +0,0 @@
1
- MAP_FUNCTION = <<END_OF_MAP_FN
2
- function () {
3
- var value = {i: 0, d: 0, n: 0, e: 0};
4
- if (this.birthdate<=-764985600) {
5
- value.i++;
6
- if (this.measures["0043"].encounter>=1253318400) {
7
- value.d++;
8
- if (this.measures["0043"].vaccination==true) {
9
- value.n++;
10
- } else if (false) {
11
- value.e++;
12
- value.d--;
13
- }
14
- }
15
- }
16
- emit(null, value);
17
- };
18
- END_OF_MAP_FN
19
-
20
- describe QME::MapReduce::Builder do
21
-
22
- before do
23
- raw_measure_json = File.read('measures/0043/0043_NQF_PneumoniaVaccinationStatusForOlderAdults.json')
24
- @measure_json = JSON.parse(raw_measure_json)
25
- raw_measure_json = File.read('fixtures/complex_measure.json')
26
- @complex_measure_json = JSON.parse(raw_measure_json)
27
- end
28
-
29
- it 'should extract the measure metadata' do
30
- measure = QME::MapReduce::Builder.new(@measure_json, :effective_date=>Time.gm(2010, 9, 19).to_i)
31
- measure.id.should eql('0043')
32
- end
33
- it 'should extract three parameters for measure 0043 (one provided, two calculated)' do
34
- time = Time.gm(2010, 9, 19).to_i
35
-
36
- measure = QME::MapReduce::Builder.new(@measure_json, :effective_date=>time)
37
- measure.parameters.size.should eql(3)
38
- measure.parameters.should have_key(:effective_date)
39
- measure.parameters[:effective_date].should eql(time)
40
- end
41
- it 'should raise a RuntimeError if not passed all the parameters' do
42
- lambda { QME::MapReduce::Builder.new(@measure_json) }.should
43
- raise_error(RuntimeError, 'No value supplied for measure parameter: effective_date')
44
- end
45
- it 'should calculate the calculated dates correctly' do
46
- date = Time.gm(2010, 9, 19).to_i
47
- measure = QME::MapReduce::Builder.new(@measure_json, :effective_date=>date)
48
- measure.parameters[:earliest_encounter].should eql(date-QME::MapReduce::Builder::YEAR_IN_SECONDS)
49
- end
50
- it 'should produce valid JavaScript expressions for the query components' do
51
- date = Time.gm(2010, 9, 19).to_i
52
- builder = QME::MapReduce::Builder.new(@measure_json, :effective_date=>date)
53
- builder.numerator.should eql('(this.measures["0043"].vaccination==true)')
54
- builder.denominator.should eql('(this.measures["0043"].encounter>='+builder.parameters[:earliest_encounter].to_s+')')
55
- builder.population.should eql('(this.birthdate<='+builder.parameters[:earliest_birthdate].to_s+')')
56
- builder.exception.should eql('(false)')
57
- builder.map_function.should eql(MAP_FUNCTION)
58
- builder.reduce_function.should eql(QME::MapReduce::Builder::REDUCE_FUNCTION)
59
- end
60
- it 'should handle logical combinations' do
61
- builder = QME::MapReduce::Builder.new(@complex_measure_json, {})
62
- builder.population.should eql('((this.measures["0043"].age>17)&&(this.measures["0043"].age<75)&&((this.measures["0043"].sex=="male")||(this.measures["0043"].sex=="female")))')
63
- end
64
- end
@@ -1,50 +0,0 @@
1
- describe QME::MapReduce::Executor do
2
-
3
- before do
4
- db_host = nil
5
- if ENV['TEST_DB_HOST']
6
- db_host = ENV['TEST_DB_HOST']
7
- else
8
- db_host = 'localhost'
9
- end
10
- @db = Mongo::Connection.new(db_host, 27017).db('test')
11
- @measures = Dir.glob('measures/*')
12
- end
13
-
14
- it 'should produce the expected results for each measure' do
15
- print "\n"
16
- @measures.each do |dir|
17
- # load db with measure and sample patient records
18
- files = Dir.glob(File.join(dir,'*.json'))
19
- files.size.should eql(1)
20
- measure_file = files[0]
21
- patient_files = Dir.glob(File.join(dir, 'patients', '*.json'))
22
- measure = JSON.parse(File.read(measure_file))
23
- measure_id = measure['id']
24
- print "Validating measure #{measure_id}"
25
- @db.drop_collection('measures')
26
- @db.drop_collection('records')
27
- measure_collection = @db.create_collection('measures')
28
- record_collection = @db.create_collection('records')
29
- measure_collection.save(measure)
30
- patient_files.each do |patient_file|
31
- patient = JSON.parse(File.read(patient_file))
32
- record_collection.save(patient)
33
- end
34
-
35
- # load expected results
36
- result_file = File.join(dir, 'result', 'result.json')
37
- expected = JSON.parse(File.read(result_file))
38
-
39
- # evaulate measure using Map/Reduce and validate results
40
- executor = QME::MapReduce::Executor.new(@db)
41
- result = executor.measure_result(measure_id, :effective_date=>Time.gm(2010, 9, 19).to_i)
42
- result[:population].should eql(expected['initialPopulation'])
43
- result[:numerator].should eql(expected['numerator'])
44
- result[:denominator].should eql(expected['denominator'])
45
- result[:exceptions].should eql(expected['exclusions'])
46
- print " - done\n"
47
- end
48
- end
49
-
50
- end
@@ -1,56 +0,0 @@
1
- describe QME::Query::JSONDocumentBuilder do
2
-
3
- before do
4
- raw_measure_json = File.read('measures/0043/0043_NQF_PneumoniaVaccinationStatusForOlderAdults.json')
5
- @measure_json = JSON.parse(raw_measure_json)
6
- raw_measure_json = File.read('fixtures/complex_measure.json')
7
- @complex_measure_json = JSON.parse(raw_measure_json)
8
- end
9
-
10
- it 'should calculate dates for a measure' do
11
- jdb = QME::Query::JSONDocumentBuilder.new(@measure_json)
12
- jdb.parameters = {:effective_date => 1287685441}
13
- jdb.calculate_dates
14
- jdb.calculated_dates['earliest_birthdate'].should == -762154559
15
- end
16
-
17
- it 'should create a query for a simple measure' do
18
- jdb = QME::Query::JSONDocumentBuilder.new(@measure_json, {:effective_date => 1287685441})
19
- query_hash = jdb.create_query(@measure_json['denominator'])
20
- query_hash.size.should be 1
21
- query_hash['measures.0043.encounter'].should_not be_nil
22
- query_hash['measures.0043.encounter']['$gte'].should == 1256149441
23
- end
24
-
25
- it 'should properly transform a property name' do
26
- jdb = QME::Query::JSONDocumentBuilder.new(@measure_json, {:effective_date => 1287685441})
27
- jdb.transform_query_property('birthdate').should == 'birthdate'
28
- jdb.transform_query_property('foo').should == 'measures.0043.foo'
29
- end
30
-
31
- it 'should properly process a query leaf when it is an expression' do
32
- jdb = QME::Query::JSONDocumentBuilder.new(@measure_json, {:effective_date => 1287685441})
33
- args = {}
34
- jdb.process_query({"encounter" => {"_gte" => "@earliest_encounter"}}, args)
35
- args.size.should be 1
36
- args['measures.0043.encounter'].should_not be_nil
37
- args['measures.0043.encounter']['$gte'].should == 1256149441
38
- end
39
-
40
- it 'should properly process a query leaf when it is a value' do
41
- jdb = QME::Query::JSONDocumentBuilder.new(@measure_json, {:effective_date => 1287685441})
42
- args = {}
43
- jdb.process_query({"encounter" => 'splat'}, args)
44
- args.size.should be 1
45
- args['measures.0043.encounter'].should_not be_nil
46
- args['measures.0043.encounter'].should == 'splat'
47
- end
48
-
49
- it 'should create a query for a complex measure' do
50
- jdb = QME::Query::JSONDocumentBuilder.new(@complex_measure_json)
51
- query_hash = jdb.create_query(@complex_measure_json['population'])
52
- query_hash['measures.0043.age']['$gt'].should == 17
53
- query_hash['measures.0043.age']['$lt'].should == 75
54
- query_hash['$or'].should have(2).items
55
- end
56
- end
data/spec/schema_spec.rb DELETED
@@ -1,21 +0,0 @@
1
- require 'json'
2
-
3
- describe JSON, 'All JSON Schemas' do
4
- it 'should conform to JSON Schema' do
5
- schema = File.open('schema/schema.json', 'rb'){|f| JSON.parse(f.read)}
6
- Dir.glob('schema/*.json').each do |schema_file|
7
- if schema_file != 'schema/schema.json' # Don't check the schema itself
8
- data = File.open(schema_file, 'rb'){|f| JSON.parse(f.read)}
9
- JSON::Schema.validate(data, schema)
10
- end
11
- end
12
- end
13
- end
14
-
15
- describe JSON, 'Result Example' do
16
- it 'should conform to the schema defined' do
17
- schema = File.open('schema/result.json', 'rb'){|f| JSON.parse(f.read)}
18
- data = File.open('fixtures/result_example.json', 'rb'){|f| JSON.parse(f.read)}
19
- JSON::Schema.validate(data, schema)
20
- end
21
- end
data/spec/spec_helper.rb DELETED
@@ -1,7 +0,0 @@
1
- require 'bundler/setup'
2
-
3
- PROJECT_ROOT = File.dirname(__FILE__) + '/../'
4
-
5
- require PROJECT_ROOT + 'lib/quality-measure-engine'
6
-
7
- Bundler.require(:test)
@@ -1,21 +0,0 @@
1
- # Validate the measure specifications and patient samples
2
-
3
- require 'json'
4
-
5
- describe JSON, 'All measure specifications' do
6
- it 'should be valid JSON' do
7
- Dir.glob('measures/*/*.json').each do |measure_file|
8
- measure = File.read(measure_file)
9
- json = JSON.parse(measure)
10
- end
11
- end
12
- end
13
-
14
- describe JSON, 'All patient samples' do
15
- it 'should be valid JSON' do
16
- Dir.glob('measures/*/patients/*.json').each do |measure_file|
17
- measure = File.read(measure_file)
18
- json = JSON.parse(measure)
19
- end
20
- end
21
- end