Class: CQM::Converter::Utils

Inherits:
Object
  • Object
show all
Defined in:
lib/cqm/converter/utils.rb

Overview

CQM Converter class utilities.

Class Method Summary collapse

Class Method Details

.date_time_adjuster(results) ⇒ Object

Adjust improper date times from the cql_qdm_patientapi.



150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/cqm/converter/utils.rb', line 150

def self.date_time_adjuster(results)
  if results.is_a?(Hash) && results.key?('year') && results.key?('minute')
    DateTime.new(results['year'], results['month'], results['day'], results['hour'], results['minute'], results['second'], results['millisecond']).to_s
  elsif results.is_a?(Hash)
    results.each do |key, value|
      results[key] = date_time_adjuster(value)
    end
  elsif results.is_a?(Array)
    results.map! { |result| date_time_adjuster(result) }
  else
    results
  end
end

.fix_infinity_dates(results) ⇒ Object

Remove any ‘infinity’ dates. The cql_qdm_patientapi adds an end time of ‘infinity’ if an event does not have an end time. Remove this when converting back to HDS from QDM.



167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/cqm/converter/utils.rb', line 167

def self.fix_infinity_dates(results)
  if results.is_a?(Hash) && results.key?('end_time')
    results.delete('end_time') if results['end_time'].to_s == '253402300799'
  elsif results.is_a?(Hash)
    results.each do |key, value|
      results[key] = fix_infinity_dates(value)
    end
  elsif results.is_a?(Array)
    results.map! { |result| fix_infinity_dates(result) }
  else
    results
  end
end

.gather_qdm_model_attrsObject

This helper method looks at the current state of cqm-models, and builds a hash of datatype models and their attributes.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/cqm/converter/utils.rb', line 31

def self.gather_qdm_model_attrs
  qdm_model_attrs = {}
  QDM.constants.each do |model|
    if QDM.const_get(model).respond_to?('fields')
      qdm_model_attrs[model.to_s] = QDM.const_get(model).fields.keys.map! { |a| a.camelize(:lower) }
    end
    if QDM.const_get(model).respond_to?('embedded_relations')
      qdm_model_attrs[model.to_s].concat(QDM.const_get(model).embedded_relations.keys.map! { |a| a.camelize(:lower) })
    end
  end
  # TODO: These fields are currently not supported. See:
  # https://github.com/projecttacoma/cql_qdm_patientapi/search?q=does+not+currently+support
  qdm_model_attrs['SubstanceAdministered'].delete('frequency')
  qdm_model_attrs['SubstanceOrder'].delete('refills')
  qdm_model_attrs['PatientCharacteristicExpired'].delete('cause')
  qdm_model_attrs['MedicationDispensed'].delete('refills')
  qdm_model_attrs['MedicationDispensed'].delete('frequency')
  qdm_model_attrs['MedicationOrder'].delete('refills')
  qdm_model_attrs['MedicationOrder'].delete('frequency')
  qdm_model_attrs['MedicationActive'].delete('frequency')
  qdm_model_attrs['MedicationAdministered'].delete('frequency')
  qdm_model_attrs['MedicationDischarge'].delete('refills')
  qdm_model_attrs['MedicationDischarge'].delete('frequency')
  qdm_model_attrs
end

.gather_qdm_to_hds_mappings(qdm_model_attrs = nil) ⇒ Object

Parse the cql_qdm_patientapi datatypes to infer how to construct corresponding HDS entries.



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/cqm/converter/utils.rb', line 59

def self.gather_qdm_to_hds_mappings(qdm_model_attrs = nil)
  qdm_model_attrs = gather_qdm_model_attrs if qdm_model_attrs.nil?
  cql_qdm_patientapi_spec = Gem::Specification.find_by_name('cql_qdm_patientapi')
  datatypes = Dir.glob(cql_qdm_patientapi_spec.gem_dir + '/app/assets/javascripts/datatypes/*.coffee')
  # Read in all datatypes
  datatypes_contents = ''
  datatypes.each do |datatype|
    datatypes_contents += File.read(datatype) + "\n"
  end
  datatypes_contents += 'class'
  # Construct the mappings
  qdm_to_hds_mappings = {}
  qdm_model_attrs.each do |datatype, attributes|
    datatype_pattern = /#{datatype} extends CQL_QDM.QDMDatatype.*?class/m
    next unless (dc_class = datatype_pattern.match(datatypes_contents))
    qdm_to_hds_mappings[datatype] = {}
    attributes.each do |attribute|
      attribute_pattern = /@_#{attribute}(Low|High| ).*?@entry.*?$/
      dc_class.to_s.to_enum(:scan, attribute_pattern).map do
        dc_attr = Regexp.last_match
        # Handle possible mixed values.
        if dc_attr.to_s.include? 'Low'
          qdm_to_hds_mappings[datatype][attribute] = {} unless qdm_to_hds_mappings[datatype][attribute]
          qdm_to_hds_mappings[datatype][attribute][:low] = dc_attr.to_s[/@entry.(.*?)(\)|$|\?)/m, 1]
        elsif dc_attr.to_s.include? 'High'
          qdm_to_hds_mappings[datatype][attribute] = {} unless qdm_to_hds_mappings[datatype][attribute]
          qdm_to_hds_mappings[datatype][attribute][:high] = dc_attr.to_s[/@entry.(.*?)(\)|$|\?)/m, 1]
        else
          qdm_to_hds_mappings[datatype][attribute] = dc_attr.to_s[/@entry.(.*?)(\)|$|\?)/m, 1]
        end
      end
    end
  end
  qdm_to_hds_mappings
end

.hds_codes_to_qdm_codes(hds_codes) ⇒ Object

Convert HDS codes structure to QDM codes structure.



19
20
21
22
23
24
25
26
27
# File 'lib/cqm/converter/utils.rb', line 19

def self.hds_codes_to_qdm_codes(hds_codes)
  qdm_codes = []
  hds_codes.each do |code_system, codes|
    codes.each do |code|
      qdm_codes << { codeSystem: code_system, code: code }
    end
  end
  qdm_codes
end

.hds_to_qdm_js(js_dependencies, record, qdm_model_attrs) ⇒ Object

Builds JavaScript to assist the HDS Record to QDM Patient conversion.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/cqm/converter/utils.rb', line 96

def self.hds_to_qdm_js(js_dependencies, record, qdm_model_attrs)
  record_json = JSON.parse(record.to_json)
  # Bonnie changes start_date and end_date in the front end before calculation,
  # and this is what is expected by the cql_qdm_patientapi, so make that change
  # before generating the executable JavaScript.
  record_json = record_json.deep_transform_keys { |key| key.to_s == 'start_date' ? 'start_time' : key }
  record_json = record_json.deep_transform_keys { |key| key.to_s == 'end_date' ? 'end_time' : key }
  "    window = {};\n    \#{js_dependencies};\n    function PatientWrapper() {\n    }\n    PatientWrapper.prototype.get = function(attr) {\n      const contents = \#{record_json.to_json};\n      return contents[attr];\n    }\n    cql = window.cql;\n    patient = new CQL_QDM.CQLPatient(new PatientWrapper());\n    raw_datatypes = patient.buildDatatypes();\n    qdm_model_attrs = \#{qdm_model_attrs.to_json};\n    processed_datatypes = {};\n    // Loop over each QDM datatype.\n    Object.keys(raw_datatypes).forEach(function(key) {\n      processed_datatypes[key] = [];\n      // Collect the values of the QDM attributes.\n      raw_datatypes[key].forEach(function(datatype) {\n        results = {};\n        qdm_model_attrs[datatype.constructor.name].forEach(function(method) {\n          // Call the datatype attribute method to get its value.\n          if (datatype[method]) {\n            result = datatype[method]();\n            // Handle CQL execution engine type results.\n            if (result && result['toJSON']) {\n              results[method] = result.toJSON();\n            } else {\n              results[method] = result;\n            }\n          }\n        });\n        // Add codes to result.\n        results['dataElementCodes'] = datatype['getCode']();\n        // Add description to result.\n        results['description'] = datatype['entry']['description'];\n        // Add oid to result.\n        results['hqmfOid'] = datatype['entry']['oid'];\n\n        processed_datatypes[key].push(results);\n      });\n    });\n    return processed_datatypes;\n  JS\nend\n"

.qdm_codes_to_hds_codes(qdm_codes) ⇒ Object

Convert QDM codes structure to HDS codes structure.



6
7
8
9
10
11
12
13
14
15
16
# File 'lib/cqm/converter/utils.rb', line 6

def self.qdm_codes_to_hds_codes(qdm_codes)
  codes = {}
  qdm_codes.each do |qdm_code|
    qdm_code = qdm_code.stringify_keys
    code_system = qdm_code['codeSystem']
    code_system = qdm_code['code_system'] if qdm_code['code_system']
    codes[code_system] = [] unless codes.key? code_system
    codes[code_system] << qdm_code['code'] if qdm_code['code']
  end
  codes
end

.qdm_to_hds_class_type(category) ⇒ Object

Helper method to handle mismatched HDS Class names for QDM things.



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/cqm/converter/utils.rb', line 182

def self.qdm_to_hds_class_type(category)
  if category.to_s.include? 'diagnostic'
    'procedure'
  elsif category.to_s.include? 'physical_exam'
    'procedure'
  elsif category.to_s.include? 'intervention'
    'procedure'
  elsif category.to_s.include? 'device'
    'medical_equipment'
  elsif category.to_s.include? 'laboratory'
    'vital_sign'
  elsif category.to_s.include? 'substance'
    'medication'
  elsif category.to_s.include? 'immunization'
    'medication'
  else
    category
  end
end