Module: HealthDataStandards::Validate::ReportedResultExtractor

Included in:
PerformanceRateValidator
Defined in:
lib/health-data-standards/validate/reported_result_extractor.rb

Instance Method Summary collapse

Instance Method Details

#convert_value(value_node) ⇒ Object

convert numbers in value nodes to Int / Float as necessary TODO add more types other than ‘REAL’



114
115
116
117
118
119
120
121
122
123
# File 'lib/health-data-standards/validate/reported_result_extractor.rb', line 114

def convert_value(value_node)
  if value_node.nil?
    return
  end
  if value_node['type'] == 'REAL' || value_node['value'].include?('.')
    return value_node['value'].to_f
  else
    return value_node['value'].to_i
  end
end

#extract_component_value(node, code, id, strata = nil) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/health-data-standards/validate/reported_result_extractor.rb', line 79

def extract_component_value(node, code, id, strata = nil)
  xpath_observation = %{ cda:component/cda:observation[./cda:value[@code = "#{code}"] and ./cda:reference/cda:externalObservation/cda:id[#{translate("@root")}='#{id.upcase}']]}
  cv = node.at_xpath(xpath_observation)
  return nil unless cv
  val = nil
  if strata
    strata_path = %{ cda:entryRelationship[@typeCode="COMP"]/cda:observation[./cda:templateId[@root = "2.16.840.1.113883.10.20.27.3.4"]  and ./cda:reference/cda:externalObservation/cda:id[#{translate("@root")}='#{strata.upcase}']]}
    n = cv.xpath(strata_path)
    val = get_aggregate_count(n) if n
  else
    val = get_aggregate_count(cv)
  end
  #Performance rate is only applicable for unstratified values
  if code == "NUMER" && strata == nil
    pref_rate_value = extract_performance_rate(node,code,id)
  end
  return val,(strata.nil? ?  extract_supplemental_data(cv) : nil),pref_rate_value
end

#extract_cv_value(node, id, msrpopl, strata = nil) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/health-data-standards/validate/reported_result_extractor.rb', line 64

def extract_cv_value(node, id, msrpopl, strata = nil)
  xpath_observation = %{ cda:component/cda:observation[./cda:value[@code = "MSRPOPL"] and ./cda:reference/cda:externalObservation/cda:id[#{translate("@root")}='#{msrpopl.upcase}']]}
  cv = node.at_xpath(xpath_observation)
  return nil unless cv
  val = nil
  if strata
  strata_path = %{ cda:entryRelationship[@typeCode="COMP"]/cda:observation[./cda:templateId[@root = "2.16.840.1.113883.10.20.27.3.4"]  and ./cda:reference/cda:externalObservation/cda:id[#{translate("@root")}='#{strata.upcase}']]}
  n = cv.xpath(strata_path)
  val = get_cv_value(n,id)
  else
  val = get_cv_value(cv,id)
  end
  return val, (strata.nil? ?  extract_supplemental_data(cv) : nil)
end

#extract_performance_rate(node, code, id) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/health-data-standards/validate/reported_result_extractor.rb', line 98

def extract_performance_rate(node,code,id)
  xpath_perf_rate = %{ cda:component/cda:observation[./cda:templateId[@root = "2.16.840.1.113883.10.20.27.3.14"] and ./cda:reference/cda:externalObservation/cda:id[#{translate("@root")}='#{id.upcase}']]/cda:value}
  perf_rate = node.at_xpath(xpath_perf_rate)
  pref_rate_value = {}
  if perf_rate != nil
    if perf_rate.at_xpath("./@nullFlavor")
      pref_rate_value["nullFlavor"] = "NA"
      return pref_rate_value
    else
      pref_rate_value["value"] = perf_rate.at_xpath("./@value").value
      return pref_rate_value
    end
  end
  return nil
end

#extract_results_by_ids(measure_id, ids, doc) ⇒ Object



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/health-data-standards/validate/reported_result_extractor.rb', line 11

def extract_results_by_ids(measure_id, ids, doc)
  results = nil
  _ids = ids.dup
  stratification = _ids.delete("stratification")
  stratification ||= _ids.delete("STRAT")
  errors = []
  nodes = find_measure_node(measure_id, doc)

  if nodes.nil? || nodes.empty?
    # short circuit and return nil
    return {}
  end

  nodes.each do |n|
   results =  get_measure_components(n, _ids, stratification)
   break if (results != nil || (results != nil && !results.empty?))
  end
  return nil if results.nil?
  results[:population_ids] = ids.dup
  results
end

#extract_supplemental_data(cv) ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/health-data-standards/validate/reported_result_extractor.rb', line 142

def extract_supplemental_data(cv)
  ret = {}
  supplemental_data_mapping = {"RACE"=> "2.16.840.1.113883.10.20.27.3.8",
                       "ETHNICITY" => "2.16.840.1.113883.10.20.27.3.7",
                       "SEX" => "2.16.840.1.113883.10.20.27.3.6",
                       "PAYER" => "2.16.840.1.113883.10.20.27.3.9"}
  supplemental_data_mapping.each_pair do |supp, id|
    key_hash = {}
    xpath = "cda:entryRelationship/cda:observation[cda:templateId[@root='#{id}']]"
    (cv.xpath(xpath) || []).each do |node|
      value = node.at_xpath('cda:value')
      count = get_aggregate_count(node)
      if value.at_xpath("./@nullFlavor")
       if supp == "PAYER" && value['xsi:type'] == 'CD' && value['nullFlavor'] == 'OTH' && value.at_xpath("cda:translation") && value.at_xpath("cda:translation")['code']
        key_hash[value.at_xpath("cda:translation")['code']] = count
       else
        key_hash["UNK"] = count
       end
      else
       key_hash[value['code']] = count
      end
    end
    ret[supp.to_s] = key_hash
  end
  ret
end

#find_measure_node(id, doc) ⇒ Object



33
34
35
36
37
38
# File 'lib/health-data-standards/validate/reported_result_extractor.rb', line 33

def find_measure_node(id, doc)
   xpath_measures = %Q{/cda:ClinicalDocument/cda:component/cda:structuredBody/cda:component/cda:section
    /cda:entry/cda:organizer[ ./cda:templateId[@root = "2.16.840.1.113883.10.20.27.3.1"]
    and ./cda:reference/cda:externalDocument/cda:id[#{translate("@extension")}='#{id.upcase}' and #{translate("@root")}='2.16.840.1.113883.4.738']]}
   return doc.xpath(xpath_measures)
end

#get_aggregate_count(node) ⇒ Object

given an observation node with an aggregate count node, return the reported and expected value within the count node



135
136
137
138
139
140
# File 'lib/health-data-standards/validate/reported_result_extractor.rb', line 135

def get_aggregate_count(node)
  xpath_value = 'cda:entryRelationship/cda:observation[./cda:templateId[@root="2.16.840.1.113883.10.20.27.3.3"]]/cda:value'
  value_node = node.at_xpath(xpath_value)
  value = convert_value(value_node) if value_node
  value
end

#get_cv_value(node, cv_id) ⇒ Object

given an observation node with an aggregate count node, return the reported and expected value within the count node



126
127
128
129
130
131
132
# File 'lib/health-data-standards/validate/reported_result_extractor.rb', line 126

def get_cv_value(node, cv_id)
  xpath_value = %{cda:entryRelationship/cda:observation[./cda:templateId[@root="2.16.840.1.113883.10.20.27.3.2"] and ./cda:reference/cda:externalObservation/cda:id[#{translate("@root")}='#{cv_id.upcase}']]/cda:value}

  value_node = node.at_xpath(xpath_value)
  value = convert_value(value_node) if value_node
  value
end

#get_measure_components(n, ids, stratification) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/health-data-standards/validate/reported_result_extractor.rb', line 40

def get_measure_components(n,ids, stratification)
  results = {:supplemental_data =>{}}
  ids.each_pair do |k,v|
    val = nil
    sup = nil
    if (k == 'OBSERV')
      msrpopl = ids['MSRPOPL']
      val, sup = extract_cv_value(n,v,msrpopl, stratification)
    else
      val,sup,pr =extract_component_value(n,k,v,stratification)
    end
    if !val.nil?
      results[k.to_s] = val
      results[:supplemental_data][k] = sup
    else
      # return nil
    end
    if !pr.nil?
      results["PR"] = pr
    end
  end
  results
end

#translate(id) ⇒ Object



169
170
171
# File 'lib/health-data-standards/validate/reported_result_extractor.rb', line 169

def translate(id)
  %{translate(#{id}, "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")}
end