Class: HQMF2CQL::DocumentPopulationHelper

Inherits:
HQMF2::DocumentPopulationHelper show all
Includes:
HQMF2::Utilities
Defined in:
lib/hqmf-parser/cql/document_helpers/doc_population_helper.rb

Overview

Handles generation of populations for the main document

Instance Method Summary collapse

Methods included from HQMF2::Utilities

#attr_val, attr_val, #strip_tokens, #to_xml

Methods included from HQMF::Conversion::Utilities

#build_hash, #check_equality, #json_array, #openstruct_to_json

Methods inherited from HQMF2::DocumentPopulationHelper

#add_id_to_population, #add_observ_to_population, #add_title_to_population, #build_population_criteria, #get_document_populations, #get_id_def, #get_title_def, #handle_base_populations, #initialize, #population_id_with_counter, #remove_population_preconditions

Constructor Details

This class inherits a constructor from HQMF2::DocumentPopulationHelper

Instance Method Details

#add_supplemental_data_elements_to_population(population_def, population) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/hqmf-parser/cql/document_helpers/doc_population_helper.rb', line 153

def add_supplemental_data_elements_to_population(population_def, population)
  begin
    supplemental_data_elements_def = population_def.xpath('cda:component/cql-ext:supplementalDataElement')
  rescue Nokogiri::XML::XPath::SyntaxError
    # Older fixtures without SDEs don't have the cql-ext namespace
    return
  end

  supplemental_data_elements = []
  supplemental_data_elements_def.each do |sde_def|
    cql_definition_name = sde_def.at_xpath('cda:precondition/cda:criteriaReference/cda:id').attribute('extension').to_s.match(/"([^"]*)"/)[1]
    supplemental_data_elements << cql_definition_name
  end
  population['supplemental_data_elements'] = supplemental_data_elements
end

#extract_main_libraryObject

Extracts the name of the main cql library from the Population Criteria Section.



116
117
118
119
120
121
122
123
124
125
126
# File 'lib/hqmf-parser/cql/document_helpers/doc_population_helper.rb', line 116

def extract_main_library
  population_criteria_sections = @doc.xpath("//cda:populationCriteriaSection/cda:component[@typeCode='COMP']", HQMF2::Document::NAMESPACES)
  criteria_section = population_criteria_sections.at_xpath("cda:initialPopulationCriteria", HQMF2::Document::NAMESPACES)
  if criteria_section
    # Example: the full name for the population criteria section is "BonnieNesting01.\"Initial Population\""
    # The regex returns everything before the "."  (BonnieNesting01), which is the file name of the cql measure
    cql_main_library_name = criteria_section.at_xpath("*/*/cda:id", HQMF2::Document::NAMESPACES).attribute('extension').to_s.match(/[^.]*/).to_s
  else
    nil
  end
end

#extract_observationsObject

Extracts potential measure observations from the CQL based HQMF. This function needs to return a boolean so that it will continue to work with HQMF2::DocumentPopulationHelper::extract_populations_and_criteria This function is being overridden because in CQL the observations are no longer data criteria in the HQMF.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/hqmf-parser/cql/document_helpers/doc_population_helper.rb', line 17

def extract_observations
  @observations = []

  # Look for observations in the measureObservationSection of the CQL based HQMF document, and if they exist extract the name of the CQL statement that calculates the observation. This is the name of the "define function" statement in the CQL.
  # In addition to the function name we also need to retreive the parameter for the function.
  observation_section = @doc.xpath('/cda:QualityMeasureDocument/cda:component/cda:measureObservationSection',
                                   HQMF2::Document::NAMESPACES)
  unless observation_section.empty?
    observation_section.each do |entry|
      # Need to add population criteria for observations
      criteria_id = 'OBSERV'
      criteria = HQMF2::PopulationCriteria.new(entry.xpath('cda:definition'), @document, @id_generator)
      criteria.type = 'OBSERV'
      if @ids_by_hqmf_id["#{criteria.hqmf_id}"]
        criteria.create_human_readable_id(@ids_by_hqmf_id[criteria.hqmf_id])
      else
        criteria.create_human_readable_id(population_id_with_counter(criteria_id))
        @ids_by_hqmf_id["#{criteria.hqmf_id}"] = criteria.id
      end
      @population_criteria << criteria

      # Extract CQL function specific details
      cql_define_function = {}
      # The at_xpath(...).values returns an array of a single element.
      # The match returns an array and since we don't want the double quotes we take the second element
      cql_define_function[:function_name] = entry.at_xpath("*/cda:measureObservationDefinition/cda:value/cda:expression").values.first.match('\\"([A-Za-z0-9 ]+)\\"')[1]
      # The criteria_reference_id is the id of the measurePopulationCriteria that should be used for this observation function
      measure_population_id = entry.at_xpath("*/cda:measureObservationDefinition/cda:component/cda:criteriaReference/cda:id").attributes['root'].value
      measure_population_name = entry.at_xpath("*/cda:measureObservationDefinition/cda:component/cda:criteriaReference/cda:id").attributes['extension'].value
      # Get the name of the parameter to the observation function within the relevant population criteria section
      cql_define_function[:parameter] = @doc.at_xpath("cda:QualityMeasureDocument/cda:component/cda:populationCriteriaSection/cda:component/cda:#{measure_population_name}Criteria/cda:id[@root = \"#{measure_population_id}\"]/../cda:precondition/cda:criteriaReference/cda:id").attributes['extension'].value.match('\\"([A-Za-z0-9 ]+)\\"')[1]

      @observations << cql_define_function
    end
  end
  !@observations.empty?
end

#extract_populationsObject



6
7
8
9
10
11
# File 'lib/hqmf-parser/cql/document_helpers/doc_population_helper.rb', line 6

def extract_populations
  @populations_cql_map = extract_populations_cql_map
  extract_populations_and_criteria
  # Return via destructuring
  [@populations, @population_criteria, @populations_cql_map, @observations]
end

#extract_populations_and_criteriaObject

Returns the population descriptions and criteria found in this document



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/hqmf-parser/cql/document_helpers/doc_population_helper.rb', line 129

def extract_populations_and_criteria
  has_observation = extract_observations
  document_populations = get_document_populations
  number_of_populations = document_populations.length
  document_populations.each_with_index do |population_def, population_index|
    population = {}
    handle_base_populations(population_def, population)

    id_def = get_id_def(population_def)
    add_id_to_population(population_def, id_def, population, population_index)
    add_title_to_population(population_def, population)
    add_observ_to_population(has_observation, population)

    add_supplemental_data_elements_to_population(population_def, population)

    @populations << population
    handle_stratifications(population_def, number_of_populations, population, id_def, population_index)
  end

  # Push in the stratification populations after the unstratified populations
  @populations.concat(@stratifications)
  [@populations, @population_criteria]
end

#extract_populations_cql_mapObject

Extracts the mappings between actual HQMF populations and their corresponding CQL define statements.



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/hqmf-parser/cql/document_helpers/doc_population_helper.rb', line 84

def extract_populations_cql_map
  populations_cql_map = {}
  @doc.xpath("//cda:populationCriteriaSection/cda:component[@typeCode='COMP']", HQMF2::Document::NAMESPACES).each do |population_def|
    {
      HQMF::PopulationCriteria::IPP => 'initialPopulationCriteria',
      HQMF::PopulationCriteria::DENOM => 'denominatorCriteria',
      HQMF::PopulationCriteria::NUMER => 'numeratorCriteria',
      HQMF::PopulationCriteria::NUMEX => 'numeratorExclusionCriteria',
      HQMF::PopulationCriteria::DENEXCEP => 'denominatorExceptionCriteria',
      HQMF::PopulationCriteria::DENEX => 'denominatorExclusionCriteria',
      HQMF::PopulationCriteria::MSRPOPL => 'measurePopulationCriteria',
      HQMF::PopulationCriteria::MSRPOPLEX => 'measurePopulationExclusionCriteria',
      HQMF::PopulationCriteria::STRAT => 'stratifierCriteria'
    }.each_pair do |criteria_id, criteria_element_name|
      criteria_def = population_def.at_xpath("cda:#{criteria_element_name}", HQMF2::Document::NAMESPACES)
      if criteria_def
        # Ignore Supplemental Data Elements
        next if HQMF::PopulationCriteria::STRAT == criteria_id &&
            !criteria_def.xpath("cda:component[@typeCode='COMP']/cda:measureAttribute/cda:code[@code='SDE']").empty?
        cql_statement = criteria_def.at_xpath("*/*/cda:id", HQMF2::Document::NAMESPACES).attribute('extension').to_s.match(/"([^"]*)"/)
        if populations_cql_map[criteria_id].nil?
          populations_cql_map[criteria_id] = []
        end
        cql_statement = cql_statement.to_s.delete('\\"')
        populations_cql_map[criteria_id].push cql_statement
      end
    end
  end
  populations_cql_map
end

#handle_stratifications(population_def, number_of_populations, population, id_def, population_index) ⇒ Object

Generate the stratifications of populations, if any exist for CQL, adds ‘population_index’ and ‘stratification_index’



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/hqmf-parser/cql/document_helpers/doc_population_helper.rb', line 57

def handle_stratifications(population_def, number_of_populations, population, id_def, population_index)
  # handle stratifications (EP137, EP155)
  stratifier_criteria_xpath = "cda:component/cda:stratifierCriteria[not(cda:component/cda:measureAttribute/cda:code[@code  = 'SDE'])]/.."
  population_def.xpath(stratifier_criteria_xpath, HQMF2::Document::NAMESPACES)
    .each_with_index do |criteria_def, criteria_def_index|
    # Skip this Stratification if any precondition doesn't contain any preconditions
    next unless HQMF2::PopulationCriteria.new(criteria_def, @document, @id_generator)
                .preconditions.all? { |prcn| prcn.preconditions.length > 0 }
    index = number_of_populations + ((population_index - 1) * criteria_def.xpath('./*/cda:precondition').length) +
            criteria_def_index
    criteria_id = HQMF::PopulationCriteria::STRAT
    stratified_population = population.dup
    stratified_population['stratification'] = criteria_def.at_xpath('./*/cda:id/@root').try(:value) ||
                                              "#{criteria_id}-#{criteria_def_index}"
    build_population_criteria(criteria_def, criteria_id, stratified_population)

    stratified_population['id'] = id_def ? "#{id_def.value} - Stratification #{criteria_def_index + 1}" : "Population#{index}"
    title_def = population_def.at_xpath('cda:title/@value', HQMF2::Document::NAMESPACES)
    stratified_population['title'] = title_def ? "#{title_def.value} - Stratification #{criteria_def_index + 1}" : "Population #{index}"
    stratified_population['population_index'] = population_index
    stratified_population['stratification_index'] = criteria_def_index
    @stratifications << stratified_population
  end
end