cqm-parsers 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +29 -0
- data/README.md +21 -0
- data/Rakefile +19 -0
- data/lib/ext/code.rb +10 -0
- data/lib/ext/data_element.rb +24 -0
- data/lib/hqmf-model/attribute.rb +63 -0
- data/lib/hqmf-model/data_criteria.rb +467 -0
- data/lib/hqmf-model/document.rb +253 -0
- data/lib/hqmf-model/population_criteria.rb +102 -0
- data/lib/hqmf-model/precondition.rb +94 -0
- data/lib/hqmf-model/types.rb +457 -0
- data/lib/hqmf-model/utilities.rb +52 -0
- data/lib/hqmf-parser.rb +116 -0
- data/lib/hqmf-parser/1.0/attribute.rb +121 -0
- data/lib/hqmf-parser/1.0/comparison.rb +34 -0
- data/lib/hqmf-parser/1.0/data_criteria.rb +92 -0
- data/lib/hqmf-parser/1.0/document.rb +195 -0
- data/lib/hqmf-parser/1.0/expression.rb +60 -0
- data/lib/hqmf-parser/1.0/observation.rb +61 -0
- data/lib/hqmf-parser/1.0/population_criteria.rb +75 -0
- data/lib/hqmf-parser/1.0/precondition.rb +90 -0
- data/lib/hqmf-parser/1.0/range.rb +76 -0
- data/lib/hqmf-parser/1.0/restriction.rb +162 -0
- data/lib/hqmf-parser/1.0/utilities.rb +55 -0
- data/lib/hqmf-parser/2.0/data_criteria.rb +372 -0
- data/lib/hqmf-parser/2.0/data_criteria_helpers/dc_base_extract.rb +80 -0
- data/lib/hqmf-parser/2.0/data_criteria_helpers/dc_definition_from_template_or_type_extract.rb +201 -0
- data/lib/hqmf-parser/2.0/data_criteria_helpers/dc_post_processing.rb +85 -0
- data/lib/hqmf-parser/2.0/data_criteria_helpers/dc_specific_occurrences_and_source_data_criteria_extract.rb +117 -0
- data/lib/hqmf-parser/2.0/document.rb +304 -0
- data/lib/hqmf-parser/2.0/document_helpers/doc_population_helper.rb +173 -0
- data/lib/hqmf-parser/2.0/document_helpers/doc_utilities.rb +131 -0
- data/lib/hqmf-parser/2.0/field_value_helper.rb +251 -0
- data/lib/hqmf-parser/2.0/population_criteria.rb +134 -0
- data/lib/hqmf-parser/2.0/precondition.rb +73 -0
- data/lib/hqmf-parser/2.0/source_data_criteria_helper.rb +112 -0
- data/lib/hqmf-parser/2.0/types.rb +448 -0
- data/lib/hqmf-parser/2.0/utilities.rb +45 -0
- data/lib/hqmf-parser/2.0/value_set_helper.rb +104 -0
- data/lib/hqmf-parser/converter/pass1/data_criteria_converter.rb +257 -0
- data/lib/hqmf-parser/converter/pass1/document_converter.rb +133 -0
- data/lib/hqmf-parser/converter/pass1/population_criteria_converter.rb +185 -0
- data/lib/hqmf-parser/converter/pass1/precondition_converter.rb +173 -0
- data/lib/hqmf-parser/converter/pass1/precondition_extractor.rb +201 -0
- data/lib/hqmf-parser/converter/pass1/simple_data_criteria.rb +26 -0
- data/lib/hqmf-parser/converter/pass1/simple_operator.rb +89 -0
- data/lib/hqmf-parser/converter/pass1/simple_population_criteria.rb +10 -0
- data/lib/hqmf-parser/converter/pass1/simple_precondition.rb +51 -0
- data/lib/hqmf-parser/converter/pass1/simple_restriction.rb +64 -0
- data/lib/hqmf-parser/converter/pass2/comparison_converter.rb +112 -0
- data/lib/hqmf-parser/converter/pass2/operator_converter.rb +102 -0
- data/lib/hqmf-parser/cql/data_criteria.rb +57 -0
- data/lib/hqmf-parser/cql/data_criteria_helpers/dc_definition_from_template_or_type_extract.rb +79 -0
- data/lib/hqmf-parser/cql/data_criteria_helpers/dc_post_processing.rb +43 -0
- data/lib/hqmf-parser/cql/document.rb +78 -0
- data/lib/hqmf-parser/cql/document_helpers/doc_population_helper.rb +124 -0
- data/lib/hqmf-parser/cql/value_set_helper.rb +103 -0
- data/lib/hqmf-parser/parser.rb +100 -0
- data/lib/qrda-export/catI-r5/qrda1_r5.rb +125 -0
- data/lib/qrda-export/helper/cat_1_view_helper.rb +142 -0
- data/lib/qrda-export/helper/code_system_helper.rb +77 -0
- data/lib/qrda-export/helper/date_helper.rb +81 -0
- data/lib/qrda-import/base-importers/demographics_importer.rb +47 -0
- data/lib/qrda-import/base-importers/medication_importer.rb +22 -0
- data/lib/qrda-import/base-importers/section_importer.rb +196 -0
- data/lib/qrda-import/cda_identifier.rb +19 -0
- data/lib/qrda-import/data-element-importers/adverse_event_importer.rb +23 -0
- data/lib/qrda-import/data-element-importers/allergy_intolerance_importer.rb +21 -0
- data/lib/qrda-import/data-element-importers/assessment_performed_importer.rb +23 -0
- data/lib/qrda-import/data-element-importers/communication_from_patient_to_provider_importer.rb +18 -0
- data/lib/qrda-import/data-element-importers/communication_from_provider_to_patient_importer.rb +18 -0
- data/lib/qrda-import/data-element-importers/communication_from_provider_to_provider_importer.rb +20 -0
- data/lib/qrda-import/data-element-importers/device_applied_importer.rb +23 -0
- data/lib/qrda-import/data-element-importers/device_order_importer.rb +18 -0
- data/lib/qrda-import/data-element-importers/diagnosis_importer.rb +23 -0
- data/lib/qrda-import/data-element-importers/diagnostic_study_order_importer.rb +20 -0
- data/lib/qrda-import/data-element-importers/diagnostic_study_performed_importer.rb +30 -0
- data/lib/qrda-import/data-element-importers/encounter_order_importer.rb +20 -0
- data/lib/qrda-import/data-element-importers/encounter_performed_importer.rb +41 -0
- data/lib/qrda-import/data-element-importers/immunization_administered_importer.rb +18 -0
- data/lib/qrda-import/data-element-importers/intervention_order_importer.rb +18 -0
- data/lib/qrda-import/data-element-importers/intervention_performed_importer.rb +22 -0
- data/lib/qrda-import/data-element-importers/laboratory_test_order_importer.rb +20 -0
- data/lib/qrda-import/data-element-importers/laboratory_test_performed_importer.rb +28 -0
- data/lib/qrda-import/data-element-importers/medication_active_importer.rb +17 -0
- data/lib/qrda-import/data-element-importers/medication_administered_importer.rb +17 -0
- data/lib/qrda-import/data-element-importers/medication_discharge_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/medication_dispensed_importer.rb +19 -0
- data/lib/qrda-import/data-element-importers/medication_order_importer.rb +16 -0
- data/lib/qrda-import/data-element-importers/patient_characteristic_expired.rb +21 -0
- data/lib/qrda-import/data-element-importers/physical_exam_performed_importer.rb +26 -0
- data/lib/qrda-import/data-element-importers/procedure_order_importer.rb +26 -0
- data/lib/qrda-import/data-element-importers/procedure_performed_importer.rb +34 -0
- data/lib/qrda-import/data-element-importers/substance_administered_importer.rb +16 -0
- data/lib/qrda-import/entry_finder.rb +20 -0
- data/lib/qrda-import/entry_package.rb +16 -0
- data/lib/qrda-import/narrative_reference_handler.rb +33 -0
- data/lib/qrda-import/patient_importer.rb +105 -0
- data/lib/util/code_system_helper.rb +76 -0
- data/lib/util/counter.rb +20 -0
- data/lib/util/hqmf_template_helper.rb +39 -0
- metadata +340 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6f44d77fe47f440f802946c4fc454de11d4fd69e
|
4
|
+
data.tar.gz: e1f87b52ea314452ade5bfd6c4ef5cc17c819384
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6feea91c08a04843dfad7119461b608986650fea25f69723a186397dc378727d0c5689e53ae56405f0762bb2f2320a12ee0f27c6b9b37c7243cc5b56760b7cb2
|
7
|
+
data.tar.gz: 1ed3943b864ec0c33c1041bf1c27d402e960e7f850eb5a494d6d84cc9217eb1ae266a339c6d83e1d200a235070f793ee1cc174b5b21996def39a04f910af0451
|
data/Gemfile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gemspec :development_group => :test
|
4
|
+
|
5
|
+
gem 'mustache'
|
6
|
+
gem 'cqm-models', '~> 0.8.2'
|
7
|
+
gem 'mongoid', '~> 5.0.0'
|
8
|
+
|
9
|
+
group :development, :test do
|
10
|
+
gem 'bundler-audit'
|
11
|
+
gem 'rubocop', '~> 0.52.1', require: false
|
12
|
+
end
|
13
|
+
|
14
|
+
group :development do
|
15
|
+
gem 'rake'
|
16
|
+
gem 'byebug', '~> 6.0.2', platforms: [:ruby_20, :ruby_21, :ruby_22, :ruby_23]
|
17
|
+
end
|
18
|
+
|
19
|
+
group :test do
|
20
|
+
gem 'factory_girl', '~> 4.1.0'
|
21
|
+
gem "tailor", '~> 1.1.2'
|
22
|
+
gem "cane", '~> 2.3.0'
|
23
|
+
gem 'simplecov', :require => false
|
24
|
+
gem 'webmock'
|
25
|
+
gem 'minitest', '~> 5.3'
|
26
|
+
gem 'minitest-reporters'
|
27
|
+
gem 'awesome_print', :require => 'ap'
|
28
|
+
gem 'simplexml_parser', :git => 'https://github.com/projecttacoma/simplexml_parser.git', :branch => 'master'
|
29
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
cqm-parsers
|
2
|
+
===========
|
3
|
+
|
4
|
+
This project contains libraries for parsing HQMF documents.
|
5
|
+
|
6
|
+
License
|
7
|
+
=======
|
8
|
+
|
9
|
+
Copyright 2018 The MITRE Corporation
|
10
|
+
|
11
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
12
|
+
you may not use this file except in compliance with the License.
|
13
|
+
You may obtain a copy of the License at
|
14
|
+
|
15
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
16
|
+
|
17
|
+
Unless required by applicable law or agreed to in writing, software
|
18
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
19
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
20
|
+
See the License for the specific language governing permissions and
|
21
|
+
limitations under the License.
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'cane/rake_task'
|
3
|
+
require "simplecov"
|
4
|
+
|
5
|
+
import 'lib/tasks/hqmf.rake'
|
6
|
+
|
7
|
+
Rake::TestTask.new(:test_unit) do |t|
|
8
|
+
t.libs << "test"
|
9
|
+
t.test_files = FileList['test/**/*_test.rb']
|
10
|
+
t.verbose = false
|
11
|
+
t.warning = false
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
task :test => [:test_unit] do
|
17
|
+
|
18
|
+
system("open coverage/index.html")
|
19
|
+
end
|
data/lib/ext/code.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module QDM
|
2
|
+
class DataElement
|
3
|
+
def merge!(other)
|
4
|
+
# ensure they're the same category (e.g. 'encounter')
|
5
|
+
return unless category == other.category
|
6
|
+
|
7
|
+
# ensure they're the same status (e.g. 'performed'), and that they both have a status set (or that they both don't)
|
8
|
+
return if respond_to?(:qdmStatus) && !other.respond_to?(:qdmStatus)
|
9
|
+
return if !respond_to?(:qdmStatus) && other.respond_to?(:qdmStatus)
|
10
|
+
return if respond_to?(:qdmStatus) && other.respond_to?(:qdmStatus) && qdmStatus != other.qdmStatus
|
11
|
+
|
12
|
+
# iterate over non-code fields
|
13
|
+
fields.each_key do |field|
|
14
|
+
next if field[0] == '_' || %w[dataElementCodes category qdmVersion qdmStatus].include?(field)
|
15
|
+
|
16
|
+
if send(field).nil?
|
17
|
+
send(field + '=', other.send(field))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
self.dataElementCodes = dataElementCodes.concat(other.dataElementCodes).uniq
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module HQMF
|
2
|
+
class Attribute
|
3
|
+
include HQMF::Conversion::Utilities
|
4
|
+
attr_reader :id,:code,:value,:unit,:name,:id_obj,:code_obj,:value_obj
|
5
|
+
# @param [String] id
|
6
|
+
# @param [String] code
|
7
|
+
# @param [String] value
|
8
|
+
# @param [String] unit
|
9
|
+
# @param [String] name
|
10
|
+
# @param [HQMF::Identifier] id_obj
|
11
|
+
# @param [HQMF::Coded] code_obj
|
12
|
+
# @param [Object] value_obj
|
13
|
+
def initialize(id,code,value,unit,name,id_obj=nil,code_obj=nil,value_obj=nil)
|
14
|
+
@id = id
|
15
|
+
@code = code
|
16
|
+
@value = value
|
17
|
+
@unit = unit
|
18
|
+
@name = name
|
19
|
+
# enhanced model
|
20
|
+
@id_obj = id_obj
|
21
|
+
@code_obj = code_obj
|
22
|
+
@value_obj = value_obj
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.from_json(json)
|
26
|
+
json = json.with_indifferent_access
|
27
|
+
|
28
|
+
id = json["id"] if json["id"]
|
29
|
+
code = json["code"] if json["code"]
|
30
|
+
value = json["value"] if json["value"]
|
31
|
+
unit = json["unit"] if json["unit"]
|
32
|
+
name = json["name"] if json["name"]
|
33
|
+
# enhanced model
|
34
|
+
id_obj = HQMF::Identifier::from_json(json["id_obj"]) if json["id_obj"]
|
35
|
+
code_obj = HQMF::Coded::from_json(json["code_obj"]) if json["code_obj"]
|
36
|
+
value_obj = nil
|
37
|
+
if (json["value_obj"])
|
38
|
+
json_value = json["value_obj"].with_indifferent_access
|
39
|
+
case json_value["type"]
|
40
|
+
when 'II'
|
41
|
+
value_obj = HQMF::Identifier::from_json(json_value)
|
42
|
+
when 'CD'
|
43
|
+
value_obj = HQMF::Coded::from_json(json_value)
|
44
|
+
when 'ED'
|
45
|
+
value_obj = HQMF::ED::from_json(json_value)
|
46
|
+
else
|
47
|
+
value_obj = json_value["value"].nil? ? HQMF::AnyValue::from_json(json_value) : HQMF::GenericValueContainer::from_json(json_value)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
HQMF::Attribute.new(id,code,value,unit,name,id_obj,code_obj,value_obj)
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_json
|
55
|
+
json = build_hash(self, [:id,:code,:value,:unit,:name])
|
56
|
+
json[:id_obj] = @id_obj.to_json if @id_obj
|
57
|
+
json[:code_obj] = @code_obj.to_json if @code_obj
|
58
|
+
json[:value_obj] = @value_obj.to_json if @value_obj
|
59
|
+
json
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,467 @@
|
|
1
|
+
module HQMF
|
2
|
+
# Represents a data criteria specification
|
3
|
+
class DataCriteria
|
4
|
+
|
5
|
+
include HQMF::Conversion::Utilities
|
6
|
+
|
7
|
+
SOURCE_DATA_CRITERIA_TEMPLATE_ID = '2.16.840.1.113883.3.100.1.1'
|
8
|
+
SOURCE_DATA_CRITERIA_TEMPLATE_TITLE = 'Source data criteria'
|
9
|
+
|
10
|
+
XPRODUCT = 'XPRODUCT'
|
11
|
+
UNION = 'UNION'
|
12
|
+
INTERSECT = 'INTERSECT'
|
13
|
+
|
14
|
+
SATISFIES_ALL = 'satisfies_all'
|
15
|
+
SATISFIES_ANY = 'satisfies_any'
|
16
|
+
VARIABLE = 'variable'
|
17
|
+
|
18
|
+
# An object containing metadata information for all attributes that are used within the measure data criteria being parsed.
|
19
|
+
#
|
20
|
+
# fields include:
|
21
|
+
# `title`: The QDM human readable title for the attribute.
|
22
|
+
# `coded_entry_method`: this appears to be a way that fields here are referenced within Bonnie.
|
23
|
+
# `field_type`: The type of whatever will be stored for this attribute. This will often be `:timestamp` or `:value`.
|
24
|
+
# `code`: The code for the entry. This should be included to make HQMF generation work properly. This is whatever code is dictated in the HQMF. For Diagnosis, this is in [HQMF QDM IG](http://www.hl7.org/implement/standards/product_brief.cfm?product_id=346) vol 2 page 155 and is `29308-4`.
|
25
|
+
# `code_system`: This is the oid for whatever code system contains `code`. For Diagnosis, this is LOINC: `2.16.840.1.113883.6.1`. This is also located at (http://www.hl7.org/implement/standards/product_brief.cfm?product_id=346) vol 2 page 155.
|
26
|
+
# `template_id`: These appear to be related to HQMFr1 template ids. These appear to be dangerously out of date. Don't use.
|
27
|
+
FIELDS = {'ABATEMENT_DATETIME' => {title:'Abatement Datetime', coded_entry_method: :end_date, field_type: :timestamp},
|
28
|
+
'ACTIVE_DATETIME' => {title:'Active Date/Time', coded_entry_method: :active_date_time, field_type: :timestamp},
|
29
|
+
'ADMISSION_DATETIME' => {title:'Admission Date/Time', coded_entry_method: :admit_time, code: '399423000', code_system:'2.16.840.1.113883.6.96', field_type: :timestamp},
|
30
|
+
# QDM 5.0 addition. This is the same as FACILITY_LOCATION.
|
31
|
+
# TODO: (LDY 10/5/2016) this is a new attribute from QDM 5.0. We do not yet have the code or template_id for this. This should be updated when we do.
|
32
|
+
'ADMISSION_SOURCE' => {title:'Admission Source', coded_entry_method: :admission_source, field_type: :value},
|
33
|
+
'ANATOMICAL_APPROACH_SITE' => {title:'Anatomical Approach Site', coded_entry_method: :anatomical_approach, field_type: :value},
|
34
|
+
'ANATOMICAL_LOCATION_SITE' => {title:'Anatomical Location Site', coded_entry_method: :anatomical_location, field_type: :value},
|
35
|
+
'ANATOMICAL_STRUCTURE' => {title:'Anatomical Structure', coded_entry_method: :anatomical_structure, code: '91723000', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.3.560.1.1000.2', field_type: :value},
|
36
|
+
'CAUSE' => {title:'Cause', coded_entry_method: :cause_of_death, code: '42752001', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.3.560.1.1017.2', field_type: :value},
|
37
|
+
# TODO: Determine actual code and code_system for component attribute
|
38
|
+
'COMPONENT' => {title: 'Component', coded_entry_method: :components, field_type: :value},
|
39
|
+
'CUMULATIVE_MEDICATION_DURATION' => {title:'Cumulative Medication Duration', coded_entry_method: :cumulative_medication_duration, code: '261773006', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.3.560.1.1001.3', field_type: :value},
|
40
|
+
# MISSING Date - The date that the patient passed away. - Patient Characteristic Expired
|
41
|
+
'DIAGNOSIS' => {title:'Diagnosis', coded_entry_method: :diagnosis, field_type: :value},
|
42
|
+
'DISCHARGE_DATETIME' => {title:'Discharge Date/Time', coded_entry_method: :discharge_time, code: '442864001', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.3.560.1.1025.1', field_type: :timestamp},
|
43
|
+
# TODO: (LDY 10/5/2016) this changed from "discharge status" to "discharge disposition". likely there is a code and template id change necessary. these are not yet known.
|
44
|
+
'DISCHARGE_STATUS' => {title:'Discharge Disposition', coded_entry_method: :discharge_disposition, code: '309039003', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.3.560.1.1003.2', field_type: :value},
|
45
|
+
# TODO: (LDY 10/4/2016) this changed from "dose" to "dosage". it's possible that there's another code associated with this. this code was not available at the time of this change.
|
46
|
+
'DOSE' => {title:'Dosage', coded_entry_method: :dose, code: '398232005', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.3.560.1.1004.1', field_type: :value},
|
47
|
+
'FACILITY_LOCATION' => {title:'Facility Location', coded_entry_method: :facility, code: 'SDLOC', field_type: :value},
|
48
|
+
# TODO: (LDY 10/5/2016) this changed from 'facility arrival/departure' to 'location period'. likely there is a code and template id change necessary. these are not yet known.
|
49
|
+
'FACILITY_LOCATION_ARRIVAL_DATETIME' => {title:'Location Period Start Date/Time', coded_entry_method: :facility_arrival, code: 'SDLOC_ARRIVAL', field_type: :nested_timestamp},
|
50
|
+
'FACILITY_LOCATION_DEPARTURE_DATETIME' => {title:'Location Period End Date/Time', coded_entry_method: :facility_departure, code: 'SDLOC_DEPARTURE', field_type: :nested_timestamp},
|
51
|
+
'FREQUENCY' => {title:'Frequency', coded_entry_method: :administration_timing, code: '307430002', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.3.560.1.1006.1', field_type: :value},
|
52
|
+
'HEALTH_RECORD_FIELD' => {title: 'Health Record Field', coded_entry_method: :health_record_field, code: '395676008', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.10.20.28.3.102:2014-11-24', field_type: :value},
|
53
|
+
'INCISION_DATETIME' => {title:'Incision Date/Time', coded_entry_method: :incision_time, code: '34896006', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.10.20.24.3.89', field_type: :timestamp},
|
54
|
+
'LATERALITY' => {title:'Laterality', coded_entry_method: :laterality, code: '272741003', code_system:'2.16.840.1.113883.6.96', template_id: '', field_type: :value},
|
55
|
+
'LENGTH_OF_STAY' => {title:'Length of Stay', coded_entry_method: :length_of_stay, code: '183797002', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.3.560.1.1029.3', field_type: :value},
|
56
|
+
'METHOD' => {title:'Method', coded_entry_method: :method, template_id: '', field_type: :value},
|
57
|
+
# Negation Rationale isn't encoded
|
58
|
+
'ONSET_AGE' => {title:'Onset Age', coded_entry_method: :onset_age, code: '445518008', code_system:'2.16.840.1.113883.6.96', template_id: '', field_type: :value},
|
59
|
+
'ONSET_DATETIME' => {title:'Onset Datetime', coded_entry_method: :start_date, field_type: :timestamp},
|
60
|
+
'ORDINAL' => {title:'Ordinality', coded_entry_method: :ordinality, code: '117363000', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.3.560.1.1012.2', field_type: :value}, # previous
|
61
|
+
'ORDINALITY' => {title:'Ordinality', coded_entry_method: :ordinality, code: '117363000', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.3.560.1.1012.2', field_type: :value},
|
62
|
+
'PATIENT_PREFERENCE' => {title:'Patient Preference', coded_entry_method: :patient_preference, code: 'PAT', code_system: '2.16.840.1.113883.5.8', template_id: '2.16.840.1.113883.10.20.24.3.83', field_type: :value},
|
63
|
+
'PRINCIPAL_DIAGNOSIS' => {title:'Principal Diagnosis', coded_entry_method: :principal_diagnosis, field_type: :value},
|
64
|
+
'PROVIDER_PREFERENCE' => {title:'Provider Preference', coded_entry_method: :provider_preference, code: '103323008', code_system: '2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.10.20.24.3.84', field_type: :value},
|
65
|
+
'RADIATION_DOSAGE' => {title:'Radiation Dosage', coded_entry_method: :radiation_dose, code: '228815006', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.10.20.24.3.91', field_type: :value},
|
66
|
+
'RADIATION_DURATION' => {title:'Radiation Duration', coded_entry_method: :radiation_duration, code: '306751006', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.10.20.24.3.91', field_type: :value},
|
67
|
+
'REACTION'=> {title:'Reaction', coded_entry_method: :reaction, code: '263851003', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.10.20.24.3.85', field_type: :value},
|
68
|
+
'REASON' => {title:'Reason', coded_entry_method: :reason, code: '410666004', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.10.20.24.3.88', field_type: :value},
|
69
|
+
'RECORDED_DATETIME' => {title:'Recorded Datetime', coded_entry_method: :start_date, field_type: :timestamp},
|
70
|
+
'REFERENCE_RANGE_HIGH' => {title:'Reference Range - High', coded_entry_method: :reference_range_high, field_type: :value},
|
71
|
+
'REFERENCE_RANGE_LOW' => {title:'Reference Range - Low', coded_entry_method: :reference_range_low, field_type: :value},
|
72
|
+
'REFILLS' => {title:'Refills', coded_entry_method: :refills, field_type: :value},
|
73
|
+
'RELATED_TO' => {title:'Related To', coded_entry_method: :related_to, code: 'REL', codeSystem: '2.16.840.1.113883.1.11.11603', field_type: :value},
|
74
|
+
'RELATIONSHIP' => {title:'Relationship', coded_entry_method: :relationship_to_patient, field_type: :value},
|
75
|
+
'REMOVAL_DATETIME' => {title:'Removal Date/Time', coded_entry_method: :removal_time, code: '118292001', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.3.560.1.1032.1', field_type: :timestamp},
|
76
|
+
# Result isn't encoded
|
77
|
+
# TODO: (LDY 10/4/2016) RESULT_DATETIME is a new attribute in QDM 5.0. We do not yet have codes/template information for this.
|
78
|
+
'RESULT_DATETIME' => {title:'Result Date/Time', coded_entry_method: :result_date_time, field_type: :timestamp},
|
79
|
+
'ROUTE' => {title:'Route', coded_entry_method: :route, code: '263513008', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.3.560.1.1020.2', field_type: :value},
|
80
|
+
'SEVERITY' => {title:'Severity', coded_entry_method: :severity, code: 'SEV', code_system:'2.16.840.1.113883.5.4', template_id: '2.16.840.1.113883.10.20.22.4.8', field_type: :value},
|
81
|
+
'SIGNED_DATETIME' => {title:'Signed Date/Time', coded_entry_method: :signed_date_time, field_type: :timestamp},
|
82
|
+
'START_DATETIME' => {title:'Start Date/Time', coded_entry_method: :start_date, code: '398201009', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.3.560.1.1027.1', field_type: :timestamp},
|
83
|
+
# STATUS is referenced in the code as `qdm_status` because entry/Record already has a `status`/`status_code` field which has a different meaning
|
84
|
+
'STATUS' => {title: 'Status', coded_entry_method: :qdm_status, code: '33999-4', code_system:'2.16.840.1.113883.6.1', field_type: :value},
|
85
|
+
'STOP_DATETIME' => {title:'Stop Date/Time', coded_entry_method: :end_date, code: '397898000', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.3.560.1.1026.1', field_type: :timestamp},
|
86
|
+
# TODO: (LDY 10/4/2016) SUPPLY is a new attribute in QDM 5.0. We do not yet have codes/template information for this.
|
87
|
+
'SUPPLY' => {title:'Supply', coded_entry_method: :supply, field_type: :value},
|
88
|
+
'TARGET_OUTCOME' => {title:'Target Outcome', coded_entry_method: :target_outcome, code: '385676005', code_system:'2.16.840.1.113883.6.96', template_id: '', field_type: :value},
|
89
|
+
# MISSING Time - The time that the patient passed away
|
90
|
+
|
91
|
+
# Custom field values
|
92
|
+
# QDM 5.3 Update: "Related To" replaces Fulfills. We are keeping the fulfills code and only make changes to the UI.
|
93
|
+
'FLFS' => {title:'Related To', coded_entry_method: :fulfills, code: 'FLFS', field_type: :reference},
|
94
|
+
'SOURCE' => {title:'Source', coded_entry_method: :source, code: '260753009', code_system:'2.16.840.1.113883.6.96', template_id: '2.16.840.1.113883.3.560.1.2001.2', field_type: :value},
|
95
|
+
'TRANSFER_FROM' => {title:'Transfer From', coded_entry_method: :transfer_from, code: 'TRANSFER_FROM', template_id: '2.16.840.1.113883.10.20.24.3.81', field_type: :value},
|
96
|
+
'TRANSFER_FROM_DATETIME' => {title:'Transfer From Date/Time', coded_entry_method: :transfer_from_time, code: 'ORG_TIME', template_id: '2.16.840.1.113883.10.20.24.3.81', field_type: :nested_timestamp},
|
97
|
+
'TRANSFER_TO' => {title:'Transfer To', coded_entry_method: :transfer_to, code: 'TRANSFER_TO', template_id: '2.16.840.1.113883.10.20.24.3.82', field_type: :value},
|
98
|
+
'TRANSFER_TO_DATETIME' => {title:'Transfer To Date/Time', coded_entry_method: :transfer_to_time, code: 'DST_TIME', template_id: '2.16.840.1.113883.10.20.24.3.82', field_type: :nested_timestamp}
|
99
|
+
}
|
100
|
+
|
101
|
+
# maps attribute codes to the attribute keys
|
102
|
+
VALUE_FIELDS = {'399423000' => 'ADMISSION_DATETIME',
|
103
|
+
'42752001' => 'CAUSE',
|
104
|
+
'261773006' => 'CUMULATIVE_MEDICATION_DURATION',
|
105
|
+
'363819003' => 'CUMULATIVE_MEDICATION_DURATION', # previous
|
106
|
+
'442864001' => 'DISCHARGE_DATETIME',
|
107
|
+
'309039003' => 'DISCHARGE_STATUS',
|
108
|
+
'398232005' => 'DOSE',
|
109
|
+
'SDLOC' => 'FACILITY_LOCATION',
|
110
|
+
'SDLOC_ARRIVAL' => 'FACILITY_LOCATION_ARRIVAL_DATETIME',
|
111
|
+
'SDLOC_DEPARTURE' => 'FACILITY_LOCATION_DEPARTURE_DATETIME',
|
112
|
+
'307430002' => 'FREQUENCY',
|
113
|
+
'260864003' => 'FREQUENCY', # previous
|
114
|
+
'395676008' => 'HEALTH_RECORD_FIELD',
|
115
|
+
'34896006' => 'INCISION_DATETIME',
|
116
|
+
'272741003' => 'LATERALITY',
|
117
|
+
'183797002' => 'LENGTH_OF_STAY',
|
118
|
+
'445518008' => 'ONSET_AGE',
|
119
|
+
'117363000' => 'ORDINALITY',
|
120
|
+
'PAT' => 'PATIENT_PREFERENCE',
|
121
|
+
'103323008' => 'PROVIDER_PREFERENCE',
|
122
|
+
'228815006' => 'RADIATION_DOSAGE',
|
123
|
+
'306751006' => 'RADIATION_DURATION',
|
124
|
+
'263851003' => 'REACTION',
|
125
|
+
'410666004' => 'REASON',
|
126
|
+
'REL' => 'RELATED_TO',
|
127
|
+
'118292001' => 'REMOVAL_DATETIME',
|
128
|
+
'263513008' => 'ROUTE',
|
129
|
+
'SEV' => 'SEVERITY',
|
130
|
+
'398201009' => 'START_DATETIME',
|
131
|
+
'33999-4' => 'STATUS',
|
132
|
+
'397898000' => 'STOP_DATETIME',
|
133
|
+
'385676005' => 'TARGET_OUTCOME',
|
134
|
+
|
135
|
+
# Custom field values
|
136
|
+
'91723000' => 'ANATOMICAL_STRUCTURE',
|
137
|
+
'FLFS' => 'FLFS',
|
138
|
+
'260753009' => 'SOURCE',
|
139
|
+
'TRANSFER_FROM' => 'TRANSFER_FROM',
|
140
|
+
'ORG_TIME' => 'TRANSFER_FROM_DATETIME',
|
141
|
+
'TRANSFER_TO' => 'TRANSFER_TO',
|
142
|
+
'DST_TIME' => 'TRANSFER_TO_DATETIME'
|
143
|
+
|
144
|
+
}
|
145
|
+
|
146
|
+
|
147
|
+
attr_reader :title, :description, :code_list_id, :derivation_operator , :specific_occurrence, :specific_occurrence_const, :source_data_criteria, :variable
|
148
|
+
attr_accessor :id, :value, :field_values, :children_criteria, :effective_time, :status, :temporal_references, :subset_operators, :definition, :inline_code_list, :negation_code_list_id, :negation, :display_name, :comments
|
149
|
+
|
150
|
+
# Create a new data criteria instance
|
151
|
+
# @param [String] id
|
152
|
+
# @param [String] title
|
153
|
+
# @param [String] display_name
|
154
|
+
# @param [String] description
|
155
|
+
# @param [String] code_list_id
|
156
|
+
# @param [String] negation_code_list_id
|
157
|
+
# @param [List<String>] children_criteria (ids of children data criteria)
|
158
|
+
# @param [String] derivation_operator
|
159
|
+
# @param [String] definition
|
160
|
+
# @param [String] status
|
161
|
+
# @param [Value|Range|Coded] value
|
162
|
+
# @param [Hash<String,Value|Range|Coded>] field_values
|
163
|
+
# @param [Range] effective_time
|
164
|
+
# @param [Hash<String,[String]>] inline_code_list
|
165
|
+
# @param [boolean] negation
|
166
|
+
# @param [String] negation_code_list_id
|
167
|
+
# @param [List<TemporalReference>] temporal_references
|
168
|
+
# @param [List<SubsetOperator>] subset_operators
|
169
|
+
# @param [String] specific_occurrence
|
170
|
+
# @param [String] specific_occurrence_const
|
171
|
+
# @param [String] source_data_criteria (id for the source data criteria, important for specific occurrences)
|
172
|
+
# @param [String] user comments for the criteria
|
173
|
+
# @param [Boolean] variable defines if the element is a QDM variable
|
174
|
+
def initialize(id, title, display_name, description, code_list_id, children_criteria, derivation_operator, definition, status, value, field_values, effective_time, inline_code_list, negation, negation_code_list_id, temporal_references, subset_operators, specific_occurrence, specific_occurrence_const, source_data_criteria=nil, comments=nil, variable=false)
|
175
|
+
|
176
|
+
status = normalize_status(definition, status)
|
177
|
+
@settings = HQMF::DataCriteria.get_settings_for_definition(definition, status)
|
178
|
+
|
179
|
+
@id = id
|
180
|
+
@title = title
|
181
|
+
@description = description
|
182
|
+
@code_list_id = code_list_id
|
183
|
+
@negation_code_list_id = negation_code_list_id
|
184
|
+
@children_criteria = children_criteria
|
185
|
+
@derivation_operator = derivation_operator
|
186
|
+
@definition = definition
|
187
|
+
@status = status
|
188
|
+
@value = value
|
189
|
+
@field_values = field_values
|
190
|
+
@effective_time = effective_time
|
191
|
+
@inline_code_list = inline_code_list
|
192
|
+
@negation = negation
|
193
|
+
@negation_code_list_id = negation_code_list_id
|
194
|
+
@temporal_references = temporal_references
|
195
|
+
@subset_operators = subset_operators
|
196
|
+
@specific_occurrence = specific_occurrence
|
197
|
+
@specific_occurrence_const = specific_occurrence_const
|
198
|
+
@source_data_criteria = source_data_criteria || id
|
199
|
+
@comments = comments
|
200
|
+
@variable = variable
|
201
|
+
end
|
202
|
+
|
203
|
+
# create a new data criteria given a category and sub_category. A sub category can either be a status or a sub category
|
204
|
+
def self.create_from_category(id, title, description, code_list_id, category, sub_category=nil, negation=false, negation_code_list_id=nil)
|
205
|
+
settings = HQMF::DataCriteria.get_settings_for_definition(category, sub_category)
|
206
|
+
HQMF::DataCriteria.new(id, title, nil, description, code_list_id, nil, nil, settings['definition'], settings['status'], nil, nil, nil, nil, negation, negation_code_list_id, nil, nil, nil,nil)
|
207
|
+
end
|
208
|
+
def type
|
209
|
+
@settings['category'].to_sym
|
210
|
+
end
|
211
|
+
def property
|
212
|
+
@settings['property'].to_sym unless @settings['property'].nil?
|
213
|
+
end
|
214
|
+
def patient_api_function
|
215
|
+
@settings['patient_api_function'].to_sym unless @settings['patient_api_function'].empty?
|
216
|
+
end
|
217
|
+
def hard_status
|
218
|
+
@settings['hard_status']
|
219
|
+
end
|
220
|
+
def update_copy(hard_status, title, description, derivation_operator, definition)
|
221
|
+
@settings['hard_status'] = hard_status
|
222
|
+
@title = title
|
223
|
+
@description = description
|
224
|
+
@derivation_operator = derivation_operator
|
225
|
+
@definition = definition
|
226
|
+
end
|
227
|
+
def definition=(definition)
|
228
|
+
@definition = definition
|
229
|
+
@settings = HQMF::DataCriteria.get_settings_for_definition(@definition, @status)
|
230
|
+
end
|
231
|
+
def status=(status)
|
232
|
+
@status = status
|
233
|
+
@settings = HQMF::DataCriteria.get_settings_for_definition(@definition, @status)
|
234
|
+
end
|
235
|
+
|
236
|
+
# Create a new data criteria instance from a JSON hash keyed with symbols
|
237
|
+
def self.from_json(id, json)
|
238
|
+
|
239
|
+
title = json["title"] if json["title"]
|
240
|
+
display_name = json["display_name"] if json["display_name"]
|
241
|
+
description = json["description"] if json["description"]
|
242
|
+
code_list_id = json["code_list_id"] if json["code_list_id"]
|
243
|
+
children_criteria = json["children_criteria"] if json["children_criteria"]
|
244
|
+
derivation_operator = json["derivation_operator"] if json["derivation_operator"]
|
245
|
+
definition = json["definition"] if json["definition"]
|
246
|
+
status = json["status"] if json["status"]
|
247
|
+
value = convert_value(json["value"]) if json["value"]
|
248
|
+
field_values = json["field_values"].inject({}){|memo,(k,v)| memo[k.to_s] = convert_value(v); memo} if json["field_values"]
|
249
|
+
effective_time = HQMF::Range.from_json(json["effective_time"]) if json["effective_time"]
|
250
|
+
inline_code_list = json["inline_code_list"].inject({}){|memo,(k,v)| memo[k.to_s] = v; memo} if json["inline_code_list"]
|
251
|
+
negation = json["negation"] || false
|
252
|
+
negation_code_list_id = json['negation_code_list_id'] if json['negation_code_list_id']
|
253
|
+
temporal_references = json["temporal_references"].map {|reference| HQMF::TemporalReference.from_json(reference)} if json["temporal_references"]
|
254
|
+
subset_operators = json["subset_operators"].map {|operator| HQMF::SubsetOperator.from_json(operator)} if json["subset_operators"]
|
255
|
+
specific_occurrence = json['specific_occurrence'] if json['specific_occurrence']
|
256
|
+
specific_occurrence_const = json['specific_occurrence_const'] if json['specific_occurrence_const']
|
257
|
+
source_data_criteria = json['source_data_criteria'] if json['source_data_criteria']
|
258
|
+
comments = json['comments'] if json['comments']
|
259
|
+
variable = json['variable'] || false
|
260
|
+
|
261
|
+
HQMF::DataCriteria.new(id, title, display_name, description, code_list_id, children_criteria, derivation_operator, definition, status, value, field_values,
|
262
|
+
effective_time, inline_code_list, negation, negation_code_list_id, temporal_references, subset_operators,specific_occurrence,specific_occurrence_const,source_data_criteria, comments, variable)
|
263
|
+
end
|
264
|
+
|
265
|
+
def is_same_type?(criteria)
|
266
|
+
return @definition == criteria.definition && @hard_status == criteria.hard_status &&
|
267
|
+
@negation == criteria.negation && all_code_set_oids.sort == criteria.all_code_set_oids.sort
|
268
|
+
end
|
269
|
+
|
270
|
+
def to_json
|
271
|
+
json = base_json
|
272
|
+
{self.id.to_s.to_sym => json}
|
273
|
+
end
|
274
|
+
|
275
|
+
def base_json
|
276
|
+
x = nil
|
277
|
+
json = build_hash(self, [:title,:display_name,:description,:code_list_id,:children_criteria, :derivation_operator, :property, :type, :definition, :status, :hard_status, :negation, :negation_code_list_id,:specific_occurrence,:specific_occurrence_const,:source_data_criteria,:variable])
|
278
|
+
json[:children_criteria] = @children_criteria unless @children_criteria.nil? || @children_criteria.empty?
|
279
|
+
json[:value] = ((@value.is_a? String) ? @value : @value.to_json) if @value
|
280
|
+
json[:field_values] = @field_values.inject({}) {|memo,(k,v)| memo[k] = (!v.nil? ? v.to_json : nil); memo} if @field_values
|
281
|
+
json[:effective_time] = @effective_time.to_json if @effective_time
|
282
|
+
json[:inline_code_list] = @inline_code_list if @inline_code_list
|
283
|
+
json[:temporal_references] = x if x = json_array(@temporal_references)
|
284
|
+
json[:subset_operators] = x if x = json_array(@subset_operators)
|
285
|
+
json[:comments] = @comments if @comments
|
286
|
+
json
|
287
|
+
end
|
288
|
+
|
289
|
+
def has_temporal(temporal_reference)
|
290
|
+
@temporal_references.reduce(false) {|found, item| found ||= item == temporal_reference }
|
291
|
+
end
|
292
|
+
def has_subset(subset_operator)
|
293
|
+
@subset_operators.reduce(false) {|found, item| found ||= item == subset_operator }
|
294
|
+
end
|
295
|
+
|
296
|
+
def self.statuses_by_definition
|
297
|
+
settings_file = File.expand_path('../data_criteria.json', __FILE__)
|
298
|
+
settings_map = JSON.parse(File.read(settings_file))
|
299
|
+
all_defs = (settings_map.map {|key, value| {category: value['category'],definition:value['definition'],status:(value['status'].empty? ? nil : value['status']), sub_category: value['sub_category'],title:value['title']} unless value['not_supported']}).compact
|
300
|
+
by_categories = {}
|
301
|
+
all_defs.each do |definition|
|
302
|
+
by_categories[definition[:category]]||={}
|
303
|
+
status = definition[:status]
|
304
|
+
def_key = definition[:definition]
|
305
|
+
if status.nil? and definition[:sub_category] and !definition[:sub_category].empty?
|
306
|
+
status = definition[:sub_category]
|
307
|
+
def_key = def_key.gsub("_#{status}",'')
|
308
|
+
end
|
309
|
+
by_categories[definition[:category]][def_key]||={category:def_key,statuses:[]}
|
310
|
+
by_categories[definition[:category]][def_key][:statuses] << status unless status.nil?
|
311
|
+
end
|
312
|
+
status_by_category = {}
|
313
|
+
by_categories.each {|key, value| status_by_category[key] = value.values}
|
314
|
+
status_by_category.delete('derived')
|
315
|
+
status_by_category.delete('variable')
|
316
|
+
status_by_category.delete('measurement_period')
|
317
|
+
status_by_category.values.flatten
|
318
|
+
end
|
319
|
+
|
320
|
+
def referenced_data_criteria(document)
|
321
|
+
referenced = []
|
322
|
+
if (@children_criteria)
|
323
|
+
@children_criteria.each do |id|
|
324
|
+
dc = document.data_criteria(id)
|
325
|
+
referenced << id
|
326
|
+
referenced.concat(dc.referenced_data_criteria(document))
|
327
|
+
end
|
328
|
+
end
|
329
|
+
if (@temporal_references)
|
330
|
+
@temporal_references.each do |tr|
|
331
|
+
id = tr.reference.id
|
332
|
+
if (id != HQMF::Document::MEASURE_PERIOD_ID)
|
333
|
+
dc = document.data_criteria(id)
|
334
|
+
referenced << id
|
335
|
+
referenced.concat(dc.referenced_data_criteria(document))
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
referenced
|
340
|
+
end
|
341
|
+
|
342
|
+
def all_code_set_oids
|
343
|
+
|
344
|
+
# root oid
|
345
|
+
referenced_oids = [code_list_id]
|
346
|
+
|
347
|
+
# value oid
|
348
|
+
referenced_oids << value.code_list_id if value != nil and value.type == 'CD'
|
349
|
+
|
350
|
+
# negation oid
|
351
|
+
referenced_oids << negation_code_list_id if negation_code_list_id != nil
|
352
|
+
|
353
|
+
# field oids
|
354
|
+
if field_values != nil
|
355
|
+
referenced_oids.concat (field_values.map {|key,field| field.code_list_id if field != nil and field.type == 'CD'})
|
356
|
+
end
|
357
|
+
|
358
|
+
referenced_oids
|
359
|
+
|
360
|
+
end
|
361
|
+
|
362
|
+
def self.get_settings_map
|
363
|
+
return @settings_map if @settings_map
|
364
|
+
settings_file = File.expand_path('../data_criteria.json', __FILE__)
|
365
|
+
@settings_map = JSON.parse(File.read(settings_file))
|
366
|
+
end
|
367
|
+
|
368
|
+
def self.get_settings_for_definition(definition, status)
|
369
|
+
settings_file = File.expand_path('../data_criteria.json', __FILE__)
|
370
|
+
settings_map = get_settings_map
|
371
|
+
key = definition + ((status.nil? || status.empty?) ? '' : "_#{status}")
|
372
|
+
settings = settings_map[key]
|
373
|
+
|
374
|
+
raise "data criteria is not supported #{key}" if settings.nil? || settings["not_supported"]
|
375
|
+
|
376
|
+
settings
|
377
|
+
end
|
378
|
+
|
379
|
+
def self.definition_for_template_id(template_id, version='r1')
|
380
|
+
get_template_id_map(version)[template_id]
|
381
|
+
end
|
382
|
+
|
383
|
+
def self.template_id_for_definition(definition, status, negation, version="r1")
|
384
|
+
# in r2 negation uses the same template as a positive assertion
|
385
|
+
negation = false if version == "r2"
|
386
|
+
get_template_id_map(version).key({'definition' => definition, 'status' => status || '', 'negation' => negation})
|
387
|
+
end
|
388
|
+
|
389
|
+
def self.title_for_template_id(template_id, version='r1')
|
390
|
+
value = get_template_id_map(version)[template_id]
|
391
|
+
if value
|
392
|
+
settings = self.get_settings_for_definition(value['definition'], value['status'])
|
393
|
+
if settings
|
394
|
+
settings['title']
|
395
|
+
else
|
396
|
+
'Unknown data criteria'
|
397
|
+
end
|
398
|
+
else
|
399
|
+
'Unknown template id'
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
def self.get_template_id_map(version="r1")
|
404
|
+
read_template_id_map(version)
|
405
|
+
end
|
406
|
+
|
407
|
+
private
|
408
|
+
|
409
|
+
def self.read_template_id_map(version)
|
410
|
+
HQMF::Util::HQMFTemplateHelper.template_id_map(version)
|
411
|
+
end
|
412
|
+
|
413
|
+
def normalize_status(definition, status)
|
414
|
+
return status if status.nil?
|
415
|
+
case status.downcase
|
416
|
+
when 'completed', 'complete'
|
417
|
+
case definition
|
418
|
+
when 'diagnosis'
|
419
|
+
'active'
|
420
|
+
else
|
421
|
+
'performed'
|
422
|
+
end
|
423
|
+
when 'order'
|
424
|
+
'ordered'
|
425
|
+
else
|
426
|
+
status.downcase
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
def self.convert_value(json)
|
431
|
+
return nil unless json.present?
|
432
|
+
type = json["type"]
|
433
|
+
case type
|
434
|
+
when 'TS', 'PQ'
|
435
|
+
value = HQMF::Value.from_json(json)
|
436
|
+
when 'IVL_PQ', 'IVL_TS'
|
437
|
+
value = HQMF::Range.from_json(json)
|
438
|
+
when 'CD'
|
439
|
+
value = HQMF::Coded.from_json(json)
|
440
|
+
when 'ANYNonNull'
|
441
|
+
value = HQMF::AnyValue.from_json(json)
|
442
|
+
when 'FLFS'
|
443
|
+
value = HQMF::TypedReference.from_json(json)
|
444
|
+
when 'ACT'
|
445
|
+
# Currentlty forcing this as the SimpleXML reresentation contains a fulfills for these types
|
446
|
+
value = HQMF::TypedReference.new(json["reference"], 'FLFS', '')
|
447
|
+
when 'CMP'
|
448
|
+
# For ResultComponent, json will have a value or "" for referenceRangeLow_value, for Component, will be nil
|
449
|
+
if json['referenceRangeLow_value']
|
450
|
+
value = ResultComponent.new(json)
|
451
|
+
else
|
452
|
+
value = Component.new(json)
|
453
|
+
end
|
454
|
+
when 'COL'
|
455
|
+
value = HQMF::Collection.from_json(json)
|
456
|
+
when 'FAC'
|
457
|
+
value = Facility.new(json)
|
458
|
+
else
|
459
|
+
raise "Unknown value type [#{type}]"
|
460
|
+
end
|
461
|
+
value
|
462
|
+
end
|
463
|
+
|
464
|
+
|
465
|
+
end
|
466
|
+
|
467
|
+
end
|