health-data-standards 3.1.1 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. data/Rakefile +2 -8
  2. data/lib/health-data-standards.rb +4 -2
  3. data/lib/health-data-standards/export/hdata/metadata.rb +2 -2
  4. data/lib/health-data-standards/export/helper/cat1_view_helper.rb +7 -101
  5. data/lib/health-data-standards/export/helper/html_view_helper.rb +2 -0
  6. data/lib/health-data-standards/export/helper/scooped_view_helper.rb +109 -0
  7. data/lib/health-data-standards/export/html.rb +2 -2
  8. data/lib/health-data-standards/export/qrda/entry_template_resolver.rb +29 -5
  9. data/lib/health-data-standards/export/view_helper.rb +2 -2
  10. data/lib/health-data-standards/import/bundle/importer.rb +8 -2
  11. data/lib/health-data-standards/import/cda/result_importer.rb +5 -0
  12. data/lib/health-data-standards/import/hdata/metadata_importer.rb +1 -1
  13. data/lib/health-data-standards/models/condition.rb +5 -0
  14. data/lib/health-data-standards/models/cqm/measure.rb +118 -1
  15. data/lib/health-data-standards/models/cqm/patient_cache.rb +60 -0
  16. data/lib/health-data-standards/models/encounter.rb +11 -0
  17. data/lib/health-data-standards/models/entry.rb +8 -0
  18. data/lib/health-data-standards/models/facility.rb +5 -0
  19. data/lib/health-data-standards/models/fulfillment_history.rb +4 -0
  20. data/lib/health-data-standards/models/guarantor.rb +5 -0
  21. data/lib/health-data-standards/models/insurance_provider.rb +10 -0
  22. data/lib/health-data-standards/models/medical_equipment.rb +5 -0
  23. data/lib/health-data-standards/models/medication.rb +11 -0
  24. data/lib/health-data-standards/models/order_information.rb +6 -0
  25. data/lib/health-data-standards/models/procedure.rb +5 -0
  26. data/lib/health-data-standards/models/provider_performance.rb +5 -0
  27. data/lib/health-data-standards/models/record.rb +16 -0
  28. data/lib/health-data-standards/models/thing_with_codes.rb +35 -5
  29. data/lib/health-data-standards/util/code_system_helper.rb +12 -3
  30. data/lib/hqmf-model/data_criteria.json +2 -2
  31. data/lib/hqmf-model/document.rb +9 -2
  32. data/lib/hqmf-parser/1.0/document.rb +6 -1
  33. data/templates/_author.hdata.erb +3 -0
  34. data/templates/_pedigree.hdata.erb +16 -15
  35. data/templates/cat1/_2.16.840.1.113883.10.20.22.4.85.cat1.erb +1 -0
  36. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.1.cat1.erb +1 -1
  37. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.103.cat1.erb +1 -1
  38. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.105.cat1.erb +1 -1
  39. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.11.cat1.erb +1 -1
  40. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.12.cat1.erb +1 -1
  41. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.13.cat1.erb +1 -1
  42. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.14.cat1.erb +1 -1
  43. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.17.cat1.erb +1 -1
  44. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.18.cat1.erb +2 -2
  45. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.2.cat1.erb +2 -1
  46. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.20.cat1.erb +2 -2
  47. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.22.cat1.erb +1 -1
  48. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.23.cat1.erb +1 -1
  49. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.28.cat1.erb +2 -2
  50. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.3.cat1.erb +3 -2
  51. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.31.cat1.erb +1 -1
  52. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.32.cat1.erb +1 -1
  53. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.34.cat1.erb +2 -2
  54. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.37.cat1.erb +1 -1
  55. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.38.cat1.erb +1 -1
  56. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.4.cat1.erb +1 -1
  57. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.40.cat1.erb +2 -2
  58. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.41.cat1.erb +1 -1
  59. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.42.cat1.erb +1 -1
  60. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.43.cat1.erb +1 -1
  61. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.44.cat1.erb +1 -1
  62. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.45.cat1.erb +1 -1
  63. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.46.cat1.erb +1 -1
  64. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.47.cat1.erb +2 -1
  65. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.55.cat1.erb +2 -2
  66. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.57.cat1.erb +2 -2
  67. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.59.cat1.erb +2 -2
  68. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.62.cat1.erb +1 -1
  69. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.63.cat1.erb +1 -1
  70. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.64.cat1.erb +6 -2
  71. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.66.cat1.erb +3 -3
  72. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.69.cat1.erb +1 -1
  73. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.7.cat1.erb +1 -1
  74. data/templates/cat1/_2.16.840.1.113883.10.20.24.3.76.cat1.erb +1 -1
  75. data/templates/cat1/_measures.cat1.erb +0 -2
  76. data/templates/cat1/_medication_details.cat1.erb +3 -3
  77. data/templates/cat1/_patient_data.cat1.erb +3 -0
  78. data/templates/cat1/_record_target.cat1.erb +6 -1
  79. data/templates/cat1/_result_value.cat1.erb +16 -13
  80. data/templates/html/_entries_by_section.html.erb +13 -5
  81. data/templates/html/show.html.erb +4 -2
  82. data/templates/metadata.hdata.erb +27 -24
  83. metadata +5 -2
data/Rakefile CHANGED
@@ -10,15 +10,9 @@ Rake::TestTask.new(:test_unit) do |t|
10
10
  t.verbose = true
11
11
  end
12
12
 
13
- Cane::RakeTask.new(:quality) do |cane|
14
- cane.abc_max = 45
15
- # cane.add_threshold 'coverage/covered_percent', :>=, 97
16
- cane.style_measure = 120
17
- cane.no_style = true
18
- cane.no_doc = true
19
- end
20
13
 
21
- task :test => [:test_unit, :quality] do
14
+
15
+ task :test => [:test_unit] do
22
16
 
23
17
  system("open coverage/index.html")
24
18
  end
@@ -25,8 +25,6 @@ require_relative 'health-data-standards/export/c32'
25
25
  require_relative 'health-data-standards/export/ccda'
26
26
  require_relative 'health-data-standards/export/ccr'
27
27
  require_relative 'health-data-standards/export/csv'
28
- require_relative 'health-data-standards/export/helper/html_view_helper'
29
- require_relative 'health-data-standards/export/html'
30
28
  require_relative 'health-data-standards/export/hdata/metadata'
31
29
 
32
30
  require_relative 'health-data-standards/export/helper/gc32_view_helper'
@@ -76,6 +74,9 @@ require_relative 'health-data-standards/models/metadata/link_info'
76
74
  require_relative 'health-data-standards/models/metadata/pedigree'
77
75
 
78
76
  require_relative 'health-data-standards/export/qrda/entry_template_resolver'
77
+ require_relative 'health-data-standards/export/helper/scooped_view_helper'
78
+ require_relative 'health-data-standards/export/helper/html_view_helper'
79
+ require_relative 'health-data-standards/export/html'
79
80
  require_relative 'health-data-standards/export/helper/cat1_view_helper'
80
81
  require_relative 'health-data-standards/export/cat_1'
81
82
  require_relative 'health-data-standards/export/cat_3'
@@ -158,6 +159,7 @@ require_relative 'health-data-standards/models/cqm/aggregate_objects'
158
159
  require_relative 'health-data-standards/models/cqm/query_cache'
159
160
  require_relative 'health-data-standards/models/cqm/bundle'
160
161
  require_relative 'health-data-standards/models/cqm/measure'
162
+ require_relative 'health-data-standards/models/cqm/patient_cache'
161
163
  require_relative 'health-data-standards/import/bundle/importer'
162
164
 
163
165
 
@@ -8,8 +8,8 @@ module HealthDataStandards
8
8
  @rendering_context.template_helper = template_helper
9
9
  end
10
10
 
11
- def export(entry, metadata)
12
- @rendering_context.render(:template => 'metadata', :locals => {entry: entry, metadata: metadata})
11
+ def export(entry, metadata, include_namespace=false)
12
+ @rendering_context.render(:template => 'metadata', :locals => {entry: entry, metadata: metadata, namespace: include_namespace})
13
13
  end
14
14
  end
15
15
  end
@@ -2,91 +2,16 @@ module HealthDataStandards
2
2
  module Export
3
3
  module Helper
4
4
  module Cat1ViewHelper
5
- include HealthDataStandards::Util
6
- include HealthDataStandards::SVS
7
-
8
- def value_set_map
9
- @@vs_map ||= Hash[*ValueSet.all.map{ |p| [p.oid, p] }.flatten]
10
- end
11
-
12
- # Find all of the entries on a patient that match the given data criteria
13
- def entries_for_data_criteria(data_criteria, patient)
14
- data_criteria_oid = HQMFTemplateHelper.template_id_by_definition_and_status(data_criteria.definition,
15
- data_criteria.status || '',
16
- data_criteria.negation)
17
- filtered_entries = []
18
- case data_criteria_oid
19
- when '2.16.840.1.113883.3.560.1.404'
20
- filtered_entries = handle_patient_expired(patient)
21
- when '2.16.840.1.113883.3.560.1.401'
22
- filtered_entries = handle_clinical_trial_participant(patient)
23
- when '2.16.840.1.113883.3.560.1.405'
24
- filtered_entries = handle_payer_information(patient)
25
- else
26
- entries = patient.entries_for_oid(data_criteria_oid)
27
- codes = []
28
- vs = value_set_map[data_criteria.code_list_id]
29
- if vs
30
- codes = vs.code_set_map
31
- else
32
- HealthDataStandards.logger.warn("No codes for #{data_criteria.code_list_id}")
33
- end
34
- filtered_entries = entries.find_all do |entry|
35
- # This special case is for when the code list is a reason
36
- if data_criteria.code_list_id =~ /2\.16\.840\.1\.113883\.3\.526\.3\.100[7-9]/
37
- entry.negation_reason.present? && codes.first['values'].include?(entry.negation_reason['code'])
38
- else
39
- # The !! hack makes sure that negation_ind is a boolean
40
- entry.is_in_code_set?(codes) && !!entry.negation_ind == data_criteria.negation
41
- end
42
- end
43
- end
44
- if filtered_entries.empty?
45
- HealthDataStandards.logger.debug("No entries for #{data_criteria.title}")
46
- end
47
-
48
- filtered_entries
49
- end
50
-
51
- # Given a set of measures, find the data criteria/value set pairs that are unique across all of them
52
- # Returns an Array of Hashes. Hashes will have a three key/value pairs. One for the data criteria oid,
53
- # one for the value set oid and one for the data criteria itself
54
- def unique_data_criteria(measures)
55
- all_data_criteria = measures.map {|measure| measure.all_data_criteria}.flatten
56
- dc_oids_and_vs_oids = all_data_criteria.map do |data_criteria|
57
- data_criteria_oid = HQMFTemplateHelper.template_id_by_definition_and_status(data_criteria.definition,
58
- (data_criteria.status || ""),
59
- data_criteria.negation)
60
- value_set_oid = data_criteria.code_list_id
61
- {'data_criteria_oid' => data_criteria_oid, 'value_set_oid' => value_set_oid, 'data_criteria' => data_criteria}
62
- end
63
- dc_oids_and_vs_oids.uniq_by {|thingy| [thingy['data_criteria_oid'], thingy['value_set_oid']]}
64
- end
5
+ include HealthDataStandards::Export::Helper::ScoopedViewHelper
65
6
 
66
7
  def render_data_criteria(dc_oid, vs_oid, entries)
67
8
  html_array = entries.map do |entry|
68
- if dc_oid == '2.16.840.1.113883.3.560.1.1001'
69
- # This is a special case. This HQMF OID maps to more than one QRDA OID.
70
- # So we need to try to figure out what template we should use based on the
71
- # content of the entry
72
- if vs_oid == '2.16.840.1.113883.3.526.3.1279'
73
- # Patient Characteristic Observation Assertion template for
74
- # Patient Characteristic: ECOG Performance Status-Poor
75
- render(:partial => '2.16.840.1.113883.10.20.24.3.103', :locals => {:entry => entry,
76
- :value_set_oid => vs_oid})
77
- elsif vs_oid == "2.16.840.1.113883.3.117.1.7.1.402" || vs_oid == "2.16.840.1.113883.3.117.1.7.1.403"
78
- # Patient Charasteristic Gestational Age
79
- render(:partial => '2.16.840.1.113883.10.20.24.3.101', :locals => {:entry => entry,
80
- :value_set_oid => vs_oid})
81
- elsif vs_oid == "2.16.840.1.113883.3.526.3.1189" || vs_oid == "2.16.840.1.113883.3.526.3.1170"
82
- # Patient Characteristic Tobacco User/Non-User
83
- render(:partial => '2.16.840.1.113883.10.20.22.4.85', :locals => {:entry => entry,
84
- :value_set_oid => vs_oid})
85
- end
86
- else
87
- render(:partial => HealthDataStandards::Export::QRDA::EntryTemplateResolver.partial_for(dc_oid), :locals => {:entry => entry,
88
- :value_set_oid => vs_oid})
89
- end
9
+ bundle_id = entry.record ? entry.record["bundle_id"] : nil
10
+ vs_map = (value_set_map(bundle_id) || {})[vs_oid]
11
+ binding.pry if vs_map.nil? || vs_map.empty?
12
+ render(:partial => HealthDataStandards::Export::QRDA::EntryTemplateResolver.partial_for(dc_oid, vs_oid), :locals => {:entry => entry,
13
+ :value_set_oid => vs_oid,
14
+ :value_set_map => vs_map})
90
15
  end
91
16
  html_array.join("\n")
92
17
  end
@@ -108,25 +33,6 @@ module HealthDataStandards
108
33
  end
109
34
  end
110
35
 
111
- def handle_clinical_trial_participant(patient)
112
- if patient.clinical_trial_participant
113
- [{dummy_entry: true}]
114
- else
115
- []
116
- end
117
- end
118
-
119
- def handle_patient_expired(patient)
120
- if patient.expired
121
- [OpenStruct.new(start_date: patient.deathdate)]
122
- else
123
- []
124
- end
125
- end
126
-
127
- def handle_payer_information(patient)
128
- patient.insurance_providers
129
- end
130
36
  end
131
37
  end
132
38
  end
@@ -2,6 +2,8 @@ module HealthDataStandards
2
2
  module Export
3
3
  module Helper
4
4
  module HTMLViewHelper
5
+ include HealthDataStandards::Export::Helper::ScoopedViewHelper
6
+
5
7
  def decode_hqmf_section(section, oid)
6
8
  if oid
7
9
  HealthDataStandards::Util::HQMFTemplateHelper.definition_for_template_id(oid)['definition'].pluralize.to_sym
@@ -0,0 +1,109 @@
1
+ module HealthDataStandards
2
+ module Export
3
+ module Helper
4
+ module ScoopedViewHelper
5
+ include HealthDataStandards::Util
6
+ include HealthDataStandards::SVS
7
+ VS_MAP = {}
8
+ def value_set_map(bundle_id=nil)
9
+
10
+ VS_MAP[bundle_id] ||= Hash[ValueSet.where({bundle_id: bundle_id}).map{ |p| [p.oid, p.code_set_map] }]
11
+ end
12
+
13
+ # Given a set of measures, find the data criteria/value set pairs that are unique across all of them
14
+ # Returns an Array of Hashes. Hashes will have a three key/value pairs. One for the data criteria oid,
15
+ # one for the value set oid and one for the data criteria itself
16
+ def unique_data_criteria(measures)
17
+ all_data_criteria = measures.map {|measure| measure.all_data_criteria}.flatten
18
+ unioned_data_criteria = all_data_criteria.map do |data_criteria|
19
+ data_criteria_oid = HQMFTemplateHelper.template_id_by_definition_and_status(data_criteria.definition,
20
+ (data_criteria.status || ""),
21
+ data_criteria.negation)
22
+ value_set_oid = data_criteria.code_list_id
23
+ {'data_criteria_oid' => data_criteria_oid, 'value_set_oid' => value_set_oid, 'data_criteria' => data_criteria}
24
+ end
25
+ unioned_data_criteria.uniq_by {|thingy| [thingy['data_criteria_oid'], thingy['value_set_oid']]}
26
+ end
27
+
28
+ # Returns true if the supplied entry matches any of the supplied data criteria, false otherwise
29
+ def entry_matches_criteria(entry, data_criteria_info_list)
30
+ data_criteria_info_list.each do |data_criteria_info|
31
+ data_criteria = data_criteria_info['data_criteria']
32
+ data_criteria_oid = HQMFTemplateHelper.template_id_by_definition_and_status(data_criteria.definition,
33
+ data_criteria.status || '',
34
+ data_criteria.negation)
35
+ if entry.respond_to?(:oid) && (entry.oid == data_criteria_oid)
36
+ codes = *(value_set_map(entry.record["bundle_id"])[data_criteria_info['value_set_oid']] || [])
37
+ if codes.empty?
38
+ HealthDataStandards.logger.warn("No codes for #{data_criteria_info['value_set_oid']}")
39
+ end
40
+ if entry.is_in_code_set?(codes) && !!entry.negation_ind == data_criteria.negation
41
+ # The !! hack makes sure that negation_ind is a boolean
42
+ return true
43
+ end
44
+ end
45
+ end
46
+
47
+ false
48
+ end
49
+
50
+ # Find all of the entries on a patient that match the given data criteria
51
+ def entries_for_data_criteria(data_criteria, patient)
52
+ data_criteria_oid = HQMFTemplateHelper.template_id_by_definition_and_status(data_criteria.definition,
53
+ data_criteria.status || '',
54
+ data_criteria.negation)
55
+ filtered_entries = []
56
+ case data_criteria_oid
57
+ when '2.16.840.1.113883.3.560.1.404'
58
+ filtered_entries = handle_patient_expired(patient)
59
+ when '2.16.840.1.113883.3.560.1.401'
60
+ filtered_entries = handle_clinical_trial_participant(patient)
61
+ when '2.16.840.1.113883.3.560.1.405'
62
+ filtered_entries = handle_payer_information(patient)
63
+ else
64
+ entries = patient.entries_for_oid(data_criteria_oid)
65
+ codes = (value_set_map(patient["bundle_id"])[data_criteria.code_list_id] || [])
66
+ if codes.empty?
67
+ HealthDataStandards.logger.warn("No codes for #{data_criteria.code_list_id}")
68
+ end
69
+ filtered_entries = entries.find_all do |entry|
70
+ # This special case is for when the code list is a reason
71
+ if data_criteria.code_list_id =~ /2\.16\.840\.1\.113883\.3\.526\.3\.100[7-9]/
72
+ entry.negation_reason.present? && codes.first['values'].include?(entry.negation_reason['code'])
73
+ else
74
+ # The !! hack makes sure that negation_ind is a boolean
75
+ entry.is_in_code_set?(codes) && !!entry.negation_ind == data_criteria.negation
76
+ end
77
+ end
78
+ end
79
+ if filtered_entries.empty?
80
+ HealthDataStandards.logger.debug("No entries for #{data_criteria.title}")
81
+ end
82
+
83
+ filtered_entries
84
+ end
85
+
86
+ def handle_clinical_trial_participant(patient)
87
+ if patient.clinical_trial_participant
88
+ [{dummy_entry: true}]
89
+ else
90
+ []
91
+ end
92
+ end
93
+
94
+ def handle_patient_expired(patient)
95
+ if patient.expired
96
+ [OpenStruct.new(start_date: patient.deathdate)]
97
+ else
98
+ []
99
+ end
100
+ end
101
+
102
+ def handle_payer_information(patient)
103
+ patient.insurance_providers
104
+ end
105
+
106
+ end
107
+ end
108
+ end
109
+ end
@@ -9,9 +9,9 @@ module HealthDataStandards
9
9
  @code_map = nil
10
10
  end
11
11
 
12
- def export(patient)
12
+ def export(patient, measures=[])
13
13
  @code_map ||= self.build_code_map
14
- @rendering_context.render(:template => 'show', :locals => {:patient => patient, :code_map => @code_map})
14
+ @rendering_context.render(:template => 'show', :locals => {:patient => patient, :code_map => @code_map, :measures => measures})
15
15
  end
16
16
 
17
17
  def build_code_map
@@ -14,12 +14,36 @@ module HealthDataStandards
14
14
  hqmf_qrda_oid_map.any? {|map_tuple| map_tuple['qrda_oid'] == oid}
15
15
  end
16
16
 
17
- def qrda_oid_for_hqmf_oid(hqmf_oid)
18
- oid_tuple = hqmf_qrda_oid_map.find {|map_tuple| map_tuple['hqmf_oid'] == hqmf_oid }
19
- if oid_tuple.nil?
20
- puts "no qrda oid for #{hqmf_oid}"
17
+ def qrda_oid_for_hqmf_oid(hqmf_oid, vs_oid = nil)
18
+
19
+ if (vs_oid && hqmf_oid == '2.16.840.1.113883.3.560.1.1001')
20
+ qrda_oid_for_hqmf_patient_characteristic(vs_oid)
21
+ else
22
+ oid_tuple = hqmf_qrda_oid_map.find {|map_tuple| map_tuple['hqmf_oid'] == hqmf_oid }
23
+ if oid_tuple.nil?
24
+ puts "no qrda oid for #{hqmf_oid}"
25
+ end
26
+ oid_tuple['qrda_oid']
27
+ end
28
+
29
+ end
30
+
31
+ # given a value set oid for a patient characteristic, return the qrda oid for the correct characteristic
32
+ def qrda_oid_for_hqmf_patient_characteristic(vs_oid)
33
+ # This is a special case. This HQMF OID maps to more than one QRDA OID.
34
+ # So we need to try to figure out what template we should use based on the
35
+ # content of the entry
36
+ if vs_oid == '2.16.840.1.113883.3.526.3.1279'
37
+ # Patient Characteristic Observation Assertion template for
38
+ # Patient Characteristic: ECOG Performance Status-Poor
39
+ '2.16.840.1.113883.10.20.24.3.103'
40
+ elsif ["2.16.840.1.113883.3.117.1.7.1.402" , "2.16.840.1.113883.3.117.1.7.1.403" , "2.16.840.1.113883.3.117.1.7.1.287" ,"2.16.840.1.113883.3.117.1.7.1.307"].index(vs_oid)
41
+ # Patient Charasteristic Gestational Age
42
+ '2.16.840.1.113883.10.20.24.3.101'
43
+ elsif vs_oid == "2.16.840.1.113883.3.526.3.1189" || vs_oid == "2.16.840.1.113883.3.526.3.1170" || vs_oid == '2.16.840.1.113883.3.600.2390'
44
+ # Patient Characteristic Tobacco User/Non-User
45
+ '2.16.840.1.113883.10.20.22.4.85'
21
46
  end
22
- oid_tuple['qrda_oid']
23
47
  end
24
48
 
25
49
  alias :partial_for :qrda_oid_for_hqmf_oid
@@ -6,7 +6,7 @@ module HealthDataStandards
6
6
  options['attribute'] ||= :codes
7
7
  options['exclude_null_flavor'] ||= false
8
8
  code_string = nil
9
- preferred_code = entry.preferred_code(options['preferred_code_sets'], options['attribute'])
9
+ preferred_code = entry.preferred_code(options['preferred_code_sets'], options['attribute'], options['value_set_map'])
10
10
  if preferred_code
11
11
  code_system_oid = HealthDataStandards::Util::CodeSystemHelper.oid_for_code_system(preferred_code['code_set'])
12
12
  code_string = "<#{options['tag_name']} code=\"#{preferred_code['code']}\" codeSystem=\"#{code_system_oid}\" #{options['extra_content']}>"
@@ -20,7 +20,7 @@ module HealthDataStandards
20
20
 
21
21
  if options["attribute"] == :codes && entry.respond_to?(:translation_codes)
22
22
  code_string += "<originalText>#{ERB::Util.html_escape entry.description}</originalText>" if entry.respond_to?(:description)
23
- entry.translation_codes(options['preferred_code_sets']).each do |translation|
23
+ entry.translation_codes(options['preferred_code_sets'], options['value_set_map']).each do |translation|
24
24
  code_string += "<translation code=\"#{translation['code']}\" codeSystem=\"#{HealthDataStandards::Util::CodeSystemHelper.oid_for_code_system(translation['code_set'])}\"/>\n"
25
25
  end
26
26
  end
@@ -41,8 +41,14 @@ module HealthDataStandards
41
41
  b.delete
42
42
  end if options[:delete_existing]
43
43
 
44
- unpack_and_store_system_js(zip_file)
45
-
44
+ #find the highest bundle version and see if one is installed that is greater than the one
45
+ # we are currently installing. Do not load the libs other wise
46
+ vers = bundle_versions.values.sort.reverse[0]
47
+ if (vers.nil? || vers <= bundle.version || options["force_js_install"])
48
+ unpack_and_store_system_js(zip_file)
49
+ else
50
+ puts "javascript libraries will not being updated as a more recent bundle version is already installed"
51
+ end
46
52
  # Store the bundle metadata.
47
53
  unless bundle.save
48
54
  raise bundle.errors.full_messages.join(",")
@@ -11,6 +11,7 @@ module HealthDataStandards
11
11
  result = super
12
12
  extract_value(entry_element, result)
13
13
  extract_interpretation(entry_element, result)
14
+ extract_reference_range(entry_element, result)
14
15
  extract_negation(entry_element, result)
15
16
  result
16
17
  end
@@ -24,6 +25,10 @@ module HealthDataStandards
24
25
  result.interpretation = {'code' => code, 'codeSystem' => code_system}
25
26
  end
26
27
  end
28
+
29
+ def extract_reference_range(parent_element, result)
30
+ result.reference_range = parent_element.at_xpath("./cda:referenceRange/cda:observationRange/cda:text").try(:text)
31
+ end
27
32
 
28
33
  end
29
34
  end
@@ -6,7 +6,7 @@ module HealthDataStandards
6
6
 
7
7
  def import(meta_xml)
8
8
  meta_xml.root.add_namespace_definition("hrf-md", Metadata::NS)
9
- meta_element = meta_xml.at_xpath("./hrf-md:DocumentMetadata")
9
+ meta_element = meta_xml.at_xpath("./hrf-md:DocumentMetaData")
10
10
  return unless meta_element
11
11
 
12
12
  meta = Metadata::Base.new
@@ -11,4 +11,9 @@ class Condition < Entry
11
11
 
12
12
  alias :cause_of_death :causeOfDeath
13
13
  alias :cause_of_death= :causeOfDeath=
14
+
15
+ def shift_dates(date_diff)
16
+ super
17
+ self.time_of_death = self.time_of_death.nil? ? nil : self.time_of_death + date_diff
18
+ end
14
19
  end
@@ -16,8 +16,15 @@ module HealthDataStandards
16
16
  field :category, type: String
17
17
  field :population_ids , type: Hash
18
18
  field :oids, type: Array
19
- field :data_criteria, type: Array
20
19
 
20
+ field :population_criteria, type: Hash
21
+ field :data_criteria, type: Hash, default: {}
22
+ field :source_data_criteria, type: Hash, default: {}
23
+ field :measure_period, type: Hash
24
+ field :measure_attributes, type: Hash
25
+ field :populations, type: Array
26
+ field :preconditions, type: Hash
27
+ field :hqmf_document, type: Hash
21
28
  scope :top_level_by_type , ->(type){where({"type"=> type}).any_of({"sub_id" => nil}, {"sub_id" => "a"})}
22
29
  scope :top_level , any_of({"sub_id" => nil}, {"sub_id" => "a"})
23
30
  scope :order_by_id_sub_id, order_by([["id", :asc],["sub_id", :asc]])
@@ -25,6 +32,9 @@ module HealthDataStandards
25
32
  index({oids: 1})
26
33
  index({hqmf_id: 1})
27
34
  index({category: 1})
35
+ index({sub_id: 1})
36
+ index({_id: 1, sub_id: 1})
37
+
28
38
  index "bundle_id" => 1
29
39
 
30
40
  validates_presence_of :id
@@ -52,6 +62,113 @@ module HealthDataStandards
52
62
  pipeline << {'$sort' => {"category" => 1}}
53
63
  Mongoid.default_session.command(aggregate: 'measures', pipeline: pipeline)['result']
54
64
  end
65
+
66
+
67
+ # Returns the hqmf-parser's ruby implementation of an HQMF document.
68
+ # Rebuild from population_criteria, data_criteria, and measure_period JSON
69
+ def as_hqmf_model
70
+ @hqmf ||= HQMF::Document.from_json(self.hqmf_document)
71
+ end
72
+
73
+ def smoking_gun_data(patient_cache_filter={})
74
+ ::Measure.calculate_smoking_gun_data(self.hqmf_id, patient_cache_filter)
75
+ end
76
+ # Calculate the smoking gun data for the given hqmf_id with the given patient_cache_filter
77
+ # The filter will allow us to segment the cache by things like test_id required for Cypress.
78
+
79
+ def self.calculate_smoking_gun_data(hqmf_id, patient_cache_filter={})
80
+ population_keys = ('a'..'zz').to_a
81
+ values = {}
82
+ measure = Measure.top_level.where({hqmf_id: hqmf_id}).first
83
+ sub_ids = []
84
+ hqmf_measure = measure.as_hqmf_model
85
+ population_codes = []
86
+ if hqmf_measure.populations.length == 1
87
+ sub_ids = nil
88
+ else
89
+ #Do not bother with populaions that contain stratifications
90
+ hqmf_measure.populations.each_with_index do |population,index|
91
+ if population["stratification"].nil?
92
+ sub_ids << population_keys[index]
93
+ HQMF::PopulationCriteria::ALL_POPULATION_CODES.each do |code|
94
+ population_codes << population[code] if population[code]
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ population_codes.uniq!
101
+
102
+ rationals = PatientCache.smoking_gun_rational(measure.hqmf_id,sub_ids,patient_cache_filter)
103
+ rationals.each_pair do |mrn,rash|
104
+ values[mrn] = []
105
+ population_codes.each do |pop_code|
106
+ # if (population[pop_code])
107
+ population_criteria = hqmf_measure.population_criteria(pop_code)
108
+ if population_criteria.preconditions
109
+ array = []
110
+
111
+ parent = population_criteria.preconditions[0]
112
+ values[mrn].concat self.loop_preconditions(hqmf_measure, parent, rash)
113
+ end # end population_criteria.preconditions
114
+ #end # end (population[pop_code])
115
+ end # population_codes
116
+ values[mrn].uniq!
117
+ end
118
+ values
119
+ end
120
+
121
+ private
122
+
123
+
124
+ def self.loop_data_criteria(hqmf, data_criteria, rationale)
125
+ result = []
126
+ if (rationale[data_criteria.id])
127
+
128
+ if data_criteria.type != :derived
129
+ template = HQMF::DataCriteria.template_id_for_definition(data_criteria.definition, data_criteria.status, data_criteria.negation)
130
+ value_set_oid = data_criteria.code_list_id
131
+ begin
132
+ qrda_template = HealthDataStandards::Export::QRDA::EntryTemplateResolver.qrda_oid_for_hqmf_oid(template,value_set_oid)
133
+ rescue
134
+ value_set_oid = 'In QRDA Header (Non Null Value)'
135
+ qrda_template = 'N/A'
136
+ end # end begin recue
137
+ result << {description: data_criteria.description, oid: value_set_oid, template: qrda_template}
138
+
139
+ if data_criteria.temporal_references
140
+ data_criteria.temporal_references.each do |temporal_reference|
141
+ if temporal_reference.reference.id != 'MeasurePeriod'
142
+ result.concat loop_data_criteria(hqmf, hqmf.data_criteria(temporal_reference.reference.id), rationale)
143
+ end #if temporal_reference.reference.id
144
+ end # end data_criteria.temporal_references.each do |temporal_reference|
145
+ end# end if data_criteria.temporal_references
146
+ else #data_criteria.type != :derived
147
+ (data_criteria.children_criteria || []).each do |child_id|
148
+ result.concat loop_data_criteria(hqmf, hqmf.data_criteria(child_id), rationale)
149
+ end
150
+ end
151
+ end
152
+ result
153
+ end
154
+
155
+ def self.loop_preconditions(hqmf, parent, rationale)
156
+ result = []
157
+ parent.preconditions.each do |precondition|
158
+ parent_key = "precondition_#{parent.id}"
159
+ key = "precondition_#{precondition.id}"
160
+ if precondition.preconditions.empty?
161
+ data_criteria = hqmf.data_criteria(precondition.reference.id)
162
+ result.concat loop_data_criteria(hqmf, data_criteria, rationale)
163
+ else
164
+ if (rationale[parent_key] && rationale[key])
165
+ result.concat loop_preconditions(hqmf, precondition, rationale)
166
+ end
167
+ end
168
+ end
169
+ result
170
+ end
171
+
55
172
  end
56
173
  end
57
174
  end