Class: CqlMeasure

Inherits:
Object
  • Object
show all
Includes:
Mongoid::Attributes::Dynamic, Mongoid::Document, Mongoid::Timestamps
Defined in:
lib/models/cql_measure.rb

Constant Summary collapse

DEFAULT_EFFECTIVE_DATE =
Time.gm(2012,12,31,23,59).to_i
MP_START_DATE =
Time.gm(2012,1,1,0,0).to_i
TYPES =
["ep", "eh"]

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.for_patient(record) ⇒ Object

Find the measures matching a patient



67
68
69
# File 'lib/models/cql_measure.rb', line 67

def self.for_patient(record)
  where user_id: record.user_id, hqmf_set_id: { '$in' => record.measure_ids }
end

Instance Method Details

#all_data_criteriaObject



115
116
117
# File 'lib/models/cql_measure.rb', line 115

def all_data_criteria
  as_hqmf_model.all_data_criteria
end

#as_hqmf_modelObject

Returns the hqmf-parser’s ruby implementation of an HQMF document. Rebuild from population_criteria, data_criteria, and measure_period JSON



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/models/cql_measure.rb', line 96

def as_hqmf_model
  json = {
    "id" => self.measure_id,
    "title" => self.title,
    "description" => self.description,
    "population_criteria" => self.population_criteria,
    "data_criteria" => self.data_criteria,
    "source_data_criteria" => self.source_data_criteria,
    "measure_period" => self.measure_period,
    "attributes" => self.measure_attributes,
    "populations" => self.populations,
    "hqmf_id" => self.hqmf_id,
    "hqmf_set_id" => self.hqmf_set_id,
    "hqmf_version_number" => self.hqmf_version_number,
    "cms_id" => self.cms_id
  }
  HQMF::Document.from_json(json)
end

#calculate_complexityObject



134
135
136
137
138
139
140
141
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
168
169
170
# File 'lib/models/cql_measure.rb', line 134

def calculate_complexity
  # We calculate the complexity for each statement, and (at least for now) store the result in the same way
  # we store the complexity for QDM variables
  # TODO: consider whether this is too much of a force fit
  self.complexity = { variables: [] }
  # Recursively look through an expression to count the logical branches
  def count_expression_logical_branches(expression)
    case expression
    when nil
      0
    when Array
      expression.map { |exp| count_expression_logical_branches(exp) }.sum
    when Hash
      case expression['type']
      when 'And', 'Or', 'Not'
        count_expression_logical_branches(expression['operand'])
      when 'Query'
        # TODO: Do we need to look into the source side of the query? Can there be logical operators there?
        count_expression_logical_branches(expression['where']) + count_expression_logical_branches(expression['relationship'])
      else
        1
      end
    else
      0
    end
  end

  # Determine the complexity of each statement
  self.elm.each do |elm|
    if statements = elm.try(:[], 'library').try(:[], 'statements').try(:[], 'def')
      statements.each do |statement|
        self.complexity[:variables] << { name: statement['name'], complexity: count_expression_logical_branches(statement['expression']) }
      end
    end
  end
  self.complexity
end

#composite_hqmf_set_idObject

Returns the composite measure’s hqmf_set_id for this component Component measure hqmf_set_id is formatted as follows:

<composite_hqmf_set_id>&<component_hqmf_set_id>


175
176
177
# File 'lib/models/cql_measure.rb', line 175

def composite_hqmf_set_id
  self.hqmf_set_id.split("&")[0]
end

#count_expression_logical_branches(expression) ⇒ Object

Recursively look through an expression to count the logical branches



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/models/cql_measure.rb', line 140

def count_expression_logical_branches(expression)
  case expression
  when nil
    0
  when Array
    expression.map { |exp| count_expression_logical_branches(exp) }.sum
  when Hash
    case expression['type']
    when 'And', 'Or', 'Not'
      count_expression_logical_branches(expression['operand'])
    when 'Query'
      # TODO: Do we need to look into the source side of the query? Can there be logical operators there?
      count_expression_logical_branches(expression['where']) + count_expression_logical_branches(expression['relationship'])
    else
      1
    end
  else
    0
  end
end

#set_continuous_variableObject



121
122
123
124
125
126
127
128
# File 'lib/models/cql_measure.rb', line 121

def set_continuous_variable
  # The return value of this function is not related to whether or not this
  # measure is a CV measure. The true return value ensures false is not
  # accidentally returned here, which would cause the chain of 'before_*' to
  # stop executing.
  self.continuous_variable = populations.map {|x| x.keys}.flatten.uniq.include? HQMF::PopulationCriteria::MSRPOPL
  true
end

#value_setsObject



71
72
73
74
75
76
# File 'lib/models/cql_measure.rb', line 71

def value_sets
  options = { oid: value_set_oids }
  options[:user_id] = user.id if user?
  @value_sets ||= HealthDataStandards::SVS::ValueSet.in(options)
  @value_sets
end

#value_sets_by_oidObject



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/models/cql_measure.rb', line 78

def value_sets_by_oid
  @value_sets_by_oid = {}
  value_sets.each do |vs|
    if @value_sets_by_oid[vs.oid]
      # If there are multiple value sets with the same oid for the user, then keep the one with
      # the version corresponding to this measure.
      if vs.version.include?(hqmf_set_id)
        @value_sets_by_oid[vs.oid] = { vs.version => vs }
      end
    else
      @value_sets_by_oid[vs.oid] = { vs.version => vs }
    end
  end
  @value_sets_by_oid
end