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



64
65
66
# File 'lib/models/cql_measure.rb', line 64

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



112
113
114
# File 'lib/models/cql_measure.rb', line 112

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



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

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



131
132
133
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
# File 'lib/models/cql_measure.rb', line 131

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

#count_expression_logical_branches(expression) ⇒ Object

Recursively look through an expression to count the logical branches



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

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



118
119
120
121
122
123
124
125
# File 'lib/models/cql_measure.rb', line 118

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



68
69
70
71
72
73
# File 'lib/models/cql_measure.rb', line 68

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



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/models/cql_measure.rb', line 75

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