health-data-standards 3.1.1 → 3.2.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.
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